# Compaq BASIC for OpenVMS
Alpha and VAX Systems
User Manual

Previous | Contents | Index

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.

## 20.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:

    %INCLUDE "SMGDEF" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET.TLB"

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

## 20.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)
    END IF

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)
    END IF

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.

# 20.5 Examples of Calling System Routines

This section provides complete examples of calling system routines from BASIC. In addition to the examples provided, the VMS Run-Time Library Routines Volume and the OpenVMS System Services Reference Manual also provide examples for selected routines. See these manuals for help about the use of a specific system routine.

Example 20-3 uses a function that invokes the SYS$TRNLNM system service. SYS$TRNLNM translates a logical name to an equivalence name. It places the equivalence name string into a string variable you supply in the parameter list.

System services never change a string variable's length. Therefore, if you use a system service that returns a string, be sure that the receiving string variable is long enough for the returned data. You can make sure of this in one of two ways:

- Define the string variable's length in a MAP, COMMON, or RECORD definition.
- Assign a long string to the variable (for example, A$ = SPACE$(80)). This pre-extends the variable so that it is long enough to receive all of the returned data.

Example 20-3 Calling System Services

    10   !This function attempts to translate a logical name while searching
         !through all of the tables defined in LNM$DCL_LOGICAL.  If the translation
         !is successful, $TRNLNM returns the equivalence name string.

         FUNCTION STRING Translate(STRING Logical_name)
         EXTERNAL LONG FUNCTION SYS$TRNLNM (LONG, STRING, STRING, LONG, ITEM_LIST)
         EXTERNAL LONG CONSTANT LNM$M_CASE_BLIND, LNM$_STRING, SS$_NORMAL

         !Declare the parameters
         DECLARE LONG attributes,   &
                      trans_status
         DECLARE WORD equiv_len

         !Declare the value returned by the function.
         DECLARE LONG CONSTANT Buffer_length = 255
         RECORD item_list
         GROUP item (1)
                 VARIANT
                      CASE
                         WORD Buf_len
                         WORD Code
                         LONG Buffer_address
                         LONG Length_address
                       CASE
                         LONG Terminator
                  END VARIANT
          END GROUP item
          END RECORD item_list
          !Declare an instance of the record

          DECLARE ITEM_LIST TRNLNM_ITEMS

          !Define a common area for Translation_buffer

          COMMON (Trans_buffer) &
                  STRING Translation_buffer = Buffer_length

          !Setting TRN$LNM to not distinguish between uppercase and lowercase
          !letters in the logical name to be translated.

          Attributes = LNM$M_CASE_BLIND
          !Assign values to each record item.

          TRNLNM_ITEMS::item(0)::Buf_len = Buffer_length
          TRNLNM_ITEMS::item(0)::Code = LNM$_STRING
          TRNLNM_ITEMS::item(0)::Buffer_address = LOC(Translation_buffer)
          TRNLNM_ITEMS::item(0)::Length_address = LOC(Equiv_len)
          TRNLNM_ITEMS::item(1)::Terminator = 0%

          !Invoke the function

          TRANS_STATUS = SYS$TRNLNM(attributes,"LNM$DCL_LOGICAL", logical_name, &
                                    ,trnlnm_items)
          !Check the condition value

          IF trans_status AND SS$_NORMAL
          THEN
                   Translate = LEFT(Translation_buffer, Equiv_len)
          ELSE
                   Translate = ""
          END IF
          END FUNCTION

Example 20-4 is a program that demonstrates the use of the system service $QIOW. Unlike SYS$QIO, SYS$QIOW performs synchronously; SYS$QIOW returns a condition value to the caller after I/O operation is complete.

