From: CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 31-AUG-1990 01:00:01.24 To: MRGATE::"ARISIA::EVERHART" CC: Subj: Re: .COM files Received: by crdgw1.ge.com (5.57/GE 1.70) id AA10155; Fri, 31 Aug 90 00:44:43 EDT Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Thu, 30 AUG 90 18:21:54 PDT Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA28172; Thu, 30 Aug 90 18:10:30 -0700 Received: from USENET by ucbvax.Berkeley.EDU with netnews for info-vax@kl.sri.com (info-vax@kl.sri.com) (contact usenet@ucbvax.Berkeley.EDU if you have questions) Date: 31 Aug 90 01:06:54 GMT From: agate!agate!jym@ucbvax.Berkeley.EDU (Jym Dyer) Organization: Berserkeley Subject: Re: .COM files Message-Id: References: <9008291828.AA04689@fngate.fnal.gov> Sender: info-vax-request@kl.sri.com To: info-vax@kl.sri.com > VAX/VMS: Writing Real Programs in DCL > by Paul C. Anagnostopoulos .-. |P|aul wrote VMSINSTAL (or, at least, early versions of it), so he `-' should know what he's talking about. Of course VMSINSTAL is no program for beginners, but presumably the book doesn't hop right into that much complexity (I haven't read it). .-. |P|aul was a great influence on me in my first days as a DECcie. `-' I'd just come out of a micro environment, where every byte counts, and my code was very compact-looking. .-. |H|e walked up to my terminal, told me I needed more whitespace, `-' and put a few random lines in my code. And I must admit, it looked better that way! * * * .-. |B|ut back to DCL. It's a pretty interesting interpreter, once `-' you get the hang of it. I can offer a few hints: o Always establish an exit handler, which in DCL means having everything exit from the same point. I usually start things off with this: $ verify_context = 'f$verify(0); $ status = %x10000001 ! SS$_NORMAL $ on control_y then goto ADIOS $ on error then goto ADIOS My exit handler looks like this: $ADIOS: $ exit (status + (0 * f$verify(1))) The `status' variable is usually set to an appropriate value, usually `$status' ORed with %x1000000. FUN HINT: If your program changes directory default, or anything else along those lines, you can save the originals in variables like `path_context' or `privilege_context' and set them back in the exit handler. o It's easier to implement Unix-style command "options" (preceded with a "-" character) than VMS-style command qualifiers (preceded with a "/" character), in part because the "@" command takes qualifiers itself. FUN HINT: Swiping an idea from another operating system, TOPS-20, I often allow the user to enter a "?" character as an argument. Then I have the program respond with a terse description of the expected values, a menu of keywords, etc. It's easy to do in a command procedure, it makes it very friendly, and it helps document the code. o I'm also a fan of Unix-style message prefixes, instead of trying to fake a VMS-style message prefix and sending the poor user off to the Error Message Dictionary (I've seen this happen). Of course, they're easy to implement: $ msg = "write sys$error ""prefix: "" +" Here's a good example of it in action: $ status = $status .or. %x10000000 $ msg "Can't open the kaputnik file:" $ msg f$message(status) $ msg " \''p1'\" You can also display status messages by hand, just make sure you document them: $ status = %x10038090 $ msg f$message(status) ! CLI$_IVVERB $ msg " \''keyword'\" FUN HINT: If you have a family of command procedures that work together, you can make your `msg' command keep track of the depth of command procedures: $ msg = "write sys$error " + - f$fao("!''f$environment("depth")'**") + ""prefix: "" +" o Put program-wide comments at the end of the program instead of at the beginning. It'll run faster that way. o If a DCL command has a /NOLOG, you probably want to use it. VMS success messages look enough like error messages to scare users, and getting (for example) a bunch of DELETE messages in the middle of a command procedure can confuse folks. Unless, of course, they're expected to know that files are being deleted. o Know your lexicals. There should be an exercise set for each lexical so that people can learn how to use them. Lexicals make DCL very powerful. o Get used to dealing with SYS$INPUT coming from the command procedure. This gets pretty handy. For example, you can use TYPE SYS$INPUT to display a lot of text. I recommend always using DECK/EOD pairs to improve readability. FUN HINT: Do you have programs that are often called from command procedures? How about writing them to parse symbols in their input streams? Look at this example: $ run my_utility $ deck args = "'p1' 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'" status = '$status' $ eod This looks like illegal DCL, but it's really a matter of MY_UTILITY parsing in a DCL-like fashion (with calls to lib$get_symbol() and such). You might want to use a different convention to avoid confusion: $ 'my_lisp' -init sys$input: -input sys$command: $ deck (setq args (list $p1 $p2 $p3 $p4 $p5 $p6 $p7 $p8)) (setq status ($$status) $ eod o Even though GOSUBs and CALLs now exist, I still find it handy to use callbacks. If you're doing anything with processes, they're a handy way to send DCL commands to them. For example, if I've got a command procedure with and embedded MMS description file, I can feed that file a command that calls the command procedure to handle something that MMS can't: $ lispit = "@''f$environment("procedure")' callback___lispit" $ msg = "write sys$error ""prefix: "" +" $! $ if (p1 .nes. "CALLBACK___LISPIT") $ then $ mms/descrip=sys$input: 'p1' $ deck stuff : one two msg "[One and Two Made]" one : lispit "one" msg "[One Made]" two : lispit "two" msg "[Two Made]" $ eod $ else $ mcr lisp $ deck (mung-it-all '$p2) $ eod $ endif o Read the _Guide_to_Making_Modular_Procedures_. It gives good hints on VMS programming styles and conventions, and your variable names, logical names, etc., would do well to follow them. For example, logical names that outlive the command procedure should have a PREFIX_ prefix (using perhaps the same prefix as your `msg' command symbol). Stuff that nobody should toy with should have a PREFIX___ prefix. (Note that the "callback___lispit" keyword worked like that.) <_Jym_>