CEEMRCR—Move resume cursor
- 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.
- 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.
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.
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.
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;