|
OpenVMS Record Management Services Reference
Manual
B.3.4 Processing File Specifications
The file name and file specification services, Parse and Search, are
used for relatively complex operations such as processing wildcard
characters.
Before you can perform operations on a file, you must establish a path
to the file. You do this by specifying the file specification string
address and size
(FAB$L_FNA and FAB$B_FNS) fields (and possibly the default file
specification string address and size fields) of the FAB to describe an
ASCII string within the program. In this ASCII string, you can have a
concatenation of the network node name; a logical or device name; the
directory name; and the file name, type, and version number.
If a logical name is used, RMS translates the logical name into its
equivalent file specification before it applies defaults to any missing
components of the file specification. If the logical name is a search
list logical name, RMS translates each element of the search list into
an equivalent file specification before it applies defaults to that
element. When using the Search service, a file specification that may
contain a search list logical
name must be handled as if wildcard characters were present in the file
specification.
The Parse service is required prior to the Search service in order to
examine the file specification for wildcard characters or a search
list. If the file is found, the Parse service sets a NAM or NAML block
bit that RMS uses internally and sets an appropriate value in the
wildcard character context that is used as input by the Search service.
The Parse service is invoked once, then the Search service is
repetitively invoked as many times as there are files that match the
original file specification.
If a wildcard is present, the Search service attempts to find all files
that match the file specification. If an asterisk (*) is in the
directory field, all directories on the specified device are searched
for files that match the remaining file specification components. As
with the use of wildcard characters, when a search list logical name is
present, a single Parse service and multiple Search services return all
files that match the file specification. With search lists, however,
all list elements are searched for matching file specifications in the
specified order without regard to uniqueness between the resulting file
specifications.
Search lists can be used in place of (or in addition to) wildcard
characters to specify a more efficient search order, which can mean
different combinations for the device, directory, file name, file type,
and version number parts of a file specification. Search lists can also
contain wildcard characters, if needed.
In summary, the Parse and Search services use a search list logical
name very much like a wildcard. Unlike the case of opening a file, in
which the first
instance where the file is found successfully ends the use of
additional search list file specifications, the Parse and Search
services use all search list file specifications.
Example B-4 shows how the $PARSE and $SEARCH macros can be used in
wildcard processing.
Example B-4 Wildcard Processing Using Parse
and Search Services |
.TITLE WILD
;
; Program to accept wildcard characters in input (partial) file
; specification and display full file specification.
;
$NAMDEF ; NAM block definitions
.PSECT DATA,NOEXE,WRT
NAM_BLK:
$NAM RSA=RES_STR,- ; Result buffer address
RSS=NAM$C_MAXRSS,- ; Result buffer size
ESA=EXP_STR,- ; Expanded buffer address
ESS=NAM$C_MAXRSS ; Expanded buffer size
FAB_BLK:
$FAB FOP=NAM,- ; Use NAM block option
NAM=NAM_BLK,- ; Pointer to NAM block
FNA=INP_STR ; Addr of file name string
EXP_STR: ; Expanded string buffer
.BLKB NAM$C_MAXRSS
RES_STR: ; Resultant string buffer
.BLKB NAM$C_MAXRSS
RES_STR_D: ; Resultant string descriptor
.BLKL 1
.LONG RES_STR
INP_STR: ; Input string buffer
.BLKB NAM$C_MAXRSS
INP_STR_D: ; Input string descriptor
.LONG NAM$C_MAXRSS
.LONG INP_STR
INP_STR_LEN: ; Input string length
.BLKL 1
PROMPT_D: ; User prompt string
.ASCID /Please enter the file specification: /
.PSECT CODE,EXE,NOWRT
.ENTRY WILD,^M<>
PUSHAB INP_STR_LEN ; Address for string length
PUSHAB PROMPT_D ; Prompt string descriptor
PUSHAB INP_STR_D ; String buffer descriptor
CALLS #3,G^LIB$GET_INPUT ; Get input string value
BLBC R0,EXIT ; Quit on error
;
; Store user input string and perform initial parse to
; set up RMS context for subsequent search.
;
MOVB INP_STR_LEN, - ; Set string size
FAB_BLK+FAB$B_FNS
$PARSE FAB=FAB_BLK ; Parse the file spec
BLBC R0,F_ERR ; Quit and signal on error
;
; Search until all possibilities are exhausted.
;
SEARCH_LOOP:
$SEARCH FAB=FAB_BLK ; Find next file
BLBC R0,SRCHERR ; Any more?
;
; Print out the resultant string from the search operation
;
MOVZBL NAM_BLK+NAM$B_RSL, -
RES_STR_D ; Set string length
PUSHAB RES_STR_D ; String descriptor
CALLS #1,G^LIB$PUT_OUTPUT ; Output the result
BLBC R0,EXIT ; Quit on error
BRB SEARCH_LOOP ; Go for more
SRCHERR: ; If error is "No more files",
CMPL R0,#RMS$_NMF ; this is normal completion
BEQL S_EXIT ; of the search loop.
F_ERR: PUSHL FAB_BLK+FAB$L_STV ; Push STV and STS on stack
PUSHL FAB_BLK+FAB$L_STS ; in reverse order
CALLS #2, G^LIB$SIGNAL ; Signal error
S_EXIT: MOVL #1,R0 ; Suppress "No More Files"
EXIT: RET
.END WILD
|
This program is designed to locate all files corresponding to a partial
file specification input. The program prompts the user for an input
string, which can consist of a partial file specification, using the
wildcard characters and/or any type of logical name, including a search
list logical name. In many respects, this program emulates the DCL
command DIRECTORY, which is discussed in the OpenVMS DCL Dictionary.
The program illustrates the use of the $PARSE and $SEARCH file name
processing macros. Here is the program statement that invokes the Parse
service for parsing the file name string:
Before invoking the Parse service ($PARSE macro), the program moves the
input string length to the file name string (FAB$B_FNS) field. If the
Parse service returns an error completion status, the program branches
to the F_ERR error routine.
Assuming no error, the program searches the disk directories specified
by the expanded string area address field in the NAM block (NAM$L_ESA)
until all possible files conforming to the partial file specification
input are found. Here is the program line that invokes the Search
service:
A status test is performed immediately after the $SEARCH macro. If an
error is detected, the program branches to the SRCHERR label. If a
no-more-files condition is detected, RMS returns the RMS$_NMF message
to indicate that all files that match the specification have been
found. (This error, however, is not signaled.)
This program contains two run-time library routines: LIB$GET_INPUT and
LIB$PUT_OUTPUT. The LIB$GET_INPUT routine inputs a record from the
current controlling input device, specified by SYS$INPUT, using the Get
service. The LIB$PUT_OUTPUT routine outputs a record (line) to the
current controlling output device, specified by SYS$OUTPUT, using the
Put service. Both routines are discussed in greater detail in the
OpenVMS RTL Library (LIB$) Manual.
B.3.5 Connecting and Disconnecting Record Streams
To associate or disassociate a file with one or more record streams,
RMS provides the Connect and Disconnect services, which are invoked
using the $CONNECT and $DISCONNECT macros.
Before reading and writing file records, the program must open (or
create) the input and output files and then connect the files to the
appropriate record streams by executing the $OPEN (or $CREATE) macro
followed by the $CONNECT macro.
Closing a file implicitly disconnects the record stream. Use the
Disconnect service to explicitly disconnect a record stream that is not
to be used immediately. This keeps the file open but releases various
data structures for use by other processes until your program needs the
record stream.
Example B-5 shows a program in which a user-entered reply determines
which key path is selected to access the indexed file created in
Example B-3. The
user-entered value determines the value specified for the RAB$B_KRF
field. The RAB$B_KRF value is set before the connect operation occurs
because this field is input to the Connect service.
Example B-5 Use of the Connect Service and
Multiple Keys |
.TITLE MULTIKEY
;
REC_SIZE=128
.PSECT DATA NOEXE,LONG
; ** RMS DATA **
MODFAB: $FAB FNM=<DATA_OUTPUT.DAT>,- ; FAB file spec.
FAC=<GET>,- ; Get access needed
SHR=<GET, UPD, PUT>,- ; Allow Get, Update, Put
MRS=REC_SIZE ; Specify record size
MODRAB: $RAB FAB=MODFAB,- ; RAB; indicate FAB
MBF=3,- ; Use 3 buffers
UBF=REC_MODBUF,- ; Specify buffer
USZ=REC_SIZE,-
KRF=0 ; Primary is default key
REC_START: .LONG REC_SIZE ; Record buffer
.ADDRESS REC_MODBUF
REC_MODBUF: .BLKB REC_SIZE
; TERMINAL I/O DATA **
MPRO0: .ASCID / /
MPRO1: .ASCID /Enter list order: 1-by name, 2-by city, 3-by state, 9-end :/
ENTRYERR: .ASCID /* * Value entered must be 1, 2, 3, or 9. * */
;
REGANS: .LONG 1
.ADDRESS REGBUF
REGBUF: .BLKB 1
;
DONE: .ASCID /Press RETURN to continue/
;
.PSECT CODE
START: .WORD ^M<>
INPUT: PUSHAL MPRO0 ; Get input
PUSHAL MPRO1 ; Display prompt
PUSHAL REGANS
CALLS #3, G^LIB$GET_INPUT
BLBC R0,FINIBR
CMPB #^A/1/,REGBUF ; Test value of menu answer
BEQLU PRIM ; 1 means primary
CMPB #^A/2/,REGBUF ; Continue testing
BEQLU ALT1 ; 2 means first alternate
CMPB #^A/3/,REGBUF ; Continue testing
BEQLU ALT2 ; 3 means second alternate
CMPB #^A/9/,REGBUF ; Continue testing
BEQLU FINIBR ; 9 means end program
BADANS: PUSHAL ENTRYERR ; otherwise, display error message
CALLS #1, G^LIB$PUT_OUTPUT
BLBC R0,FINIBR
BRB INPUT ; Entry error; retry
FINIBR: BRW FINI ; branch extender
PRIM: MOVB #0,MODRAB+RAB$B_KRF ; Set key of reference in RAB
BRB OPEN
ALT1: MOVB #1,MODRAB+RAB$B_KRF ; Set key of reference in RAB
BRB OPEN
ALT2: MOVB #2,MODRAB+RAB$B_KRF ; Set key of reference in RAB
OPEN: $OPEN FAB=MODFAB ; Open file
BLBS R0,CONN
BRW ERROR_OPEN
CONN: $CONNECT RAB=MODRAB ; Connect record stream
BLBS R0,NEXT
BRW ERROR
NEXT: $GET RAB=MODRAB ; Get record
CMPL #RMS$_EOF,R0 ; Test if EOF
BEQLU CLEAN
BLBC R0,ERROR
MOVZWL RAB$W_USZ+MODRAB,REC_START ; Set ASCII descriptor length
PUSHAL REC_START ; Display each record
CALLS #1, G^LIB$PUT_OUTPUT
BLBS R0,NEXT
BRB FINI ; Repeat until EOF
CLEAN: $CLOSE FAB=MODFAB ; Close file
BLBC R0,ERROR_OPEN
PUSHAL MPRO0
CALLS #1, G^LIB$PUT_OUTPUT
BLBC R0,FINI
PUSHAL DONE
PUSHAL REGANS
CALLS #2, G^LIB$GET_INPUT
BLBC R0,FINI
BRW INPUT
;
ERROR_OPEN:
PUSHL MODFAB+FAB$L_STV ; Error opening
PUSHL MODFAB+FAB$L_STS ; file. Signal error
CALLS #2, G^LIB$SIGNAL ; using LIB$SIGNAL.
BRB FINI ; End program
ERROR: PUSHL MODRAB+RAB$L_STV ; Record-related error
PUSHL MODRAB+RAB$L_STS
CALLS #2, G^LIB$SIGNAL ; Signal error, then
$CLOSE FAB=MODFAB ; close file
FINI: RET
.END START
|
Here the SHR argument limits access to processes that perform the Get
service, Put service, and Update service. If you anticipate no file
modifications as your program accesses the file, you can improve
performance by having the SHR argument limit access to processes that
use the Get service (SHR=GET).
Errors are signaled according to the recommended practice of using the
FAB$L_STS and FAB$L_STV fields for file errors and RAB$L_STS and
RAB$L_STV fields for record errors.
B.3.6 Other File-Processing Operations
Other file services include the Display, Erase, Extend, Remove, and
Rename services, which can be invoked using the $DISPLAY, $ERASE,
$EXTEND, $REMOVE, and $RENAME macros, respectively.
Example B-6 illustrates the use of the Rename service to rename a
file from directory [USER] named NAMES.DAT to directory [USER.HISTORY]
named OLD_NAMES.DAT.
Example B-6 Use of the Rename Service |
.TITLE RENAME
;
; Program that renames a file into a different directory and
; displays the resultant string.
;
.PSECT DATA,NOEXE,WRT
;
; Define old FAB, old NAM, new FAB, new NAM, and buffers
;
OLD_FAB: ; Define old file FAB
$FAB FNM=<[USER]NAMES.DAT>,-
NAM=OLD_NAM ; Pointer to NAM block
OLD_NAM: ; Define old file NAM
$NAM ESA=EXP_OLD,- ; Equivalence string
ESS=NAM$C_MAXRSS,- ; address and size
RSA=RES_OLD,- ; Resultant string
RSS=NAM$C_MAXRSS ; address and size
NEW_FAB: ; Define new file FAB
$FAB FNM=<[USER.HISTORY]OLD_NAMES.DAT>,-
NAM=NEW_NAM ; Pointer to NAM block
NEW_NAM:
$NAM ESA=EXP_NEW,- ; Equivalence string
ESS=NAM$C_MAXRSS,- ; address and size
RSA=RES_NEW,- ; Resultant string
RSS=NAM$C_MAXRSS ; address and size
EXP_OLD: ; Old file equivalence
.BLKB NAM$C_MAXRSS ; string buffer
EXP_NEW: ; New file equivalence
.BLKB NAM$C_MAXRSS ; string buffer
RES_OLD: ; Old file resultant
.BLKB NAM$C_MAXRSS ; string buffer
RES_OLD_D: ; String descriptor
.BLKL 1
.LONG RES_OLD
RES_NEW: ; New file resultant
.BLKB NAM$C_MAXRSS ; string buffer
RES_NEW_D: ; String descriptor
.BLKL 1
.LONG RES_NEW
;
MESS: .ASCID /has been successfully relocated to /
;
.PSECT CODE,EXE,NOWRT
.ENTRY RENAME,^M<>
; Rename file
;
$RENAME OLDFAB=OLD_FAB, NEWFAB=NEW_FAB
BLBC R0,ERROR
; Set up descriptors
;
MOVZBL OLD_NAM+NAM$B_RSL,RES_OLD_D
MOVZBL NEW_NAM+NAM$B_RSL,RES_NEW_D
;
PUSHAL RES_OLD_D ; Push resultant name,
CALLS #1,G^LIB$PUT_OUTPUT ; display old file spec.
BLBC R0,TERM_ERROR ; Branch on error
PUSHAL MESS ; Push message on stack,
CALLS #1,G^LIB$PUT_OUTPUT ; display message
BLBC R0,TERM_ERROR ; Branch on error
PUSHAL RES_NEW_D ; Push resultant name,
CALLS #1,G^LIB$PUT_OUTPUT ; display new file spec.
BLBS R0,DONE ; Branch on success
TERM_ERROR:
PUSHL R0 ; Signal output error
CALLS #1,G^LIB$SIGNAL ; from R0
BRB DONE
ERROR: PUSHL OLD_FAB+FAB$L_STV ; Push STV and STS on
PUSHL OLD_FAB+FAB$L_STS ; stack (reverse order)
CALLS #2,G^LIB$SIGNAL ; Signal error
DONE: RET
.END RENAME
|
This program uses the Rename service to change both the directory and
the name of the object file, which is being replaced by a new file
(created by a separate program). If the Rename service executes
correctly, the resultant
file specification of the old file, the message defined by the ASCII
descriptor following the label MESS, and the resultant file
specification of the new file are displayed as verification that the
Rename service successfully completed.
B.3.7 Retrieving and Inserting Records
The record-processing services provided by RMS insert records into a
file and retrieve records from a file. These services are the Find,
Get, and Put services, which can be invoked by the $FIND, $GET, and
$PUT macros, respectively.
Example B-7 illustrates the use of the $GET and $PUT macros. It
connects the input and output record streams, reads a record from an
indexed file, and writes the record to a relative file. The program
illustrates the use of the key string buffer, the key string
descriptor, and the key string length when reading indexed records, and
it includes the use of a user prompt string.
Example B-7 Use of the Get and Put
Services |
.TITLE LOOKUP
;
; This program looks up records in the input file and
; writes the records to the output file.
.PSECT DATA,WRT,NOEXE
INFAB: $FAB FNM = <INFILE:>,- ; Input file logical name
SHR = <GET,PUT,UPD,DEL> ; Allow read/write sharing
INRAB: $RAB FAB = INFAB,- ; Pointer to FAB
KBF = INP_STR,- ; Key buffer
KRF = 0,- ; Primary key
RAC = KEY,- ; Keyed access
ROP = WAT,- ; Wait for record
UBF = REC_BUFF,- ; Record buffer
USZ = REC_SIZE ; and size
OUTFAB: $FAB FNM = <OUTFILE:>,- ; Output file logical name
BKS = 3,- ; 3 blocks per bucket
MRS = REC_SIZE,- ; Maximum record size
ORG = REL,- ; Relative file
RAT = CR ; Implied carriage control
OUTRAB: $RAB FAB = OUTFAB,- ; Pointer to FAB
RBF = REC_BUFF ; Output uses same buffer
; as input
REC_SIZE = 132 ; Maximum size records
REC_BUFF:
.BLKB REC_SIZE ; Record buffer
INP_STR: ; Key string buffer
.BLKB REC_SIZE
INP_STR_D: ; Key string descriptor
.LONG REC_SIZE
.LONG INP_STR
INP_STR_LEN: ; Key string length
.BLKL 1
PROMPT_D: ; User prompt string
.ASCID /Please input key value: /
.PSECT CODE,NOWRT,EXE
;
; Initialization - Open input and output files and connect streams
;
.ENTRY LOOKUP,^M<> ; No registers to save
$OPEN FAB=INFAB ; Open input file
BLBC R0,EXIT1 ; Quit on error
$CONNECT RAB=INRAB ; Connect to input
BLBC R0,EXIT2 ; Quit on error
$CREATE FAB=OUTFAB ; Create output file
BLBC R0,EXIT3 ; Quit on error
$CONNECT RAB=OUTRAB ; Connect to output
BLBC R0,EXIT4 ; Quit on error
BRB READ ; Skip error branching
EXIT1: MOVAL INFAB, R6 ; Keep INFAB address
BRW F_ERR ; Signal FAB error
EXIT2: MOVAL INRAB, R6 ; Keep INRAB address
BRW R_ERR ; Signal RAB error
EXIT3: MOVAL OUTFAB, R6 ; Keep OUTFAB address
BRB F_ERR ; Signal FAB error
EXIT4: MOVAL OUTRAB, R6 ; Keep OUTRAB address
BRB R_ERR ; Signal RAB error
;
; Loop to copy records
;
READ:
PUSHAB INP_STR_LEN ; Address for string length
PUSHAB PROMPT_D ; Prompt string descriptor
PUSHAB INP_STR_D ; String buffer descriptor
CALLS #3,G^LIB$GET_INPUT ; Get input string value
BLBS R0,GET ; Quit on error or end-of-file
CMPL R0,#RMS$_EOF ; Was error end-of-file?
BEQL DONE ; Successful completion
BRB EXIT ; Error otherwise
GET: MOVB INP_STR_LEN, - ; Set key size
INRAB+RAB$B_KSZ
$GET RAB=INRAB ; Get a record
BLBS R0,PUT ; Put if successful
CMPL R0,#RMS$_RNF ; No such record?
BEQL READ ; Try again
BRB EXIT2 ; Error otherwise
PUT: MOVW INRAB+RAB$W_RSZ, - ; Set the record size
OUTRAB+RAB$W_RSZ ; for output
$PUT RAB=OUTRAB ; Write the record
BLBC R0,EXIT4 ; Quit on error
BRB READ ; Go back for more
;
; Close files and exit
;
F_ERR: PUSHL FAB$L_STV(R6) ; Push STV and STS on
PUSHL FAB$L_STS(R6) ; stack in reverse order
CALLS #2, G^LIB$SIGNAL ; Signal message
BRB EXIT
R_ERR: PUSHL RAB$L_STV(R6) ; Push STV and STS on
PUSHL RAB$L_STS(R6) ; stack in reverse order
CALLS #2, G^LIB$SIGNAL ; Signal message
DONE: $CLOSE FAB=INFAB ; Close input
$CLOSE FAB=OUTFAB ; and output
EXIT: RET ; Return with status in R0
.END LOOKUP
|
This program writes records from an existing indexed input file into a
newly created relative output file.
The program configures the file-sharing field (FAB$B_SHR) in the input
FAB to permit sharing of the file by processes that use the Get, Put,
Update, and Delete services.
The output FAB sets the bucket size field (FAB$B_BKS) at 3 blocks per
bucket, limits the record size in the output file to 132 bytes,
specifies the relative file organization, and specifies an implicit
carriage control when the file output is directed to a terminal.
The RAB for the input file establishes the key data, sets the WAIT
record option, and defines the record buffer. The output RAB locates
the record buffer. The rest of the first program section assigns values
and allocates space to various program variables. After the program
opens and creates the two files and connects the record streams, it
executes a series of instructions at label READ that input the required
key values and the user prompt. Then the program uses the $GET and $PUT
macros to invoke the respective services for retrieving and inserting
the records. The $GET macro uses the INRAB and the $PUT macro uses the
OUTRAB, as shown in the following program statements:
$GET RAB=INRAB
$PUT RAB=OUTRAB
|
Each time the program reads or writes a record, it performs a status
check. If the status check is successful, the program branches back to
the READ label for the next record. If any of the status checks
indicate an error, the program branches to the appropriate error
handler before exiting.
When the program completes the record transfers, it branches to the
DONE label to close the record and exit.
|