prohaska@coors.DEC (08/20/85)
I have developed a preprocessor for writing DCL command procedures
using control structures like if-then-else, while, for etc. It is
similar to what RATFOR is for writing structured FORTRAN. The
preprocessor is written in C. I posted the source to net.sources
about a month ago. I am posting an excerpt from the documentation to
net.decus. If there is enough interest, I'll post the source to
net.decus. Or you can send me individual inquires for the source.
Sohail Aslam
...decvax!decwrl!dec-rhea!dec-coors!prohaska
Here's the excerpt.
SDCL -- A Preprocessor for Structured DCL
The command language under the VAX/VMS operating system is called
Digital Command Language, or DCL. DCL provides a whole host of
capabilities that allow the user not only execute simple commands but
develop command procedures that can accomplish a complex task. DCL
provides variables, conditional operators, an IF-THEN-command
construct and a number of built-in functions. It is thus a small
programming language. Unfortunately, the only control structure
provided is the
IF condition THEN a command
By building a simple preprocessor, I have extended the control
structure to include C like control structures, e.g, if-else, while,
for, do-while etc. These structures can operate on a single command
or a group of commands.
The real motivation for wanting to have structured DCL came from
the tradition set by RATFOR (RATional FORtran). For those of you not
familiar with RATFOR, RATFOR allows one to write code in FORTRAN in a
C like manner. DCL has similar deficiencies when it comes to writing
command procedures. I just wanted to illustrate that one does not
have to live with GOTO's and COMEFROM's in one's programming
practices. It is rather trivial to develop a layer of structured
environment on top of something that does not support it.
Page 2
The language recognized, and thus parsed, by sdcl is very simple.
Here it is BNF form:
program : statement
| program statement
statement : if ( condition ) statement
| if ( condition ) statement else statement
| while ( condition ) statement
| for ( intialize ; condition ; reinitialze )
statement
| do statement while ( condition )
| break
| next
| { program }
| other
Here is a summary of sdcl usage.
o The input file to sdcl is an ordinary text file containing
sdcl statements. Unlike DCL, statements must not begin with
a "$" sign.
o Statements can be enclosed within {} to form the so-called
compound statement.
o The preprocessor looks at the first token of each statement
to determine the type of statement so you should not preceed
keywords with DCL labels e.g. "usage: if( p1 .eqs. ..".
Statements that donot match one of the structured statements
are classified as "other" and simply emitted.
o Any sdcl source statement can be continued across more that
one line by placing a "\" (backslash) just before the end of
line.
o In structured constructs, the "\" need not be used however,
because sdcl can infer whether the constructs is complete or
not by simply going across line boundaries until satisfied.
So if the condition part is too long to fit on one line in an
"if" statement, it can simply be continued on the next line.
o Donot use the "-" (minus) as the continuation character in
sdcl statements.
o If a source line begins with a "#" sign, the pound sign is
removed and rest of the line is emitted AS IS. This can be
used to pass lines through sdcl untouched to DCL.
Page 3
Here is a command procedure to give you a flavor of sdcl,
/* Bun -- VMS DCL command procedure to bundle files into */
/* distribution package which can then be unbundled */
/* using UNIX shell. The output will be placed on the */
/* on the file given as the arg to this procedure */
if( p1 .eqs. "" ){
write sys$output\
"Usage: bundle outfile (outfile will receive bundle)"
exit /* DCL exit */
}
/* if the file exists, open it, otherwise create it */
open/write/err=out_err fout 'p1'
exist := "TRUE"
out_err:
if( exist .nes. "TRUE" ){
create 'p1'
open/write/err=give_up fout 'p1'
}
q := "'"
for( rc = 0; ; ){ /* no condition, no reinit */
inquire infile "File? "
if( infile .eqs. "" )
break /* time to wrapup */
open/read/err=infile_err inf 'infile'
write fout "echo ''infile' 1>&2"
write fout "cat >''infile' <<''q'END OF ''infile'''q'"
rc = rc + 2
done = 0
while( done .eq. 0 ){
read/end=eof inf line
write fout line
rc = rc + 1
}
eof: close inf
write fout "END OF ''infile'"
rc = rc + 1
next
/*
come here if trouble opening 'infile'
*/
infile_err: write sys$output \
"error opening ''infile'"
}
if( rc .gt. 0 ){
write sys$output "''rc' records written to ''p1'"
close fout
}
else
write sys$output "0 records written out"
exit