B.4 Interfacing with COBOL
The facilities 
relevant to interfacing with the COBOL language are the package Interfaces.COBOL 
and support for specifying the Convention aspect with 
convention_identifier 
COBOL.
 
The COBOL interface 
package supplies several sets of facilities: 
A set of types corresponding to the native COBOL 
types of the supported COBOL implementation (so-called “internal 
COBOL representations”), allowing Ada data to be passed as parameters 
to COBOL programs
A set of types and constants reflecting external 
data representations such as might be found in files or databases, allowing 
COBOL-generated data to be read by an Ada program, and Ada-generated 
data to be read by COBOL programs
A generic package for converting between an Ada 
decimal type value and either an internal or external COBOL representation 
Static Semantics
The library package 
Interfaces.COBOL has the following declaration: 
package Interfaces.COBOL 
is
   pragma Preelaborate(COBOL);
 
-- Types and operations for internal data representations
   type Floating      
is digits implementation-defined;
   
type Long_Floating 
is digits implementation-defined;
 
   type Binary      
is range implementation-defined;
   
type Long_Binary 
is range implementation-defined;
 
   Max_Digits_Binary      : 
constant := 
implementation-defined;
   
Max_Digits_Long_Binary : 
constant := 
implementation-defined;
 
   type Decimal_Element  
is mod implementation-defined;
   
type Packed_Decimal 
is array (Positive 
range <>) 
of Decimal_Element
      
with Pack;
 
   type COBOL_Character 
is implementation-defined character type;
 
   Ada_To_COBOL : 
array (Character) 
of COBOL_Character := 
implementation-defined;
 
   COBOL_To_Ada : 
array (COBOL_Character) 
of Character := 
implementation-defined;
 
   type Alphanumeric 
is array (Positive range <>) 
of COBOL_Character
      
with Pack;
 
   function To_COBOL (Item : 
in String) 
return Alphanumeric;
   
function To_Ada   (Item : 
in Alphanumeric) 
return String;
 
   procedure To_COBOL (Item       : 
in String;
                       Target     : 
out Alphanumeric;
                       Last       : 
out Natural);
 
   procedure To_Ada (Item     : 
in Alphanumeric;
                     Target   : 
out String;
                     Last     : 
out Natural);
 
   type Numeric 
is array (Positive 
range <>) 
of COBOL_Character
      
with Pack;
 
-- Formats for COBOL data representations
   type Display_Format 
is private;
 
   Unsigned             : 
constant Display_Format;
   
Leading_Separate     : 
constant Display_Format;
   
Trailing_Separate    : 
constant Display_Format;
   
Leading_Nonseparate  : 
constant Display_Format;
   
Trailing_Nonseparate : 
constant Display_Format;
 
   type Binary_Format 
is private;
 
   High_Order_First  : 
constant Binary_Format;
   
Low_Order_First   : 
constant Binary_Format;
   
Native_Binary     : 
constant Binary_Format;
 
   type Packed_Format 
is private;
 
   Packed_Unsigned   : 
constant Packed_Format;
   
Packed_Signed     : 
constant Packed_Format;
 
-- Types for external representation of COBOL binary data
   type Byte 
is mod 2**COBOL_Character'Size;
   
type Byte_Array 
is array (Positive 
range <>) 
of Byte
      
with Pack;
 
   Conversion_Error : 
exception;
 
   generic
      type Num 
is delta <> 
digits <>;
   
package Decimal_Conversions 
is 
      -- Display Formats: data values are represented as Numeric
      function Valid (Item   : 
in Numeric;
                      Format : 
in Display_Format) 
return Boolean;
 
      function Length (Format : 
in Display_Format) 
return Natural;
 
      function To_Decimal (Item   : 
in Numeric;
                           Format : 
in Display_Format) 
return Num;
 
      function To_Display (Item   : 
in Num;
                           Format : 
in Display_Format) 
return Numeric;
 
      -- Packed Formats: data values are represented as Packed_Decimal
      function Valid (Item   : 
in Packed_Decimal;
                      Format : 
in Packed_Format) 
return Boolean;
 
      function Length (Format : 
in Packed_Format) 
return Natural;
 
      function To_Decimal (Item   : 
in Packed_Decimal;
                           Format : 
in Packed_Format) 
return Num;
 
      function To_Packed (Item   : 
in Num;
                          Format : 
in Packed_Format) 
return Packed_Decimal;
 
      -- Binary Formats: external data values are represented as Byte_Array
      function Valid (Item   : 
in Byte_Array;
                      Format : 
in Binary_Format) 
return Boolean;
 
      function Length (Format : 
in Binary_Format) 
return Natural;
      
