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-2008, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 -- The body of Interfaces.COBOL is implementation independent (i.e. the same
35 -- version is used with all versions of GNAT). The specialization to a
36 -- particular COBOL format is completely contained in the private part of
39 with Interfaces
; use Interfaces
;
40 with System
; use System
;
41 with Ada
.Unchecked_Conversion
;
43 package body Interfaces
.COBOL
is
45 -----------------------------------------------
46 -- Declarations for External Binary Handling --
47 -----------------------------------------------
49 subtype B1
is Byte_Array
(1 .. 1);
50 subtype B2
is Byte_Array
(1 .. 2);
51 subtype B4
is Byte_Array
(1 .. 4);
52 subtype B8
is Byte_Array
(1 .. 8);
53 -- Representations for 1,2,4,8 byte binary values
55 function To_B1
is new Ada
.Unchecked_Conversion
(Integer_8
, B1
);
56 function To_B2
is new Ada
.Unchecked_Conversion
(Integer_16
, B2
);
57 function To_B4
is new Ada
.Unchecked_Conversion
(Integer_32
, B4
);
58 function To_B8
is new Ada
.Unchecked_Conversion
(Integer_64
, B8
);
59 -- Conversions from native binary to external binary
61 function From_B1
is new Ada
.Unchecked_Conversion
(B1
, Integer_8
);
62 function From_B2
is new Ada
.Unchecked_Conversion
(B2
, Integer_16
);
63 function From_B4
is new Ada
.Unchecked_Conversion
(B4
, Integer_32
);
64 function From_B8
is new Ada
.Unchecked_Conversion
(B8
, Integer_64
);
65 -- Conversions from external binary to signed native binary
67 function From_B1U
is new Ada
.Unchecked_Conversion
(B1
, Unsigned_8
);
68 function From_B2U
is new Ada
.Unchecked_Conversion
(B2
, Unsigned_16
);
69 function From_B4U
is new Ada
.Unchecked_Conversion
(B4
, Unsigned_32
);
70 function From_B8U
is new Ada
.Unchecked_Conversion
(B8
, Unsigned_64
);
71 -- Conversions from external binary to unsigned native binary
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
77 function Binary_To_Decimal
79 Format
: Binary_Format
) return Integer_64
;
80 -- This function converts a numeric value in the given format to its
81 -- corresponding integer value. This is the non-generic implementation
82 -- of Decimal_Conversions.To_Decimal. The generic routine does the
83 -- final conversion to the fixed-point format.
85 function Numeric_To_Decimal
87 Format
: Display_Format
) return Integer_64
;
88 -- This function converts a numeric value in the given format to its
89 -- corresponding integer value. This is the non-generic implementation
90 -- of Decimal_Conversions.To_Decimal. The generic routine does the
91 -- final conversion to the fixed-point format.
93 function Packed_To_Decimal
94 (Item
: Packed_Decimal
;
95 Format
: Packed_Format
) return Integer_64
;
96 -- This function converts a packed value in the given format to its
97 -- corresponding integer value. This is the non-generic implementation
98 -- of Decimal_Conversions.To_Decimal. The generic routine does the
99 -- final conversion to the fixed-point format.
101 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
);
102 -- Swaps the bytes if required by the binary format F
106 Format
: Display_Format
;
107 Length
: Natural) return Numeric
;
108 -- This function converts the given integer value into display format,
109 -- using the given format, with the length in bytes of the result given
110 -- by the last parameter. This is the non-generic implementation of
111 -- Decimal_Conversions.To_Display. The conversion of the item from its
112 -- original decimal format to Integer_64 is done by the generic routine.
116 Format
: Packed_Format
;
117 Length
: Natural) return Packed_Decimal
;
118 -- This function converts the given integer value into packed format,
119 -- using the given format, with the length in digits of the result given
120 -- by the last parameter. This is the non-generic implementation of
121 -- Decimal_Conversions.To_Display. The conversion of the item from its
122 -- original decimal format to Integer_64 is done by the generic routine.
124 function Valid_Numeric
126 Format
: Display_Format
) return Boolean;
127 -- This is the non-generic implementation of Decimal_Conversions.Valid
128 -- for the display case.
130 function Valid_Packed
131 (Item
: Packed_Decimal
;
132 Format
: Packed_Format
) return Boolean;
133 -- This is the non-generic implementation of Decimal_Conversions.Valid
134 -- for the packed case.
136 -----------------------
137 -- Binary_To_Decimal --
138 -----------------------
140 function Binary_To_Decimal
142 Format
: Binary_Format
) return Integer_64
144 Len
: constant Natural := Item
'Length;
148 if Format
in Binary_Unsigned_Format
then
149 return Integer_64
(From_B1U
(Item
));
151 return Integer_64
(From_B1
(Item
));
161 if Format
in Binary_Unsigned_Format
then
162 return Integer_64
(From_B2U
(R
));
164 return Integer_64
(From_B2
(R
));
175 if Format
in Binary_Unsigned_Format
then
176 return Integer_64
(From_B4U
(R
));
178 return Integer_64
(From_B4
(R
));
189 if Format
in Binary_Unsigned_Format
then
190 return Integer_64
(From_B8U
(R
));
192 return Integer_64
(From_B8
(R
));
196 -- Length is not 1, 2, 4 or 8
199 raise Conversion_Error
;
201 end Binary_To_Decimal
;
203 ------------------------
204 -- Numeric_To_Decimal --
205 ------------------------
207 -- The following assumptions are made in the coding of this routine:
209 -- The range of COBOL_Digits is compact and the ten values
210 -- represent the digits 0-9 in sequence
212 -- The range of COBOL_Plus_Digits is compact and the ten values
213 -- represent the digits 0-9 in sequence with a plus sign.
215 -- The range of COBOL_Minus_Digits is compact and the ten values
216 -- represent the digits 0-9 in sequence with a minus sign.
218 -- The COBOL_Minus_Digits set is disjoint from COBOL_Digits
220 -- These assumptions are true for all COBOL representations we know of
222 function Numeric_To_Decimal
224 Format
: Display_Format
) return Integer_64
226 pragma Unsuppress
(Range_Check
);
227 Sign
: COBOL_Character
:= COBOL_Plus
;
228 Result
: Integer_64
:= 0;
231 if not Valid_Numeric
(Item
, Format
) then
232 raise Conversion_Error
;
235 for J
in Item
'Range loop
237 K
: constant COBOL_Character
:= Item
(J
);
240 if K
in COBOL_Digits
then
241 Result
:= Result
* 10 +
242 (COBOL_Character
'Pos (K
) -
243 COBOL_Character
'Pos (COBOL_Digits
'First));
245 elsif K
in COBOL_Plus_Digits
then
246 Result
:= Result
* 10 +
247 (COBOL_Character
'Pos (K
) -
248 COBOL_Character
'Pos (COBOL_Plus_Digits
'First));
250 elsif K
in COBOL_Minus_Digits
then
251 Result
:= Result
* 10 +
252 (COBOL_Character
'Pos (K
) -
253 COBOL_Character
'Pos (COBOL_Minus_Digits
'First));
256 -- Only remaining possibility is COBOL_Plus or COBOL_Minus
264 if Sign
= COBOL_Plus
then
271 when Constraint_Error
=>
272 raise Conversion_Error
;
274 end Numeric_To_Decimal
;
276 -----------------------
277 -- Packed_To_Decimal --
278 -----------------------
280 function Packed_To_Decimal
281 (Item
: Packed_Decimal
;
282 Format
: Packed_Format
) return Integer_64
284 pragma Unsuppress
(Range_Check
);
285 Result
: Integer_64
:= 0;
286 Sign
: constant Decimal_Element
:= Item
(Item
'Last);
289 if not Valid_Packed
(Item
, Format
) then
290 raise Conversion_Error
;
293 case Packed_Representation
is
295 for J
in Item
'First .. Item
'Last - 1 loop
296 Result
:= Result
* 10 + Integer_64
(Item
(J
));
299 if Sign
= 16#
0B#
or else Sign
= 16#
0D#
then
307 when Constraint_Error
=>
308 raise Conversion_Error
;
309 end Packed_To_Decimal
;
315 procedure Swap
(B
: in out Byte_Array
; F
: Binary_Format
) is
316 Little_Endian
: constant Boolean :=
317 System
.Default_Bit_Order
= System
.Low_Order_First
;
320 -- Return if no swap needed
324 if not Little_Endian
then
329 if Little_Endian
then
337 -- Here a swap is needed
340 Len
: constant Natural := B
'Length;
343 for J
in 1 .. Len
/ 2 loop
345 Temp
: constant Byte
:= B
(J
);
348 B
(J
) := B
(Len
+ 1 - J
);
349 B
(Len
+ 1 - J
) := Temp
;
355 -----------------------
356 -- To_Ada (function) --
357 -----------------------
359 function To_Ada
(Item
: Alphanumeric
) return String is
360 Result
: String (Item
'Range);
363 for J
in Item
'Range loop
364 Result
(J
) := COBOL_To_Ada
(Item
(J
));
370 ------------------------
371 -- To_Ada (procedure) --
372 ------------------------
375 (Item
: Alphanumeric
;
382 if Item
'Length > Target
'Length then
383 raise Constraint_Error
;
386 Last_Val
:= Target
'First - 1;
387 for J
in Item
'Range loop
388 Last_Val
:= Last_Val
+ 1;
389 Target
(Last_Val
) := COBOL_To_Ada
(Item
(J
));
395 -------------------------
396 -- To_COBOL (function) --
397 -------------------------
399 function To_COBOL
(Item
: String) return Alphanumeric
is
400 Result
: Alphanumeric
(Item
'Range);
403 for J
in Item
'Range loop
404 Result
(J
) := Ada_To_COBOL
(Item
(J
));
410 --------------------------
411 -- To_COBOL (procedure) --
412 --------------------------
416 Target
: out Alphanumeric
;
422 if Item
'Length > Target
'Length then
423 raise Constraint_Error
;
426 Last_Val
:= Target
'First - 1;
427 for J
in Item
'Range loop
428 Last_Val
:= Last_Val
+ 1;
429 Target
(Last_Val
) := Ada_To_COBOL
(Item
(J
));
441 Format
: Display_Format
;
442 Length
: Natural) return Numeric
444 Result
: Numeric
(1 .. Length
);
445 Val
: Integer_64
:= Item
;
447 procedure Convert
(First
, Last
: Natural);
448 -- Convert the number in Val into COBOL_Digits, storing the result
449 -- in Result (First .. Last). Raise Conversion_Error if too large.
451 procedure Embed_Sign
(Loc
: Natural);
452 -- Used for the nonseparate formats to embed the appropriate sign
453 -- at the specified location (i.e. at Result (Loc))
459 procedure Convert
(First
, Last
: Natural) is
464 while J
>= First
loop
467 (COBOL_Character
'Pos (COBOL_Digits
'First) +
468 Integer (Val
mod 10));
472 for K
in First
.. J
- 1 loop
473 Result
(J
) := COBOL_Digits
'First;
483 raise Conversion_Error
;
490 procedure Embed_Sign
(Loc
: Natural) is
491 Digit
: Natural range 0 .. 9;
494 Digit
:= COBOL_Character
'Pos (Result
(Loc
)) -
495 COBOL_Character
'Pos (COBOL_Digits
'First);
500 (COBOL_Character
'Pos (COBOL_Plus_Digits
'First) + Digit
);
504 (COBOL_Character
'Pos (COBOL_Minus_Digits
'First) + Digit
);
508 -- Start of processing for To_Display
514 raise Conversion_Error
;
519 when Leading_Separate
=>
521 Result
(1) := COBOL_Minus
;
524 Result
(1) := COBOL_Plus
;
529 when Trailing_Separate
=>
531 Result
(Length
) := COBOL_Minus
;
534 Result
(Length
) := COBOL_Plus
;
537 Convert
(1, Length
- 1);
539 when Leading_Nonseparate
=>
544 when Trailing_Nonseparate
=>
560 Format
: Packed_Format
;
561 Length
: Natural) return Packed_Decimal
563 Result
: Packed_Decimal
(1 .. Length
);
566 procedure Convert
(First
, Last
: Natural);
567 -- Convert the number in Val into a sequence of Decimal_Element values,
568 -- storing the result in Result (First .. Last). Raise Conversion_Error
569 -- if the value is too large to fit.
575 procedure Convert
(First
, Last
: Natural) is
579 while J
>= First
loop
580 Result
(J
) := Decimal_Element
(Val
mod 10);
585 for K
in First
.. J
- 1 loop
596 raise Conversion_Error
;
599 -- Start of processing for To_Packed
602 case Packed_Representation
is
604 if Format
= Packed_Unsigned
then
606 raise Conversion_Error
;
608 Result
(Length
) := 16#F#
;
613 Result
(Length
) := 16#C#
;
617 Result
(Length
) := 16#D#
;
621 Convert
(1, Length
- 1);
630 function Valid_Numeric
632 Format
: Display_Format
) return Boolean
635 if Item
'Length = 0 then
639 -- All character positions except first and last must be Digits.
640 -- This is true for all the formats.
642 for J
in Item
'First + 1 .. Item
'Last - 1 loop
643 if Item
(J
) not in COBOL_Digits
then
650 return Item
(Item
'First) in COBOL_Digits
651 and then Item
(Item
'Last) in COBOL_Digits
;
653 when Leading_Separate
=>
654 return (Item
(Item
'First) = COBOL_Plus
or else
655 Item
(Item
'First) = COBOL_Minus
)
656 and then Item
(Item
'Last) in COBOL_Digits
;
658 when Trailing_Separate
=>
659 return Item
(Item
'First) in COBOL_Digits
661 (Item
(Item
'Last) = COBOL_Plus
or else
662 Item
(Item
'Last) = COBOL_Minus
);
664 when Leading_Nonseparate
=>
665 return (Item
(Item
'First) in COBOL_Plus_Digits
or else
666 Item
(Item
'First) in COBOL_Minus_Digits
)
667 and then Item
(Item
'Last) in COBOL_Digits
;
669 when Trailing_Nonseparate
=>
670 return Item
(Item
'First) in COBOL_Digits
672 (Item
(Item
'Last) in COBOL_Plus_Digits
or else
673 Item
(Item
'Last) in COBOL_Minus_Digits
);
682 function Valid_Packed
683 (Item
: Packed_Decimal
;
684 Format
: Packed_Format
) return Boolean
687 case Packed_Representation
is
689 for J
in Item
'First .. Item
'Last - 1 loop
695 -- For unsigned, sign digit must be F
697 if Format
= Packed_Unsigned
then
698 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
721 pragma Unreferenced
(Format
);
723 if Num
'Digits <= 2 then
725 elsif Num
'Digits <= 4 then
727 elsif Num
'Digits <= 9 then
729 else -- Num'Digits in 10 .. 18
734 ----------------------
735 -- Length (display) --
736 ----------------------
738 function Length
(Format
: Display_Format
) return Natural is
740 if Format
= Leading_Separate
or else Format
= Trailing_Separate
then
741 return Num
'Digits + 1;
747 ---------------------
748 -- Length (packed) --
749 ---------------------
751 -- Note that the tests here are all compile time checks
754 (Format
: Packed_Format
) return Natural
756 pragma Unreferenced
(Format
);
758 case Packed_Representation
is
760 return (Num
'Digits + 2) / 2 * 2;
770 Format
: Binary_Format
) return Byte_Array
773 -- Note: all these tests are compile time tests
775 if Num
'Digits <= 2 then
776 return To_B1
(Integer_8
'Integer_Value (Item
));
778 elsif Num
'Digits <= 4 then
780 R
: B2
:= To_B2
(Integer_16
'Integer_Value (Item
));
787 elsif Num
'Digits <= 9 then
789 R
: B4
:= To_B4
(Integer_32
'Integer_Value (Item
));
796 else -- Num'Digits in 10 .. 18
798 R
: B8
:= To_B8
(Integer_64
'Integer_Value (Item
));
807 when Constraint_Error
=>
808 raise Conversion_Error
;
811 ---------------------------------
812 -- To_Binary (internal binary) --
813 ---------------------------------
815 function To_Binary
(Item
: Num
) return Binary
is
816 pragma Unsuppress
(Range_Check
);
818 return Binary
'Integer_Value (Item
);
820 when Constraint_Error
=>
821 raise Conversion_Error
;
824 -------------------------
825 -- To_Decimal (binary) --
826 -------------------------
830 Format
: Binary_Format
) return Num
832 pragma Unsuppress
(Range_Check
);
834 return Num
'Fixed_Value (Binary_To_Decimal
(Item
, Format
));
836 when Constraint_Error
=>
837 raise Conversion_Error
;
840 ----------------------------------
841 -- To_Decimal (internal binary) --
842 ----------------------------------
844 function To_Decimal
(Item
: Binary
) return Num
is
845 pragma Unsuppress
(Range_Check
);
847 return Num
'Fixed_Value (Item
);
849 when Constraint_Error
=>
850 raise Conversion_Error
;
853 --------------------------
854 -- To_Decimal (display) --
855 --------------------------
859 Format
: Display_Format
) return Num
861 pragma Unsuppress
(Range_Check
);
864 return Num
'Fixed_Value (Numeric_To_Decimal
(Item
, Format
));
866 when Constraint_Error
=>
867 raise Conversion_Error
;
870 ---------------------------------------
871 -- To_Decimal (internal long binary) --
872 ---------------------------------------
874 function To_Decimal
(Item
: Long_Binary
) return Num
is
875 pragma Unsuppress
(Range_Check
);
877 return Num
'Fixed_Value (Item
);
879 when Constraint_Error
=>
880 raise Conversion_Error
;
883 -------------------------
884 -- To_Decimal (packed) --
885 -------------------------
888 (Item
: Packed_Decimal
;
889 Format
: Packed_Format
) return Num
891 pragma Unsuppress
(Range_Check
);
893 return Num
'Fixed_Value (Packed_To_Decimal
(Item
, Format
));
895 when Constraint_Error
=>
896 raise Conversion_Error
;
905 Format
: Display_Format
) return Numeric
907 pragma Unsuppress
(Range_Check
);
911 (Integer_64
'Integer_Value (Item
),
915 when Constraint_Error
=>
916 raise Conversion_Error
;
923 function To_Long_Binary
(Item
: Num
) return Long_Binary
is
924 pragma Unsuppress
(Range_Check
);
926 return Long_Binary
'Integer_Value (Item
);
928 when Constraint_Error
=>
929 raise Conversion_Error
;
938 Format
: Packed_Format
) return Packed_Decimal
940 pragma Unsuppress
(Range_Check
);
944 (Integer_64
'Integer_Value (Item
),
948 when Constraint_Error
=>
949 raise Conversion_Error
;
958 Format
: Binary_Format
) return Boolean
961 pragma Unreferenced
(Val
);
963 Val
:= To_Decimal
(Item
, Format
);
966 when Conversion_Error
=>
970 ---------------------
971 -- Valid (display) --
972 ---------------------
976 Format
: Display_Format
) return Boolean
979 return Valid_Numeric
(Item
, Format
);
987 (Item
: Packed_Decimal
;
988 Format
: Packed_Format
) return Boolean
991 return Valid_Packed
(Item
, Format
);
994 end Decimal_Conversions
;
996 end Interfaces
.COBOL
;