Document revision date: 30 March 2001

## Guide to OpenVMS File Applications

Previous | Contents | Index

Example 5-2 also shows the proper way to signal errors. The RAB$L_STS (completion status) field and the RAB$L_STV (additional status values) field of the FAB or RAB are used so that secondary completion information is displayed, if appropriate, by the LIB$SIGNAL or LIB$STOP routines.

The VAX MACRO program shown in Example 5-3 invokes the Parse service, determines whether a wildcard character or search list is present, and conditionally branches to a sequence of instructions that invoke the Search service followed by the Open service. The resultant string is displayed after the file is opened.

For more information about the LIB$ routines, see the OpenVMS RTL Library (LIB$) Manual.

The next example program uses the $PARSE and $SEARCH functions, demonstrates the use of C language's fopen function, and shows how you can mix RMS calls and C I/O calls.

Example 5-3 uses cc$rms_fab and cc$rms_nam to define the $FAB and $NAM control blocks and specify the arguments for the Parse, and Search services.

The program shows how to preprocess a file specification using the Parse and Search services. First, the program prompts the user for an input file specification that may contain wildcard characters. The program then searches each file that matches the file specification for the specified text string.

Finally, the program outputs all records from the target files that contain the specified string.

Example 5-3 Using the Parse and Search Services

    /* Using Parse and Search Services */
    #include <stdio.h>
    #include <ssdef.h>
    #include <stsdef.h>
    #include <string.h>
    #include <rms.h>
    #include <starlet.h>

    #define MAXLINE 256

    static int rms_status;  /* RMS status variable */
    static char ibuf[MAXLINE],  /* input buffer */
      obuf[MAXLINE],  /* output buffer */
      fbuf[MAXLINE],  /* filename buffer */
      xbuf[MAXLINE];  /* expanded filename buffer */
    struct FAB filfab;   /* FAB for $PARSE and $SEARCH */
    struct NAM filnam;   /* NAM for $PARSE and $SEARCH */
    void init()    /* Initialize RMS structures */
    {
     filfab = cc$rms_fab;  /* Get a FAB */
     filfab.fab$l_fna = ibuf; /* Parse filename from IBUF */
     filfab.fab$b_fac = FAB$M_GET; /* Only allow $GETs */
     filfab.fab$l_fop = FAB$M_NAM; /* Use the NAM block for filename */
     filfab.fab$l_nam = &filnam; /* -> NAM block */

     filnam = cc$rms_nam;  /* Get a NAM block */
     filnam.nam$l_esa = xbuf; /* -> Expanded filespec buffer */
     filnam.nam$b_ess = 255;  /* Expanded filespec buffer length */
     filnam.nam$l_rsa = fbuf;        /* -> Resultant filespec buffer */
     filnam.nam$b_rss = 255;         /* Resultant filespec buffer length */
    }
    main()
    {
     auto FILE *fil;  /* File pointer for file functions */
     auto int i;  /* Generic loop variable */

     init();    /* Initialize RMS structures */

     /* Get filespec to search */
     fputs("File: ", stdout);
     if (!gets(ibuf)) return;

     /* Validate filespec */
     filfab.fab$b_fns = strlen(ibuf);
     if (((rms_status = sys$parse(&filfab)) & STS$M_SUCCESS) == 0)
      return (rms_status);

     /* Get search string */
     fputs("String: ", stdout);
     if (!gets(ibuf)) return;
     /* Loop for all files matching filespec */
     while ((rms_status = sys$search(&filfab)) & STS$M_SUCCESS)
     {
      /* Output a row of asterisks, the filename,
         and other row of asterisks */
      for (i = 0; i < 80; i++)
       obuf[i] = '*';
      obuf[80] = '\0';
      puts(obuf);
      fbuf[filnam.nam$b_rsl] = '\0'; /* Add <NUL> terminator */
      puts(fbuf);
      puts(obuf);
      if (fil = fopen(fbuf, "r")) /* Try to open the file */
      {
       /* Process the file... */
       while (fgets(obuf, MAXLINE, fil))
        if (strstr(obuf, ibuf)) fputs(obuf, stdout);
       fclose(fil);  /* Done with this file */
      }
      putchar('\f');   /* Print <FF> between files */
     }
     if ((rms_status == RMS$_FNF) || (rms_status == RMS$_NMF))
      rms_status = SS$_NORMAL; /* Handle expected errors */

     return(rms_status);
    }

An application may also need to process either one file or many files, depending on the file specification that the terminal user enters or the logical name that is provided (if the program uses a logical name in its file specification). Each of these cases is discussed in the following sections.

