エラー処理サブルーチンの使用

エラー処理サブルーチンを作成する時には、次の 2 つのことを行います。

  1. RPG サブルーチン・エラー処理プログラムの活動化

    このサブルーチン・エラー処理プログラムは例外を処理して、制御をユーザー のサブルーチンに渡します。

  2. 回復処置の指定 (任意指定)

    エラー処理サブルーチンを使用して、起こったエラーに基づいて特定の処置を 取るか、あるいは一般処置 (例えば、すべてのエラーに照会メッセージを出 すなど) を取ることができます。

エラー処理サブルーチンには次の考慮事項が適用されます。

ファイル・エラー処理 (INFSR) サブルーチンの使用

メイン・プロシージャーでファイル・エラーまたは例外を処理するためには、 ファイル・エラー処理 (INFSR) サブルーチンを作成することができます。 ファイル例外が起こると、次のようになります。

  1. INFDS が更新されます。
  2. 次のもので例外が起こった場合には、ファイル・エラー処理サブルーチン (INFSR) が制御を受け取ります。

ファイル・エラー処理サブルーチンは複数のファイルでエラーを処理すること ができます。

次の制約事項が適用されます。

プログラムにファイル・エラー処理サブルーチンを追加するためには、 次のステップを行ってください。

  1. ファイル仕様書のキーワード INFSR の後にサブルーチンの名前を記入し てください。 サブルーチン名は *PSSR とすることができますが、これはこのファイルでの例 外でプログラム・エラー処理サブルーチンに制御が渡されることを示します。
  2. 任意指定で、キーワード INFDS を使用してファイル仕様書でファイル情報 データ構造を指定してください。
  3. 演算項目 1 にキーワード INFSR に指定したものと同じサブルーチン名のあ る BEGSR 命令を指定してください。
  4. 戻り点がある場合にはそれを指定して、サブルーチンの ENDSR 命令にそれを コーディングしてください。 演算項目 2 の有効な項目については、ENDSR 命令での戻り点の指定を参照してくださ い。
  5. ファイル・エラー処理サブルーチンの残りをコーディングしてください。 ファイル・エラー処理サブルーチンで ILE RPG コンパイラー命令を使用することができますが、エラーのあった同じファイルに入出力命令を使用することは望ましくありません。ENDSR 命令は、ファイル・エラー処理サブルーチンの最後の仕様書でなければな りません。

図 132 には、INFSR エラー処理サブルーチンを使った例外処理の例が 示してあります。 プログラム TRNSUPDT は単純な在庫更新プログラムです。このプログラムはトランザクション・ファイル TRANSACT を使用して 在庫マスター・ファイル PRDMAS を更新します。入出力エラーが起こった場合には、INFSR エラー処理サブルーチンが呼び出さ れます。 レコード・ロック・エラーの場合には、そのレコードがバックログ・ファイル に書き出されます。 そうでない場合には、照会メッセージが出されます。

PRDMAS のファイル仕様書は INFDS を識別するとともに、それに関連した INFSR を識別するということに注意してください。

TRANSACT ファイルの各レコードに対して次のことが行われます。

  1. トランザクション製品番号を使用して製品マスター・ファイル中で該当す るレコードが見付けられます。
  2. レコードが見付かった場合には、在庫数量が更新されます。
  3. UPDATE 命令でエラーが起こった場合には、 制御が INFSR エラー処理サブルーチンに渡されます。
  4. レコードが見付からなかった場合には、エラー報告書に製品番号が書き出 されます。
