【入門編】ENTRY属性とOPTIONS(COBOL/ASM)による他言語連携 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダンな、あるいはビジネスの現場でなじみ深い言語を経験されてきた方にとって、IBMの汎用機(メインフレーム)やPL/Iという名前を聞くだけで、「なんだか難しそう……」「古い仕様のせいでハマりそう……」と身構えてしまうかもしれませんよね。

でも、安心してください。怖がる必要はまったくありません。
今回は、PL/Iのちょっとユニークな「他言語連携」、特にCOBOLやアセンブラを呼び出すときの作法について、私と一緒に一つずつ紐解いていきましょう。

1. なぜPL/IからCOBOLやアセンブラを呼ぶの?

基幹システムの現場では、何十年も動き続けている信頼性抜群のCOBOL製サブルーチンや、超高速で動作するアセンブラ製のユーティリティが眠っています。「新しく作るシステムやバッチの一部をPL/Iで書きたいけれど、既存の資産(モジュール)はそのまま再利用したい!」――そんな場面で必要になるのが、この他言語連携です。

Javaなどの世界であれば「インターフェースがどうとか、JNIの初期化がどうとか……」と頭を悩ませるところですが、メインフレームの世界では、リンケージエディタ(リンク編集)という仕組みを通じて、言語の壁を軽々と越えてサブルーチンを呼び出すことができます。

その主役となるのが、`ENTRY`属性`OPTIONS`オプションです。

2. 魔法の呪文:ENTRY属性とOPTIONSの正体

PL/Iから外部のプログラム(COBOLやアセンブラ)を呼び出すとき、私たちはコンパイラに対してこう教え込む必要があります。

> 「今度呼び出すあいつらは、PL/Iの作法じゃなくて、COBOLやアセンブラの作法で動くからよろしくね!」

これを指定するのが、おなじみの `OPTIONS(COBOL)` や `OPTIONS(ASM)` です。
具体的なコードを見てみましょう。

/ ========================================================== /
/ PL/Iメインプログラム:COBOLおよびアセンブラの呼び出し例 /
/ ========================================================== /
TESTCALL: PROC OPTIONS(MAIN);

/ 1. 呼び出す外部ルーチンのインターフェースを宣言します /
/ COBOLサブルーチンを呼び出すためのENTRY宣言 /
DCL COB_SUB ENTRY
EXTERNAL / 外部モジュールであることを明示 /
OPTIONS(COBOL); / 「あいつはCOBOLの作法で動くよ」という宣言 /

/ アセンブラルーチンを呼び出すためのENTRY宣言 /
DCL ASM_SUB ENTRY
EXTERNAL
OPTIONS(ASM); / 「あいつはアセンブラの作法だよ」という宣言 /

/ 2. 渡すためのデータを定義します(ストレージ属性に注意!) /
DCL WK_AMT FIXED DEC(9,2) INIT(12345.67); / 金額項目 /
DCL WK_NAME CHAR(20) INIT(‘IBM MAINFRAME’); / 名称項目 /

/ 3. いざ、COBOLサブルーチンへ! /
PUT SKIP LIST(‘— COBOLサブルーチンの呼び出し開始 —‘);
CALL COB_SUB(WK_AMT, WK_NAME);

/ 4. いざ、アセンブラルーチンへ! /
PUT SKIP LIST(‘— アセンブラサブルーチンの呼び出し開始 —‘);
CALL ASM_SUB(WK_AMT);

PUT SKIP LIST(‘すべての呼び出しが正常に終了しました。’);

END TESTCALL;

どうでしょう?見慣れないキーワードはあるものの、構造自体は「使う関数を宣言して、`CALL`で呼ぶ」というお馴染みの流れですよね。

3. ここがハマりどころ!データ型とストレージの罠

他言語連携で最もトラブルになりやすいのが、「データの受け渡し(引数)」です。
JavaやC言語の感覚でデータを渡すと、メインフレームのメモリ上で予期せぬズレが生じ、最悪の場合はシステムが異常終了(ABEND:アベンディング)してしまいます。

ここで、代表的なデータ型の翻訳ルールを抑えておきましょう。

① 数値データの翻訳(FIXED DEC と COMP-3)

PL/Iの `FIXED DECIMAL(9,2)` は、COBOLでいう `PIC S9(7)V92 PACKED-DECIMAL`(いわゆるゾーン10進数やパック10進数、COMP-3)とメモリ上で完全に一致させることができます。
メインフレームでは、この「パック形式」のデータ表現が銭単位の計算や金融データの標準です。桁数や小数点位置(スケール)が双方で一致しているかを必ず確認してください。

② 文字列の翻訳(CHAR と DISPLAY)

PL/Iの `CHAR(20)` は、COBOLの `PIC X(20)` とそのまま互換性があります。
ただし、PL/Iの文字列はデフォルトで「可変長(長さを表すプレフィックスが付く)」として扱われることがあるため、外部連携の際は必ず`NONVARYING`(または単に長さ指定のみ)で固定長文字列として渡すのが鉄則です。

4. リンケージエディタの制約:名前の長さにご用心!

もう一つ、レガシーシステム特有の「お作法」として忘れてはならないのが、外部シンボル名の文字数制限です。

現代のオープン系システムであれば、変数名や関数名が何文字あっても気になりませんが、メインフレームのリンケージエディタ(特に古い世代)や、COBOLの仕様によっては、外部名(プログラム名やENTRY名)が最大8文字までしか認識されないという制約にぶつかることがあります。

  • PL/I側で `DCL VERY_LONG_COBOL_PROGRAM_NAME ENTRY OPTIONS(COBOL);` と書いても、リンク時にうまく結びつかない……という悲劇が起きがちなのはこのためです。
  • 対策としては、外部名には極力8文字以内の分かりやすい名前を割り当てるか、リンケージエディタの制御文(ALIASやNAMEカード)で上手にマッピングしてあげる配慮が必要です。

さいごに

PL/Iからの他言語連携、いかがでしたでしょうか?
「他言語の作法をオプションで指定してあげること」「メモリ上のデータ型(特に数値と文字の持ち方)をぴったり合わせること」――この2つさえ押さえておけば、何十年も前に書かれた堅牢なCOBOLやアセンブラの資産を、今のPL/Iプログラムから自由自在に使いこなすことができます。

レガシーシステムのモダナイゼーションや改修作業は、一見すると壁が高く見えるかもしれませんが、パズルのピースを合わせるような面白さがあります。
恐れず、一歩ずつ、コードと向き合っていきましょう。あなたのメインフレームライフを、心から応援しています!

タイトルとURLをコピーしました