hp.com home products and services support and drivers solutions how to buy
cd-rom home
End of Jump to page title
HP OpenVMS systems
documentation

Jump to content


HP OpenVMS Programming Concepts Manual

HP OpenVMS Programming Concepts Manual


Previous Contents Index

9.11.3.1.9 Accessing Modified Messages Without Relinking

To allow a program to access modified messages without relinking, create a message pointer file. Message pointer files are useful if you need either to provide messages in more than one language or frequently change the text of existing messages. See the description of the Message utility in the HP OpenVMS Command Definition, Librarian, and Message Utilities Manual.

9.11.4 Signaling User-Defined Values and Messages with Global and Local Symbols

To signal a user-defined condition value, you use the symbol formed by the facility prefix and the condition name (for example, INCOME__BADFIXVAL). Typically, you reference a condition value as a global symbol; however, you can create an include file (similar to the modules in the system library SYS$LIBRARY:FORSTSDEF.TLB) to define the condition values as local symbols. If the message text contains FAO arguments, you must specify parameters for those arguments when you signal the condition value.

9.11.4.1 Signaling with Global Symbols

To signal a user-defined condition value using a global symbol, declare the appropriate condition value in the appropriate section of the program unit, and then invoke the RTL routine LIB$SIGNAL to signal the condition value. The following statements signal the condition value INCOME__NOHOUSE when the value of FIX_HOUSE_NO is less than 1 or greater than the value of TOTAL_HOUSES:


EXTERNAL INCOME__NOHOUSE 
   .
   .
   .
IF ((FIX_HOUSE_NO .GT. TOTAL_HOUSES) .OR. 
2    FIX_HOUSE_NO .LT. 1)) THEN 
  CALL LIB$SIGNAL (%VAL (%LOC (INCOME__NOHOUSE))) 
  END IF 

9.11.4.2 Signaling with Local Symbols

To signal a user-defined condition value using a local symbol, you must first create a file containing PARAMETER statements that equate each condition value with its user-defined condition value. To create such a file, do the following:

  1. Create a listing file---Compile the message source file with the /LIST qualifier to the MESSAGE command. The /LIST qualifier produces a listing file with the same name as the source file and a file type of .LIS. The following line might appear in a listing file:


    08018020     11 NOHOUSE   "No such house number" 
    

    The hexadecimal value in the left column is the value of the condition value, the decimal number in the second column is the line number, the text in the third column is the condition name, and the text in quotation marks is the message text.

  2. Edit the listing file---For each condition name, define the matching condition value as a longword variable, and use a language statement to equate the condition value to its hexadecimal condition value.
    Assuming a prefix of INCOME__, editing the previous statement results in the following statements:


    INTEGER INCOME__NOHOUSE 
    PARAMETER (INCOME__NOHOUSE = '08018020'X) 
    

  3. Rename the listing file---Name the edited listing file using the same name as the source file and a file type for your programming language (for example, .FOR for HP Fortran).

In the definition section of your program unit, declare the local symbol definitions by naming your edited listing file in an INCLUDE statement. (You must still link the message object file with your program.) Invoke the RTL routine LIB$SIGNAL to signal the condition code. The following statements signal the condition code INCOME__NOHOUSE when the value of FIX_HOUSE_NO is less than 1 or greater than the value of TOTAL_HOUSES:


! Specify the full file specification 
INCLUDE '$DISK1:[DEV.INCOME]INCMSG.FOR' 
   .
   .
   .
IF ((FIX_HOUSE_NO .GT. TOTAL_HOUSES) .OR. 
2    FIX_HOUSE_NO .LT. 1)) THEN 
  CALL LIB$SIGNAL (%VAL (INCOME__NOHOUSE)) 
END IF 

9.11.4.3 Specifying FAO Parameters

If the message contains FAO arguments, you must specify the number of FAO arguments as the second argument of LIB$SIGNAL, the first FAO argument as the third argument, the second FAO argument as the fourth argument, and so on. Pass string FAO arguments by descriptor (the default). For example, to signal the condition code INCOME__NONUMBER, where FIX_HOUSE_NO contains the erroneous house number, specify the following:


EXTERNAL INCOME__NONUMBER 
   .
   .
   .