図 132. ファイル例外処理の例
      *=================================================================*
      * TRNSUPDT: このプログラムは簡単な在庫更新プログラムです。        *
      * トランザクション・ファイル (TRANSACT) が連続的に処理されます。  *
      * トランザクションにある製品番号が、マスター・ファイル (PRDMAS)   *
      * にランダムにアクセスするキーとして使用されます。                *
      * 1. レコードが見つかった場合には、在庫数量が                     *
      *    更新されます。                                               *
      * 2. レコードが見つからなかった場合には、報告書にエラーが         *
      *    印刷されます。                                               *
      * 3. 現在レコードがロックされている場合には、トランザクションは   *
      *    トランザクション受注残ファイルに書き出され、                 *
      *    後で処理されます。                                           *
      * 4. それ以外の予期しないエラーが起こった場合には、実行時エラー・ *
      *    メッセージが出されます。                                     *
      *=================================================================*
      *-----------------------------------------------------------------*
      * ファイルの定義:                                                 *
      *   1) PRDMAS      - 製品マスター・ファイル                       *
      *   2) TRANSACT    - トランザクション・ファイル                   *
      *   3) TRNBACKLG   - トランザクション受注残ファイル               *
      *   2) PRINT       - エラー報告書                                 *
      *-----------------------------------------------------------------*
     FPRDMAS    UF   E           K DISK
     F                                     INFSR(PrdInfsr)
     F                                     INFDS(PrdInfds)
     FTRANSACT  IP   E             DISK
     FTRNBACKLG O    E             DISK
     FPRINT     O    F   80        PRINTER
      *-----------------------------------------------------------------*
      * ファイル PRDMAS のファイル情報データ構造を定義します。          *
      * *STATUS フィールドは取るべき処置を決めるために使用されます。    *
      *-----------------------------------------------------------------*
     D PrdInfds        DS
     D  PrdStatus        *STATUS
      *-----------------------------------------------------------------*
      * 予期される例外をリストします。                                  *
      *-----------------------------------------------------------------*
     D ErrRecLock      C                   CONST(1218)
      *-----------------------------------------------------------------*
      * トランザクションの製品番号を使用して、製品マスター・ファイルに  *
      * アクセスします。                                                *
      *-----------------------------------------------------------------*
     C     TRNPRDNO      CHAIN     PRDREC                             10
      *-----------------------------------------------------------------*
      * レコードが見つかった場合、マスター・ファイルの数量を更新します。*
      *-----------------------------------------------------------------*
     C                   IF        NOT *IN10
     C                   SUB       TRNQTY        PRDQTY
     C                   UPDATE    PRDREC
      *-----------------------------------------------------------------*
      * レコードが見つからない場合には、エラー報告書を書き出します。    *
      *-----------------------------------------------------------------*
     C                   ELSE
     C                   EXCEPT    NOTFOUND
     C                   ENDIF
     C                   SETON                                        LR
      *-----------------------------------------------------------------*
      * エラー処理ルーチン。                                            *
      *-----------------------------------------------------------------*
     C     PrdInfsr      BEGSR
      *-----------------------------------------------------------------*
      * 現在マスター・レコードがロックされている場合、トランザクション・*
      * レコードを受注残ファイルに書き次のトランザクションにスキップ。  *
      *-----------------------------------------------------------------*
     C     PrdStatus     DSPLY
     C                   IF        (PrdStatus = ErrRecLock)
     C                   WRITE     TRNBREC
     C                   MOVE      '*GETIN'      ReturnPt          6
      *-----------------------------------------------------------------*
      * 予期しないエラーが起こった場合、照会メッセージが出されます。    *
      *-----------------------------------------------------------------*
     C                   ELSE
     C                   MOVE      *BLANK        ReturnPt
     C                   ENDIF
     C                   ENDSR     ReturnPt
      *-----------------------------------------------------------------*
      * エラー報告書の形式。
      *-----------------------------------------------------------------*
     OPRINT     E            NOTFOUND
     O                       TRNPRDNO
     O                                           29 'NOT IN PRDMAS FILE'

制御がエラー処理サブルーチンに渡されると、次のことが起こります。

