HP Fortran for OpenVMS
User Manual


Previous Contents Index

14.7 Returning from a Condition Handler

One way that condition handlers control subsequent execution is by specifying a function return value (symbols defined in library module $SSDEF). Function return values and their effects are defined in Table 14-4.

Table 14-4 Condition-Handler Function Return Values
Symbolic Values Effects
SS$_CONTINUE If you assign SS$_CONTINUE to the function value of the condition handler, the handler returns control to the program unit at the statement that signaled the condition (fault) or the statement following the one that signaled the condition (trap).
SS$_RESIGNAL If you assign SS$_RESIGNAL to the function value of the condition handler, or do not specify a function value (function value of zero), the CHF will search for another condition handler in the call stack. If you modify SIGARGS or MECHARGS before resignaling, the modified arrays are passed to the next handler.

A condition handler can also request a call stack unwind by calling SYS$UNWIND before returning. Unwinding the call stack:

In this case, any function return values established by condition handlers are ignored by the CHF.

You can unwind the call stack whether the condition was detected by hardware or signaled by means of LIB$SIGNAL or LIB$STOP. Unwinding is the only way to continue execution after a call to LIB$STOP.

A stack unwind is typically made to one of two places:

The actual stack unwind is not performed immediately after the condition handler issues the call to SYS$UNWIND. It occurs when a condition handler returns control to the CHF.

During the actual unwinding of the call stack, SYS$UNWIND examines each frame in the call stack to determine whether a condition handler was declared. If a handler was declared, SYS$UNWIND calls the handler with the condition value SS_$UNWIND (indicating that the stack is being unwound) in the condition name argument of the signal array. When a condition handler is called with this condition value, that handler can perform any procedure-specific clean-up operations that may be required. After the condition handler returns, the call frame is removed from the stack.

The system service SYS$GOTO_UNWIND performs a similar function.

For More Information:

On an example that uses SYS$UNWIND, see Section 14.13.

14.8 Matching Condition Values to Determine Program Behavior

In many condition-handling situations, you may want to respond to an exception condition regardless of the value of the severity code passed in the condition value. To ignore the severity and control fields of a condition value, use the LIB$MATCH_COND routine as a function in the following form:

index = LIB$MATCH_COND(SIGARGS(2),con-1,...con-n)

index

An integer variable that is assigned a value for use in a subsequent computed GOTO statement.

con

A condition value.

The LIB$MATCH_COND function compares bits 27:3 of the value in SIGARGS(2) with bits 27:3 of each specified condition value. If it finds a match, the function assigns the index value according to the position of the matching condition value in the list.

If the match is with the third condition value following SIGARGS(2), then index = 3. If no match is found, index = 0. The value of the index can then be used to transfer control, as in the following example:


      INTEGER (KIND=4) FUNCTION HANDL(SIGARGS,MECHARGS) 
      INCLUDE '($CHFDEF)' 
      INCLUDE '($FORDEF)' 
      INCLUDE '($SSDEF)' 
      INTEGER (KIND=4) SIGARGS(*) 
      RECORD /CHFDEF2/ MECHARGS 
 
      INDEX=LIB$MATCH_COND(SIGARGS(2), FOR$_FILNOTFOU, & 
                  FOR$_NO_SUCDEV, FOR$_FILNAMSPE, FOR$_OPEFAI) 
 
      GO TO (100,200,300,400), INDEX 
      HANDL=SS$_RESIGNAL 
      RETURN 
       ... 
 100  ! Handle FOR$_FILNOTFOU 
       ... 
 200  ! Handle FOR$_NO_SUCDEV 
       ... 
 300  ! Handle FOR$_FILNAMSPE 
       ... 
 400  ! Handle FOR$_OPEFAI 
       . 
       . 
       . 

If no match is found between the condition value in SIGARGS(2) and any of the values in the list, then INDEX = 0 and control transfers to the next executable statement after the computed GOTO. A match with any of the values in the list transfers control to the corresponding statement in the GOTO list.

If SIGARGS(2) matches the condition symbol FOR$_OPEFAI, control transfers to statement 400.

For More Information:

14.9 Changing a Signal to a Return Status

When it is preferable to detect errors by signaling, but the calling procedure expects a returned status, LIB$SIG_TO_RET may be used by the procedure that signals. LIB$SIG_TO_RET is a condition handler that converts any signaled condition to a return status. The status is returned to the caller of the procedure that established LIB$SIG_TO_RET.

The arguments for LIB$SIG_TO_RET are:

LIB$SIG_TO_RET (sig-args,mch-args)

sig-args

Contains the address of the signal argument array (see Section 14.6).

