Presentation is loading. Please wait.

Presentation is loading. Please wait.

Writing better DCL procedures A simple guide by Andy Park

Similar presentations


Presentation on theme: "Writing better DCL procedures A simple guide by Andy Park"— Presentation transcript:

1 Writing better DCL procedures A simple guide by Andy Park Http://home.online.nl/andy.park

2 Andy Park Graduate of Loughborough University. Designed and built HW and SW. Industrial, office, business automation. PDP8, PDP11, VAX, Alpha.

3 Objectives Improve the quality of your coding. Make life easier for yourself. Make life easier for your successors. Learn some of the basics of DCL. Learn some of the less well known parts of DCL.

4 Introduction Creating command procedures is easy. The ones with a future are a bit more difficult. Creating a template. Making procedures flexible. Tips/Tricks with DCL.

5 Does this look familiar? $ on error then goto help $… $ help: $! If my procedure goes wrong then $! only xxx can help you. $ write sys$output “Sorry no help available” $ exit ! If you can

6 The three liner! We’ve all made them! The quick three liner. Then someone else adds a bit. And then someone else adds a bit more. Before you know it you have: “undocumented spaghetti”.

7 Where to start Make a template. Use it as the basis for each procedure.

8 Contents of template Beginning. Middle. End. Not too boring I hope!

9 Beginning of template Information about the procedure. Save the current process environment. Set standard symbols. Check usage restriction (enough privileges).

10 Information about the procedure Copyright Author Date Procedure Name Description Parameters Called by Calls Submits Changes

11 Example $! $!Copyright: "(c) 2003 Andy Park" $! $!Author: Andy Park $!Date: $!Procedure name: TEMPLATE.COM $! $!Description: $! $!Parameters: P1 = $! $!Called by: $! $!Calls: $! $!Submits: $! $! Changes:

12 Save environment Current verify status. Current default directory. Current message settings. Current privileges.

13 Example $VERIFY = 'F$VERIFY(0)' $SET NOON $IF 0'_DEBUG'.GT. F$ENVIRONMENT("DEPTH") THEN SET VERIFY $GOTO SETUP $! Procedure information described previously $ SETUP: $SAVE_DEFAULT = F$ENVIRONMENT("DEFAULT") $SAVE_MESSAGE = F$ENVIRONMENT("MESSAGE") $REQUIRED_PRIVILEGES = "NETMBX,TMPMBX" $SAVE_PRIVILEGES = F$SETPRV(REQUIRED_PRIVILEGES) $

14 Set standard symbols Node name. Procedure name. SAY. Base directory (where the procedure is).

15 Example $IF F$TYPE(SAY).EQS. "" THEN SAY := WRITE SYS$OUTPUT $IF F$TYPE(SAYLOG).EQS. "" THEN SAYLOG := IF - F$TRNLNM("""LOG_FILE""").NES. """""" THEN WRITE LOG_FILE $NODENAME = F$GETSYI("NODENAME") $PROCEDURE = F$ENVIRONMENT("PROCEDURE") - "][" $BASE_DIRECTORY = F$ELEMENT(0,"]",PROCEDURE) + "]"

16 Check usage requirements Does the user have the required privileges. Is the procedure running in the correct mode.

17 Example $STATUS = %X24 ! Insufficient privileges $IF.NOT. F$PRIVILEGE(REQUIRED_PRIVILEGES) THEN GOTO DONE $STATUS = %X10000001

18 Middle of procedure Set up working environment. Placeholder for “check parameters”. Placeholder for “the real code!”.

19 Set up working environment Set default to location of procedure. Optionally create log file. Optionally set prefix. Optionally set verify on.

20 Example $!---------------------------------------------------------- $! $ BEGIN: $! $!!!LOG_FILE = F$PARSE("[.LOG].LOG",PROCEDURE) $!!!CLOSE/NOLOG LOG_FILE $!!!OPEN/WRITE/ERROR=ERROR LOG_FILE 'LOG_FILE' $!!!SAYLOG "Log file created at ''F$TIME()'" $!!!SAYLOG "Processing beginning on node ''NODENAME'" $!!!SAYLOG "Executing ''PROCEDURE'" $SET DEFAULT 'BASE_DIRECTORY' $SAY "Executing ''PROCEDURE'" $! $ IF F$MODE().EQS. "BATCH" THEN SET VERIFY $ SET PREFIX "''F$TRNLNM("NODE_HAS_PREFIX",,1)'" $

21 Placeholders Note to check that all the required information is available. Note that this is where the real code is to be added.

22 End of procedure Placeholder for error handling code. General tidy up. Restore process environment.

23 Placeholders General errors. File open/close errors. File read/write errors. Ensure error status set.

24 Example $! $!-------------------------------------------------------- $! $ ERROR: $STATUS = $STATUS $IF STATUS.EQ. 1 THEN STATUS = 0 $GOTO DONE $!

