【入門編】TESTコンパイラオプションとSYMテーブルの生成 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!IBMメインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいは従来型のビジネス言語の経験がおありの方にとって、PL/I(Programming Language One)という名前は、どこかレトロで、少し近寄りがたい雰囲気を漂わせているかもしれませんね。

特に、データセンターの奥深くで稼働する巨大な基幹システムを支えるPL/Iは、「何やら難解な呪文のようだ」と身構えてしまう方も多いはずです。でも、安心してください。ベースにある考え方を一つずつ紐解いていけば、決して怖くありません。

今回は、そんなPL/Iの基本と、実務の現場で必ず直面する「TESTコンパイラオプションとSYMテーブル」について、デバッグの裏側を覗き見するような感覚で、優しく丁寧に解説していきますね。

1. 他言語とはココが違う? PL/Iの「キーワード」と「識別子」の優しい関係

JavaやCOBOLを触ってきた方なら、「`IF` や `MOVE`、`RESERVED` などの予約語と同じ名前を変数に使ってはいけない」というのは常識ですよね。もし使おうものなら、コンパイラから「そんな名前は使えません!」とお叱りを受けてしまいます。

しかし、PL/Iの歴史的かつ面白い(そして少し油断ならない)特徴として、「PL/Iには厳密な意味での『予約語(Reserved Words)』が存在しない」という仕様があります。

どういうことかと言うと、極端な話、言語の命令であるはずの名前を変数名として使っても、コンパイラは文脈から「あ、これは変数だな」「ここは命令だな」と賢く判断してくれます。例えば、以下のようなコードもPL/Iでは許容されてしまいます。

1
/ PL/Iの少しユニークな変数宣言の例 /
DECLARE IF FIXED BINARY(31); / 「IF」という名前の数値変数 /
DECLARE THEN CHARACTER(10); / 「THEN」という名前の文字変数 /

IF = 10; / 変数IFに10を代入している /

初めてこれを見たときは、「なんてカオスな言語なんだ…!」と驚愕しましたよね。でも、実務の現場では、こんな紛らわしい書き方は誰もが避けます。後からコードを読む開発者が混乱して泣いてしまいますからね。JavaやCOBOLと同じように、「キーワードっぽすぎる名前を変数に使うのはやめよう」というマナーを守っていれば大丈夫です。

2. デバッグの強い味方!「TESTコンパイラオプション」とは何か?

さて、ここからが今回の本題です。
あなたが苦労して書いたPL/Iプログラムをコンパイルし、いざテスト環境で動かしてみたら……「あれ、意図しないデータが取れている」「なぜかここで異常終了(ABEND)するぞ?」という場面に必ず直面します。

そんな時、現代の私たちは IBM z/OS Debugger(旧Debug Tool) という強力なデバッガを使って、プログラムを1行ずつ止めたり、変数の中身を覗き見したりします。

ここで重要になってくるのが、コンパイル時に指定する `TEST` オプション です。

//STEP1 EXEC PIGZC, <-- PL/Iコンパイラ起動PROC // PARM.COLS='TEST,NODEC' <-- ここに注目!TESTを指定

TESTオプションがやってくれること

普段、私たちが書いたPL/Iのソースコードは、コンパイラによって機械語(オブジェクトコード)に翻訳され、メモリ上で実行されます。この時、コンピュータは「変数 `WK_EMP_NAME` がどこにあって、どんな属性か」という人間向けのラベル(シンボル情報)を、効率化のために削ぎ落としてしまいます。

しかし、コンパイル時に `TEST` を指定すると、コンパイラは機械語と一緒に 「SYMテーブル(シンボルテーブル)」 という名の「ソースコードの設計図」をロードモジュールの中にこっそり埋め込んでくれます。

これがあるおかげで、デバッガ画面で以下のような魔法が使えるようになります。

  • 「`LIST WK_EMP_NAME;`」と打つだけで、変数の値がリアルタイムで見える
  • ソースコードの何行目で止まっているかが画面に表示される

3. SYMテーブルの光と影:ロードモジュールサイズへの影響

「じゃあ、デバッグが便利になるんだから、いつでもどこでも `TEST` オプションを付けておけば万全だね!」
……と言いたいところですが、ここにシステムアーキテクトの腕の見せ所、そしてレガシーシステムならではのシビアな現実があります。