Example 20-4 Program Displaying the$QIOW System Service Routine

    10  !Declare SYS$QIOW as an EXTERNAL FUNCTION

        EXTERNAL LONG FUNCTION SYS$QIOW(,WORD BY VALUE,LONG BY VALUE,WORD DIM() &
                                         BY REF,,,STRING BY REF,LONG BY VALUE,, &
                                         LONG BY VALUE,,)
        !Declare SYS$ASSIGN as an EXTERNAL FUNCTION

        EXTERNAL LONG FUNCTION SYS$ASSIGN(STRING,WORD,,)

        EXTERNAL LONG CONSTANT IO$_WRITEVBLK
        !Declare the parameters

        DECLARE STRING my_term, out_str, &
                WORD term_chan, counter, stat_block(3),&
                LONG ret_status, msg_len, car_cntrl

        out_str = "Successful $QIOW output!"
        my_term = "SYS$COMMAND"
        msg_len = LEN(out_str)
        car_cntrl = 32%
        !Assign a channel to the terminal
        ret_status = SYS$ASSIGN(my_term, term_chan, ,)
        CALL LIB$STOP(ret_status BY VALUE) IF (ret_status AND 1%) = 0%
        !Output the message four times
        FOR counter = 1% to 4%
            ret_status = SYS$QIOW(,term_chan BY VALUE, IO$_WRITEVBLK BY VALUE, &
                                   stat_block() BY REF,,,out_str BY REF,       &
                                   msg_len BY VALUE,,car_cntrl BY VALUE,,)
            CALL LIB$STOP(ret_status BY VALUE) IF (ret_status AND 1%) = 0%
            CALL LIB$STOP(stat_block(0%) BY VALUE) &
                          IF (stat_block(0%) and 1%) = 0%
        NEXT counter

        END

Output

    Successful $QIOW output!
    Successful $QIOW output!
    Successful $QIOW output!
    Successful $QIOW output!

In addition to invoking the function SYS$QIOW, the previous example also invokes the function SYS$ASSIGN. This function provides a process with an I/O channel so that input and output operations can be performed on a logical device name (my_term). As soon as SYS$ASSIGN is invoked and a path is established to the device, a counter is set up to invoke the $QIOW function four times. Once all I/O operations are complete, $QIOW returns to the caller.

# 20.6 The OpenVMS Calling Standard

The primary purpose of the OpenVMS Calling Standard is to define the concepts for invoking routines and passing data between them. For more information, see the OpenVMS Calling Standard.

# 20.7 Additional Information

The information provided on system routines in this chapter is general to all system services and OpenVMS Run-Time Library routines. For specific information about these routines, see the VMS Run-Time Library Routines Volume and the OpenVMS System Services Reference Manual.

# Chapter 21
Libraries and Shareable Images

Libraries and shareable images allow you to access program symbols and incorporate commonly used routines into your source code. This chapter describes how to create and access libraries and shareable images in Compaq BASIC. (Compaq BASIC for OpenVMS Alpha is referred to as Alpha BASIC; Compaq BASIC for OpenVMS VAX is referred to as VAX BASIC.)

# 21.1 Overview of Libraries

Libraries are files that can contain object modules, text modules, and shareable images. There are two types of libraries: system-supplied and user-supplied. System-supplied libraries are provided by the OpenVMS system, and user-supplied libraries are libraries that you create.

Shareable images are similar to libraries; they contain code that can be shared by other programs. However, shareable images contain executable code rather than object code.

If you have routines that are used in many programs, placing the routines in object module libraries or shareable image libraries lets you access them at link time. You do not need to include the routines in the source code, thus shortening compilation time and conserving disk space.

If you have routines that are used simultaneously by many different programs, placing the routines in installed shareable images can improve performance at run time, conserve main physical memory, and reduce paging I/O because one copy of the executable code is shared by all users.

Object module libraries, shareable image libraries, and shareable images can be accessed in the VAX BASIC Environment as well as at DCL command level. When you link programs at DCL command level, these libraries can contain object code created by any native mode compiler or assembler.

When you run a program in the VAX BASIC Environment, you can access:

- Object libraries containing only BASIC object code (object code from SUB, FUNCTION, and PICTURE subprograms)
- Shareable image libraries that contain BASIC or non BASIC object code (such as a transfer vector written in VAX MACRO)

Only BASIC subprograms can be loaded into the environment with the LOAD command.

For a more thorough understanding of libraries and shareable images, see the OpenVMS Linker Utility Manual and the Guide to Creating Modular Library Procedures. See the OpenVMS System Manager's Manual for more information about installing shareable images. For information about text libraries, see Chapter 17.

# 21.2 System-Supplied Libraries

If symbols are unresolved after the OpenVMS Linker (linker) searches all user-supplied libraries, the linker goes on to search the files in the default system library. The OpenVMS system supplies the following libraries:

System Library | Description
--- | ---
IMAGELIB.OLB | Contains symbol tables for all Run-Time Library (RTL) shareable images that are part of the OpenVMS operating system---for example, an OpenVMS RTL routine is called Lib$FAO.
STARLET.OLB | An object module library containing the object files used to create the shareable image version of the OpenVMS RTL, and other less frequently used procedures. If program symbols remain unresolved after the OpenVMS Linker searches IMAGELIB.OLB, the linker then searches this library.

The linker searches modules in the following order:

1. Modules and libraries specified in the LINK command line, in the order given
2. User-supplied libraries (logicals of the form LNK$LIBRARY and LNK$LIBRARY_1 through LNK$LIBRARY_999)
3. Images contained in IMAGELIB.OLB
4. Modules contained in STARLET.OLB

The linker only includes references to needed shareable images in the image being created. You can use the /NOSYSSHR qualifier to the LINK command to suppress the linker's search of RTL shareable images. Similarly, you can use the /NOSYSLIB qualifier to suppress the linker's search of both RTL shareable images and STARLET.OLB.

The linker searches user-supplied libraries before searching the default system library. If one of your modules has the same name (program symbol) as an OpenVMS System Service or an RTL routine, the linker includes your module in the resulting image rather than the system service or RTL routine.

# 21.3 Creating User-Supplied Object Module Libraries

You create a user-supplied object module library with the DCL command LIBRARY. Specify a library file specification as well as a list of the program modules you want to insert into the library. For example:

    $ BASIC MODULE1,MODULE2
    $ LIBRARY/CREATE TESTLIB1.OLB MODULE1.OBJ,MODULE2.OBJ

In the previous example, the BASIC command creates object files from MODULE1.BAS and MODULE2.BAS. The LIBRARY command creates an object module library named TESTLIB1.OLB and inserts MODULE1.OBJ and MODULE2.OBJ into that library. See the OpenVMS DCL Dictionary for more information about the LIBRARY command.

## 21.3.1 Accessing User-Supplied Object Module Libraries in the BASIC Environment

BASIC allows you to automatically access user-supplied object module libraries containing object files created by BASIC. Assign the logical name BASIC$LIBn (n represents a number from 0 to 9) to each library you want to access. For example:

    $ DEFINE BASIC$LIB0 USER$$DEV:[SMITH]TESTLIB.OLB

After you enter this command, a program executing in the VAX BASIC Environment automatically accesses USER$$DEV:[SMITH]TESTLIB.OLB to resolve program symbols. Note that this command assigns BASIC$LIB0 as a process-wide logical name. A privileged user can also define a BASIC library as a groupwide or systemwide logical name.

## 21.3.2 Accessing User-Supplied Object Module Libraries at DCL Level

To access user-supplied object module libraries at DCL level, specify the /LIBRARY qualifier to the DCL command LINK. For example:

    $ LINK MAIN,TESTLIB/LIBRARY

This command instructs the linker to search the library TESTLIB.OLB for any unresolved symbols in the BASIC object module MAIN.OBJ.

Also, you can explicitly include a module from a library with the /INCLUDE qualifier. For example:

    $ LINK MAIN,TESTLIB/LIBRARY/INCLUDE = (module1,module2)

