Compaq BASIC for OpenVMS
Alpha and VAX Systems
User Manual


Previous Contents Index

19.2.2.6 Rewinding a Tape

When you mount a magnetic tape, the system will position the tape at the load point (BOT). Your program can rewind the tape during program execution with the RESTORE statement. For example:


OPEN "MT1:" FOR OUTPUT AS FILE #2%, ACCESS READ 
   .
   .
   .
PUT #2% 
RESTORE #2% 
INPUT "NEXT RECORD"; NXTRECBB% 

If you rewind a tape opened without ACCESS READ before closing it, you erase all data written before the RESTORE operation.

19.2.2.7 Closing a Tape

The CLOSE statement ends I/O to the tape. For example, the following statement ends input and output to the tape open on channel #12.


CLOSE #12% 

If you opened the file with ACCESS READ, CLOSE has no further effect. If you opened the file without specifying ACCESS READ and the tape is not write-locked (that is, if the plastic write ring is in place), BASIC does the following:

The tape is not rewound unless you specified RESTORE in your program.

19.2.3 Device-Specific I/O to Disks

When performing device-specific I/O to disks, you write and read data with PUT and GET statements. The data must fit in 512-byte blocks, and you must do your own blocking and deblocking with MAP/REMAP or MOVE statements. Note that, when accessing disks with device-specific I/O operations, you are performing logical I/O. Because of this, you should be careful not to overwrite block number zero, which is often the disk's boot block. You must have LOG_IO privileges to perform these operations.

The following sections describe device-specific I/O to disks.

19.2.3.1 Assigning and Mounting a Disk

You must allocate a disk unit to your process before starting operations. The following command line assigns disk DUA3: to your process:


$ ALLOCATE DUA3:

When you perform I/O directly to a disk, you must mount the disk with the MOUNT command before accessing it. For example:


$ MOUNT/FOREIGN DUA3:

You can then open the disk for input or output.

19.2.3.2 Opening a Disk File for Output

To create and open the disk file, you use the OPEN statement. For example:


OPEN "DUA3:" FOR OUTPUT AS FILE #2%, SEQUENTIAL FIXED, & 
       RECORDSIZE=512 

You can then write data to the disk.

The record size determined by the MAP or RECORDSIZE clause must be an integer multiple of 512 bytes.

19.2.3.3 Opening a Disk File for Input

To open an existing disk file, you also use the OPEN statement. For example:


OPEN "DUA1:" FOR INPUT AS FILE #4%, SEQUENTIAL FIXED, & 
       RECORDSIZE=512 

You can then read data from the disk.

The record size determined by the MAP or RECORDSIZE clause must be an integer multiple of 512 bytes. The default is 512.

Specify ACCESS READ in the OPEN statement if you only plan to read from the disk.

19.2.3.4 Writing Records to a Disk File

You write data by defining a record buffer and writing the data to the file with PUT statements. The following program writes eight 64 byte records into each 512-byte block on the disk. When your program fills one block, writing continues in the next. The FILL field in the MOVE statement positions the data in the block.


INPUT "HOW MANY RECORDS TO WRITE"; J% 
OPEN "DBB2: FOR OUTPUT AS FILE #2%, SEQUENTIAL FIXED, & 
      RECORDSIZE=512 
FOR K% = 1% TO J% 
   FOR I% = 0% TO 7% 
        INPUT "NAME OF BOOK"; BOOK_NAME$ 
        INPUT "RETRIEVAL NUMBER"; RET_NUM% 
        INPUT "SUBJECT AREA"; SUBJ$ 
        MOVE TO #2%, FILL$ = I% * 64%, BOOK_NAME$, RET_NUM%, SUBJ$ 
   NEXT I% 
PUT #2% 
NEXT K% 
CLOSE #2 

When you write records, BASIC does not prefix the records with any count bytes.

19.2.3.5 Reading Records from a Disk File

You read data by defining a record buffer and reading the data from the device with GET statements. After the data has been retrieved with a GET statement you can deblock the data with MOVE or REMAP statements.

In the following example, each disk block contains twelve 40-byte records. Each record contains a 32-byte string, a 4-byte SINGLE number, and a 4-byte LONG integer. After each GET operation, the FOR...NEXT loop uses the REMAP statement to redefine the position of the variables in the record. At the end of the file, the program closes the file. See Chapter 8 and the Compaq BASIC for OpenVMS Alpha and VAX Systems Reference Manual for more information about the MAP, MAP DYNAMIC, and REMAP statements.


