PL/I

Простейшие операторы ввода-вывода в PL/I

Результаты, получаемые в процессе решения задачи, практически всегда передаются из оперативной памяти ЭВМ на какие-либо внешние устройства. Семейство данных, расположенное на внешнем устройстве (в том числе и терминале), называется набором данных. Процесс передачи данных из оперативной памяти ЭВМ на внешние носители называется выводом данных. Исходные данные для решения задачи передаются в оперативную память ЭВМ с каких-либо внешних носителей. Этот процесс называется вводом данных. Процесс ввода-вывода данных осуществляется с помощью операторов ввода и вывода данных. Операторы ввода-вывода используют только логическую структуру набора данных, без её физических характеристик. В языке PL/1 предусмотрены разнообразные операторы для выполнения ввода и вывода данных. Подробно они будут рассмотрены ниже. Однако, учитывая необходимость ввода и вывода данных даже в программах с простейшей структурой, рассмотрим наиболее часто используемые формы операторов ввода-вывода.

Оператор цикла DO в PL/I

Последовательность операторов a1a2…an образует цикл, если a1 – оператор заголовка цикла, an – оператор конца END. Различают четыре типа оператора заголовка цикла.

Оператор первого типа имеет вид или

DO WHILE (e1) u;

или

DO UNTIL (e2) w;

Пустой оператор в PL/I

Пустой оператор имеет пустое тело. Оператор не задаёт никаких действий, Он может быть, например, использован для размещения метки.

Условный оператор в PL/I

Условный оператор имеет одну из следующих форм

IF x THEN y;

IF x THEN y; ELSE z;

где x – выражение; y, z –либо отдельный оператор (кроме операторов DECLARE, DEFAULT, PROCEDURE, DO, BEGIN, END, ENTRY, FORMAT, %выражений), либо группа операторов (цикл), либо блок BEGIN. Выражение x принято называть логическим. Обычно в качестве логических используются выражения, значения которых являются строками из одного бита (напомним, что результаты всех операций сравнения являются строками из одного бита). Условный оператор выполняется следующим образом. Вычисляется значение выражения x. Если оно равно биту 1, то управление передается y; после выполнения y (если не изменится порядок выполнения программы) управление передается оператору, следующему за z (если конструкция ELSE задана) либо за y (если конструкция ELSE не задана). Если значение выражения равно биту 0, то управление передается z (если конструкция ELSE задана), либо оператору, следующему за y (если конструкция ELSE не задана).

Оператор перехода в PL/I. Переменные типа метка

Оператор перехода имеет вид

GO TO x;

где x – любая метка оператора (кроме операторов PROCEDURE, ENRTY,DECLARE, DEFAULT, FORMAT), либо переменная типа метки. Если x – метка, то выполнение оператора перехода заключается в передаче управления, помеченному меткой x оператору.

Переменные типа метка должны быть явно описаны в операторе описания с описателем вида

LABEL либо LABEL (m1,m2,…,mn),

где mi (i=1,2,…,n) метки операторов, представляющие собой все возможные значения данной переменной типа метка. Присвоение значения переменной типа метка можно осуществить с помощью оператора присваивания. В левой части такого оператора указывается одна или несколько переменных типа метка, а в правой части – либо переменная типа метка, либо метка какого-либо оператора допустимого типа, называемая иногда константой-меткой.

Примеры:

1) DCL xyz label;
2) dcl ladel_x label init(a);
3) dcl xyz label(abc,d4);
4) dcl xyz label;
...
Abc: выражение
...
D4:выражение;
...
Xyz=abc

Оператор присваивания в PL/I

Оператор присваивания для переменных имеет вид

v1,v2,…,vn=e;

Здесь e – выражение, vi – имена переменных либо имена псевдопеременных. Выполнение оператора заключается в вычислении значения выражения e и присвоении этого значения переменным v1,v2,…,vn. Если необходимо, то вычисленное значение выражения перед присвоением преобразуется в соответствии с описателями переменной vi по правилам, приведенным при рассмотрении выражений.

Оператор описания в PL/I (DECLARE).

Различные объекты, используемые в программе, могут быть описаны в операторе описания. Этот оператор в общем виде может быть представлен следующим образом:

DECLARE n1N1a11a12… a1k, n2N2a21a22…a2p,…, nmNmam1,am2,…,aml;

где Ni – идентификатор (имя описываемого объекта); ni – номер уровня, задаваемый только при описании структур, в остальных случаях ni – пусто; aij – описатели (атрибуты), к числу которых относятся описатели типа данных, измерения и др. Описатели данного объекта могут следовать в любом порядке. Исключение составляют описатели точности, длины, и измерения массива, для которых установлен определённый порядок следования.

Организация программы. Основные операторы

PL/1 является блочно-структурированным языком. То есть структурно программа состоит из блоков операторов. Различают блоки PACKAGE, PROCEDURE и блоки BEGIN. Блоки могут быть вложены или транслироваться отдельно. Приложение на PL/1 содержит один или несколько загрузочных модулей. Загрузочный модуль в свою очередь состоит из одного или нескольких отдельно компилируемых сущностей, называемых компилируемыми единицами. Компилируемой единицей в PL/1 является либо блок PACKAGE либо внешний блок PROCEDURE. Каждый пакет может содержать нуль или несколько процедур.

Любая программа обязательно содержит внешний блок PROCEDURE, который обычно определяют как главную процедуру.

Программа с простейшей структурой представляет собой последовательность операторов s1s2…sk, в которой s1 –оператор-заголовок программы, имеющий вид

labеl: PROCEDURE OPTIONS (MAIN);

sk – оператор конца, имеющий вид

[label1:…] END [label2];

Выражения над структурами в языке PL/1

Выражения над структурами допускаются только в операторе присваивания и как аргументы процедур и функций. Операндами такого выражения, помимо структур, могут быть константы, указатели функций и имена переменных; имена массивов не могут быть операндами выражений над структурами. Все операнды-структуры должны иметь идентичную организацию. Результатом вычисления выражения над структурами является структура с той же организацией, что и у операндов-структур. Выражение, хотя бы один операнд которого является имя массива структур, называется выражением над массивами структур. Операндами такого выражения, помимо массивов структур, могут быть константы, указатели функций и имена переменных; имена массивов переменных и имена структур не могут быть операндами выражений над массивами структур. Все массивы структур, являющиеся опе6рандами одного выражения, должны иметь одинаковую размерность, одинаковые границы индексов и идентичную организацию элементов-структур.

Выражение над массивами в языке PL/1

В языке PL/1 можно задавать действия не только над элементами массивов (которые рассматриваются как скалярные выражения), но и над целыми массивами. Синтаксически такие выражения аналогичны скалярным выражениям. Однако в данном случае в качестве операнда помимо константы, имени переменной и указателя функции может быть использовано и имя массива. Все массивы, входящие в выражение, должны иметь одинаковую размерность и одинаковые границы по соответствующим измерениям. Значением выражения над массивами является массив той же размерности и с теми же границами по каждому измерению, что и в массивах, входящих в это выражение. В выражениях над массивами могут быть использованы функции, результатом выполнения которых являются не отдельное значение, а массив значений. Кроме того, имеется ряд встроенных функций, аргументами которых могут быть массивы, вычисляющих одно скалярное значение.

Работа с указателями в языке PL/1

При работе с указателями допустимы следующие действия:

1. Добавление арифметического выражения и вычитание арифметического выражения из указателя. При этом при необходимости результат арифметического выражения преобразуется к типу FIXED BINARY (31,0). Например
Ptr1 = Ptr1 – 16;
Prt2 = Ptr1 + (I*J);
2. Вычитание двух указателей для получения логической разности.
3. Сравнение двух выражений с указателями.
4. Использовать выражение с указателями в качестве аргументов соответствующих встроенных функций.

Операции сравнения языка PL/1

К операциям сравнения относятся: = (равно), = (не равно), > (больше), > (не больше), < (меньше), < (не меньше). Результатом операции сравнения является битовая строка ‘1’B, если сравнение верно для данных операндов, в противном случае результат равен строке ‘0’B.

Операции сравнения непосредственно определены либо для двух арифметических операндов, либо для двух символьно-строчных операндов либо для двух битово-строчных операндов. Для арифметических операндов операции сравнения имеют обычный математический смысл. Для комплексных чисел определены лишь операции сравнения = (равно) и = (не равно).