mch-args

Contains the address of the mechanism argument array (see Section 14.6).

You can establish LIB$SIG_TO_RET as a condition handler by specifying it in a call to LIB$ESTABLISH. You can also establish it by calling it from a user-written condition handler. If LIB$SIG_TO_RET is called from a condition handler, the signaled condition is returned as a function value to the caller of the establisher of that handler when the handler returns to the CHF. When a signaled exception condition occurs, LIB$SIG_TO_RET procedure does the following:

Your calling procedure is then able to test R0 and R1 as if the called procedure had returned a status. Then the calling procedure can specify an error recovery action.

14.10 Changing a Signal to a Stop

The routine LIB$SIG_TO_STOP causes a signal to appear as though it had been signaled by a call to LIB$STOP.

LIB$SIG_TO_STOP can be established as a condition handler or called from within a user-written condition handler.

The argument that you passed to LIB$STOP is a 4-byte condition value (see Section 14.4.3). The argument must be passed using the %VAL argument-passing mechanism.

When a signal is generated by LIB$STOP, the severity code is forced to severe (STS$K_SEVERE) and control cannot be returned to the procedure that signaled the condition.

14.11 Checking for Arithmetic Exceptions

On OpenVMS I64 systems, arithmetic exceptions are indicated by specific condition codes. Examples are SS$_FLTDIV or SS$_INTOVR.

On OpenVMS Alpha systems, arithmetic exceptions are indicated by the condition code SS$_HPARITH. The signal array for arithmetic exceptions (condition code SS$_HPARITH) is unique to OpenVMS Alpha systems and contains seven longwords (seven INTEGER (KIND=4) array elements):

In the integer register write mask and the floating-point register write mask, where each bit represents a register, any bits set indicate the registers that were targets of the exception. The exception summary indicates the type of exception or exceptions in the first seven bits of that longword, as follows:
Bit Meaning
0 Software completion.
1 Invalid floating arithmetic, conversion, or comparison.
2 Invalid attempt to perform a floating-point divide with a divisor of zero. (Integer divide-by-zero is not reported.)
3 Floating-point exponent overflow (arithmetic or conversion).
4 Floating-point exponent underflow (arithmetic or conversion).
5 Floating-point inexact result (arithmetic or conversion).
6 Integer arithmetic overflow or precision overflow during conversion from floating-point to integer.

To allow precise reporting of exceptions, specify the /SYNCHRONOUS_EXCEPTIONS (Alpha only) qualifier on the FORTRAN command line.

If you omit /SYNCHRONOUS_EXCEPTIONS, instructions beyond the instruction causing the exception may have been executed by the time the exception is reported. This causes the PC to be located at a subsequent instruction (inexact exception reporting). Specifying /SYNCHRONOUS_EXCEPTIONS drains the instruction pipeline after appropriate arithmetic instructions, but this slows performance.

For More Information:

14.12 Checking for Data Alignment Traps

Although HP Fortran naturally aligns local variables and provides the /ALIGNMENT qualifier to control alignment of fields in a record structures, derived-type structures, or a common block, certain conditions can result in unaligned data (see Section 5.3).

Unaligned data can result in a data alignment trap, which is an exception indicated by the condition code SS$_ALIGN. The OpenVMS operating system fixes up data alignment traps and does not report them to the program unless requested.

To obtain data alignment trap information, your program can call the SYS$START_ALIGN_FAULT_REPORT service.

You can also run the program within the OpenVMS debugger environment to detect the location of any unaligned data by using the SET BREAK/UNALIGNED debugger command (see Section 4.7).

Use the FORTRAN command /SYNCHRONOUS_EXCEPTIONS (Alpha only) qualifier to ensure precise exception reporting.

Depending on the type of optimizations that might be applied, use the FORTRAN command /NOOPTIMIZE qualifier to ensure exception reporting.

For More Information:

14.13 Condition Handler Example

The example in this section demonstrates the use of condition handlers in typical Fortran procedures.

The following example creates a function HANDLER that tests for integer overflow. The program needs to be compiled using the /CHECK=OVERFLOW, /SYNCHRONOUS_EXCEPTIONS (Alpha only), and (if fixed source form) /EXTEND_SOURCE qualifiers.


