HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
Some run-time library routines require a variable number of parameters. For example, there is no fixed limit on the number of values that can be passed to functions that return the minimum or maximum value from a list of input parameters. The LIST attribute supplied by HP Pascal allows you to indicate the mechanism by which excess actual parameters are to be passed. For example:
[ASYNCHRONOUS] FUNCTION MTH$DMIN1 ( D_FLOATING : DOUBLE; EXTRA_PARAMS : [LIST] DOUBLE) : DOUBLE; EXTERNAL; |
Because the function MTH$DMIN1 returns the D_floating minimum of an arbitrary number of D_floating parameters, the formal parameter EXTRA_PARAMS is declared with the LIST attribute. All actual parameters must be double-precision real numbers passed by reference with value semantics.
On the LIST attribute (HP Pascal for OpenVMS Language Reference Manual)
6.3 Calling System Routines
All system routines are functions that return an integer condition
value; this value indicates whether the function executed successfully.
An odd-numbered condition value indicates successful completion; an
even-numbered condition value indicates a warning message or failure.
Your program can use the
HP Pascal predeclared function ODD to test the function return
value for success or failure. For example:
IF NOT ODD ($BINTIM(Ascii_Time,Binary_Time)) THEN BEGIN WRITELN('Illegal format for time string'); HALT; END; |
In addition, run-time library routines return one or two values: the result of a computation or the routine's completion status, or both. When the routine returns a completion status, you should verify the return status before checking the result of a computation. You can use the function ODD to test for success or failure or you can check for a particular return status by comparing the return status to one of the status codes defined by the system. For example:
VAR Seed_Value : INTEGER; Rand_Result : REAL; [ASYNCHRONOUS] FUNCTION MTH$RANDOM ( VAR seed : [VOLATILE] UNSIGNED) : SINGLE; EXTERNAL; {In the executable section:} Rand_Result := MTH$RANDOM (Seed_Value); |
When the routine's completion status is irrelevant, your program can treat the function as though it were an external procedure and ignore the return value. For example, your program can declare the Hibernate (SYS$HIBER) system service as a function but call it as though it were a procedure:
[ASYNCHRONOUS,EXTERNAL(SYS$HIBER)] FUNCTION $HIBER : INTEGER; EXTERNAL; {In the executable section:} $HIBER; { Put process to sleep } |
Because SYS$HIBER is expected to execute successfully, the program will
ignore the integer condition value that is returned.
6.4 Using Attributes
When writing programs that use OpenVMS System Services and run-time library routines, it is common to use several HP Pascal attributes.
The VOLATILE attribute indicates that a variable is written or read indirectly without explicit program action. The most common occurrence for this is with item lists. In that case, the address of the variable is placed in the item list (most likely using the IADDRESS routine). This address is then used later when the entire item list is passed to a system service. Without the VOLATILE attribute, the compiler does not realize that the call to the system service or run-time library routine uses the variable.
The UNBOUND attribute designates a routine that does not have a static link available to it. Without a static link, a routine can only access local variables, parameters, or statically allocated variables. System services that require AST or action routines want the address of an UNBOUND routine. Routines at the outer level of a PROGRAM or MODULE are UNBOUND by default.
The ASYNCHRONOUS attribute designates a routine that might be called
asynchronously of any program action. This allows the compiler to
verify that the asynchronous routine only accesses local variables,
parameters, and VOLATILE variables declared at outer levels. Without
the assurance that only VOLATILE variables are used, the asynchronous
routine might access incorrect data, or data written by the routine
will not be available to the main program.
6.5 Using Item Lists
Many OpenVMS system services use item lists. Item lists are sequences of control structures that provide input to the system service and that describe where the service should place its output. These item lists can have an arbitrary number of cells and are terminated with a longword of value 0.
Since different programs need a different number of item list cells, you can use a schema type to define a generic item list data type. This schema type can then be discriminated with the appropriate number of cells. Consider the following example:
TYPE Item_List_Cell = RECORD CASE INTEGER OF 1: ( { Normal Cell } Buffer_Length : [WORD] 0..65535; Item_Code : [WORD] 0..65535; Buffer_Addr : UNSIGNED; Return_Addr : UNSIGNED ); 2: ( { Terminator } Terminator : UNSIGNED ); END; Item_List_Template( Count : INTEGER ) = ARRAY [1..Count] OF Item_List_Cell; |
The Item_List_Cell data type specifies what a single cell looks like. The Buffer_Addr and Return_Addr fields are declared as UNSIGNED since most applications use the IADDRESS predeclared routine to fill them in. The Item_List_Template schema type defines an array of item list cells with a upper bound to be filled in by an actual discriminant.
To use this schema type, first determine the number of item list cells required including one cell for the terminator. After the number of cells has been determined, declare a variable discriminating the schema. Consider the following example:
VAR Item_List : Item_List_Template( 2 ); |
Additionally, since actual discriminants to schema can be run-time expressions, you can write a routine that can have item lists with a number of cells that is determined at run time.
After the item list variable has been declared, each cell must be filled in according to the system service and operation requested.
Consider the following example using the SYS$TRNLNM system service:
VAR Item_List : Item_List_Template( 2 ); Translated_Name : [VOLATILE] VARYING [132] OF CHAR; {Specify the buffer to return the translation:} Item_List[1].Buffer_Length := SIZE( Translated_Name.BODY ); Item_List[1].Item_Code := LNM$_String; Item_List[1].Buffer_Addr := IADDRESS( Translated_Name.BODY ); Item_List[1].Return_Addr := IADDRESS( Translated_Name.LENGTH); { Terminate the item list:} Item_List[2].Terminator := 0; |
The VAR section declares an item list with two cells. It also declares an output buffer for the system service. The VOLATILE attribute is used since the call to SYS$TRNLNM indirectly writes into the variable. The first cell is filled in with the operation desired, the size of the output buffer, the location to write the result, and the location to write the size of the result.
Using the SIZE predeclared function prevents the code from having to be
modified if the output buffer ever changes size. Using the BODY and
LENGTH predeclared fields of the VARYING string allows the system
service to construct a valid VARYING OF CHAR string. Finally, the
second cell of the item list is initialized. Since the second cell is
the last cell, the terminator field must be filled in with a value of 0.
6.6 Using Foreign Mechanism Specifiers on Actual Parameters
The definition files provided by HP Pascal (SYS$LIBRARY:STARLET.PAS and so forth) are created from a generic description language used by the OpenVMS operating system. Since this description language does not contain all the features found in HP Pascal, some of the translations do not take advantage of HP Pascal features. Also, since several of the system services are generic in nature, it is impossible to provide a definitive definition for every situation.
If a formal parameter definition does not reflect the current usage, you can use a foreign mechanism specifier to direct the compiler to use a different passing mechanism or different descriptor type than the default for that parameter.
HP Pascal on OpenVMS I64 and OpenVMS Alpha systems includes limited support for 64-bit pointers.
64-bit pointers can be declared by using the [QUAD] attribute on a
pointer variable declaration. When [QUAD] is used, the generated code
will use all 64 bits of the pointer.
6.7.1 Pascal Language Features Not Supported with 64-Bit Pointers
Several Pascal features are not supported with 64-bit pointers. These features are:
var quad_ptr : [quad] ^integer; begin quad_ptr := my_alloc_routine(size(integer)); read(quad_ptr^); end |
type s32 = packed array [1..32] of char; var qp : [quad] ^s; begin qp := my_alloc_routine(size(s32)); some_routine( %stdescr qp^ ); end; |
type s32 = packed array [1..32] of char; var qp : [quad] ^s; procedure a( p : packed array [l..u:integer] of char ); begin writeln(a); end; procedure b( var p : s32 ); begin a(p); { This will generate a bad descriptor } end; begin qp := my_alloc_routine(size(s32)); b(qp^); end; |
For routines that have parameters that are 64-bit pointers, the Pascal definition uses a 64-bit record type. The definition files do not support either the INTEGER64 datatype or 64-bit pointers.
You can override the formal definition inside of definition files by using a foreign mechanism specifier (that is, %IMMED, %REF, %STDESCR, and %DESCR) on an actual parameter.
For example, the following is an example of calling lib$get_vm_64 using %ref to override the definition from PASCAL$LIB_ROUTINES.PEN:
[inherit('sys$library:pascal$lib_routines')] program p64(input,output); const arr_size = (8192 * 10) div 4; ! Make each array be 10 pages type arr = array [1..arr_size] of integer; arrptr = [quad] ^arr; var ptr : arrptr; ptrarr : array [1..10] of arrptr; i,j,stat : integer; sum : integer64; ! PASCAL$LIB_ROUTINES.PAS on a V7.1 system contains ! the following definitions for LIB$GET_VM_64 ! !type ! $QUAD = [QUAD,UNSAFE] RECORD ! L0:UNSIGNED; L1:INTEGER; END; ! $UQUAD = [QUAD,UNSAFE] RECORD ! L0,L1:UNSIGNED; END; ! lib$routines$$typ4 = ^$QUAD; ! ![ASYNCHRONOUS] FUNCTION lib$get_vm_64 ( ! number_of_bytes : $QUAD; ! VAR base_address : [VOLATILE] lib$routines$$typ4; ! zone_id : $UQUAD := %IMMED 0) : INTEGER; EXTERNAL; ! ! Note that the BASE_ADDRESS parameter is a 64-bit pointer ! that will be returned by LIB$GET_VM_64. The definition ! incorrectly declared it as a pointer to a record that is ! quadword sized. ! begin ! Allocate memory with lib$get_vm_64. The definition of ! lib$get_vm_64 declares the return address parameter as ! a quadword-sized record since it doesn't have sufficient ! information to generate a INTEGER64 or other type. ! ! Use an explicit '%ref' foreign mechanism specifier to ! override the formal parameter's type definition and pass ! our pointer to lib$get_vm_64. ! writeln('arr_size = ',arr_size:1); for i := 1 to 10 do begin stat := lib$get_vm_64( size(arr), %ref ptrarr[i] ); if not odd(stat) then begin writeln('Error from lib$get_vm_64: ',hex(stat)); lib$signal(stat); end; writeln('ptrarr[',i:1,'] = ',hex(ptrarr[i])); end; ! Read/write all the memory locations to get some page faults ! writeln('Initialize all memory'); for i := 1 to 10 do for j := 1 to arr_size do ptrarr[i]^[j] := i + j; sum := 0; writeln('Add up all memory in reverse direction'); for i := 10 downto 1 do for j := arr_size downto 1 do sum := sum + ptrarr[i]^[j]; writeln('Sum of array contents = ',sum:1); end. |
On OpenVMS I64 and OpenVMS Alpha systems, the compiler allows the LONG and QUAD attributes to be specified on pointer types, as shown in the following example:
var long_ptr : ^integer; quad_ptr : [quad] ^integer; |
Both pointers point to integers, but long_ptr is 32 bits while quad_ptr is 64 bits.
This chapter provides details on the input/output (I/O) support provided for OpenVMS systems and discusses the following topics:
HP Pascal uses the Record Management Services (RMS) to perform I/O tasks at the system level. In this environment, all of the HP Pascal I/O model is supported; the model is based on RMS concepts. If these sections contain no information on a concept or element in the HP Pascal I/O model, then this environment supports the concept or element exactly as it is described in the HP Pascal for OpenVMS Language Reference Manual.
You can use RMS features through HP Pascal when you call the OPEN procedure. For instance, when you call this procedure, you can specify the file organization, the component format, and the access method.
If you choose to use additional features of RMS that are not available in the HP Pascal I/O model, you can write a user-action function that manipulates the RMS control blocks: the file access block (FAB), the record access block (RAB), and the extended attribute block (XAB). Once you write the user-action function, you pass the function name as a parameter to the OPEN procedure.
The HP Pascal I/O model allows you to use most of the features of RMS indexed files. However, if you wish to use segmented or null keys, you must write a user-action function.
When an existing indexed file is opened, the run-time library compares the keys in the file against the KEY attributes specified in the program. If no KEY attribute was specified for the corresponding key in the indexed file, then the comparison is bypassed and the open continues. The run-time library compares the position and the data type of the file's keys against the KEY attributes specified. If the KEY attribute explicitly specifies a collating sequence (ASCENDING or DESCENDING), then the specified sequence must match that of the key in the file. If no sequence is specified, either sequence is allowed. The CHANGES and DUPLICATES options are not checked.
In the HP Pascal I/O model, data items in a file are called
components. In RMS, these items are called records.
7.1.3 Count Fields for Variable-Length Components
Each variable-length component contains a count field as a prefix. This
count field contains the number of bytes in the rest of the component.
For files on tape, this count field is 4 bytes in length; for files on
disk, this count field is 2 bytes in length.
7.1.4 Variable-Length with Fixed-Length Control Field (VFC) Component Format
The HP Pascal I/O model does not provide a direct means to create files of variable-length components with fixed-length control fields (VFC). If you open a file of this component format, HP Pascal treats the file like a file of variable-length components. If you want to create files of this component format, you must write a user-action function.
The HP Pascal I/O model does not allow random access by record file address. If you want to use this type of access, you must write a user-action function.
RMS supports random access by Record File Address (RFA) for relative and indexed files, and for sequential files only on disk. The RFA is a unique number supplied for files on disk. The RFA remains constant as long as the record is in the file. RMS makes the RFA available to your program every time the record is stored or retrieved. Your program can either ignore the RFA or it can keep it as a random-access pointer to the record for subsequent accesses.
If your disk file is sequential with variable-length records, the RFA provides the only method for randomly accessing records of that file.
When you use the OPEN procedure, RMS applies default values for OpenVMS file specifications, and assigns values to FAB, RAB, XAB, and Name Block data structures.
Previous | Next | Contents | Index |