PL/Iの深淵へ:外部呼出しの作法と「予約語なき世界」の落とし穴
メインフレームの現場で何十年と稼働し続けるPL/I。C言語のような厳格な予約語がなく、どんな単語でも変数名にできてしまうこの自由さが、時に後世のエンジニアを震え上がらせるバグの温床となる。
今日は、大規模マイグレーションや保守の現場で必ず直面する「外部プロシージャ呼出し」の作法と、その裏で暗躍するリンケージエディタの役割について、実務的な視点で深く掘り下げていこう。
—
1. 予約語なき言語の教訓:なぜ識別子に悩まされるのか
PL/Iには「予約語」が存在しない。これは仕様書上の美徳だが、実務上は「呪い」になり得る。
例えば、`IF`や`THEN`、`GOTO`といったキーワードを、うっかり変数名として宣言できてしまう。コンパイラは文脈から「これはキーワードか、識別子か」を判別するが、可読性は最悪になる。
鉄則:
「予約語がないから自由」なのではなく、「チーム内で予約語を定義し、それを絶対に使用しないルール」こそが、生き残るコードの条件だ。保守開発で新しい変数を追加する際は、既存のソースに混ざっている命名規則を読み取り、決して「PL/Iのキーワード」を汚染しないように気を配れ。
—
2. 外部呼出しの核心:BYADDRとBYVALUEの攻防
PL/Iで外部ルーチン(別のコンパイル単位)を呼び出す際、最も注意すべきは引数の渡し方だ。特にC言語やCOBOLと混在する環境では、この規約の不一致が「謎のメモリアクセス例外(S0C4)」を招く。
- BYADDR(デフォルト): 引数の「アドレス」を渡す。PL/Iの標準だ。
- BYVALUE: 値そのものを渡す。C言語など他言語とのインターフェースで必須となる。
以下のサンプルを見てほしい。これは典型的な外部プロシージャ呼出しの構成だ。
1
/ 外部ルーチン呼出しの例 /
EXTERNAL_CALL_SAMPLE: PROC OPTIONS(MAIN);
/ 外部ルーチン定義:BYVALUEで値を渡し、戻り値を受け取る /
DCL CALC_ROUTINE ENTRY(FIXED BIN(31) VALUE,
FIXED BIN(31) BYADDR)
RETURNS(FIXED BIN(31));
DCL (VAL1, VAL2, RESULT) FIXED BIN(31);
VAL1 = 100;
VAL2 = 200;
/ 呼出し:VAL1は値渡し、VAL2は参照渡し(デフォルト) /
RESULT = CALC_ROUTINE(VAL1, VAL2);
PUT SKIP LIST(‘RESULT IS: ‘ || RESULT);
END EXTERNAL_CALL_SAMPLE;
リンケージエディタが果たす「最後の一線」
コンパイラがオブジェクトコードを吐き出した後、リンケージエディタ(バインダ)が果たす役割は極めて大きい。`ENTRY`属性で宣言されたプロシージャは、バインド時に名前が解決される。もし、引数の型や渡し方が食い違っていても、リンケージエディタは「名前さえ合致すれば」結合してしまう。
ここが運命の分かれ道だ。型不一致はコンパイル時ではなく、実行時の不定なメモリ破壊として顕在化する。 デバッグでソースを追っても原因が掴めない場合、まずは呼び出し元の`ENTRY`定義と、呼び出し先の引数リストが「型・桁数・渡し方」のすべてで完全に一致しているか、リストファイルを突き合わせるのが鉄則だ。
—
3. 実践:VSAM操作とONユニットによる異常系制御
現場で避けて通れないのがVSAMファイルアクセスと、例外発生時の制御フローだ。`ON`ユニットはPL/Iの強力な機能だが、多用しすぎるとスパゲッティコードの元になる。
1
/ VSAMファイルのレコード入出力とエラーハンドリング /
DCL VSAM_FILE FILE RECORD INPUT ENV(VSAM);
/ エラー発生時のONユニット定義 /
ON ENDFILE(VSAM_FILE) BEGIN;
PUT SKIP LIST(‘ファイル終了を検知しました。処理を終了します。’);
CLOSE FILE(VSAM_FILE);
STOP;
END;
ON UNDEFINEDFILE(VSAM_FILE) BEGIN;
PUT SKIP LIST(‘ファイルオープン失敗。JCLを確認せよ。’);
SIGNAL ERROR; / 意図的に例外を再送出 /
END;
OPEN FILE(VSAM_FILE);
/ READ文に組み込むBUILTIN関数 /
READ FILE(VSAM_FILE) INTO(DATA_AREA);
/ 正常系処理は続く /
ベテランからのアドバイス
`ON`ユニットは、そのブロックが終了した後に「発生元へ戻る」という性質がある。これは非常に強力だが、制御フローが直感的に追えなくなるリスクと隣り合わせだ。
大規模な改修を行う際は、「ONユニットは例外のログ出力と終了処理の定型化にのみ使い、ビジネスロジックの分岐には決して使わない」という規約を設けるべきだ。
—
最後に:継承されるべき技術的矜持
メインフレームのコードは、書かれた当時のエンジニアの考え方がそのまま化石のように残っている。しかし、コンパイラが進化しても、データ構造の渡し方やメモリ管理の基本は変わらない。
「なぜこの引数はBYVALUEなのか?」「なぜここではENTRY宣言を分けているのか?」という疑問を、単なる仕様の確認で終わらせず、その背後にある「なぜそうしなければならなかったのか(他言語との連携や過去のメモリ制限)」という文脈まで想像できるようになれば、君も一人前のメインフレームアーキテクトだ。
現場のコードは、君たちが守るべき資産だ。慎重に、しかし大胆に、黒い画面の向こう側を読み解いていってほしい。
