Document revision date: 30 March 2001

## OpenVMS Programming Concepts Manual

Previous | Contents | Index

### 9.5.1 Return Status Convention

Most system-defined procedures are functions of longwords, where the function value is equated to a condition value. In this capacity, the condition value is referred to as a return status. You can write your own routines to follow this convention. See Section 9.14.3 for information about how to change a signal to a return status. Each routine description in the OpenVMS System Services Reference Manual, OpenVMS RTL Library (LIB$) Manual, OpenVMS Record Management Utilities Reference Manual, and OpenVMS Utility Routines Manual lists the condition values that can be returned by that procedure.

#### 9.5.1.1 Testing Returned Condition Values

When a function returns a condition value to your program unit, you should always examine the returned condition value. To check for a failure condition (warning, error, or severe error), test the returned condition value for a logical value of false. The following program segment invokes the run-time library procedure LIB$DATE_TIME, checks the returned condition value (returned in the variable STATUS), and, if an error has occurred, signals the condition value by calling the run-time library procedure LIB$SIGNAL ( Section 9.8 describes signaling):

    INTEGER*4 STATUS,
    2         LIB$DATE_TIME
    CHARACTER*23 DATE

    STATUS = LIB$DATE_TIME (DATE)
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

To check for a specific error, test the return status for a particular condition value. For example, LIB$DATE_TIME returns a success value (LIB$_STRTRU) when it truncates the string. If you want to take special action when truncation occurs, specify the condition as shown in the following example (the special action would follow the IF statement):

    INTEGER*4 STATUS,
    2         LIB$DATE_TIME
    CHARACTER*23 DATE

    INCLUDE '($LIBDEF)'
       .
       .
       .
    STATUS = LIB$DATE_TIME (DATE)
    IF (STATUS .EQ. LIB$_STRTRU) THEN
       .
       .
       .

#### 9.5.1.2 Testing SS$_NOPRIV and SS$_EXQUOTA Condition Values

The SS$_NOPRIV and SS$_EXQUOTA condition values returned by a number of system service procedures require special checking. Any system service that is listed as returning SS$_NOPRIV or SS$_EXQUOTA can instead return a more specific condition value that indicates the privilege or quota in question. Table 9-7 list the specific privilege errors, and Table 9-8 lists the quota errors.

Table 9-7 Privilege Errors
SS$_NOACNT | SS$_NOALLSPOOL | SS$_NOALTPRI
SS$_NOBUGCHK | SS$_NOBYPASS | SS$_NOCMEXEC
SS$_NOCMKRNL | SS$_NODETACH | SS$_NODIAGNOSE
SS$_NODOWNGRADE | SS$_NOEXQUOTA | SS$_NOGROUP
SS$_NOGRPNAM | SS$_NOGRPPRV | SS$_NOLOGIO
SS$_NOMOUNT | SS$_NONETMBX | SS$_NOOPER
SS$_NOPFNMAP | SS$_NOPHYIO | SS$_NOPRMCEB
SS$_NOPRMGBL | SS$_NOPRMMBX | SS$_NOPSWAPM
SS$_NOREADALL | SS$_NOSECURITY | SS$_NOSETPRV
SS$_NOSHARE | SS$_NOSHMEM | SS$_NOSYSGBL
SS$_NOSYSLCK | SS$_NOSYSNAM | SS$_NOSYSPRV
SS$_NOTMPMBX | SS$_NOUPGRADE | SS$_NOVOLPRO
SS$_NOWORLD |  |

Table 9-8 Quota Errors
SS$_EXASTLM | SS$_EXBIOLM | SS$_EXBYTLM
SS$_EXDIOLM | SS$_EXENQLM | SS$_EXFILLM
SS$_EXPGFLQUOTA | SS$_EXPRCLM | SS$_EXTQELM

Because either a general or a specific value can be returned, your program must test for both. The following four symbols provide a starting and ending point with which you can compare the returned condition value:

- SS$_NOPRIVSTRT---First specific value for SS$_NOPRIV
- SS$_NOPRIVEND---Last specific value for SS$_NOPRIV
- SS$_NOQUOTASTRT---First specific value for SS$_EXQUOTA
- SS$_NOQUOTAEND---Last specific value for SS$_EXQUOTA

The following Compaq Fortran example tests for a privilege error by comparing STATUS (the returned condition value) with the specific condition value SS$_NOPRIV and the range provided by SS$_NOPRIVSTRT and SS$_NOPRIVEND. You would test for SS$_NOEXQUOTA in a similar fashion.

       .
       .
       .
    ! Declare status and status values
    INTEGER STATUS
    INCLUDE '($SSDEF)'
       .
       .
       .
    IF (.NOT. STATUS) THEN
      IF ((STATUS .EQ. SS$_NOPRIV) .OR.
    2     ((STATUS .GE. SS$_NOPRIVSTRT) .AND.
    2      (STATUS .LE. SS$_NOPRIVEND))) THEN
       .
       .
       .
      ELSE
       CALL LIB$SIGNAL (%VAL(STATUS))
      END IF
    END IF

### 9.5.2 Modifying Condition Values

To modify a condition value, copy a series of bits from one longword to another longword. For example, the following statement copies the first three bits (bits <2:0>) of STS$K_INFO to the first three bits of the signaled condition code, which is in the second element of the signal array named SIGARGS. As shown in Table 9-6, STS$K_INFO contains the symbolic severity code for an informational message.

    ! Declare STS$K_ symbols
    INCLUDE '($STSDEF)'
       .
       .
       .
    ! Change the severity of the condition code
    ! in SIGARGS(2) to informational
    CALL MVBITS (STS$K_INFO,
    2            0,
    2            3,
    2            SIGARGS(2),
    2            0)

Once you modify the condition value, you can resignal the condition value and either let the default condition handler display the associated message or use the SYS$PUTMSG system service to display the message. If your condition handler displays the message, do not resignal the condition value, or the default condition handler will display the message a second time.

In the following example, the condition handler verifies that the signaled condition value is LIB$_NOSUCHSYM. If it is, the handler changes its severity from error to informational and then resignals the modified condition value. As a result of the handler's actions, the program displays an informational message indicating that the specified symbol does not exist, and then continues executing.

    INTEGER FUNCTION SYMBOL (SIGARGS,
    2                        MECHARGS)
    ! Changes LIB$_NOSUCHSYM to an informational message

    ! Declare dummy arguments
    INTEGER*4 SIGARGS(*),
    2         MECHARGS(*)
    ! Declare index variable for LIB$MATCH_COND
    INTEGER INDEX
    ! Declare condition codes
    INCLUDE '($LIBDEF)'
    INCLUDE '($STSDEF)'
    INCLUDE '($SSDEF)'
    ! Declare library procedures
    INTEGER LIB$MATCH_COND
    INDEX = LIB$MATCH_COND (SIGARGS(2),
    2                       LIB$NO_SUCHSYM)
    ! If the signaled condition code is LIB$NO_SUCHSYM,
    ! change its severity to informational.
    IF (INDEX .GT. 0)
    2  CALL MVBITS (STS$K_INFO,
    2               0,
    2               3,
    2               SIGARGS(2),
    2               0)

    SYMBOL = SS$_RESIGNAL

    END

## 9.6 Exception Dispatcher

When an exception occurs, control is passed to the operating system's exception-dispatching routine. The exception dispatcher searches for a condition-handling routine invoking the first handler it finds and passes the information to the handler about the condition code and the state of the program when the condition code was signaled. If the handler resignals, the operating system searches for another handler; otherwise, the search for a condition handler ends.

The operating system searches for condition handlers in the following sequence:

1. Primary exception vectors---Four vectors (lists) of one or more condition handlers; each vector is associated with an access mode. By default, all of the primary exception vectors are empty. Exception vectors are used primarily for system programming, not application programming. The debugger uses the primary exception vector associated with user mode.
   When an exception occurs, the operating system searches the primary exception associated with the access mode at which the exception occurred. To enter or cancel a condition handler in an exception vector, use the SYS$SETEXV system service. Condition handlers that are entered into the exception vectors associated with kernel, executive, and supervisor modes remain in effect either until they are canceled or until you log out. Condition handlers that are entered into the exception vector associated with user mode remain in effect either until they are canceled or until the image that entered them exits.
2. Secondary exception vectors---A set of exception vectors with the same structure as the primary exception vectors. Exception vectors are primarily used for system programming, not application programming. By default, all of the secondary exception vectors are empty.
3. Call frame condition handlers---Each program unit can establish one condition handler (the address of the handler is placed in the call frame of the program unit). The operating system searches for condition handlers established by your program, beginning with the current program unit. If the current program unit has not established a condition handler, the operating system searches for a handler that was established by the program unit that invoked the current program unit, and so on back to the main program.
4. Traceback handler---If you do not establish any condition handlers and link your program with the /TRACEBACK qualifier of the LINK command (the default), the operating system finds and invokes the traceback handler.
5. Catchall handler---If you do not establish any condition handlers and you link your program with the /NOTRACEBACK qualifier to the LINK command, the operating system finds and invokes the catchall handler. The catchall handler is at the bottom of the user stack and in the last-chance exception vector.
6. Last-chance exception vectors---A set of exception vectors with the same structure as the primary and secondary exception vectors. Exception vectors are used primarily for system programming, not application programming. By default, the user- and supervisor-mode last-chance exception vectors are empty. The executive- and kernel-mode last-chance exception vectors contain procedures that cause a bugcheck (a nonfatal bugcheck results in an error log entry; a fatal bugcheck results in a system shutdown). The debugger uses the user-mode last-chance exception vector, and DCL uses the supervisor-mode last-chance exception vector.

The search is terminated when the dispatcher finds a condition handler. If the dispatcher cannot find a user-specified condition handler, it calls the condition handler whose address is stored in the last-chance exception vector. If the image was activated by the command language interpreter, the last-chance vector points to the catchall condition handler. The catchall handler issues a message and either continues program execution or causes the image to exit, depending on whether the condition was a warning or an error condition, respectively.

You can call the catchall handler in two ways:

- If the last-chance exception vector either returns to the dispatcher or is empty, then it calls the catchall condition handler and exits with the return status code SS$_NOHANDLER.
- If the exception dispatcher detects an access violation, it calls the catchall condition handler and exits with the return status code SS$_ACCVIO.

Figure 9-4 illustrates the exception dispatcher's search of the call stack for a condition handler.

Figure 9-4 Searching the Stack for a Condition Handler

In cases where the default condition handling is insufficient, you can establish your own handler by one of the mechanisms described in Section 9.2.1. Typically, you need condition handlers only if your program must perform one of the following operations:

- Respond to condition values that are signaled rather than returned, such as an integer overflow error. ( Section 9.14.3 describes the system-defined handler LIB$SIG_TO_RET that allows you to treat signals as return values; Section 9.4.2 describes other useful system-defined handlers for arithmetic errors.)
- Modify part of a condition code, such as the severity. See Section 9.5.2 for more information. If you want to change the severity of any condition code to a severe error, you can use the run-time library procedure LIB$STOP instead of writing your own condition handler.
- Add messages to the one associated with the originally signaled condition code or log the messages associated with the originally signaled condition code.

## 9.7 Argument List Passed to a Condition Handler

On VAX systems, the argument list passed to the condition handler is constructed on the stack and consists of the addresses of two argument arrays, signal and mechanism, as illustrated in Section 9.8.2 and Section 9.8.3.

On Alpha systems, the arrays are set up on the stack, but any argument is passed in registers.

On VAX systems, you can use the $CHFDEF macro instruction to define the symbolic names to refer to the arguments listed in Table 9-9.

