Previous | Contents | Index |
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 |
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.
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. |
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:
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.
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:
$ RUN COPYT |
OPEN 'WESTON::"TASK = MARG"' AS FILE #1%, SEQUENTIAL |
OPEN 'SYS$NET' FOR INPUT AS FILE #1%, SEQUENTIAL |
!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.
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.
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 |
Previous | Next | Contents | Index |