PCL exec 1.0 INTRO The Programmable Command Language which is now running as the system exec allows you to define your own commands. This document explains how to do that. We would like as many people as possible to experiment, so we can get a good idea regarding what changes and enhancements are desirable. The customizing features were implemented at Carnegie Mellon University. Please note that none of the customizing features have been committed yet, so they may go away in the future. This document provides an example in order to get people started. 2.0 SIMPLIFIED OVERVIEW To define your own command, you create a file with file type .PCL, in which you specify the name of the command being defined, and also in which you specify exactly what input the command should accept, and what the command is supposed to do. Then, you issue the command @DECLARE PCL-ROUTINES file.PCL to tell the exec the filename in which you have defined the new command. The DECLARE command causes the exec to read the specified file and define the commands specified within as commands available to your job as real commands. 3.0 EXAMPLE Suppose you would like to be able to type @BYE (FOR NOW) and have it log you out. You can do this by making a file which we will call TEST.PCL, in which you define how the BYE command should work. Here's the contents of TEST.PCL that will successfully define this command: Page 2 COMMAND BYE; BEGIN GUIDE "FOR NOW"; PARSE EOL; DISPLAY " See you later! "; DOCOMMAND "LOGOUT"; END; To tell the exec to define the BYE command using this file, you say @DECLARE PCL-ROUTINES TEST.PCL After this, the BYE command is available to you. This definition specifies the following attributes of the command: 1) It's called BYE. 2) If ESCAPE is typed, "(FOR NOW)" will be displayed. 3) The message "See you later!" is displayed before you are logged out. 4.0 EXPLANATION OF THE FILE CONTENTS The first line that says COMMAND BYE; specifies that the command being defined is called BYE. The semicolon is required after every statement in the definition file. Carriage returns in the file are used merely for your own personal formatting preference. It's the semicolons that really denote where the end of a statement is. The COMMAND statement must be the first statement. The second line saying BEGIN is needed to begin the command definition. The line with GUIDE specifies what the guidewords should be. The commands DOCOMMAND "text" cause the specified text to be issued as exec commands. Page 3 5.0 MORE INVOLVED EXAMPLE Here's another example. This example defines a MEMO command, allowing me to say things like @MEMO FOO which causes the file FOO.TXT to be sent through the RTRANS program, which produces FOO.RNO. Then MEMO continues by running DSR to process FOO.RNO and produce FOO.MEM. Page 4 The MEMO command becomes available to me when I say @DECLARE PCL-ROUTINES MEMDEF where the file MEMDEF.PCL contains the following contents: COMMAND MEMO; BEGIN EXTERNAL PROCEDURE FILNAM; STRING RESULT,FNAME,NAME; GUIDE "FILE"; PARSE FILE ( INPUT, HELP "File to be sent through RTRANS and DSR", DEFAULT_EXT "TXT"); LET NAME = $FILEL; CALL FILNAM($FILES,FNAME); INVOKE "SYS:RTRANS"; GETTYPEOUT RESULT; DISPLAY NORETURN RESULT; TYPEIN NAME; DISPLAY NAME; TYPEIN ""; GETTYPEOUT RESULT; DISPLAY RESULT; LET FNAME = "DSR " + FNAME + "=" + FNAME; DISPLAY "@" + FNAME; DOCOMMAND FNAME; END; PROCEDURE FILNAM (STRING SNAME,THENAM); BEGIN EXTERNAL PROCEDURE RITCHR; INTEGER SLENTH,NAMLEN,POS; STRING DOT; LET DOT = "."; CALL RITCHR (SNAME,DOT,POS); LET SLENTH = $LENGTH (SNAME); IF POS = 0 THEN LET POS = SLENTH + 1; LET NAMLEN = POS - 1; LET THENAM = SNAME[1:NAMLEN]; END; PROCEDURE RITCHR (STRING BASE,CHAR; INTEGER RANK); BEGIN INTEGER IDX,BASLEN,WHERE; STRING SUB; LET BASLEN = $LENGTH (BASE); LET IDX = 1; LET WHERE = 0; LOOP: LET SUB = BASE[IDX:1]; IF CHAR EQL SUB THEN BEGIN LET WHERE = IDX; LET IDX = BASLEN; END; Page 5 LET IDX = IDX + 1; IF IDX LEQ BASLEN THEN GOTO LOOP; LET RANK = WHERE; END; The RITCHR routine shows the use of labels, as in LOOP: It also illustrates the use of an inner BEGIN / END block. The line saying IF CHAR EQL SUB THEN BEGIN causes the variable WHERE to be assigned the value of IDX, and for IDX to be assigned the value of BASLEN, but both of these assignments are only made if the string in CHAR equals the string in SUB. Here's a demonstration. In this demonstration, I use the file MEMDEF.PCL to define the MEMO command. Then I type out the WHAT.TXT file that I intend to process with the MEMO command. Finally, I use the MEMO command to produce the WHAT.MEM file, which I then type out: .literal TOPS-20 Command processor 5(607) @declare pcl-routines memdef.pcl [Command MEMO defined] [Procedure FILNAM defined] [Procedure RITCHR defined] @type what.txt Demonstration of Pickle This file is a text file intended to be put through RTRANS and DSR to produce a .MEM file. It has absolutely no other purpose. This is the second paragraph. It says absolutely nothing. It is merely here so that RTRANS's capabilities can be demonstrated. @memo what.txt RTRANS V7(20) INPUT FILE NAME? OUTPUT FILE NAME? Done! EXIT *No errors detected by version 1(115) of RUNOFF 1 page written to DSK:WHAT.MEM ** @type what.mem Demonstration of Pickle Page 6 This file is a text file intended to be put through RTRANS and DSR to produce a .MEM file. It has absolutely no other purpose. This is the second paragraph. It says absolutely nothing. It is merely here so that RTRANS's capabilities can be demonstrated. 6.0 GETTING MORE INFORMATION The file SYS:PCL.DOC is the documentation file supplied by CMU. It tells all the possible statements that can appear in a definition file. This file is rather cryptic, but not impossible to understand. By understanding one or two examples, and seeing how the PCL.DOC file defines the parts you understand, you can often then figure out how other parts work. Hopefully, CMU will give us better documentation soon, at which point it will be made available. Please use MS or GRUMP to report any problems. If you have questions you can mail to me. Have fun! --Eric .