Online Expert Day - HPE Data Storage - Live Now
April 24/25 - Online Expert Day - HPE Data Storage - Live Now
Read more
Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Disabling and enabling DCL verification elegantly

SOLVED
Go to solution
Jim Geier_1
Regular Advisor

Disabling and enabling DCL verification elegantly

Having been a very-long-time VMS system manager, I thought I knew this, but I find that I don't.

I often disable and enable DCL verification in a command procedure like:

$ save_verify = 'f$verify(0)'
$ some-command-that-will-not-be-seen
$ if save_verify then set verify

This works well inside the DCL -- the three lines shown above do not show up if verification is on. The problem is exiting. I can simply let the end-of-file be the exit, and do the following:

$ save_verify = 'f$verify(0)'
$
$! DCL lines
$
$ if save_verify then set verify

If the command procedure contains only those five lines, the last line will not be displayed, the verification state will be restored, and the procedure wil exit with a status of 1. The problem is exiting at a different point and/or with a status. I want to be able to exit the DCL script with a status and enable verification if it was on but not have the exit line be verified. I have often done the following:

$ save_verify = 'f$verify(0)'
$! the preceding line does not show up,
$! and verification is turned off
$
$ status = 1
$ if f$search("some_file.dat") .eqs. ""
$ then
$ write sys$output "The file was not found"
$ status = 2322 ! %SYSTEM-E-NOSUCHFILE
$ endif
$
$ exit 'status' + 0*'f$verify(save_verify)'

This almost works, but if verification was on before the DCL is executed, the EXIT line is displayed. How can I exit the DCL with the status, restore the verfication state, and not have the last line displayed? Am I missing something obvious? Am I asking for too much?
5 REPLIES
John Gillings
Honored Contributor
Solution

Re: Disabling and enabling DCL verification elegantly

Jim,
My DCL procedure template starts with:

$ verf='F$VERIFY(F$TRNLNM(F$PARSE(F$ENVIRONMENT("PROCEDURE"),,,"NAME")+"_VERIFY"))

and ends with:

$ EXIT %X10000000.OR.'stat'+(F$VERIFY(verf).AND.0)

This does not display the EXIT command on termination.

The difference is your EXIT command has F$VERIFY in single quotes. This forces it to be executed in the first phase of command parsing. You WANT that on the first line, so verify is enabled or disabled immediately, but not on the last where you want the enable or disable to be deferred to the command execution phase.

FWIW, a bit more of my template:

$ verf='F$VERIFY(F$TRNLNM(F$PARSE(F$ENVIRONMENT("PROCEDURE"),,,"NAME")+"_VERIFY"))
$ self=F$PARSE(";",F$ENVIRONMENT("PROCEDURE"))
$ name=F$PARSE(self,,,"NAME")
$ debug=F$TRNLNM(name+"_DEBUG").NES.""
$ node=F$GETSYI("NODENAME")
$ now=F$CVTIME(,"ABSOLUTE")
$ stat=1
$
$ IF F$EXTRACT(0,1,p1).EQS."#"
$ THEN
$ target=p1-"#"
$ GOTO 'target'
$ ENDIF
$
$ ! Main body here
$
$ GOTO FinExit
$
$ DEBUG:
$ VERIFY:
$ DEFINE/NOLOG 'name'_'target' TRUE
$ IF p2.NES.""
$ THEN
$ @'self' "''p2'" "''p3'" "''p4'" "''p5'" "''p6'" "''p7'" "''p8'"
$ stat=$STATUS
$ GOTO NO'target'
$ ENDIF
$ GOTO FinExit
$ NODEBUG:
$ NOVERIFY:
$ target=target-"NO"
$ IF F$TRNLNM("''name'_''target'").NES."" THEN DEASSIGN 'name'_'target'
$ GOTO FinExit
$
$ FinExit:
$ EXIT %X10000000.OR.'stat'+(F$VERIFY(verf).AND.0)