IF ((FIX_HOUSE_NO .GT. TOTAL_HOUSES) .OR. 
2    FIX_HOUSE_NO .LT. 1)) THEN 
  CALL LIB$SIGNAL (%VAL (%LOC (INCOME__NONUMBER)), 
2                  %VAL (1), 
2                  %VAL (FIX_HOUSE_NO)) 
  END IF 

To signal the condition code NOFILE, where FILE_NAME contains the invalid file specification, specify the following:


EXTERNAL INCOME__NOFILE 
   .
   .
   .
IF (IOSTAT .EQ. FOR$IOS_FILNOTFOU) 
2  CALL LIB$SIGNAL (%VAL (%LOC (INCOME__NOFILE)), 
2                   %VAL (1), 
2                   FILE_NAME) 

Both of the previous examples use global symbols for the condition values. Alternatively, you could use local symbols, as described in Section 9.11.4.2.

9.12 Writing a Condition Handler

When you write a condition handler into your program, the process involves one or more of the following actions:

You can write a condition handler to take action when an exception condition is signaled. When the exception condition occurs, the OpenVMS Condition Handling facility sets up the signal argument vector and mechanism argument vector and begins the search for a condition handler. Therefore, your condition-handling routine must declare variables to contain the two argument vectors. Further, the handler must indicate the action to be taken when it returns to the OpenVMS Condition Handling facility. The handler uses its function value to do this. Thus, the calling sequence for your condition handler has the following format:

handler signal-args ,mechanism-args

signal-args

The address of a vector of longwords indicating the nature of the condition. See Section 9.8.2 for a detailed description.

mechanism-args

The address of a vector of longwords that indicates the state of the process at the time of the signal. See Section 9.8.3 and Section 9.8.4 for more details.

result

A condition value. Success (bit <0> = 1) causes execution to continue at the PC; failure (bit <0> = 0) causes the condition to be resignaled. That is, the system resumes the search for other handlers. If the handler calls the Unwind (SYS$UNWIND) system service, the return value is ignored and the stack is unwound. (See Section 9.12.3.)

Handlers can modify the contents of either the signal-args vector or the mechanism-args vector.

In order to protect compiler optimization, a condition handler and any routines that it calls can reference only arguments that are explicitly passed to handlers. They cannot reference COMMON or other external storage, and they cannot reference local storage in the routine that established the handler unless the compiler considers the storage to be volatile. Compilers that do not adhere to this rule must ensure that any variables referenced by the handler are always kept in memory, not in a register.

As mentioned previously, a condition handler can take one of three actions:

The sections that follow describe how to write condition handlers to perform these three operations.

9.12.1 Continuing Execution

To continue execution from the instruction following the signal, with no error messages or traceback, the handler returns with the function value SS$_CONTINUE (bit <0> = 1). If, however, the condition was signaled with a call to LIB$STOP, the SS$_CONTINUE return status causes an error message (Attempt To Continue From Stop), and the image exits. The only way to continue from a call to LIB$STOP is for the condition handler to request a stack unwind.

If execution is to continue after a hardware fault (such as a reserved operand fault), the condition handler must correct the cause of the condition before returning the function value SS$_CONTINUE or requesting a stack unwind. Otherwise, the instruction that caused the fault executed again.

Note

On most VAX systems, hardware floating-point traps have been changed to hardware faults. If you still want floating-point exception conditions to be treated as traps, use LIB$SIM_TRAP to simulate the action of floating-point traps.

On Alpha and I64 systems, LIB$SIM_TRAP is not supported. Table 9-5 lists the run-time library routines that are supported and not supported on Alpha and I64 systems.

9.12.2 Resignaling

Condition handlers check for specific errors. If the signaled condition is not one of the expected errors, the handler resignals. That is, it returns control to the OpenVMS Condition Handling facility with the function value SS$_RESIGNAL (with bit <0> clear). To alter the severity of the signal, the handler modifies the low-order 3 bits of the condition value and resignals.

For an example of resignaling, see Section 9.8.6.

9.12.3 Unwinding the Call Stack

