|
CEEHDLR
registers a user-written condition handler for the current stack frame.
The user condition handler is invoked when: - It is registered for the current stack frame by CEEHDLR, and
- The Language Environment condition
manager requests the condition handler associated with the current
stack frame handle the condition.
Language Environment places
the user-written condition handlers associated with each stack frame
in a queue. The queue can be empty at any given time. The Language Environment condition
manager invokes the registered condition handlers in LIFO (last in,
first out) order to handle the condition.
The opposite of CEEHDLR,
which registers a user-written condition handler, is CEEHDLU, which
unregisters the handler. You do not necessarily need to use CEEHDLU
to remove user-written condition handlers you registered with CEEHDLR.
Any user-written condition handlers created through CEEHDLR and not
unregistered by CEEHDLU are unregistered automatically by Language Environment, but
only when the associated stack frame is removed from the stack.
Language Environment condition
handlers are driven only for synchronous conditions.
Syntax
>>-CEEHDLR--(--routine--,--token--,--fc--)---------------------><
- routine (input)
- An entry variable or entry constant for the routine called to
process the condition. The entry variable or constant must be passed
by reference. The routine must be an external routine; that is, it
must not be a nested routine.
- token (input)
- A fullword integer of information you want passed to your user
handler each time it is called. This can be a pointer or any other
fullword integer you want to pass.
- fc (output)
- A 12-byte feedback code, optional in some languages, that indicates
the result of this service. If you choose to omit this parameter,
refer to Invoking callable services for the appropriate
syntax to indicate that the feedback code was omitted.
The following symbolic conditions can result from this service:
Code |
Severity |
Message number |
Message text |
---|
CEE000 |
0 |
— |
The service completed successfully. |
CEE080 |
1 |
0256 |
The user-written condition handler routine specified was already
registered for this stack frame. It was registered again. |
CEE081 |
3 |
0257 |
The routine specified contained an invalid entry variable. |
Usage notes - PL/I MTF
consideration—CEEHDLR is not supported in PL/I MTF
applications. This includes any CEEHDLR service called from a COBOL program
in the application.
- COBOL consideration—You should not call CEEHDLR from a nested
COBOL program.
- z/OS UNIX consideration—In
multithread applications, CEEHDLR affects only the calling thread.
- C consideration—The
CEEHDLR service does not save Writeable Static Area (WSA) information
about the user handler, so it's possible that the user handler will
be given control with the wrong WSA. Specifically, the user handlers
on the stack will be invoked with the WSA of the routine that incurred
the condition. The preferred method of handling conditions from a C application
is to use C signal
handlers.
Examples - Following is an example of CEEHDLR called by C/C++.
/*Module/File Name: EDCHDLR */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <leawi.h>
#include <ceeedcct.h>
#ifdef __cplusplus
extern "C" {
#endif
void handler(_FEEDBACK *,_INT4 *,_INT4 *,_FEEDBACK *);
#ifdef __cplusplus
}
#endif
int main(void) {
_FEEDBACK fc;
_ENTRY routine;
_INT4 token;
/* set the routine structure to point to the handler */
/* and use CEEHDLR to register the user handler */
token = 99;
routine.address = (_POINTER)&handler;
routine.nesting = NULL;
CEEHDLR(&routine,&token,&fc);
/* verify that CEEHDLR was successful */
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEEHDLR failed with message number %d\n",
fc.tok_msgno);
exit (2999);
}
/*
⋮
*/
}
/*******************************************************/
/* handler is a user condition handler */
/*******************************************************/
void handler(_FEEDBACK *fc, _INT4 *token, _INT4 *result,
_FEEDBACK *newfc) {
/*
⋮
*/
}
- Following is an example of CEEHDLR called by a COBOL program
that registers a handler routine.
CBL LIB,QUOTE
*Module/File Name: IGZTHDLR
***********************************************
** **
** CBLHDLR - Call CEEHDLR to register a user **
** condition handler **
** **
***********************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. CBLHDLR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 ROUTINE PROCEDURE-POINTER.
01 TOKEN PIC S9(9) BINARY.
01 SEV PIC S9(4) BINARY.
01 MSGNO PIC S9(4) BINARY.
01 CASE PIC S9(4) BINARY.
01 SEV2 PIC S9(4) BINARY.
01 CNTRL PIC S9(4) BINARY.
01 FACID PIC X(3).
01 ISINFO PIC S9(9) BINARY.
01 QDATA PIC S9(9) BINARY.
01 FC.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) BINARY.
04 Msg-No PIC S9(4) BINARY.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) BINARY.
04 Cause-Code PIC S9(4) BINARY.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) BINARY.
01 CONDTOK.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) BINARY.
04 Msg-No PIC S9(4) BINARY.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) BINARY.
04 Cause-Code PIC S9(4) BINARY.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) BINARY.
PROCEDURE DIVISION.
PARA-CBLHDLR.
SET ROUTINE TO ENTRY "HANDLER".
CALL "CEEHDLR" USING ROUTINE, TOKEN, FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEEHDLR failed with msg "
Msg-No of FC UPON CONSOLE
STOP RUN
END-IF.
* RAISE A SIGNAL
PARA-CBLSGL.
*************************************************
** Call CEENCOD with the values assigned above **
** to build a condition token "CONDTOK" **
** Set CONDTOK to sev=3, msgno=1 facid=CEE. We **
** raise a sev 3 to ensure our handler is driven*
*************************************************
MOVE 3 TO SEV.
MOVE 1 TO MSGNO.
MOVE 1 TO CASE.
MOVE 3 TO SEV2.
MOVE 1 TO CNTRL.
MOVE "CEE" TO FACID.
MOVE 0 TO ISINFO.
CALL "CEENCOD" USING SEV, MSGNO, CASE,
SEV2, CNTRL, FACID, ISINFO, CONDTOK, FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEENCOD failed with msg "
Msg-No of FC UPON CONSOLE
STOP RUN
END-IF.
*************************************************
** Call CEESGL to signal the condition with **
** the condition token and qdata described **
** in CONDTOK and QDATA **
*************************************************
MOVE 0 TO QDATA.
CALL "CEESGL" USING CONDTOK, QDATA, FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEESGL failed with msg "
Msg-No of FC UPON CONSOLE
STOP RUN
END-IF.
GOBACK.
- Following is an example of a COBOL user-written
condition handler that is registered by CBLHDLR and unregistered by
CBLHDLU.
CBL LIB,QUOTE,NOOPT,NODYNAM
*Module/File Name: IGZTHAND
*************************************************
** **
** DRVHAND - Drive sample program for COBOL **
** user-written condition handler. **
** **
*************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. DRVHAND.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 ROUTINE PROCEDURE-POINTER.
01 DENOMINATOR PIC S9(9) BINARY.
01 NUMERATOR PIC S9(9) BINARY.
01 RATIO PIC S9(9) BINARY.
01 TOKEN PIC S9(9) BINARY VALUE 0.
01 FC.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) BINARY.
04 Msg-No PIC S9(4) BINARY.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) BINARY.
04 Cause-Code PIC S9(4) BINARY.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) BINARY.
PROCEDURE DIVISION.
REGISTER-HANDLER.
************************************************
** Register handler **
************************************************
SET ROUTINE TO ENTRY "HANDLER".
CALL "CEEHDLR" USING ROUTINE , TOKEN , FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEEHDLR failed with msg "
Msg-No of FC UPON CONSOLE
STOP RUN
END-IF.
RAISE-CONDITION.
************************************************
** Cause a zero-divide condition. **
************************************************
MOVE 0 TO DENOMINATOR.
MOVE 1 TO NUMERATOR.
DIVIDE NUMERATOR BY DENOMINATOR
GIVING RATIO.
DISPLAY "Execution continues following "
"divide-by-zero exception".
UNREGISTER-HANDLER.
************************************************
** UNregister handler **
************************************************
CALL "CEEHDLU" USING ROUTINE, TOKEN, FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEEHDLU failed with msg "
Msg-No of FC UPON CONSOLE
END-IF.
STOP RUN.
END PROGRAM DRVHAND.
IDENTIFICATION DIVISION.
PROGRAM-ID. HANDLER.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01 TOKEN PIC S9(9) BINARY.
01 RESULT PIC S9(9) BINARY.
88 RESUME VALUE 10.
01 CURCOND.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) BINARY.
04 Msg-No PIC S9(4) BINARY.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) BINARY.
04 Cause-Code PIC S9(4) BINARY.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) BINARY.
01 NEWCOND.
02 Condition-Token-Value.
COPY CEEIGZCT.
03 Case-1-Condition-ID.
04 Severity PIC S9(4) BINARY.
04 Msg-No PIC S9(4) BINARY.
03 Case-2-Condition-ID
REDEFINES Case-1-Condition-ID.
04 Class-Code PIC S9(4) BINARY.
04 Cause-Code PIC S9(4) BINARY.
03 Case-Sev-Ctl PIC X.
03 Facility-ID PIC XXX.
02 I-S-Info PIC S9(9) BINARY.
PROCEDURE DIVISION USING CURCOND, TOKEN,
RESULT, NEWCOND.
PARA-HANDLER.
DISPLAY "Entered user handler for condition"
" with message number " Msg-No Of CURCOND
" -- will resume execution".
SET RESUME TO TRUE.
GOBACK.
END PROGRAM HANDLER.
- Following is an example of a PL/I program
to handle divide-by-zero condition.
*Process macro;
/* Module/File Name: IBMHDLR */
/****************************************************/
/* */
/* EXCOND .-> DIVZERO */
/* - register handler | - force a divide-by-0 */
/* - call DIVZERO --' */
/* ==> "resume point" */
/* - unregister handler */
/* USRHDLR: */
/* - if divide-by-zero then */
/* - move resume cursor */
/* - resume at "resume" */
/* point */
/* */
/****************************************************/
Excond :Proc Options(Main);
/**************************************************/
/* Important elements are found in these includes */
/* - feedback declaration */
/* - fbcheck macro call */
/* - condition tokens such as CEE000 */
/* - entry declarations such as ceehdlr */
/**************************************************/
%include ceeibmct;
%include ceeibmaw;
dcl Usrhdlr external entry;
dcl 1 fback feedback;
dcl divisor fixed bin(31);
dcl token fixed bin(31);
/*********************************************/
/* Register a user-written condition handler */
/*********************************************/
token = 97;
Call ceehdlr(Usrhdlr, token, fback);
If fbcheck (fback, cee000) then
display ('MAIN: registered USRHDLR');
else
do;
display ('CEEHDLR failed with message number ' ||
fback.MsgNo);
stop;
end;
/*********************************************/
/* Call DIVZERO to divide by zero */
/* and drive USRHDLR */
/*********************************************/
divisor = 0;
call divzero (divisor);
display ('MAIN: resumption after DIVZERO');
/*********************************************/
/* Unregister the user condition handler */
/*********************************************/
Call ceehdlu (Usrhdlr, fback);
If fbcheck (fback, cee000) then
display ('MAIN: unregistered USRHDLR');
else
do;
display ('CEEHDLU failed with message number ' ||
fback.MsgNo);
stop;
end;
/*********************************************/
/* Subroutine that simply raises ZERODIVIDE */
/*********************************************/
divzero: proc (arg);
dcl arg fixed bin(31);
display(' DIVZERO: starting.');
arg = 1 / arg;
display(' DIVZERO: Returning to its caller');
end divzero;
end Excond;
- Following is an example of CEEHDLR called by PL/I.
AHDL TITLE 'Main program that registers a handler'
*
* Symbolic Register Definitions and Usage
*
R0 EQU 0 Parm list addr (CMS only)
R1 EQU 1 Parm list addr, 0=no parms
R10 EQU 10 Base reg for executable code
R12 EQU 12 Language Environment Common Anchor Area addr
R13 EQU 13 Dynamic Storage Area addr
R14 EQU 14 Return point addr
R15 EQU 15 Entry point address
*
* Prologue
*
CEEHDLRA CEEENTRY AUTO=DSASIZ, Main memory to obtain *
MAIN=YES, This program is a MAIN prog *
PPA=PPA1, Our Program Prolog Area *
BASE=R10 Base reg for executable code
USING CEECAA,R12 Addressing for LE/370 CAA
USING CEEDSA,R13 Addressing for dynamic data
*
* Announce ourselves
*
WTO 'CEEHDLRA Says "HELLO"',ROUTCDE=11
*
* Register User Handler
*
LA R1,USRHDLPP Get addr of proc-ptr to Hdlr
ST R1,PARM1 Make it 1st parameter
LA R1,TOKEN Get addr of 32-bit token
ST R1,PARM2 Make it 2nd parameter
LA R1,FEEDBACK Get addr of feedback code
ST R1,PARM3 Make it 3rd parameter
LA R1,HDLRPLST Point to CEEHDLR's parm list
CALL CEEHDLR Invoke CEEHDLR service
CLC FEEDBACK,=XL12'00' Check for success..
BE HDLRGOOD Skip diagnostics if success
* Failure.. issue diagnostics
WTO '**** Call to CEEHDLR failed ****', *
ROUTCDE=11
ABEND 1,DUMP Terminate program with Dump
HDLRGOOD EQU * Handler registered OK
* ... code covered by User-Written Handler goes here...
* Un-Register User Handler
*
LA R1,USRHDLPP Get addr of proc-ptr to Hdlr
ST R1,HDLUPRM1 Make it 1st parameter
LA R1,HDLUFBC Address for feedback code
ST R1,HDLUPRM2 Make it 2nd parameter
LA R1,HDLUPLST Point to CEEHDLU parm list
CALL CEEHDLU Invoke CEEHDLU service
* Bid a fond farewell
WTO 'CEEHDLRA Says "GOOD-BYE"',ROUTCDE=11
*
* Epilogue
*
CEETERM RC=4,MODIFIER=1 Terminate program
*
* Program Constants and Local Static Variables
*
USRHDLPP DC V(USRHDLR),A(0) Procedure-ptr to Handlr
*
LTORG , Place Literal Pool here
EJECT
PPA1 CEEPPA , Our Program Prolog Area
EJECT
CEEDSA , Map CEE Dynamic Save Area
*
* Local Automatic (Dynamic) Storage.
*
HDLRPLST DS 0F
PARM1 DS A Addr of User-written Handler
PARM2 DS A Addr of 32-bit Token
PARM3 DS A Addr of feedback code
*
HDLUPLST DS 0F
HDLUPRM1 DS A Addr of User-written Handler
HDLUPRM2 DS A Addr of feedback code
*
TOKEN DS F 32-bit Token: fullword whose
* *value* will be passed
* to the user handler
* each time it is called.
FEEDBACK DS CL12 CEEHDLR Feedback code
*
HDLUFBC DS CL12 CEEHDLU Feedback code
*
DSASIZ EQU *-CEEDSA Length of DSA
EJECT
CEECAA , Map LE370 Common Anchor Area
END CEEHDLRA
|