SYMテーブルは「容量を食う」

`TEST` オプションを有効にして生成されたSYMテーブルは、いわば「プログラムの住所録と辞書」です。プログラムの規模が大きくなればなるほど、この辞書の厚みも増していきます。

結果として何が起きるかというと、ロードモジュール(実行ファイルのサイズ)が肥大化します。

  • 開発・単体テスト環境:

バグを見つけて修正するスピードが命なので、多少ロードモジュールが大きくなろうとも、絶対に `TEST`(または `TEST(SYM)` など)を付けてコンパイルします。デバッガが使えないと、abendダンプ(SYSUDUMP)の16進数とにらめっこするハメになり、残業が確定してしまいますからね。

  • 本番運用(プロダクション)環境:

メインフレームの世界では、メモリ(ストレージ)やロードモジュールのロード時間は、システムのパフォーマンスに直結する貴重な資源です。本番稼働するプログラムに不要なデバッグ用シンボルを残しておくことは、「無駄な荷物を積んで高速道路を走る」ようなものです。そのため、本番リリース前の最終コンパイルでは必ず `NOTEST` に変更し、スリムで引き締まったロードモジュールへと仕上げます。

4. 実務で役立つPL/Iデータ宣言とデバッグの作法

最後に、実務のバッチプログラム改修でよく見かける、PL/Iらしいデータ構造と、デバッグを意識したコードの書き方のサンプルをご紹介します。

1
/ —————————————————————- /
/ プログラム名: PAYCALC /
/ 概要 : 給与計算バッチ(TESTコンパイラとSYMテーブルの挙動確認用) /
/ —————————————————————- /
PAYCALC: PROC OPTIONS(MAIN);

/ 従業員マスタ入力レコード(COBOLの01レベルに相当する構造体) /
DECLARE 1 EMP_RECORD,
5 EMP_ID CHARACTER(5), / 従業員ID /
5 EMP_NAME CHARACTER(20), / 従業員名 /
5 EMP_SALARY FIXED DEC(9,2); / 給与額 /

/ 計算用ワークエリア /
DECLARE WK_TAX_RATE FIXED DEC(3,2) INITIAL(0.10); / 税率 10% /
DECLARE WK_NET_PAY FIXED DEC(9,2); / 支給額 /

/ 処理開始 /
PUT SKIP LIST(‘ PAYCALC START ‘);

/ サンプルデータの擬似代入(通常はファイルからREADします) /
EMP_ID = ‘A1023’;
EMP_NAME = ‘山田 太郎’;
EMP_SALARY = 350000.00;

/ 給与計算ロジック /
/ ★ここでz/OS Debuggerを使い、EMP_SALARYやWK_NET_PAYの中身をウォッチします /
WK_NET_PAY = EMP_SALARY (1.00 – WK_TAX_RATE);

/ 結果出力 /
PUT SKIP EDIT (‘社員ID: ‘, EMP_ID, ‘ 支給額: ‘, WK_NET_PAY)
(A, A, A, F(10,2));

PUT SKIP LIST(‘ PAYCALC END ‘);

RETURN;

END PAYCALC;

もしこのプログラムを `TEST` オプション付きでコンパイルしていれば、デバッガ上で `WK_NET_PAY` にどのような値が算出して格納されたのか、一目で確認することができます。もし計算結果がおかしい場合でも、変数の名前(シンボル)がそのまま残っているため、パニックにならずに原因を特定できるというわけです。

まとめ

いかがでしたでしょうか?

  • PL/Iのキーワード規則:予約語がないというユニークさはあるけれど、常識的な命名をしていれば恐れるに足りないこと。
  • TESTオプションとSYMテーブル:デバッグを劇的にラクにしてくれる「プログラムの設計図」である一方、本番環境ではロードモジュールサイズ肥大化を防ぐために外すべきものであること。

メインフレームの世界は、一見すると古いルールや独特の用語が多くて圧倒されがちですが、その裏側にある設計思想(なぜそのオプションがあるのか、なぜそのサイズを気にするのか)を知ると、とても合理的で美しい仕組みで作られていることに気づきます。

日々の保守や移行作業でPL/Iに出会ったときは、「あ、これはこういう理由なのね」と、ぜひ今回の話を思い出してみてください。あなたのメインフレームライフが、少しでもスムーズで楽しいものになりますように!

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