1. 導入:なぜ「%GOTO」が必要なのか?
メインフレームのPL/I開発において、複雑な条件分岐によってソースコードを生成する際、「特定の処理をスキップしたい」「特定の定義ブロックへ強制的にジャンプさせたい」という場面に直面することがあります。そこで活躍するのがプリプロセッサ命令の「%GOTO」と「%LABEL」です。これを使うことで、コンパイル時にソースコードの生成順序を動的に制御し、不要なコード生成を防ぐことができます。
2. 基礎知識:通常のGOTOとの違い
まず重要なのは、「%GOTO」はプログラム実行時の制御命令ではないということです。PL/Iプログラムが実行される際に行われるのではなく、ソースコードをコンパイル(プリプロセス)する段階で、コンパイラが「どの行を読み飛ばすか」「どこから読み直すか」を決定するための命令です。つまり、「コンパイル後のソースコードの形を、コンパイル中に決定する」ための魔法のスイッチだと考えてください。
3. 実装と解決策
%GOTOを使用するには、移動先の行に「%ラベル名:」を記述します。
プリプロセッサが%GOTO命令を読み込むと、即座に指定したラベルの場所までスキャン位置を飛ばします。これにより、条件によって出力するコードを大きく切り替えるといった柔軟なロジックが組めます。
4. サンプルプログラム
以下のコードは、デバッグモードがONの時だけ特定のログ出力用コードを生成する例です。
/ プリプロセッサ変数としてDEBUGを定義 /
%DCL DEBUG CHAR;
%DEBUG = ‘ON’;
/ DEBUGがONならラベルDEBUG_LOGへジャンプ /
%IF DEBUG = ‘ON’ %THEN %GOTO DEBUG_LOG;
/ DEBUGがOFFの時に実行される処理 /
PUT SKIP LIST(‘本番処理を実行します’);
%GOTO FINISH;
/ %LABELを使ってジャンプ先を定義 /
%DEBUG_LOG:;
PUT SKIP LIST(‘デバッグログ: 処理を開始しました’);
%FINISH:;
PUT SKIP LIST(‘プログラム終了’);
5. 応用・注意点:スパゲッティ化を避けるために
この機能は非常に強力ですが、乱用すると「どこからどこへジャンプしているのか」が追いづらくなる、いわゆる「スパゲッティ・コード」の原因となります。
特に注意すべきは以下の2点です。
・ジャンプによる「読み飛ばし」の弊害:本来定義されるべき変数宣言や初期化処理をスキップしてしまうと、コンパイルエラーや予期せぬ実行時エラーが発生します。
・可読性の低下:可能な限り「%IF-%THEN-%ELSE」構造で解決できないか検討してください。%GOTOは、どうしても複雑な構造を回避できない場合の「最後の手段」として使うのが、保守性の高いコードを書くコツです。
現場の移行作業などでこのコードに出会った際は、まず「どのコードが生成され、どのコードがスキップされているのか」をシミュレータ等で慎重に追いかけるようにしましょう。

コメント