[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

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:

  • Removes call frames, starting with the call frame for the program unit in which the condition occurred
  • Returns control to an earlier program unit in the current calling sequence

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:

  • To the establisher of the condition handler that issues the SYS$UNWIND. You pass the call depth (first half of the third element of the MECHARGS array) as the first argument in the call to SYS$UNWIND. Do not specify a second argument. For example:


    INCLUDE '($CHFDEF)'
    RECORD /CHFDEF2/ MECHARGS
    CALL SYS$UNWIND(MECHARGS.CHF$IS_MCH_DEPTH,)
    

    Control returns to the establisher and execution resumes at the point of the call that resulted in the exception.
  • To the establisher's caller. Do not specify either of the arguments in the call to SYS$UNWIND. For example:


    CALL SYS$UNWIND(,)
    

    Control returns to the program unit that called the establisher of the condition handler that issues the call to SYS$UNWIND.

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:

  • On a list of HP Fortran condition symbols, see Table 7-1.
  • On an example that uses LIB$MATCH_COND, see Section 14.13.

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:

  • Places the signaled condition value in the image of R0 that is saved as part of the mechanism argument vector.
  • Calls the unwind system service (SYS$UNWIND) with the default arguments. After returning from LIB$SIG_TO_RET (when it is established as a condition handler) or after returning from the condition handler that called LIB$SIG_TO_RET (when LIB$SIG_TO_RET is called from within a condition handler), the stack is unwound to the caller of the procedure that established the handler.

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):

  • SIGARRAY(1) contains the argument count.
  • SIGARRAY(2) contains the condition code SS$_HPARITH.
  • SIGARRAY(3) contains the integer register write mask.
  • SIGARRAY(4) contains the floating-point register write mask.
  • SIGARRAY(5) contains the exception summary.
  • SIGARRAY(6) contains the exception PC (program counter).
  • SIGARRAY(7) contains the exception PS (processor status).

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:

  • On alignment, see Section 5.3.
  • On using the OpenVMS Debugger to detect unaligned data, see Section 4.7.
  • On the SYS$START_ALIGN_FAULT_REPORT service, see the HP OpenVMS System Services Reference Manual.
  • On the /CHECK qualifier, see Section 2.3.11.
  • On the /SYNCHRONOUS_EXCEPTIONS (Alpha only) qualifier, see Section 2.3.46.

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:
    • Display the %SYSTEM-F-HPARITH message.
    • Display the traceback information. Note that the PC address is the address of the HANDLER routine. To obtain the approximate address where the exception occurred, the CALL LIB$ESTABLISH line can be commented out in the routine causing the exception and recompiled, relinked, and rerun.
    • Stop program execution. This is not a continuable error.
  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