function To_Decimal (Item   : 
in Byte_Array;
                           Format : 
in Binary_Format) 
return Num;
 
      function To_Binary (Item   : 
in Num;
                        Format : 
in Binary_Format) 
return Byte_Array;
 
      -- Internal Binary formats: data values are of type Binary or Long_Binary
      function To_Decimal (Item : 
in Binary)      
return Num;
      
function To_Decimal (Item : 
in Long_Binary) 
return Num;
 
      function To_Binary      (Item : 
in Num)  
return Binary;
      
function To_Long_Binary (Item : 
in Num)  
return Long_Binary;
 
   end Decimal_Conversions;
private
   ... -- not specified by the language
end Interfaces.COBOL;
Each of the types in Interfaces.COBOL is COBOL-compatible.
The types Floating and Long_Floating correspond to 
the native types in COBOL for data items with computational usage implemented 
by floating point. The types Binary and Long_Binary correspond to the 
native types in COBOL for data items with binary usage, or with computational 
usage implemented by binary.
Max_Digits_Binary is the largest number of decimal 
digits in a numeric value that is represented as Binary. Max_Digits_Long_Binary 
is the largest number of decimal digits in a numeric value that is represented 
as Long_Binary.
The type Packed_Decimal corresponds to COBOL's packed-decimal 
usage.
The type COBOL_Character defines the run-time character 
set used in the COBOL implementation. Ada_To_COBOL and COBOL_To_Ada are 
the mappings between the Ada and COBOL run-time character sets. 
Type Alphanumeric corresponds to COBOL's alphanumeric 
data category.
Each of the functions To_COBOL and To_Ada converts 
its parameter based on the mappings Ada_To_COBOL and COBOL_To_Ada, respectively. 
The length of the result for each is the length of the parameter, and 
the lower bound of the result is 1. Each component of the result is obtained 
by applying the relevant mapping to the corresponding component of the 
parameter.
Each of the procedures To_COBOL and To_Ada copies 
converted elements from Item to Target, using the appropriate mapping 
(Ada_To_COBOL or COBOL_To_Ada, respectively). The index in Target of 
the last element assigned is returned in Last (0 if Item is a null array). 
If Item'Length exceeds Target'Length, Constraint_Error 
is propagated.
 
Type Numeric corresponds to COBOL's numeric data 
category with display usage.
The types Display_Format, 
Binary_Format, and Packed_Format are used in conversions between Ada 
decimal type values and COBOL internal or external data representations. 
The value of the constant Native_Binary is either High_Order_First or 
Low_Order_First, depending on the implementation. 
function Valid (Item   : in Numeric;
                Format : in Display_Format) return Boolean;
The function Valid 
checks that the Item parameter has a value consistent with the value 
of Format. If the value of Format is other than Unsigned, Leading_Separate, 
and Trailing_Separate, the effect is implementation defined. If Format 
does have one of these values, the following rules apply: 
Format=Unsigned: if Item comprises one 
or more decimal digit characters, then Valid returns True, else it returns 
False.
Format=Leading_Separate: if Item comprises 
a single occurrence of the plus or minus sign character, and then one 
or more decimal digit characters, then Valid returns True, else it returns 
False.
Format=Trailing_Separate: 
if Item comprises one or more decimal digit characters and finally a 
plus or minus sign character, then Valid returns True, else it returns 
False. 
function Length (Format : in Display_Format) return Natural;
The Length function 
returns the minimal length of a Numeric value sufficient to hold any 
value of type Num when represented as Format.
function To_Decimal (Item   : in Numeric;
                     Format : in Display_Format) return Num;
