The following example shows you how to:
The example consists of two procedures:
While SHOWERR is designed primarily to show how RPGHDLR works, the two procedures combined are also useful for determining 'how' ILE exception handling works. Both procedures write to QSYSPRT the 'actions' which occur as they are processed. You might want to modify these procedures in order to simulate other aspects of ILE exception handling which you would like to explore.
Figure 143 shows the source for the procedure RPGHDLR. The procedure defines three procedure parameters: an ILE condition token structure, a pointer to a communication area between SHOWERR and RPGHDLR, and a field to contain the possible actions, resume or percolate. (RPGHDLR does not promote any exceptions).
The basic logic of RPGHDLR is the following:
*=================================================================*
* RPGHDLR: RPG exception handling procedure. *
* This procedure does the following: *
* Handles the exception if it is the RPG *
* out of bounds error (RNX0100) *
* otherwise *
* percolates the exception *
* It also prints out what it has done. *
* *
* Note: This is the exception handling procedure for the *
* SHOWERR procedure. *
*=================================================================*
FQSYSPRT O F 132 PRINTER
D RPGHDLR PR
D Parm1 LIKE(CondTok)
D Parm2 *
D Parm3 10I 0
D Parm4 LIKE(CondTok)
*-----------------------------------------------------------------*
* Procedure parameters *
* 1. Input: Condition token structure *
* 2. Input: Pointer to communication area containing *
* a. A pointer to the PSDS of the procedure being handled *
* b. An indicator telling whether a string error is valid *
* 3. Output: Code identifying actions to be performed on the *
* exception *
* 4. Output: New condition if we decide to promote the *
* condition. Since this handler only resumes and *
* percolates, we will ignore this parameter. *
*-----------------------------------------------------------------*
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
*
* Action codes are:
*
D Resume C 10
D Percolate C 20
*-----------------------------------------------------------------*
* Point to the input condition token *
*-----------------------------------------------------------------*
C EVAL pCondTok = %ADDR(InCondTok)
*-----------------------------------------------------------------*
* If substring error, then handle else percolate. *
* Note that the message number value (MsgNo) is in hex. *
*-----------------------------------------------------------------*
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
*=================================================================*
* Procedure Output *
*=================================================================*
OQSYSPRT E
O 'HDLR: In Handler for '
O ProcName
OQSYSPRT E Handling
O 'HDLR: Handling...'
OQSYSPRT E Perclating
O 'HDLR: Percolating...'
Figure 144 shows the source for the procedure SHOWERR, in which the condition handler RPGHDLR is registered.
The procedure parameters include a procedure pointer to RPGHDLR and a pointer to the communication area which contains a pointer to the module's PSDS and an indicator telling whether the out-of-bounds string error can be ignored. In addition, it requires a definition for the error-prone array ARR1, and identification of the parameter lists used by the ILE bindable APIs CEEHDLR and CEEHDLU.
The basic logic of the program is as follows:
The handler RPGHDLR is automatically called. It handles the exception, and indicates that processing should resumes in the next machine instruction following the error. Note that the next machine instruction may not be at the beginning of the next RPG operation.
Again, RPGHDLR is automatically called. However, this time it cannot handle the exception, and so it percolates it to the next exception handler associated with the procedure, namely, the *PSSR error subroutine.
The *PSSR cancels the procedure.
As with the RPGHDLR procedure, SHOWERR writes to QSYSPRT to show what is occurring as it is processed.
*=================================================================*
* SHOWERR: Show exception handling using a user-defined *
* exception handler. *
*=================================================================*
FQSYSPRT O F 132 PRINTER
*-----------------------------------------------------------------*
* The following are the parameter definitions for the CEEHDLR *
* API. The first is the procedure pointer to the *
* procedure which will handle the exception. The second *
* is a pointer to a communication area which will be passed *
* to the exception handling procedure. In this example, this *
* area will contain a pointer to the PSDS of this module, and *
* an indicator telling whether an error is allowed. *
* *
* We should make sure this program (SHOWERR) does not ignore any *
* handled errors, so we will check the 'Error' indicator after *
* any operation that might cause an error that RPGHDLR will *
* "allow". We will also check at the end of the program to make *
* sure we didn't miss any errors. *
*-----------------------------------------------------------------*
D pConHdlr S * PROCPTR
D INZ(%paddr('RPGHDLR'))
*-----------------------------------------------------------------*
* Communication area *
*-----------------------------------------------------------------*
D CommArea DS NOOPT
D pPsds * INZ(%ADDR(DSPsds))
D AllowError 1N INZ('0')
*-----------------------------------------------------------------*
* PSDS *
*-----------------------------------------------------------------*
D DSPsds SDS NOOPT
D ProcName *PROC
*-----------------------------------------------------------------*
* Variables that will be used to cause errors *
*-----------------------------------------------------------------*
D Arr1 S 10A DIM(5)
D Num S 5P 0
*-----------------------------------------------------------------*
* CEEHDLR Interface *
*-----------------------------------------------------------------*
D CEEHDLR PR
D pConHdlr * PROCPTR
D CommArea * CONST
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------*
* CEEHDLU Interface *
*-----------------------------------------------------------------*
D CEEHDLU PR
D pConHdlr * PROCPTR
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------*
* Register the handler and generate errors *
*-----------------------------------------------------------------*
C EXSR RegHndlr
*-----------------------------------------------------------------*
* Generate a substring error *
* This is an "allowed" error for this example (RPGHDLR *
* handles the exception, allowing control to return to the *
* next instruction after the error). *
* RPGHDLR will not allow the error unless the "AllowError" *
* indicator is set on. This ensures that if, for example, *
* a SCAN operation is added to SHOWERR later, RPGHDLR will *
* not by default allow it to have an error. *
*-----------------------------------------------------------------*
C Z-ADD -1 Num
C EVAL AllowError = '1'
C Num SUBST 'Hello' Examp 10
C EVAL AllowError = '0'
*-----------------------------------------------------------------*
* The exception was handled by the handler and control *
* resumes here. *
*-----------------------------------------------------------------*
C EXCEPT ImBack
*-----------------------------------------------------------------*
* Generate an array out of bounds error *
* This is not an "expected" error for this example. *
*-----------------------------------------------------------------*
C Z-ADD -1 Num
C MOVE Arr1(Num) Arr1(Num)
*-----------------------------------------------------------------*
* The exception was not handled by the handler, so, *
* control does not return here. The exception is *
* percolated and control resumes in the *PSSR. *
*-----------------------------------------------------------------*
*-----------------------------------------------------------------*
* Deregister the handler *
* Note: If an exception occurs before the handler is *
* deregistered, it will be automatically deregistered *
* when the procedure is cancelled. *
*-----------------------------------------------------------------*
C EXSR DeRegHndlr
C SETON LR
*=================================================================*
* RegHdlr - Call the API to register the Handler *
*=================================================================*
C RegHndlr BEGSR
C CALLP CEEHDLR(pConHdlr : %ADDR(CommArea) : *OMIT)
C ENDSR
*=================================================================*
* DeRegHndlr - Call the API to unregister the Handler *
*=================================================================*
C DeRegHndlr BEGSR
C CALLP CEEHDLU(pConHdlr : *OMIT)
C ENDSR
*=================================================================*
* *PSSR: Error Subroutine for the procedure *
*=================================================================*
C *PSSR BEGSR
C EXCEPT InPssr
C EXCEPT Cancelling
C ENDSR '*CANCL'
*=================================================================*
* Procedure Output *
*=================================================================*
OQSYSPRT E ImBack
O 'I''m Back'
OQSYSPRT E InPssr
O 'In PSSR'
OQSYSPRT E Cancelling
O 'Cancelling...'
If you want to try these procedures, follow these steps:
CRTRPGMOD MODULE(MYLIB/RPGHDLR)
CRTRPGMOD MODULE(MYLIB/SHOWERR)
CRTPGM PGM(MYLIB/ERRORTEST) MODULE(SHOWERR RPGHDLR)
OVRPRTF FILE(QSYSPRT) SHARE(*YES)
CALL PGM(MYLIB/ERRORTEST)
The output is shown below:
HDLR: In Handler for SHOWERR
HDLR: Handling...
I'm Back
HDLR: In Handler for SHOWERR
HDLR: Percolating...
In PSSR
Cancelling...