[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS Record Management Services Reference Manual


Previous Contents Index

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:


$PARSE FAB=FAB_BLK 

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:


$SEARCH FAB=FAB_BLK 

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.


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
4523PRO_039.HTML