Copyright 1989-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, 1989 By Kevin G. Barkes Don't Quote Me Everyone has a pet peeve. Mine is excessive use of quotes in DCL. By "excessive", I mean placing quotes around DCL symbols in locations where their use is superfluous, or forcing substitutions with the apostrophe (') when such substitution is unnecessary. For a definitive discussion on the topic, refer to DEC's "DCL Concepts" manual. In any event, here's a brief lowdown on quoting rules in DCL: ASSIGNMENT USE: Symbols are assigned by using =, ==, := and :==. The = and := assign local symbols, while == and :== make global symbol assignments. When you use = or == to assign a string value to a symbol, you must enclose the value being assigned in quotes: $ COMMAND1 = "WRITE SYS$OUTPUT" $ SHOW SYMBOL COMMAND1 COMMAND1 = "WRITE SYS$OUTPUT" If you forget the quotes, you'll get: $ COMMAND1 = WRITE SYS$OUTPUT %DCL-W-UNDSYM, undefined symbol - check validity and spelling \WRITE\ That's because DCL thinks the word WRITE is another symbol. After all, you didn't enclose the phrase in quotes, which is how the = determines if the value is a string. If you need to include quotes in the symbol, you have to enclose the quotes within quotes: $ TEXT1 = "Drive, he said." $ WRITE SYS$OUTPUT TEXT1 Drive, he said. $ TEXT2 = """Drive, "" he said." $ WRITE SYS$OUTPUT TEXT2 "Drive, " he said. Note in the above examples there are no quotes or apostrophes around the symbols TEXT1 or TEXT2. That's because WRITE is one of the commands which can accept a symbol as a command parameter. You can save omit the quotes if you use := or :==, the special string assignment operators: $ COMMAND2 := write sys$output $ SHOW SYMBOL COMMAND2 COMMAND2 = WRITE SYS$OUTPUT $ TEXT1 := Drive, he said. $ WRITE SYS$OUTPUT TEXT1 DRIVE, HE SAID. In addition to assigning a string to a symbol, the := also converts the string to all upper case, compresses multiple spaces and tabs into single spaces, and trims any trailing spaces. If you don't want DCL to do any conversions, enclose the string in quotes: $ TEXT1 := "Drive, he said." $ WRITE SYS$OUTPUT TEXT1 Drive, he said. To include quotes in the symbol, $ TEXT1 := """Drive, "" he said." $ WRITE SYS$OUTPUT TEXT1 "Drive, " he said. Watch what happens when we incorrectly place the quotes: $ TEXT1 := "Drive, " he said. $ WRITE SYS$OUTPUT TEXT1 Drive, HE SAID. In this case, DCL preserved "Drive ,", since it was enclosed in quotes, but converted the "he said", which was unquoted, to all caps. In the above example, we could have formatted the WRITE commands as: $ WRITE SYS$OUTPUT "''TEXT1'" But why bother? WRITE can handle symbols all by itself. MORE THAN WRITE The WRITE command isn't the only one which can deal with symbols without excessive quotes and apostrophes. DEPOSIT, EXAMINE and IF automatically evaluate symbols contained in their command line. DEPOSIT and EXAMINE are a trifle obscure for the typical DCL user, so let's look at IF: $ VAL = 1 $ TEXT = "TRUE" $ IF VAL .EQ. 1 THEN WRITE SYS$OUTPUT TEXT TRUE IF was able to tell that VAL was a symbol and, of course, WRITE could handle the symbol TEXT with no problem. Symbols are legal arguments to lexical functions as well: $ FILE := LOGIN.COM $ TYPE := UIC $ VAL = F$FILE(FILE,TYPE) $ WRITE SYS$OUTPUT VAL [GROUP,USER] Not a quote or apostrophe in sight. You could have entered: $ VAL = F$FILE("''FILE'","''TYPE'") as well. In a command procedure with SET VERIFY turned on, the line would appear as $ VAL = F$FILE("LOGIN.COM","UIC") as the procedure executed. This is okay for debugging purposes, but for the sake of efficiency and proper coding technique, you should eliminate the excess baggage in the final version of the file. AN EXTREME EXAMPLE: TTT.COM (Program 1) is a DCL version of the game Tic-Tac-Toe. It's also an example of DCL code pared down to an absolute minimum. Command names have been shortened as much as possible, symbol and label names have been kept to minimal size and comments are practically non-existant. The original source for this game is about twice as large; this is the "production" version, stripped down for speed. Note there are very few quotes or apostrophes in the file; the only places where they're used are in symbol definitions and as the prompting text for the INQUIRE command, which does not accept symbols. I wrote this command file to prove to a UNIX afficiando that DCL can be as unreadable as a UNIX shell script, and also as an example of nontraditional uses of DCL for my "DCL Diversions" session at the recent DECUS symposium in Atlanta. $! TTT_DCL -- See info at end of file. $ GOT END $B: $ T := WR SYS$OUTPUT $ O = "O" $ O1 = ".OO" $ O2 = "O.O" $ O3 = "OO." $ P = "." $ Q1 = "Your play..." $ Q2 = "> " $ Q3 = "N" $ Q4 = "Q" $ Q5 = "Congratulations! You win!" $ Q6 = "Play again? " $ Q7 = "Sorry, I win." $ Q8 = "Tie game." $ Q9 = "Illegal move. Try again." $ Q0 = "Thanks for playing." $ QA = "Beginning new game..." $ S = " " $ WP = "XXX" $ X = "X" $ X1 = ".XX" $ X2 = "X.X" $ X3 = "XX." $ Z = "" $ GOS V $! Initialization $IN: $ P1 = P $ P2 = P $ P3 = P $ P4 = P $ P5 = P $ P6 = P $ P7 = P $ P8 = P $ P9 = P $ T QA $! $! $N: $ T Q1 $ INQ/NOP M "''Q2'" $ IF M .EQS. Z .OR. - F$LE(M) .GT. 1 THEN GOT E $ IF M .EQS. Q3 THEN GOT IN $ IF M .EQS. Q4 THEN GOT Q $ IF F$IN(M) .EQ. 0 THEN GOT E $ IF P'M' .NES. P THEN GOT E $ P'M' = X $ GOS BB $ IF F$LOC(P,BD) .EQ. 9 - THEN GOT TIE $ GOS DB $ GOS CW $ IF W THEN GOT HW $! Grab center square, if available. $ IF P5 .NES. P THEN GOT W $ P5 = O $ GOS BB $ GOS DB $ GOT N $W: $ GOS DW $ GOS WB $ IF MV THEN GOT N $ GOS GC $ GOS BB $ GOS DB $ GOT N $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $! SUBROUTINES ! $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $BB: $ BD = P1+P2+P3+P4+P5+P6+P7+P8+P9 $ RET $! $! Display the board: $DB: $ T Z $ T S+P1+S+P2+S+P3 $ T S+P4+S+P5+S+P6 $ T S+P7+S+P8+S+P9 $ T Z $ RET $! $! Is move a winner? $CW: $ W = 0 $! Check horizontally: $ IF P1+P2+P3 .EQS. WP THEN W=1 $ IF P4+P5+P6 .EQS. WP THEN W=1 $ IF P7+P8+P9 .EQS. WP THEN W=1 $ IF W THEN RET $! Check vertically: $ IF P1+P4+P7 .EQS. WP THEN W=1 $ IF P2+P5+P8 .EQS. WP THEN W=1 $ IF P3+P6+P9 .EQS. WP THEN W=1 $ IF W THEN RET $! Check diagonally: $ IF P1+P5+P9 .EQS. WP THEN W=1 $ IF P3+P5+P7 .EQS. WP THEN W=1 $ RET $! $WB: $ MV = 0 $ OB = BD $ R = P1+P2+P3 $ IF R .EQS. X1 THEN P1 = O $ IF R .EQS. X2 THEN P2 = O $ IF R .EQS. X3 THEN P3 = O $ IF R .NES. P1+P2+P3 THEN GOT BN $ R = P4+P5+P6 $ IF R .EQS. X1 THEN P4 = O $ IF R .EQS. X2 THEN P5 = O $ IF R .EQS. X3 THEN P6 = O $ IF R .NES. P4+P5+P6 THEN GOT BN $ R = P7+P8+P9 $ IF R .EQS. X1 THEN P7 = O $ IF R .EQS. X2 THEN P8 = O $ IF R .EQS. X3 THEN P9 = O $ IF R .NES. P7+P8+P9 THEN GOT BN $ R = P1+P4+P7 $ IF R .EQS. X1 THEN P1 = O $ IF R .EQS. X2 THEN P4 = O $ IF R .EQS. X3 THEN P7 = O $ IF R .NES. P1+P4+P7 THEN GOT BN $ R = P2+P5+P8 $ IF R .EQS. X1 THEN P2 = O $ IF R .EQS. X2 THEN P5 = O $ IF R .EQS. X3 THEN P8 = O $ IF R .NES. P2+P5+P8 THEN GOT BN $ R = P3+P6+P9 $ IF R .EQS. X1 THEN P3 = O $ IF R .EQS. X2 THEN P6 = O $ IF R .EQS. X3 THEN P9 = O $ IF R .NES. P3+P6+P9 THEN GOT BN $ R = P1+P5+P9 $ IF R .EQS. X1 THEN P1 = O $ IF R .EQS. X2 THEN P5 = O $ IF R .EQS. X3 THEN P9 = O $ IF R .NES. P1+P5+P9 THEN GOT BN $ R = P3+P5+P7 $ IF R .EQS. X1 THEN P3 = O $ IF R .EQS. X2 THEN P5 = O $ IF R .EQS. X3 THEN P7 = O $ IF R .NES. P3+P5+P7 THEN GOT BN $ RET $BN: $ MV = 1 $ GOS BB $ GOS DB $ RET $! $ DW: $ MV = 0 $ OB = BD $ R = P1+P2+P3 $ IF R .EQS. O1 THEN P1 = O $ IF R .EQS. O2 THEN P2 = O $ IF R .EQS. O3 THEN P3 = O $ IF R .NES. P1+P2+P3 THEN GOT WD $ R = P4+P5+P6 $ IF R .EQS. O1 THEN P4 = O $ IF R .EQS. O2 THEN P5 = O $ IF R .EQS. O3 THEN P6 = O $ IF R .NES. P4+P5+P6 THEN GOT WD $ R = P7+P8+P9 $ IF R .EQS. O1 THEN P7 = O $ IF R .EQS. O2 THEN P8 = O $ IF R .EQS. O3 THEN P9 = O $ IF R .NES. P7+P8+P9 THEN GOT WD $ R = P1+P4+P7 $ IF R .EQS. O1 THEN P1 = O $ IF R .EQS. O2 THEN P4 = O $ IF R .EQS. O3 THEN P7 = O $ IF R .NES. P1+P4+P7 THEN GOT WD $ R = P2+P5+P8 $ IF R .EQS. O1 THEN P2 = O $ IF R .EQS. O2 THEN P5 = O $ IF R .EQS. O3 THEN P8 = O $ IF R .NES. P2+P5+P8 THEN GOT WD $ R = P3+P6+P9 $ IF R .EQS. O1 THEN P3 = O $ IF R .EQS. O2 THEN P6 = O $ IF R .EQS. O3 THEN P9 = O $ IF R .NES. P3+P6+P9 THEN GOT WD $ R = P1+P5+P9 $ IF R .EQS. O1 THEN P1 = O $ IF R .EQS. O2 THEN P5 = O $ IF R .EQS. O3 THEN P9 = O $ IF R .NES. P1+P5+P9 THEN GOT WD $ R = P3+P5+P7 $ IF R .EQS. O1 THEN P3 = O $ IF R .EQS. O2 THEN P5 = O $ IF R .EQS. O3 THEN P7 = O $ IF R .NES. P3+P5+P7 THEN GOT WD $ RET $WD: $ MV = 1 $ GOS BB $ GOS DB $ GOT WC $! $GC: $ IF P1 .NES. P THEN GOT G3 $ P1 = O $ RET $G3: $ IF P3 .NES. P THEN GOT G7 $ P3 = O $ RET $G7: $ IF P7 .NES. P THEN GOT G9 $ P7 = O $ RET $G9: $ IF P9 .NES. P THEN RET $ P9 = O $ RET $! $ V: $ TY SYS$INPUT: This command procedure plays Tic-Tac-Toe. Your mark is X and you will play first. The board is numbered as follows: 1 2 3 4 5 6 7 8 9 When it is your turn to play, enter the number of the square you wish to mark. For example, if you type "5", the result is: . . . . X . . . . You may start a new game by typing N or quit by typing Q. $ RET $HW: $ GOS DB $ T Q5 $ INQ/NOP A "''Q6" $ IF A THEN GOT IN $ GOT Q $! $WC: $ T Q7 $ INQ/NOP A "''Q6'" $ IF A THEN GOT IN $ GOT Q $! $TIE: $ GOS DB $ T Q8 $ INQ/NOP A "''Q6'" $ IF A THEN GOT IN $ GOT Q $! $E: $ T Q9 $ GOT N $! $Q: $ T Q0 $ EXI $END: $ GOT B $! TTT_DCL $! DCL version of Tic-Tac-Toe $! Loosely based on algorithms contained $! in the book "String and List $! Processing in SNOBOL" by $! Ralph E. Griswold and the SNOBOL4+ code $! developed and copyrighted by Mark Emmer $! of Catspaw, Inc. $! $! Copyright (C) 1999 by $! Kevin G. Barkes $! 1512 Annette Ave $! Library, PA 15129 $! 412-854-2550 (Voice) $! 412-854-4707 (Facsimile) $! All rights reserved. No restriction on $! non-commercial distribution. This $! software is guaranteed to suck up cpu $! time. No other warranties are made or $! implied. ********************* 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.