HP OpenVMS Systems Documentation

Content starts here

User Manual

Previous Contents Index

19.3 Calling HP BASIC Subprograms from Other Languages

When you call a HP BASIC subprogram from another language, there are some additional considerations that you should be aware of. For example, although HP BASIC conforms to the OpenVMS Calling Standard, you should specify explicit passing mechanisms when calling a routine written in another language. The default passing mechanisms of BASIC may not match what the procedure expects. In the following section, FORTRAN refers to VAX FORTRAN and HP Fortran.

FORTRAN passes and receives numeric data by reference; only the default parameter-passing mechanisms are required for passing numeric data back and forth between FORTRAN and HP BASIC programs.

Both HP BASIC and FORTRAN pass strings by descriptor. However, FORTRAN subprograms cannot change the length of strings passed to them. Therefore, if you pass a string to a FORTRAN subprogram, you must make sure that the string is long enough to receive the result. You do this in one of two ways:

  • Pre-extend the string. Set the string variable equal to SPACE$(n), where n is large enough to receive the result.
  • Define the string as fixed-length. Name the string in a COMMON or MAP statement.

Because the length of the returned string does not change, it is either padded with spaces or truncated.

To pass an array to a FORTRAN subprogram, you must specify BY REF.

Note that FORTRAN arrays are one-based, while HP BASIC arrays are zero-based by default. For example, in FORTRAN the array Two_D(5,3) represents a 5 by 3 matrix, while in HP BASIC the array Two_d(5,3) represents a 6 by 4 matrix. You can adjust your array bounds in HP BASIC by using the keyword TO when defining the array bounds. For more information about array bounds, see Chapter 6.

When passing two-dimensional arrays as parameters, keep in mind that FORTRAN addresses array elements in column major order, while BASIC refers to array elements in row major order. That is, FORTRAN arrays are of the form Fortran_array(column,row), while HP BASIC array elements are addressed as Basic_array(row,column). The FORTRAN array Grid(x,y) is therefore referred to as GRID(y,x) in HP BASIC. You should reverse references to array elements when passing arrays between HP BASIC and FORTRAN program modules. You can do this in one of two ways:

  • Reverse array bounds in parameter lists
  • Switch row and column variables within loops in your program module

Example 19-1 shows a HP BASIC program that passes a two-dimensional array to a FORTRAN subprogram. The FORTRAN subprogram is shown in Example 19-2.

Example 19-1 BASIC Main Program

PROGRAM call_fortran
    ! The BASIC main program prints the array before
    ! calling the subroutine
        EXTERNAL SUB forsub (WORD DIM(,) BY REF)
        DIM WORD array_x(1 TO 10, 1 TO 5)
        FOR column = 1 TO 5
            FOR row = 1 TO 10
                array_x(row,column)=(10*row + column)
                PRINT array_x(row,column);
            NEXT row
        NEXT column

        CALL forsub(array_x(,) BY REF)


Example 19-2 FORTRAN Subprogram

C       The FORTRAN subprogram receives
C       and then prints the same array

        SUBROUTINE forsub(f_array)
        INTEGER*2 f_array(5,10)
        DO 20 row = 1,5
            TYPE *, (f_array(row,column), column = 1,10)
20      CONTINUE

You can pass only the data types that HP BASIC and FORTRAN have in common. You cannot pass a complex number from a FORTRAN program to a HP BASIC program, because HP BASIC does not support complex numbers. However, you can pass a complex number as two floating-point numbers and treat them independently in the HP BASIC program.

19.4 Calling System Routines

The steps for calling system routines are the same as those for calling any external routine. However, when calling system routines, you need to provide additional information, which is discussed in the following sections.

19.4.1 OpenVMS Run-Time Library Routines

The OpenVMS Run-Time Library routines are grouped according to the types of tasks they perform. The routines in each group have a prefix that identifies them as members of a particular OpenVMS Run-Time Library facility. Table 19-2 lists all the language-independent Run-Time Library facility prefixes and the types of tasks each facility performs.