Если арифметические операнды, участвующие в операции сравнения имеют различные характеристики, то выполняются преобразования по тем же правилам, что и для арифметических операций. Если сравниваются арифметический и строковый операнды, то строковый операнд предварительно преобразуется к числовому виду по тем же правилам, что и для арифметических операций.

Выражения языка PL/1

Выражение является представлением значения. Выражения образуются из операндов, знаков операций и круглых скобок. Знаками арифметических операций являются: + (сложить), - (вычесть), * (умножить), / (разделить), ** (возвести в степень). Знаками операций сравнения являются: = (равно), = (не равно), < (меньше), < (не меньше), > (больше), > (не больше), <= (меньше или равно), >= (больше или равно). Логические операции имеют следующие знаки  (НЕТ), & (И), | (ИЛИ). Операция над строками || (сцепление).

Выражение может состоять из одной константы, одной переменной или одного указателя функции. Или же выражение состоит из комбинации констант, переменных, операций, указателей функций и круглых скобок. Выражение, содержащее операции называется операторным выражением. Константы, переменные и операторные выражения называются операндами.

Различают три типа выражений: скалярные выражения, выражения над массивами, выражения над структурами.

Переменные языка PL/1

Значения арифметических переменных имеют те же характеристики, что и числовых констант: тип (вещественный (REAL) или комплексный (COMPLEX)), основание системы счисления (десятичное (DECIMAL) или двоичное (BINARY)), форма представления (с плавающей (FLOAD) или фиксированной (FIXED) точкой) и точность (p) или (p,q), где p – целое положительное десятичное число, q – целое десятичное число (положительное или отрицательное). Число p указывает на количество цифр в представлении значений переменной, число q играет роль масштабного множителя, указывающего, что значение переменной должно быть умножено на число 10-q, если значение переменной дано в десятичной системе счисления, и на число 2-q, если значение переменной дано в двоичной системе счисления. Например, пусть значение переменной имеет вид 58, а характеристики точности – вид (2, -2). Тогда истинное значение переменной – число 5800.

Константы языка PL/1

Рассмотрим основные типы данных на примере констант.

Десятичные константы с фиксированной точкой (DECIMAL FIXED POINT) могут иметь один из следующих видов:

a) Sa1a2…an.b1b2…bk
b) Sa1a2…an.
c) Sa1a2…an
d) S.b1b2…bk

Здесь S – либо пусто, либо знак константы (плюс или минус), ai (i=1,…,n) –цифры целой части, bj (j=1,…,k) – цифры дробной части, символ . (точка) – разделитель целой и дробной частей константы, называемый десятичной точкой. То есть десятичные константы с фиксированной точкой представляют собой строку из одной или нескольких десятичных цифр с десятичной точкой или без неё. Если десятичной точки нет, то предполагается, что она следует сразу же за последним числом строки.

Примеры

8.7625
-248
-.00007
972.
+10.2
-0.123

Если в константе отсутствует дробная часть, её называют десятичной целой.

По умолчанию максимальная длина константы составляет 15 десятичных цифр. При компилировании можно указанием опций увеличить длину до 31.

Данные языка PL/1

Данное - это или значение переменной, или константа. Данные могут являться либо отдельными скалярными величинами, обращение к которым возможно только индивидуально, либо совокупностью скалярных величин, обращение к которым возможно как в целом, так и индивидуально. К совокупностям данных относятся массивы, структуры и объединения.

Переменная – это величина, которая может изменяться в процессе выполнения программы. Переменная объявляется оператором описания. Объявление включает в себя указание имени переменной и определённых атрибутов переменной. Переменная, имеющая атрибут NONASSIGNABLE, предполагается не изменяемой в процессе выполнения программы. Ссылка на переменную может осуществляться либо по её имени, либо опосредовано квалификацией указателя, квалификацией структуры или индексом.

Операторы языка PL/1

Основной конструкцией PL-программы является оператор. Оператор (statement) в PL/1 образуется из идентификаторов, разделителей, операций и констант. В общем виде оператор можно представить следующим образом

pms;

Здесь p – либо пусто, либо список префиксов состояний; m – либо пусто, либо конструкция вида m1:m2:…:mk (k1), где mi (i=1,…,k) – метка оператора; s – собственно оператор (иногда s называют телом оператора); ; - признак конца оператора.

