Многие из вас слышали об одном из старейших языков программирования COBOL, а также о том, что как сильно сейчас нужны COBOL-программисты для поддержки старого кода. Существует еще один «старожил», о котором знают немногие, который используется сейчас и будет использоваться еще достаточно долгое время для написания программ в различных сферах человеческой деятельности (финансовой, банковской и др.). Имя этому языку — IBM RPG.
Once upon a time...
RPG — проприетарный язык программирования высокого уровня, являющийся собственностью корпорации IBM, для создания бизнес-приложений. Последние версии языка доступны только для операционной системы IBM i (и ее прошлых версий под старым названием OS/400).
У RPG более чем полувековая история. К концу 50-х IBM выпустила огромное количество электромеханических машин, называемых табуляторами. Последним серийным табулятором стала модель IBM 407 Accounting Machine:
Рисунок 1. IBM 407 в Арсенале армии США в 1961 году.
К слову, аренда такого табулятора в зависимости от модели стоила от $800 до $920 в месяц (в перерасчете на современный доллар — от $8100 до $9300), а прекращена их продажа была 17 декабря 1976 года.
Как известно, технический прогресс не стоял на месте, и к концу 50-ых годов стали появляться транзисторные компьютеры. Первым таким компьютером для IBM стал IBM 1401, вышедший в 1959 году:
Рисунок 2. IBM 1401 в Центре истории и наследия Эндикотта.
В Музее компьютерной истории находится вполне рабочий экземпляр, я думаю, вам будет интересно посмотреть, как все это работало (особенно «доставляют» слова "We need a little bit of cooling" на 4:41):
Для упрощения перехода своих клиентов на новые транзисторные компьютеры в 1959 году также были придуманы сразу два инструмента, имитирующие процесс обработки перфокарт на компьютере — FARGO (Fourteen-o-one Automatic Report Generation Operation) и RPG (Report Program Generator). Синтаксис обоих языков был схож с командным языком электромеханических табуляторов. Кроме этого, FARGO и RPG повторяли важную особенность табуляторов: они эмулировали их циклический режим работы (программный цикл), во время которого табуляторы считывали данные с перфокарт, суммировали их и печатали результаты. IBM и на сегодняшний момент обеспечивает обратную совместимость с программным циклом даже в последнем диалекте RPG IV.
Хоть RPG и создавался под влиянием FARGO, уже через несколько лет RPG вытеснил своего предшественника как более перспективный вариант. А следующей системой, куда «подвезли» RPG, был мейнфрейм IBM System/360 Model 20:
Рисунок 3. IBM System/360 Model 20 в Немецком музее.
А уже через пару лет (конец 60-ых) IBM предоставляет следующий диалект языка — RPG II — для среднего компьютера System/3:
Рисунок 4. Средний компьютер IBM System/3 Model 10 с оператором.
С тех пор RPG развился в высокоуровневый аналог языков COBOL и PL/I. Отличительной особенностью языка (по сравнению с современными) являлся «фиксированный формат» синтаксиса, затруднявшим чтение программ без специального отладочного шаблона.
Рисунок 5. Отладочный шаблон.
Программы начинались со спецификаций файлов (File Specifications) — списка всех файлов, подлежащих чтению, записи или обновлению. За ними шли спецификации определений данных (Data Definition Specifications) — список элементов программы, таких как структуры данных или массивы. Этот блок напоминает секцию рабочей памяти (Working-Storage) в языке COBOL или команды с ключевым словом «var» в Паскале. Для указания типа переменной в колонку 40 спецификации определений записывается соответствующий символ (см. таблицу ниже). Если он опущен, т.е. вместо него стоит пробел, то типом по умолчанию будет A при условии, что не заданы десятичные разряды. В противном случае типом по умолчанию будет P.
Тип данных | Название | Длина | Описание |
* | Указатель на базированную переменную
Указатель на процедуру Системный указатель |
16 байт | Обращение к данным
Обращение к активированной процедуре Обращение к объектному файлу |
A | Буквенно-цифровой символ | От 1 до 16 773 104 байт (фиксированная длина)
От 1 до 16 773 100 байт (переменная длина) |
Буква или цифра |
B | Двоичное число | 1 байт (8-бит)
2 байт (16-бит) 4 байт (32-бит) 8 байт (64-бит) |
Двоичное целое число со знаком |
C | Символ в кодировке UCS-2 | От 1 до 8 386 552 символов (фиксированная длина)
От 1 до 8 386 550 символов (переменная длина) |
16-битный символ в кодировке UCS-2 (набор символов DBCS или EGCS) |
D | Дата | 10 байт | Дата: год, месяц, день |
F | Число с плавающей точкой | 4 байт (32-бит)
8 байт (64-бит) |
Двоичное вещественное число с плавающей точкой, со знаком |
G | Графический символ | От 1 до 8 386 552 символов (фиксированная длина)
от 1 до 8 386 550 символов (переменная длина) |
16-битный графический символ (набор символов DBCS или EGCS) |
I | Целое число | 1 байт (8-бит)
2 байт (16-бит) 4 байт (32-бит) 8 байт (64-бит) |
Двоичное целое число со знаком |
N | Индикатор символа | 1 байт | '1' = TRUE
'0' = FALSE |
O | Объектный файл | Размер неизвестен | Ссылка на объектный файл |
P | Упакованное десятичное число | От 1 до 63 цифр,
по 2 цифры на байт плюс знак |
Десятичное число с фиксированной точкой, со знаком, с целой и дробной частями |
S | Распакованное десятичное число | От 1 до 63 цифр,
по 1 цифре на байт |
Десятичное число с фиксированной точкой, со знаком, с целой и дробной частями |
T | Время | 8 байт | Время: час, минута, секунда |
U | Целое число | 1 байт (8-бит)
2 байт (16-бит) 4 байт (32-бит) 8 байт (64-бит) |
Целое число без знака |
Z | Метка времени | 26 байт | Дата и время: год, месяц, день, час, минута, секунда, микросекунды |
Далее указывались спецификации вычислений (Calculation Specifications) — список команд для исполнения. Также могли добавляться спецификации вывода (Output Specifications), определяющие вид выходных файлов или отчетов.
Приведу также дополнительную информацию о всех типах спецификаций:
- U — спецификация автоотчета (Auto Report), требуется только для программ с автогенерируемым отчетом.
- H — спецификация заголовков (Header), служит началом программы и описывает такие опции компилятора, как максимальный размер объектного кода, листинг компиляции, а также флаг поддержки доступа с нескольких терминалов (Multiple Requestor Terminal, MRT). Имя объектной программы записывается в колонки 75-80; если спецификация заголовков отсутствует, используется имя по умолчанию RPGOBJ.
- F — спецификации файлов (File). Здесь описываются файлы, используемые в программе. Это могут быть как файлы на диске (DISK), так и устройства, такие как принтер (PRINTER), рабочая станция (WORKSTN), клавиатура (KEYBORD), неформатируемый дисплей (CRT или DISPLAY) либо пользовательское устройство (SPECIAL). Здесь же описывается размер записей и блоков, индикаторы переполнения и внешние индикаторы. Спецификации F могут отсутствовать.
- E — спецификации расширений (Extension), описывают массивы и таблицы, предварительно извлекаемые из файлов на диске (таблицы ввода) или констант в конце исходного кода между символами ** и /* либо собираемые по итогам вычислений.
- L — спецификации счетчика строк (Line Counter). Если присутствуют, то описывают формат вывода на печать: количество строк на странице и границы начала и конца печати.
- I — спецификации ввода (Input): описывают области данных внутри файлов. RPG II разрешает переопределять области данных, так что поле FLDA может занимать ту же область, что и массив AR, содержащий 8 односимвольных элементов. Здесь же могут описываться области, не являющиеся записями, например, структуры данных. Индикаторы могут использоваться в условиях, зависящих от значений входящей записи.
- C — спецификации вычислений (Calculation). Здесь описываются и наращиваются поля для итоговых результатов. Над ними можно проводить сложные вычисления и операции со строками. Индикаторы могут использоваться в условиях.
- O — спецификации вывода (Output), которые описывают поля и границы выходящей записи.
А теперь небольшой пример для разминки ваших глаз (опущены спецификации файлов и определений данных):
* Звездочка (*) в колонке 7 определяет строку-комментарий
* В колонке 6 пишется спецификация одним символом. Определяет,
* что будет происходить в строке (например, раздел объявлений,
* раздел вычислений, ...).
* Спецификация "C" (calculation) - вычисление
C HOURS IFLE 40
C HOURS MULT RATE PAY
C ELSE
C RATE MULT 40 PAY 72
C HOURS SUB 40 OTIME 30
C RATE MULT 1.5 OTRATE 94
C OTRATE MULT OTIME OTPAY 72
C ADD OTPAY PAY
C END
Код сложен для восприятия, не правда ли? А здесь всего лишь производится расчет налога на заработную плату для сотрудника с почасовой оплатой труда (работники, переработавшие 40 часов, получают полуторную ставку).
В 1978 году IBM представляет одновременно средний компьютер System/38 и новый диалект языка — RPG III — для него:
Рисунок 6. Средний компьютер IBM System/38
С этого момента ограничения языка несколько ослабляются и разрешается писать спецификации вычислений в «свободном формате»:
/free
If Hours <= 40;
Pay = Hours * Rate;
Else;
Pay = (40 * Rate) + ((Hours - 40) * (Rate * 1.5));
EndIf;
/end-free
И, наконец, последняя версия диалекта — RPG IV (иначе RPGLE, ILE RPG) — вышла в 1994 году. Тремя основными «фичами» можно назвать встроенные функции, процедуры и «свободный формат» программирования. До ноября 2013 года свободный формат был доступен только для спецификаций вычислений. В обновлении V7R1 TR7 команды "/free" и "/end-free" были упразднены, а язык наконец-то освободился от наследия эпохи перфокарт.
Предлагаю также ознакомиться с данной брошюрой, в которой IBM показывает, как сильно изменился диалект языка. Сам же язык широко используется сейчас под ОС IBM i на аппаратной платформе IBM Power i:
Рисунок 7. Линейка серверов IBM Power i
В общей сложности, язык RPG успел побывать на таких компьютерах, как 1401, System/360, System/3, System/32, System/34, System/36, System/38, AS/400 и System i. Имелись и реализации для платформ Digital VAX, Sperry Univac BC/7, Univac system 80, Siemens BS2000, Burroughs B700, B1700, Hewlett Packard HP3000, серии ICL 2900, Honeywell 6220 и 2020, серий Four-Phase IV/70 и IV/90, Singer System 10 и WANG VS, а также разнообразные компиляторы и среды исполнения для Unix-систем, например, Infinite36 (бывшая Unibol 36), и PC (Baby/400, Lattice-RPG).
К настоящему времени язык RPG развился в сильный, жизнеспособный язык. Программы можно по-прежнему писать в обычном редакторе в черно-зеленой гамме (green-screen):
Рисунок 8. Green-screen.
Однако появилось и множество других инструментов. Среди них — Visual Age для RPG, разработанные IBM и продвигаемые Джоном Пэрисом (Jon Paris) и другими. Наиболее популярным редактором на данный момент является IBM Websphere Development Studio, позднее переименованный в RDi (Rational Developer for i), являющийся пользовательской реализацией Eclipse:
Рисунок 9. Rational Developer for i.
Также компилятор RPG реализован для платформы Microsoft .NET. Помимо базовой версии в него входят дополнительные расширения языка RPG IV, что позволяет Microsoft Windows и .NET пользоваться окружением Native и System/36, а также портировать файлы DB/2 в базы данных Microsoft Access и Microsoft SQL Server через интерфейс ODBC.
Заключение
Хоть язык и представляет собой экзотику, мы понимаем, что на нем написано много кода для финансовой, банковской и других видов деятельности. Он достаточно многообразен: существует 4 диалекта, фиксированная и свободная формы синтаксиса. Необходимость в поддержке старого и написании нового кода вынуждает компании искать RPG-программистов, которые, по-видимому, уже занесены в Красную книгу. В таких условиях возникает потребность в использовании дополнительных инструментов по контролю качества кода, например, таких как статический анализатор.
Возможно, читатель уже догадался, почему мы решили написать эту статью, и к чему мы клоним. Да, мы подумываем создать статический анализатор кода для языка RPG. Думаю, такой анализатор станет отличным подспорьем тем, кто продолжает сопровождать и развивать программы на этом языке. Однако, решение ещё не принято. Думаю, вы понимаете, что это весьма специфическое направление.
Поэтому, если вы хотите, чтобы анализатор PVS-Studio научился искать ошибки в RPG программах, то напишите нам. Мы ищем Вас, уважаемых потенциальных клиентов PVS-Studio RPG. Пишите нам!
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Phillip Khandeliants. A first look at RPG: turns out it's not only Role-Playing Games
Автор: khandeliants