Справочник по Ada 95
B.4 Взаимодействие с COBOL
Средства, относящиеся к взаимодействию с языком COBOL, — это пакет Interfaces.COBOL и поддержка директив Import, Export и Convention с convention_идентификатором COBOL.
Пакет интерфейса COBOL предоставляет несколько наборов средств:
- Набор типов, соответствующих родным типам COBOL поддерживаемой реализации COBOL (так называемые «внутренние представления COBOL»), позволяющие передавать данные Ada в качестве параметров программам COBOL
- Набор типов и констант, отражающих внешние представления данных, такие как те, которые могут встречаться в файлах или базах данных, позволяющие программе Ada читать данные, сгенерированные COBOL, а программам COBOL — данные, сгенерированные Ada
- Обобщенный пакет для преобразования значения типа Ada decimal в внутреннее или внешнее представление COBOL
Статическая семантика
Пакет библиотеки Interfaces.COBOL имеет следующую декларацию:
package Interfaces.COBOL is
pragma Preelaborate(COBOL);
pragma Preelaborate(COBOL);
-- Типы и операции для внутренних представлений данных
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;
pragma Pack(Packed_Decimal);
type Packed_Decimal is array (Positive range <>) of Decimal_Element;
pragma Pack(Packed_Decimal);
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;
pragma Pack(Alphanumeric);
pragma Pack(Alphanumeric);
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;
pragma Pack(Numeric);
pragma Pack(Numeric);
-- Форматы для представлений данных 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;
pragma Pack (Byte_Array);
type Byte_Array is array (Positive range <>) of Byte;
pragma Pack (Byte_Array);
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 decimal и внутренними или внешними представлениями данных 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;
END_OF_DOCUMENT_MARKER Функция 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, представленное в соответствии с Format. Длина возвращаемого значения равна 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 слишком велико для представления в типе результата.
Требования к реализации
Реализация должна поддерживать pragma 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.
- Скалярный параметр Ada in передается как элемент данных ``BY CONTENT'' соответствующего типа COBOL.
- Любой другой параметр Ada передается как элемент данных ``BY REFERENCE'' соответствующего типа COBOL; для скаляров используется локальная копия, если необходимо, для обеспечения семантики копирования.
ПРИМЕЧАНИЯ
15 Реализация не обязана поддерживать pragma Convention для типов доступа, а также не обязана поддерживать pragma Import, Export или Convention для функций.
16 Если подпрограмма 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;
pragma Convention (COBOL, COBOL_Record);
record
Name : COBOL.Numeric(1..20);
SSN : COBOL.Numeric(1..9);
Salary : COBOL.Binary; -- Предполагается, что Binary = 32 бит
end record;
pragma Convention (COBOL, COBOL_Record);
procedure Prog (Item : in out COBOL_Record);
pragma Import (COBOL, Prog, "PROG");
pragma Import (COBOL, Prog, "PROG");
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;
pragma Convention (COBOL, COBOL_Employee_Record_Type);
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;
pragma Convention (COBOL, COBOL_Employee_Record_Type);
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);
END_OF_DOCUMENT_MARKER 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);
... -- Обработать Ada_Record
end loop;
exception
when End_Error => ...
end Test_External_Formats;
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);
... -- Обработать Ada_Record
end loop;
exception
when End_Error => ...
end Test_External_Formats;