DCL stands for Digital Command Language. It is the primariy command line interface on OpenVMS systems. DCL is in charge of interpreting commands entered either interactively from a terminal, or read form a command procedure.
[up]
Often the same series of DCL commands need to be issued many times, or some action needs to be automated. By placing a series of DCL commands in a file these goals can be attained. DCL supports control logic (IF, GOTO, CALL, etc.) so that quite complicated programs can be written in it, if need be.
Example DCL procedure (finds all organization:sequential files in a directory - not a terribly useful thing to do!):
$!first line of DCL procedure: search_example.com $!P1 is a search string $ if(P1 .nes. "") $ then $ string = P1 $ else $ string = "*.*" $ endif $top: $ file = f$search(string) $ if (file .eqs. "")then exit $ org = f$file_attributes(file,"ORG") $ if (org .eqs. "SEQ")then write sys$output file $ goto top $!last line of DCL procedure $ @SEARCH_EXAMPLE Default, look at everything in local directory $ @SEARCH_EXAMPLE [.SUBDIR]*.TXT Look where indicated $ SUBMIT/LOG=SYS$LOGIN:/NOPRINT/AFTER=20:00 SEARCH_EXAMPLE Default, but do in batch, after 8:00 PM $ SUBMIT/LOG=SYS$LOGIN:/NOPRINT/AFTER=20:00 - $_/PARAMETER=("[.SUBDIR]*.TXT")SEARCH_EXAMPLE Look where indicated, in batch after 8:00 PM
[up]
You would use one if you don't want to type the same thing over and over, if you want something to happen when you aren't around, or if you need to do some processing and/or calculations, but not manually.
[up]
Use the same tools as for any other file.
[up]
You can pass up to eight parameters to a DCL procedure.
$ @procedure A B C D E F G H
Note: If any parameter A through H contains case sensitive values or spaces, enclose it in double quotes.
[up]
You can pass up to eight parameters to a DCL procedure which is run in batch:
$ SUBMIT/parameter=(A,B,C,D,E,F,G,H) procedure
Note: If any parameter A through H contains case sensitive values or spaces, enclose it in double quotes.
[up]
Inside a DCL command file they will appear as symbols, named P1 through P8.
Here is a common trick:
$ if(P1 .eqs. "") $ then $! There was no P1 parameter $ else $! There was a P1 parameter $ endif
Note that other global symbols (those defined with :== or == before the procedure is run) may also be used inside a procedure. However, the proper way to test for one of these is like this:
$ if("''SOME_GLOBAL_SYMBOL'" .eqs. "")
The "''symbol'" form must be used with global symbols because otherwise if one were not defined the procedure would generate an error like this:
Undefined symbol - check validity and spelling \SOME_GLOBAL_SYMBOL\
The simpler form can be used for P1 through P8 because when a procedure starts, DCL creates all eight symbols automatically (even those that were not specified on the command line, which are set to "").
[up]
Here are some examples of the control structures in DCL, for more information on each use HELP:
$ ON condition THEN action $ IF (expression) THEN action $ IF (expression) $ THEN $! action1 $ ELSE $ action2 $ ENDIF $ TOP: This is a label, note the colon. $ GOTO TOP This is a goto, not the lack of a colon.
Note 1: As for command procedures, up to eight parameters may be passed to a subroutine. This form is roughly equivalent to creating a separate file and executing it via "@filename parameters". Here is an example, note especially the SUBROUTINE and ENDSUBROUTINE lines:
$ SUB1: SUBROUTINE Begin a subroutine declaration. $! a bunch of commands that compose the subroutine $ EXIT Exit point for subroutine. $ ENDSUBROUTINE End subroutine declaration. $ CALL SUB1 A B C D E F G H
Note 2: There is another form of subroutine, a labeled subroutine, that runs at the same level as the calling program. One cannot pass parameters to them. Not is there a need to - they have direct access to all locally defined variables. Here is an example of this second type of subroutine In the following example of this second type of subroutine, note in particular that the transfer of control to the subroutine is via a GOSUB rather than a CALL, that the SUBROUTINE and ENDSUBROUTINE lines are absent, and the use of RETURN instead of EXIT:
$ SEMISUB1: Begin a labeled subroutine. $! a bunch of commands that compose the subroutine $ RETURN [value] Exit point for subroutine. $! $ GOSUB SEMISUB
[up]
There are a lot things that one can do with symbols. Here is a not particularly useful piece of code that shows some of them.
$ INQUIRE string "This is a prompt, enter a string" $! echo the string to the terminal, note that it has gone to all upper case $ WRITE SYS$OUTPUT string $! echo the string to the terminal, show what quotes do in double quotes $ WRITE SYS$OUTPUT "This is a ''string'" $! Here's a lexical function - learn them, love them $ x = f$length(string) $ WRITE SYS$OUTPUT "''string' is ''x' characters long" $! one more time, same output, different method $ WRITE SYS$OUTPUT string," is ",x," characters long" $ write sys$output "Here is ''string' in all lower case, no spaces",- F$edit(string,"LOWERCASE,COLLAPSE") $! $! invert string order $! $ ix = X - 1 $ OUTSTRING="" $ TOP: $ OUTSTRING = OUTSTRING + F$EXTRACT(ix, 1, string) $ ix = ix - 1 $ if (ix .ge. 0)then goto top $ write sys$Output "''string' backwards is: ''outstring'" $! $! more fun with strings, replace part of a string $! $ frag = "this is a long string" $ frag[0,4] := THIS $ write sys$output "this is frag now: ''frag'" $! $! remove a piece and glue on another one $! $ where :== disk:[DIR.SUBDIR1] $ where = where - "]" + ".SUBDIR2]filename" $ write sys$Output "Where is ''where'" $! $! ring a bell on the user's terminal $! $ bell[0,7]=7 $ write sys$output "You should hear a bell''bell'"
[up]
Use DEFINE, ASSIGN, DEASSIGN and sometimes SHOW LOGICAL or F$TRNLNM("logical_symbol_name").
Examples:
$ DEFINE there DISK1:[USERS.FRED] Define a logical value specifying a location. $ ASSIGN DISK1:[USERS.FRED] there Same effect as preceding command. $ DEFINE avalue "This is a string that some program needs" $ SHOW LOG avalue "AVALUE" = "This is a string that some program needs" (LNM$PROCESS_TABLE) $ DEASSIGN avalue Get rid of the logical name.
[up]
Use lexical functions. For more information use:
$ HELP LEXICAL Look up info on lexical functions.
See in particular:
F$FILE_ATTRIBUTES Get file information F$GETDVI Get device information F$GETJPI Get job and process information F$GETQUI Get batch and print job information F$GETSYI Get local system information
[up]
To put things like {bell} or {escape} into a text string one must use a special symbol definition syntax. Note that the symbol must not have been previously defined or this will NOT work.
$ bell[0,7]=7 $ esc[0,7]=27 $ write sys$output "''esc'[5mblinking''esc'[m and beeping ''bell'"
The list of escape codes for various terminals is in SYS$SYSTEM:SMGTERMS.TXT, where {$} is used for {escape}. Note that the user's terminal must understand VT type escape codes to respond properly. You can and should check this before sending these codes to a terminal (and NEVER to a batch job). This information can be found via:
$ if(F$GETDVI("TERM","TT_DECCRT"))then some action
[up]
With "vanilla" DCL you cannot - it only supports integer math. However, in some cases you can fake it, for instance, if you need to multiply 1.2 * 1.3, you might instead multiply 12 * 13 and then use other DCL features to shift the decimal point back where you want it.
Sometimes a better option is to use ICALCV. (ICALCV is available via anonymous FTP as [.software]ICALCV.ZIP from seqaxp.bio.caltech.edu, UNZIP is available from ftp.wku.edu) ICALC is a small program that implements a command line calculator, ICALCV is a slightly modified version that places the last 10 results into a comma delimited list and assigns that string to the DCL symbol ICALC_OUT. So, for instance:
$ show symbol icalc ICALC must be defined ICALC == "$ICALC:ICALCV" $ define/user sys$output nla0: suppress terminal output $ icalc 1.2*1.3 $ write sys$Output icalc_out Show the result 1.56
Or, to do a bunch of things at once, for instance, as part of a DCL procedure:
$ string := 1.2*1.3; 1.3*1.5; 1.5*1.9; 1.2*sqrt(10) $ define/user sys$output nla0: suppress terminal output $ icalc 'string' $ write sys$Output icalc_out Show the result 1.56, 1.95, 2.85, 3.794733192
Then use F$ELEMENT to retrieve each desired result, for instance:
$ write sys$output f$element(0,",",icalc_out) 1.56 $ write sys$output f$element(1,",",icalc_out) 1.95
etc.
[up]
Author: David
Mathog
Credits: Rich Lafferty
Maintained by:
helpline@alcor.concordia.ca
Last update: $Date: 1999/05/18 16:16:23 $ -- Rich Lafferty