|
CEEMRCR
moves the resume cursor to a position relative to the current position
of the handle cursor. The actions supported are: - Moving the resume cursor to the call return point of the routine
registering the executing condition handler.
- Moving the resume cursor to the caller of the routine registering
the executing condition handler.
Initially, the resume cursor is placed after the instruction
that caused the condition. Whenever CEEMRCR moves the resume cursor
and passes stack frames, associated exit routines are invoked. Note
that “exit routine” refers to user condition handlers as well as language-specific
condition handlers. In
addition, any associated user condition handlers are unregistered.
The movement direction is always toward earlier stack frames, never
toward more recent stack frames. The movement occurs only after the
condition handler returns to the Language Environment condition
manager.
Multiple calls to CEEMRCR yield the net results of
the calls; that is, if two calls move the resume cursor to different
places for the same stack frame, the most restrictive call (that closest
to the earliest stack frame) is used for that stack frame.
Moving
the resume cursor to a particular stack frame: - Cancels all stack frames from the previous resume point up to
but not including the new resume point
- Unregisters any user condition handlers registered for the canceled
stack frames
Syntax
>>-CEEMRCR--(--type_of_move--,--fc--)--------------------------><
- type_of_move (input)
- A
fullword binary signed integer indicating the target of the resume
cursor movement. The possible values for type_of_move are:
- 0
- Move the resume cursor to the call return point of the stack frame
associated with the handle cursor.
- 1
- Move the resume cursor to the call return point of the stack frame
prior to the stack frame associated with the handle cursor. The handle
cursor is moved to the most recently established condition handler
of the stack frame. The new resume cursor position now points to this
condition handler for the stack frame. Do not use a type_of_move value
of 1 if the caller of the stack frame associated with the handle cursor
is a nested COBOL program.
Modifying the resume cursor to point to stack frame
0 is not allowed. You cannot move the resume cursor beyond the earliest
stack frame.
- 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. |
CEE07U |
1 |
0254 |
The first parameter passed to CEEMRCR was not 0 or 1. |
CEE083 |
3 |
0259 |
A move to stack frame zero using CEEMRCR was attempted from
a MAIN routine. |
CEE084 |
3 |
0260 |
No condition was active when a call to a condition management
routine was made. The requested function was not performed. |
CEE08L |
1 |
0277 |
CEEMRCR was called to perform an unnecessary move. |
Usage notes - PL/I MTF
consideration—CEEMRCR is not supported in PL/I MTF
applications. This includes any CEEHDLR service called from a COBOL program
in the application.
- z/OS UNIX considerations—In
multithread applications, CEEMRCR affects only the calling thread.
You can use CEEMRCR only within the thread's call chain.
Illustration of CEEMRCR Usage The following
three figures illustrate how you can move the resume cursor by using
the CEEMRCR service.
In Figure 1,
routine A calls routine B, which in turn calls C, which calls D. User
condition handlers are registered in routines B and C.
When
a condition is raised in routine D, the Language Environment condition
manager passes control to the user condition handler established for
routine C. The handle cursor now points to the stack frame for routine
C. Routine C percolates the condition.
The handle cursor now
points to the stack frame for routine B. The next user condition handler
to gain control is that one established for routine B; it recognizes
the condition and issues a resume by calling CEEMRCR.
A 0 type_of_move,
meaning move the resume cursor to the stack frame associated with
the handle cursor, causes control to resume at the call return point
in routine B, the instruction immediately following the call to routine
C. A 1 type_of_move, meaning move the resume
cursor to the call return point of the stack frame immediately preceding
the one to which the handle cursor points, moves the resume cursor
to the instruction immediately following a call in routine A to routine
B.
Figure 1. First example moving
resume cursor using CEEMRCR
The same scenario is illustrated in Figure 2, except that HDLR2 issues a resume
for the signaled condition rather than percolating it. HDLR1 never
gains control. Because the handle cursor now points to the stack frame
for routine C, a 0 type_of_move causes control
to resume at the call return point in routine C, the instruction immediately
following the call to routine D. A 1 type_of_move moves
the resume cursor to the instruction immediately following a call
in routine B to routine C.
Figure 2. Second example moving resume
cursor using CEEMRCR
In Figure 3, the user condition handlers are established
for routines C and D. When a condition is raised in routine D, only
a 1 type_of_move is permitted. A 0 type_of_move results
in error warning message CEE0277.
Figure 3. Third example moving resume cursor using CEEMRCR
Examples - Following is an example of CEEMRCR
called by C/C++.
/*Module/File Name: EDCMRCR */
#include <stdio.h>
#include <string.h>
#include <leawi.h>
#include <stdlib.h>
#include <ceeedcct.h>
#ifdef __cplusplus
extern "C" {
#endif
void handler(_FEEDBACK *,_INT4 *,_INT4 *,_FEEDBACK *);
#ifdef __cplusplus
}
#endif
void b(void);
int main(void) {
/*
⋮ */
b();
/* the CEEMRCR call in the handler will place the */
/* resume cursor at this point. */
/*
⋮ */
}
void b(void) {
_FEEDBACK fc,condtok;
_ENTRY routine;
_INT4 token,qdata;
_INT2 c_1,c_2,cond_case,sev,control;
_CHAR3 facid;
_INT4 isi;
/* register the condition handler */
token = 99;
routine.address = (_POINTER)&handler;;
routine.nesting = NULL;
CEEHDLR(&routine,&token,&fc);
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEEHDLR failed with message number %d\n",
fc.tok_msgno);
exit (2999);
}
/*
⋮ */
/* set up the condition using CEENCOD */
c_1 = 3;
c_2 = 2523;
cond_case = 1;
sev = 3;
control = 0;
memcpy(facid,"CEE",3);
isi = 0;
CEENCOD(&c_1,&c_2,&cond_case,&sev,&control,;
facid,&isi,&condtok,&fc);
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEENCOD failed with message number %d\n",
fc.tok_msgno);
exit(2999);
}
/* signal the condition */
CEESGL(&condtok,&qdata,&fc);
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEESGL failed with message number %d\n",
fc.tok_msgno);
exit(2999);
}
/*
⋮
*/
}
void handler(_FEEDBACK *fc, _INT4 *token, _INT4 *result,
_FEEDBACK *newfc) {
_FEEDBACK cursorfc, orig_fc;
_INT4 type;
/* .
.
. */
/* move the resume cursor to the caller of the */
/* routine that registered the condition handler */
type = 1;
CEEMRCR(&type,&cursorfc);
if ( _FBCHECK ( cursorfc , CEE000 ) != 0 ) {
printf("CEEMRCR failed with message number %d\n",
cursorfc.tok_msgno);
exit (2999);
}
printf("condition handled\n");
*result = 10;
return;
}
- Following is an example of CEEMRCR called by COBOL.
CBL LIB,QUOTE
*Module/File Name: IGZTMRCR
************************************************
** **
** CBLMAIN - Main for sample program for **
** CEEMRCR. **
** **
************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. CBLMAIN.
PROCEDURE DIVISION.
CALL "DRVMRCR"
DISPLAY "Resumed execution in the CALLER "
"of the routine which registered the "
"handler"
GOBACK.
END PROGRAM CBLMAIN.
************************************************
** **
** DRVMRCR - Drive sample program CEEMRCR. **
** **
************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. DRVMRCR.
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 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 QDATA 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.
************************************************
** Register handler **
************************************************
SET ROUTINE TO ENTRY "CBLMRCR".
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.
************************************************
** Signal a condition **
************************************************
MOVE 1 TO QDATA.
SET CEE001 of CONDTOK to TRUE.
MOVE ZERO to I-S-Info of CONDTOK.
CALL "CEESGL" USING CONDTOK, QDATA, FC.
IF CEE000 of FC THEN
DISPLAY "**** Resumed execution in the "
"routine which registered the handler"
ELSE
DISPLAY "CEESGL failed with msg "
Msg-No of FC UPON CONSOLE
END-IF.
************************************************
** 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 DRVMRCR.
************************************************
** **
** CBLMRCR - Invoke CEEMRCR to Move resume **
** cursor relative to handle cursor **
** **
************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. CBLMRCR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MOVETYP PIC S9(9) BINARY.
01 DEST PIC S9(9) BINARY VALUE 2.
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 FC2.
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.
LINKAGE SECTION.
01 CURRENT-CONDITION.
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 TOKEN PIC X(4).
01 RESULT-CODE PIC S9(9) BINARY.
88 RESUME VALUE +10.
88 PERCOLATE VALUE +20.
88 PROMOTE VALUE +30.
01 NEW-CONDITION.
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 CURRENT-CONDITION,
TOKEN, RESULT-CODE,
NEW-CONDITION
************************************************
** Move the resume cursor to the caller of **
** the routine that registered the condition **
** handler **
************************************************
MOVE 1 TO MOVETYP.
CALL "CEEMRCR" USING MOVETYP , FC.
IF NOT CEE000 of FC THEN
DISPLAY "CEEMRCR failed with msg "
Msg-No of FC UPON CONSOLE
CALL "CEEMSG" USING FC, DEST, FC2
IF NOT CEE000 of FC2 THEN
DISPLAY "CEEMSG failed with msg "
Msg-No of FC2 UPON CONSOLE
MOVE FC TO NEW-CONDITION
SET PROMOTE TO TRUE
GOBACK
END-IF.
SET RESUME TO TRUE.
GOBACK.
END PROGRAM CBLMRCR.
- Following is an example of a PL/I to
handle divide-by-zero condition.
*Process macro;
/* Module/File Name: IBMMRCR */
/****************************************************/
/* */
/* Usrhdlr - the user handler routine. */
/* Handle DIVIDE-BY-ZERO conditions, */
/* percolate all others. */
/* */
/****************************************************/
Usrhdlr: Proc (@condtok, @token, @result, @newcond)
options(byvalue);
%include ceeibmct;
%include ceeibmaw;
/* Parameters */
dcl @condtok pointer;
dcl @token pointer;
dcl @result pointer;
dcl @newcond pointer;
dcl 1 condtok based(@condtok) feedback;
dcl token fixed bin(31) based(@token);
dcl result fixed bin(31) based(@result);
dcl 1 newcond based(@newcond) feedback;
dcl 1 fback feedback;
dcl move_type fixed bin(31);
dcl resume fixed bin(31) static initial(10);
dcl percolate fixed bin(31) static initial(20);
dcl promote fixed bin(31) static initial(30);
dcl promote_sf fixed bin(31) static initial(31);
display ('>>> USRHDLR: Entered user handler');
display ('>>> USRHDLR: passed token value is ' ||
token);
/* Check if this is the divide-by-zero token */
if fbcheck (condtok, cee349) then
do;
move_type = 0;
call ceemrcr (move_type, fback);
If fbcheck (fback, cee000) then
do;
result = resume;
display ('>>> USRHDLR: Resuming execution');
end;
else
do;
display
('CEEMRCR failed with message number ' ||
fback.MsgNo);
stop;
end;
end;
else /* something besides div-zero token */
do;
result = percolate;
display ('>>> USRHDLR: Percolating it');
end;
end Usrhdlr;
|