HP OpenVMS Systems

BASIC
Content starts here

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:

  • Writes file trailer labels and two end-of-file marks following the last record
  • Backspaces over the last end-of-file mark

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:

  • Read and write files on a remote node as you do files on your own system (remote file access)
  • Exchange data with a process executing at a remote location (task-to-task communication)

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:

  • External routines written in other OpenVMS languages
  • OpenVMS Run-Time Library routines
  • OpenVMS system services

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:

  • By reference---BY REF
  • By descriptor---BY DESC
  • By value---BY VALUE

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:

  • Character strings
  • Arrays
  • Compound data structures

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