エラー処理サブルーチンでのループの防止

前の例では、*PSSR でエラーが起こるため、ループの起こる可能性は少なくなっています。 しかし、*PSSR がどのように書かれるかによって、*PSSR の処理中に例外が起こるとループが起こる可能性があります。

このようなループを避ける 1 つの方法として、 サブルーチンに初回の実行を示すスイッチを設定することができます。 サブルーチンの初回の実行でない場合には、ENDSR 命令の演算項目 2 に *CANCL などの 適切な戻り点を指定することができます。

図 1 には、*PSSR サブルーチン内でのループを避ける方法を 示すために例外を生成するように設計されたプログラム NOLOOP を示してあります。 このプログラムは例外を次の 2 回生成します。
  1. コードの本体で *PSSR に制御権を渡すため
  2. *PSSR 内部で潜在的にループを起こすため
図 1. エラー処理サブルーチンでのループの防止
      *=================================================================*
      * NOLOOP:  *PSSR サブルーチンの反復を回避する方法を示します。     *
      *=================================================================*
      *-----------------------------------------------------------------*
      * エラーを起こすために使用する配列                                *
      *-----------------------------------------------------------------*
     D Arr1            S             10A   DIM(5)
      *-----------------------------------------------------------------*
      * 配列の範囲外エラーを生成し、制御を *PSSR に渡します。           *
      *-----------------------------------------------------------------*
     C                   Z-ADD     -1            Neg1              5 0
     C                   MOVE      Arr1(Neg1)    Arr1(Neg1)
     C                   MOVE      *ON           *INLR
      *=================================================================*
      * *PSSR: プロシージャーのエラー処理サブルーチン。PSSR の反復を検出*
      *        するために変数 InPssr を使用します。                     *
      *        反復を検出した場合には、プロシージャーを *CANCL します。 *
      *=================================================================*
     C     *PSSR         BEGSR
     C                   IF        InPssr = 1
     C                   MOVE      '*CANCL'      ReturnPt          6
     C                   Z-ADD     0             InPssr            1 0
     C                   ELSE
     C                   Z-ADD     1             InPssr
      *                                                                 *
      *         サブルーチンがプロシージャーを取り消す方法を見るために  *
      *         ここで PSSR に別のエラーを生成します。                  *
      *                                                                 *
     C                   MOVE      Arr1(Neg1)    Arr1(Neg1)
      *                                                                 *
      *         Neg1 がまだ負の場合には、次の 2 つの命令は処理されない  *
      *         ことに注意してください。                                *
      *                                                                 *
     C                   MOVE      '*GETIN'      ReturnPt
     C                   Z-ADD     0             InPssr
     C                   ENDIF
     C                   ENDSR     ReturnPt
図 1 のソースを使ってプログラムを作成し、そのデバッグを 始めるには、次の入力をします。
CRTBNDRPG PGM(MYLIB/NOLOOP) DBGVIEW(*SOURCE)
STRDBG PGM(MYLIB/NOLOOP)

*PSSR サブルーチンの BEGSR 行に中断点を設定することにより、*PSSR サブルーチンを ステップスルーすることができます。

プログラムを呼び出すと、次のことが起こります。
  1. プログラムが負の指標を使用して配列に MOVE 命令を実行しようとすると、 例外が起こります。制御が *PSSR に渡されます。
  2. これが *PSSR の最初の実行であるので、変数 In_Pssr はまだオンに設定されていません。 将来のループを防止するために変数 In_Pssr がオンに設定されます。
  3. 処理は、*PSSR 内の ELSE の後の MOVE で続行されます。 再び例外が起こり、*PSSR の処理が新たに始まります。
  4. 今回の実行では変数 In_Pssr が既に 1 に設定されています。 これはサブルーチンがループ状態にあることを示しているので、ReturnPt フィールドを *CANCL に 設定することによってプロシージャーが取り消されます。
  5. ENDSR 命令が制御を受け取り、プロシージャーが取り消されます。

ループを避けるためにここで用いた方法は、INFSR エラー処理サブルーチン内でも使用することができます。