Produces a value 
of type Num corresponding to Item as represented by Format. The number 
of digits after the assumed radix point in Item is Num'Scale. Conversion_Error 
is propagated if the value represented by Item is outside the range of 
Num. 
function To_Display (Item   : in Num;
                     Format : in Display_Format) return Numeric;
This function returns 
the Numeric value for Item, represented in accordance with Format. The 
length of the returned value is Length(Format), and the lower bound is 
1. Conversion_Error is propagated if Num is negative and Format is Unsigned.
function Valid (Item   : in Packed_Decimal;
                Format : in Packed_Format) return Boolean;
This function returns 
True if Item has a value consistent with Format, and False otherwise. 
The rules for the formation of Packed_Decimal values are implementation 
defined.
function Length (Format : in Packed_Format) return Natural;
This function returns 
the minimal length of a Packed_Decimal value sufficient to hold any value 
of type Num when represented as Format.
function To_Decimal (Item   : in Packed_Decimal;
                     Format : in Packed_Format) return Num;
Produces a value 
of type Num corresponding to Item as represented by Format. Num'Scale 
is the number of digits after the assumed radix point in Item. Conversion_Error 
is propagated if the value represented by Item is outside the range of 
Num.
function To_Packed (Item   : in Num;
                    Format : in Packed_Format) return Packed_Decimal;
This function returns 
the Packed_Decimal value for Item, represented in accordance with Format. 
The length of the returned value is Length(Format), and the lower bound 
is 1. Conversion_Error is propagated if Num is negative and Format is 
Packed_Unsigned.
function Valid (Item   : in Byte_Array;
                Format : in Binary_Format) return Boolean;
This function returns 
True if Item has a value consistent with Format, and False otherwise. 
function Length (Format : in Binary_Format) return Natural;
This function returns 
the minimal length of a Byte_Array value sufficient to hold any value 
of type Num when represented as Format.
function To_Decimal (Item   : in Byte_Array;
                     Format : in Binary_Format) return Num;
Produces a value 
of type Num corresponding to Item as represented by Format. Num'Scale 
is the number of digits after the assumed radix point in Item. Conversion_Error 
is propagated if the value represented by Item is outside the range of 
Num.
function To_Binary (Item   : in Num;
                    Format : in Binary_Format) return Byte_Array;
This function returns 
the Byte_Array value for Item, represented in accordance with Format. 
The length of the returned value is Length(Format), and the lower bound 
is 1.
function To_Decimal (Item : in Binary)      return Num;
function To_Decimal (Item : in Long_Binary) return Num;
These functions 
convert from COBOL binary format to a corresponding value of the decimal 
type Num. Conversion_Error is propagated if Item is too large for Num. 
function To_Binary      (Item : in Num)  return Binary;
function To_Long_Binary (Item : in Num)  return Long_Binary;
These functions convert from Ada decimal to COBOL 
binary format. Conversion_Error is propagated if the value of Item is 
too large to be represented in the result type. 
Implementation Requirements
 An implementation shall support specifying aspect 
Convention with a COBOL 
convention_
identifier 
for a COBOL-eligible type (see 
B.1). 
 
