【テクニカル・上級編】ON ENDFILEユニットによるファイル終了制御 – PL/Iの基本構文とデータ制御実践ガイド

汎用機の「終わり方」を極める:ON ENDFILEの深淵と次世代移行への教訓

メインフレームのバッチ処理において、ファイル終端(EOF)の検知は、いわば「プログラムの死に様」を定義する重要な儀式だ。PL/Iの`ON ENDFILE`ユニットは、単なるファイル読み込みの停止条件ではない。それは、OSやアクセス方式(QSAM/VSAM)の深層と対話するための、非同期的な例外処理の門番である。

今回は、基幹システムの保守・刷新を担うテックリード層に向けて、`ON ENDFILE`の挙動と、それがモダンな言語へのマイグレーション時にどのような「地雷」と化すのか、アーキテクトの視点で紐解いていく。

1. ON ENDFILEの制御フローと「見えないスタック」

PL/Iの`ON ENDFILE`は、`SIGNAL`や`REVERT`と組み合わせることで強力な制御フローを構築できる。しかし、この仕組みはプログラムの静的な構造以上に、動的な「ブロックの有効範囲(Scope)」に強く依存する。

/ ファイル終了処理の基本パターン /
MAIN_PROC: PROC OPTIONS(MAIN);

ON ENDFILE(SYSIN) BEGIN;
PUT SKIP LIST(‘入力終了を検知しました’);
EOF_FLAG = ‘1’B;
/ ここでGOTOを発行してループを抜けるのが汎用機流の定石 /
GOTO EXIT_LABEL;
END;

DO WHILE (EOF_FLAG = ‘0’B);
READ FILE(SYSIN) INTO(IN_REC);
/ 処理ロジック /
END;

EXIT_LABEL:
CLOSE FILE(SYSIN);
RETURN;
END MAIN_PROC;

ここで重要なのは、`ON`ユニットが確立された時点の環境(自動変数のアドレス解決等)を保持している点だ。マイグレーションの際、Javaの`try-catch-finally`に単純変換しようとして、この「動的な範囲指定」の概念を見落とすと、ファイルクローズ漏れやメモリリークという名の「亡霊」がシステムに憑りつくことになる。

2. 移行現場で遭遇する「パックデシマル」と「内部表現」の罠

`READ`文で構造体にデータを流し込む際、PL/Iでは`DECIMAL FIXED`(パックデシマル)の内部符号がしばしば問題を引き起こす。IBM汎用機では、正数は`C`、負数は`D`(符号なしの場合は`F`)で表現される。

もしレガシーなデータセットに不正な符号(例えば`E`など)が紛れ込んでいた場合、`ON ENDFILE`に到達する前に、`CONVERSION`例外が発生してアベンド(S0C7等)することがある。

アーキテクトの知見:
JavaやC#へ移行する際、こうした内部符号の「甘い処理」をそのまま放置してはならない。EBCDICからUnicodeへの変換時、あるいはパックデシマルをバイナリ変換する際、`ON CONVERSION`ユニットで行っていたような厳格なバリデーションを、移行先のデシマル演算クラスに明示的に実装しなければ、本番稼働後のデータ破壊という最悪のシナリオを招く。

3. ポインタと動的メモリ操作の闇

`ON ENDFILE`の中で、`BASED`変数とポインタ(`PTR`)を駆使した動的メモリ解放を行うケースがある。特に、`ALLOCATE`した領域を解放し忘れたまま`GOTO`でループを抜けるコードは、長年の改修で継ぎ足されたシステムによく見られる。

/ ポインタを用いた動的領域の管理例 /
DCL P_REC PTR;
DCL REC_AREA CHAR(80) BASED(P_REC);

/ 終了時のメモリ解放漏れを防ぐ /
ON ENDFILE(SYSIN) BEGIN;
IF P_REC ^= NULL() THEN FREE REC_AREA;
EOF_FLAG = ‘1’B;
END;

マイグレーション先のマネージド言語(Java/C#)では、ガベージコレクションがあるから安心だと思ったら大間違いだ。PL/Iのポインタは「メモリの直接操作」を意味する。移行対象のコードが、どのようなポインタ演算を行っているのか、コンパイラの最適化オプション(`OPT(2)`や`OPT(3)`)で変数の生存期間がどう管理されているかを解析せねばならない。

4. ダンプ解析とCICSエッジケースへの備え

CICS環境下での`ON ENDFILE`は、通常のバッチとは異なり、タスクの異常終了と直接結びつく。特に、`EXEC CICS READ`を併用する場合、PL/Iの標準入出力とCICSの制御フローが競合し、意図しない`SIGNAL`が発生することがある。

アベンドダンプを解析する際、まずは「ONユニットのスタック深さ」を確認してほしい。ダンプ上のプログラム制御ブロックを確認し、`ON`ユニットがどのブロックで有効化され、どこで`REVERT`されたのかを辿る。ここが読めれば、レガシー移行の半分は成功したも同然だ。

結びに代えて:言語が変わっても「設計思想」は変わらない

PL/Iという言語は、非常に広大で、かつ危険な自由度を持っている。`ON ENDFILE`を単なるファイル終了制御と捉えず、「プログラムのライフサイクル管理の要」と捉えること。それが、枯れたコードを堅牢な次世代システムへ昇華させる唯一の道である。

読者の皆さんが直面している複雑なマイグレーション課題も、この「PL/Iの内部挙動を紐解く」という一歩から必ず解決の糸口が見えてくるはずだ。健闘を祈る。

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