Updated: 11 December 1998 |
OpenVMS User's Manual
Previous | Contents | Index |
A case statement is a special form of conditional code that executes one out of a set of command blocks, depending on the value of a variable or expression. Typically, the valid values for the case statement are labels at the beginning of each command block. The case statement passes control to the appropriate block of code by using the specified value as the target label in a GOTO statement.
To write a case statement, you must:
To list the labels, equate a symbol to a string that contains a list of the labels delimited by slashes (or any character you choose to act as a delimiter). This symbol definition should precede the command blocks.
This example equates the symbol COMMAND_LIST to the labels PURGE, DELETE and EXIT:
$ COMMAND_LIST = "/PURGE/DELETE/EXIT/" |
To write the case statement, follow this procedure:
Step | Action |
---|---|
1 | Use the INQUIRE command to get the value of the case variable. |
2 | Use the IF command with F$LOCATE and F$LENGTH to determine whether the value of the case variable is valid. |
3 |
If the case variable is valid, execute the case statement (with a GOTO
command) to pass control to the appropriate block of code.
Otherwise, display a message and exit or request a different case value. |
In the following example, the label is equated to the full command name. Therefore, F$LOCATE includes the delimiters in its search for the command name to ensure that the command is not abbreviated:
$GET_COMMAND: $ INQUIRE COMMAND - "Command (EXIT,PURGE,DELETE)" $ IF F$LOCATE ("/"+COMMAND+"/",COMMAND_LIST) .EQ. - F$LENGTH (COMMAND_LIST) THEN GOTO ERROR_1 $ GOTO 'COMMAND' . . . $ERROR_1: $ WRITE SYS$OUTPUT "No such command as ''COMMAND'." $ GOTO GET_COMMAND |
Each block of commands may contain one or more commands. Begin each command block with a unique label. End each command block by passing control to a label outside the list of command blocks.
In the following example, each block of commands begins with a unique label (PURGE:, DELETE:) and is ended by passing control to a label (GOTO GET_COMMAND) outside of the current command block:
$GET_COMMAND: . . . $PURGE: $ INQUIRE FILE $ PURGE 'FILE' $ GOTO GET_COMMAND $ ! $DELETE: $ INQUIRE FILE $ DELETE 'FILE' $ GOTO GET_COMMAND $ ! $EXIT: |
You can write loops that test variables at the beginning of the command block (as described in Chapter 15). However, you can also write loops that test the termination variable at the end of the loop, by following this procedure:
Step | Action |
---|---|
1 | Begin the loop. |
2 | Perform the commands in the body of the loop. |
3 | Change the termination variable. |
4 |
Test the termination variable.
If the condition is not met, go to the beginning of the loop. |
5 | End the loop. |
Note that when you test the termination variable at the end of the loop, the commands in the body of the loop are executed at least once, regardless of the value in the termination variable.
Both of the command blocks shown in this example execute a loop that terminates when COMMAND equals "EX" (EXIT). F$EXTRACT truncates COMMAND to its first two characters. In the first example, COMMAND, the termination variable, is tested at the beginning of the loop; in the second, it is tested at the end of the loop:
$ ! EXAMPLE 1 $ ! $GET_COMMAND: $ INQUIRE COMMAND- "Command (EXIT,DIRECTORY,TYPE,PURGE,DELETE,COPY)" $ COMMAND = F$EXTRACT(0,2,COMMAND) $ IF COMMAND .EQS. "EX" THEN GOTO END_LOOP . . . $ GOTO GET_COMMAND $END_LOOP: |
$ ! EXAMPLE 2 $ ! $GET_COMMAND: $ INQUIRE COMMAND- "Command (EXIT,DIRECTORY,TYPE,PURGE,DELETE,COPY)" $ COMMAND = F$EXTRACT(0,2,COMMAND) . . . $ IF COMMAND .NES. "EX" THEN GOTO GET_COMMAND $ ! End of loop |
To perform a loop a specific number of times, use a counter as the termination variable. In the following example, 10 file names are input by the user and placed into the local symbols FIL1, FIL2, ..., FIL10:
$ NUM = 1 ! Set counter $LOOP: ! Begin loop $ INQUIRE FIL'NUM' "File" ! Get file name $ NUM = NUM + 1 ! Update counter $ IF NUM .LT. 11 THEN GOTO LOOP ! Test for termination $END_LOOP: ! End loop . . . |
The following example uses a counter to control the number of times a loop executes. The loop executes 10 times; the termination variable is tested at the end of the loop:
$! Obtain 10 file names and store them in the $! symbols FILE_1 to FILE_10 $! $ COUNT = 0 $ LOOP: $ COUNT = COUNT + 1 $ INQUIRE FILE_'COUNT' "File" $ IF COUNT .LT. 10 THEN GOTO LOOP $! $ PROCESS_FILES: . . . |
The symbol COUNT is used to record the number of times the commands in the loop are executed. COUNT is also used to create the symbol names FILE_1, FILE_2, and so on to FILE_10. Note that the value of COUNT is incremented at the beginning of the loop but is tested at the end of the loop. Therefore, when COUNT is incremented from 9 to 10, the loop executes a last time (obtaining a value for FILE_10) before the IF statement finds a false result.
To perform a loop for a known sequence of values, use the F$ELEMENT lexical function. The F$ELEMENT lexical function obtains items from a list of items separated by delimiters. You must supply the item number, the item delimiter, and the list as arguments for F$ELEMENT.
For more information on how to use the F$ELEMENT lexical function, see the OpenVMS DCL Dictionary.
In the following example, the files CHAP1, CHAP2, CHAP3, CHAPA, CHAPB, and CHAPC are processed in order:
$ FILE_LIST = "1,2,3,A,B,C" $ INDEX = 0 $PROCESS: $ NUM = F$ELEMENT(INDEX,",",FILE_LIST) $ IF NUM .EQS. "," THEN GOTO END_LOOP $ FILE = "CHAP''NUM'" $ ! process file named by FILE . . . $ INDEX = INDEX + 1 $ GOTO PROCESS $END_LOOP: $ EXIT |
In the following example, the command procedure uses a loop to copy the files listed in the symbol FILE_LIST to a directory on another node:
$ FILE_LIST = "CHAP1/CHAP2/CHAP3/CHAP4/CHAP5" $ NUM = 0 $! $! Process each file listed in FILE_LIST $ PROCESS_LOOP: $ FILE = F$ELEMENT(NUM,"/",FILE_LIST) $ IF FILE .EQS. "/" THEN GOTO DONE $ COPY 'FILE'.MEM MORRIS::DISK3:[DOCSET]*.* $ NUM = NUM + 1 $ GOTO PROCESS_LOOP $! $ DONE: $ WRITE SYS$OUTPUT "Finished copying files." $ EXIT |
The first file returned by the F$ELEMENT lexical function is CHAP1, the
next file is CHAP2, and so on. Each time through the loop, the value of
NUM is increased so that the next file name is obtained. When the
F$ELEMENT returns a slash, all the items from FILE_LIST have been
processed and the loop is terminated.
16.20 Using the PIPE Command
The PIPE command executes one or more DCL command strings from the same command line. It enables you to perform UNIX-style command processing, such as command pipelining, input/output redirection, and conditional and background execution.
This style of command processing supports the development and use of Internet software, which often expects some form of pipeline command parsing to be present on both host and target systems.
The following sections describe different methods of using the PIPE command to execute DCL commands, how to interrupt a PIPE command, and how to improve subprocess performance. There are also examples.
For complete information about the PIPE command, refer to the OpenVMS DCL Dictionary: N--Z.
You can specify multiple DCL commands in a single PIPE command. The DCL commands are then executed sequentially. Use the following format:
PIPE command-sequence ; command-sequence [; command-sequences]... |
16.20.1 Using the PIPE Command for Conditional Command Execution
A command sequence is executed conditionally depending on the execution result of the preceding command sequence. Use the format:
PIPE command-sequence1 && command-sequence2 |
Note that command-sequence2 executes if and only if command-sequence1 succeeds. If you use the following format, command-sequence2 executes if and only if command-sequence1 fails.
PIPE command-sequence1 || command-sequence2 |
16.20.2 Using the PIPE Command for Pipeline Execution
A pipeline is a sequence of pipeline-segment commands connected by pipes, represented by the vertical-bar (|) separator. A pipeline-segment command is a DCL command that appears in a pipeline. The pipe connects the SYS$OUTPUT of one pipeline-segment command to the SYS$INPUT of the next command. The format of a pipeline is as follows:
PIPE pipeline-segment-command | pipeline-segment-command [|...] |
Each pipeline-segment command runs in a separate subprocess with its SYS$OUTPUT connected to the SYS$INPUT of the next pipeline-segment command. These subprocesses execute in parallel; however, they are synchronized to the extent that each pipeline-segment command, except the first, reads the standard output of its predecessor as its standard input. A pipeline completes execution when the last pipeline-segment command is finished.
It is very common to use "filter applications" in a pipeline. A filter application is a program that takes data from SYS$INPUT, transforms it in a specific way, and writes it to SYS$OUTPUT.
Some aspects of DCL function differently in the context of a pipeline. For example:
$ ! TEE.COM - command procedure to display/log data flowing through $ ! a pipeline $ ! Usage: @TEE log-file $ $ OPEN/WRITE tee_file 'P1' $ LOOP: $ READ/END_OF_FILE=EXIT SYS$PIPE LINE $ WRITE SYS$OUTPUT LINE ! Send it out to the next stage of the pipeline $ WRITE tee_file LINE ! Log output to the log file $ GOTO LOOP $ EXIT: $ CLOSE tee_file $ EXIT |
$ PIPE SHOW SYSTEM | @TEE showsys.log | SEARCH SYS$INPUT LEF |
$ PIPE ... | (SET VERIFY=IMAGE ; ...) | ... |
$ PIPE CC/NOOBJ/NOLIS TEST.C | SEARCH SYS$INPUT/WIND=(1,1) "%cc-w-" %SEARCH-F-RFAERR, RMS error using RFA access -RMS-F-RAC, invalid record access mode |
A subshell is one or more command sequences separated by separators and enclosed in parentheses. The format of a subshell is as follows:
PIPE ( command-sequence [separator command-sequence]... ) |
The command sequences in a subshell are executed in a subprocess
environment. DCL waits for the subshell to complete before executing
the next command sequence. The ( ) separator is similar to the
SPAWN/WAIT command.
16.20.4 Using the PIPE Command for Background Execution
Command sequences can be executed in a subprocess environment by using the following form:
PIPE command-sequence [ separator command-sequence]... & |
DCL does not wait for the command sequences to finish. Control passes
back to DCL once the background subprocess is created.
16.20.5 Using the PIPE Command for Input/Output Redirection
A command sequence can redirect its SYS$INPUT, SYS$OUTPUT, or SYS$ERROR to a file during execution of the command as follows:
PIPE command-sequence < redirected-input-file |
PIPE command-sequence > redirected-output-file |
PIPE command-sequence 2> redirected-error-file |
A pipeline-segment command can also redirect its SYS$INPUT, SYS$OUTPUT or SYS$ERROR. However, SYS$OUTPUT redirection is allowed only for the last pipeline-segment command, and SYS$INPUT redirection is allowed only for the first pipeline-segment command.
Note that a PIPE command redirection is different from one created using the DEFINE or ASSIGN command. The differences are as follows:
When SYS$OUTPUT is redirected, the redirected output file is always created, whether the command sequence actually writes to SYS$OUTPUT. If a version of a file with the same name as the redirected output file already exists, a new version of that file is created. (This behavior is the same as using the DEFINE or ASSIGN command to redefine SYS$OUTPUT in supervisor mode.) Note that the redirected file is created before the command sequence is executed. If the redirected file is also used in the command sequence, the operation may fail, as in the following example:
$ PIPE SEARCH TRANS.LOG "alpha" > TRANS.LOG %SEARCH-W-OPENIN, error opening TRANS.LOG;2 as input -RMS-E-FLK, file currently locked by another user |
When SYS$ERROR is redirected, the redirected error file is only created
when the command sequence actually writes to the SYS$ERROR during
execution, and there is no existing file with the same name as the
redirected error file. If a file with the same name as the redirected
error file already exists, that file is opened as the redirected error
file. The error output generated by this command sequence is then
appended to the end of the redirected error file. (This behavior is the
same as using the DEFINE or ASSIGN command to redefine SYS$ERROR in
supervisor mode.)
16.20.6 Interrupting a PIPE Command
You can interrupt a PIPE command by pressing Ctrl/Y. If the PIPE command is executing in a pipeline or a subshell command sequence, the command sequence and the PIPE command are deleted. In this case, a CONTINUE command entered immediately after the interrupt will not resume the execution of the PIPE command.
If the PIPE command is executing a command sequence other than a
subshell or a pipeline command sequence, DCL behaves as if the command
sequence were entered as a DCL command without the PIPE command verb
and interrupted by Ctrl/Y. See Section 3.11.2 and Section 15.11 for more
information about the Ctrl/Y interrupt.
16.20.7 Improving Subprocess Performance
A PIPE command can generate a number of subprocesses during execution. Often, the applications invoked by command sequences do not depend on the process logical names and symbol names. In this case, the spawning of subprocesses can be accelerated by using the /NOLOGICAL_NAMES and /NOSYMBOLS qualifiers, which suppress the passing of process logical names and symbols to the subprocesses created by the PIPE command.
The following examples use the PIPE command:
$ CD_WORK :== PIPE SAVE_DIR=F$DIRECTORY() ; SET DEFAULT FOO:[WORK] $ BACK :== SET DEF 'SAVE_DIR' $ $ CD_WORK ! Switch to working directory $ : $ : $ BACK ! Switch back to home directory $ GET_RECORD :== PIPE READ/END_OF_FILE=CLEANUP IN RECORD ; - F$EDIT(RECORD, "COMPRESS, TRIM") $ $ OPEN IN EMPLOYEE.DAT $ LOOP: $ GET_RECORD $ : $ : $ GOTO LOOP $ $ CLEAN_UP: $ : |
$ PIPE cc foo.c && link foo, sys$library:vaxcrtl.olb/lib |
$ PIPE RUN COLLECT_DATA.EXE || GOTO CLEAN_UP $ : $ : $ EXIT $ $ CLEAN_UP: $ : $ : |
$ PIPE COPY LARGE_FILE.DAT REMOTE"user password"::[DESTINATION]*.* & |
$ PIPE (SET DEF [.DATA_DIR] ; BACKUP DATA.SAV/SAV [...]) ; RUN FOO |
$ PIPE SHOW SYSTEM | SEARCH SYS$INPUT HIB |
$ PIPE RUN TEST | SORT/SPECIFICATION=TEST.SRT SYS$INPUT SYS$OUTPUT - | DIFF SYS$INPUT TEST.BENCHMARK |
$ PIPE ( SET DEF WRK$:[WORK] ; RUN REPORT ) | MAIL SYS$INPUT SMITH |
$ more :== TYPE/PAGE=SAVE SYS$INPUT $ PIPE ANA/RMS PAGE.TXT | more Check RMS File Integrity 26-JAN-1996 16:12:00.06 Page 1 SYS$SYSDEVICE:[TEST]PAGE.TXT;2 FILE HEADER File Spec: SYS$SYSDEVICE:[TEST]PAGE.TXT;2 File ID: (4135,58220,0) Owner UIC: [PIPE] Protection: System: RWED, Owner: RWED, Group: RE, World: Creation Date: 26-NOV-1996 16:08:50.05 Revision Date: 26-NOV-1996 16:09:09.06, Number: 1 Expiration Date: none specified Backup Date: none posted Contiguity Options: none Performance Options: none Reliability Options: none Journaling Enabled: none RMS FILE ATTRIBUTES RETURN/SPACE=More, PREV/NEXT=Scroll, INS/REM=Pan, SELECT=80/132, Q=Quit |
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
6489PRO_044.HTML
|