【PL/I学習|初心者向け】PL/I開発の必須知識:プリプロセッサ・スキャンの仕組みと「再スキャン」の罠

なぜプリプロセッサ・スキャンを知る必要があるのか

メインフレームのPL/I開発において、コンパイルは単なる「翻訳」ではありません。特に「プリプロセッサ」は、ソースコードをコンパイルする前に、プログラムを「動的に書き換える」強力な機能です。このプロセスを理解していないと、意図した通りのコードが生成されず、デバッグで迷宮入りすることがあります。今回は、このプリプロセッサ・スキャンの仕組みと、開発者が必ず押さえておくべき「再スキャン(Rescan)」の挙動について解説します。

基礎知識:プリプロセッサとは何か

プリプロセッサとは、コンパイラが本来の翻訳(オブジェクト生成)を行う前段階で動作する「ソースコードの加工屋」です。
「%」で始まる行を見つけると、それを命令として解釈し、ソースコードを書き換えます。例えば、定数を埋め込んだり、特定の条件でコードの断片を挿入したりします。この処理を「スキャン」と呼びます。

解決策:再スキャンの連鎖を理解する

PL/Iのプリプロセッサには重要な性質があります。それは、一度マクロを展開して生成されたコードを、再度スキャンする(Rescan)という点です。
もし展開されたコードの中にさらにマクロ文が含まれていれば、それも展開されます。この「連鎖」を理解していないと、最終的にコンパイラに渡されるコードが想定外のものになり、ロジックエラーや予期せぬ仕様変更を引き起こします。

サンプルプログラム:マクロ展開と再スキャンの挙動

以下のコード例で、マクロ変数がどのように置き換わり、展開されるかを確認してみましょう。

/ サンプルコード:プリプロセッサ変数の定義と展開 /
%DCL MY_VAR CHAR; / プリプロセッサ変数 MY_VAR を宣言 /
%MY_VAR = ‘ABC’; / 値を代入 /

PROC OPTIONS(MAIN);
/
下の行の MY_VAR は、プリプロセッサによって
‘ABC’ という文字列に置き換わります。
/
DCL DATA CHAR(3) INIT(MY_VAR);

PUT SKIP LIST(‘データ値は: ‘ || DATA);
%END;

/
【解説】
1. コンパイラが %DCL を見つけ、MY_VAR をメモリに確保します。
2. ソースコードをスキャンし、MY_VAR を見つけると、
メモリ上の ‘ABC’ に即座に置換します。
3. 最終的なソースには DCL DATA CHAR(3) INIT(‘ABC’); が渡されます。
/

応用・注意点:現場でのバグ回避

現場で最も陥りやすいのは、「マクロの展開結果が、さらに別のマクロを呼び出してしまうケース」です。

1. 無限ループに注意: マクロの中でマクロを生成し、それがさらに自分自身を呼び出すような再スキャンが発生すると、コンパイラが「再スキャン限界」でエラーを吐くことがあります。
2. 移行解析での盲点: 古いプログラムを解析する際、単純にソースを読むだけでは不十分です。必ず「コンパイラリスト(SYSIN等に出力される展開後のコード)」を確認してください。そこに書かれているコードこそが、実際にCPUが実行するロジックの正体です。

プリプロセッサは便利ですが、コードを「動的に作る」ため、ブラックボックス化しやすい性質があります。常に「展開後、最終的にどんなコードが生成されるのか?」を意識する癖をつけることが、熟練のメインフレーム技術者への近道です。

コメント

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