MAP (SAM) FILL$ = 512 
MAP DYNAMIC (SAM) STRING PRT_ID, SINGLE MAFLD, LONG ADIR_OLDN 
OPEN "DUA1:" FOR INPUT AS FILE #2%, SEQUENTIAL FIXED, & 
            ACCESS READ, MAP SAM 
WHEN ERROR USE err_hand 
WHILE 1% = 1% 
     GET #2% 
     FOR I% = 0% TO 11% 
         REMAP (SAM) STRING FILL(I% * 40%), PRT_ID = 32, MAFLD, ADIR_OLDN 
         PRINT PRT_ID, MAFLD, ADIR_OLDN 
     NEXT I% 
NEXT 
END WHEN 
HANDLER err_hand 
  IF ERR <> 11% 
    THEN 
      EXIT HANDLER 
  END IF 
END HANDLER 
CLOSE #2% 
END 

19.3 I/O to Mailboxes

A mailbox is a record I/O device that passes data from one process to another. You can use a valid mailbox name as a file name, and treat that mailbox as a normal record file. You must have TMPMBX or PRMMBX privilege to create mailboxes. Mailboxes are created and deleted by system services. For more information about using system services in BASIC programs, see Chapter 20.

Use the EXTERNAL statement to define the SYS$CREMBX system service that creates the mailbox. In BASIC programs, you create mailboxes by invoking SYS$CREMBX as a function passing either a channel argument and a string literal or a logical name for the mailbox. For example:


EXTERNAL INTEGER FUNCTION SYS$CREMBX 
SYS$STATUS% = SYS$CREMBX(,CHAN%,,,,,"CONFIRMATION_MBX") 

If you supply a logical name for the mailbox, be sure that it is in uppercase letters. Once you create the mailbox, you can use it as a logical file name.

The following two examples, when executed on two separate processes, allow you to send and receive data from one process to another.

Example 1


DECLARE STRING passenger_name, Confirm_msg 
OPEN "CONFIRMATION_MBX" AS FILE #1% 
INPUT "WHAT IS THE PASSENGER NAME"; passenger_name 
PRINT #1%, passenger_name 
LINPUT #1%, confirm_msg 
PRINT confirm_msg 
END 

Example 2


MAP (res) STRING passenger_name = 32% 
DECLARE WORD mbx_chan, LONG sys_status 
EXTERNAL LONG FUNCTION sys$crembx (LONG, WORD, LONG, LONG,    & 
                                     LONG, LONG, STRING) 
WHEN ERROR USE err_trap 
sys_status = sys$crembx ( ,mbx_chan,,,,,"CONFIRMATION_MBX") 
OPEN "CONFIRMATION_MBX" FOR INPUT AS FILE #1% 
LINPUT #1%, passenger_name 
OPEN "RESER.LST" FOR INPUT AS FILE #2%,            & 
        ORGANIZATION INDEXED, MAP RES, ACCESS READ            & 
        PRIMARY passenger_name 
FIND #2%, KEY #0% EQ passenger_name 
RECEIVING.MSG$ = "Passenger reservation confirmed" 
PRINT #1%, RECEIVING.MSG$ 
END WHEN 
HANDLER err_trap 
    IF (ERR = 155) 
       THEN 
       RECEIVING.MSG$ = "Reservation does not exist" 
       ELSE 
       EXIT HANDLER 
    END IF 
END HANDLER 
CLOSE #2%, #1% 
END PROGRAM 

Example 1 requests a passenger name and sends it to the mailbox.

Example 2 looks up the name in an indexed file. If the passenger name exists, Example 2 writes the confirmation message to the mailbox. If the passenger name does not exist, the error handler writes an alternate message. Example 1 then reads the mailbox and returns the result.

BASIC treats the mailbox as a sequential file. You write to the file with the PRINT # or PUT statement, and read it with the INPUT #, LINPUT #, or GET statement.

When either program closes the mailbox, the other program receives an end-of-file error message when it attempts to read the mailbox.

Note

All mailbox operations are synchronous. Control does not pass back from a mailbox operation, such as a PUT, to your program until the other program completes the corresponding operation, such as a GET.

