[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS User's Manual


Previous Contents Index

14.7.3 Returning Data from Command Procedures

Global symbols and logical names return data from a command procedure to a calling procedure or to DCL command level. You can read a global symbol or a logical name at any command level. Logical names can return data from a nested command procedure to the calling procedure.

The following example shows how a command procedure passes a value with a global symbol created with a global assignment statement:


$ @DATA "Paul Cramer"

$ ! DATA.COM
$ !
$ ! P1 is a full name.
$ ! NAME.COM returns the last name in the
$ ! global symbol LAST_NAME.
$ !
$ @NAME 'P1'
       $ ! NAME.COM
       $ ! P1 is a first name
       $ ! P2 is a last name
       $ ! return P2 in the global symbol LAST_NAME
       $ LAST_NAME == P2
       $ EXIT
$ ! write LAST_NAME to the terminal
$ WRITE SYS$OUTPUT "LAST_NAME = ''LAST_NAME'"

LAST_NAME = CRAMER

DATA.COM invokes the command procedure NAME.COM, passing NAME.COM a full name. NAME.COM places the last name in the global symbol LAST_NAME. When NAME.COM completes, DCL continues executing DATA.COM, which reads the last name by specifying the global symbol LAST_NAME. The command procedure NAME.COM would be in a separate file. It is shown indented in this example for clarity.

In this command procedure, REPORT.COM obtains the file name for a report, equates the file name to the logical name REPORT_FILE, and executes a program that writes a report to REPORT_FILE:


$! Obtain the name of a file and then run
$! REPORT.EXE to write a report to the file
$!
$ INQUIRE FILE "Name of report file"
$ DEFINE/NOLOG REPORT_FILE 'FILE'
$ RUN REPORT
$ EXIT

In the following example, the command procedure REPORT.COM is invoked from another procedure. The calling procedure uses the logical name REPORT_FILE to refer to the report file.


$! Command procedure that updates data files
$! and optionally prepares reports
$!
$ UPDATE:
   .
   .
   .
$   INQUIRE REPORT "Prepare a report [Y or N]"
$   IF REPORT THEN GOTO REPORT_SEC
$   EXIT
$!
$ REPORT_SEC:
$   @REPORT
$   WRITE SYS$OUTPUT "Report written to ", F$TRNLNM("REPORT_FILE")
$   EXIT

14.7.4 Redirecting Error Messages

The following sections describe how to redirect error messages.

14.7.4.1 Redefining SYS$ERROR

By default, command procedures send system error messages to the file indicated by SYS$ERROR. You can redefine SYS$ERROR to direct system error messages to a specified file. However, if you redefine SYS$ERROR to be different from SYS$OUTPUT (or if you redefine SYS$OUTPUT without also redefining SYS$ERROR), DCL commands and images that use standard system error display mechanisms send system error level and system severe level error messages to both SYS$ERROR and SYS$OUTPUT. Therefore, you receive these messages twice---once in the file indicated by the definition of SYS$ERROR and once in the file indicated by SYS$OUTPUT. Success, informational, and warning level messages are sent only to the file indicated by SYS$OUTPUT. If you want to suppress system error messages from a DCL command, be sure that neither SYS$ERROR nor SYS$OUTPUT is equated to the terminal.

If you run one of your own images from a command procedure and the image references SYS$ERROR, the image sends system error messages only to the file indicated by SYS$ERROR --- even if SYS$ERROR is different from SYS$OUTPUT. Only DCL commands and images that use standard system error display mechanisms send messages to both SYS$ERROR and SYS$OUTPUT when these files are different.

This command procedure accepts a directory name as a parameter, sets the default to that directory, and purges files in the directory. To suppress system error messages, the procedure temporarily defines SYS$ERROR and SYS$OUTPUT as the null device:


$ ! Purge files in a directory and suppress messages
$ !
$ SET DEFAULT 'P1'
$ ! Suppress messages
$ !
$ DEFINE/USER_MODE SYS$ERROR NL:
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ PURGE
$ EXIT

14.7.4.2 Suppressing System Error Messages

You can also use the SET MESSAGE command to suppress system messages. By using the qualifiers /NOFACILITY, /NOIDENTIFICATION, /NOSEVERITY, or /NOTEXT, you can suppress the facility name, message identification, severity level, or the message text.

In the following example, the facility, identification, severity, and text messages are temporarily suppressed, until the second SET MESSAGE command is issued:


$ ! Purge files in a directory and suppress system messages
$ !
$ SET DEFAULT 'P1'
$ ! Suppress system messages
$ !
$ SET MESSAGE/NOFACILITY -
             /NOIDENTIFICATION -
             /NOSEVERITY -
             /NOTEXT
$ PURGE
$ SET MESSAGE/FACILITY -
             /IDENTIFICATION -
             /SEVERITY
             /TEXT
$ EXIT

14.8 Reading and Writing Files (File I/O)

The basic steps in reading and writing files from command procedures are:

Step Action
1 Use the OPEN command to open files.

This assigns a logical name to the file and specifies whether the file is to be read, written, or both read and written. Subsequent READ, WRITE, and CLOSE commands use this logical name to refer to the file.

2 Use the READ or WRITE commands to read or write records to files.

Input and output to files is usually accomplished by designing a loop to read a record, process the record, and write the modified record to either the same file or to another file.

3 Use the CLOSE command to close files.

If you do not include the CLOSE command, files remain open until you log out.

Note

You do not have to open process-permanent files such as SYS$INPUT, SYS$OUTPUT, SYS$COMMAND, and SYS$ERROR explicitly to read or write to them because the system opens these files for you when you log in.

The following sections describe:

  • Using the OPEN command
  • Writing to files
  • Using the WRITE command
  • Using the READ command
  • Using the CLOSE command
  • Modifying files
    • Updating records
    • Creating new output files
    • Appending records to files

14.9 Using the OPEN Command

The OPEN command opens sequential, relative, or indexed sequential files. The files are opened as process-permanent; they remain open for the duration of your process unless you explicitly close them (with the CLOSE command). While the files are open, they are subject to OpenVMS RMS restrictions on using process-permanent files.

When you open a file, the OPEN command assigns a logical name (specified as the first parameter) to the file (specified as the second parameter) and places the name in the process logical name table. Subsequent READ, WRITE, and CLOSE commands use this logical name to refer to the file.

In the following example, the OPEN command assigns the logical name INFILE to the file DISK4:[MURPHY]STATS.DAT:


$ OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT

Note

The logical name in the OPEN command must be unique. If the OPEN command does not work and your commands seem correct, change the logical name in the OPEN command. To display a list of logical name definitions, use the SHOW LOGICAL command.

To ensure that the command procedure can access the correct files, use complete file specifications (for example, DISK4:[MURPHY]STATS.DAT) or use the SET DEFAULT command to specify the proper device and directory before you open a file.

You can also specify shareable files. The /SHARE qualifier enables other opened files. In addition, users can access shareable files with the DCL commands TYPE and SEARCH.

The OPEN/READ command opens the files, assigns logical names to the files, and places record pointers at the beginning of the files. When you open files for reading, you can read but not write records. Each time you read a record, the pointer moves to the next record.

The OPEN/READ command in this command procedure opens the file STATS.DAT and assigns the logical name INFILE to the file:


$   OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT
$ READ_FILE:
$   READ/END_OF_FILE=DONE INFILE DATA
$   GOTO READ_FILE
$ DONE:
$   CLOSE INFILE
$   EXIT

Use the OPEN/WRITE command when you want to write to a new file. The OPEN/WRITE command creates a sequential file in print file format. The record format for the file is variable with fixed control (VFC), with a 2-byte record header. The /WRITE qualifier cannot be used with the /APPEND qualifier.

If you specify a file that already exists, the OPEN/WRITE command opens a new file with a version number that is one greater than the existing file.

The command procedure in the following example creates a new file (NAMES.DAT) that can be used for writing:


$   OPEN/WRITE OUTFILE DISK4:[MURPHY]NAMES.DAT
$ UPDATE:
$   INQUIRE NEW_RECORD "Enter name"
$   WRITE OUTFILE NEW_RECORD
$   IF NEW_RECORD .EQS. "" THEN GOTO EXIT_CODE
$   GOTO UPDATE
$ EXIT_CODE:
$   CLOSE OUTFILE
$   EXIT

The OPEN/APPEND command appends records to the end of an existing file. If you attempt to open a file that does not exist, an error occurs and the file is not opened. The /APPEND qualifier cannot be used with the /WRITE qualifier.

In the following example, records are appended to the end of an existing file, NAMES.DAT:


$ OPEN/APPEND OUTFILE DISK4:[MURPHY]NAMES.DAT
$ INQUIRE NEW_RECORD "Enter name"
$ WRITE OUTFILE NEW_RECORD
   .
   .
   .
$ CLOSE OUTFILE

The OPEN/READ/WRITE command places the record pointer at the beginning of a file so you can read the first record. When you use this method to open a file, you can replace only the record you have read most recently; you cannot write new records to the end of the file. In addition, a revised record must be exactly the same size as the record being replaced.

In the following example, the record pointer is placed at the beginning of the file STATS.DAT so the first record can be read:


$ OPEN/READ/WRITE FILE DISK4:[MURPHY]STATS.DAT

14.10 Writing to Files

To write to files, use the following procedure:

Step Action
1 Open the file for writing.
2 Begin the write loop with a label.

File I/O is always done in a loop unless you are writing or reading a single record.

3 Read the data to be written.

Use the INQUIRE command or the READ command to read data into a symbol.

4 Test the data.

Check the symbol containing the data. If the symbol is null (for example, if you press Return and enter no data on the line), you have reached the end of the data to be written to the file and you should go to the end of the loop. Otherwise, continue.

5 Write the data to the file.

Use the WRITE command to write the value of the symbol (one record) to the file.

6 Return to the beginning of the loop.

You remain within the loop until there is no more data to be written to the file.

7 End the loop and close the file.

The following command procedure writes data to the new file STATS.DAT. If a file of that name exists, a new version is created.


$ ! Write a file
$ ON ERROR THEN EXIT                         ! Exit if the command
$ !                                          !   procedure cannot
$ !                                          !   open the file
$ OPEN/WRITE IN_FILE DISK4:[MURPHY]STATS.DAT ! Open the file
$ ON CONTROL_Y THEN GOTO END_WRITE           ! Close the file if you
$ !                                          !   quit execution with
$ !                                          !   Ctrl/Y
$ ON ERROR THEN GOTO END_WRITE               ! Close the file if an
$ !                                          !   error occurs
$WRITE:                                      ! Begin the loop
$ INQUIRE STUFF "Input data"                 ! Prompt for input
$ IF STUFF .EQS. "" THEN GOTO END_WRITE      ! Test for the end of
$ !                                          !   the file
$ WRITE IN_FILE STUFF                        ! Write to the file
$ GOTO WRITE                                 ! Go to the beginning
$END_WRITE:                                  ! End the loop
$ !                                          !
$ CLOSE IN_FILE                              ! Close the file

14.10.1 Creating Files with Unique File Names

To create a file with a unique name, use the F$SEARCH lexical function to see if the name is already in the directory. (Refer to the lexical function descriptions in the OpenVMS DCL Dictionary for more information about F$SEARCH.)

This command procedure prompts the user for a file name, then uses the F$SEARCH lexical function to search the default directory for the name. If a file with that name already exists, control is passed to ERROR_1, the procedure prints the message "The file already exists" and control returns to the label GET_NAME. The procedure then prompts for another file name as shown in the following example:


$ ! FILES.COM
$ !
$GET_NAME:
$ INQUIRE FILE "File"           ! Prompt the user for a file name
$ IF F$SEARCH (FILE) .NES. ""   ! Make sure the file name is unique
$ THEN
$    WRITE SYS$OUTPUT "The file already exists"
$    GOTO GET_NAME
$ ELSE
$    OPEN/WRITE IN_FILE 'FILE'  ! Open the file with WRITE access
$ ENDIF
   .
   .
   .
$ EXIT

14.11 Using the WRITE Command

The following sections describe how to use the WRITE command.

14.11.1 Specifying Data

When you specify data for the WRITE command, follow the rules for character string expressions described in Chapter 12. You can specify data in the following ways:

  • Specify data to be written as a character string expression. The WRITE command automatically substitutes symbols and lexical functions.
  • Write a string to an output file as a literal character string. The WRITE command does not perform symbol substitution on strings enclosed in quotation marks.
  • Combine literal strings with symbol names. To force symbol substitution, place the entire string within quotation marks and use double apostrophes before the symbol to identify it and a single apostrophe following it.
    Another way to combine literal strings with symbol names is to insert a comma before and after the symbol, place quotation marks around the delimited symbol, and enclose the entire character string in quotation marks. For example:


    $ WRITE OUTFILE "Count is ",COUNT,"."
    
  • Use apostrophes in the WRITE command line to force symbol substitution.
  • Combine literal strings and lexical functions by using apostrophes to force symbol substitution within character strings.

Example


$! Define symbols
$!
$ CREATED = "File created April 15, 2002"
$ COUNT = 4
$ P4 = "fourth parameter"
$!
$! Open the file DATA.OUT for writing
$!
$ OPEN/WRITE OUTFILE DISK4:[MURPHY]DATA.OUT
$!
$ WRITE OUTFILE CREATED                 (1)
$ WRITE OUTFILE "CREATED"               (2)
$!
$ WRITE OUTFILE "Count is ''COUNT'."    (3)
$ WRITE OUTFILE P'COUNT'                (4)
$!
$ WRITE OUTFILE "Mode is ''f$mode()'"   (5)
$!
$ CLOSE OUTFILE


$ TYPE DISK4:[MURPHY]DATA.OUT [Return]   (6)
File created April 15, 2002
CREATED
Count is 4.
fourth parameter
Mode is INTERACTIVE
$

As you examine the example, note the following:

  1. Specifies the data to be written as a character string expression.
  2. Writes the string CREATED to the output file as a literal character string.
  3. Combines literal strings with symbol names.
  4. Uses an apostrophe in the WRITE command line to force symbol substitution. In this example, the WRITE command substitutes a value for the symbol COUNT and performs symbol substitution on the resulting command string (P4).
  5. Combines literal strings and lexical functions.
  6. Displays the data written to the output file DATA.OUT by the preceding WRITE commands.

14.11.2 Using the /SYMBOL Qualifier

When the WRITE command writes a record, it positions the record pointer after the record just written. The WRITE command can write a record that is up to 2,048 bytes long.

Use the /SYMBOL qualifier to write a record if either of the following conditions exist:

  • The record is longer than 1,024 bytes.
  • An expression in the WRITE command is longer than 255 bytes.

Refer to the description of the WRITE command in the OpenVMS DCL Dictionary for more information on writing long records.

14.11.3 Using the /UPDATE Qualifier

You can use the WRITE command with the /UPDATE qualifier to change a record rather than insert a new one. To use the /UPDATE qualifier, you must open the file for both reading and writing.

14.12 Using the READ Command

Use the READ command to read a record and assign its contents to a symbol. You can use the READ command to read records that are less than or equal to 1,024 characters in length. To read data from a file, use the following procedure:

Step Action
1 Open the file for reading.
2 Begin the read loop with a label.

File I/O is always done in a loop unless you are reading or writing a single record.

3 Read the data from the file.

Use the READ command with the /END_OF_FILE qualifier to read a record and assign its contents to a symbol. The /END_OF_FILE qualifier causes DCL to pass control to the label specified by the /END_OF_FILE qualifier when you reach the end of the file. Generally, you specify the label that marks the end of the read loop.

4 Process the data.

When you read a file sequentially, process the current record before reading the next one.

5 Return to the beginning of the loop.

You remain in the loop until you reach the end of the file.

6 End the loop and close the file.

The following command procedure reads and processes each record in the file STATS.DAT. The procedure executes the READ command repeatedly until the end-of-file status is returned. Then, the procedure branches to the line labeled END_READ.


$ OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT  !Open the file
$ !
$READ_DATA:                                 !Begin the loop
$ READ/END_OF_FILE=END_READ INFILE RECORD   !Read a record; test for
$                                           !  end of file
$                                           ! Process the data
   .
   .
   .
$ GOTO READ_DATA                            !Go to the beginning
$                                           !   of the loop
$END_READ:                                  !End of loop
$ CLOSE INFILE                              !Close the file
$ EXIT

When you specify a symbol name for the READ command, the command interpreter places the symbol name in the local symbol table for the current command level. If you use the same symbol name for more than one READ command, each READ command redefines the value of the symbol name. For example, in the preceding example, the READ command reads a new record from the input file (STATS.DAT) each time through the loop. It then uses this record to redefine the value of the symbol RECORD.

14.12.1 Using the /END_OF_FILE Qualifier

When you read from files, you generally read and process each record until you reach the end of the file. By using the /END_OF_FILE qualifier with the READ command, you can construct a loop to read records from a file, process the records, and exit from the loop when you have finished reading all the records.

Note that the labels you specify for /END_OF_FILE qualifiers are subject to the same rules as labels specified for a GOTO command. (See Chapter 13 for more information on using the GOTO command.)

You should always use the /END_OF_FILE qualifier when you use the READ command in a loop. Otherwise, when the error condition indicating the end-of-file is returned by the OpenVMS Record Management Services (OpenVMS RMS), the command interpreter performs the error action specified by the current ON command. For example, OpenVMS RMS returns the error status %RMS-E-EOF. This causes a command procedure to exit unless the procedure has established its own error handling.


Previous Next Contents Index