おい、最近入った若手が「先輩、JCLのPARMで渡したパラメータをPL/Iのメインプログラムでどうやって受け取るんですか? COBOLみたいに LINKAGE SECTION 書かないですよね?」って慌てて聞きに来たんだよ。
COBOLer上がりの連中や、最近オープン系からスライドしてきたエンジニアは、ここで必ずと言っていいほど躓く。PL/IにはCOBOLの `PROCEDURE DIVISION USING` なんて洒落た(あるいは冗長な)仕組みはない。しかも、PL/Iの最大の特徴は「予約語を持たない」という狂気的……いや、革新的な言語仕様にある。変数名に `IF` や `READ` と名付けてもコンパイラは怒らない代わり、文脈で解釈するため、一歩間違えると大ハマりする地雷原でもあるんだ。
今回は、基幹システムのバッチ処理で避けて通れない 「JCL PARMパラメータのPL/Iメインプロシージャへの引き渡し」 について、実務でそのまま使えるコードと鉄則を叩き込んでやろう。
—
1. PL/IにおけるJCL PARM受け渡しの基本メカニズム
IBM Enterprise PL/Iで書かれたメインプロシージャにJCLの `PARM=` の値を渡すのは、驚くほどシンプルだ。プロシージャの引数(パラメータ)として変数を受け取るだけでいい。
1
MYPROG: PROC(P_PARM) OPTIONS(MAIN);
これだけで、JCLのEXEC文にある `PARM=’ABCDE’` が `P_PARM` に格納される。ただし、ここにベテランなら誰もが知る「最大の罠」が潜んでいる。
⚠️ 注意すべき最大長制限(100バイトの呪縛)
何も考えずに `P_PARM` を単なる `CHAR(100)` などの固定長で定義したり、型を省略したりすると、予期せぬ切り捨てや異常終了に直面する。
JCLのPARMは、仕様上最大100バイト(正確にはOSの制限やEXEC文の制約があるが、OS/390以降でもJCL自体のパラメータ長制限に縛られる)だが、PL/I側で受け取る際は `CHARACTER VARYING`(可変長文字列) を使うのが鉄則だ。
もし固定長 `CHAR(100)` で受けると、JCL側が5バイトしか渡していなくても、残りの95バイトにゴミ(あるいはパディングの空白)が残り、後続のバリデーションやデータベース検索(VSAMキーなど)で大事故を引き起こす。
—
2. 実践!PARM受け取りとVSAM/レコード処理の統合サンプル
百聞は一見にしかずだ。実際の現場で使える、堅牢なバッチプログラムの構造を見てみよう。
このサンプルでは、JCLから渡された日付パラメータ(例: `20231031`)を `VARYING` で受け取り、それをキーにしてVSAM(KSDS)ファイルを読み込む一連の流れを実装している。
1
/——————————————————————–\
- プログラム名: BATCH01P
- 概要 : JCL PARM取得およびVSAMマスターファイル参照処理
\——————————————————————–/
BATCH01P: PROC(IN_PARM) OPTIONS(MAIN);
/ — 宣言部 — /
/ JCL PARM受信用: 可変長文字列(最大100バイト) /
DCL IN_PARM CHAR(100) VARYING;
/ ワーク変数 /
DCL W_TARGET_DATE CHAR(8) INIT(‘ ‘);
DCL W_MSG_AREA CHAR(80) INIT(‘ ‘);
DCL 99_ABEND CONDITION; / 独自異常終了用コンディション /
/ VSAM(KSDS)マスターファイル定義 /
DCL MST_FILE FILE RECORD SEQUENTIAL KEYED
ENVIRONMENT(VSAM);
/ VSAMレコード構造体 /
DCL 1 MST_REC,
3 MST_KEY CHAR(8), / 検索キー(日付等) /
3 MST_NAME CHAR(30), / 得意先名など /
3 MST_STATUS CHAR(1); / ステータス /
/ ファイル状態監視用ビルトイン関数 /
DCL (ENDFILE, ONCODE) BUILTIN;
/ — オンユニット(例外処理)の定義 — /
ON ENDFILE(MST_FILE) BEGIN;
PUT SKIP LIST(‘— 終了: VSAMファイルがEOFに達しました —‘);
END;
ON UNDEFINEDFILE(MST_FILE) BEGIN;
PUT SKIP LIST(‘ 致命的エラー: VSAMファイルのオープンに失敗しました ‘);
SIGNAL CONDITION(99_ABEND);
END;
ON KEY(MST_FILE) BEGIN;
PUT SKIP EDIT(‘ 警告: 指定されたキーが見つかりません. CODE = ‘, ONCODE) (A, F(4));
SIGNAL CONDITION(99_ABEND);
END;
ON CONDITION(99_ABEND) BEGIN;
PUT SKIP LIST(‘ バッチ処理を異常終了します ‘);
STOP;
END;
/ — 処理開始 — /
PUT SKIP LIST(‘=== BATCH01P 処理開始 ===’);
/ 1. JCL PARMのバリデーションと値の切り出し /
IF LENGTH(IN_PARM) < 8 THEN DO;
PUT SKIP EDIT(' エラー: パラメータ長が不正です. LEN = ', LENGTH(IN_PARM)) (A, F(4));
SIGNAL CONDITION(99_ABEND);
END;
/ VARYING変数の特性を活かし、先頭から8バイトを処理日付として取得 /
W_TARGET_DATE = SUBSTR(IN_PARM, 1, 8);
PUT SKIP EDIT('取得した処理パラメータ(日付): ', W_TARGET_DATE) (A, A);
/ 2. VSAMファイルのオープン(KEYEDアクセス) /
OPEN FILE(MST_FILE) INPUT;
/ 3. VSAMレコードのダイレクト参照(READ ... KEY) /
/ JCLのPARMから取得した値をキーにして直接レコードを引く /
READ FILE(MST_FILE) INTO(MST_REC) KEY(W_TARGET_DATE);
PUT SKIP EDIT('レコード読み込み成功 - キー: ', MST_REC.MST_KEY,
' 名称: ', MST_REC.MST_NAME) (A, A, A, A);
/ 4. 終了処理 /
CLOSE FILE(MST_FILE);
PUT SKIP LIST('=== BATCH01P 正常終了 ===');
END BATCH01P;
---
3. ベテランが教えるデバッグとコーディングの勘所
上記のコードを見れば、ただ動くだけのコードと、障害に強い「現場のコード」の違いが分かるはずだ。特に注意すべきポイントをいくつか解説しておこう。
① `LENGTH` ビルトイン関数の活用
`CHAR(100) VARYING` で受け取った場合、JCL側が `PARM=’20231031’` であれば、`LENGTH(IN_PARM)` は厳密に `8` を返す。従来の固定長だと右側にスペースがパディングされてしまい、文字数カウントに苦労したが、`VARYING` ならその心配がいらない。
必ず処理の最初に `LENGTH()` を使った桁数チェック(バリデーション)を入れること。これがバグを防ぐ最大の防衛策だ。
② ONユニットによる堅牢な制御フロー
PL/Iの真骨頂は、この `ON` ユニット(例外処理機構)にある。COBOLの `INVALID KEY` 句も悪くないが、PL/Iはファイル入出力エラー(`KEY`コンディション)、ファイル未定義(`UNDEFINEDFILE`)、ファイル終端(`ENDFILE`)を体系的にトラップできる。
特にVSAMのランダムアクセスでキーが存在しない場合、`KEY` オンユニットが発火する。これを適切に捕捉して異常終了シグナル(`SIGNAL CONDITION`)を送る設計にしておかないと、プログラムが予期せぬ挙動を引き起こすので注意してほしい。
③ 予約語を持たない仕様への配慮
冒頭でも言った通り、PL/Iには厳密な意味での「予約語」がない(コンテキスト依存キーワードが多い)。そのため、うっかり変数名に `READ` や `FILE` と書いてもコンパイルエラーにならず、後から「なんだこのバグは!?」と頭を抱えることになる。
変数名をつけるときは、サンプルコードのように `IN_PARM` や `W_TARGET_DATE` のようにプレフィックス(接頭辞)を必ずつけるコーディング規約をチーム全体で徹底してくれ。
—
おわりに
メインフレームの寿命は長い。君たちが今書いている、あるいは保守しているそのPL/Iプログラムも、あと何年、何十年と日本の金融や流通の基幹を支え続ける。
JCLのPARMという、一見すると枯れ切った小さな仕様の裏側にも、メモリの振る舞いやコンパイラの最適化、そして何より「絶対に止めてはならない」という設計思想が詰まっている。
今回の解説をしっかりと血肉にして、トラブルに強い、後輩から信頼されるメインフレームエンジニアを目指してくれ。さて、コーヒーでも飲んだら次のチケットに取り掛かろうか。