!   This program types a maximum value for a 4-byte integer and 
!   then causes an exception with integer overflow, transferring 
!   control to a condition handler named HANDLER. 
! 
!   Compile with: /CHECK=OVERFLOW 
!                 /SYNCHRONOUS_EXCEPTIONS 
!                 (and if fixed format, /EXTEND_SOURCE) 
! 
!   File: INT_OVR.F90 
! 
    INTEGER (KIND=4) INT4 
 
    EXTERNAL HANDLER                                     (1)
 
    CALL LIB$ESTABLISH (HANDLER)                         (2)
    int4=2147483645 
    WRITE (6,*) ' Beginning DO LOOP, adding 1 to ', int4 
    DO I=1,10 
       INT4=INT4+1                                       (3)
       WRITE (6,*) ' INT4 NUMBER IS  ', int4       
    END DO 
    WRITE (6,*) ' The end ...' 
    END PROGRAM 
 
 
!   The function HANDLER that handles the condition SS$_HPARITH 
 
    INTEGER (KIND=4) FUNCTION HANDLER (SIGARGS, MECHARGS)   (4)
 
    INTEGER (KIND=4) SIGARGS(*),MECHARGS(*)                 (5)
    INCLUDE '($CHFDEF)' 
    INCLUDE '($SSDEF)' 
    RECORD /CHFDEF1/ SIGARGS 
    RECORD /CHFDEF2/ MECHARGS 
    INTEGER INDEX 
    INTEGER LIB$MATCH_COND 
 
    INDEX = LIB$MATCH_COND(SIGARGS(2), SS$_HPARITH)        (6)
    IF (INDEX .EQ. 0 ) THEN 
        HANDLER = SS$_RESIGNAL 
    ELSE IF (INDEX .GT. 0) THEN 
        WRITE (6,*) '--> Arithmetic exception detected. Now in HANDLER' 
        CALL LIB$STOP(%VAL(SIGARGS(2)),)                   (7)
    END IF 
 
    RETURN 
    END FUNCTION HANDLER 

The program is compiled, linked, and executed:


$ FORTRAN/CHECK=OVERFLOW/SYNCHRONOUS_EXCEPTIONS INT_OVR (8)
$ LINK INT_OVR
$ RUN  INT_OVR
 Beginning DO LOOP, adding 1 to   2147483645 
 INT4 NUMBER IS    2147483646 
 INT4 NUMBER IS    2147483647                             (3)
 --> Arithmetic exception detected. Now in HANDLER 
%SYSTEM-F-HPARITH, high performance arithmetic trap, Imask=00000000, 
Fmask=0002023C, summary=1B, PC=00000001, PS=00000001 
-SYSTEM-F-FLTINV, floating invalid operation, PC=00000001, PS=00000001 
-SYSTEM-F-FLTOVF, arithmetic trap, floating overflow at PC=00000001, 
 PS=00000001 
-SYSTEM-F-FLTUND, arithmetic trap, floating underflow at PC=00000001, 
 PS=00000001 
TRACE-F-TRACEBACK, symbolic stack dump follows             (7)
Image Name   Module Name    Routine Name  Line Number  rel PC      abs PC 
 INT_OVR      INT_OVR$MAIN   HANDLER              1718 0000023C   0002023C 
 DEC$FORRTL                                          0 000729F4   000A49F4 
----- above condition handler called with exception 00000504: 
%SYSTEM-F-HPARITH, high performance arithmetic trap, Imask=00000002, 
Fmask=00000000, summary=40, PC=000200CC, PS=0000001B 
-SYSTEM-F-INTOVF, arithmetic trap,integer overflow at PC=000200CC, PS=0000001B 
----- end of exception message 
                                                     0 84C122BC    84C122BC 
INT_OVR      INT_OVR$MAIN    INT_OVR$MAIN           19 000000CC    000200CC 
                                                     0 84D140D0    84D140D0

  1. The routine HANDLER is declared as EXTERNAL.
  2. The main program calls LIB$ESTABLISH to establish the condition handler named HANDLER.
  3. Within the DO loop, the value of variable INT4 is incremented. When the overflow occurs, control transfers to the condition handler.
  4. The condition handler (function HANDLER) is declared as an integer function accepting the signal array and mechanism array arguments.
  5. The library modules $SSDEF and $CHFDEF from FORSYSDEF.TLB are included and the SIGARGS and MECHARGS variables are declared as records. In this case, the structure definitions for the MECHARGS array are not needed, so the $CHFDEF library module is not included.
  6. The condition handler is only intended to handle the condition code SS$_HPARITH. For other conditions, SS$_RESIGNAL is returned, allowing the CHF to look for another condition handler.
  7. If the exception is SS$_HPARITH, the condition handler makes a call to LIB$STOP to:
  8. The program must be compiled using /CHECK=OVERFLOW. Using /SYNCHRONOUS_EXCEPTIONS (Alpha only) allows more precise exception reporting. If the program is compiled as fixed-form file, specify the /EXTEND_SOURCE qualifier.


Previous Next Contents Index