Table 9-9 $CHFDEF Symbolic Names and Arguments on VAX Systems
Symbolic Name | Related Argument
--- | ---
CHF$L_SIGARGLST | Address of signal array
CHF$L_MCHARGLST | Address of mechanism array
CHF$L_SIG_ARGS | Number of signal arguments
CHF$L_SIG_NAME | Condition name
CHF$L_SIG_ARG1 | First signal-specific argument
CHF$L_MCH_ARGS | Number of mechanism arguments
CHF$L_MCH_FRAME | Establisher frame address
CHF$L_MCH_DEPTH | Frame depth of establisher
CHF$L_MCH_SAVR0 | Saved register R0
CHF$L_MCH_SAVR1 | Saved register R1

On Alpha systems, you can use the $CHFDEF2 macro instruction to define the symbolic names to refer to the arguments listed in Table 9-10.

Table 9-10 $CHFDEF2 Symbolic Names and Arguments on Alpha Systems
Symbolic Name | Related Argument
--- | ---
CHF$L_SIGARGLST | Address of signal array
CHF$L_MCHARGLST | Address of mechanism array
CHF$IS_SIG_ARGS | Number of signal arguments
CHF$IS_SIG_NAME | Condition name
CHF$IS_SIG_ARG1 | First signal-specific argument
CHF$IS_MCH_ARGS | Number of mechanism arguments
CHF$IS_MCH_FLAGS | Flag bits <63:0> for related argument mechanism information
CHF$PH_MCH_FRAME | Establisher frame address
CHF$IS_MCH_DEPTH | Frame depth of establisher
CHF$PH_MCH_DADDR | Address of the handler data quadword if the exception handler data field is present
CHF$PH_MCH_ESF_ADDR | Address of the exception stack frame
CHF$PH_MCH_SIG_ADDR | Address of the signal array
CHF$IH_MCH_SAVR nn | A copy of the saved integer registers at the time of the exception
CHF$FH_MCH_SAVF nn | A copy of the saved floating-point registers at the time of the exception

## 9.8 Signaling

Signaling can be initiated when hardware or software detects an exception condition. In either case, the exception condition is said to be signaled by the routine in which it occurred. If hardware detects the error, it passes control to a condition dispatcher. If software detects the error, it calls one of the run-time library signal-generating routines: LIB$SIGNAL or LIB$STOP. The RTL signal-generating routines pass control to the same condition dispatcher. When LIB$STOP is called, the severity code is forced to severe, and control cannot return to the routine that signaled the condition. See Section 9.12.1 for a description of how a signal can be dismissed and how normal execution from the point of the exception condition can be continued.

When a routine signals, it passes to the OpenVMS Condition Handling facility (CHF) the condition value associated with the exception condition, as well as optional arguments that can be passed to a condition handler. The CHF uses these arguments to build two data structures on the stack:

- The signal argument vector. This vector contains the information describing the nature of the exception condition.
- The mechanism argument vector. This vector describes the state of the process at the time the exception condition occurred.

These two vectors become the arguments that the CHF passes to condition handlers.

These argument vectors are described in detail in Section 9.8.2 and Section 9.8.3.

After the signal and mechanism argument vectors are set up, the CHF searches for enabled condition handlers. A condition handler is a separate routine that has been associated with a routine in order to take a specific action when an exception condition occurs. The CHF searches for condition handlers to handle the exception condition, beginning with the primary exception vector of the access mode in which the exception condition occurred. If this vector contains the address of a handler, that handler is called. If the address is 0 or if the handler resignals, then the CHF repeats the process with the secondary exception vector. Enabling vectored handlers is discussed in detail in the OpenVMS Calling Standard. Because the exception vectors are allocated in static storage, they are not generally used by modular routines.

