【実務・中級編】RETURNS属性を用いた関数型プロシージャの戻り値定義 – PL/Iの基本構文とデータ制御実践ガイド

現場のPL/I職人が教える:RETURNS属性による関数設計の「落とし穴」と鉄則

メインフレームの現場で長くコードを読んでいると、「なぜか本番バッチでデータが化ける」「原因不明の例外終了(ABEND)が発生する」といったトラブルの多くが、実はプロシージャのインターフェース設計、特に`RETURNS`属性の不整合に起因していることに気づかされます。

今回は、PL/Iにおいて関数型プロシージャを定義する際の「戻り値定義」について、実務的な観点から深掘りします。

1. なぜ「RETURNS」の整合性が命取りになるのか

PL/Iの強力な点は、コンパイラが型チェックを厳格に行うことですが、一方で暗黙的な型変換(デフォルトの変換規則)が災いすることもあります。特に古いソースコードでは、`RETURNS`を省略したり、呼び出し側と戻り値の型が微妙にずれているケースが見受けられます。

例えば、`FIXED BIN(31)`で計算した結果を`FIXED DEC(15,0)`で受け取ろうとした場合、あるいはその逆。これらはコンパイラが気を利かせて変換してくれますが、オーバーフローや精度落ちは容赦なく発生します。

2. 実践コード:堅牢な関数型プロシージャの書き方

まずは、VSAMファイルから特定レコードのステータスを読み取り、計算結果を返す標準的な構成例を見てみましょう。

1
/ —————————————————————— /
/ FUNCTION: GET_VALUATION /
/ 戻り値: 評価額 (FIXED DEC(15, 2)) /
/ —————————————————————— /
GET_VALUATION: PROCEDURE(IN_ID)
RETURNS(FIXED DEC(15, 2)) OPTIONS(REENTRANT);

DCL IN_ID CHAR(10);
DCL WRK_VAL FIXED DEC(15, 2) INIT(0);

/ VSAMアクセス用のエリア定義 /
DCL VSAM_RECORD CHAR(100) BASED(ADDR(VSAM_BUF));

/ ビルトイン関数を利用した安全な比較 /
IF VERIFY(IN_ID, ‘0123456789’) ^= 0 THEN DO;
SIGNAL ERROR; / 入力異常をONユニットへ飛ばす /
END;

/ ここに本来のVSAM読み込みロジックが入る /
/ READ FILE(MSTFILE) INTO(VSAM_RECORD) KEY(IN_ID); /

WRK_VAL = 12345.67; / 擬似的な計算結果代入 /

RETURN(WRK_VAL);

END GET_VALUATION;

ここで意識すべき「現場の鉄則」

  • OPTIONS(REENTRANT)の付与: 大規模バッチでは、マルチタスクや再帰呼び出しを想定して必ず付与しましょう。これを忘れると、スタティックストレージの競合で地獄を見ることになります。
  • 明示的なRETURNS定義: 呼び出し側(CALL側)で`DCL`にて`RETURNS`属性を正確に宣言しておくことが必須です。これを怠ると、コンパイラは戻り値を`FIXED BIN(15)`と勝手に解釈し、データが切り捨てられるという悲劇を招きます。

3. トラブルを未然に防ぐ「呼び出し側」の心得

呼び出し側では、戻り値を受け取るための`DCL`が鍵を握ります。

1
MAIN_PROC: PROCEDURE OPTIONS(MAIN);

/ 外部関数プロトタイプの宣言 (ここが最も重要!) /
DCL GET_VALUATION ENTRY(CHAR(10))
RETURNS(FIXED DEC(15, 2));

DCL RESULT_VAL FIXED DEC(15, 2);
DCL ERR_FLG FIXED BIN(15) INIT(0);

/ ONユニットによるエラーハンドリング /
ON ERROR BEGIN;
PUT SKIP LIST(‘関数呼び出しで異常が発生しました’);
ERR_FLG = 1;
END;

/ 関数呼び出し /
RESULT_VAL = GET_VALUATION(‘1234567890’);

IF ERR_FLG = 0 THEN
PUT SKIP EDIT(‘評価額は:’, RESULT_VAL)(A, F(15,2));

END MAIN_PROC;

4. ベテランからのアドバイス:デバッグの極意

もし、本番で「なぜか戻り値が正しくない」という事象に遭遇したら、以下の手順で切り分けてください。

1. コンパイラ・リスト(マッピング)の確認: `ATTRIBUTES`オプションをつけてコンパイルし、戻り値の型が意図通りか、暗黙変換が発生していないかを確認する。
2. ON ERRORのトレース: `SIGNAL ERROR`を活用し、異常系フローを意図的に通して、`ON`ユニットが正しくスタックを解放できているか確認する。
3. ストレージ・ダンプの比較: `HEX`関数を使用して、関数から戻った直後のレジスタ/メモリ上の値を直接確認する。PL/Iはメモリ配置が明快なので、ダンプを読めば「型」の違いは一目瞭然です。

まとめ

PL/Iの`RETURNS`属性は、単なる値の受け渡し以上の意味を持ちます。それは「システム間の契約」です。呼び出し側と被呼び出し側で、型定義という名の契約書をしっかり交わすこと。これが、バッチ改修における障害をゼロに近づける唯一の方法です。

皆さんの現場のソースコードも、一度`DCL`の宣言部を再確認してみてください。長年気づかなかった「型不整合の爆弾」が眠っているかもしれませんよ。

次回は、「VSAMのキー指定におけるパディング問題」についてお話しします。それでは、良いバッチ・プログラミングを。

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