### 5.9.1 Processing One File

When only a single file needs to be processed, but more than one location for the file may need to be searched, you can usually find the file by specifying a file specification that contains a search list.

For example, consider the case of a directory that contains the file PAY.DAT and a backup copy of the file named PAY_BUP.DAT. You could specify a file name of PAY*.DAT in the file specification and invoke the Parse service once and the Search service once to locate either of the two files; this method will locate PAY.DAT before PAY_BUP.DAT.

A potential problem arises if the file PAY.DAT has been deleted or renamed. In this case, unless the program determines that the file specification is one of several that are acceptable, any file named PAY that has the file type .DAT could be accessed: for example, PAY_ACC.DAT. You can avoid such problems by defining a search list logical name that specifies a search for PAY.DAT and PAY_BUP.DAT. A search list named SEARCH could be defined as follows for the directory [SMITH]:

    $ DEFINE SEARCH [SMITH]PAY.DAT,[SMITH]PAY_BUP.DAT

To locate the file, specify SEARCH as the primary file specification.

When the file locations to be searched reside in different directories of a directory tree, you can use the ellipsis wildcard character in the directory field to search all subdirectories. Alternatively, you could define a search list that searches for the file PAY.DAT in one directory, the same file name in a subdirectory, and PAY_BUP.DAT in any directory in the directory tree by using the following DEFINE command:

    $ DEFINE SEARCH [SMITH]PAY,[SMITH.PAY]PAY,[SMITH...]PAY_BUP

You use the file specification SEARCH:.DAT to locate the desired file. In this example, note that one of the search list file specifications contains wildcard characters. Wildcard characters can be used in a search list if they are needed, just as with any other logical names and file specifications. However, the Parse and Search services must be used to locate the correct file.

When you need to locate files in different directory trees (or top-level directories), include complete directory specifications in your search list definition. For example, to locate the file TEST_DATA.DAT in the device/directory combinations of DISK1:[SMITH], DISK2:[STATS], or DISK2:[SMITH] you could use the following command to define the search list TST:

    $ DEFINE TST DISK1:[SMITH],DISK2:[STATS],DISK2:[SMITH]

You can also use search lists to locate files on different devices. To locate this file, you specify TST:TEST_DATA.DAT.

To find the same directory and the same file name on different devices, you could use the following command to define TST:

    $ DEFINE TST DISK1:,DISK2:,DISK3:

When you define the search list TST in this manner, you can locate the file by using the search list to specify the device name. In this way, you can use a single search list to locate files that would otherwise require multiple file specifications, even if wildcard characters were used.

### 5.9.2 Processing Many Files

To process many files using a single file specification, you always need to use the Parse and Search services to locate the files.

The application requirements and the directory location of the files generally determine whether one or more search lists, wildcard characters, or search lists containing wildcard characters are used in the file specification. When files must be accessed in nonalphabetical order, use a search list.

To process multiple files using a single file specification, invoke the Parse service (or its equivalent) once to interpret the file specification and to create the file specification pattern to be searched. After the file specification is parsed, you can invoke the Search service to locate each file that matches the original file specification. In some cases, you can examine (or display) the resultant file specification string returned by the Search service to determine if you (or the interactive user) want to process (open) the file.

If you want to list all file specifications that match a particular file specification and let the terminal user choose each file to be processed, wildcard characters can be used safely, possibly in a search list that contains wildcard characters in one or more of its file specifications. To reduce the number of files that the user might choose to process, use a search list without wildcard characters or rely less on wildcard characters. For example, to locate all files in a directory tree on different devices with a file type of .DAT, you could define the search list TREE as follows:

    $ DEFINE TREE DISK1:[MYDIR...],DISK2:[MYDIR...]

The primary file specification that would be used for the Parse service would be TREE:*.DAT. A great number of files might match this.

For applications that will need to locate certain files, search lists with limited use of wildcard characters might be needed. Consider a file that contains a prefix of RESULTS followed by the date for which the data applies. You could use the file name RESULTS*JUN*.DAT to locate a record that was entered in the month of June by executing a Search service followed by an Open service for each file, reading all records until the correct one is found, and invoking the Close service after processing each file.

A search list should be used when a predefined group of files is processed by a program that is not intended to be interactive. Using a search list is particularly desirable if the files have unrelated file names or if they are located on different directories or devices. A search list also minimizes processing time by searching for a definite group of files.

### 5.9.3 Processing One or Many Files

