Summary of Template Make one.Use it. Helps standardize your code: –Makes life easier for yourself. Makes the code easier to read: –Makes life easier for your successors. Improves the quality of your coding.
Making you procedures flexible Avoid “data” in the procedure. Use: –Parameters –Logical names –Data in files Use relative directory specifications. Put log, data, temp files in subdirectory.
Parameters Always check that they are all present and correct. If the procedure is running interactively you can ask for missing information.
Example $! $! P1 should contain the name of an existing disk, if not ask for it... $! $DISK = P1! Assume P1 specified $ GET_DISK: $IF (DISK.EQS. "") ! Was P1 specified? $THEN ! P1 was not specified $SAY "(Valid) disk not yet specified" $IF (F$MODE().NES. "INTERACTIVE") THEN GOTO ERROR $READ /PROMPT="Please specify name of disk: " - /ERROR=ERROR/END=DONE SYS$COMMAND DISK $GOTO GET_DISK $ENDIF $IF.NOT. F$GETDVI(DISK,"EXISTS") $THEN $SAY "Disk ''DISK' does not exist, please re-enter" $DISK = "" $GOTO GET_DISK $ENDIF $DISK = F$GETDVI(DISK, "FULLDEVNAM")
Logical names You can put a lot of information in one logical name. You can easily get at it.
Example part 1 $! $! Sometime during system startup register information about disks. $! $! In this case, disk 3 is physical disk $1$DGA3. $! It has the volume label DISK03. $! It has the logical name DISK03. $! It is for users (as opposed to databases, applications etc.) $! It will be backed up in backup stream 1. $! It should be defragmented. $! During disk check, purge, rebuild and repair the disk. $! Warn the data manager if the disk has less than 10% free. $! $ ASSIGN/TABLE=xxx/EXECUTIVE "$1$DGA3","DISK03","DISK03","USER","BACKUP_1", - "DEFRAG","PURGE,REBUILD,REPAIR","10%" NODE_HAS_DISK_3 $!
Example part 2 $! $! Somewhere in a disk check procedure. $! $COUNT = 3 $DEVICE = F$TRNLNM(”NODE_HAS_DISK_’’COUNT’”,,0) $VOLUME = F$TRNLNM(”NODE_HAS_DISK_’’COUNT’”,,1) $USAGE = F$TRNLNM(”NODE_HAS_DISK_’’COUNT’”,,3) $OPTIONS = F$TRNLNM(”NODE_HAS_DISK_’’COUNT’”,,6) $MIN_FREE = F$TRNLNM(”NODE_HAS_DISK_’’COUNT’”,,7) $! $IF (OPTIONS - ”REBUILD”).NES. OPTIONS THEN - SET VOLUME/REBUILD ’VOLUME’ $ IF (OPTIONS - ”REPAIR”).NES. OPTIONS THEN - ANALYZE/DISK/REPAIR ’DEVICE’ $! Etc...
Data in files Always close (sequential) files before opening them. Have you tried using indexed files? –It not so difficult. Keep files in subdirectories. –Use relative directory specifications.
Example $! Put the file name into a symbol, you then only need to change one line $! when someone decides the file must have another name. $DATA_FILE = F$SEARCH(”[.DAT]DATA_FILE_1.DAT”) - ”][” $! $! When a procedure crashes, or is killed (ctrl-C), files remain open. $! Note OPEN does not complain if the file was already open. $! You just continue from where you left off in the middle of the file. $! So always close the file just in case the file was open. $CLOSE/NOLOG DATA_FILE $! $! I always use the same name for the logical pointing to the file $! and the symbol containing the file name. $! Some people have a problem with this. Use what best for you. $OPEN/READ/ERROR=OPEN_ERROR DATA_FILE ’DATA_FILE’ $! $! /ERROR and /END should be compulsory $READ/ERROR=READ_ERROR/END=DONE_FILE DATA_FILE LINE_OF_INFO $
Extracting data from line You have just read a line of data. Make use of lexical functions to get at data.
Example $! Get data into standard format. $ LINE_OF_DATA = - F$EDIT(LINE_OF_DATA,”UNCOMMENT,COMPRESS,TRIM,UPCASE”) $! Skip lines meant purely for comment. $ IF LINE_OF_DATA.EQS. ”” THEN GOTO IGNORE_COMMENT_LINES $! Split the data into meaningful pieces. $ DATA_0 = F$ELEMENT(0,” ”,LINE_OF_DATA) $ DATA_1 = F$ELEMENT(1,” ”,LINE_OF_DATA) $ DATA_2 = F$ELEMENT(2,” ”,LINE_OF_DATA) $! Make sure its all there $ IF (DATA_1.EQS. ” ”).OR. - (DATA_2.EQS. ” ”) THEN GOTO MISSING_DATA $! $ BEGIN_DATA_2 = F$EXTRACT(0,3,DATA_2) $ REST_DATA_2 = F$EXTRACT(3,-1,DATA_2)
Putting data in file Format output for easier reading.
Indexed files Just another file but: You can add a single record. You can modify/overwrite a record. You can delete a record. Files can be shared.
Example $! Clean out old users from mail profile file $ EX_USER = ”SACKED” $ OPEN/READ/WRITE/SHARE=WRITE/ERROR=ERROR MAIL_PROFILE - SYS$SYSTEM:VMSMAIL_PROFILE.DATA $ READ/DELETE/ERROR=ERROR/KEY=”’’EX_USER’” MAIL_PROFILE LINE $ CLOSE/NOLOG MAIL_PROFILE
Summary flexible procedures Separate code and data. Code in command procedures. Data elsewhere: –Files in subdirectories. –Logical names.
Tips/Tricks with DCL PIPE commands. Strings. Other useful lexical functions.
Avoid temporary files Big overhead creating/deleting temporary files. Easily avoided. Use PIPE command.
Example, send MAIL $ LINE1 = ”This message was created on ’’F$CVTIME()’” $ LINE2 = ”It is sent from ’’NODENAME’” $ LINE3 = ”Problem detected in ’’PROCEDURE’” $ PIPE (SAY LINE1 ; SAY LINE2 ; SAY LINE3) | - MAIL SYS$PIPE to solve”
Example, SYSMAN $ SYSMAN := $SYSMAN $ COMMAND1 = ”DO SHOW SYSTEM/NOPROCESS” $ COMMAND2 = ”DO SHOW MEMORY” $ PIPE (SAY COMMAND1 ; SAY COMMAND2 ) | - SYSMAN SET ENVIRONMENT/CLUSTER
Example SEARCH $ UAF := $AUTHORIZE $ USER := SYSTEM $ PIPE UAF SHOW ’USER’ | SEARCH SYS$PIPE login: | - (READ SYS$PIPE LINE ; ASSIGN/JOB &LINE LINE ) $ LINE = F$TRNLNM(”LINE”,”LNM$JOB”) $ DEASSIGN/JOB LINE $ SAY ”’’USER’ last login info ’’LINE’”
Recursive example $ IF F$TRNLNM(”SYS$PIPE”).NES. ”” THEN GOTO PIPE_SUB $! $ PIPE/NOLOGICAL UAF SHOW/FULL * UAF_REPORT $ PIPE_SUB: $SET NOON ! Plus save environment $ GOTO ’P1’ $ PIPE_EXIT: ! Restore environment $ EXIT $ UAF_REPORT: $! Make report, (can not access SYSUAF.DAT) $ GOTO PIPE_EXIT
Manipulating strings Just a few hints.
Examples of string manipulations $ X = ”some long string to split” $ LEN_X = F$LENGTH(X) $ MIDDLE = F$ELEMENT(2,” ”,X) $ SPLIT = F$LOCATE(MIDDLE,X) $ BEGIN = F$EXTRACT(0,SPLIT,X) $ TAIL = F$EXTRCT(SPLIT,-1,X) $ FOUND = (X - ”Look for”).NES. X
Overwriting a part of a string $ TEMPLATE = “User is active” $ X = TEMPLATE $ USER = “SYSTEM” $ X[6,10] := ‘USER’
CALL verses GOSUB $ GOSUB label –Uses current local symbols. –No parameters. –Same depth. –Leave with RETURN. –$ label: code –$ RETURN
READ SYS$COMMAND verses INQUIRE READ SYS$COMMAND –Gets text as typed. –You have control. INQUIRE –full DCL parse on typed input is done. a ’F$LEXICAL()’ will be executed. input converted to uppercase. –User has control (possible security problem).
Golden rules Always use fully written DCL verbs in procedures. –for example: always DELETE never DEL. Never make symbols the same as DCL verbs. –DEL*ET := DELETE/CONFIRM is OK. –DEL*ETE := DELETE/asking_for_trouble.
Summary of tips/tricks with DCL. Read up on: –The PIPE command. –Strings. –F$PARSE. –F$SEARCH. –GOSUB and CALL
Summary Make, and use a template for your procedures. Aim to make procedures flexible from the start. –No data in procedure. Try out the tricks. –Use the full range of DCL. –Read the book(s) sometime; It’s worth it.