Updated: 11 December 1998 |
OpenVMS Programming Concepts Manual
Previous | Contents | Index |
On Alpha systems, the handler should modify the saved copies of R0 and R1 (CHF$IH_MCH_SAVRnn).
R0 and R1 are restored from the mechanism argument vector at the end of the unwind.
Figure 15-13 Unwinding the Call Stack
15.10.2 GOTO Unwind Operations (Alpha Only)
On Alpha systems, a current procedure invocation is one in whose
context the thread of execution is currently executing. At any instant,
a thread of execution has exactly one current procedure. If code in the
current procedure calls another procedure, then the called procedure
becomes the current procedure. As each stack frame or register frame
procedure is called, its invocation context is recorded in a procedure
frame. The invocation context is mainly a snapshot of process registers
at procedure invocation. It is used during return from the called
procedure to restore the calling procedure's state. The chain of all
procedure frames starting with the current procedure and going all the
way back to the first procedure invocation for the thread is called the
call chain. While a procedure is part of the call
chain, it is called an active procedure.
When a current procedure returns to its calling procedure, the most recent procedure frame is removed from the call chain and used to restore the now current procedure's state. As each current procedure returns to its calling procedure, its associated procedure frame is removed from the call chain. This is the normal unwind process of a call chain.
You can bypass the normal return path by forcibly unwinding the call chain. The Unwind Call Chain (SYS$UNWIND) system service allows a condition handler to transfer control from a series of nested procedure invocations to a previous point of execution, bypassing the normal return path. The Goto Unwind (SYS$GOTO_UNWIND) system service allows any procedure to achieve the same effect. SYS$GOTO_UNWIND restores saved register context for each nested procedure invocation, calling the condition handler, if any, for each procedure frame that it unwinds. Restoring saved register context from each procedure frame from the most recent one to the target procedure frame ensures that the register context is correct when the target procedure gains control. Also, each condition handler called during unwind can release any resources acquired by its establishing procedure.
For information about the GOTO unwind operations and how to use the
SYS$GOTO_UNWIND system service, see the OpenVMS Calling Standard and the
OpenVMS System Services Reference Manual.
15.11 Displaying Messages
The standard format for a message is as follows:
%facility-l-ident, message-text |
facility | Abbreviated name of the software component that issued the message |
l | Indicator showing the severity level of the exception condition that caused the message |
ident | Symbol of up to nine characters representing the message |
message-text | Brief definition of the cause of the message |
The message can also include up to 255 formatted ASCII output (FAO) arguments. These arguments can be used to display variable information about the condition that caused the message. In the following examples, the file specification is an FAO argument:
%TYPE-W-OPENIN, error opening _DB0:[FOSTER]AUTHOR.DAT; as input |
For information about specifying FAO parameters, see Section 15.11.4.3.
Signaling provides a consistent and unified method for displaying messages. This section describes how the OpenVMS Condition Handling facility translates the original signal into intelligible messages.
Signaling is used to signal exception conditions generated by Compaq software. When software detects an exception condition, it signals the exception condition to the user by calling LIB$SIGNAL or LIB$STOP. The signaling routine passes a signal argument list to these run-time library routines. This signal argument list is made up of the condition value and a set of optional arguments that provide information to condition handlers.
You can use the signaling mechanism to signal messages that are specific to your application. Further, you can chain your own message to a system message. For more information, see Section 15.11.3.
LIB$SIGNAL and LIB$STOP copy the signal argument list and use it to create the signal argument vector. The signal argument vector serves as part of the input to the user-established handlers and the system default handlers.
If all intervening handlers have resignaled, the system default handlers take control. The system-supplied default handlers are the only handlers that should actually issue messages, whether the exception conditions are signaled by Compaq software or your own programs. That is, a routine should signal exception conditions rather than issue its own messages. In this way, other applications can call the routine and override its signal in order to change the messages. Further, this technique decides formatting details, and it also keeps wording centralized and consistent.
The system default handlers pass the signal argument vector to the Put Message (SYS$PUTMSG) system service. SYS$PUTMSG formats and displays the information in the signal argument vector.
SYS$PUTMSG performs the following steps:
You can use the signal array that the operating system passes to the condition handler as the first argument of the SYS$PUTMSG system service. The signal array contains the condition code, the number of required FAO arguments for each condition code, and the FAO arguments (see Figure 15-14). The OpenVMS System Services Reference Manual contains complete specifications for SYS$PUTMSG.
See Section 15.11.2 for information about how to create and suppress messages on a running log using SYS$PUTMSG.
The last two array elements, the PC and PSL, are not FAO arguments and should be deleted before the array is passed to SYS$PUTMSG. Because the first element of the signal array contains the number of longwords in the array, you can effectively delete the last two elements of the array by subtracting 2 from the value in the first element. Before exiting from the condition handler, you should restore the last two elements of the array by adding 2 to the first element in case other handlers reference the array.
In the following example, the condition handler uses the SYS$PUTMSG system service and then returns a value of SS$_CONTINUE so that the default handler is not executed.
INTEGER*4 FUNCTION SYMBOL (SIGARGS, 2 MECHARGS) . . . INDEX = LIB$MATCH_COND (SIGARGS(2), 2 LIB$_NOSUCHSYM) IF (INDEX .GT. 0) THEN ! If condition code is LIB$_NOSUCHSYM, ! change the severity to informational CALL MVBITS (STS$K_INFO, 2 0, 2 3, 2 SIGARGS(2), 2 0) ! Display the message SIGARGS(1) = SIGARGS(1) - 2 ! Subtract last two elements CALL SYS$PUTMSG (SIGARGS,,,) SIGARGS(1) = SIGARGS(1) + 2 ! Restore last two elements ! Continue program execution; SYMBOL = SS$_CONTINUE ELSE ! Otherwise, resignal the condition SYMBOL = SS$_RESIGNAL END IF END |
Each message sequence in the signal argument list produces one line of output. Figure 15-14 illustrates the three possible message sequence formats.
Figure 15-14 Formats of Message Sequences
OpenVMS RMS system services return two related completion values: the completion code and the associated status value. The completion code is returned in R0 using the function value mechanism. The same value is also placed in the Completion Status Code field of the RMS file access block (FAB) or record access block (RAB) associated with the file (FAB$L_STS or RAB$L_STS). The status value is returned in the Status Value field of the same FAB or RAB (FAB$L_STV or RAB$L_STV). The meaning of this secondary value is based on the corresponding STS (Completion Status Code) value. Its meaning could be any of the following:
Rather than have each calling program determine the meaning of the STV value, SYS$PUTMSG performs the necessary processing. Therefore, this STV value must always be passed in place of the FAO argument count. In other words, an RMS message sequence always consists of two arguments (passed by immediate value): an STS value and an STV value.
15.11.1 Chaining Messages
You can use a condition handler to add condition values to an
originally signaled condition code. For example, if your program
calculates the standard deviation of a series of numbers and the user
only enters one value, the operating system signals the condition code
SS$_INTDIV when the program attempts to divide by zero. (In calculating
the standard deviation, the divisor is the number of values entered
minus 1.) You could use a condition handler to add a user-defined
message to the original message to indicate that only one value was
entered.
To display multiple messages, pass the condition values associated with the messages to the RTL routine LIB$SIGNAL. To display the message associated with an additional condition code, the handler must pass LIB$SIGNAL the condition code, the number of FAO arguments used, and the FAO arguments. To display the message associated with the originally signaled condition codes, the handler must pass LIB$SIGNAL each element of the signal array as a separate argument. Because the signal array is a variable-length array and LIB$SIGNAL cannot accept a variable number of arguments, when you write your handler you must pass LIB$SIGNAL more arguments than you think will be required. Then, during execution of the handler, zero the arguments that you do not need (LIB$SIGNAL ignores zero values), as described in the following steps:
INTEGER*4 NEWSIGARGS(15) |
The following example demonstrates steps 2 and 3:
DO I = 1, 15 IF (I .LE. SIGARGS(1) - 2) THEN NEWSIGARGS(I) = SIGARGS(I+1) ! Start with SIGARGS(2) ELSE NEWSIGARGS(I) = 0 ! Pad with zeros END IF END DO |
Because the new array is a known-length array, you can specify each element as an argument to LIB$SIGNAL.
The following condition handler ensures that the signaled condition code is SS$_INTDIV. If it is, the user-defined message ONE_VALUE is added to SS$_INTDIV, and both messages are displayed.
INTEGER FUNCTION HANDLER (SIGARGS, 2 MECHARGS) ! Declare dummy arguments INTEGER SIGARGS(*), 2 MECHARGS(*) ! Declare new array for SIGARGS INTEGER NEWSIGARGS (15) ! Declare index variable for LIB$MATCH_COND INTEGER INDEX ! Declare procedures INTEGER LIB$MATCH_COND ! Declare condition codes EXTERNAL ONE_VALUE INCLUDE '($SSDEF)' INDEX = LIB$MATCH_COND (SIGARGS(2), 2 SS$_INTDIV) IF (INDEX .GT. 0) THEN DO I=1,15 IF (I .LE. SIGARGS(1) - 2) THEN NEWSIGARGS(I) = SIGARGS(I+1) ! Start with SIGARGS(2) ELSE NEWSIGARGS(I) = 0 ! Pad with zeros END IF END DO ! Signal messages CALL LIB$SIGNAL (%VAL(NEWSIGARGS(1)), 2 %VAL(NEWSIGARGS(2)), 2 %VAL(NEWSIGARGS(3)), 2 %VAL(NEWSIGARGS(4)), 2 %VAL(NEWSIGARGS(5)), 2 %VAL(NEWSIGARGS(6)), 2 %VAL(NEWSIGARGS(7)), 2 %VAL(NEWSIGARGS(8)), 2 %VAL(NEWSIGARGS(9)), 2 %VAL(NEWSIGARGS(10)), 2 %VAL(NEWSIGARGS(11)), 2 %VAL(NEWSIGARGS(12)), 2 %VAL(NEWSIGARGS(13)), 2 %VAL(NEWSIGARGS(14)), 2 %VAL(NEWSIGARGS(15)), 2 %VAL(%LOC(ONE_VALUE)), 2 %VAL(0)) HANDLER = SS$_CONTINUE ELSE HANDLER = SS$_RESIGNAL END IF END |
A signal argument list may contain one or more condition values and FAO arguments. Each condition value and its FAO arguments is "chained" to the next condition value and its FAO arguments. You can use chained messages to provide more specific information about the exception condition being signaled, along with a general message.
The following message source file defines the exception condition PROG__FAIGETMEM:
.FACILITY PROG,1 /PREFIX=PROG__ .SEVERITY FATAL .BASE 100 FAIGETMEM <failed to get !UL bytes of memory>/FAO_COUNT=1 .END |
This source file sets up the exception message as follows:
You can write a condition handler to obtain a copy of a system error message text and write the message into an auxiliary file, such as a listing file. In this way, you can receive identical messages at the terminal (or batch log file) and in the auxiliary file.
To log messages, you must write a condition handler and an action subroutine. Your handler calls the Put Message (SYS$PUTMSG) system service explicitly. The operation of SYS$PUTMSG is described in Section 15.11. The handler passes to SYS$PUTMSG the signal argument vector and the address of the action subroutine. SYS$PUTMSG passes to the action subroutine the address of a string descriptor that contains the length and address of the formatted message. The action subroutine can scan the message or copy it into a log file, or both.
It is important to keep the display messages centralized and consistent. Thus, you should use only SYS$PUTMSG to display or log system error messages. Further, because the system default handlers call SYS$PUTMSG to display error messages, your handlers should avoid displaying the error messages. You can do this in two ways:
Figure 15-15 shows the sequence of events involved in calling SYS$PUTMSG to log an error message to a file.
Figure 15-15 Using a Condition Handler to Log an Error Message
To keep a running log (that is, a log that is resumed each time your
program is invoked) of the messages displayed by your program, use
SYS$PUTMSG. Create a condition handler that invokes SYS$PUTMSG
regardless of the signaled condition code. When you invoke SYS$PUTMSG,
specify a function that writes the formatted message to your log file
and then returns with a function value of 0. Have the condition handler
resignal the condition code. One of the arguments of SYS$PUTMSG allows
you to specify a user-defined function that SYS$PUTMSG invokes after
formatting the message and before displaying the message. SYS$PUTMSG
passes the specified function the formatted message. If the function
returns with a function value of 0, SYS$PUTMSG does not display the
message; if the function returns with a value of 1, SYS$PUTMSG displays
the message. The OpenVMS System Services Reference Manual contains complete specifications for
SYS$PUTMSG.
15.11.2.2 Suppressing the Display of Messages in the Running Log
To keep a running log of messages, you might have your main program open a file for the error log, write the date, and then establish a condition handler to write all signaled messages to the error log. Each time a condition is signaled, a condition handler like the one in the following example invokes SYS$PUTMSG and specifies a function that writes the message to the log file and returns with a function value of 0. SYS$PUTMSG writes the message to the log file but does not display the message. After SYS$PUTMSG writes the message to the log file, the condition handler resignals to continue program execution. (The condition handler uses LIB$GET_COMMON to read the unit number of the file from the per-process common block.)
INTEGER FUNCTION ERRLOG (SIGARGS, 2 MECHARGS) ! Writes the message to file opened on the ! logical unit named in the per-process common block ! Define the dummy arguments INTEGER SIGARGS(*), 2 MECHARGS(*) INCLUDE '($SSDEF)' EXTERNAL PUT_LINE INTEGER PUT_LINE ! Pass signal array and PUT_LINE routine to SYS$PUTMSG SIGARGS(1) = SIGARGS(1) - 2 ! Subtract PC/PSL from signal array CALL SYS$PUTMSG (SIGARGS, 2 PUT_LINE, ) SIGARGS(1) = SIGARGS(1) + 2 ! Replace PC/PSL ERRLOG = SS$_RESIGNAL END |
INTEGER FUNCTION PUT_LINE (LINE) ! Writes the formatted message in LINE to ! the file opened on the logical unit named ! in the per-process common block ! Dummy argument CHARACTER*(*) LINE ! Logical unit number CHARACTER*4 LOGICAL_UNIT INTEGER UNIT_NUM ! Indicates that SYS$PUTMSG is not to display the message PUT_LINE = 0 ! Get logical unit number and change to integer STATUS = LIB$GET_COMMON (LOGICAL_UNIT) READ (UNIT = LOGICAL_UNIT, 2 FMT = '(I4)') UNIT_NUMBER ! The main program opens the error log WRITE (UNIT = UNIT_NUMBER, 2 FMT = '(A)') LINE END |
Section 15.11 explains how the OpenVMS Condition Handling facility displays messages. The signal argument list passed to LIB$SIGNAL or LIB$STOP can be seen as one or more message sequences. Each message sequence consists of a condition value; an FAO count, which specifies the number of FAO arguments to come; and the FAO arguments themselves. (The FAO count is omitted in the case of system and RMS messages.) The message text definition itself is actually a SYS$FAO control string, which may contain embedded $FAO directives. The OpenVMS System Services Reference Manual describes the Formatted ASCII Output (SYS$FAO) system service in detail.
The Message utility is provided for compiling message sequences specific to your application. When you have defined an exception condition and used the Message utility to associate a message with that exception condition, your program can call LIB$SIGNAL or LIB$STOP to signal the exception condition. You signal a message that is defined in a message source file by calling LIB$SIGNAL or LIB$STOP, as for any software-detected exception condition. Then the system default condition handlers display your error message in the standard operating system format.
To use the Message utility, follow these steps:
See also the description of the Message utility in the OpenVMS Command Definition, Librarian, and Message Utilities Manual.
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
5841PRO_043.HTML
|