Previous | Contents | Index |
The following notes are keyed to Example 10-8:
For more detailed information on the argument lists passed to a
condition handler and for descriptions of the values in the signal
array and mechanism array, see the OpenVMS System Services Reference Manual. Note that the PL/I
run-time system signals conditions using the conventions for specifying
signal arguments. Specifically, it passes arguments following the
requirements described for the SYS$PUTMSG procedure. This procedure is
described in the Introduction to the VMS Run-Time Library.
10.7.2 ONCODE Built-In Function
You can use the built-in function ONCODE to obtain the specific 32-bit status value that describes any condition that is signaled. The low-order three bits of this value contain the severity of the condition (success, warning, error, or fatal). The severity of a condition is important only when no ON-unit exists for a condition, and default condition handling is performed by either PL/I or the system (see Section 10.4).
All OpenVMS-defined conditions have symbolic names associated with them. Table 10-2 lists the PL/I keyword condition names and the global symbol names for the OpenVMS condition values associated with them. If the ONCODE built-in function is invoked in an ON-unit for the related PL/I condition name, it returns the value of the indicated global symbol.
PL/I Condition | VMS Global Symbol Name1 |
---|---|
AREA | See the Kednos PL/I for OpenVMS Systems Reference Manual and Chapter 15 of this manual for a discussion of allocation in areas. |
CONDITION | PLI$_CONDITION |
CONVERSION | PLI$_CONVERSION if a SIGNAL CONVERSION statement was executed, otherwise PLI$_ONCNVPOS (PLI$_ONCNVPOS could change in a future release of PL/I) |
ENDFILE | PLI$_ENDFILE |
ENDPAGE | PLI$_ENDPAGE |
ERROR | A specific status value associated with the error that caused the condition to be signaled 2 |
FINISH | PLI$_FINISH |
FIXEDOVERFLOW | SS$_DECOVF or SS$_INTOVF |
KEY | RMS$_ name, where name is one of the following specific RMS condition names that describe a key error: RMS$_RNF, RMS$_DUP, RMS$_KEY, RMS$_MRN, RMS$_REX; or, PLI$_ name, where name describes a PL/I run-time error, for example PLI$_CNVERR 2 |
OVERFLOW | SS$_FLTOVF or SS$_FLTOVF_F |
STORAGE | The value returned by LIB$GET_VM |
STRINGRANGE | PLI$_STRRANGE, or PLI$_SUBSTRn (where n is 2 or 3, indicating the 2nd or 3rd argument of the SUBSTR built-in function), or PLI$_BIFSTAPOS (indicating an out-of-range starting position for an INDEX, SEARCH, or VERIFY built-in function) |
SUBSCRIPTRANGE | PLI$_SUBRANGE or PLI$_SUBRANGEn (where n is a number in the range 1 through 8 indicating the subscript number) |
UNDEFINEDFILE | RMS$_ name, where name indicates a specific status value associated with an RMS error; or, PLI$_ name, where name describes a PL/I run-time error 2 |
UNDERFLOW | SS$_FLTUND or SS$_FLTUND_F |
VAXCONDITION | Any user-defined condition value that was signaled |
ZERODIVIDE | SS$_FLTDIV, SS$_INTDIV, or SS$_FLTDIV_F |
When you write an ON-unit to handle one or more conditions, you can refer specifically to the values returned by the ONCODE built-in function using system global symbol names. Table 10-2 lists, where appropriate, the specific system global symbol for a condition name.
All symbolic names associated with OpenVMS condition values are defined as system global symbols. Thus, you can declare the names for these values in a PL/I program using the GLOBALREF and VALUE attributes, and refer to them symbolically. The linker will automatically locate the definitions of the symbols in the default system libraries when the procedure is linked.
For example, the FIXEDOVERFLOW condition can be signaled for either of two conditions. An ON-unit can determine which condition was actually signaled by testing the value of ONCODE as follows:
DECLARE SS$_DECOVF GLOBALREF VALUE FIXED BINARY(31); ON FIXEDOVERFLOW BEGIN; IF ONCODE() = SS$_DECOVF THEN PUT LIST ('Decimal overflow'); ELSE PUT LIST ('Integer overflow'); END; |
In this example, the global symbol SS$_DECOVF is declared with the
GLOBALREF and VALUE attributes. The ON-unit established for the
FIXEDOVERFLOW condition determines, from the value returned by ONCODE,
whether the condition was specifically a decimal overflow or an integer
overflow.
10.7.3 ONFILE Built-In Function
The ONFILE built-in function returns the name of the file constant for which the current file-related condition was signaled. Its format is given in the Kednos PL/I for OpenVMS Systems Reference Manual.
This built-in function can be used in any of the following ON-units:
The returned value is a varying-length character string. If referenced
outside an ON-unit or within an ON-unit that is executed as a result of
a SIGNAL statement, the ONFILE function returns a null string.
10.7.4 ONKEY Built-In Function
The ONKEY built-in function returns the key value that caused the KEY condition to be signaled during an I/O operation to a file that is being accessed by key. Its format is given in the Kednos PL/I for OpenVMS Systems Reference Manual.
This built-in function can be used in an ON-unit established for these conditions:
The returned key value is a varying-length character string. If referenced outside an ON-unit, or within an ON-unit executed as a result of the SIGNAL statement, the ONKEY built-in function returns a null string.
The Kednos PL/I for OpenVMS VAX and Kednos PL/I for OpenVMS Alpha compilers are part of the OpenVMS common language environment. This environment defines certain calling procedures and guidelines that allow you to call routines written in different languages or prewritten system routines from PL/I. You can call any of the following routine types from PL/I:
The definitions of routine, procedure, and function used throughout this chapter are somewhat different from standard PL/I terminology. These definitions are consistent with the OpenVMS system routines documentation and apply only throughout this chapter. |
A routine is a closed, ordered set of instructions that performs one or more specific tasks. Every routine has an entry point (the routine name), and optionally an argument list. Procedures and functions are specific types of routines: a procedure is a routine that does not return a value, whereas a function is a routine that returns a value by assigning that value to the function's identifier.
System routines are prewritten OpenVMS routines that perform
common tasks, such as finding the square root of a number or allocating
virtual memory. You can call any system routine from your program,
provided that PL/I supports the data structures required to call the
routine. The system routines used most often are OpenVMS Run-Time
Library routines, utility routines, and system services. System
routines, which are discussed later in this chapter, are documented in
detail in the VMS Run-Time Library Routines Volume, the OpenVMS Utility Routines Manual, and the OpenVMS System Services Reference Manual.
11.1 OpenVMS Calling Standard
The OpenVMS Calling Standard describes the concepts used by OpenVMS languages for invoking routines and passing data between them. It also describes the differences between the OpenVMS VAX and OpenVMS Alpha parameter passing mechanisms. The OpenVMS Calling Standard specifies the following attributes:
The following sections discuss these attributes in more detail. The OpenVMS Calling Standard also defines such attributes as the calling sequence, the argument data types and descriptor formats, condition handling, and stack unwinding. These attributes are discussed in detail in the Introduction to VMS System Routines.
11.1.1 Register and Stack Usage
The OpenVMS Calling Standard defines registers and their uses, as listed in
Table 11-1 and Table 11-2.
Register | Use |
---|---|
PC | Program counter |
SP | Stack pointer |
FP | Current stack frame pointer |
AP | Argument pointer (when necessary) |
R1 | Environment value (when necessary) |
R0, R1 | Function value return registers |
Register | Use |
---|---|
PC | Program counter |
SP | Stack pointer |
FP | Frame pointer for current procedure |
R25 | Argument information register |
R16 to R21,
F16 to F21 |
Argument list registers |
R0 | Function value return register |
By definition, any called routine can use registers R2 through R11 for computation, and the AP register as a temporary register.
Figure 11-1 The Call Stack ( OpenVMS VAX)
In the OpenVMS Calling Standard, a stack is defined as a LIFO (last-in/first-out) temporary storage area that the system allocates for every user process. The system keeps information about each routine call in the current image on the call stack. Then, each time you call a routine, the system creates a structure on this call stack, known as the call frame. The call frame for each active procedure contains the following:
Figure 11-1 illustrates the call stack and several call frames. Procedure A calls procedure B, which calls procedure C.
When a routine completes execution, the system uses the frame pointer
in the call
frame of the current routine to locate the frame of the previous
routine. The system then removes the call frame of the current routine
from the stack.
11.1.2 Return of the Function Value
A function is a routine that returns a single value to the calling
routine. The function value is the value returned to the
caller. According to the calling standard, a function value may be
returned as either an actual value or a condition value that indicates
success or failure.
11.1.3 The Argument List
The OpenVMS Calling Standard also defines a data structure called the argument list. You use an argument list to pass information to a routine and receive results.
On OpenVMS Alpha systems, an argument list is formed using registers R16 to R21 or F16 to F21 and a collection of quadwords in memory (depending on the number and type of the arguments.
On VAX systems, an argument list is a collection of longwords in memory that represents a routine parameter list and possibly includes information for the return of a function value, if a function returns a value that is not suitable for return in R0 or R0/R1. Figure 11-2 shows the structure of a typical OpenVMS VAX argument list.
Figure 11-2 Structure of an OpenVMS VAX Argument List
The first longword must be present; this longword stores the number of arguments (the argument count: n) as an unsigned integer value in the low byte of the longword. The remaining 24 bits of the first longword are reserved for use by Hewlett Packard and should be zero. The longwords labeled arg1 through argn are the actual parameters, which can be any of the following:
The argument list contains the parameters that are passed to the routine. Depending on the passing mechanisms for these parameters, the forms of the arguments contained in the argument list vary. For example, if you pass three arguments, the first by value, the second by reference, and the third by descriptor, the argument list contains the value of the first argument, the address of the second, and the address of the descriptor of the third. Figure 11-3 shows this argument list.
Figure 11-3 Example of an OpenVMS VAX Argument List
To pass data between routines that are not written in the same OpenVMS language, you must specify how you want that data to be represented and interpreted. You do this by specifying a parameter-passing mechanism. The three general parameter-passing mechanisms and their keywords and abbreviations in PL/I are as follows:
The parameter-passing mechanisms are intended for use only in calling non-PL/I routines. External routines written in PL/I should be called with the default mechanisms.
The following sections describe the arguments in terms of PL/I data
types, dummy arguments created (if any), parameter-passing mechanism
conventions, and attributes to define the manner in which parameters
are to be passed. Remember that when PL/I creates a dummy argument,
modifications, if any, that the called procedure makes to the dummy
argument are not accessible to the caller.
11.2.1 Passing Parameters by Reference
When you pass a parameter by reference, the PL/I compiler passes the address at which the actual parameter value is stored. In other words, your routine has access to the parameter's storage address. Therefore, when you manipulate and change the value of this parameter, the changed value overwrites the previous value of the parameter. Thus, when you pass a parameter by reference, any changes that you make to the value of the parameter in your routine are reflected in the calling routine as well, provided a dummy argument is not created.
You can pass an argument of any data type by reference. This mechanism is the default used by PL/I for all arguments except character strings or arrays with nonconstant extents, and unaligned bit strings. Note that bit-string variables must have the ALIGNED attribute to be passed by reference. In general, the parameter descriptor for an argument to be passed by reference need specify only the data type of the parameter.
For example, the Read Event Flags (SYS$READEF) system service requires its first argument to be passed by value and its second argument to be passed by reference. This PL/I procedure can be declared as follows:
DECLARE SYS$READEF ENTRY (FIXED BINARY(31) VALUE, BIT(32) ALIGNED); |
Most OpenVMS routines have declarations in PLI$STARLET; it is therefore not normally necessary to declare them yourself. |
When this procedure is invoked, the second argument must be a variable declared as BIT(32) ALIGNED. PL/I passes the argument by reference. The following PL/I code example with Figure 11-4 illustrates argument passing by reference.
DECLARE FLAGS BIT(32) ALIGNED; DECLARE SYS$READEF ENTRY ( FIXED BINARY(31) VALUE, BIT(32) ALIGNED; . . . CALL SYS$READEF(4, FLAGS); |
Figure 11-4 Argument Passing by Reference
The data types in the parameter descriptors of all output arguments
must match the data types of the written arguments.
11.2.1.1 Using the ANY Attribute
When you write a parameter descriptor for a non-PL/I procedure, you can specify the ANY attribute without the VALUE attribute to describe an argument that is to be passed by reference. The argument can be of any addressable data type known to PL/I. For example, the SYS$READEF service can be specified as follows:
DECLARE SYS$READEF ENTRY (FIXED BINARY(31) VALUE, ANY); |
The second parameter descriptor in the ENTRY attribute indicates that the second argument is to be passed by reference to the procedure SYS$READEF and that it can have any data type. When you specify ANY for an argument to be passed by reference, you cannot specify data type attributes. Note that if you specify the VALUE attribute in conjunction with the ANY attribute, PL/I passes the argument by value.
The ANY attribute is especially useful when you must specify a data structure as an argument. You need not declare the structure within the parameter descriptor, only the ANY attribute.
Previous | Next | Contents | Index |