レコード・ロック・エラーの検査は、PRDMAS の INFDS の *STATUS サブフィールドを、 レコード・ロック状況コードの値によって定義される ErrRecLock フィールドと突き合わせることによって 行われるということに注意してください。 他のエラーを定義し、 そのエラーを検査し、適切な処置を取ることによって、 他のタイプの入出力エラーを処理できるように INFSR を拡張することができます。

プログラム・エラー処理サブルーチンの使用

プログラム・エラーまたは例外を処理するためには、プログラム・エラー処理 サブルーチン (*PSSR) を作成することができます。 プログラム・エラーが起こると、次のようになります。

  1. プログラム状況データ構造が更新されます。
  2. 命令コードの 73 〜 74 桁目に標識が指定されていない 場合には、 エラーが処理され、制御が *PSSR に移されます。

    ファイル仕様書でキーワード INFSR の後に *PSSR を指定することによって、 ファイル・エラーの後でプログラム・エラー処理サブルーチンに明示的に制御を渡すことができます。

モジュールのプロシージャーのどれか (あるいはすべて) に *PSSR をコーディングすることができます。 各 *PSSR は、それがコーディングされているプロシージャーに固有です。

プログラムに *PSSR エラー処理サブルーチンを追加するためには、 次のステップを行ってください。

  1. 定義仕様書の 23 桁目に S を指定することによって、任意指定でプログラム 状況データ構造 (PSDS) を指定してください。
  2. *PSSR の演算項目 1 で BEGSR 命令を指定してください。
  3. 戻り点がある場合にはそれを指定して、サブルーチンの ENDSR 命令にそれを コーディングしてください。 サブプロシージャーでは、演算項目 2 はブランクでなければなりません。 演算項目 2 の有効な項目については、ENDSR 命令での戻り点の指定を参照してくださ い。
  4. プログラム・エラー処理サブルーチンの残りをコーディングしてください。 プログラム・エラー処理サブルーチンでは、どんな ILE RPG コンパイラー命令でも使用することができます。ENDSR 命令は、 プログラム・エラー処理サブルーチンの最後の仕様書でなければなりません。

図 133 には、 メイン・プロシージャーのプログラム・エラー処理サブルーチンの例を示して あります。

図 133. メイン・プロシージャーの *PSSR サブルーチンの例
      *-----------------------------------------------------------------*
      *  プログラム状況データ構造の対応する部分を定義します。           *
      *-----------------------------------------------------------------*
     D Psds           SDS
     D  Loc              *ROUTINE
     D  Err              *STATUS
     D  Parms            *PARMS
     D  Name             *PROC
      *-----------------------------------------------------------------*
      *  コーディングの本体部分
      *  ゼロによる除算が行なわれるとエラーが発生します。
      *  *PSSR サブルーチンに制御が渡されます。
      *-----------------------------------------------------------------*
      *=================================================================*
      * *PSSR: メイン・プロシージャーのエラー処理サブルーチン。状況が
      *        102 であるかどうかをチェックすることにより、ゼロによる
      *        除算エラーをチェックします。エラーがあれば、除数に 1 を
      *        加算し、*GETIN を ReturnPt に転送して続行します。
      *=================================================================*
     C     *PSSR         BEGSR
     C                   IF        Err = 102
     C                   ADD       1             Divisor
     C                   MOVE      '*GETIN'      ReturnPt          6
      *-----------------------------------------------------------------*
      *       予期しないエラーが起こったため、
      *       *CANCL を ReturnPt に転送してプロシージャーを終了させます。
      *-----------------------------------------------------------------*
     C                   ELSE
     C                   MOVE      '*CANCL'      ReturnPt
     C                   ENDIF
     C                   ENDSR     ReturnPt

プログラム状況データ構造は、定義仕様書で定義されます。 事前定義のサブフィールドの *STATUS, *ROUTINE, *PARMS, および *PROGRAM が指定され、 各サブフィールドには名前が割り当てられています。

