DCL command file processing provides for as many as eight (8) com-line parameters in all versions of OpenVMS (V8.4 and above actually have 16 now), which are used/known as local variables named P1
, P2
, P3
, P4
, P5
, P6
, P7
and P8
within the command file itself. Each of these local “parameter-variables” behaves exactly like any other programmer-created DCL local variables within the script, except for the fact that their initial values are picked up from what the user types on the command line when invoking (running) that script.
In the DCL examples on wiki-page DCL Symbol Substitution - String Substitution Examples and Command File Parameters P1 thru P8, you can see how P1
is used in the first FANCYSHOW.COM
script; all 8 parameter-variables are demonstrated in the last COM_FILE_PARAMETERS.COM
script.
What follows are the important things to know about DCL scripts and parameters.
@
”; for example, a script named EXAMPLE.COM
:$ @EXAMPLE
If that script is not located in your current working directory (see SHOW DEFAULT
), then use as much device and/or directory/subdirectory file specification as needed to locate it:
$ @[-.CALEB.COMMANDS]EXAMPLE
…or:
$ @DISK$USER:[USERS.CALEB.COMMANDS]EXAMPLE
…and logical names work well too:
$ SHOW LOGICAL USER_COMMANDS USER_COMMANDS = "DISK$USER:[USERS.ALL.COMMANDS]" (LNM$SYSTEM_TABLE) $ @USER_COMMANDS:EXAMPLE
With all these variations, we'll stick with the first, short form for what follows, just for brevity.
$ @EXAMPLE
), the com-file's name can be followed with from one to eight parameters, separated by spaces (blanks).P1
up to P8
.$ @EXAMPLE value1 value2 value3 value4 value5 value6 value7 value8 $ ! becomes: | | | | | | | | $ ! v v v v v v v v $ ! P1 P2 P3 P4 P5 P6 P7 P8 $ ! within the script...
“
:$ @EXAMPLE "lowercase" "MixedCase" upperCASE "UPPERCASE"
In the above example, the values of P1
and P2
will be “lowercase”
and “MixedCase”
respectively, but each value for P3
and P4
will be “UPPERCASE”
.
$ @EXAMPLE "This is a test" "Another test"
Here, P1
's value becomes “This is a test”
, and P2
's value becomes “Another test”
.
$ @EXAMPLE 123 "45678"
With or without quotes, both of the above parameter values are character strings that just happen to contain digit-characters: P1
's value is “123”
, and P2
's value is “45678”
. However, if arithmetic is indeed the goal for either/both of these parameter variables, you can convert these character-strings (containing digit characters) to true DCL integer values using the F$INTEGER
lexical function:
$ ! ...in the command file itself: $ ival1 = F$INTEGER( P1 ) $ ival2 = F$INTEGER( P2 ) $ sum = ival1 + ival2 $ ! or also: $ sum = F$INTEGER( P1 ) + F$INTEGER( P2 ) $ WRITE sys$output "The arithmetic sum of the values is: ''sum'"
yields this output:
The arithmetic sum of the values is: 45801
Note that if you attempt to just “add” P1
and P2
directly, you'll end up with string concatenation:
$ ! ...again, in the command file: $ not_a_sum = P1 + P2 $ WRITE sys$output "Wrong! The arithmetic sum of the values is not: ""''not_a_sum'""" $ WRITE sys$output "That is just a concatenated string of digit-characters..."
yields:
Wrong! The arithmetic sum of the values is not: "12345678" That is just a concatenated string of digit-characters...
You know to execute a command file “interactively,” from the command line as seen above:
$ @UTILS:DISK_BACKUP dka0: now mkb300: verify
which will execute the command file DISK_BACKUP.COM
from the UTILS:
directory (likely a logical name), and passes four parameter values, “DKA0:”
, “NOW”
, “MKB300:”
and “VERIFY”
(all are UPCASED, because no quotes were used on any of the parameter values/words), which become P1
, P2
, P3
and P4
, respectively, within the script.
You likely know how to run that same command file in a batch job, perhaps delaying it until sometime this evening when everyone's gone home for the day:
$ SUBMIT /AFTER=21:00 UTILS:DISK_BACKUP
But what if you need to provide parameters to that batch job when it runs? Certainly not like this:
$ SUBMIT /AFTER=21:00 UTILS:DISK_BACKUP dka0: now mkb300: verify $ ! wrong!---^^^^^ ^^^ ^^^^^^^ ^^^^^^
That's wrong syntax for the SUBMIT
command… those “parameter words” will not be seen as actual parameter values in the SUBMIT
command's syntax. Instead, you pass parameter values to the batch job like this:
$ SUBMIT /AFTER=21:00 UTILS:DISK_BACKUP /PARAMETER=(dka0:,now,mkb300:,verify) $ !... or like this -- double-quoting continues to work for lowercase and/or multi-word values: $ SUBMIT /AFTER=21:00 UTILS:DISK_BACKUP /PARAMETER=("dka0:","now","mkb300:","verify")
Normally, eight parameters P1…P8 is sufficient for almost any script/application, but sometimes you might need more. There are two ways to handle this – The first one requires the assistance (and approval) of your VMS system administrator; the second one you can just implement yourself. Specifically:
P1
…P16
rather than the traditional eight parameters.
(Note to system administrators: If you consider using the DCL_CTLFLAGS approach, be sure to read the help text $ MCR SYSGEN HELP SYS_PARAMETERS DCL_CTLFLAGS
in its entirety; and see the text for Bit 3
specifically. If you elect to make this change for your system, be certain to include this parameter and its new value in your system's SYS$SYSTEM:MODPARAMS.DAT
file so that it will be included in future AUTOGEN operations. In practice, this change is rarely justified and/or actually done; the value 0
is quite normal for this parameter on most VMS systems.)
Here's an example of the second method, “compound parameter values”:
$ ! COMPOUND_PARAMETERS.COM $ ! $ ! Assume that com-line parameters P1..P7 are allocated and used $ ! for specific purposes in this script, but you need "a few more"... $ ! $ ! Make P8 function as a compound parameter: "val8;val9;val10;val11;..." $ ! $ ! ...Process parameters P1..P7 here... $ ! $ SEP = ";" ! the "separator character", here, a semicolon... (can be any single character you want) $ j = 0 ! initialize ("j" is a short-&-sweet name for an "index" variable) $CPLOOP1: $ arg'j' = F$ELEMENT( j, SEP, P8 ) $ IF ( arg'j' .EQS. SEP ) THEN GOTO CPCONTINUE1 ! =SEP character means no more elements in P8 $ ! ...else, got a good element/value from P8... $ ! ...so edit that element: Upcase it, remove leading/trailing space, compress multiple spaces $ arg'j' = F$EDIT( arg'j', "TRIM,COMPRESS,UPCASE" ) $ j = j + 1 ! since it's a good one, count it $ GOTO CPLOOP1 ! and try again... $ ! $CPCONTINUE1: $ ! At this point, we've got from zero (0) to j+1 elements extracted from P8 $ ! (j is our upper-limit)... $ ! Process these compound values (here, demo'd by just echoing them out to display): $ i = 0 ! another short&sweet index variable $ WRITE sys$output "Echo P8 compound parameter values:" $CPLOOP2: $ ! When i > j, we're done... $ IF ( i .GT. j ) THEN GOTO CPCONTINUE2 ! done with all compound parameters? $ ! ...nope, process the compound parameter (here, just display it): $ tmp = arg'i' ! makes single-tick substitution easy in the quoted-output: $ WRITE sys$output " ''tmp'" $ ! ...or, this works too: $ WRITE sys$output " ", arg'i' $ i = i + 1 ! next counted-element... $ GOTO CPLOOP2 $ ! $CPCONTINUE2: $ ! ...script continues here $ WRITE sys$output "" $ WRITE sys$output "...processing continues" $ WRITE sys$output "" $Done: $ EXIT 1
Then you could invoke (call) this script, with more than 8 parameter values, as follows:
$ @COMPOUND_PARAMETERS value1 value2 value3 value4 value5 value6 value7 - "value8; value9; value10 is multiword; value11; value12" Echo P8 compound parameter values: VALUE8 VALUE9 VALUE10 IS MULTIWORD VALUE11 VALUE12 ...processing continues $
This approach has the benefit of being generally portable to other VMS systems without needing to involve other system admins in messing with the DCL_CTLFLAGS system parameter.