【実務・中級編】ENTRY属性とOPTIONS(ASM/COBOL)による外部呼出し – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの「自由」を使いこなせ:外部呼出しにおけるリンケージ規約の罠と処方箋

若手のエンジニアからよく聞く悩みの一つに、「PL/Iの変数は何でもありすぎて怖い」というものがある。確かに、PL/Iは予約語という概念をほとんど持たない(キーワードは文脈で判断される)。`IF` という名前の変数だって作れてしまう。この「自由度」こそが、PL/Iを強力にしている反面、外部言語と連携する際に「地雷」を踏み抜く原因にもなっているんだ。

今日は、メインフレームの基幹バッチ改修で避けては通れない、アセンブラやCOBOLとの連携(外部呼出し)について、現場で泣きを見ないための勘所を伝授しよう。

なぜ「属性」を明示しないといけないのか

PL/Iのコンパイラは優秀だが、外部のモジュールがどういう規約で動いているかまでは忖度してくれない。特に `ENTRY` 属性を指定せずに外部ルーチンを呼ぶと、デフォルトのリンケージ規約が適用され、最悪の場合はABEND(システム異常終了)直行だ。

リンケージ規約の基本:BYADDR と BYVALUE

COBOLやアセンブラを呼び出す際、一番重要なのは「引数をどう渡すか」だ。

  • BYADDR(デフォルト): 引数の「アドレス」を渡す。COBOLでいう `USING` に対応する。
  • BYVALUE: 引数の「値そのもの」をレジスタに積んで渡す。C言語や最新の環境ではこちらが主流だが、レガシーなCOBOLバッチを叩くときは注意が必要だ。

実践コード:COBOL/ASMサブルーチンを呼び出す定石

現場では、VSAMのアクセスルーチンや、特定の計算ロジックをアセンブラで書いたモジュールを呼び出すケースが多い。以下のようなコーディング標準を意識してほしい。

1
/ —————————————————————– /
/ サンプル:外部アセンブラルーチン(ASM_MOD)の呼出し /
/ —————————————————————– /
TEST_PROG: PROC OPTIONS(MAIN);

/ 外部定義:ASMルーチンをENTRYとして宣言 /
/ OPTIONS(ASM)によりリンケージ規約を明示 /
DCL ASM_MOD ENTRY(
FIXED BIN(31), / 第1引数:ポインタ渡し(BYADDR) /
CHAR(8) BYVALUE / 第2引数:値渡し(BYVALUE)の例 /
) OPTIONS(ASM);

DCL WS_WK_VAL FIXED BIN(31) INIT(100);
DCL WS_CHAR_VAL CHAR(8) INIT(‘TESTDATA’);

/ 呼出し実行 /
CALL ASM_MOD(WS_WK_VAL, WS_CHAR_VAL);

/ VSAMファイルの制御等もこの後に行う /
/ ONユニットによるエラーハンドリングは必須 /
ON ENDFILE(VSAM_FILE) BEGIN;
PUT SKIP LIST(‘ファイル終了を検知しました’);
END;

END TEST_PROG;

現場で遭遇する「落とし穴」

1. 予約語を持たないゆえの悲劇

冒頭で述べた通り、PL/Iは `DCL IF FIXED BIN` と書けば `IF` という名前の変数が作れてしまう。外部ルーチンから戻ってきた値を変数に格納する際、うっかりコンパイラの予約語っぽい名前を付けると、後でソースを読んだ人間が発狂する。識別子には必ずプレフィックス(例: `WS_` や `WK_`)を付けるのが、何十年経っても変わらぬ鉄則だ。

2. ONユニットのスコープ

外部ルーチンで異常が発生した場合、PL/Iの `ON` ユニットがどう反応するかを理解しておく必要がある。メインフレームのバッチでは、`ON ERROR` を定義し忘れると、予期せぬ条件で `U4038` 等のシステムコードが出て調査に時間がかかる。外部ルーチンを呼ぶ前には、必ず `ON` ユニットでエラートラップを張り、スタックトレースを吐き出すルーチンを仕込んでおこう。

3. BUILTIN関数の活用

データ変換の際、`ADDR` や `LENGTH` といった `BUILTIN` 関数は非常に便利だ。特に外部呼出し時の引数チェックには `ADDR` を使って、渡しているポインタが正しいかデバッグ中に確認する癖をつけてほしい。

アーキテクトからのアドバイス

「動けばいい」というコードは、数年後のマイグレーション時に必ず牙を剥く。特にPL/Iの外部呼出しは、コンパイル時にチェックしきれない「実行時の契約」が強い。

  • 引数の長さと型を厳密に合わせる: `FIXED BIN(31)` なのか `FIXED BIN(15)` なのか。ここを疎かにすると、メインフレーム特有の「データの上書き」が発生し、原因不明のバグとして数日間悩むことになる。
  • ドキュメントには「規約」を書く: ソースコードのヘッダーに、どのルーチンがどの引数を `BYVALUE` で要求しているか、必ず明記すること。

PL/Iは、その自由さゆえに「設計者の意図」が如実に現れる言語だ。怖がらず、しかし敬意を持って向き合えば、これほど強力な武器はない。何か詰まったら、いつでも聞いてくれ。現場で戦うエンジニアを、私は全力でサポートする。

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