19.4 Network I/O

If your system supports DECnet for OpenVMS VAX facilities, and your computer is one of the nodes in a DECnet for OpenVMS VAX, you can communicate with other nodes in the network with BASIC program statements. BASIC lets you do the following:

19.4.1 Remote File Access

To write or read files at a remote site, include the node name as part of the file specification. For example:


OPEN "WESTON::DUA1:[HOLT]TEST.DAT;2" FOR INPUT AS FILE #2% 

You can also assign a logical name to the file specification, and use that logical name in all file I/O.

Note

You need NETMBX privileges to access files at a remote node.

If the account at the remote site requires a username and password, include this access string in the file specification. You do this by enclosing the access string in quotation marks and placing it between the node name and the double colon. The following file specification accesses the account [HOLT.TMP] on node WESTON by giving the username HOLT and the password PASWRD. After accessing the file, your BASIC program can read and write records as if the file were in your account.


OPEN 'WESTON"HOLT PASWRD"::DUA0:[HOLT.TMP]INDEXU.DAT;4' & 
          FOR INPUT AS FILE #1%, INDEXED, PRIMARY TEXT$ 

Do not use the CONNECT clause when opening a file on a remote node or BASIC will signal the error "Cannot open file" (ERR=162).

19.4.2 Task-to-Task Communication

BASIC supports task-to-task communication if your account has NETMBX privileges.

Follow these steps for task-to-task communication:

  1. Establish a command file at the remote site to execute the program you want. The program must be in executable image format. For example, you can create the file MARG.COM at the remote site. MARG.COM contains a line to run an image (in this case, COPYT.EXE).


    $ RUN COPYT
    

    The OPEN statements in the programs at both nodes must specify the same file attributes.

  2. Start task-to-task communication by accessing the command file at the remote site. For example, a program at the local node could contain the following line:


    OPEN 'WESTON::"TASK = MARG"' AS FILE #1%, SEQUENTIAL 
    

  3. The system then assigns the logical name SYS$NET to the program at the local node. At the remote node, the program (COPYT.EXE) must use this logical for all operations. For example:


    OPEN 'SYS$NET' FOR INPUT AS FILE #1%, SEQUENTIAL 
    

  4. The two programs can then exchange messages. The programs must have a complementary series of send/receive statements.


!Local Program 
MAP (SJK) MSG$ = 32% 
OPEN 'WESTON"DAVIS PSWRD"::"TASK = MARG"' & 
        FOR OUTPUT AS FILE #1%, SEQUENTIAL, MAP SJK 
LINPUT "WHAT IS THE CUSTOMER NAME"; MSG$ 
PUT #1% 
GET #1% 
PRINT MSG$ 
CLOSE #1% 
END 


!Remote Node Program 
   .
   .
   .
10   MAP (SJK) MSG$ = 32% 
     MAP (FIL) NAME$ = 32%, RESERVATION$ = 64% 
     OPEN 'SYS$NET' FOR INPUT AS FILE #1%, SEQUENTIAL, & 
            MAP SJK 
     OPEN 'RESER.DAT'FOR INPUT AS FILE #2%,  & 
              INDEXED FIXED, PRIMARY NAME$, MAP FIL 
     GET #1% 
     MSG$ = "NAME CONFIRMED" 
     WHEN ERROR IN 
100  FIND #2%, KEY 0% EQ MSG$ 
     USE 
        IF ERR = 153 
          THEN 
             MSG$ = "ERROR IN NAME" 
          ELSE 
             EXIT HANDLER 
        END IF 
     END WHEN 
 
     PUT #1% 
   .
   .
   .
     CLOSE #2%, 1% 
     END 

The task-to-task communication ends when the files are closed.

See the DECnet for OpenVMS Networking Manual and the OpenVMS System Manager's Manual for more information.

19.4.3 Accessing a VAX Rdb/VMS Database

If you have purchased a VAX Rdb/VMS development license, you can store and access data in a VAX Rdb/VMS database from a BASIC program. To do this, you embed RDO statements in your BASIC program. Each line of an RDO statement must be preceded by the Rdb/VMS statement flag (&RDB&). BASIC line numbers cannot be included in any RDO statement line. You then precompile your program with the Rdb/VMS precompiler. The precompiler translates the RDO statements into BASIC statements that make direct calls to Rdb/VMS.