Операторы используются для указания некоторых действий, описания свойств величин, определения структуры программы. Единственным оператором, не задающим никаких сведений, является пустой оператор. Тело этого оператора не содержит никаких символов. Например, пустой оператор с метками М1 и М2 имеет вид

М1: М2: ;

Программа с простейшей структурой представляет собой последовательность операторов

s1s2…sk (k2),

где si (i=1,…k) – оператор. Оператор s1 является оператором заголовка процедуры, имеющим в простейшем случае вид

Основные символы языка PL/1

PL/1 имеет набор из 61 символа. В наборе существуют три вида символов: алфавитные (буквы), цифровые и специальные. Некоторые символы могут быть объединены, они образуют комбинированные (составные) символы.

PL/1 поддерживает однобайтовое множество символов (SBCS) и двухбайтное множество символов (DBCS).

Следующие символы входят в набор символов.

Буквы (алфавитные символы) – это 26 символов английского алфавита: A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z.

Цифры – это следующие десять символов: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

В PL/1 не делается различий между большими и малыми буквами при написании ключевых слов и идентификаторов.

В зависимости от контекста PL/1 различает двоичные цифры 0 и 1, десятичные цифры 0,…,9 и шестнадцатеричные цифры 1,…,9, A,…,F.

Первичные конструкции языка PL/1

Алгоритмический язык образуют три его составляющие: алфавит, синтаксис и семантика.

Алфавит – это фиксированный для данного языка набор основных символов, из которых должен состоять любой текст на этом языке – никакие другие символы в тексте не допускаются.

Синтаксис – это система правил, определяющих допустимые конструкции из букв алфавита.

Семантика – это система правил истолкования отдельных языковых конструкций, позволяющих однозначно воспроизвести процесс обработки данных по заданной программе.

Процесс выполнения PL-программы

Процесс выполнения PL-программы включает в себя следующие четыре основных действия:

1. Введение PL-программы в компьютер.
2. Компиляция программы - перевод программы c языка PL в последовательность машинных команд (создание так называемого объектного модуля).
3. Редактирование связей: создание загрузочного модуля из объектного модуля. Данное действие включает присоединение к объектному модулю библиотечных модулей и возможно других откомпилированных программ, а также адресацию и выделение памяти.
4. Выполнение загрузочного модуля.

Последовательность этих действий не обязательно должна повторяться целиком. Программа может быть один раз откомпилирована, и затем выполняться нужное число раз.

История возникновения языка PL/1

При разработке системы языков программирования существовало три подхода. При первом подходе считалось, что основу системы должен составлять язык с тщательно отобранным и сравнительно небольшим набором объектов и операций, допускающий возможность расширения и имеющий строго формализованные синтаксис и семантику. Языковая система, ориентированная на решение некоторого класса задач, должна представлять собой надстройку над базовым языком, образованную средствами языка. Второй подход предусматривал наличие системы языков специализированного и общего назначения. При написании сложных программ выбираются языки, на которых удобнее писать их отдельные части. В процессе трансляции программа, написанная на различных языках, собирается в единую программу на внутреннем языке машины. Третий подход заключался в создании единого языка, обладающего большим запасом конкретных средств, обеспечивающих описание всех основных операций и объектов.

Добавить или отнять месяц к дате в PL/I

Бывают случаи, когда использование возможностей DB2 для оперирования с датами либо затруднено, либо просто невозможно.

Вот тогда и приходится решать данные задачи исключительно средствами PL/I.

Один из простых примеров - имеется задача вычитания 1 месяца из даты в формате DD-MM-YYYY.

Давайте напишем процедуру, которая будет выполнять данную операцию:

SUB_MONTH: PROC(DAT_IN) RETURNS (CHAR(10));
 DCL DAT_IN     CHAR (10) ;
 DCL 1 IN_S     BASED (ADDR (DAT_IN) ),
       3 DD     CHAR (02),
       3 S1     CHAR (01),
       3 MM     CHAR (02),
       3 S2     CHAR (01),
       3 CC     CHAR (02),
       3 YY     CHAR (02);
 
 IF IN_S.MM = '01' THEN
 DO;
     IN_S.MM = '12';
     IN_S.YY = IN_S.YY - 1;
 END;
 ELSE
 DO;
   IN_S.MM = IN_S.MM - 1;
 END;
 RETURN (DAT_IN);