This command instructs the linker to include module1 and module2 from the library TESTLIB.OLB, whether or not it needs these modules to resolve symbols.

As in the VAX BASIC Environment, BASIC at DCL level allows you to access user-supplied object module libraries automatically. However, a program executing at DCL level does not automatically search libraries that are assigned to the logical name BASIC$LIB0. Instead, the linker searches libraries that are assigned to the logical name LNK$LIBRARY. If you have more than one library for the linker to search, you must number these libraries consecutively; otherwise, the linker does not search past the first missing logical name. The linker allows you to number libraries from 1 to 999.

For example:

    $ DEFINE LNK$LIBRARY USER$$DEV:[KELLY]TESTLIB.OLB
    $ DEFINE LNK$LIBRARY_1 USER$$DEV:[KELLY]TESTLIB1.OLB
    $ DEFINE LNK$LIBRARY_2 USER$$DEV:[KELLY]TESTLIB2.OLB

After you issue these commands, a program executing at DCL level automatically accesses USER$$DEV:[KELLY]TESTLIB.OLB, USER$$DEV:[KELLY]TESTLIB1.OLB, and USER$$DEV:[KELLY]TESTLIB2.OLB to resolve program symbols.

# 21.4 Shareable Images

Shareable images are not directly executable. They contain executable code that can be shared by other images and are intended to be included by the linker in other images. You can access shareable images both in the VAX BASIC Environment and at DCL level, as described in the following sections.

The benefits of using shareable images include:

- Conserving disk storage space
- Conserving main physical memory
- Reducing paging I/O
- Allowing shared memory-resident databases
- Eliminating the need to relink programs that access a new version of a shared routine

Note Some of these benefits can only be realized if the shareable image is installed with the OpenVMS Install utility (Install).

To create a shareable image, use the /SHAREABLE qualifier with the DCL command LINK and specify at least one object module. For example:

    $ LINK/SHAREABLE prog1

This command creates an image that can be linked to other programs. You cannot execute a shareable image with the DCL command RUN.

When a program is linked with a shareable image, the required shareable image code is not included in the created executable image on the disk. This code is included by the image activator at run time. Therefore, many programs can reside on disk and be bound with a particular shareable image, and only one physical copy of that shareable image file needs to exist on disk.

If a shareable image has been installed using the OpenVMS Install utility, you conserve physical memory and potentially reduce paging I/O. Many processes can include the physical memory pages of an installed shareable image in their address space. This reduces the requirements for physical memory.

Paging occurs when a process attempts to access a virtual address that is not in the process working set. When this page fault occurs, the page is either in a disk file, in which case paging I/O is required, or is already in physical memory. If a page fault occurs for a shared page, the shared page may already be resident in memory and no paging I/O is required.

## 21.4.1 Accessing Shareable Images in the BASIC Environment

To access a shareable image in the VAX BASIC Environment, create a shareable image library and place the shareable image you want to use in that library. See Section 21.4.2 for information about creating a shareable image.

Use the DCL command LIBRARY with the /CREATE and /SHARE qualifiers to create a shareable image library. For example:

    $ LIBRARY/CREATE/SHARE MYLIB PROG1

This command creates the shareable image library MYLIB and inserts the shareable image PROG1 in that library.

Once you create a shareable image library, you must define the logical name BASIC$LIBn (n represents a number from 0 to 9) to point to the library. For example:

    $ DEFINE BASIC$LIB0 DEV$$DISK:[BOB.LIBRARIES]MYLIB

Once this command executes, a program executing in the VAX BASIC Environment automatically accesses the library MYLIB as a shareable image library to resolve global names.

Any shareable images referenced by the shareable image library must reside in SYS$SHARE, or a logical name for the image must specify where the shareable image resides. For example:

    $ DEFINE PROG1 DEV$$DISK:[BOB.IMAGES]PROG1.EXE

Note Sharing of data between shareable images and programs being run in the VAX BASIC Environment is not supported.

Previous | Next | Contents | Index