Previous | Contents | Index |
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.
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:
INCLUDE '($CHFDEF)' RECORD /CHFDEF2/ MECHARGS CALL SYS$UNWIND(MECHARGS.CHF$IS_MCH_DEPTH,) |
CALL 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.
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.
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.
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.
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 |
Previous | Next | Contents | Index |