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-2001 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#;
699 -- For signed, accept all standard and non-standard signs
702 return Item (Item'Last) in 16#A# .. 16#F#;
707 -------------------------
708 -- Decimal_Conversions --
709 -------------------------
711 package body Decimal_Conversions is
713 ---------------------
714 -- Length (binary) --
715 ---------------------
717 -- Note that the tests here are all compile time tests
719 function Length (Format : Binary_Format) return Natural is
720 pragma Warnings (Off, Format);
723 if Num'Digits <= 2 then
726 elsif Num'Digits <= 4 then
729 elsif Num'Digits <= 9 then
732 else -- Num'Digits in 10 .. 18
737 ----------------------
738 -- Length (display) --
739 ----------------------
741 function Length (Format : Display_Format) return Natural is
743 if Format = Leading_Separate or else Format = Trailing_Separate then
744 return Num'Digits + 1;
750 ---------------------
751 -- Length (packed) --
752 ---------------------
754 -- Note that the tests here are all compile time checks
757 (Format : Packed_Format)
760 pragma Warnings (Off, Format);
763 case Packed_Representation is
765 return (Num'Digits + 2) / 2 * 2;
775 Format : Binary_Format)
779 -- Note: all these tests are compile time tests
781 if Num'Digits <= 2 then
782 return To_B1 (Integer_8'Integer_Value (Item));
784 elsif Num'Digits <= 4 then
786 R : B2 := To_B2 (Integer_16'Integer_Value (Item));
793 elsif Num'Digits <= 9 then
795 R : B4 := To_B4 (Integer_32'Integer_Value (Item));
802 else -- Num'Digits in 10 .. 18
804 R : B8 := To_B8 (Integer_64'Integer_Value (Item));
813 when Constraint_Error =>
814 raise Conversion_Error;
817 ---------------------------------
818 -- To_Binary (internal binary) --
819 ---------------------------------
821 function To_Binary (Item : Num) return Binary is
822 pragma Unsuppress (Range_Check);
824 return Binary'Integer_Value (Item);
827 when Constraint_Error =>
828 raise Conversion_Error;
831 -------------------------
832 -- To_Decimal (binary) --
833 -------------------------
837 Format : Binary_Format)
840 pragma Unsuppress (Range_Check);
843 return Num'Fixed_Value (Binary_To_Decimal (Item, Format));
846 when Constraint_Error =>
847 raise Conversion_Error;
850 ----------------------------------
851 -- To_Decimal (internal binary) --
852 ----------------------------------
854 function To_Decimal (Item : Binary) return Num is
855 pragma Unsuppress (Range_Check);
858 return Num'Fixed_Value (Item);
861 when Constraint_Error =>
862 raise Conversion_Error;
865 --------------------------
866 -- To_Decimal (display) --
867 --------------------------
871 Format : Display_Format)
874 pragma Unsuppress (Range_Check);
877 return Num'Fixed_Value (Numeric_To_Decimal (Item, Format));
880 when Constraint_Error =>
881 raise Conversion_Error;
884 ---------------------------------------
885 -- To_Decimal (internal long binary) --
886 ---------------------------------------
888 function To_Decimal (Item : Long_Binary) return Num is
889 pragma Unsuppress (Range_Check);
892 return Num'Fixed_Value (Item);
895 when Constraint_Error =>
896 raise Conversion_Error;
899 -------------------------
900 -- To_Decimal (packed) --
901 -------------------------
904 (Item : Packed_Decimal;
905 Format : Packed_Format)
908 pragma Unsuppress (Range_Check);
911 return Num'Fixed_Value (Packed_To_Decimal (Item, Format));
914 when Constraint_Error =>
915 raise Conversion_Error;
924 Format : Display_Format)
927 pragma Unsuppress (Range_Check);
932 (Integer_64'Integer_Value (Item),
937 when Constraint_Error =>
938 raise Conversion_Error;
945 function To_Long_Binary (Item : Num) return Long_Binary is
946 pragma Unsuppress (Range_Check);
949 return Long_Binary'Integer_Value (Item);
952 when Constraint_Error =>
953 raise Conversion_Error;
962 Format : Packed_Format)
963 return Packed_Decimal
965 pragma Unsuppress (Range_Check);
970 (Integer_64'Integer_Value (Item),
975 when Constraint_Error =>
976 raise Conversion_Error;
985 Format : Binary_Format)
991 Val := To_Decimal (Item, Format);
995 when Conversion_Error =>
999 ---------------------
1000 -- Valid (display) --
1001 ---------------------
1005 Format : Display_Format)
1009 return Valid_Numeric (Item, Format);
1012 --------------------
1013 -- Valid (packed) --
1014 --------------------
1017 (Item : Packed_Decimal;
1018 Format : Packed_Format)
1022 return Valid_Packed (Item, Format);
1025 end Decimal_Conversions;
1027 end Interfaces.COBOL;