Implementation Permissions
An implementation may provide additional constants 
of the private types Display_Format, Binary_Format, or Packed_Format. 
An implementation may provide further floating point 
and integer types in Interfaces.COBOL to match additional native COBOL 
types, and may also supply corresponding conversion functions in the 
generic package Decimal_Conversions. 
Implementation Advice
An Ada implementation should support the following 
interface correspondences between Ada and COBOL. 
An Ada access T parameter is passed as a 
“BY REFERENCE” data item of the COBOL type corresponding 
to T.
An Ada in scalar parameter is passed as 
a “BY CONTENT” data item of the corresponding COBOL type.
Any other Ada parameter is passed as a “BY 
REFERENCE” data item of the COBOL type corresponding to the Ada 
parameter type; for scalars, a local copy is used if necessary to ensure 
by-copy semantics. 
12  An implementation is not required to 
support specifying aspect Convention for access types, nor is it required 
to support specifying aspects Import, Export, or Convention for functions. 
13  If an Ada subprogram is exported to 
COBOL, then a call from COBOL call may specify either “BY CONTENT” 
or “BY REFERENCE”. 
Examples
Examples of Interfaces.COBOL: 
with Interfaces.COBOL;
procedure Test_Call is
   -- Calling a foreign COBOL program
   -- Assume that a COBOL program PROG has the following declaration
   --  in its LINKAGE section:
   --  01 Parameter-Area
   --     05 NAME   PIC X(20).
   --     05 SSN    PIC X(9).
   --     05 SALARY PIC 99999V99 USAGE COMP.
   -- The effect of PROG is to update SALARY based on some algorithm
   package COBOL renames Interfaces.COBOL;
   type Salary_Type is delta 0.01 digits 7;
   type COBOL_Record is
      record
         Name   : COBOL.Numeric(1..20);
         SSN    : COBOL.Numeric(1..9);
         Salary : COBOL.Binary;  -- Assume Binary = 32 bits
      end record
      with Convention => COBOL;
   procedure Prog (Item : in out COBOL_Record)
      with Import => True, Convention => COBOL;
   package Salary_Conversions is
      new COBOL.Decimal_Conversions(Salary_Type);
   Some_Salary : Salary_Type := 12_345.67;
   Some_Record : COBOL_Record :=
      (Name   => "Johnson, John       ",
       SSN    => "111223333",
       Salary => Salary_Conversions.To_Binary(Some_Salary));
begin
   Prog (Some_Record);
   ...
end Test_Call;
with Interfaces.COBOL;
with COBOL_Sequential_IO; -- Assumed to be supplied by implementation
procedure Test_External_Formats is
   -- Using data created by a COBOL program
   -- Assume that a COBOL program has created a sequential file with
   --  the following record structure, and that we need to
   --  process the records in an Ada program
   --  01 EMPLOYEE-RECORD
   --     05 NAME    PIC X(20).
   --     05 SSN     PIC X(9).
   --     05 SALARY  PIC 99999V99 USAGE COMP.
   --     05 ADJUST  PIC S999V999 SIGN LEADING SEPARATE.
   -- The COMP data is binary (32 bits), high-order byte first
   package COBOL renames Interfaces.COBOL;
   type Salary_Type      is delta 0.01  digits 7;
   type Adjustments_Type is delta 0.001 digits 6;
   type COBOL_Employee_Record_Type is  -- External representation
      record
         Name    : COBOL.Alphanumeric(1..20);
         SSN     : COBOL.Alphanumeric(1..9);
         Salary  : COBOL.Byte_Array(1..4);
         Adjust  : COBOL.Numeric(1..7);  -- Sign and 6 digits
      end record
      with Convention => COBOL;
   package COBOL_Employee_IO is
      new COBOL_Sequential_IO(COBOL_Employee_Record_Type);
   use COBOL_Employee_IO;
   COBOL_File : File_Type;
   type Ada_Employee_Record_Type is  -- Internal representation
      record
         Name    : String(1..20);
         SSN     : String(1..9);
         Salary  : Salary_Type;
         Adjust  : Adjustments_Type;
      end record;
   COBOL_Record : COBOL_Employee_Record_Type;
   Ada_Record   : Ada_Employee_Record_Type;
   package Salary_Conversions is
      new COBOL.Decimal_Conversions(Salary_Type);
   use Salary_Conversions;
   package Adjustments_Conversions is
      new COBOL.Decimal_Conversions(Adjustments_Type);
   use Adjustments_Conversions;
begin
   Open (COBOL_File, Name => "Some_File");
   loop
     Read (COBOL_File, COBOL_Record);
     Ada_Record.Name := To_Ada(COBOL_Record.Name);
     Ada_Record.SSN  := To_Ada(COBOL_Record.SSN);
     Ada_Record.Salary :=
        To_Decimal(COBOL_Record.Salary, COBOL.High_Order_First);
     Ada_Record.Adjust :=
        To_Decimal(COBOL_Record.Adjust, COBOL.Leading_Separate);
     ... -- Process Ada_Record
   end loop;
exception
   when End_Error => ...
end Test_External_Formats;
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe