【現場の流儀】PL/IのON ENDFILEでハマらないための「終了制御」の鉄則
メインフレームの現場で長く戦っていると、若手から「なぜかファイル読み込みループが終わらない」「EOF検知が正しく動作しない」という相談をよく受ける。
PL/Iの`ON ENDFILE`ユニットは、C言語の`feof()`やJavaの`hasNext()`に慣れた世代には、いささか独特な「非同期的な割り込み」のように映るかもしれない。しかし、この仕組みこそがPL/Iの強力な制御構造であり、正しく扱えばバッチ処理の堅牢性は格段に上がる。
今日は、順次ファイル(QSAM)やVSAMを読み込む際の、「フラグ制御によるループ脱出」の定石を伝授しよう。
—
1. なぜ「ONユニット」を使うのか
PL/Iの歴史を振り返れば、`ON ENDFILE`は単なるエラーハンドリングではなく、システムがファイル終了を検知した瞬間に、メインロジックとは別の「例外処理」として呼び出される仕組みだ。
ここでやってはいけないのが、`ON`ユニット内でいきなり`GO TO`でメインループの外へ飛び出すことだ。プログラムの構造を破壊し、保守性を損なう悪手である。現場の標準として推奨するのは、「フラグ変数によるステータス管理」だ。
2. 実践的なコーディング・パターン
以下に、VSAM(またはQSAM)を読み込み、フラグを用いてループを綺麗に終了させる標準的なテンプレートを示す。
/i
SAMPLE_BATCH: PACKAGE;
/
- メインプロシージャ:OPTIONS(MAIN)はプログラムのエントリポイント
- 必要なファイル定義やデータ属性はここに集約する
/
MAIN_PROC: PROCEDURE OPTIONS(MAIN);
DCL INFILE FILE RECORD INPUT; / 入力ファイル /
DCL EOF_FLG BIT(1) INIT(‘0’B); / 終了検知フラグ:’1’Bで終了 /
/ ファイル終了時のONユニット定義 /
ON ENDFILE(INFILE) BEGIN;
EOF_FLG = ‘1’B;
END;
OPEN FILE(INFILE);
/ 読み込みループ /
DO WHILE(^EOF_FLG);
READ FILE(INFILE) INTO(RECORD_AREA);
/ フラグが立っていないか再確認(ガード節) /
IF EOF_FLG THEN LEAVE;
/ ここに実務ロジックを記述 /
CALL PROCESS_LOGIC(RECORD_AREA);
END;
CLOSE FILE(INFILE);
END MAIN_PROC;
/ 処理用サブプロシージャの例 /
PROCESS_LOGIC: PROCEDURE(REC);
DCL REC CHAR(80);
/ 業務処理をここに記述 /
END PROCESS_LOGIC;
END SAMPLE_BATCH;
3. このコードにおける「こだわり」と現場のコツ
① `BEGIN` … `END` ブロックの徹底
`ON ENDFILE(INFILE) EOF_FLG = ‘1’B;` と一行で書くことも可能だが、実務では将来的な拡張(例えばログ出力やカウンターのリセットなど)を見越して、必ず`BEGIN`ブロックを使う習慣をつけよう。
② `DO WHILE(^EOF_FLG)` のガード
`READ`文の直後に `IF EOF_FLG THEN LEAVE;` を入れている点に注目してほしい。これは非常に重要だ。なぜなら、`READ`文が実行された瞬間にEOFに到達した場合、直ちに`ON`ユニットが起動するが、その後の処理で誤ったデータを加工しないよう、即座にループを抜ける「防御」が必要だからだ。
③ `PACKAGE`の活用
昔のPL/Iプログラムは、一つのソースにすべてを詰め込みがちだった。しかし、現代的なメインフレーム開発では、`PACKAGE`を用いてスコープを明確に区切ることが、コンパイル単位の整理にもなり、デバッグ時のメモリ監視も容易になる。
4. トラブルシューティング:ハマりやすいポイント
- ONユニットの定義位置: `OPEN`文よりも前に`ON`ユニットを配置することを忘れないこと。`OPEN`の後に配置すると、最悪の場合、読み込み開始直後のEOFを検知できず、無限ループや異常終了(ABEND)を招く。
- フラグの初期化: 同じタスク内で複数のファイルを順次読み込む場合、フラグの初期化忘れは致命的だ。`DO`ループに入る直前に必ず初期化されているか、常に意識すること。
- VSAMの場合: VSAMのキー順読み込みなどで`READ`の代わりに`READ SET`を使用する場合、ポインタの扱いに注意が必要だが、基本構造(EOF検知→フラグ変更→ループ脱出)は変わらない。
—
最後に:シニアエンジニアからの助言
PL/Iは古い言語と言われることもあるが、その言語仕様には「データに対する誠実さ」が詰まっている。`ON ENDFILE`を使いこなすということは、プログラムの「正常系」と「異常系(終了処理)」を明確に切り分けるという、システム開発の基本原則を体現することに他ならない。
後輩諸君、単に動くコードを書くだけではなく、「誰が読んでも読み込み終了のタイミングが論理的に追えるコード」を目指してほしい。それが大規模バッチの保守における、君たちの最大の武器になるはずだ。
また何か不明点があればいつでも聞いてくれ。設計の現場で待っている。