If neither the primary nor secondary vectored handlers handle the exception condition by continuing program execution, then the CHF looks for stack frame condition handlers. It looks for the address of a condition handler in the first longword of the routine stack frame on VAX systems, or in the procedure descriptor (in which the handler valid bit is set) for the routine stack frame on Alpha systems where the exception condition occurred. At this point, several actions are possible, depending on the results of this search:

- If this routine has not set up a condition handler, the CHF continues the stack scan by moving to the previous stack frame (that is, the stack frame of the calling routine).
- If a condition handler is present, the CHF then calls this handler, which may resignal, continue, or unwind. See Section 9.10.

The OpenVMS Condition Handling facility searches for and calls condition handlers from each frame on the stack until the frame pointer is zero (indicating the end of the call sequence). At that point, the CHF calls the vectored catchall handler, which displays an error message and causes the program to exit. Note that, normally, the frame containing the stack catchall handler is at the end of the calling sequence or at the bottom of the stack. Section 9.9 explains the possible actions of default and user condition handlers in more detail.

Figure 9-5 illustrates a stack scan for condition handlers in which the main program calls procedure A, which then calls procedure B. A stack scan is initiated either when a hardware exception condition occurs or when a call is made to LIB$SIGNAL or LIB$STOP.

Figure 9-5 Sample Stack Scan for Condition Handlers

### 9.8.1 Generating Signals with LIB$SIGNAL and LIB$STOP

When software detects an exception condition, the software normally calls one of the run-time library signal-generating routines, LIB$SIGNAL or LIB$STOP, to initiate the signaling mechanism. This call indicates to the calling program that the exception condition has occurred. Your program can also call one of these routines explicitly to indicate an exception condition.

LIB$SIGNAL Routine

You can signal a condition code by invoking the run-time library procedure LIB$SIGNAL and passing the condition code as the first argument. (The OpenVMS RTL Library (LIB$) Manual contains the complete specifications for LIB$SIGNAL.) The following statement signals the condition code contained in the variable STATUS:

`CALL LIB$SIGNAL (%VAL(STATUS))`

When an error occurs in a subprogram, the subprogram can signal the appropriate condition code rather than return the condition code to the invoking program unit. In addition, some statements also signal condition codes; for example, an assignment statement that attempts to divide by zero signals the condition code SS$_INTDIV.

When your program wants to issue a message and allow execution to continue after handling the condition, it calls the standard routine, LIB$SIGNAL. The calling sequence for LIB$SIGNAL is the following:

    LIB$SIGNAL condition-value [,condition-argument...]
               [,condition-value-n [,condition-argument-n...]...]

Only the condition-value argument must be specified; other arguments are optional. A description of the arguments is as follows:

> #### condition-value

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | read only
> mechanism: | by value

> OpenVMS 32-bit condition value. The condition-value argument is an unsigned longword that contains this condition value. Section 9.5 explains the format of a condition value.

> #### condition-argument

> OpenVMS usage: | varying_arg
> type: | unspecified
> access: | read only
> mechanism: | by value

> As many arguments as are required to process the exception specified by condition-value. These arguments are also used as FAO (formatted ASCII output) arguments to format a message.

> #### condition-value-n

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | read only
> mechanism: | by value

> OpenVMS 32-bit condition value. The optional condition-value-n argument is an unsigned longword that contains this condition value. The calling routine can specify additional conditions to be processed by specifying condition-value-2 through condition-value-n, with each condition value followed by any arguments required to process the condition specified. However, the total number of arguments in the call to LIB$SIGNAL must not exceed 253.

> #### condition-argument-n

> OpenVMS usage: | varying_arg
> type: | unspecified
> access: | read only
> mechanism: | by value

> As many arguments as required to create the message reporting the exception specified by condition-value-n.

LIB$STOP

When your program wants to issue a message and stop execution unconditionally, it calls LIB$STOP. The calling sequence for LIB$STOP is as follows:

`LIB$STOP condition-value [,number-of-arguments] [,FAO-argument....]`

Previous | Next | Contents | Index

| privacy and legal statement |
5841PRO_028.HTML