For general-purpose applications, when the user enters a file specification that may indicate one file or many files, there is a means of testing whether one file or many files are to be processed, or to explicitly disallow the use of wildcard characters for applications where only a single file should be processed. To test for wildcard characters or search lists, or both, invoke the Parse service and test the appropriate bits in the NAM$L_FNB or NAML$L_FNB field.

The presence of a wildcard character usually indicates that many files should be processed, depending on program conventions. If a search list is present, it may or may not indicate that only one file should be processed and a convention is needed for users of that program. Thus, by testing whether a wildcard is present, the program can either invoke the Parse service once and the Search service repeatedly for each file to be opened, or it can disallow wildcard characters and request that the file specification be reentered. In some cases, the program may need to disallow the use of a search list or allow one or many files to be accessed, depending upon application conventions.

If you want to disallow wildcard characters, invoke the Open service. The Open service fails when it encounters a wildcard character.

## Chapter 6
Advanced Use of File Specifications

This chapter is intended for readers who want to better understand how OpenVMS RMS (hereafter referred to as RMS) internally applies defaults, parses file specifications, and handles directory specifications. This chapter also describes the use of rooted-directory syntax and process-permanent files.

## 6.1 How RMS Applies Defaults

This section describes how RMS applies defaults when it parses specifications supplied by your program.

Several file specifications can be used by RMS's Parse operation to compose a fully-qualified expanded file specification, which can then be used for operations such as searching for a specific file, opening an existing file, or creating a new file.

The program-supplied file specifications are the primary file specification, the default file specification, and one or more related file specifications. RMS also uses the process-default file specification, but it is not supplied by the program.

The program accepts from the user a file specification and passes it to RMS as the primary file specification.

The program provides to RMS, through the default file specification, components that RMS can use in place of missing components in the primary specification, and that are related to the program's function rather than to the files being operated on. Typically, the default file specification contains a default for the type component (for example, .DAT to specify a data file, or .TXT to specify a text file), or it contains default device and directory components.

The related file specification is used when two files are involved in an operation, such as copying or merging files, in which the input file specification can provide default components for the output file specification.

The final default mechanism, which is not provided by the program, is for RMS to use the process default device and directory. Table 6-1 describes the defaults that RMS uses to produce a complete file specification when these components (device and directory) cannot be obtained from the primary, default, and related file specifications.

Table 6-1 File Specification Defaults
File Specification | Description
--- | ---
Primary | If the device field is a logical name, RMS translates the logical device name to its component parts. The resulting device name may be a physical device name, a process-permanent file name, or another logical name.
Default | If the device field is a logical name, RMS translates it before defaults are applied. If any of the fields in the file specification from the previous step are missing, they are supplied from the corresponding fields in the translated default file specification, where applicable.
Related | If the device field is a logical name, RMS translates it and applies the default values before it uses the related file specification to add missing component fields. If fields contain wildcard characters, the wildcard characters remain in the fields. When RMS uses the related file specification to complete an output file specification, the file name field and the file type field are replaced by the corresponding related file specification fields, where applicable. For more information, including the use of multiple related file specifications, see Section 6.2.3.
Device and Directory | If the device name is omitted, the device field and, optionally, the directory field accept the system logical name SYS$DISK. If RMS cannot translate the logical name SYS$DISK to a physical device name, an error occurs. If the directory field does not accept the logical name SYS$DISK, it accepts the name of the current process default directory.

Primary, default, and related file specifications can use logical names. RMS translates the primary file specification before it applies defaults and missing components. RMS also translates the default file specification before using the default values. Finally, RMS translates the related file specification before it uses missing components supplied by the related file specification. If the file specification is still missing the device or directory name components, the process executing the program supplies default device and directory values.

The algorithm used in determining the appropriate translation is as follows:

    if node name present
       then translate node name
    else if device name present
       then translate device name
    else if only file name present
       then translate file name

For the remainder of this description, the component parts of the file specification are referred to as strings. For example, the device component is referred to as the device string; the name component is the name string, and so forth. Furthermore, as components are added to a file specification, the expanded file specification is referred to as the expanded string. Finally, the resultant file specification is called the resultant string.

Table 6-2 shows the sequence in which defaults are applied to a file specification (primary file specification string) and the resulting file specification (resultant string). In Table 6-2, the program specifies the primary file specification string FILE, omitting all other components of the file specification. The default file specification string .DAT provides the file type component. The related file specification string does not provide any component strings, but the default device string (logically SYS$DISK) provides the device string DISK1: and the directory string, [INV_C], is provided by the default directory string. Finally, because the resultant string is used to specify a new file, RMS applies the version number 1 to complete the new file specification.

