Document revision date: 30 March 2001

## 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

| privacy and legal statement |
4523PRO_040.HTML