Daily bump.
[official-gcc.git] / gcc / ada / i-pacdec.adb
blobf7dadf4e321160b983727ae6e4a509cbe34f2dba
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- I N T E R F A C E S . P A C K E D _ D E C I M A L --
6 -- --
7 -- B o d y --
8 -- (Version for IBM Mainframe Packed Decimal Format) --
9 -- --
10 -- Copyright (C) 1992-2007, Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
21 -- Boston, MA 02110-1301, USA. --
22 -- --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
29 -- --
30 -- GNAT was originally developed by the GNAT team at New York University. --
31 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 -- --
33 ------------------------------------------------------------------------------
35 with System; use System;
37 with Ada.Unchecked_Conversion;
39 package body Interfaces.Packed_Decimal is
41 type Packed is array (Byte_Length) of Unsigned_8;
42 -- The type used internally to represent packed decimal
44 type Packed_Ptr is access Packed;
45 function To_Packed_Ptr is
46 new Ada.Unchecked_Conversion (Address, Packed_Ptr);
48 -- The following array is used to convert a value in the range 0-99 to
49 -- a packed decimal format with two hexadecimal nibbles. It is worth
50 -- using table look up in this direction because divides are expensive.
52 Packed_Byte : constant array (00 .. 99) of Unsigned_8 :=
53 (16#00#, 16#01#, 16#02#, 16#03#, 16#04#,
54 16#05#, 16#06#, 16#07#, 16#08#, 16#09#,
55 16#10#, 16#11#, 16#12#, 16#13#, 16#14#,
56 16#15#, 16#16#, 16#17#, 16#18#, 16#19#,
57 16#20#, 16#21#, 16#22#, 16#23#, 16#24#,
58 16#25#, 16#26#, 16#27#, 16#28#, 16#29#,
59 16#30#, 16#31#, 16#32#, 16#33#, 16#34#,
60 16#35#, 16#36#, 16#37#, 16#38#, 16#39#,
61 16#40#, 16#41#, 16#42#, 16#43#, 16#44#,
62 16#45#, 16#46#, 16#47#, 16#48#, 16#49#,
63 16#50#, 16#51#, 16#52#, 16#53#, 16#54#,
64 16#55#, 16#56#, 16#57#, 16#58#, 16#59#,
65 16#60#, 16#61#, 16#62#, 16#63#, 16#64#,
66 16#65#, 16#66#, 16#67#, 16#68#, 16#69#,
67 16#70#, 16#71#, 16#72#, 16#73#, 16#74#,
68 16#75#, 16#76#, 16#77#, 16#78#, 16#79#,
69 16#80#, 16#81#, 16#82#, 16#83#, 16#84#,
70 16#85#, 16#86#, 16#87#, 16#88#, 16#89#,
71 16#90#, 16#91#, 16#92#, 16#93#, 16#94#,
72 16#95#, 16#96#, 16#97#, 16#98#, 16#99#);
74 ---------------------
75 -- Int32_To_Packed --
76 ---------------------
78 procedure Int32_To_Packed (V : Integer_32; P : System.Address; D : D32) is
79 PP : constant Packed_Ptr := To_Packed_Ptr (P);
80 Empty_Nibble : constant Boolean := ((D rem 2) = 0);
81 B : constant Byte_Length := (D / 2) + 1;
82 VV : Integer_32 := V;
84 begin
85 -- Deal with sign byte first
87 if VV >= 0 then
88 PP (B) := Unsigned_8 (VV rem 10) * 16 + 16#C#;
89 VV := VV / 10;
91 else
92 VV := -VV;
93 PP (B) := Unsigned_8 (VV rem 10) * 16 + 16#D#;
94 end if;
96 for J in reverse B - 1 .. 2 loop
97 if VV = 0 then
98 for K in 1 .. J loop
99 PP (K) := 16#00#;
100 end loop;
102 return;
104 else
105 PP (J) := Packed_Byte (Integer (VV rem 100));
106 VV := VV / 100;
107 end if;
108 end loop;
110 -- Deal with leading byte
112 if Empty_Nibble then
113 if VV > 9 then
114 raise Constraint_Error;
115 else
116 PP (1) := Unsigned_8 (VV);
117 end if;
119 else
120 if VV > 99 then
121 raise Constraint_Error;
122 else
123 PP (1) := Packed_Byte (Integer (VV));
124 end if;
125 end if;
127 end Int32_To_Packed;
129 ---------------------
130 -- Int64_To_Packed --
131 ---------------------
133 procedure Int64_To_Packed (V : Integer_64; P : System.Address; D : D64) is
134 PP : constant Packed_Ptr := To_Packed_Ptr (P);
135 Empty_Nibble : constant Boolean := ((D rem 2) = 0);
136 B : constant Byte_Length := (D / 2) + 1;
137 VV : Integer_64 := V;
139 begin
140 -- Deal with sign byte first
142 if VV >= 0 then
143 PP (B) := Unsigned_8 (VV rem 10) * 16 + 16#C#;
144 VV := VV / 10;
146 else
147 VV := -VV;
148 PP (B) := Unsigned_8 (VV rem 10) * 16 + 16#D#;
149 end if;
151 for J in reverse B - 1 .. 2 loop
152 if VV = 0 then
153 for K in 1 .. J loop
154 PP (K) := 16#00#;
155 end loop;
157 return;
159 else
160 PP (J) := Packed_Byte (Integer (VV rem 100));
161 VV := VV / 100;
162 end if;
163 end loop;
165 -- Deal with leading byte
167 if Empty_Nibble then
168 if VV > 9 then
169 raise Constraint_Error;
170 else
171 PP (1) := Unsigned_8 (VV);
172 end if;
174 else
175 if VV > 99 then
176 raise Constraint_Error;
177 else
178 PP (1) := Packed_Byte (Integer (VV));
179 end if;
180 end if;
182 end Int64_To_Packed;
184 ---------------------
185 -- Packed_To_Int32 --
186 ---------------------
188 function Packed_To_Int32 (P : System.Address; D : D32) return Integer_32 is
189 PP : constant Packed_Ptr := To_Packed_Ptr (P);
190 Empty_Nibble : constant Boolean := ((D mod 2) = 0);
191 B : constant Byte_Length := (D / 2) + 1;
192 V : Integer_32;
193 Dig : Unsigned_8;
194 Sign : Unsigned_8;
195 J : Positive;
197 begin
198 -- Cases where there is an unused (zero) nibble in the first byte.
199 -- Deal with the single digit nibble at the right of this byte
201 if Empty_Nibble then
202 V := Integer_32 (PP (1));
203 J := 2;
205 if V > 9 then
206 raise Constraint_Error;
207 end if;
209 -- Cases where all nibbles are used
211 else
212 V := 0;
213 J := 1;
214 end if;
216 -- Loop to process bytes containing two digit nibbles
218 while J < B loop
219 Dig := Shift_Right (PP (J), 4);
221 if Dig > 9 then
222 raise Constraint_Error;
223 else
224 V := V * 10 + Integer_32 (Dig);
225 end if;
227 Dig := PP (J) and 16#0F#;
229 if Dig > 9 then
230 raise Constraint_Error;
231 else
232 V := V * 10 + Integer_32 (Dig);
233 end if;
235 J := J + 1;
236 end loop;
238 -- Deal with digit nibble in sign byte
240 Dig := Shift_Right (PP (J), 4);
242 if Dig > 9 then
243 raise Constraint_Error;
244 else
245 V := V * 10 + Integer_32 (Dig);
246 end if;
248 Sign := PP (J) and 16#0F#;
250 -- Process sign nibble (deal with most common cases first)
252 if Sign = 16#C# then
253 return V;
255 elsif Sign = 16#D# then
256 return -V;
258 elsif Sign = 16#B# then
259 return -V;
261 elsif Sign >= 16#A# then
262 return V;
264 else
265 raise Constraint_Error;
266 end if;
267 end Packed_To_Int32;
269 ---------------------
270 -- Packed_To_Int64 --
271 ---------------------
273 function Packed_To_Int64 (P : System.Address; D : D64) return Integer_64 is
274 PP : constant Packed_Ptr := To_Packed_Ptr (P);
275 Empty_Nibble : constant Boolean := ((D mod 2) = 0);
276 B : constant Byte_Length := (D / 2) + 1;
277 V : Integer_64;
278 Dig : Unsigned_8;
279 Sign : Unsigned_8;
280 J : Positive;
282 begin
283 -- Cases where there is an unused (zero) nibble in the first byte.
284 -- Deal with the single digit nibble at the right of this byte
286 if Empty_Nibble then
287 V := Integer_64 (PP (1));
288 J := 2;
290 if V > 9 then
291 raise Constraint_Error;
292 end if;
294 -- Cases where all nibbles are used
296 else
297 J := 1;
298 V := 0;
299 end if;
301 -- Loop to process bytes containing two digit nibbles
303 while J < B loop
304 Dig := Shift_Right (PP (J), 4);
306 if Dig > 9 then
307 raise Constraint_Error;
308 else
309 V := V * 10 + Integer_64 (Dig);
310 end if;
312 Dig := PP (J) and 16#0F#;
314 if Dig > 9 then
315 raise Constraint_Error;
316 else
317 V := V * 10 + Integer_64 (Dig);
318 end if;
320 J := J + 1;
321 end loop;
323 -- Deal with digit nibble in sign byte
325 Dig := Shift_Right (PP (J), 4);
327 if Dig > 9 then
328 raise Constraint_Error;
329 else
330 V := V * 10 + Integer_64 (Dig);
331 end if;
333 Sign := PP (J) and 16#0F#;
335 -- Process sign nibble (deal with most common cases first)
337 if Sign = 16#C# then
338 return V;
340 elsif Sign = 16#D# then
341 return -V;
343 elsif Sign = 16#B# then
344 return -V;
346 elsif Sign >= 16#A# then
347 return V;
349 else
350 raise Constraint_Error;
351 end if;
352 end Packed_To_Int64;
354 end Interfaces.Packed_Decimal;