HP OpenVMS Systems Documentation |
HP Fortran for OpenVMS
|
Previous | Contents | Index |
In most cases, you should check the return status after calling a system service. Therefore, you should invoke system services by function reference rather than by issuing a call to a subroutine.
For example:
INCLUDE '($SSDEF)' INCLUDE '($SYSSRVNAM)' INTEGER (KIND=2) CHANNEL . . . MBX_STATUS = SYS$CREMBX(,CHANNEL,,,,,'MAILBOX') IF (MBX_STATUS .NE. SS$_NORMAL) GO TO 100 |
In this example, the system service referenced is the Create Mailbox system service. An INTEGER (KIND=2) variable (CHANNEL) is declared to receive the channel number.
The function reference allows a return status value to be stored in the variable MBX_STATUS, which can then be checked for correct completion on return. If the function's return status is not SS$_NORMAL, failure is indicated and control is transferred to statement 100. At that point, some form of error processing can be undertaken.
You can also test the return status of a system service as a logical value. The status codes are defined so that when they are tested as logical values, successful codes have the value true and error codes have the value false. The last line in the preceding example could then be changed to the following:
IF (.NOT. MBX_STATUS) GO TO 100 |
Refer to the HP OpenVMS System Services Reference Manual for information concerning return status
codes. The return status codes are included in the description of each
system service.
10.8.3 Calling System Services as Subroutines
Subroutine calls to system services are made like other subroutine calls. For example, to call the Create Mailbox system service, issue a call to SYS$CREMBX, passing the appropriate arguments to it, as follows:
CALL SYS$CREMBX(,CHANNEL,,,,,'MAILBOX') |
This call corresponds to the function reference described in
Section 10.8.2. The main difference is that the status code returned by
the system service is not tested. For this reason, you should avoid
this method and use a function reference when calling system services
whenever the service could fail for any reason.
10.8.4 Passing Arguments to System Services
The description of each system service in the HP OpenVMS System Services Reference Manual specifies the argument-passing method for each argument. Four methods are supported:
These methods are discussed separately in Section 10.8.4.1 through Section 10.8.4.4.
You can determine the arguments required by a system service from the service description in the HP OpenVMS System Services Reference Manual. Each system service description indicates the service name, the number of arguments required, and the positional dependency of each argument.
Table 10-6 lists the HP Fortran declarations that you can use to pass any of the standard OpenVMS data types as arguments. OpenVMS data types are defined in OpenVMS Programming Interfaces: Calling a System Routine.
Instead of using record structure declarations for most standard OpenVMS data types, you can consider using derived-type structures if you use the SEQUENCE statement and are careful of alignment. However, RMS control block structures must be declared as record structures (STRUCTURE statement).
OpenVMS Data Type | HP Fortran Declaration |
---|---|
access_bit_names |
INTEGER (KIND=4) (2,32)
or STRUCTURE /access_bit_names/ INTEGER (KIND=4) access_name_len INTEGER (KIND=4) access_name_buf END STRUCTURE !access_bit_names RECORD /access_bit_names/ my_names(32) |
access_mode | BYTE or INTEGER (KIND=1) |
address | INTEGER (KIND=4) |
address_range |
INTEGER (KIND=4) (2)
or STRUCTURE /address_range/ INTEGER (KIND=4) low_address INTEGER (KIND=4) high_address END STRUCTURE |
arg_list | INTEGER (KIND=4)(n) |
ast_procedure | EXTERNAL |
boolean | LOGICAL (KIND=4) |
byte_signed | BYTE or INTEGER (KIND=1) |
byte_unsigned | BYTE or INTEGER (KIND=1) 1 |
channel | INTEGER (KIND=2) |
char_string | CHARACTER (LEN= n) 2 |
complex_number |
COMPLEX (KIND=4)
3
COMPLEX (KIND=8) 3 |
cond_value | INTEGER (KIND=4) |
context | INTEGER (KIND=4) |
date_time | INTEGER (KIND=8) |
device_name | CHARACTER (LEN= n) |
ef_cluster_name | CHARACTER (LEN= n) |
ef_number | INTEGER (KIND=4) |
exit_handler_block |
STRUCTURE /exhblock/
INTEGER (KIND=4) flink INTEGER (KIND=4) exit_handler_addr BYTE(3) %FILL BYTE arg_count INTEGER (KIND=4) cond_value ! . ! .(optional arguments ... ! . one argument per longword) ! END STRUCTURE !cntrlblk RECORD /exhblock/ myexh_block |
fab |
INCLUDE '($FABDEF)'
RECORD /FABDEF/ myfab |
file_protection | INTEGER (KIND=4) |
floating_point |
REAL (KIND=4)
3
REAL (KIND=8) 3 DOUBLE PRECISION 3 REAL (KIND=16) 3 |
function_code | INTEGER (KIND=4) |
identifier | INTEGER (KIND=4) |
invo_context_blk |
INCLUDE '($LIBICB)'
RECORD /INVO_CONTEXT_BLK/ invo_context_blk |
invo_handle | INTEGER (KIND=4) |
io_status_block |
STRUCTURE /iosb/
INTEGER (KIND=2) iostat, ! return status INTEGER (KIND=2) term_offset, ! Loc. of terminator INTEGER (KIND=2) terminator, ! terminator value INTEGER (KIND=2) term_size ! terminator size END STRUCTURE RECORD /iosb/ my_iosb |
item_list_2 |
STRUCTURE /itmlst/
UNION MAP INTEGER (KIND=2) buflen,code INTEGER (KIND=4) bufadr END MAP MAP INTEGER (KIND=4) end_list /0/ END MAP END UNION END STRUCTURE !itmlst RECORD /itmlst/ my_itmlst_2(n) (Allocate n records, where n is the number item codes plus an extra element for the end-of-list item.) |
item_list_3 |
STRUCTURE /itmlst/
UNION MAP INTEGER (KIND=2) buflen,code INTEGER (KIND=4) bufadr,retlenadr END MAP MAP INTEGER (KIND=4) end_list /0/ END MAP END UNION END STRUCTURE !itmlst RECORD /itmlst/ my_itmlst_3(n) (Allocate n records where n is the number item codes plus an extra element for the end-of-list item.) |
item_list_pair |
STRUCTURE /itmlist_pair/
UNION MAP INTEGER (KIND=4) code INTEGER (KIND=4) value END MAP MAP INTEGER (KIND=4) end_list /0/ END MAP END UNION END STRUCTURE !itmlst_pair RECORD /itmlst_pair/ my_itmlst_pair(n) (Allocate n records where n is the number item codes plus an extra element for the end-of-list item.) |
item_quota_list |
STRUCTURE /item_quota_list/
MAP BYTE quota_name INTEGER (KIND=4) quota_value END MAP MAP BYTE end_quota_list END MAP END STRUCTURE !item_quota_list |
lock_id | INTEGER (KIND=4) |
lock_status_block |
STRUCTURE/lksb/
INTEGER (KIND=2) cond_value INTEGER (KIND=2) unused INTEGER (KIND=4) lock_id BYTE(16) END STRUCTURE !lksb RECORD /lksb/ my_lksb |
lock_value_block | BYTE(16) |
logical_name | CHARACTER (LEN= n) |
longword_signed | INTEGER (KIND=4) |
longword_unsigned | INTEGER (KIND=4) 1 |
mask_byte | INTEGER (KIND=1) ! (or BYTE) |
mask_longword | INTEGER (KIND=4) |
mask_quadword | INTEGER (KIND=8) |
mask_word | INTEGER (KIND=2) |
mechanism_args |
INCLUDE '($CHFDEF)'
RECORD /CHFDEF2/ mechargs ! (For more information, see Section 14.6.) |
null_arg | %VAL(0) ! (or an unspecified optional argument) |
octaword_signed | INTEGER (KIND=4)(4) |
octaword_unsigned | INTEGER (KIND=4)(4) 1 |
page_protection | INTEGER (KIND=4) |
procedure | INTEGER (KIND=4) |
process_id | INTEGER (KIND=4) |
process_name | CHARACTER (LEN= n) |
quadword_signed | INTEGER (KIND=8) |
quadword_unsigned | INTEGER (KIND=8) 1 |
rights_holder |
STRUCTURE /rights_holder/
INTEGER (KIND=4) rights_id INTEGER (KIND=4) rights_mask END STRUCTURE !rights_holder RECORD /rights_holder/ my_rights_holder |
rights_id | INTEGER (KIND=4) |
rab |
INCLUDE '($RABDEF)'
RECORD /RABDEF/ myrab |
section_id | INTEGER (KIND=4)(2) or INTEGER (KIND=8) |
section_name | CHARACTER (LEN= n) |
system_access_id | INTEGER (KIND=4)(2) or INTEGER (KIND=8) |
time_name | CHARACTER (LEN=23) |
transaction_id | INTEGER (KIND=4)(4) |
uic | INTEGER (KIND=4) |
user_arg | Any longword quantity |
varying_arg | Any appropriate type |
vector_byte_signed | BYTE(n) |
vector_byte_unsigned | BYTE(n) 1 |
vector_longword_signed | INTEGER(KIND=4) (n) |
vector_longword_unsigned | INTEGER(KIND=4) (n) 1 |
vector_quadword_signed | INTEGER(KIND=8) (n) |
vector_quadword_unsigned | INTEGER (KIND=8) (n) 1 |
vector_word_signed | INTEGER (KIND=2) (n) |
vector_word_unsigned | INTEGER (KIND=2) (n) 1 |
word_signed | INTEGER (KIND=2) (n) |
word_unsigned | INTEGER (KIND=2) (n) 1 |
Many arguments to system services are optional. However, if you omit an optional argument, you must include a comma (,) to indicate the absence of that argument. For example, the SYS$TRNLNM system service takes five arguments. If you omit the first and the last two arguments, you must include commas to indicate their existence, as follows:
ISTAT = SYS$TRNLNM(,'LNM$FILE_DEV','LOGNAM',,) |
An invalid reference results if you specify the arguments as follows:
ISTAT = SYS$TRNLNM('LOGNAM',LENGTH,BUFFA) |
This reference provides only three arguments, not the required five.
When you omit an optional argument by including an extra comma, the
compiler supplies a default value of zero (passed by immediate value).
10.8.4.1 Immediate Value Arguments
Value arguments are typically used when the description of the system service specifies that the argument is a "number," "mask," "mode," "value," "code," or "indicator." You must use either the cDEC$ ATTRIBUTES VALUE (see Section 10.4.2.3) or the %VAL built-in function (see Section 10.3.3) whenever this method is required.
Immediate value arguments are used for input arguments only.
10.8.4.2 Address Arguments
Use address arguments when the description of the system service specifies that the argument is "the address of." (However, refer to Section 10.8.4.3 to determine what to do when "the address of a descriptor" is specified.) In HP Fortran, this argument-passing method is called "by reference."
Because this method is the HP Fortran default for passing numeric arguments, you need to specify the cDEC$ ATTRIBUTES REFERENCE directive (see Section 10.4.2.3) or the %REF built-in function only when the data type of the argument is character.
The argument description also gives the hardware data type required.
For arguments described as "address of an entry mask" or "address of a routine," declare the argument value as an external procedure. For example, if a system service requires the address of a routine and you want to specify the routine HANDLER3, include the following statement in the declarations portion of your program:
EXTERNAL HANDLER3 |
Address arguments are used for both input and output:
INCLUDE '($SYSSRVNAM)' INTEGER (KIND=8) SYSTIM . . . ISTAT = SYS$GETTIM(SYSTIM) |
OpenVMS Type Required | Input Argument Declaration | Output Argument Declaration |
---|---|---|
Byte | BYTE, INTEGER (KIND=1), INTEGER (KIND=2), INTEGER (KIND=4) | BYTE, INTEGER (KIND=1) |
Word | INTEGER (KIND=2), INTEGER (KIND=4) | INTEGER (KIND=2) |
Longword | INTEGER (KIND=4) | INTEGER (KIND=4) |
Quadword | INTEGER (KIND=8) or INTEGER (KIND=4) (2) or properly dimensioned array | INTEGER (KIND=8) or INTEGER (KIND=4) (2) or properly dimensioned array |
Indicator | LOGICAL | |
Character string descriptor | CHARACTER (LEN= n) | CHARACTER (LEN= n) |
Entry mask or routine | EXTERNAL |
Descriptor arguments are used for input and output of character strings. Use a descriptor argument when the argument description specifies "address of a descriptor." Because this method is the HP Fortran default for character arguments, you need to specify the %DESCR built-in function only when the data type of the argument is not character.
On input, a character constant, variable, array element, or expression is passed to the system service by descriptor. On output, two items are needed:
In the following example of the Translate Logical Name system service (SYS$TRNLNM), the logical name LOGNAM is translated to its associated name or file specification. The output string and string length are stored in the variables EQV_BUFFER and W_NAMELEN, respectively:
INCLUDE '($LNMDEF)' INCLUDE '($SYSSRVNAM)' STRUCTURE /LIST/ INTEGER (KIND=2) BUF_LEN/255/ INTEGER (KIND=2) ITEM_CODE/LNM$_STRING/ INTEGER (KIND=4) TRANS_LOG INTEGER (KIND=4) TRANS_LEN INTEGER (KIND=4) END_ENTRY/0/ END STRUCTURE !LIST CHARACTER (LEN=255) EQV_BUFFER INTEGER (KIND=2) W_NAMELEN RECORD/LIST/ ITEM_LIST ITEM_LIST.TRANS_LOG = %LOC(EQV_BUFFER) ITEM_LIST.TRANS_LEN = %LOC(W_NAMELEN) ISTAT = SYS$TRNLNM(, 'LNM$FILE_DEV', 'FOR$SRC', ,ITEM_LIST) IF (ISTAT) PRINT *, EQV_BUFFER(:W_NAMELEN) END |
Data structure arguments are used when the argument description specifies "address of a list," "address of a control block," or "address of a vector." The data structures required for these arguments are constructed in HP Fortran with structure declaration blocks and the RECORD statement. The storage declared by a RECORD statement is allocated in exactly the order given in the structure declaration, with no space between adjacent items. For example, the item list required for the SYS$GETJPI (or SYS$GETJPIW) system service requires a sequence of items of two words and two longwords each. By declaring each item as part of a structure, you ensure that the fields and items are allocated contiguously:
STRUCTURE /GETJPI_STR/ INTEGER (KIND=2) BUFLEN, ITMCOD INTEGER (KIND=4) BUFADR, RETLEN END STRUCTURE ... RECORD /GETJPI_STR/ LIST(5) |
If a given field is provided as input to the system service, the calling program must fill the field before the system service is called. You can accomplish this with data initialization (for fields with values that are known at compile time) and with assignment statements (for fields that must be computed).
When the data structure description requires a field that must be filled with an address value, use the %LOC built-in function to generate the desired address (see Section 10.3.2). When the description requires a field that must be filled with a symbolic value (system-service function code), you can define the value of the symbol by the method described in Section 10.8.1.
Previous | Next | Contents | Index |