1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- I N T E R F A C E S . C O B O L --
9 -- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- The body of Interfaces.COBOL is implementation independent (i.e. the same
33 -- version is used with all versions of GNAT). The specialization to a
34 -- particular COBOL format is completely contained in the private part of
37 with Interfaces
; use Interfaces
;
38 with System
; use System
;
39 with Ada
.Unchecked_Conversion
;
41 package body Interfaces
.COBOL
is
43 -----------------------------------------------
44 -- Declarations for External Binary Handling --
45 -----------------------------------------------
47 subtype B1
is Byte_Array
(1 .. 1);
48 subtype B2
is Byte_Array
(1 .. 2);
49 subtype B4
is Byte_Array
(1 .. 4);
50 subtype B8
is Byte_Array
(1 .. 8);
51 -- Representations for 1,2,4,8 byte binary values
53 function To_B1
is new Ada
.Unchecked_Conversion
(Integer_8
, B1
);
54 function To_B2
is new Ada
.Unchecked_Conversion
(Integer_16
, B2
);
55 function To_B4
is new Ada
.Unchecked_Conversion
(Integer_32
, B4
);
56 function To_B8
is new Ada
.Unchecked_Conversion
(Integer_64
, B8
);
57 -- Conversions from native binary to external binary
59 function From_B1
is new Ada
.Unchecked_Conversion
(B1
, Integer_8
);
60 function From_B2
is new Ada
.Unchecked_Conversion
(B2
, Integer_16
);
61 function From_B4
is new Ada
.Unchecked_Conversion
(B4
, Integer_32
);
62 function From_B8
is new Ada
.Unchecked_Conversion
(B8
, Integer_64
);
63 -- Conversions from external binary to signed native binary
65 function From_B1U
is new Ada
.Unchecked_Conversion
(B1
, Unsigned_8
);
66 function From_B2U
is new Ada
.Unchecked_Conversion
(B2
, Unsigned_16
);
67 function From_B4U
is new Ada
.Unchecked_Conversion
(B4
, Unsigned_32
);
68 function From_B8U
is new Ada
.Unchecked_Conversion
(B8
, Unsigned_64
);
69 -- Conversions from external binary to unsigned native binary
71 -----------------------
72 -- Local Subprograms --
73 -----------------------
75 function Binary_To_Decimal
77 Format
: Binary_Format
) return Integer_64
;
78 -- This function converts a numeric value in the given format to its
79 -- corresponding integer value. This is the non-generic implementation
80 -- of Decimal_Conversions.To_Decimal. The generic routine does the
81 -- final conversion to the fixed-point format.
83 function Numeric_To_Decimal
85 Format
: Display_Format
) return Integer_64
;
86 -- This function converts a numeric value in the given format to its
87 -- corresponding integer value. This is the non-generic implementation
88 -- of Decimal_Conversions.To_Decimal. The generic routine does the
89 -- final conversion to the fixed-point format.
91 function Packed_To_Decimal
92 (Item
: Packed_Decimal
;
93 Format
: Packed_Format
) return Integer_64
;
94 -- This function converts a packed value in the given format to its
95 -- corresponding integer value. This is the non-generic implementation
96 -- of Decimal_Conversions.To_Decimal. The generic routine does the
97 -- final conversion to the fixed-point format.
99 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
);
100 -- Swaps the bytes if required by the binary format F
104 Format
: Display_Format
;
105 Length
: Natural) return Numeric
;
106 -- This function converts the given integer value into display format,
107 -- using the given format, with the length in bytes of the result given
108 -- by the last parameter. This is the non-generic implementation of
109 -- Decimal_Conversions.To_Display. The conversion of the item from its
110 -- original decimal format to Integer_64 is done by the generic routine.
114 Format
: Packed_Format
;
115 Length
: Natural) return Packed_Decimal
;
116 -- This function converts the given integer value into packed format,
117 -- using the given format, with the length in digits of the result given
118 -- by the last parameter. This is the non-generic implementation of
119 -- Decimal_Conversions.To_Display. The conversion of the item from its
120 -- original decimal format to Integer_64 is done by the generic routine.
122 function Valid_Numeric
124 Format
: Display_Format
) return Boolean;
125 -- This is the non-generic implementation of Decimal_Conversions.Valid
126 -- for the display case.
128 function Valid_Packed
129 (Item
: Packed_Decimal
;
130 Format
: Packed_Format
) return Boolean;
131 -- This is the non-generic implementation of Decimal_Conversions.Valid
132 -- for the packed case.
134 -----------------------
135 -- Binary_To_Decimal --
136 -----------------------
138 function Binary_To_Decimal
140 Format
: Binary_Format
) return Integer_64
142 Len
: constant Natural := Item
'Length;
146 if Format
in Binary_Unsigned_Format
then
147 return Integer_64
(From_B1U
(Item
));
149 return Integer_64
(From_B1
(Item
));
159 if Format
in Binary_Unsigned_Format
then
160 return Integer_64
(From_B2U
(R
));
162 return Integer_64
(From_B2
(R
));
173 if Format
in Binary_Unsigned_Format
then
174 return Integer_64
(From_B4U
(R
));
176 return Integer_64
(From_B4
(R
));
187 if Format
in Binary_Unsigned_Format
then
188 return Integer_64
(From_B8U
(R
));
190 return Integer_64
(From_B8
(R
));
194 -- Length is not 1, 2, 4 or 8
197 raise Conversion_Error
;
199 end Binary_To_Decimal
;
201 ------------------------
202 -- Numeric_To_Decimal --
203 ------------------------
205 -- The following assumptions are made in the coding of this routine:
207 -- The range of COBOL_Digits is compact and the ten values
208 -- represent the digits 0-9 in sequence
210 -- The range of COBOL_Plus_Digits is compact and the ten values
211 -- represent the digits 0-9 in sequence with a plus sign.
213 -- The range of COBOL_Minus_Digits is compact and the ten values
214 -- represent the digits 0-9 in sequence with a minus sign.
216 -- The COBOL_Minus_Digits set is disjoint from COBOL_Digits
218 -- These assumptions are true for all COBOL representations we know of
220 function Numeric_To_Decimal
222 Format
: Display_Format
) return Integer_64
224 pragma Unsuppress
(Range_Check
);
225 Sign
: COBOL_Character
:= COBOL_Plus
;
226 Result
: Integer_64
:= 0;
229 if not Valid_Numeric
(Item
, Format
) then
230 raise Conversion_Error
;
233 for J
in Item
'Range loop
235 K
: constant COBOL_Character
:= Item
(J
);
238 if K
in COBOL_Digits
then
239 Result
:= Result
* 10 +
240 (COBOL_Character
'Pos (K
) -
241 COBOL_Character
'Pos (COBOL_Digits
'First));
243 elsif K
in COBOL_Plus_Digits
then
244 Result
:= Result
* 10 +
245 (COBOL_Character
'Pos (K
) -
246 COBOL_Character
'Pos (COBOL_Plus_Digits
'First));
248 elsif K
in COBOL_Minus_Digits
then
249 Result
:= Result
* 10 +
250 (COBOL_Character
'Pos (K
) -
251 COBOL_Character
'Pos (COBOL_Minus_Digits
'First));
254 -- Only remaining possibility is COBOL_Plus or COBOL_Minus
262 if Sign
= COBOL_Plus
then
269 when Constraint_Error
=>
270 raise Conversion_Error
;
272 end Numeric_To_Decimal
;
274 -----------------------
275 -- Packed_To_Decimal --
276 -----------------------
278 function Packed_To_Decimal
279 (Item
: Packed_Decimal
;
280 Format
: Packed_Format
) return Integer_64
282 pragma Unsuppress
(Range_Check
);
283 Result
: Integer_64
:= 0;
284 Sign
: constant Decimal_Element
:= Item
(Item
'Last);
287 if not Valid_Packed
(Item
, Format
) then
288 raise Conversion_Error
;
291 case Packed_Representation
is
293 for J
in Item
'First .. Item
'Last - 1 loop
294 Result
:= Result
* 10 + Integer_64
(Item
(J
));
297 if Sign
= 16#
0B#
or else Sign
= 16#
0D#
then
305 when Constraint_Error
=>
306 raise Conversion_Error
;
307 end Packed_To_Decimal
;
313 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
) is
314 Little_Endian
: constant Boolean :=
315 System
.Default_Bit_Order
= System
.Low_Order_First
;
318 -- Return if no swap needed
322 if not Little_Endian
then
327 if Little_Endian
then
335 -- Here a swap is needed
338 Len
: constant Natural := B
'Length;
341 for J
in 1 .. Len
/ 2 loop
343 Temp
: constant Byte
:= B
(J
);
346 B
(J
) := B
(Len
+ 1 - J
);
347 B
(Len
+ 1 - J
) := Temp
;
353 -----------------------
354 -- To_Ada (function) --
355 -----------------------
357 function To_Ada
(Item
: Alphanumeric
) return String is
358 Result
: String (Item
'Range);
361 for J
in Item
'Range loop
362 Result
(J
) := COBOL_To_Ada
(Item
(J
));
368 ------------------------
369 -- To_Ada (procedure) --
370 ------------------------
373 (Item
: Alphanumeric
;
380 if Item
'Length > Target
'Length then
381 raise Constraint_Error
;
384 Last_Val
:= Target
'First - 1;
385 for J
in Item
'Range loop
386 Last_Val
:= Last_Val
+ 1;
387 Target
(Last_Val
) := COBOL_To_Ada
(Item
(J
));
393 -------------------------
394 -- To_COBOL (function) --
395 -------------------------
397 function To_COBOL
(Item
: String) return Alphanumeric
is
398 Result
: Alphanumeric
(Item
'Range);
401 for J
in Item
'Range loop
402 Result
(J
) := Ada_To_COBOL
(Item
(J
));
408 --------------------------
409 -- To_COBOL (procedure) --
410 --------------------------
414 Target
: out Alphanumeric
;
420 if Item
'Length > Target
'Length then
421 raise Constraint_Error
;
424 Last_Val
:= Target
'First - 1;
425 for J
in Item
'Range loop
426 Last_Val
:= Last_Val
+ 1;
427 Target
(Last_Val
) := Ada_To_COBOL
(Item
(J
));
439 Format
: Display_Format
;
440 Length
: Natural) return Numeric
442 Result
: Numeric
(1 .. Length
);
443 Val
: Integer_64
:= Item
;
445 procedure Convert
(First
, Last
: Natural);
446 -- Convert the number in Val into COBOL_Digits, storing the result
447 -- in Result (First .. Last). Raise Conversion_Error if too large.
449 procedure Embed_Sign
(Loc
: Natural);
450 -- Used for the nonseparate formats to embed the appropriate sign
451 -- at the specified location (i.e. at Result (Loc))
457 procedure Convert
(First
, Last
: Natural) is
462 while J
>= First
loop
465 (COBOL_Character
'Pos (COBOL_Digits
'First) +
466 Integer (Val
mod 10));
470 for K
in First
.. J
- 1 loop
471 Result
(J
) := COBOL_Digits
'First;
481 raise Conversion_Error
;
488 procedure Embed_Sign
(Loc
: Natural) is
489 Digit
: Natural range 0 .. 9;
492 Digit
:= COBOL_Character
'Pos (Result
(Loc
)) -
493 COBOL_Character
'Pos (COBOL_Digits
'First);
498 (COBOL_Character
'Pos (COBOL_Plus_Digits
'First) + Digit
);
502 (COBOL_Character
'Pos (COBOL_Minus_Digits
'First) + Digit
);
506 -- Start of processing for To_Display
512 raise Conversion_Error
;
517 when Leading_Separate
=>
519 Result
(1) := COBOL_Minus
;
522 Result
(1) := COBOL_Plus
;
527 when Trailing_Separate
=>
529 Result
(Length
) := COBOL_Minus
;
532 Result
(Length
) := COBOL_Plus
;
535 Convert
(1, Length
- 1);
537 when Leading_Nonseparate
=>
542 when Trailing_Nonseparate
=>
558 Format
: Packed_Format
;
559 Length
: Natural) return Packed_Decimal
561 Result
: Packed_Decimal
(1 .. Length
);
564 procedure Convert
(First
, Last
: Natural);
565 -- Convert the number in Val into a sequence of Decimal_Element values,
566 -- storing the result in Result (First .. Last). Raise Conversion_Error
567 -- if the value is too large to fit.
573 procedure Convert
(First
, Last
: Natural) is
577 while J
>= First
loop
578 Result
(J
) := Decimal_Element
(Val
mod 10);
583 for K
in First
.. J
- 1 loop
594 raise Conversion_Error
;
597 -- Start of processing for To_Packed
600 case Packed_Representation
is
602 if Format
= Packed_Unsigned
then
604 raise Conversion_Error
;
606 Result
(Length
) := 16#F#
;
611 Result
(Length
) := 16#C#
;
615 Result
(Length
) := 16#D#
;
619 Convert
(1, Length
- 1);
628 function Valid_Numeric
630 Format
: Display_Format
) return Boolean
633 if Item
'Length = 0 then
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
) return Boolean
685 case Packed_Representation
is
687 for J
in Item
'First .. Item
'Last - 1 loop
693 -- For unsigned, sign digit must be F
695 if Format
= Packed_Unsigned
then
696 return Item
(Item
'Last) = 16#F#
;
698 -- For signed, accept all standard and non-standard signs
701 return Item
(Item
'Last) in 16#A#
.. 16#F#
;
706 -------------------------
707 -- Decimal_Conversions --
708 -------------------------
710 package body Decimal_Conversions
is
712 ---------------------
713 -- Length (binary) --
714 ---------------------
716 -- Note that the tests here are all compile time tests
718 function Length
(Format
: Binary_Format
) return Natural is
719 pragma Unreferenced
(Format
);
721 if Num
'Digits <= 2 then
723 elsif Num
'Digits <= 4 then
725 elsif Num
'Digits <= 9 then
727 else -- Num'Digits in 10 .. 18
732 ----------------------
733 -- Length (display) --
734 ----------------------
736 function Length
(Format
: Display_Format
) return Natural is
738 if Format
= Leading_Separate
or else Format
= Trailing_Separate
then
739 return Num
'Digits + 1;
745 ---------------------
746 -- Length (packed) --
747 ---------------------
749 -- Note that the tests here are all compile time checks
752 (Format
: Packed_Format
) return Natural
754 pragma Unreferenced
(Format
);
756 case Packed_Representation
is
758 return (Num
'Digits + 2) / 2 * 2;
768 Format
: Binary_Format
) return Byte_Array
771 -- Note: all these tests are compile time tests
773 if Num
'Digits <= 2 then
774 return To_B1
(Integer_8
'Integer_Value (Item
));
776 elsif Num
'Digits <= 4 then
778 R
: B2
:= To_B2
(Integer_16
'Integer_Value (Item
));
785 elsif Num
'Digits <= 9 then
787 R
: B4
:= To_B4
(Integer_32
'Integer_Value (Item
));
794 else -- Num'Digits in 10 .. 18
796 R
: B8
:= To_B8
(Integer_64
'Integer_Value (Item
));
805 when Constraint_Error
=>
806 raise Conversion_Error
;
809 ---------------------------------
810 -- To_Binary (internal binary) --
811 ---------------------------------
813 function To_Binary
(Item
: Num
) return Binary
is
814 pragma Unsuppress
(Range_Check
);
816 return Binary
'Integer_Value (Item
);
818 when Constraint_Error
=>
819 raise Conversion_Error
;
822 -------------------------
823 -- To_Decimal (binary) --
824 -------------------------
828 Format
: Binary_Format
) return Num
830 pragma Unsuppress
(Range_Check
);
832 return Num
'Fixed_Value (Binary_To_Decimal
(Item
, Format
));
834 when Constraint_Error
=>
835 raise Conversion_Error
;
838 ----------------------------------
839 -- To_Decimal (internal binary) --
840 ----------------------------------
842 function To_Decimal
(Item
: Binary
) return Num
is
843 pragma Unsuppress
(Range_Check
);
845 return Num
'Fixed_Value (Item
);
847 when Constraint_Error
=>
848 raise Conversion_Error
;
851 --------------------------
852 -- To_Decimal (display) --
853 --------------------------
857 Format
: Display_Format
) return Num
859 pragma Unsuppress
(Range_Check
);
862 return Num
'Fixed_Value (Numeric_To_Decimal
(Item
, Format
));
864 when Constraint_Error
=>
865 raise Conversion_Error
;
868 ---------------------------------------
869 -- To_Decimal (internal long binary) --
870 ---------------------------------------
872 function To_Decimal
(Item
: Long_Binary
) return Num
is
873 pragma Unsuppress
(Range_Check
);
875 return Num
'Fixed_Value (Item
);
877 when Constraint_Error
=>
878 raise Conversion_Error
;
881 -------------------------
882 -- To_Decimal (packed) --
883 -------------------------
886 (Item
: Packed_Decimal
;
887 Format
: Packed_Format
) return Num
889 pragma Unsuppress
(Range_Check
);
891 return Num
'Fixed_Value (Packed_To_Decimal
(Item
, Format
));
893 when Constraint_Error
=>
894 raise Conversion_Error
;
903 Format
: Display_Format
) return Numeric
905 pragma Unsuppress
(Range_Check
);
909 (Integer_64
'Integer_Value (Item
),
913 when Constraint_Error
=>
914 raise Conversion_Error
;
921 function To_Long_Binary
(Item
: Num
) return Long_Binary
is
922 pragma Unsuppress
(Range_Check
);
924 return Long_Binary
'Integer_Value (Item
);
926 when Constraint_Error
=>
927 raise Conversion_Error
;
936 Format
: Packed_Format
) return Packed_Decimal
938 pragma Unsuppress
(Range_Check
);
942 (Integer_64
'Integer_Value (Item
),
946 when Constraint_Error
=>
947 raise Conversion_Error
;
956 Format
: Binary_Format
) return Boolean
959 pragma Unreferenced
(Val
);
961 Val
:= To_Decimal
(Item
, Format
);
964 when Conversion_Error
=>
968 ---------------------
969 -- Valid (display) --
970 ---------------------
974 Format
: Display_Format
) return Boolean
977 return Valid_Numeric
(Item
, Format
);
985 (Item
: Packed_Decimal
;
986 Format
: Packed_Format
) return Boolean
989 return Valid_Packed
(Item
, Format
);
992 end Decimal_Conversions
;
994 end Interfaces
.COBOL
;