Chapter 20
Using BASIC in the Common Language Environment

The Compaq BASIC compiler lets you call external routines from a BASIC program. Herein, Alpha BASIC refers to Compaq BASIC for OpenVMS Alpha, and VAX BASIC refers to Compaq BASIC for OpenVMS VAX.

This chapter shows you how to call the following:

The terms routine, procedure, and function are used throughout this chapter. A routine is a closed, ordered set of instructions that performs one or more specific tasks. Every routine has an entry point (the routine name), and may or may not have an argument list. Procedures and functions are specific types of routines: a procedure is a routine that does not return a value, while a function is a routine that returns a value by assigning that value to the function's identifier.

System routines are prewritten OpenVMS routines that perform common tasks such as finding the square root of a number or allocating virtual memory. You can call any system routine from BASIC provided that the data structures necessary for that routine are supported. The system routines used most often are OpenVMS Run-Time Library routines and system services. System routines, which are discussed later in this chapter, are documented in detail in the OpenVMS Run-Time Library Routines Volume and the OpenVMS System Services Reference Manual.

20.1 Specifying Parameter-Passing Mechanisms

When you pass data between routines that are not written in the same language, you have to specify how you want that data to be represented and interpreted. You do this by specifying a parameter-passing mechanism. The general parameter-passing mechanisms and their keywords in BASIC are as follows:

The following sections outline each of these parameter-passing mechanisms in more detail.

20.1.1 Passing Parameters by Reference

When you pass a parameter by reference, BASIC passes the address at which the actual parameter value is stored. In other words, your routine has access to the parameter's storage address; therefore, you can manipulate and change the value of this parameter. Any changes that you make to the value of the parameter in your routine are reflected in the calling routine as well.

20.1.2 Passing Parameters by Descriptor

A descriptor is a data structure that contains the address of a parameter, along with other information such as the parameter's data type and size. When you pass a parameter by descriptor, the BASIC compiler passes the address of a descriptor to the called routine. You usually use descriptors to pass parameters that have unknown lengths, such as the following:

Like parameters passed by reference, any change made to the value of a parameter passed by descriptor is reflected in the calling routine.

20.1.3 Passing Parameters by Value

When you pass a parameter by value, you pass a copy of the parameter value to the routine instead of passing its address. Because the actual value of the parameter is passed, the routine does not have access to the storage location of the parameter; therefore, any changes that you make to the parameter value in the routine do not affect the value of that parameter in the calling routine.

Both Alpha BASIC and VAX BASIC are able to pass actual parameters by value, but only Alpha BASIC allows formal parameters to be passed by value.

20.1.4 BASIC Default Parameter-Passing Mechanisms

There are default parameter-passing mechanisms established for every data type you can use with BASIC. Table 20-1 shows which BASIC data types you can use with each parameter-passing mechanism.

Table 20-1 Valid Parameter-Passing Mechanisms
Parameter BY VALUE BY REF BY DESC
Integer and Real Data      
Variables Yes Yes 1 Yes
Constants Yes Local
copy 1
Local
copy
Expressions Yes Local
copy 1
Local
copy
Elements of a
nonvirtual array
Yes Yes 1 Yes
Virtual
array elements
Yes Local
copy 1
Local
copy
Nonvirtual
entire array
No Yes Yes 1
Virtual
entire array
No No No
Packed Decimal Data      
Variables No Yes 1 Yes
Constants No Local
copy 1
Local
copy
Expressions No Local
copy 1
Local
copy
Nonvirtual
array elements
No Yes 1 Yes
Virtual
array elements
No Local
copy 1
Local
copy
Nonvirtual
entire arrays
No Yes Yes 1
Virtual
entire arrays
No No No
String Data      
Variables No Yes Yes 1
Constants No Local
copy
Local
copy 1
Expressions No Local
copy
Local
copy 1
Nonvirtual
array elements
No Yes Yes 1
Virtual
array elements
No Local
copy
Local
copy 1
Nonvirtual
entire arrays
No Yes Yes 1
Virtual
entire arrays
No No No
Other Parameters      
RECORD variables No Yes 1 No
RFA variables No Yes 1 No


1Specifies the default parameter-passing mechanism.


Previous Next Contents Index