Table 19-2 Run-Time Library Facilities
Facility Prefix Types of Tasks Performed
DTK$ DECtalk routines that are used to control the DECtalk device
LIB$ General purpose routines that obtain records from devices, manipulate strings, convert data types for I/O, allocate resources, obtain system information, signal exceptions, establish condition handlers, enable detection of hardware exceptions, and process cross-reference data
OTS$ Language-independent support routines that perform tasks such as data type conversions as part of a compiler's generated code

19.4.2 System Service Routines

System services are system routines that perform a variety of tasks such as controlling processes, communicating among processes, and coordinating I/O.


Table 19-3 System Services
Group Types of Tasks Performed
AST Allows processes to control the handling of ASTs
Change Mode Changes the access mode of particular routines
Condition Handling Designates condition handlers for special purposes
Lock Management Enables processes to coordinate access to shareable system resources
Process Control Creates, deletes, and controls execution of processes
Security Enhances the security of OpenVMS systems
Time and Timing Schedules events, and obtains and formats binary time values

19.4.3 System Routine Arguments

All of the system routine arguments are described in terms of the following information:

  • OpenVMS usage
  • Data type
  • Type of access allowed
  • Passing mechanism

OpenVMS usages are data structures that are layered on the standard OpenVMS data types. For example, the OpenVMS usage mask_longword signifies an unsigned longword integer that is used as a bit mask, and the OpenVMS usage floating_point represents any OpenVMS floating-point data type. Table 19-4 lists all the OpenVMS usages and the HP BASIC statements you need to implement them.

Table 19-4 OpenVMS Usages
OpenVMS Usage BASIC Implementation
access_bit_names Not applicable (NA)
access_mode BYTE (signed)
address LONG
address_range LONG address_range 1
RECORD address_range
LONG beginning_address
LONG ending_address
arg_list NA
ast_procedure EXTERNAL LONG FUNCTION ast_proc 1
boolean LONG
byte_signed BYTE
byte_unsigned BYTE 2
channel WORD
char_string STRING
complex_number RECORD complex
REAL real_part
REAL imaginary_part
cond_value LONG
context LONG
date_time QUAD
device_name STRING
ef_cluster_name STRING
ef_number LONG
exit_handler_block RECORD EHCB
LONG flink
LONG handler_addr
BYTE arg_count
LONG status_value_addr
fab NA
file_protection LONG
floating_point SINGLE
function_code RECORD function-code
WORD major-function
WORD subfunction
identifier LONG
io_status_block RECORD iosb
WORD iosb_field(1 to 4)
item_list_2 RECORD item_list_two
GROUP item(15)
WORD comp_length
WORD code
LONG comp_address
LONG terminator
item_list_3 RECORD item_list_3
GROUP item (15)
WORD buf_len
WORD code
LONG buffer_address
LONG length_address
LONG terminator
item_list_pair RECORD item_list_pair
GROUP item(15)
LONG code
LONG item_value
LONG terminator
END RECORD item_list_pair
item_quota_list RECORD item_quota_list
GROUP quota(n)
BYTE quota_name
LONG item_value
BYTE list_end
lock_id LONG
lock_status_block NA
lock_value_block NA
logical_name STRING
longword_signed LONG
longword_unsigned LONG 2
mask_byte BYTE
mask_longword LONG
mask_quadword QUAD
mask_word WORD
null_arg A null argument is indicated by a comma used as a placekeeper in the argument list.
octaword_signed BASIC$OCTAWORD 3
octaword_unsigned BASIC$OCTAWORD 3
page_protection LONG
process_id LONG
process_name STRING
quadword_signed QUAD
quadword_unsigned QUAD 2
rights_holder QUAD
rights_id LONG
rab NA
section_id QUAD
section_name STRING
system_access_id QUAD
time_name STRING
uic LONG
user_arg LONG
varying_arg Dependent upon application.
vector_byte_signed BYTE array(n)
vector_byte_unsigned BYTE array(n) 2
vector_longword_signed LONG array(n)
vector_longword_unsigned LONG array(n) 2
vector_quadword_signed QUAD array(n)
vector_quadword_unsigned QUAD array(n) 2
vector_word_signed WORD array(n)
vector_word_unsigned WORD array(n) 2
word_signed WORD
word_unsigned WORD 2