*PSSR エラー処理サブルーチンは、演算仕様書でコーディングされています。 プログラム・エラーが起こると、ILE RPG は制御を *PSSR エラー処理サブルーチンに渡します。 このサブルーチンは、除数がゼロの除算命令が原因で例外が起こったかどうかを判別します。 そうであった場合には、除数 (Divisor) に 1 が加算され、 フィールド ReturnPt にリテラル '*DETC' が転送され、 明細演算ルーチンの始めからプログラムが処理を再開することを示します。

例外がゼロによる除算でなかった場合には、リテラル '*CANCL' が フィールド ReturnPt に転送され、プロシージャーが終了します。

図 134 および 図 135 では、 サブプロシージャーの類似したプログラム・エラー処理サブルーチンを コーディングする方法を示しています。1 つの例として、GOTO を、 他の例としては、RETURN 命令をコーディングします。

図 134. GOTO のある *PSSR サブルーチン のサブプロシージャーの例
      *-----------------------------------------------------------------*
      *  サブプロシージャー定義の開始
      *-----------------------------------------------------------------*
     P SubProc         B
     D SubProc         PI             5P 0
      ...
      *-----------------------------------------------------------------*
      *  回復コードを含むコーディング本体
      *-----------------------------------------------------------------*
     C      TryAgain     TAG
     C      X            DIV       Divisor       Result
     C                   Return    Result
      *-----------------------------------------------------------------*
      *  ゼロによる除算が行なわれるとエラーが発生します。
      *  *PSSR サブルーチンに制御が渡されます。
      *-----------------------------------------------------------------*
     C     *PSSR         BEGSR
      *-----------------------------------------------------------------*
      * これがゼロによる除算のエラーの場合は、除数に 1 を加算して、
      * 再試行します。
      *-----------------------------------------------------------------*
     C                   IF        Err = 102
     C                   ADD       1             Divisor
     C                   GOTO      TryAgain
     C                   ENDIF
      *-----------------------------------------------------------------*
      * 制御が ENDSR に達すると、プロシージャーは正常に実行されません。
      *-----------------------------------------------------------------*
     C                   ENDSR
     P                 E
図 135. RETURN のある *PSSR サブルーチン のサブプロシージャーの例
      *-----------------------------------------------------------------*
      *  サブプロシージャー定義の開始
      *-----------------------------------------------------------------*
     P SubProc         B
     D SubProc         PI             5P 0
      ...
      *-----------------------------------------------------------------*
      *  除算命令を含むコーディング本体
      *-----------------------------------------------------------------*
     C      X            DIV       Divisor       Result
     C                   Return    Result
      *-----------------------------------------------------------------*
      *  ゼロによる除算が行なわれるとエラーが発生します。
      *  *PSSR サブルーチンに制御が渡されます。
      *-----------------------------------------------------------------*
     C     *PSSR         BEGSR
      *-----------------------------------------------------------------*
      * これがゼロによる除算エラーの場合、サブプロシージャーから
      * 0 が戻されます。
      *-----------------------------------------------------------------*
     C                   IF        Err = 102
     C                   RETURN    0
     C                   ENDIF
      *-----------------------------------------------------------------*
      * 制御が ENDSR に達すると、プロシージャーは正常に実行されません。
      *-----------------------------------------------------------------*
     C                   ENDSR
     P                 E

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

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

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

図 136 には、*PSSR サブルーチン内でのループを避ける方法を 示すために例外を生成するように設計されたプログラム NOLOOP を示してあります。 このプログラムは例外を次の 2 回生成します。

  1. コードの本体で *PSSR に制御権を渡すため
  2. *PSSR 内部で潜在的にループを起こすため
図 136. エラー処理サブルーチンでのループの防止
      *=================================================================*
      * 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

図 136 のソースを使ってプログラムを作成し、そのデバッグを 始めるには、次の入力をします。

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 エラー処理サブルーチン内でも使用することができます。