Previous | Contents | Index |
You can invoke system services in a Compaq Fortran program with a function reference or a subroutine CALL statement that specifies the system service you want to use. To specify a system service, use the form:
SYS$service-name(arg,...,arg) |
You pass arguments to the system services according to the requirements of the particular service you are calling; the service may require an immediate value, an address, the address of a descriptor, or the address of a data structure. Section 10.7.4 describes the Compaq Fortran syntax rules for each of these cases. See the OpenVMS System Services Reference Manual for a full definition of individual services.
The basic steps for calling system services are the same as those for
calling any external routine. However, when calling system services (or
Run-Time Library routines), additional information is often required.
The sections that follow describe these requirements.
10.7.1 Obtaining Values for System Symbols
OpenVMS uses symbolic names to identify the following values or codes for system services:
The values chosen determine the specific action performed by the service.
The OpenVMS System Services Reference Manual describes the symbols that are used with each system service. The VMS I/O User's Reference Volume describes the symbols that are used with I/O-related services.
The Compaq Fortran symbolic definition library FORSYSDEF contains Compaq Fortran source definitions for related groups of system symbols. Each related group of system symbols is stored in a separate text library module; for example, the library module $IODEF in FORSYSDEF contains PARAMETER statements that define the I/O function codes.
The library modules in FORSYSDEF correspond to the symbolic definition macros that OpenVMS MACRO programmers use to define system symbols. The library modules have the same names as the macros and contain Compaq Fortran source code, which is functionally equivalent to the MACRO source code. To determine whether you need to include other symbol definitions for the system service you want to use, refer to the documentation for that particular system service. If the documentation states that values are defined in a macro, you must include those symbol definitions in your program.
For example, the description for the flags argument in the SYS$MGBLSC (Map Global Section) system service states that "Symbolic names for the flag bits are defined by the $SECDEF macro." Therefore, when you call SYS$MGBLSC, you must include the definitions provided in the $SECDEF macro.
Library module $SYSSRVNAM in FORSYSDEF contains declarations for all system-service names. It contains the necessary INTEGER and EXTERNAL declarations for the system-service names. (The library module, once extracted from FORSYSDEF.TLB, also contains comments describing the arguments for each of the system services.) Also, library module $SSDEF contains system-service return status codes and is generally required whenever you access any of the services.
The library modules in FORSYSDEF contain definitions for constants, bit masks, and data structures. See Section 10.7.4.4 for a description of how to create data structure arguments in Compaq Fortran. Refer to Appendix D for a list of library modules that are in FORSYSDEF.
You can access the library modules in the FORSYSDEF library with the INCLUDE statement, using the following format:
INCLUDE '(library-module-name)' |
The notation library-module-name represents the name of a
library module contained in FORSYSDEF. The library FORSYSDEF is
searched if the specified library module was not found in a previously
searched library.
10.7.2 Calling System Services by Function Reference
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 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.7.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.7.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.7.4 Passing Arguments to System Services
The description of each system service in the 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.7.4.1 through Section 10.7.4.4.
You can determine the arguments required by a system service from the service description in the 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 Compaq Fortran declarations that you can use to pass any of the standard OpenVMS data types as arguments. OpenVMS data types are defined in the 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 | Compaq 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 1 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.5.) |
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.7.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.3.2.3) or the %VAL built-in function (see Section 10.2.3) whenever this method is required.
Immediate value arguments are used for input arguments only.
10.7.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.7.4.3 to determine what to do when "the address of a descriptor" is specified.) In Compaq Fortran, this argument-passing method is called "by reference."
Because this method is the Compaq Fortran default for passing numeric arguments, you need to specify the cDEC$ ATTRIBUTES REFERENCE directive (see Section 10.3.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 Compaq 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 Compaq 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.2.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.7.1.
10.7.4.5 Examples of Passing Arguments
Example 10-4 shows a complete subroutine that uses a data structure argument to the SYS$GETJPIW system service:
Example 10-4 Subroutine Using a Data Structure Argument |
---|
! Subroutine to obtain absolute and incremental values of process parameters: ! CPU time, Buffered I/O count, Direct I/O count, Page faults. SUBROUTINE PROCESS_INFO(ABS_VALUES, INCR_VALUES) ! Declare the arguments and working storage INTEGER (KIND=4) ABS_VALUES(4), INCR_VALUES(4), LCL_VALUES(4) INTEGER (KIND=4) STATUS, I ! Declare the SYS$GETJPIW item list data structure in a structure declaration STRUCTURE /GETJPI_STR/ INTEGER (KIND=2) BUFLEN /4/, ITMCOD /0/ INTEGER (KIND=4) BUFADR, RETLEN /0/ END STRUCTURE ! Create a record with the fields defined in the structure declaration RECORD /GETJPI_STR/ LIST(5) ! Declare the structure of an I/O Status Block STRUCTURE /IOSB_STR/ INTEGER (KIND=4) STATUS, RESERVED END STRUCTURE ! Declare the I/O Status Block RECORD /IOSB_STR/ IOSB ! Assign all static values in the item list LIST(1).ITMCOD = JPI$_CPUTIM LIST(2).ITMCOD = JPI$_BUFIO LIST(3).ITMCOD = JPI$_DIRIO LIST(4).ITMCOD = JPI$_PAGEFLTS ! Assign all item fields requiring addresses LIST(1).BUFADR = %LOC(LCL_VALUES(1)) LIST(2).BUFADR = %LOC(LCL_VALUES(2)) LIST(3).BUFADR = %LOC(LCL_VALUES(3)) LIST(4).BUFADR = %LOC(LCL_VALUES(4)) STATUS = SYS$GETJPIW(,,,LIST,IOSB,,) ! Perform system service call IF (STATUS) STATUS = IOSB.STATUS ! Check completion status IF (.NOT. STATUS) CALL EXIT (STATUS) ! Assign the new values to the arguments DO I=1,4 INCR_VALUES(I) = LCL_VALUES(I) - ABS_VALUES(I) ABS_VALUES(I) = LCL_VALUES(I) END DO RETURN END SUBROUTINE PROCESS_INFO |
Example 10-5 is an example of the typical use of an I/O system service. The program invokes SYS$QIOW to enable Ctrl/C trapping. When the program runs, it prints an informational message whenever it is interrupted by a Ctrl/C, and then it continues execution:
Example 10-5 Ctrl/C Trapping Example |
---|
PROGRAM TRAPC INCLUDE '($SYSSRVNAM)' INTEGER (KIND=2) TT_CHAN COMMON TT_CHAN CHARACTER (LEN=40) LINE ! Assign the I/O channel. If unsuccessful stop; otherwise ! initialize the trap routine. ISTAT = SYS$ASSIGN ('TT',TT_CHAN,,) IF (.NOT. ISTAT) CALL LIB$STOP(%VAL(ISTAT)) CALL ENABLE_CTRLC ! Read a line of input and echo it 10 READ (5,'(A)',END=999) LINE TYPE *, 'LINE READ: ', LINE GO TO 10 999 END SUBROUTINE ENABLE_CTRLC INTEGER (KIND=2) TT_CHAN COMMON TT_CHAN EXTERNAL CTRLC_ROUT ! Include I/O symbols INCLUDE '($IODEF)' INCLUDE '($SYSSRVNAM)' ! Enable Ctrl/C trapping and specify CTRLC_ROUT ! as routine to be called when Ctrl/C occurs ISTAT = SYS$QIOW( ,%VAL(TT_CHAN), %VAL(IO$_SETMODE .OR. IO$M_CTRLCAST),& ,,,CTRLC_ROUT,,%VAL(3),,,) IF (.NOT. ISTAT) CALL LIB$STOP(%VAL(ISTAT)) RETURN END SUBROUTINE ENABLE_CTRLC SUBROUTINE CTRLC_ROUT PRINT *, 'Ctrl/C pressed' CALL ENABLE_CTRLC RETURN END SUBROUTINE CTRLC_ROUT |
For more examples of calling system services and RTL routines, see Appendix E.
Previous | Next | Contents | Index |