Using a Condition Handler
- Code a condition handler to handle the RPG 'out-of-bounds' error
- Register a condition handler
- Deregister a condition handler
- Code a *PSSR error subroutine.
- RPGHDLR, which consists of a user-written condition handler for out-of-bound substring errors
- SHOWERR, which tests the RPGHDLR procedure.
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 1 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).
- Test to see if it is an out-of-bounds error by testing the message ID
- If it is, and if SHOWERR has indicated that out-of-bounds errors maybe ignored, it writes 'Handling...' to QSYSPRT and then sets the action to 'Resume'.
- Otheriwse, it writes out 'Percolating' to QSYSPRT, and then sets the action to 'Percolate'.
- Return.
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 2 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.
- Register the handler RPGHDLR using the subroutine RegHndlr. This subroutine calls the CEEHDLR API, passing it the procedure pointer to RPGHDLR.
- Indicate to RPGHDLR that the out-of-bounds error is allowed, and then
generate an out-of-bounds substring error, then set off the indicator so that
RPGHDLR will not allow any unexpected out-of-bounds string errors.
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.
- Generate an out-of-bounds array error.
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.
- Unregister the condition handler RPGHDLR via a call to CEEHDLU.
- Return
As with the RPGHDLR procedure, SHOWERR writes to QSYSPRT to show what is occurring as it is processed.
*-----------------------------------------------------------------*
* 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...'
- To create the procedure RPGHDLR, using the source shown in Figure 1,
type:
CRTRPGMOD MODULE(MYLIB/RPGHDLR)
- To create the procedure SHOWERR, using the source shown in Figure 2,
type:
CRTRPGMOD MODULE(MYLIB/SHOWERR)
- To create the program, ERRORTEST, type
CRTPGM PGM(MYLIB/ERRORTEST) MODULE(SHOWERR RPGHDLR)
- To run the program ERRORTEST, type:
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...