Руководство по Ada (Ada 2022)
B.4 Взаимодействие с COBOL
Средства, относящиеся к взаимодействию с языком COBOL, — это пакет Interfaces.COBOL и поддержка указания аспекта Convention с convention_идентификатором COBOL.
Пакет интерфейса COBOL предоставляет несколько наборов средств:
- Набор типов, соответствующих родным типам COBOL поддерживаемой реализации COBOL (так называемые «внутренние представления COBOL»), позволяющие передавать данные Ada в качестве параметров программам COBOL
- Набор типов и констант, отражающих внешние представления данных, такие как те, которые можно найти в файлах или базах данных, позволяющие программе Ada читать данные, сгенерированные COBOL, а также данные, сгенерированные Ada, могут быть прочитаны программами COBOL
- Обобщённый пакет для преобразования между значением типа десятичной арифметики Ada и либо внутренним, либо внешним представлением COBOL
Статическая семантика
Пакет библиотеки Interfaces.COBOL имеет следующее объявление:
package Interfaces.COBOL
with Preelaborate, Nonblocking, Global => in out synchronized is
with Preelaborate, Nonblocking, Global => in out synchronized is
-- Типы и операции для внутренних представлений данных
type Floating is digits определяемое реализацией;
type Long_Floating is digits определяемое реализацией;
type Long_Floating is digits определяемое реализацией;
type Binary is range определяемое реализацией;
type Long_Binary is range определяемое реализацией;
type Long_Binary is range определяемое реализацией;
Max_Digits_Binary : constant := определяемое реализацией;
Max_Digits_Long_Binary : constant := определяемое реализацией;
Max_Digits_Long_Binary : constant := определяемое реализацией;
type Decimal_Element is mod определяемое реализацией;
type Packed_Decimal is array (Positive range <>) of Decimal_Element
with Pack;
type Packed_Decimal is array (Positive range <>) of Decimal_Element
with Pack;
type COBOL_Character is тип символов, определяемый реализацией;
Ada_To_COBOL : array (Character) of COBOL_Character := определяемое реализацией;
COBOL_To_Ada : array (COBOL_Character) of Character := определяемое реализацией;
type Alphanumeric is array (Positive range <>) of COBOL_Character
with Pack;
with Pack;
function To_COBOL (Item : in String) return Alphanumeric;
function To_Ada (Item : in Alphanumeric) return String;
function To_Ada (Item : in Alphanumeric) return String;
procedure To_COBOL (Item : in String;
Target : out Alphanumeric;
Last : out Natural);
Target : out Alphanumeric;
Last : out Natural);
procedure To_Ada (Item : in Alphanumeric;
Target : out String;
Last : out Natural);
Target : out String;
Last : out Natural);
type Numeric is array (Positive range <>) of COBOL_Character
with Pack;
with Pack;
-- Форматы для представлений данных COBOL
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;
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;
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;
Packed_Signed : constant Packed_Format;
-- Типы для внешнего представления двоичных данных COBOL
type Byte is mod 2**COBOL_Character'Size;
type Byte_Array is array (Positive range <>) of Byte
with Pack;
type Byte_Array is array (Positive range <>) of Byte
with Pack;
Conversion_Error : exception;
generic
type Num is delta <> digits <>;
package Decimal_Conversions is
type Num is delta <> digits <>;
package Decimal_Conversions is
-- Форматы отображения: значения данных представлены как Numeric
function Valid (Item : in Numeric;
Format : in Display_Format) return Boolean;
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;
Format : in Display_Format) return Num;
function To_Display (Item : in Num;
Format : in Display_Format) return Numeric;
Format : in Display_Format) return Numeric;
-- Упакованные форматы: значения данных представлены как Packed_Decimal
function Valid (Item : in Packed_Decimal;
Format : in Packed_Format) return Boolean;
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;
Format : in Packed_Format) return Num;
function To_Packed (Item : in Num;
Format : in Packed_Format) return Packed_Decimal;
Format : in Packed_Format) return Packed_Decimal;
-- Двоичные форматы: внешние значения данных представлены как Byte_Array
function Valid (Item : in Byte_Array;
Format : in Binary_Format) return Boolean;
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_Decimal (Item : in Byte_Array;
Format : in Binary_Format) return Num;
function To_Binary (Item : in Num;
Format : in Binary_Format) return Byte_Array;
Format : in Binary_Format) return Byte_Array;
-- Внутренние двоичные форматы: значения данных имеют тип Binary или Long_Binary
function To_Decimal (Item : in Binary) return Num;
function To_Decimal (Item : in Long_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;
function To_Long_Binary (Item : in Num) return Long_Binary;
end Decimal_Conversions;
private
... -- не определено языком
end Interfaces.COBOL;
... -- не определено языком
end Interfaces.COBOL;
Каждый из типов в Interfaces.COBOL совместим с COBOL.
Типы Floating и Long_Floating соответствуют родным типам в COBOL для элементов данных с вычислительным использованием, реализованным с помощью плавающей точки. Типы Binary и Long_Binary соответствуют родным типам в COBOL для элементов данных с двоичным использованием или с вычислительным использованием, реализованным с помощью двоичного кода.
Max_Digits_Binary — это максимальное количество десятичных цифр в числовом значении, представленном как Binary. Max_Digits_Long_Binary — это максимальное количество десятичных цифр в числовом значении, представленном как Long_Binary.
Тип Packed_Decimal соответствует упакованному десятичному представлению COBOL.
Тип COBOL_Character определяет набор символов во время выполнения, используемый в реализации COBOL. Ada_To_COBOL и COBOL_To_Ada — это сопоставления между наборами символов Ada и COBOL во время выполнения.
Тип Alphanumeric соответствует алфавитно-цифровому типу данных COBOL.
Каждая из функций To_COBOL и To_Ada преобразует свой параметр на основе соответствий Ada_To_COBOL и COBOL_To_Ada соответственно. Длина результата для каждого — это длина параметра, а нижняя граница результата — 1. Каждый компонент результата получается путём применения соответствующего сопоставления к соответствующему компоненту параметра.
Каждая из процедур To_COBOL и To_Ada копирует преобразованные элементы из Item в Target, используя соответствующее сопоставление (Ada_To_COBOL или COBOL_To_Ada соответственно). Индекс в Target последнего присвоенного элемента возвращается в Last (0, если Item — массив null). Если Item'Length превышает Target'Length, генерируется исключение Constraint_Error.
Тип Numeric соответствует числовому типу данных COBOL с использованием отображения.
Типы Display_Format, Binary_Format и Packed_Format используются при преобразованиях между значениями десятичного типа Ada и внутренними или внешними представлениями данных COBOL. Значение константы Native_Binary равно либо High_Order_First, либо Low_Order_First, в зависимости от реализации.
function Valid (Item : in Numeric;
Format : in Display_Format) return Boolean;
Format : in Display_Format) return Boolean;
Функция Valid проверяет, соответствует ли значение параметра Item значению Format. Если значение Format отличается от Unsigned, Leading_Separate и Trailing_Separate, то результат определяется реализацией. Если Format имеет одно из этих значений, применяются следующие правила:
Format=Unsigned: если Item состоит из одной или нескольких десятичных цифр, то Valid возвращает True, иначе — False.
Format=Leading_Separate: если Item состоит из одного символа знака плюс или минус, а затем из одной или нескольких десятичных цифр, то Valid возвращает True, иначе — False.
Format=Trailing_Separate: если Item состоит из одной или нескольких десятичных цифр, а затем символа знака плюс или минус, то Valid возвращает True, иначе — False.
function Length (Format : in Display_Format) return Natural;
Функция Length возвращает минимальную длину числового значения, достаточного для хранения любого значения типа Num, представленного в формате Format.
function To_Decimal (Item : in Numeric;
Format : in Display_Format) return Num;
Format : in Display_Format) return Num;
Возвращает значение типа Num, соответствующее Item, представленному в формате Format. Количество цифр после предполагаемой запятой в Item равно Num'Scale. Ошибка преобразования распространяется, если значение, представленное Item, выходит за пределы диапазона Num.
function To_Display (Item : in Num;
Format : in Display_Format) return Numeric;
Format : in Display_Format) return Numeric;
Эта функция возвращает числовое значение Item, представленное в соответствии с форматом. Длина возвращаемого значения равна Length(Format), а нижняя граница равна 1. Ошибка преобразования распространяется, если Num отрицательно, а Format — Unsigned.
function Valid (Item : in Packed_Decimal;
Format : in Packed_Format) return Boolean;
Format : in Packed_Format) return Boolean;
Эта функция возвращает True, если Item имеет значение, согласованное с Format, и False в противном случае. Правила формирования значений Packed_Decimal определяются реализацией.
function Length (Format : in Packed_Format) return Natural;
Эта функция возвращает минимальную длину значения Packed_Decimal, достаточную для хранения любого значения типа Num, представленного в формате Format.
function To_Decimal (Item : in Packed_Decimal;
Format : in Packed_Format) return Num;
Format : in Packed_Format) return Num;
Возвращает значение типа Num, соответствующее Item, представленному в формате Format. Num'Scale — количество цифр после предполагаемой запятой в Item. Ошибка преобразования распространяется, если значение, представленное Item, выходит за пределы диапазона Num.
function To_Packed (Item : in Num;
Format : in Packed_Format) return Packed_Decimal;
Format : in Packed_Format) return Packed_Decimal;
Эта функция возвращает значение Packed_Decimal для Item, представленное в соответствии с Format. Длина возвращаемого значения равна Length(Format), а нижняя граница равна 1. Ошибка преобразования распространяется, если Num отрицательно, а Format — Packed_Unsigned.
function Valid (Item : in Byte_Array;
Format : in Binary_Format) return Boolean;
Format : in Binary_Format) return Boolean;
Эта функция возвращает True, если Item имеет значение, согласованное с Format, и False в противном случае.
function Length (Format : in Binary_Format) return Natural;
Эта функция возвращает минимальную длину значения Byte_Array, достаточную для хранения любого значения типа Num, представленного в формате Format.
function To_Decimal (Item : in Byte_Array;
Format : in Binary_Format) return Num;
Format : in Binary_Format) return Num;
Возвращает значение типа Num, соответствующее Item, представленному в формате Format. Num'Scale — количество цифр после предполагаемой запятой в Item. Ошибка преобразования распространяется, если значение, представленное Item, выходит за пределы диапазона Num.
function To_Binary (Item : in Num;
Format : in Binary_Format) return Byte_Array;
Format : in Binary_Format) return Byte_Array;
Эта функция возвращает значение Byte_Array для Item, представленное в соответствии с Format. Длина возвращаемого значения равна Length(Format), а нижняя граница равна 1.
function To_Decimal (Item : in Binary) return Num;
function To_Decimal (Item : in Long_Binary) return Num;
function To_Decimal (Item : in Long_Binary) return Num;
Эти функции преобразуют формат двоичных данных COBOL в соответствующее значение десятичного типа Num. Ошибка преобразования распространяется, если Item слишком велик для Num.
function To_Binary (Item : in Num) return Binary;
function To_Long_Binary (Item : in Num) return Long_Binary;
function To_Long_Binary (Item : in Num) return Long_Binary;
Эти функции преобразуют десятичное значение Ada в двоичный формат COBOL. Ошибка преобразования распространяется, если значение Item слишком велико для представления в типе результата.
Требования к реализации
Реализация должна поддерживать указание аспекта Convention с идентификатором COBOL convention_identifier для типа, совместимого с COBOL (см. B.1).
Разрешения реализации
Реализация может предоставить дополнительные константы частных типов Display_Format, Binary_Format или Packed_Format.
Реализация может предоставить дополнительные типы с плавающей запятой и целые типы в Interfaces.COBOL для соответствия дополнительным нативным типам COBOL, а также может предоставить соответствующие функции преобразования в обобщенном пакете Decimal_Conversions.
Рекомендации по реализации
Реализация Ada должна поддерживать следующие соответствия интерфейсов между Ada и COBOL.
- Параметр Ada access T передается как элемент данных «BY REFERENCE» соответствующего типа COBOL для T.
- Скалярный параметр Ada in передается как элемент данных «BY CONTENT» соответствующего типа COBOL.
- Любой другой параметр Ada передается как элемент данных «BY REFERENCE» соответствующего типа COBOL для типа параметра Ada; для скаляров локальная копия используется при необходимости, чтобы обеспечить семантику копирования.
ПРИМЕЧАНИЕ 1 Реализация не обязана поддерживать указание аспекта Convention для типов access, а также не обязана поддерживать указание аспектов Import, Export или Convention для функций.
ПРИМЕЧАНИЕ 2 Если подпрограмма Ada экспортируется в COBOL, то вызов из COBOL может указать либо «BY CONTENT», либо «BY REFERENCE».
Примеры
Примеры Interfaces.COBOL:
with Interfaces.COBOL;
procedure Test_Call is
procedure Test_Call is
-- Вызов внешней COBOL программы
-- Предположим, что COBOL программа PROG имеет следующее объявление
-- в разделе LINKAGE:
-- 01 Parameter-Area
-- 05 NAME PIC X(20).
-- 05 SSN PIC X(9).
-- 05 SALARY PIC 99999V99 USAGE COMP.
-- Эффект PROG — обновление SALARY на основе некоторого алгоритма
-- Предположим, что COBOL программа PROG имеет следующее объявление
-- в разделе LINKAGE:
-- 01 Parameter-Area
-- 05 NAME PIC X(20).
-- 05 SSN PIC X(9).
-- 05 SALARY PIC 99999V99 USAGE COMP.
-- Эффект PROG — обновление SALARY на основе некоторого алгоритма
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; -- Предполагается, что Binary = 32 бита
end record
with Convention => COBOL;
record
Name : COBOL.Numeric(1..20);
SSN : COBOL.Numeric(1..9);
Salary : COBOL.Binary; -- Предполагается, что Binary = 32 бита
end record
with Convention => COBOL;
procedure Prog (Item : in out COBOL_Record)
with Import => True, Convention => COBOL;
with Import => True, Convention => COBOL;
package Salary_Conversions is
new COBOL.Decimal_Conversions(Salary_Type);
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));
Some_Record : COBOL_Record :=
(Name => "Johnson, John ",
SSN => "111223333",
Salary => Salary_Conversions.To_Binary(Some_Salary));
begin
Prog (Some_Record);
...
end Test_Call;
Prog (Some_Record);
...
end Test_Call;
with Interfaces.COBOL;
with COBOL_Sequential_IO; -- Предполагается, что поставляется реализацией
procedure Test_External_Formats is
with COBOL_Sequential_IO; -- Предполагается, что поставляется реализацией
procedure Test_External_Formats is
-- Использование данных, созданных COBOL программой
-- Предположим, что COBOL программа создала последовательный файл со
-- следующей структурой записи, и мы хотим
-- обработать записи в Ada программе
-- 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.
-- Данные COMP — двоичные (32 бита), старший байт первым
-- Предположим, что COBOL программа создала последовательный файл со
-- следующей структурой записи, и мы хотим
-- обработать записи в Ada программе
-- 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.
-- Данные COMP — двоичные (32 бита), старший байт первым
package COBOL renames Interfaces.COBOL;
type Salary_Type is delta 0.01 digits 7;
type Adjustments_Type is delta 0.001 digits 6;
type Adjustments_Type is delta 0.001 digits 6;
type COBOL_Employee_Record_Type is -- Внешнее представление
record
Name : COBOL.Alphanumeric(1..20);
SSN : COBOL.Alphanumeric(1..9);
Salary : COBOL.Byte_Array(1..4);
Adjust : COBOL.Numeric(1..7); -- Знак и 6 цифр
end record
with Convention => COBOL;
record
Name : COBOL.Alphanumeric(1..20);
SSN : COBOL.Alphanumeric(1..9);
Salary : COBOL.Byte_Array(1..4);
Adjust : COBOL.Numeric(1..7); -- Знак и 6 цифр
end record
with Convention => COBOL;
package COBOL_Employee_IO is
new COBOL_Sequential_IO(COBOL_Employee_Record_Type);
use COBOL_Employee_IO;
new COBOL_Sequential_IO(COBOL_Employee_Record_Type);
use COBOL_Employee_IO;
COBOL_File : File_Type;
type Ada_Employee_Record_Type is -- Внутреннее представление
record
Name : String(1..20);
SSN : String(1..9);
Salary : Salary_Type;
Adjust : Adjustments_Type;
end record;
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;
Ada_Record : Ada_Employee_Record_Type;
package Salary_Conversions is
new COBOL.Decimal_Conversions(Salary_Type);
use Salary_Conversions;
new COBOL.Decimal_Conversions(Salary_Type);
use Salary_Conversions;
package Adjustments_Conversions is
new COBOL.Decimal_Conversions(Adjustments_Type);
use Adjustments_Conversions;
new COBOL.Decimal_Conversions(Adjustments_Type);
use Adjustments_Conversions;
begin
Open (COBOL_File, Name => "Some_File");
Open (COBOL_File, Name => "Some_File");
loop
Read (COBOL_File, COBOL_Record);
Read (COBOL_File, COBOL_Record);
Ada_Record.Name := COBOL.To_Ada(COBOL_Record.Name);
Ada_Record.SSN := COBOL.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);
... -- Обработать Ada_Record
end loop;
exception
when End_Error => ...
end Test_External_Formats;
Ada_Record.SSN := COBOL.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);
... -- Обработать Ada_Record
end loop;
exception
when End_Error => ...
end Test_External_Formats;