CEEMRCR—Move resume cursor

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
Read syntax diagramSkip visual syntax diagram
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
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
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
Third example moving resume cursor using CEEMRCR

Examples

  1. 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;
    }
  2. 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.
  3. 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;