home *** CD-ROM | disk | FTP | other *** search
- SUPERSUB
-
- A replacement for the CP/M SUBMIT utility
-
- Ron Fowler
- Nov. 16, 1981
- Westland, Michigan
-
-
-
-
- One of the most useful programs provided with CP/M is the
- SUBMIT utility, which allows system commands to be read from a
- disk file for automatic processing. Its command-line
- substitution facility provides a convenient means of developing
- "prototype" command files, with actual parameter substitution
- performed when the command file is invoked.
- There are, however, some shortcomings associated with
- SUBMIT that recur frequently. Frequently enough to inspire me
- to write my own batch processor, SUPERSUB, that completely
- replaces, and is fully compatible with, the standard SUBMIT
- utility.
-
- PROBLEMS WITH SUBMIT
-
- SUBMIT will produce a "garbaged" output file whenever it
- encounters an empty line in the input file. This is a real
- handicap when attempting to pass command lines to PIP.COM, for
- example, using XSUB (the CP/M2 utility that extends the SUBMIT
- capability to transient programs), since the only way to exit
- PIP is to enter an empty command line (you can enter a control-
- "C" as the first character of the line, but this is a "real-
- time" function, and cannot be done within a SUBMIT file).
- SUPERSUB generates the necessary zero-length line in the output
- file.
- Another SUBMIT drawback is the constant need to enter an
- editor and create a command file, even for the simplest of
- jobs. This added step discourages the use of SUBMIT for very
- simple "command stacking" applications. With this in mind, I
- gave SUPERSUB the ability to interactively accept command lines
- from the console. An additional option allows the entire job
- to be specified on the SUPERSUB command line.
-
- COMMAND FILE NESTING
-
- I felt that a nesting capability would be a significant
- feature to add to SUPERSUB. For example, it would be useful to
- create a submit file called COMPILE.SUB, to facilitate the
- program compilation process, and "clean up" any leftover files.
- COMPILE.SUB might look like this:
-
- BASCOM =$1 ;COMPILE PROGRAM SPECIFIED IN CMD LINE
- L80 $1,$1/N/E ;LINK THE PROGRAM
- PIP B:=$1.COM ;MOVE THE OBJECT FILE TO THE B DRIVE
- ERA $1.REL ;DELETE THE .REL FILE
- ERA $1.COM ; AND THE OBJECT FILE
-
- Now let's say I want to compile several programs at once
- (a common situation in applications programming). Under
- SUBMIT, I would have to type in a SUBMIT invocation for each
- program:
-
- A>SUBMIT COMPILE LEDGER [COMPILE.SUB executes, operator waits
- for it to complete, then types:]
- A>SUBMIT COMPILE PAYABLES [more waiting for COMPILE.SUB, then:]
- A>SUBMIT COMPILE RECVBLES [and the job is finally done.]
-
- Using SUPERSUB, I can create a file (CMPILALL.SUB)
- containing the commands
-
- SUBMIT COMPILE LEDGER
- SUBMIT COMPILE PAYABLES
- SUBMIT COMPILE RECVBLES
-
- and execute the whole thing with the single command line
-
- A>SSUB CMPILALL
-
- (Note that I've abbreviated SUPERSUB to SSUB on all my disks;
- SUPERSUB as a name is a bit grandiose anyway). I can also save
- the trouble of creating CMPILALL.SUB (especially if I want to
- do this only once) and enter the single command line
-
- A>SSUB /COMPILE LEDGER;SSUB COMPILE PAYABLES;SSUB COMPILE RECVBLES
-
- or, if the individual command lines to be executed are a bit
- long, I can specify the Interactive mode by entering only a
- slash ("/") on the command line (after the SUPERSUB
- invocation). SUPERSUB will then prompt for each command line
- with an asterisk. To continue the previous example,
-
- A>SSUB /
- *COMPILE LEDGER
- *SSUB COMPILE PAYABLES
- *SSUB COMPILE RECVBLES
- * [empty line here terminates]
-
- ON-LINE HELP FUNCTION
-
- I believe all programs of any complexity should be "self-
- instructive" by providing the user a means of typing out, on
- the terminal, the major modes of operation, and any necessary
- command line syntax. Further, the command line used to invoke
- this "help summary" should be the simplest possible form not
- otherwise used by the program. In the case of SUPERSUB, this
- is a command line with no arguments at all:
-
- A>SSUB
-
- SUBMIT.COM COMPATIBILITY
-
- SUPERSUB is fully compatible with CP/M's SUBMIT utility,
- including command parameter substitution and control-character
- translation:
-
- 1) Parameters within the "prototype" file, of the form $1,
- $2, etc., are substituted from the command line on a one-
- for-one basis. Parameters are passed through to any
- nested files. Two successive dollar-sign characters
- ("$$") may be used to introduce a single "$" into the
- output file.
-
- 2) An up-arrow symbol ("^") may precede an alphabetic
- character to insert the associated control-character into
- the output file.
-
- DETAILED INSTRUCTIONS
-
- In addition to the normal SUBMIT mode of operation and
- associated command line usage, SUPERSUB provides two additional
- modes of input: Interactive and Summary.
-
-
- SUMMARY MODE
-
- Summary mode allows the entire SUBMIT job to be specified in
- the CP/M command line. This mode is enabled by using the slash
- ("/")character as the first character of the command line. The
- individual submit lines must be seperated with a semicolon. For
- example,
-
- A>SSUB / CRCK *.* F;CRCK B:*.* F;COMPARE CRCKFILE.CRC B:
- ^
- |
- ----> (this space is optional)
-
- will create a file of CRC's of all files on A:, then create a
- similar file on B:, then compare the two. (CRCK, by Keith
- Petersen, and COMPARE, by Ward Christensen, are available from
- the CP/M Users Group).
-
- INTERACTIVE MODE
-
- You may enter the interactive entry mode by typing
- "SUPERSUB /<CR>" (ie, "SUPERSUB /" with no arguments).
- Supersub will prompt for input with an asterisk, and you may
- then enter SUBMIT lines from the keyboard. Multiple commands
- may be entered on a line by separating them with semicolons.
- An empty line terminates the input. Example:
-
- A>SUPERSUB /
- *CRCK *.* F
- *CRCK B:*.* F
- *COMPARE CRCKFILE.CRC B:
- * <empty line here>
- A>CRCK *.* F <submit file begins execution>
-
- has the same effect as the above SUMMARY mode example.
-
- HELP FUNCTION
-
- Typing SUPERSUB with no arguments will print the built-in help
- file.
-
-
-
-
-
- NOTES
-
- 1) Nested SUBMIT runs are only usable up to a maximum of 128
- nested commands at any one time. This is a limitation of
- the CP/M Console Command Processor.
-
- 2) If you change the drive specification for the output file,
- you may want to do the same thing with XSUB (Digital
- Research's function nine extender). Within XSUB, find the
- submit File Control Block (search for "$$$ SUB" within
- XSUB.COM) and change the first FCB byte (ie, the byte
- before the first "$") to:
- 0 - to use default drive
- 1 - to use drive A:
- 2 - to use drive B:
- etc.
-
- 3) In SUMMARY and INTERACTIVE modes, passed parameters have no
- meaning. When these modes are used, the parameter flag,
- "$", will be passed through literally to the output file.
-
- 4) Zero-length output lines may be created in SUMMARY and
- INTERACTIVE modes by using two consecutive semicolons. This
- is, in effect, a blank logical line.
-
- 5) Interactive mode may be aborted by typing control-C as the
- first character of a line. Also, all normal CP/M editing
- characters are available in this mode.
-
- HOW IT WORKS
-
- Those who have been following Ward Christensen's series of
- tutorials on CP/M know that the output file ($$$.SUB) consists
- of lines from the input file written in reverse order, one line
- per CP/M record. To fully understand how this file is built,
- refer to the assembly listing while reading the following
- program description.
-
- SUPERSUB can be divided into three distinct sections:
- initialization, input file read, and output file write
- ($$$.SUB). Each will be discussed, along with any called
- subroutines.
-
- PROGRAM INITIALIZATION
-
- Initialization begins with a check for a HELP request (an
- empty command line), which suppresses the sign-on message, and
- branches directly to the HELP print routine.
- If there is no help request, then the sign-on message is
- printed and the routine INITVAR is called. INITVAR zeroes the
- working variable area and initializes to empty the table which
- will later hold the address of each command-line parameter.
- Next, the routine GETPAR is called. GETPAR parses the
- input command line, setting up the variables OPTION and CLFLAG
- (which will be used later to determine the input mode), and
- calls the routine PUTPAR as each command-line parameter is
- encountered. PUTPAR stores each parameter (prefixed by its
- length) into free memory, advances the free memory pointer, and
- stores a pointer to the parameter into TABLE. This pointer
- will later be used to locate the parameter when user parameter
- substitution is done.
- Finally, the input file control block is prepared for use
- by the routine SETUP. SETUP insures that the input name
- specified is of type "SUB". If the type field is left blank,
- SETUP moves the correct type into place.
-
- READING THE INPUT FILE
-
- The RDFILE routine has the responsibility of reading in
- the user's text file. RDFILE reads each line sequentially into
- memory, prefixed by a link word that contains the absolute
- memory address of the previous line (the first line has a link
- value of zero) followed by a length byte, then the line itself
- (stripped of carriage-return/line feed characters). No
- parameter substitution is done during the file read.
- RDFILE increases the value of LINNUM with each line read.
- This variable is used by the error handlers to provide line
- number reporting when an error is encountered.
- RDFILE gets its input character-by-character by calling
- GNB, the character "GET" routine. This is the level at which
- the command-line option flags OPTION and CLFLAG must be used to
- determine the source of characters. If the OPTION variable is
- an ascii slash ("/"), then the character is retrieved from the
- GNBKBD routine. Otherwise control passes to GNB1, which
- handles disk file character input. GNB1 uses the IBP byte to
- form a pointer into TBUF, the disk buffer. If IBP is pointing
- past the buffer end, the FILL routine is called to refill TBUF.
- IBP is then incremented, and the character is returned in the
- accumulator.
- The GNBKBD routine is used when the input source is NOT a
- disk file. At this point, there are two possible sources of
- input: the original command line (Summary mode) and the console
- (Interactive mode). The flag CLFLAG is used to decide which
- source to use. If CLFLAG is non-zero, then the Summary mode is
- active, and characters are read from the original command line
- (passed by CP/M in TBUF). A CLFLAG of zero indicates
- Interactive mode, and characters are read from the keyboard
- buffer CLBUF (which is filled using CP/M function #10 whenever
- it is found empty by GNBKBD).
- The code at label GNBCL is common to both modes, and
- substitutes an end-of-line character for a semicolon, to allow
- multiple logical lines on a physical line.
- The end of file condition is returned by GNB as a 1AH in
- the accumulator. This value is normally returned only from a
- disk file, so special logic in GNBKBD must detect the end
- condition. This logic returns EOF at the end of the input
- command line (in Summary mode) or upon entry of an empty line
- (in Interactive mode).
-
- WRITING THE OUTPUT FILE
-
- You may have wondered why the input file was read in with
- link pointers and length bytes added. That's because CP/M's
- CCP (and XSUB utility) read the temporary submit file BACKWARD,
- one line packed into each disk record. This allows CP/M to use
- the record count and next record fields of the directory entry
- as file pointers. This also means that SUPERSUB must write out
- the last line first, followed by the next-to-last line, etc.,
- with the first line of the input file being at the END of the
- output file. The linked list provides a simple means of
- traversing the lines in reverse order.
- The subroutine WRSUB writes the output file, and is the
- last routine called by the mainline code. WRSUB first scans
- backward from the end of the input file, looking for the last
- line in the file that is not empty. If one is found (an error
- message is issued if one is not), control passes to the WRLOP
- loop, which calls PUTLIN to move the line to the output buffer,
- decrements the line number for possible error reporting
- (remember, we're working BACKWARD now), and scans back to the
- previous line to repeat the process. If there is no previous
- line (indicated by a link pointer with zero value), then the
- file is closed, and a warm-boot to CP/M is executed, causing
- the batch job to begin.
- The PUTLIN routine moves characters one-by-one from the
- input line stored in memory to the output buffer at TBUF. This
- is the point where parameter substitution and control-character
- translation take place (unless Summary or Interactive modes are
- active, which have no reason to do substitutions). Buffer
- pointers and counters are set up for the GETCHR and PUTCHR
- routines, after which characters are received one-at-a-time by
- calling GETCHR.
- Each character is checked to see if it is either of the
- option characters, "$" or "^". In the case of the "$"
- character, LKAHEAD is called to determine if the "$" is present
- twice successively, which is interpreted as a single "$" to
- move from input file to output file. If there is no second "$"
- character, the next character is considered to be the parameter
- number (as in "$1", "$2", etc.). The code at label SUBS
- collects the parameter number from the input stream (which may
- be more than one digit, if the conditional NPAR is greater than
- ten) and uses it to index into the parameter address table.
- The parameter, prefixed by its length, is then moved from the
- parameter storage area into the output buffer.
- After each line is moved into the output buffer, the
- subroutine FLUSH writes the buffer to the disk.
- When WRSUB has written the last record to the output file,
- control returns to the mainline routine, which warm-boots CP/M
- and begins execution of the new file.
-