1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- I N T E R F A C E S . C O B O L --
11 -- Copyright (C) 1992-1999 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
34 ------------------------------------------------------------------------------
36 -- The body of Interfaces.COBOL is implementation independent (i.e. the
37 -- same version is used with all versions of GNAT). The specialization
38 -- to a particular COBOL format is completely contained in the private
41 with Interfaces
; use Interfaces
;
42 with System
; use System
;
43 with Unchecked_Conversion
;
45 package body Interfaces
.COBOL
is
47 -----------------------------------------------
48 -- Declarations for External Binary Handling --
49 -----------------------------------------------
51 subtype B1
is Byte_Array
(1 .. 1);
52 subtype B2
is Byte_Array
(1 .. 2);
53 subtype B4
is Byte_Array
(1 .. 4);
54 subtype B8
is Byte_Array
(1 .. 8);
55 -- Representations for 1,2,4,8 byte binary values
57 function To_B1
is new Unchecked_Conversion
(Integer_8
, B1
);
58 function To_B2
is new Unchecked_Conversion
(Integer_16
, B2
);
59 function To_B4
is new Unchecked_Conversion
(Integer_32
, B4
);
60 function To_B8
is new Unchecked_Conversion
(Integer_64
, B8
);
61 -- Conversions from native binary to external binary
63 function From_B1
is new Unchecked_Conversion
(B1
, Integer_8
);
64 function From_B2
is new Unchecked_Conversion
(B2
, Integer_16
);
65 function From_B4
is new Unchecked_Conversion
(B4
, Integer_32
);
66 function From_B8
is new Unchecked_Conversion
(B8
, Integer_64
);
67 -- Conversions from external binary to signed native binary
69 function From_B1U
is new Unchecked_Conversion
(B1
, Unsigned_8
);
70 function From_B2U
is new Unchecked_Conversion
(B2
, Unsigned_16
);
71 function From_B4U
is new Unchecked_Conversion
(B4
, Unsigned_32
);
72 function From_B8U
is new Unchecked_Conversion
(B8
, Unsigned_64
);
73 -- Conversions from external binary to unsigned native binary
75 -----------------------
76 -- Local Subprograms --
77 -----------------------
79 function Binary_To_Decimal
81 Format
: Binary_Format
)
83 -- This function converts a numeric value in the given format to its
84 -- corresponding integer value. This is the non-generic implementation
85 -- of Decimal_Conversions.To_Decimal. The generic routine does the
86 -- final conversion to the fixed-point format.
88 function Numeric_To_Decimal
90 Format
: Display_Format
)
92 -- This function converts a numeric value in the given format to its
93 -- corresponding integer value. This is the non-generic implementation
94 -- of Decimal_Conversions.To_Decimal. The generic routine does the
95 -- final conversion to the fixed-point format.
97 function Packed_To_Decimal
98 (Item
: Packed_Decimal
;
99 Format
: Packed_Format
)
101 -- This function converts a packed value in the given format to its
102 -- corresponding integer value. This is the non-generic implementation
103 -- of Decimal_Conversions.To_Decimal. The generic routine does the
104 -- final conversion to the fixed-point format.
106 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
);
107 -- Swaps the bytes if required by the binary format F
111 Format
: Display_Format
;
114 -- This function converts the given integer value into display format,
115 -- using the given format, with the length in bytes of the result given
116 -- by the last parameter. This is the non-generic implementation of
117 -- Decimal_Conversions.To_Display. The conversion of the item from its
118 -- original decimal format to Integer_64 is done by the generic routine.
122 Format
: Packed_Format
;
124 return Packed_Decimal
;
125 -- This function converts the given integer value into packed format,
126 -- using the given format, with the length in digits of the result given
127 -- by the last parameter. This is the non-generic implementation of
128 -- Decimal_Conversions.To_Display. The conversion of the item from its
129 -- original decimal format to Integer_64 is done by the generic routine.
131 function Valid_Numeric
133 Format
: Display_Format
)
135 -- This is the non-generic implementation of Decimal_Conversions.Valid
136 -- for the display case.
138 function Valid_Packed
139 (Item
: Packed_Decimal
;
140 Format
: Packed_Format
)
142 -- This is the non-generic implementation of Decimal_Conversions.Valid
143 -- for the packed case.
145 -----------------------
146 -- Binary_To_Decimal --
147 -----------------------
149 function Binary_To_Decimal
151 Format
: Binary_Format
)
154 Len
: constant Natural := Item
'Length;
158 if Format
in Binary_Unsigned_Format
then
159 return Integer_64
(From_B1U
(Item
));
161 return Integer_64
(From_B1
(Item
));
171 if Format
in Binary_Unsigned_Format
then
172 return Integer_64
(From_B2U
(R
));
174 return Integer_64
(From_B2
(R
));
185 if Format
in Binary_Unsigned_Format
then
186 return Integer_64
(From_B4U
(R
));
188 return Integer_64
(From_B4
(R
));
199 if Format
in Binary_Unsigned_Format
then
200 return Integer_64
(From_B8U
(R
));
202 return Integer_64
(From_B8
(R
));
206 -- Length is not 1, 2, 4 or 8
209 raise Conversion_Error
;
211 end Binary_To_Decimal
;
213 ------------------------
214 -- Numeric_To_Decimal --
215 ------------------------
217 -- The following assumptions are made in the coding of this routine
219 -- The range of COBOL_Digits is compact and the ten values
220 -- represent the digits 0-9 in sequence
222 -- The range of COBOL_Plus_Digits is compact and the ten values
223 -- represent the digits 0-9 in sequence with a plus sign.
225 -- The range of COBOL_Minus_Digits is compact and the ten values
226 -- represent the digits 0-9 in sequence with a minus sign.
228 -- The COBOL_Minus_Digits set is disjoint from COBOL_Digits
230 -- These assumptions are true for all COBOL representations we know of.
232 function Numeric_To_Decimal
234 Format
: Display_Format
)
237 pragma Unsuppress
(Range_Check
);
238 Sign
: COBOL_Character
:= COBOL_Plus
;
239 Result
: Integer_64
:= 0;
242 if not Valid_Numeric
(Item
, Format
) then
243 raise Conversion_Error
;
246 for J
in Item
'Range loop
248 K
: constant COBOL_Character
:= Item
(J
);
251 if K
in COBOL_Digits
then
252 Result
:= Result
* 10 +
253 (COBOL_Character
'Pos (K
) -
254 COBOL_Character
'Pos (COBOL_Digits
'First));
256 elsif K
in COBOL_Plus_Digits
then
257 Result
:= Result
* 10 +
258 (COBOL_Character
'Pos (K
) -
259 COBOL_Character
'Pos (COBOL_Plus_Digits
'First));
261 elsif K
in COBOL_Minus_Digits
then
262 Result
:= Result
* 10 +
263 (COBOL_Character
'Pos (K
) -
264 COBOL_Character
'Pos (COBOL_Minus_Digits
'First));
267 -- Only remaining possibility is COBOL_Plus or COBOL_Minus
275 if Sign
= COBOL_Plus
then
282 when Constraint_Error
=>
283 raise Conversion_Error
;
285 end Numeric_To_Decimal
;
287 -----------------------
288 -- Packed_To_Decimal --
289 -----------------------
291 function Packed_To_Decimal
292 (Item
: Packed_Decimal
;
293 Format
: Packed_Format
)
296 pragma Unsuppress
(Range_Check
);
297 Result
: Integer_64
:= 0;
298 Sign
: constant Decimal_Element
:= Item
(Item
'Last);
301 if not Valid_Packed
(Item
, Format
) then
302 raise Conversion_Error
;
305 case Packed_Representation
is
307 for J
in Item
'First .. Item
'Last - 1 loop
308 Result
:= Result
* 10 + Integer_64
(Item
(J
));
311 if Sign
= 16#
0B#
or else Sign
= 16#
0D#
then
319 when Constraint_Error
=>
320 raise Conversion_Error
;
321 end Packed_To_Decimal
;
327 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
) is
328 Little_Endian
: constant Boolean :=
329 System
.Default_Bit_Order
= System
.Low_Order_First
;
332 -- Return if no swap needed
336 if not Little_Endian
then
341 if Little_Endian
then
349 -- Here a swap is needed
352 Len
: constant Natural := B
'Length;
355 for J
in 1 .. Len
/ 2 loop
357 Temp
: constant Byte
:= B
(J
);
360 B
(J
) := B
(Len
+ 1 - J
);
361 B
(Len
+ 1 - J
) := Temp
;
367 -----------------------
368 -- To_Ada (function) --
369 -----------------------
371 function To_Ada
(Item
: Alphanumeric
) return String is
372 Result
: String (Item
'Range);
375 for J
in Item
'Range loop
376 Result
(J
) := COBOL_To_Ada
(Item
(J
));
382 ------------------------
383 -- To_Ada (procedure) --
384 ------------------------
387 (Item
: Alphanumeric
;
394 if Item
'Length > Target
'Length then
395 raise Constraint_Error
;
398 Last_Val
:= Target
'First - 1;
399 for J
in Item
'Range loop
400 Last_Val
:= Last_Val
+ 1;
401 Target
(Last_Val
) := COBOL_To_Ada
(Item
(J
));
407 -------------------------
408 -- To_COBOL (function) --
409 -------------------------
411 function To_COBOL
(Item
: String) return Alphanumeric
is
412 Result
: Alphanumeric
(Item
'Range);
415 for J
in Item
'Range loop
416 Result
(J
) := Ada_To_COBOL
(Item
(J
));
422 --------------------------
423 -- To_COBOL (procedure) --
424 --------------------------
428 Target
: out Alphanumeric
;
434 if Item
'Length > Target
'Length then
435 raise Constraint_Error
;
438 Last_Val
:= Target
'First - 1;
439 for J
in Item
'Range loop
440 Last_Val
:= Last_Val
+ 1;
441 Target
(Last_Val
) := Ada_To_COBOL
(Item
(J
));
453 Format
: Display_Format
;
457 Result
: Numeric
(1 .. Length
);
458 Val
: Integer_64
:= Item
;
460 procedure Convert
(First
, Last
: Natural);
461 -- Convert the number in Val into COBOL_Digits, storing the result
462 -- in Result (First .. Last). Raise Conversion_Error if too large.
464 procedure Embed_Sign
(Loc
: Natural);
465 -- Used for the nonseparate formats to embed the appropriate sign
466 -- at the specified location (i.e. at Result (Loc))
468 procedure Convert
(First
, Last
: Natural) is
472 while J
>= First
loop
475 (COBOL_Character
'Pos (COBOL_Digits
'First) +
476 Integer (Val
mod 10));
480 for K
in First
.. J
- 1 loop
481 Result
(J
) := COBOL_Digits
'First;
491 raise Conversion_Error
;
494 procedure Embed_Sign
(Loc
: Natural) is
495 Digit
: Natural range 0 .. 9;
498 Digit
:= COBOL_Character
'Pos (Result
(Loc
)) -
499 COBOL_Character
'Pos (COBOL_Digits
'First);
504 (COBOL_Character
'Pos (COBOL_Plus_Digits
'First) + Digit
);
508 (COBOL_Character
'Pos (COBOL_Minus_Digits
'First) + Digit
);
512 -- Start of processing for To_Display
518 raise Conversion_Error
;
523 when Leading_Separate
=>
525 Result
(1) := COBOL_Minus
;
528 Result
(1) := COBOL_Plus
;
533 when Trailing_Separate
=>
535 Result
(Length
) := COBOL_Minus
;
538 Result
(Length
) := COBOL_Plus
;
541 Convert
(1, Length
- 1);
543 when Leading_Nonseparate
=>
548 when Trailing_Nonseparate
=>
564 Format
: Packed_Format
;
566 return Packed_Decimal
568 Result
: Packed_Decimal
(1 .. Length
);
571 procedure Convert
(First
, Last
: Natural);
572 -- Convert the number in Val into a sequence of Decimal_Element values,
573 -- storing the result in Result (First .. Last). Raise Conversion_Error
574 -- if the value is too large to fit.
576 procedure Convert
(First
, Last
: Natural) is
580 while J
>= First
loop
581 Result
(J
) := Decimal_Element
(Val
mod 10);
586 for K
in First
.. J
- 1 loop
597 raise Conversion_Error
;
600 -- Start of processing for To_Packed
603 case Packed_Representation
is
605 if Format
= Packed_Unsigned
then
607 raise Conversion_Error
;
609 Result
(Length
) := 16#F#
;
614 Result
(Length
) := 16#C#
;
618 Result
(Length
) := 16#D#
;
622 Convert
(1, Length
- 1);
631 function Valid_Numeric
633 Format
: Display_Format
)
637 -- All character positions except first and last must be Digits.
638 -- This is true for all the formats.
640 for J
in Item
'First + 1 .. Item
'Last - 1 loop
641 if Item
(J
) not in COBOL_Digits
then
648 return Item
(Item
'First) in COBOL_Digits
649 and then Item
(Item
'Last) in COBOL_Digits
;
651 when Leading_Separate
=>
652 return (Item
(Item
'First) = COBOL_Plus
or else
653 Item
(Item
'First) = COBOL_Minus
)
654 and then Item
(Item
'Last) in COBOL_Digits
;
656 when Trailing_Separate
=>
657 return Item
(Item
'First) in COBOL_Digits
659 (Item
(Item
'Last) = COBOL_Plus
or else
660 Item
(Item
'Last) = COBOL_Minus
);
662 when Leading_Nonseparate
=>
663 return (Item
(Item
'First) in COBOL_Plus_Digits
or else
664 Item
(Item
'First) in COBOL_Minus_Digits
)
665 and then Item
(Item
'Last) in COBOL_Digits
;
667 when Trailing_Nonseparate
=>
668 return Item
(Item
'First) in COBOL_Digits
670 (Item
(Item
'Last) in COBOL_Plus_Digits
or else
671 Item
(Item
'Last) in COBOL_Minus_Digits
);
680 function Valid_Packed
681 (Item
: Packed_Decimal
;
682 Format
: Packed_Format
)
686 case Packed_Representation
is
688 for J
in Item
'First .. Item
'Last - 1 loop
694 -- For unsigned, sign digit must be F
696 if Format
= Packed_Unsigned
then
697 return Item
(Item
'Last) = 16#F#
;
700 -- For signed, accept all standard and non-standard signs
703 return Item
(Item
'Last) in 16#A#
.. 16#F#
;
708 -------------------------
709 -- Decimal_Conversions --
710 -------------------------
712 package body Decimal_Conversions
is
714 ---------------------
715 -- Length (binary) --
716 ---------------------
718 -- Note that the tests here are all compile time tests
720 function Length
(Format
: Binary_Format
) return Natural is
722 if Num
'Digits <= 2 then
725 elsif Num
'Digits <= 4 then
728 elsif Num
'Digits <= 9 then
731 else -- Num'Digits in 10 .. 18
736 ----------------------
737 -- Length (display) --
738 ----------------------
740 function Length
(Format
: Display_Format
) return Natural is
742 if Format
= Leading_Separate
or else Format
= Trailing_Separate
then
743 return Num
'Digits + 1;
749 ---------------------
750 -- Length (packed) --
751 ---------------------
753 -- Note that the tests here are all compile time checks
756 (Format
: Packed_Format
)
760 case Packed_Representation
is
762 return (Num
'Digits + 2) / 2 * 2;
772 Format
: Binary_Format
)
776 -- Note: all these tests are compile time tests
778 if Num
'Digits <= 2 then
779 return To_B1
(Integer_8
'Integer_Value (Item
));
781 elsif Num
'Digits <= 4 then
783 R
: B2
:= To_B2
(Integer_16
'Integer_Value (Item
));
790 elsif Num
'Digits <= 9 then
792 R
: B4
:= To_B4
(Integer_32
'Integer_Value (Item
));
799 else -- Num'Digits in 10 .. 18
801 R
: B8
:= To_B8
(Integer_64
'Integer_Value (Item
));
810 when Constraint_Error
=>
811 raise Conversion_Error
;
814 ---------------------------------
815 -- To_Binary (internal binary) --
816 ---------------------------------
818 function To_Binary
(Item
: Num
) return Binary
is
819 pragma Unsuppress
(Range_Check
);
821 return Binary
'Integer_Value (Item
);
824 when Constraint_Error
=>
825 raise Conversion_Error
;
828 -------------------------
829 -- To_Decimal (binary) --
830 -------------------------
834 Format
: Binary_Format
)
837 pragma Unsuppress
(Range_Check
);
840 return Num
'Fixed_Value (Binary_To_Decimal
(Item
, Format
));
843 when Constraint_Error
=>
844 raise Conversion_Error
;
847 ----------------------------------
848 -- To_Decimal (internal binary) --
849 ----------------------------------
851 function To_Decimal
(Item
: Binary
) return Num
is
852 pragma Unsuppress
(Range_Check
);
855 return Num
'Fixed_Value (Item
);
858 when Constraint_Error
=>
859 raise Conversion_Error
;
862 --------------------------
863 -- To_Decimal (display) --
864 --------------------------
868 Format
: Display_Format
)
871 pragma Unsuppress
(Range_Check
);
874 return Num
'Fixed_Value (Numeric_To_Decimal
(Item
, Format
));
877 when Constraint_Error
=>
878 raise Conversion_Error
;
881 ---------------------------------------
882 -- To_Decimal (internal long binary) --
883 ---------------------------------------
885 function To_Decimal
(Item
: Long_Binary
) return Num
is
886 pragma Unsuppress
(Range_Check
);
889 return Num
'Fixed_Value (Item
);
892 when Constraint_Error
=>
893 raise Conversion_Error
;
896 -------------------------
897 -- To_Decimal (packed) --
898 -------------------------
901 (Item
: Packed_Decimal
;
902 Format
: Packed_Format
)
905 pragma Unsuppress
(Range_Check
);
908 return Num
'Fixed_Value (Packed_To_Decimal
(Item
, Format
));
911 when Constraint_Error
=>
912 raise Conversion_Error
;
921 Format
: Display_Format
)
924 pragma Unsuppress
(Range_Check
);
929 (Integer_64
'Integer_Value (Item
),
934 when Constraint_Error
=>
935 raise Conversion_Error
;
942 function To_Long_Binary
(Item
: Num
) return Long_Binary
is
943 pragma Unsuppress
(Range_Check
);
946 return Long_Binary
'Integer_Value (Item
);
949 when Constraint_Error
=>
950 raise Conversion_Error
;
959 Format
: Packed_Format
)
960 return Packed_Decimal
962 pragma Unsuppress
(Range_Check
);
967 (Integer_64
'Integer_Value (Item
),
972 when Constraint_Error
=>
973 raise Conversion_Error
;
982 Format
: Binary_Format
)
988 Val
:= To_Decimal
(Item
, Format
);
992 when Conversion_Error
=>
996 ---------------------
997 -- Valid (display) --
998 ---------------------
1002 Format
: Display_Format
)
1006 return Valid_Numeric
(Item
, Format
);
1009 --------------------
1010 -- Valid (packed) --
1011 --------------------
1014 (Item
: Packed_Decimal
;
1015 Format
: Packed_Format
)
1019 return Valid_Packed
(Item
, Format
);
1022 end Decimal_Conversions
;
1024 end Interfaces
.COBOL
;