70h UT$ENTR establish a control region
Input X register - Address of routine to be entered.
D register - Parameter to be passed to the routine.
Output B register - Code number (generally an error code).
C-flag - Clear if B register is zero, else set.
Description

Allows a routine at X to be called in such a way that it may be exited from any of the routines nested within it. The parameter in D is passed to the routine at X.

The most important use for UT$ENTR (together with UT$LEAV) is for error handling: they can mimic the ON ERROR and RAISE facilities in OPL.

UT$ENTR establishes a new control region, meaning that an entered routine can be terminated early by a call to UT$LEAV. That is, any of the routines (to any depth) used within the entered routine can call UT$LEAV which will cause 'immediate' return to the instruction after the call to UT$ENTR. The B register will then contain the value passed to UT$LEAV.

So, in the same way that an 'RTS' instruction causes control to return from a normal subroutine to the calling routine, the call to UT$LEAV causes control to return from within UT$ENTR to the routine that called UT$ENTR. In both cases the stack is adjusted appropriately for return.

Calls to UT$ENTR can be nested to any depth, with a control region for each call. UT$LEAV dis-establishes only the most recently established region, returning to the instruction after the last UT$ENTR call.

Note that a new control region is disestablished either by normal return from UT$ENTR, or by a call to UT$LEAV within the new region (unless called within a nested control region).

The entered routine must return an appropriate code number (generally 0 to indicate non-error) in the B register.

The locations UTW_S1 through UTW_S5 may be used for passing parameters to the entered routine. UTW_S0 is corrupted prior to entry, however.

See also UT$LEAV.

This routine is best illustrated by the examples.

Example To enter ROUTINE_1, which calls other routines, any of which may call UT$LEAV on error. Pass the value 1 to ROUTINE_1.
ENTER_ROUTINE_1:
        LDX     #ROUTINE_1  ; UT$ENTR calls the routine at address X
        LDD     #1          ; Set parameter for ROUTINE_1
        OS      UT$ENTR     ; Establish new control region
; Region now dis-established
        BCS     ERROR       ; On error, B set to error code, C-flag set
        RTS

ROUTINE_1:
        STD     ROUTINE_1_PARAMETER
        BCC     NO_ERROR_1
        LDAB    #ERROR_CODE_1
        OS      UT$LEAV ; return B to ENTER_ROUTINE_1, setting C-flag
NO_ERROR_1:
        JSR     ROUTINE_2   ; if either of these 2 routines call 
        JSR     ROUTINE_3   ;   UT$LEAV, control doesn't return to 
                            ;   this routine
        CLRB                ; B must be cleared to indicate non-error
        RTS

ROUTINE_2:
        .
        .
        BCC     NO_ERROR_2
        LDAB    #ERROR_CODE_2
        OS      UT$LEAV ; return B to ENTER_ROUTINE_1, setting C-flag
NO_ERROR_2:
        RTS                 ; no need to clear B here as not called
                            ; directly by UT$ENTR
The following example establishes nested control regions, clarifying where control continues after calling UT$LEAV. (In this example, 0 in the B register is used to signify non-error return from UT$ENTR).
MAIN:
        .
        .
        LDX     #REGION_1
        LDD     P1          ; set D to parameter for REGION_1
                                  Establish a new control region
        OS      UT$ENTR     ; Establish a new control region
; REGION_1 now dis-established
        BCS     ERROR       ; On error, B set to error code, C-flag set
        RTS
        
REGION_1:
        STD     PARAMETER_1
        .
        .
        BCC     NO_ERROR_1
        LDAB    #CODE1
        OS      UT$LEAV     ; return B register to MAIN, setting C-flag
NO_ERROR_1:
        JSR     RTN1        ; if RTN1 calls UT$LEAV,
        .                   ;    control returns to MAIN
        .
        LDX     #REGION_2
        LDD     P2          ; set D to parameter for REGION_2
        OS      UT$ENTR     ; Establish a new control region
; REGION_2 now dis-established
        BCS     ERROR       ; On error, B set to error code, C-flag set
        CLRB                ; B must be cleared for normal return
        RTS

REGION_2:
        STD     PARAMETER_2
        .
        .
        BCC     NO_ERROR_2
        LDAB    #CODE2
        OS      UT$LEAV     ; return to REGION_1, setting C-flag
NO_ERROR_2:
        JSR     RTN2        ; if RTN2 calls UT$LEAV,
                            ;    control returns to REGION_1
        .
        .
        LDX     #REGION_3
        LDD     P3          ; set D to parameter for REGION_3
         OS      UT$ENTR    ; Establish a new control region
; REGION_3 now dis-established
        BCS     ERROR       ; On error, B set to error code, C-flag set
        CLRB                ; B must be cleared for normal return
        RTS
Errors - none -