A condition handler can dismiss the signal by calling the system service SYS$UNWIND. The stack unwind is initiated when a condition handler that has called SYS$UNWIND returns to OpenVMS Condition Handling facility. For an explanation of unwinding, see Section 9.10.1; for an example of using SYS$UNWIND to return control to the program, see Section 9.12.4.5.

9.12.4 Example of Writing a Condition Handler

The operating system passes two arrays to a condition handler. Any condition handler that you write should declare two arguments as variable-length arrays, as in the following:


INTEGER*4 FUNCTION HANDLER (SIGARGS, 
2                           MECHARGS) 
 
INTEGER*4 SIGARGS(*), 
2         MECHARGS(*) 
   .
   .
   .

9.12.4.1 Signal Array

The first dummy argument, the signal array, describes the signaled condition codes that indicate which error occurred and the state of the process when the condition code was signaled. For the structure of the signal array, see Section 9.8.2.

9.12.4.2 Mechanism Array

The second dummy argument, the mechanism array, describes the state of the process when the condition code was signaled. Typically, a condition handler references only the call depth and the saved function value. Currently, the mechanism array contains exactly five elements except on Alpha and I64; however, because its length is subject to change, you should declare the dummy argument as a variable-length array. For the structure of the mechanism array, see Section 9.8.3.

Usually you write a condition handler in anticipation of a particular set of condition values. Because a handler is invoked in response to any signaled condition code, begin your handler by comparing the condition code passed to the handler (element 2 of the signal array) against the condition codes expected by the handler. If the signaled condition code is not one of the expected codes, resignal the condition code by equating the function value of the handler to the global symbol SS$_RESIGNAL.

9.12.4.3 Comparing the Signaled Condition with an Expected Condition

You can use the RTL routine LIB$MATCH_COND to compare the signaled condition code to a list of expected condition values. The first argument passed to LIB$MATCH_COND is the signaled condition code, the second element of the signal array. The rest of the arguments passed to LIB$MATCH_COND are the expected condition values. LIB$MATCH_COND compares the first argument with each of the remaining arguments and returns the number of the argument that matches the first one. For example, if the second argument matches the first argument, LIB$MATCH_COND returns a value of 1. If the first argument does not match any of the other arguments, LIB$MATCH_COND returns 0.

The following condition handler determines whether the signaled condition code is one of four HP Fortran I/O errors. If it is not, the condition handler resignals the condition code. Note that, when an HP Fortran I/O error is signaled, the signal array describes operating system's condition code, not the HP Fortran error code.


INTEGER FUNCTION HANDLER (SIGARGS, 
2                         MECHARGS) 
 
! Declare dummy arguments 
INTEGER*4 SIGARGS(*), 
2         MECHARGS(*) 
INCLUDE '($FORDEF)'   ! Declare the FOR$_ symbols 
INCLUDE '($SSDEF)'    ! Declare the SS$_ symbols 
INTEGER INDEX 
! Declare procedures 
INTEGER LIB$MATCH_COND 
INDEX = LIB$MATCH_COND (SIGARGS(2), 
2                       FOR$_FILNOTFOU, 
2                       FOR$_OPEFAI, 
2                       FOR$_NO_SUCDEV, 
2                       FOR$_FILNAMSPE) 
IF (INDEX .EQ. 0) THEN 
  ! Not an expected condition code, resignal 
  HANDLER = SS$_RESIGNAL 
ELSE IF (INDEX .GT. 0) THEN 
  ! Expected condition code, handle it 
   .
   .
   .
END IF 
 
END 

9.12.4.4 Exiting from the Condition Handler

You can exit from a condition handler in one of three ways:

9.12.4.5 Returning Control to the Program

Your handlers should return control either to the program unit that established the handler or to the program unit that invoked the program unit that established the handler.

To return control to the program unit that established the handler, invoke SYS$UNWIND and pass the call depth (third element of the VAX mechanism array, or the CHF$IS_MCH_DEPTH field for Alpha and I64) as the first argument with no second argument.


! Declare dummy arguments 
INTEGER*4 SIGARGS(*), 
2         MECHARGS(*) 
   .
   .
   .
CALL SYS$UNWIND (MECHARGS(3),) 

To return control to the caller of the program unit that established the handler, invoke SYS$UNWIND without passing any arguments.