25 Tidy up Make sure log files are closed. Make sure any other files are closed. Delete any temporary files.

26 Restore environment Restore privileges. Restore message settings. Restore default directory. Restore verify.

27 Example $! $!----------------------------------------------------------- $! $ DONE: $SAY "Exiting ''PROCEDURE'" $!!!SAYLOG "Exiting ''PROCEDURE'" $!!!CLOSE/NOLOG LOG_FILE $CLOSE/NOLOG TMP_FILE $IF F$SEARCH(TMP_FILE).NES. "" THEN DELETE 'TMP_FILE';* $SET MESSAGE 'SAVE_MESSAGE' $SET DEFAULT 'SAVE_DEFAULT' $PRIV = F$SETPRV(SAVE_PRIVILEGES) $EXIT STATUS + 0*F$VERIFY('VERIFY')

28 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.

29 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.

30 Parameters Always check that they are all present and correct. If the procedure is running interactively you can ask for missing information.

31 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")

32 Logical names You can put a lot of information in one logical name. You can easily get at it.

33 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 $!

34 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...

35 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.

36 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 $

37 Extracting data from line You have just read a line of data. Make use of lexical functions to get at data.

38 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)

39 Putting data in file Format output for easier reading.

40 Example $ FORMAT_STRING = ”!10AS !20AS !10AS” $ CLOSE/NOLOG MY_REPORT $ OPEN/WRITE/ERROR=ERROR MY_REPORT [.REPORT]MY_REPORT.TXT $ REPORT = WRITE MY_REPORT $ OUT_LINE = - F$FAO(FORMAT_STRING,”Title 1”,”Title 2”,”Title 3”) $ REPORT OUT_LINE $ LOOP: $! Get data $IF NO_MORE_DATA THEN GOTO END_LOOP $OUT_LINE = F$FAO(FORMAT_STRING,DATA_1,DATA_2,DATA_3) $ REPORT OUT_LINE $GOTO LOOP $ END_LOOP: $ CLOSE/NOLOG MY_REPORT

41 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.

42 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

43 Summary flexible procedures Separate code and data. Code in command procedures. Data elsewhere: –Files in subdirectories. –Logical names.

44 Tips/Tricks with DCL PIPE commands. Strings. Other useful lexical functions.

45 Avoid temporary files Big overhead creating/deleting temporary files. Easily avoided. Use PIPE command.

46 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 ”user@address”/SUBJECT=”Problem to solve”

47 Example, SYSMAN $ SYSMAN := $SYSMAN $ COMMAND1 = ”DO SHOW SYSTEM/NOPROCESS” $ COMMAND2 = ”DO SHOW MEMORY” $ PIPE (SAY COMMAND1 ; SAY COMMAND2 ) | - SYSMAN SET ENVIRONMENT/CLUSTER

48 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’”

49 Recursive example $ IF F$TRNLNM(”SYS$PIPE”).NES. ”” THEN GOTO PIPE_SUB $! $ PIPE/NOLOGICAL UAF SHOW/FULL * | @’PROCEDURE’ 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

50 Manipulating strings Just a few hints.

51 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

52 Overwriting a part of a string $ TEMPLATE = “User is active” $ X = TEMPLATE $ USER = “SYSTEM” $ X[6,10] := ‘USER’

53 F$PARSE $ FILESPEC = F$PARSE(”FILE.EXT”,”DISK:[DIR.DIR1.DIR2];0”) $ FILENAME = F$PARSE(FILESPEC,,,”NAME”) $ FILEDIR = F$PARSE(FILESPEC,,,”DIRECTORY”)

54 F$SEARCH $ NEWEST = F$SEARCH(”FILE.EXE;0”) $ OLDEST = F$SEARCH(”FILE.EXT;-0”) $ EMPTY = F$SERCH(”NO.FILE”)

55 Substitution Difference between ’x’ and &x. –’x’ substitution before execution. –&x substitution during command execution. – Example: $ XP1 := TEST.DAT;1 $ XP2 := TEST.DAT;2 $ N = 2 $ DELETE &XP’N’ ! Delete test.dat;2

56 CALL verses GOSUB $ CALL label parameters. –Own local symbols. –Parameters. –Higher “depth”. –Leave with EXIT (or ENDSUBROUTINE). –$ label: SUBROUTINE –$ ENDSUBROUTINE

57 CALL verses GOSUB $ GOSUB label –Uses current local symbols. –No parameters. –Same depth. –Leave with RETURN. –$ label: code –$ RETURN

58 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).

59 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.

60 Summary of tips/tricks with DCL. Read up on: –The PIPE command. –Strings. –F$PARSE. –F$SEARCH. –GOSUB and CALL

61 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.

62 Thanks for listening! Any Questions? Http://home.online.nl/andy.park


Download ppt "Writing better DCL procedures A simple guide by Andy Park"

Similar presentations


Ads by Google