次の例は以下のことを行う方法を示したものです。
この例は、次の 2 つのプロシージャーから成っています。
SHOWERR は主に RPGHDLR の働きを示すために設計されていますが、2 つが結合したプロシージャーは、ILE 例外処理が「どのように」行われるかを判別する上でも有用です。両方のプロシージャーは、処理されて時に起こる「処置」を QSYSPRT に 書き出します。 調べたい、ILE 例外処理の別の側面をシミュレートするために、これらのプロシージャーを変更することができます。
図 143 にはプロシージャー RPGHDLR のソースを示してありま す。 このプロシージャーは 3 つのプロシージャー・パラメーターを定義します。 すなわち、ILE 条件トークンの構造、SHOWERR と RPGHDLR 間の連絡域へのポインター、および可能な処置、再開またはパーコレートの 指示が入るフィールドです (RPGHDLR は例外をプロモートしません)。
RPGHDLR の基本ロジックは次のとおりです。
*=================================================================* * RPGHDLR: RPG 例外処理プロシージャー。 * * このプロシージャーは次のことを実行します。 * * RPG 範囲外エラー (RNX0100) の場合には、 * * 例外を処理します。 * * そうでない場合には、 * * 例外をパーコレートします。 * * また、実行したことを印刷します。 * * * * 注: これは SHOWERR プロシージャーの例外処理プロシージャー * * です。 * *=================================================================* FQSYSPRT O F 132 PRINTER D RPGHDLR PR D Parm1 LIKE(CondTok) D Parm2 * D Parm3 10I 0 D Parm4 LIKE(CondTok) *-----------------------------------------------------------------* * プロシージャー・パラメーター * * 1. 入力: 条件トークン構造 * * 2. 入力: 以下を含んでいる連絡域へのポインター * * a. 処理されているプロシージャーの PSDS へのポインター * * b. ストリング・エラーが有効かどうかを示す標識 * * 3. 出力: 例外に対して実行されるべき処置を * * 識別するコード * * 4. 出力: 条件をプロモートすることに決めた場合の新しい条件。 * * この処理プログラムは再開とパーコレートしか実行しない * * ので、このパラメーターを無視します。 * *-----------------------------------------------------------------* D RPGHDLR PI D InCondTok LIKE(CondTok) D pCommArea * D Action 10I 0 D OutCondTok LIKE(CondTok)
D CondTok DS BASED(pCondTok) D MsgSev 5I 0 D MsgNo 2A D 1A D MsgPrefix 3A D MsgKey 4A D CommArea DS BASED(pCommArea) D pPSDS * D AllowError 1N D PassedPSDS DS BASED(pPSDS) D ProcName 1 10 * * 処置コード: * D Resume C 10 D Percolate C 20 *-----------------------------------------------------------------* * 入力条件トークンをポイントする。 * *-----------------------------------------------------------------* C EVAL pCondTok = %ADDR(InCondTok) *-----------------------------------------------------------------* * サブストリング・エラーの場合は、ELSE パーコレートを処理します。 * * メッセージ番号 (MsgNo) の値は 16 進であることに注意。 * *-----------------------------------------------------------------* C EXCEPT C IF MsgPrefix = 'RNX' AND C MsgNo = X'0100' AND C AllowError = '1' C EXCEPT Handling C EVAL Action = Resume C ELSE C EXCEPT Perclating C EVAL Action = Percolate C ENDIF C RETURN *=================================================================* * プロシージャー出力 * *=================================================================* OQSYSPRT E O 'HDLR: In Handler for ' O ProcName OQSYSPRT E Handling O 'HDLR: Handling...' OQSYSPRT E Perclating O 'HDLR: Percolating...'
図 144 は、条件処理プログラム RPGHDLR が登録されている プロシージャー SHOWERR のソースを示します。
プロシージャー・パラメーターには、RPGHDLR へのプロシージャー・ポインター、およびモジュールの PSDS へのポインターを含む連絡域へのポインター、そして範囲外ストリング・エラーを無視できるかどうかを示す標識が含まれます。 さらに、エラーとなる可能性がある配列 ARR1 の定義、および ILE バインド可能 API の CEEHDLR および CEEHDLU によって使用されるパラメーター・リストの識別を必要とします。
プログラムの基本論理は次のとおりです。
処理プログラム RPGHDLR は自動的に呼び出されます。 この処理プログラムは例外を処理し、エラーの後の次の機械語 命令 で処理が再開されることを示します。 次の機械語命令が次の RPG 命令の始めにない場合があるということに注意して ください。
再び RPGHDLR が自動的に呼び出されます。 しかし今回は例外を処理できない ので、それをプロシージャーに関連した次の例外処理プログラム、 すなわち *PSSR エラー処理サブルーチンにパーコレートします。
*PSSR がプロシージャーを取り消します。
RPGHDLR プロシージャーと同様に、SHOWERR は QSYSPRT に書き出しを行って、 処理時に何が起こったかを示します。
*=================================================================* * SHOWERR: ユーザー定義の例外処理プログラムを使用した * * 例外処理を示します。 * *=================================================================* FQSYSPRT O F 132 PRINTER *-----------------------------------------------------------------* * CEEHDLR API のパラメーター定義は次のとおりです。最初の * * パラメーターは例外を処理するプロシージャーへのプロシージャー・ * * ポインターです。2 番目は例外処理プロシージャーに渡される * * 連絡域へのポインターです。この例では、 * * この連絡域にはこのモジュールの PSDS へのポインターと、 * * エラーが許されるかどうかを示す * * 標識が含まれています。 * * * * このプログラム (SHOWERR) が処理されたいかなるエラーも無視しない * * ようにするため、RPGHDLR が「許可」するであろうエラーを起こす * * 可能性のあるすべての命令の後で「エラー」標識をチェックします。 * * また、プログラムの終了時に、いかなるエラーも見逃さなかった * * ことを確認するためにチェックを行ないます。 * *-----------------------------------------------------------------* D pConHdlr S * PROCPTR D INZ(%paddr('RPGHDLR')) *-----------------------------------------------------------------* * 連絡域 * *-----------------------------------------------------------------* D CommArea DS NOOPT D pPsds * INZ(%ADDR(DSPsds)) D AllowError 1N INZ('0') *-----------------------------------------------------------------* * PSDS * *-----------------------------------------------------------------* D DSPsds SDS NOOPT D ProcName *PROC *-----------------------------------------------------------------* * エラーを起こすために使用される変数 * *-----------------------------------------------------------------* D Arr1 S 10A DIM(5) D Num S 5P 0 *-----------------------------------------------------------------* * CEEHDLR インターフェース *-----------------------------------------------------------------* D CEEHDLR PR D pConHdlr * PROCPTR D CommArea * CONST D Feedback 12A OPTIONS(*OMIT) *-----------------------------------------------------------------* * CEEHDLU インターフェース *-----------------------------------------------------------------* D CEEHDLU PR D pConHdlr * PROCPTR D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------* * 処理プログラムを登録し、エラーを生成します。 * *-----------------------------------------------------------------* C EXSR RegHndlr *-----------------------------------------------------------------* * サブストリング・エラーを生成します。 * * これはこの例で「許される」エラーです (RPGHDLR は、エラーの * * 後で次の命令に戻るための制御を許可するという、例外を処理 * * します)。 * * RPGHDLR は "AllowError" 標識がオンに設定されているとき以外 * * エラーを許しません。これは、例えば SCAN 命令が後で * * SHOWERR に追加された場合、RPGHDLR はデフォルトでエラーを * * 許可しないことを保証します。 * *-----------------------------------------------------------------* C Z-ADD -1 Num C EVAL AllowError = '1' C Num SUBST 'Hello' Examp 10 C EVAL AllowError = '0' *-----------------------------------------------------------------* * 処理プログラムによって例外が処理され、ここで * * 制御が再開されます。 * *-----------------------------------------------------------------* C EXCEPT ImBack *-----------------------------------------------------------------* * 配列の範囲外エラーを生成します。 * * これはこの例では「予想された」エラーではありません。 * *-----------------------------------------------------------------* C Z-ADD -1 Num C MOVE Arr1(Num) Arr1(Num) *-----------------------------------------------------------------* * この例外は処理プログラムでは処理されないので、 * * 制御はここには戻りません。この例外は * * パーコレートされ、制御は *PSSR で再開されます。 * *-----------------------------------------------------------------* *-----------------------------------------------------------------* * 処理プログラムの登録解除 * * 注: 処理プログラムが登録解除される前に例外が起こった場合 * * は、プロシージャーが取り消される時に自動的に * * 登録解除されます。 * *-----------------------------------------------------------------* C EXSR DeRegHndlr C SETON LR *=================================================================* * RegHdlr - 処理プログラムを登録する API の呼び出し * *=================================================================* C RegHndlr BEGSR C CALLP CEEHDLR(pConHdlr : %ADDR(CommArea) : *OMIT) C ENDSR *=================================================================* * DeRegHndlr - 処理プログラムを登録解除する API の呼び出し * *=================================================================* C DeRegHndlr BEGSR C CALLP CEEHDLU(pConHdlr : *OMIT) C ENDSR
*=================================================================* * *PSSR: プロシージャーのエラー処理サブルーチン * *=================================================================* C *PSSR BEGSR C EXCEPT InPssr C EXCEPT Cancelling C ENDSR '*CANCL' *=================================================================* * プロシージャー出力 * *=================================================================* OQSYSPRT E ImBack O 'I''m Back' OQSYSPRT E InPssr O 'In PSSR' OQSYSPRT E Cancelling O 'Cancelling...'
これらのプロシージャーを試したい場合には、次のステップに従ってください。
CRTRPGMOD MODULE(MYLIB/RPGHDLR)
CRTRPGMOD MODULE(MYLIB/SHOWERR)
CRTPGM PGM(MYLIB/ERRORTEST) MODULE(SHOWERR RPGHDLR)
OVRPRTF FILE(QSYSPRT) SHARE(*YES) CALL PGM(MYLIB/ERRORTEST)
出力を以下に示します。
HDLR: In Handler for SHOWERR HDLR: Handling... I'm Back HDLR: In Handler for SHOWERR HDLR: Percolating... In PSSR Cancelling...