1Use the LOC function to pass the address of an AST routine to a system service. Specify BY VALUE for the passing mechanism.
2Although unsigned data structures are not directly supported in BASIC, you can substitute the signed equivalent provided you do not exceed the range of the signed data structure.
3The definition of the RECORD structures are included in the HP BASIC system definitions text library. See Section 19.4.4 for more information.

If a system routine argument is optional, it will be indicated in the format section of the routine description in one of the following ways:


If the comma appears outside the brackets, you must either pass a zero by value or use a comma in the argument list as a placeholder to indicate the place of the omitted argument. If this is the last argument in the list, you must still include the comma as a placeholder. If the comma appears inside the brackets, you can omit the argument altogether as long as it is the last argument in the list.

19.4.4 Including Symbolic Definitions

To enhance program development, BASIC allows you to use symbolic definitions. Symbolic definitions are names or symbols associated with values. These symbols are used in many ways; the value associated with a symbol can be a status code, a mask, or an offset into a data structure. Many system routines depend on values that are defined in separate symbol definition files. For example, the status code for successful completion has a value of one; however, this code for successful completion is defined in the system library (STARLET) as the symbol SS$_NORMAL.

A program might compare the status code returned by a system service to either the symbolic constant SS$_NORMAL or the integer value one. The program would execute the same way in either case. In the first case, the value for SS$_NORMAL is supplied at link time by the OpenVMS Linker. In the second case, the value 1 is included in the program as a literal constant.

The advantages of using symbolic definitions are as follows:

  • Because symbolic definition names are mnemonic, the program is easier to read and understand.
  • It is easier to write the symbolic definition and let the OpenVMS Linker fill in the value, than to look up the value associated with the symbol and include that value in the program.
  • Should the value associated with a symbol ever change, you must relink the program. To change a hard-coded definition, you must edit the source file, then recompile and relink.

Symbolic definitions used by system services are located in the default system library, STARLET.OLB.

For Run-Time Library routines, the only time that you need to include symbolic definitions is when you are calling an SMG$ routine, or when you are calling a routine that is a jacket to a system service. (A jacket routine in the Run-Time Library is a routine that provides a simpler, more easily used interface to a system service.) If you call a routine in the SMG$ facility, you must include the definition file SMGDEF. All system services, however, require that you include SSDEF to check status. Many other system services require other symbol definitions as well.

To determine whether or not you need to include other symbolic definitions for the system service you want to reference, see the documentation for that service. If the documentation states that values are defined in the specified macro, you must include those symbolic definitions in your program. BASIC provides a text library that contains symbolic definitions that can be accessed using the %INCLUDE directive. In the following example, the definition file, SMGDEF is included from the text library SYS$LIBRARY:BASIC$STARLET.TLB:


For more information about including text libraries, see Chapter 16.

19.4.5 Condition Values

Many system routines return a condition value that indicates success or failure. If a condition value is returned, you should check this value after you call a system routine and control returns to your program.

Condition values indicating success always appear first in the list of condition values for a particular routine, and success codes always have odd values. A success code that is common to many system routines is the condition value SS$_NORMAL, which indicates that the routine completed normally and successfully. You can test for this condition value as follows:

ret_status = SMG$CREATE_PASTEBOARD(pb_id)
IF (ret_status <> SS$_NORMAL) THEN
   CALL LIB$STOP(ret_status BY VALUE)

Because all success codes have odd values, you can check a return status for any success code. For example, you can cause execution to continue only if a success code is returned by including the following statements in your program:

ret_status = SMG$CREATE_PASTEBOARD(pb_id)
IF (ret_status AND 1%) = 0% THEN
   CALL LIB$STOP(ret_status BY VALUE)

In general, you can check for a particular success or failure code or you can test the condition value returned against all success codes or all failure codes.

Previous Next Contents Index