Copyright 1988-2016 by Kevin G. Barkes All rights reserved. This article may be duplicated or redistributed provided no alterations of any kind are made to this file. This edition of DCL Dialogue is sponsored by Networking Dynamics, developers and marketers of productivity software for OpenVMS systems. Contact our website www.networkingdynamics.com to download free demos of our software and see how you will save time, money and raise productivity! Be sure to mention DCL Dialogue! DCL DIALOGUE Originally published July, 1988 By Kevin G. Barkes Errors, Non-Errors and Errata For the most part, DCL is a very friendly environment in which to develop utilities. The command language interpreter excels in providing programmers with information about the environment in which their procedures execute. Even when DCL responds in an atypical, brain-damaged way to a command, there are usually simple workarounds available. Consider, for instance, the SET DEFAULT command. While I'd allegedly taken the pledge and totally forsaken DCL procedures offering "enhanced" set default capabilities, I decided to create a procedure which emulates the MS-DOS CD (change directory) command. The challenge here was to recover from a SET DEFAULT to an invalid directory. Normally after issuing a DCL command, you can determine the success of the execution by examining the value of $SEVERITY. Totally successful command executions place the value 1 in $SEVERITY; commands which neither completely succeed nor completely fail (that is, they terminate with an informational status) insert the integer 3 in $SEVERITY. I built the .COM file and was chagrined to discover it wasn't behaving properly; it appeared as if the value in $SEVERITY was incorrect. A simple test proved this assumption: $ set def [-.qrk] (non-existent directory) $ sho def DISK1:[USERFILES.TEST.QRK] %DCL-I-INVDEF, DISK1:[USERFILES.TEST.QRK] does not exist $ write sys$output $severity 1 DCL's text of the severity level, "-I-", for informational, was correct. Nonetheless, the value placed in $SEVERITY was 1, indicating normal successful completion, rather than 3, successful completion with informational. This was an interesting discovery but didn't didn't solve my problem. The workaround was fairly simple, even though it did make the procedure a bit longer: $! CD.COM $ IF P1 .EQS. "" - THEN GOTO B $ IF F$PARSE(P1) .NES. "" - THEN GOTO A $ WRITE SYS$OUTPUT - "''P1' is an invalid default." $ EXIT $ A: $ SET DEFAULT 'P1' $ B: $ WRITE SYS$OUTPUT - F$ENV("DEFAULT") $ EXIT There are really only two "active" lines in the procedure. The first line after the comment tests to see if P1 is blank, that is, that no default was specified. If the parameter is empty, the procedure branches to B: and displays the current default using the F$ENVIRONMENT lexical function. If P1 does contain text, the lexical function F$PARSE is used to test whether the specified default exists. If it doesn't, F$PARSE returns the null string and the procedure's error message is displayed. Otherwise, the procedure executes the set default command and displays the new default. Using F$PARSE has another benefit; give it a bad default or incorrect directory specification, and all it does is return the null string. No error messages are generated, unlike SET and SHOW DEFAULT which do the DCL equivalent of screaming bloody murder when bad data is passed to them. This eliminates the need for using SET MESSAGE to inhibit unwanted error messages. CD is all I need in a set default utility, and I've included it here just to show some of the ways of getting around limitations in DCL. Please, please, don't send me any more, unless you've developed a telepathic interface to the keyboard! ***** STUPID DCL TRICKS This was the "short title" of the session I was to present at the Cincinnati DECUS Symposium in May, although the seminar was officially entitled "Utility Development in DCL". This column's being written about a month prior to the event and (apologies to David Letterman) I'm busily putting the finishing touches on the DCL Lexicalthrillcam and trying to find a 50 foot platform from which to drop a DCL Dictionary. "Stupid DCL Tricks" will also be an irregular feature of this column, and readers are invited to send in examples of contorted uses of DCL to achieve otherwise practical goals. There are only two rules: the procedures must perform some useful function and must represent the simplest DCL solution to the problem. I'll start off the proceedings with REC.COM, (PROGRAM 1) which returns the number of records contained in a file. There is no direct way to obtain this information from DCL; the F$FILE_ATTRIBUTES lexical can provide scads of data, but a file's record count isn't one of them. REC.COM is about as inefficient and kludgy a procedure as you'll find, but it works and its existence can be justified since it performs a valid function. The results of REC.COM's operation is placed in the global symbol REC_COUNT. The symbol will contain either the number of records in the file, or the value -1 if the procedure failed for some reason. Additional error-checking can be added to bulletproof the procedure, but for our purposes it's sufficient. @REC FILENAME invokes the procedure. If the specified file can't be found or is an invalid file name, REC_COUNT is set to -1. Otherwise, we use the APPEND/LOG command to append the file to the null device, and use the ASSIGN/USER to redirect the output of the file to REC.TMP. Next, we read in REC.TMP and, using several lexicals, extract the number of records "appended" to the null file. The value is assigned to REC_COUNT and the procedure performs clean-up prior to exit. About as elegant as an oiled duck, but it works. ************ Program 1 $! REC.COM $ SET NOON $ IF P1 .EQS. "" THEN GOTO ZIPPO $ IF F$SEARCH(P1) .EQS. "" THEN GOTO ZIPPO $ ASSIGN/USER REC.TMP SYS$OUTPUT $ APPEND/LOG 'P1' NLA0: $ OPEN/READ IN REC.TMP $ READ IN REC $ START = F$LOCATE("(",REC) + 1 $ VAL2 = F$LOCATE(" records",REC) $ REC_COUNT == F$INT(F$EXT(START,VAL2-START,REC)) $ CLOSE IN $ DELETE/NOCONFIRM/NOLOG REC.TMP;* $ EXIT $ ZIPPO: $ REC_COUNT == -1 $ EXIT ---------- Kevin G. Barkes is an independent consultant. He publishes the KGB Report newsletter, operates the www.kgbreport.com website, lurks on comp.os.vms, and can be reached at kgbarkes@gmail.com.