END;

TRIM без Enterprise PL/I

Как известно, Enterprise PL/I содержит ббольшое количество весьма полезных втроенных функций. Однако, не всегда имеется возможность использовать именно этот компилятор. А необходимость получить такую же функционльность имеется.

Вот так и с BUILTIN функцией TRIM - она весьма полезна для решения большого количества задач.

Давайте напишем небольшую процедуру, которая сможет собой заменить встроенный TRIM из комплекта Enterprise PL/I.

Сложность написания данной функции крайне низка, но готовый код так или иначе сможет уменьшить суммарное время на разработку программы.

/*********************************************************************/
/* TRIM LEADING AND TRAILING BLANKS                                  */
/*********************************************************************/
TRIM: PROC(INSTR) RETURNS(CHAR(35));
  DCL INSTR          CHAR(35);
  DCL (M,START_IND)  BIN FIXED(31);
  START_IND = 0;
  DO M = 1 TO 35 WHILE(START_IND = 0);

Отсылка электронной почты средствами PL/I

Для случая, когда отсылка почты из задания - это не совсем подходящий вариант реализации задачи, можно использовать средства PL/I для отсылки корреспонденции.

В нашем распоряжении имеется JES SPOOL API, и именно ее мы и будем использовать.

Для работы необходимо объявить следующие структуры:

DCL
1       CHNG_OPTIONS,
  3     LL        FIXED BIN (31),
  3     ZZ        FIXED BIN (15)
                  INIT      (0),
  3     TEXT1     CHAR      (14)
                  INIT      ('IAFP=N0M,PRTO='),
  3     CHNG_CMD  CHAR      (34) VARYING,
        LEN       FIXED BIN (15) BASED (ADDR(CHNG_CMD));
CHNG_OPTIONS.LL = CSTG(CHNG_OPTIONS)-2;
 
DCL
1       CHNG_FEEDBACK,
  3     LEN       FIXED BIN (31)
                  INIT      (104),
  3     ZZ        FIXED BIN (15)
                  INIT      (0),
  3     TEXT      CHAR      (100)
                  INIT      ('');
 
DCL
1       PROFS_DATA,

Отсылка IMS триггеров из PL/I

Сегодня я предлагаю поговорить о ситуациях, когда требуется отправить IMS сообщение MPP процессу из программы, написанной на PL/I.

Работа с IMS очередями (и, в принципе, с IMS) осуществляется при помощи внешней процедуры PLITDLI:

DCL PLITDLI         EXTERNAL ENTRY;

Для отсылки сообщения нам потребуется выполнить три команды:
1. Установка альтернативного PCB на требуемую IMS очередь.
2. Запись сообщения в IMS очередь.
3. Отсылка сигнала о том, что сообщение готово к отсылке (так называемый purge).

Процедура PLITDLI вызывается с переменным числом параметров. В качестве первого параметра Вам необходимо передать количество остальных параметров.

Для передачи этого количество слудет использовать статичные целочисленные переменные длиной 4 байта:

DCL TWO             FIXED BIN(31) STATIC INIT(2);
DCL THREE           FIXED BIN(31) STATIC INIT(3);
DCL FOUR            FIXED BIN(31) STATIC INIT(4);

Отсылка файла в MQ очередь при помощи PL/I

Давайте создадим небольшую программу, в котором отправим содержимое текстового файла в MQ очередь.

Текст программы (немного откомментировал, если будут вопросы - пишите в комментариях):

/*********************************************************************/
/* MYMQSND: LOAD MQ QUEUE FROM FILE                                  */
/*********************************************************************/
MYMQSND: PROC OPTIONS(MAIN) REORDER;
/*********************************************************************/
/* BUILTIN функции                                                   */
/*********************************************************************/
DCL TRIM             BUILTIN;
DCL LENGTH           BUILTIN;
DCL ADDR             BUILTIN;
DCL ONCHAR           BUILTIN;
DCL ONCODE           BUILTIN;
DCL ONLOC            BUILTIN;
DCL ONSOURCE         BUILTIN;
/*********************************************************************/