Table 6-2 Example of Applying Defaults
String Name | String Applied | Expanded String
--- | --- | ---
Primary file specification | FILE | FILE
Default file specification | .DAT | FILE.DAT;
Related file specification | None. | FILE.DAT;
Default device (SYS$DISK) | DISK1: | DISK1:FILE.DAT;
Default directory | [INV_C] | DISK1:[INV_C]FILE.DAT;
Resultant string |  | DISK1:[INV_C]FILE.DAT;1

RMS appends the version number to the expanded string to convert it into the resultant string. The resultant string is the resultant file specification that RMS uses to locate the file.

When coding the file specification information in a program, you can use the language keyword for the OPEN (or CREATE) statement. Then you use the FDL Editor to enter the file specification characteristics. Finally, you call the FDL$CREATE routine to create a file, or you call the FDL$PARSE routine and the FDL$RELEASE routine to open a file.

Alternatively, you can set the appropriate control block fields and call the RMS services directly, perhaps as part of a USEROPEN routine or a USER_ACTION routine.

Consider a program that does not explicitly specify the device and directory in any of the file specifications and does not have a related file specification. RMS adds the current process default device and the current process default directory to the expanded string after it applies components provided by the default file specification. However, if the program looks for a data file that is not in the current process default device and directory, it does not find the file. In this case, the solution is to specify the data file's device and directory either in the primary file specification, the default file specification, or the related file specification.

The program-supplied file specifications can be specified using the methods summarized in the following chart:

File Specification | How You Can Specify It
--- | ---
Primary | Use the FDL attribute FILE_NAME; use the file name or the name following the FILE, FILE_ID, or FILENAME keywords in the OPEN statement in some high-level languages; or use the string pointed to by the FAB field FAB$L_FNA.
Default | Use the FDL attribute FILE DEFAULT_NAME; use the default file specification or the name following the DEFAULTNAME or DEFAULT_FILE_ID keyword in the OPEN statement in some high-level languages; or use the string pointed to by the FAB field FAB$L_DNA.
Related | Use the name block (NAM) pointed to by the NAM$L_RLF field; the related name block must specify the location of a file specification, which must be pointed to by the NAM field NAM$L_RSA.

Specifying all components in the primary file specification explicitly decreases the chance of error. However, defaults are provided and can be very useful, especially for general-purpose applications and for applications in which the file specification is entered by the interactive user. Another option to consider is the use of logical names.

See the appropriate languages documentation for information about language statements and their keywords. Consult the OpenVMS Record Management Utilities Reference Manual for information about the FDL Editor, and refer to the OpenVMS Utility Routines Manual for information about the FDL$PARSE and FDL$RELEASE routines. For detailed information about RMS control blocks and services, see the OpenVMS Record Management Services Reference Manual.

## 6.2 Understanding RMS Parsing

In the following text, the term expanded string buffer refers to the user-allocated buffer that is pointed to by the NAM block expanded string address field (NAM$L_ESA), by the NAML block short expanded string address field (NAML$L_ESA), or by the NAML block long expanded string address field (NAML$L_LONG_EXPAND).

As it processes each program-supplied file specification, RMS identifies each specification's component parts. Components present in the primary, default, or related, and process-default file specifications are used to form the expanded file specification. The expanded file specification can then be used to locate one or more files. If a name block (NAM or NAML) is present, and the address and size of the expanded string buffer are specified, the file specification is copied into the expanded string buffer.

Note that the Parse service operates differently from other services with regard to the expanded string. With the Parse service, the expanded string contains all wildcard characters present in the file specification. RMS does not generate the resultant string until the program invokes a related service, such as SYS$SEARCH, which uses the expanded string from the Parse service as input.

When you use a search list, the expanded string contains the first location to be searched. RMS stores internally the information that specifies the remaining search list equivalence strings. Note that the equivalence string from a $PARSE is not guaranteed to point to an actual file. As different file locations are examined, RMS updates the expanded string to reflect the current location, and the resultant string contains the actual file specification of the file.

With the Create, Display, Erase, Open, and Search services, defaults are applied to the expanded string to select the actual file used. The resultant string can be used by the program to indicate which file was located. When the file is located, the version number found (or created) is appended to the resultant file specification string (not the expanded file specification string). When a search list is used, the resultant string contains the file specification where the file was actually found.

The following sections describe the steps that RMS uses to create a complete file specification.

Previous | Next | Contents | Index

| privacy and legal statement |
4506PRO_016.HTML