【入門編】ON条件におけるENDFILEの制御構造とファイルクローズ – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!IBMメインフレームの世界へようこそ。システムアーキテクトの私です。

JavaやCOBOLといったモダン、あるいは従来型のビジネス言語をバリバリ書いてきた方にとって、初めて見るPL/I(ピーエルアイ)のソースコードは、ちょっとした「異世界」に見えるかもしれません。何せ、あの独特なデータ宣言や、文末のセミコロン(`;`)、そして何より「予約語がない(あるいはコンテキストによっていくらでも変化する)」という自由度の高さに、最初は戸惑うことでしょう。

「変数名に `IF` や `READ` って使っても怒られないの?」
「ファイルの終わりを検知する `ENDFILE` って、COBOLの `AT END` と何が違うの?」

そんな疑問や不安を抱えているあなたへ。大丈夫、怖がる必要は全くありません。今回は、PL/Iにおける順次ファイルの読み込み終了(ENDFILE条件)の捉え方と、ファイルポインタの整合性をピシッと保ったまま美しくクローズするための極意を、現場のリアルな知見を交えて優しく紐解いていきますね。

1. 他言語とはココが違う!PL/Iの「ENDFILE」と予約語の懐の深さ

Javaなら `while ((line = reader.readLine()) != null)`、COBOLなら `READ FILE AT END …` と書くところを、PL/Iでは ON単位(ON-unit) という独特の割り込み処理メカニズムを使ってファイルの終端(EOF)を捕捉します。

ここで最初に驚かれるのが、PL/Iには「厳格な意味での予約語がほとんどない」という仕様です。
例えば、JavaやC言語では `READ` や `FILE` はキーワードとしてガチガチに予約されていますよね。しかしPL/Iの世界では、コンパイラが前後の文脈(コンテキスト)から「おっ、ここはファイル名だな」「ここは命令だな」と空気を読んで判断してくれます。そのため、極端な話、変数名に `READ` や `WRITE` と名付けてもコンパイルエラーにはなりません(※後々のメンテナンスで自分が泣くことになるので、絶対にやめましょうね!)。

この「柔軟だけど、一歩間違えるとカオスになる」懐の深い言語仕様が、PL/Iをベテランにはたまらなく、初心者には少しだけミステリアスに感じさせる要因なんです。

2. 【実録】ENDFILE制御のアンチパターンと正しい作法

順次ファイル(Sequential File)を読み込む際、よくある初学者のミスが「ファイルの終わり(EOF)に達した後のファイルクローズ処理のし忘れ」や「ポインタの置き去り」です。

メインフレームのバッチ処理において、ファイルのクローズ漏れや異常終了時の放置は、JCL(Job Control Language)側のデータセット制御ブロック(DCB)やカタログに悪影響を及ぼし、最悪の場合、夜間バッチ全体を止める大惨事になりかねません。

では、一体どう書くのが「プロの作法」なのか。実際のPL/Iコードを見てみましょう。

実用PL/Iサンプルコード:安全なファイルの読み込みとクローズ

1
/ ======================================================= /
/ 順次ファイルの安全な読み込みと終了処理サンプル /
/ ======================================================= /
SAFE_READ_PGM: PROC OPTIONS(MAIN);

/ 1. ファイル(データセット)の宣言 /
/ INPUT文で読み込み専用、STREAMで文字ベースを指定 /
DCL IN_FILE FILE INPUT STREAM RECORD;

/ 2. ワークエリア(レコード受信用変数)の宣言 /
Dcl 01 WK_REC,
05 WK_KEY CHAR(5),
05 WK_DATA CHAR(80);

/ 3. 読み込み終了フラグの定義 /
DCLEOF_FLG CHAR(1) INIT(‘0’);

/ 4. ファイルのオープン(JCLのDD名と連動します) /
OPEN FILE(IN_FILE);

/ 5. ENDFILE条件の捕捉(ONユニットの定義) /
/ ファイルの終端に達した瞬間に、このブロックが発動します /
ON ENDFILE(IN_FILE) BEGIN;
EOF_FLG = ‘1’;
PUT SKIP LIST(‘ ファイルの終端(EOF)を検知しました ‘);
END;

/ 6. メインの読み込みループ /
DO WHILE (EOF_FLG = ‘0’);

/ レコードの読み込み(READ… INTO…形式) /
READ FILE(IN_FILE) INTO(WK_REC);

/ ファイル終了フラグが立っていなければ処理を続行 /
IF EOF_FLG = ‘0’ THEN DO;
/ ここに実際のビジネスロジック(編集や集計など)を記述 /
PUT SKIP EDIT (WK_KEY, ‘ : ‘, WK_DATA) (A, A, A);
END;

END;

/ 7. 整合性を保ったファイルのクローズ /
/ 忘れずにファイルを閉じてOSへリソースを返却します /
CLOSE FILE(IN_FILE);

PUT SKIP LIST(‘ バッチ処理が正常終了しました ‘);

END SAFE_READ_PGM;

3. コードのポイントと、メインフレームアーキテクトからのアドバイス

上記のコードには、レガシーシステムで生き抜くための大切なエッセンスが詰まっています。いくつか重要なポイントを解説しますね。

① ON ENDFILE は「割り込み」である

PL/Iの `ON ENDFILE(IN_FILE)` は、C言語の `feof()` のように「読み込んだ後に判定する」のではなく、「OSからEOFが返ってきたその瞬間に割り込んで飛んでくるイベントハンドラ」に近い挙動をします。
そのため、フラグ変数(上記の例では `EOF_FLG`)をきっちり立てて、メインの `DO WHILE` ループを安全に抜け出す設計にすることが鉄則です。

② ファイルポインタの整合性と CLOSE の美学

「ループを抜けたらおしまい」ではありません。OS側(z/OSなど)の資源管理の観点から、開いたファイルは必ず `CLOSE` 文で閉じる必要があります。
PL/Iでは、プログラムが正常終了する際に暗黙的にオープン中のファイルをクローズしてくれる親切設計もありますが、大規模なバッチプログラムやサブプロシージャを挟む構造では、「開いたら閉じる(Open and Close)」のペアを明示的にコーディングするのが、後々の保守メンバに対する最大の優しさであり、バグを防ぐ防壁となります。

おわりに

いかがでしたでしょうか?
「PL/I」「ENDFILE」「ON条件」といった聞き慣れない用語も、一つひとつ紐解いていけば、Javaの例外処理(Try-Catch)やイベント駆動の考え方と根っこは同じであることが見えてきたかと思います。

レガシーシステムのモダナイゼーションや保守において、PL/Iの古いコードに直面したとき、怖がる必要は全くありません。言語の仕様をリスペクトし、先輩たちが残してくれた作法を丁寧に読み解いていけば、必ずあなたを温かく迎え入れてくれますよ。

それでは、次回のメインフレーム・アーキテクチャ解説もお楽しみに!

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