(I make this the last line of the procedure by convention, but it's not actually necessary).

This allows DCL procedures to implement a simple "subcommand" interpreter by starting P1 with a # symbol. This is particularly useful when generating pipelines of procedures. For example, in the main body, I could code:

$ PIPE @'self' #FIRST | @'self' #SECOND

thus I can code all the pipe segments within the same file. Alternatively it's a kind of "Object Oriented DCL" where the procedure implements a number of "methods" associated with some object.

It also allows my VERIFY and DEBUG logic in the template. I can execute:

$ @MYPROC #VERIFY

to turn it on for this procedure and

$ @MYPROC #NOVERIFY

to turn it off.

The real value here is the ability to easily selectively enable VERIFY for specific procedure(s) that may be called from a deep nest of other procedures.

The other trick is:

$ @MYPROC #VERIFY param1 param2

to execute the procedure with verify on, then turn it off afterwards.

Similarly for #DEBUG, but all that does by default is set the flag "debug". You have to code any debugging, for example:

$ IF debug THEN SHOW SYMBOL MySymbol

Note that the code is identical for all procedures, using F$ENVIRONMENT("PROCEDURE") to discriminate.
A crucible of informative mistakes
Hoff
Honored Contributor

Re: Disabling and enabling DCL verification elegantly

I don't generally care all that much about the last line of DCL command output during verification, as I don't generally "show off" DCL command processing save during the debugging of the command procedure.

What I do use is a latent feature of DCL -- one of many -- which involves processing lexical functions during comments. And I use a logical name to selectively enable verification. For instance:


$! 'f$verify(0)
$ vfy = f$verify(f$trnlnm("WHATSIT_VFY"))
...
$! 'f$verify(0)

Some folks are fond of similar and of extended constructs, the first being John Gillings...

$ verf='F$VERIFY(F$TRNLNM(F$PARSE(F$ENVIRONMENT("PROCEDURE"),,,"NAME
")+"_VERIFY"))

and ends with:

$ EXIT 'stat'+(F$VERIFY(verf).AND.0)

And Jess Goodman uses:

$ VERIFY = 'F$VERIFY(0)'
$ IF (F$MODE().NES."BATCH") THEN VERIFY = F$VERIFY(VERIFY)
...

The Writing Real Programs in DCL Book (2nd ed) goes into a whole lot of detail on programming (I happen to know the fellow that wrote the 2nd edition quite well, and my wife is even married to him), but it's out of print and rather hard to find.

qv:
http://forums12.itrc.hp.com/service/forums/questionanswer.do?threadId=1173943
Jim Geier_1
Regular Advisor

Re: Disabling and enabling DCL verification elegantly

I don't like to rely on "latent" features of DCL. When release notes say something like, this may not work in the future, and is no longer supported, or even this no longer works, I stop using that technique. I recall similar statements about the parsing of anything after the "!" in a command line quite some time back, possibly as far back as V5.4 or V6.1. I stopped using such mechanisms then.

The answer to this problem was, as John Gillings noted, was the apostrophes. The presence of the apostrophes basically says to do it now, for this command line! And in my case of enabling or disabling verification, one wants verification disabled immediately for the current command line, but not when enabling verification -- I want the enabling of verification to take place on the next command line. Therefore, the following does what I want:

$ save_verify = f$$verify(0)'
$! the preceding line does not display,
$! and command line verification is disabled
$!
$!...
$!
$! the last line does not display,
$! and verification is either enabled or not,
$! depending on the value of the "save_verify" symbol
$
$ exit 'status' + 0*f$verify(save_verify)
Jess Goodman
Esteemed Contributor

Re: Disabling and enabling DCL verification elegantly

Hoff, you've mentioned that DCL processes lexical function during comments before. But 'F$VERIFY is the only lexical that DCL will still process if it is after a ! comment delimitter.

A long time ago (VMS 4.x?) DCL did process any 'symbol' or 'lexical' in comments, but it was decided that this behavior was a bad idea, or at least useless, for anything other than 'F$VERIFY. There were already examples that showed how to turn off verify silently in the first line of a procedure, so an exception was made for 'F$VERIFY because it was useful behavior and changing it would break existing code.

You can easily tell other 'lexical' and 'symbols' are not processed in comments. In a command procedure this line:
$ SET NOON ! 'F$VERIFY(1)'
will be output as either:
$ SET NOON ! 0
or
$ SET NOON ! 1
but a line with a different ! 'lexical' or with ! 'symbol' will show up in verify output exactly as is unless you're still running V4.x.

Also F$CONTEXT, F$CSID, F$DEVICE, F$FILE, F$GETQUI, F$PARSE, F$PID, F$SEARCH, F$SETPRIV can have side effects and a test would show that these side effects will not happen when they are after a ! comment.

The verify output test helps to explain why 'lexicals' and 'symbols' were "processed" when after a ! comment in the first place. DCL processes command lines in multiple steps. The first step is to process 'symbol' and 'lexical' references. After this first step, if verify is on the line is output. Only then do comments get removed, white-space trimmed/compressed, and upcasing occurs.

So it was not a simple matter to change DCL so it would not process a 'lexical' or 'symbol ' in a comment. You can't check fsor a ! comment character until after processing any 'symbol' or 'lexical' reference that comes before it because the substitution string can contain the special characters ' ! or " and they would affect how DCL processes the remaining part of the line. DCL now has to check for a ! comment in two different steps.
I have one, but it's personal.
Hoff
Honored Contributor

Re: Disabling and enabling DCL verification elegantly

My recollection of the history involved here was that an intrepid engineering explorer working deep within DCL made a (reasonable) decision a long time ago to fix DCL to not to execute lexical calls within comments, which then broke existing DCL procedures that exercised this, um, feature, and which then caused DCL to be reworked to allow f$verify to work.

DCL can be very powerful, weak in some areas (the lack of regexp comes to mind), and surprisingly brittle and (due to its installed base) inflexible.

Lua, Python, Ruby and other such have some very nice ideas and capabilities, as do older schemes such as bash. Unfortunately for OpenVMS developers working cross-platform, these interpreters are not available (either by default, or at all) on OpenVMS.