! Declare dummy arguments 
INTEGER*4 SIGARGS(*), 
2         MECHARGS(*) 
   .
   .
   .
CALL SYS$UNWIND (,) 

The first argument SYS$UNWIND specifies the number of program units to unwind (remove from the stack). If you specify this argument at all, you should do so as shown in the previous example. MECHARGS(3) (or the CHF$IS_MCH_DEPTH field for Alpha and I64) contains the number of program units that must be unwound to reach the program unit that established the handler that invoked SYS$UNWIND.) The second argument SYS$UNWIND contains the location of the next statement to be executed. Typically, you omit the second argument to indicate that the program should resume execution at the statement following the last statement executed in the program unit that is regaining control.

Each time SYS$UNWIND removes a program unit from the stack, it invokes any condition handler established by that program unit and passes the condition handler the SS$_UNWIND condition code. To prevent the condition handler from resignaling the SS$_UNWIND condition code (and so complicating the unwind operation), include SS$_UNWIND as an expected condition code when you invoke LIB$MATCH_COND. When the condition code is SS$_UNWIND, your condition handler might perform necessary cleanup operations or do nothing.

In the following example, if the condition code is SS$_UNWIND, no action is performed. If the condition code is another of the expected codes, the handler displays the message and then returns control to the program unit that called the program unit that established the condition handler.


INTEGER FUNCTION HANDLER (SIGARGS, 
2                         MECHARGS) 
 
! Declare dummy arguments 
INTEGER*4 SIGARGS(*), 
2         MECHARGS(*) 
INCLUDE '($FORDEF)' 
INCLUDE '($SSDEF)' 
INTEGER*4 INDEX, 
2         LIB$MATCH_COND 
INDEX = LIB$MATCH_COND (SIGARGS(2), 
2                       SS$_UNWIND, 
2                       FOR$_FILNOTFOU, 
2                       FOR$_OPEFAI, 
2                       FOR$_NO_SUCDEV, 
2                       FOR$_FILNAMSPE) 
IF (INDEX .EQ. 0) THEN 
  ! Unexpected condition, resignal 
  HANDLER = SS$_RESIGNAL 
ELSE IF (INDEX .EQ. 1) THEN 
  ! Unwinding, do nothing 
ELSE IF (INDEX .GT. 1) THEN 
   .
   .
   .
              ! Display the message 
   .
   .
   .
  CALL SYS$UNWIND (,) 
END IF 

9.12.5 Example of Condition-Handling Routines

The following example shows two procedures, A and B, that have declared condition handlers. The notes describe the sequence of events that would occur if a call to a system service failed during the execution of procedure B.


 
/* PGMA */ 
 
#include <stdio.h> 
#include <ssdef.h> 
 
unsigned int sigargs[],mechargs[]; 
 
main() { 
        unsigned int status, vector=0, old_handler; 
 
        old_handler = LIB$ESTABLISH( handlera );               (1)
 
        status = pgmb (arglst);                                (2)
   .
   .
   .
} 
 
/* PGMB */ 
 
#include <stdio.h> 
#include <ssdef.h> 
 
main() { 
 
 old_handler = LIB$ESTABLISH( handlerb );                      (3)
   .
   .
   .
 
                                                               (4)
                                                               (5)
} 
 
/* Handler A */                                               
 
int handlera( sigargs, mechargs ) { 
 
/* Compare condition value signalled with expected value */  
                                                               (6)
                        if (sigargs[1] != SS$_SSFAIL) 
                                goto no_fail; 
   .
   .
   .
/* Signal to continue */ 
 
                        return SS$_CONTINUE; 
 
/* Signal to resignal */ 
no_fail:        
                        return SS$_RESIGNAL; 
 
} 
 
/* Handler B */ 
 
int handlerb( sigargs, mechargs ) { 
 
/* Compare condition value signalled with expected value */ 
                        if (sigargs[1] != SS$_BREAK)              (7)
                                goto no_fail; 
   .
   .
   .
                        return SS$_CONTINUE; 
 
no_fail:        
                        return SS$_RESIGNAL; 
 
 
} 
 
 
 
 


Previous Next Contents Index