The Callable TPU Interface
VAXTPU (VAX Text Processing Utility, hereafter referred to as TPU) was introduced with VAX/VMS version 4.2. TPU is a programmable text processing utility that allows applications programmers to easily write editing interfaces and extend interfaces already written in TPU. TPU provides a compiler and an interpreter for the TPU language. One of the editing interfaces written in TPU is the “new” EVE editor, an editor that allows great flexibility (though the default key definitions don’t show it).
DEC provides a series of callable procedures that allow applications to invoke TPU without spawning a DCL subprocess. Using these routines, your application can call an editor written in TPU as easily as any other subroutine. There are two callable interfaces to TPU – a simplified interface and a full interface (the simplified interface calls the full interface to actually invoke TPU). The callable interfaces are described in the VAX/VMS Manual, Utility Routines.
Regardless of the interface used to invoke TPU, the actual call is accomplished by linking to the shareable TPU image, SYS$LIBRARY:TPUSHR.EXE. When you link a program that calls TPU, you can specify the shareable image to the linker. However, the VMS linker is capable of determining what you are doing and will automatically link you to the shareable image.
THE SIMPLIFIED INTERFACE
The simplified interface consists of two routines, TPU$TPU and TPU$EDIT. TPU$TPU accepts one parameter, which is a string in the format of a DCL command normally used to invoke EVE:
$ TPU INFILE.TXT/OUTPUT=OUTFILE.TXT/COMMAND=EVEINI.TPU
TPU$TPU calls routines in the full interface to parse the string and invoke TPU. Ultimately, the utility routine CLI$DCL_PARSE is called to parse the string as a DCL command. The other routine in the simplified interface, TPU$EDIT, accepts an input file name and an output file name as parameters. This routine takes the given file names, creates a DCL command string using them, and then calls TPU$TPU. TPU$EDIT is by far the easiest way to invoke callable TPU, since only an input file is needed. The simplified interface is indeed “simple,” and is probably perfect for most applications needing to call TPU.
Problems using TPU$TPU and TPU$EDIT
While reading about callable TPU, I decided that TPU$EDIT was the routine I would call from one of my programs. My program was using the CLI routines to parse commands and make queries about the elements of the command line. When I added the call to TPU, the editor was invoked as expected. All appeared fine until my routine later made a call to CLI$PRESENT to see if a certain qualifier had been given on the command line. The CLI routine signalled an error, “Specified entity not found in command tables.” The routine had worked fine before I added the call to TPU$EDIT, so I knew that it was somehow responsible for the problem.
Before long, I realized that my routine and TPU$EDIT were both calling the CLI routines. The problem turned out to be that CLI$DCL_PARSE needs the address of a command table to parse a command. When my program first called CLI$DCL_PARSE, the command table for my program was established as the command table for subsequent calls to the other CLI routines. Because TPU$EDIT was also calling CLI$DCL_PARSE, TPU’s CLI command table was superseding mine. When my routine called CLI$PRESENT after calling TPU$EDIT, the CLI routine was still using TPU’s CLI command table, not mine. Hence the error that was signalled. One solution was to call CLI$DCL_PARSE again before I called CLI$PRESENT, but I felt that was unnecessarily sloppy. The other solution left to me was to use the full callable TPU interface.
The full TPU interface isn’t exactly easy to use (at least not as easy as I wanted). So I decided to write my own simplified interface that did what DEC’s should have done to begin with – allow various parameters to be passed in and then call the full interface routines without calling the CLI routines. I can see a couple of reasons for DEC’s approach (TPU$TPU uses a command line that is already familiar to a TPU user), but the simplified interface sure is inefficient. If you call TPU$EDIT, you’re really calling TPU$TPU, which calls TPU$CLIPARSE, which in turn calls CLI$DCL_PARSE, just to find the names of the input file and output file that you originally passed in to TPU$EDIT! (OK, there are a couple of other defaults that this handily takes care of, but still..)
The design for my simplified interface, TPU_EDIT (Program 1), was based on DEC’s callable EDT routine (also described in the Utility Routines manual). My routine allows you to pass in everything that could be specified on the DCL command line. This approach seems to give all of the flexibility that TPU$TPU allows, without introducing the complexity (and without calling the CLI routines!). The parameters that can be passed are as follows:
- The name of the input file
- The name of the output file
- The name of the command file (corresponds to /COMMAND)
- The name of the section file (corresponds to /SECTION)
- The name of the journal file (corresponds to /JOURNAL)
- An options bit mask that indicates options to be used (/CREATE, /DISPLAY, etc.)
All of the parameters are optional except the input and output file name. An example of calling TPU_EDIT from BASIC would look like this:
CALL TPU_EDIT ("INFILE.TXT","OUTFILE.TXT")
THE FULL INTERFACE
Before describing my simplified TPU interface, I will provide brief descriptions of the 10 routines that make up the full callable TPU interface. For detailed descriptions of each of these routines, see the VAX/VMS manual Utility Routines.
As the name implies, this routine is called to initialize TPU. This routine performs the allocation of global data structures and calls the initialization routines for the major parts of the editor (screen management routines, I/O routines, etc.). It accepts one argument, the address of a callback routine that returns the address of an item list describing the initialization parameters. There are nine items that can be specified in the item list, including the name of the section file, the name of the input file, and the name of the output file. TPU$INITIALIZE defaults all strings to the null string. Two items that cannot be defaulted are the FILEIO routine (the routine that performs all file I/O operations) and the CALLUSER routine.
This routine is the default error handler for TPU. It calls the system service SYS$PUTMSG to format the text of error messages and then calls another TPU$ routine to print the message to the screen (TPU$MESSAGE). For non-fatal errors, the handler returns with a continue status, allowing the TPU procedure to continue executing. If the error is fatal or is not a TPU error, the error is resignaled (usually resulting in a fatal TPU error and a nice little message about submitting an SPR).
This routine will allow you to execute a user-written TPU initialization file. If used, this routine must be called after TPU$INITIALIZE and before any other TPU$ routines. If a section file was successfully mapped in by TPU$INITIALIZE, the TPU procedure TPU$INIT_PROCEDURE is located and executed. If a command file was given, it is then read into a buffer, compiled, and executed.
This is the main routine for callable TPU; it reads keystrokes and performs all of the editing functions. Before calling this routine, TPU$INITIALIZE must be called. Once this routine takes control, the user’s program will not receive control until the user leaves the editor (either by quitting or exiting).
When TPU is no longer needed, this routine is called to release data structures, close the section file, reset the terminal characteristics, and perform other cleanup tasks. It accepts one parameter, the address of a longword bit mask that describes the various cleanup options. When this routine is called, you can have it perform only certain jobs (such as deleting buffers and windows) or delete the entire TPU editing context (TPU$M_DELETE_CONTEXT).
This routine provides access to the built-in TPU function MESSAGE. It can be called by a user routine to print a message that is consistent with TPU’s messages. It accepts one parameter, the address of a string descriptor that points to the message text.
This routine allows a non-TPU user-routine to execute TPU commands. It accepts the TPU command as a string. This routine performs the same function as the TPU built-in command EXECUTE.
This routine is TPU’s default file I/O routine. It can be specified in the TPU$INITIALIZE item list as the FILEIO routine.
TPU$PARSEINFO and TPU$CLIPARSE
These routines are used to parse a command string and build an item list to pass to TPU$INITIALIZE. Both routines call the CLI (Command Language Interpreter) utility routines to determine what information was passed on the command line.
TPU_EDIT – My Simplified TPU Interface
The calling sequence for the full TPU interface is straight-forward:
- Establish a condition handler (TPU$HANDLER, in this case).
- Initialize the TPU structures (TPU$INITIALIZE).
- Execute the TPU procedure TPU$INIT_PROCEDURE in the section file that was opened (TPU$EXECUTE_INIFILE).
- Turn control ovur to TPU (TPU$CONTROL).
- Clean up by releasing memory no longer needed, closing files, etc. (TPU$CLEANUP)
Step 1 – The Error Handler
The first step in calling TPU is to establish a condition handler to take care of errors that may occur. For my purposes, the default TPU condition handler (TPU$HANDLER) was fine; from MACRO, establishing a condition handler takes only a single instruction:
This instruction moves the handler’s address to the top of the current call frame (pointed to by the Frame Pointer – FP). From a high-level language, you can call the Run-Time Library routine LIB$ESTABLISH to establish a condition handler.
Step 2 – Calling TPU$INITIALIZE
The second step, calling TPU$INITIALIZE, proved to be the most complicated part of the process. TPU$INITIALIZE uses an item list that describes initialization parameters; however, its parameter is the address of a routine that TPU$INITIALIZE calls. This callback routine returns the address of the item list. For an application that needs to call TPU and has a static item list, this is trivial; the callback routine simply moves the address of the item list into R0 and returns. But because I wanted to provide a flexible interface that would allow calling routines to omit arguments, my callback routine is a little more complex.
The item list that TPU$INITIALIZE needs is an array of item descriptors (see Figure 1). There is an item code for each piece of information that can be included in the item list. For example, the item code for the input file is TPU$K_INPUTFILE. Each of the item codes (as well as error codes) is declared as a global constant by the TPU shareable image. When you link your program with the shareable image, all references to these constants are resolved. The item descriptor for the input file consists of the length of the input file name, the item code, the address of the input file name string, and a return address (0 for item descriptors). The item descriptors can be passed in any order; the list is terminated with a descriptor whose fields are zero.
When passing procedure addresses in TPU, a Bound Procedure Value (BPV) is used. A BPV consists of two longwords: the first longword is the address of the routine and the second is the environment value (a value that is passed to your routine in R1). It is the address of the BPV for your callback routine that is passed to TPU$INITIALIZE.
The code for my callback routine checks the arguments originally passed to TPU_EDIT. If an argument is omitted (or 0 is passed in), certain defaults are used to make this routine consistent with the DCL-TPU interface:
- If an options mask is not passed in, a default mask is used. This mask matches all options that normally default with the DCL command.
- If no section file is passed, the default is TPUSECINI.
- If no command file is passed, the routine checks to see if a TPUINI file exists. If it does, it is used as the command file.
- If no journal file name is passed, the name defaults to the name of the input file.
For each of the arguments passed to the routine, an item descriptor is added to the item list. The FILEIO item always defaults to TPU$FILEIO. When the item list is complete, the callback routine places its address in R0 and returns to TPU$INITIALIZE, which continues the TPU initialization.
Step 3 – Calling TPU$EXECUTE_INIFILE
Before control can be turned over to TPU, TPU$INIT_PROCEDURE in the section file must be executed. For EVE, this procedure creates all of the buffers, windows, etc., necessary for EVE to work. This third step is accomplished by simply calling TPU$EXECUTE_INIFILE.
Step 4 – Calling TPU$CONTROL
The routine is now ready to turn control over to TPU by calling TPU$CONTROL. TPU reads all of the keystrokes and performs all of the editing functions. Control does not return to my routine until the user exits the editor.
TPU$CONTROL returns one of two condition values: TPU$_EXITING (returning because of EXIT) and TPU$_QUITTING (returning because of QUIT). One detail not mentioned anywhere is that these condition values, when returned by TPU$CONTROL, have bit 28 turned on; this bit, when set, prevents any message from being printed on image exit. This is fine unless your program wants to check which of these values was returned. Normally, bit 28 is clear; if your program simply compares the return value with TPU$_EXITING, they will not be equal, even if the user did EXIT. TPU_EDIT clears this bit before returning it to the caller, allowing calling programs to check for these two conditions.
Step 5 – Calling TPU$CLEANUP
The final step is to call TPU$CLEANUP to release unneeded memory. The address of a bit mask that denotes the cleanup options is passed to TPU$CLEANUP. All of the cleanup options available appear in the VMS manual entry for TPU$CLEANUP. My routine asks TPU$CLEANUP to do all cleanup options except closing the section file. By leaving the section file open, processing time is decreased the next time the main routine invokes TPU. My routine works like TPU$TPU in this respect.
Linking with TPU_EDIT and TPU
To assemble TPU_EDIT and link it with a program, simply write the calling program (called CALL_EDITOR in the example), and compile and link as you normally would:
$ MACRO TPU_EDIT $ BASIC CALL_EDITOR $ LINK CALL_EDITOR,TPU_EDIT
When you run CALL_EDITOR, TPU will be invoked without spawning a subprocess.
As I said earlier, calling TPU$EDIT will be sufficient for invoking TPU from most programs. If you encounter the problem I had, TPU_EDIT will provide the same functionality. Either way, you should now be more familiar with the callable TPU interface.
Hunter Goatley, a graduate in Computer Science from Western Kentucky University, is currently working as a programmer/analyst for Clyde Digital Systems, Orem, Utah.
+-----------------------------------------------+ +0 | | | | Item code | Buffer Length | | | | |-----------------------------------------------| +4 | | | Buffer address | | | |-----------------------------------------------| +8 | | | Return address (0 for item lists) | | | +-----------------------------------------------+ Figure 1 -- Item descriptor
+-----------------------------------------------+ +0 | | | Procedure address | | | |-----------------------------------------------| +4 | | | Environment Value (passed in R1) | | | +-----------------------------------------------+ Figure 2 -- BPV
.TITLE TPU_EDIT - Provide simplified callable interface to VAXTPU .IDENT /01-001/ ;++ ; ; Routine: TPU_EDIT ; ; Author: Hunter Goatley ; Clyde Digital Systems ; 371 East 800 South ; Orem, Utah 84058 ; (801) 224-5306 ; ; Date: November 7, 1987 ; ; Functional Description: ; ; This routine provides a simple interface to callable VAXTPU. This ; routine differs from DEC's simplified interfaces in that parameters ; are passed to this routine, which then sets up a TPU initialization ; item list and calls the full callable TPU interface. ; ; This routine is necessary because DEC's simplified interface routines ; call the routine TPU$PARSEINFO, which in turn calls CLI$DCL_PARSE. ; This poses a problem if the calling program is also using the CLI ; parsing routines because any call to a CLI$ routine after the TPU ; invocation is unknowingly using TPU's CLI table! The CLI$ routines ; do not change command tables until another call to CLI$DCL_PARSE is ; made. ; ; Modified by: ; ; 01-001 Hunter Goatley 7-NOV-1987 11:36 ; Original version. ; ;-- ; ; Argument offsets from (AP) ; INFILE = 1 * 4 ; Arg 1 = input file spec OUTFILE = 2 * 4 ; Arg 2 = output file spec COM_FILE = 3 * 4 ; Arg 3 = command file spec SEC_FILE = 4 * 4 ; Arg 4 = section file spec JOU_FILE = 5 * 4 ; Arg 5 = journal file spec OPTIONS = 6 * 4 ; Arg 6 = options mask $SSDEF ; System service status symbols $STSDEF ; STS$ condition symbols $LIBDEF ; LIB$ status symbols ;=============================================================================== ; ; Read-only data ; .PSECT _TPU_EDIT_DATA_RD,NOEXE,NOWRT,LONG,SHR,PIC INIT_ARGS: .LONG 1 ; TPU$INITIALIZE argument list .ADDRESS CALLBACK_BPV ; ... Bound Procedure Value ; ... for callback routine CALLBACK_BPV: ; Bound Procedure Value .ADDRESS INITIALIZE_CALLBACK ; Address of routine .LONG 0 ; Environment (passed in R1) ; CLEAN_ARGS: .LONG 1 ; TPU$CLEANUP argument list .ADDRESS CLEANUP_FLAG ; ... Cleanup options ; CLEANUP_FLAG: .LONG <TPU$M_RESET_TERMINAL!TPU$M_DELETE_BUFFERS - !TPU$M_DELETE_JOURNAL!TPU$M_DELETE_WINDOWS - !TPU$M_DELETE_EXITH!TPU$M_EXECUTE_PROC - !TPU$M_EXECUTE_FILE!TPU$M_KILL_PROCESSES - > ; FILEIO_BPV: .ADDRESS TPU$FILEIO ; BPV for FILEIO routine .LONG 0 ; (points to TPU$FILEIO) ; OPTIONS_MASK: .LONG <TPU$M_SECTION!TPU$M_DISPLAY! - TPU$M_JOURNAL!TPU$M_OUTPUT! - TPU$M_CREATE!TPU$M_COMMAND> ; FINDINI: .LONG 4 ; LIB$FIND_FILE argument list .ADDRESS TPUINI ; Addr of TPUINI .ADDRESS WORK_BUFFER ; Addr for resultant spec .ADDRESS INICONTEXT ; The search context .ADDRESS TPUINI_DEF ; The SYS$DISK: string FINDINI2: .LONG 1 ; LIB$FIND_FILE_END arg. list .ADDRESS INICONTEXT ; The search context ; TPUSECINI: .ASCID /TPUSECINI/ ; TPU section file logical .ALIGN LONG ; Align on longword boundary TPUINI: .ASCID /TPUINI/ ; Default spec for command file .ALIGN LONG ; Align on longword boundary TPUINI_DEF: .ASCID /SYS$DISK:.TPU/ ; Default spec for TPUINI file ;=============================================================================== ; ; Read/Write data ; .PSECT _TPU_EDIT_DATA,NOEXE,WRT,LONG,PIC ; ; Item list returned to TPU$INITIALIZE. This list provides all information ; about all of the TPU options selected. The FILEIO descriptor is always ; present in the list. ; ITEM_LIST: .WORD 4 ; Item list descriptor for .WORD TPU$K_FILEIO ; ... FILEIO routine (points .ADDRESS FILEIO_BPV ; ... to BPV for default TPU .LONG 0 ; ... routine (TPU$FILEIO) ; ; Variable portion of item list ; VAR_ITEM_LIST: .LONG 0[9*3*4] ; Up to 9 additional items ; ... (including end of list) ; ORIG_ARGS: .BLKL 10 ; Space for argument list copy ; INICONTEXT: .LONG 0 ; LIB$FIND_FILE search context WORK_BUFFER: .LONG 256 ; Temporary work buffer .ADDRESS .+4 ; ... for LIB$FIND_FILE .BLKB 256 ; ... ;+ ; ; FUNCTIONAL DESCRIPTION: ; ; This routine copies its argument list to ORIG_ARGS, establishes the ; default TPU condition handler (TPU$HANDLER) as its handler, and calls ; the initialization routines to invoke VAXTPU. ; ; FORMAL ARGUMENTS: ; ; 4(AP) - Address of input file name descriptor ; 8(AP) - Address of output file name descriptor ; 12(AP) - Address of command file name descriptor (/COMMAND) ; (Optional - defaults to TPUINI) ; 16(AP) - Address of section file name descriptor (/SECTION) ; (Optional - defaults to TPUSECINI) ; 20(AP) - Address of journal file name descriptor (/JOURNAL) ; (Optional - defaults to input_file.TJL) ; 24(AP) - Address of longword options mask (Optional) ; ; Options mask bits: ; ; TPU$M_CREATE - create input file if the one specified ; does not exist (DEFAULT) ; TPU$M_DISPLAY - Attempts to use the terminal for screen- ; oriented editing (DEFAULT) ; TPU$M_OUTPUT - Writes the modified input file on exiting ; (DEFAULT) ; TPU$M_SECTION - Maps in a VAXTPU section file on startup ; (DEFAULT) ; TPU$M_COMMAND - Executes a command file during startup ; (DEFAULT) ; TPU$M_JOURNAL - Journals the edit session (DEFAULT) ; TPU$M_READ - Makes main buffer READ_ONLY edit session ; TPU$M_RECOVER - Performs a recovery operation ; ; IMPLICIT INPUTS: ; ; ORIG_ARGS - Copy of this routine's argument list ; INIT_ARGS - Argument list for TPU$INITIALIZE ; CLEAN_ARGS - Argument list for TPU$CLEANUP ; ; IMPLICIT OUTPUTS: ; ; None. ; ; COMPLETION CODES: ; ; LIB$_WRONUMARG - The wrong number of arguments was specified ; TPU$_EXITING - User EXITed from editor ; TPU$_QUITTING - User QUIT from editor ; ; Any other code returned by TPU$INITIALIZE, TPU$EXECUTE_INIFILE, ; TPU$CONTROL, and TPU$CLEANUP. ; ; SIDE EFFECTS: ; ; Invokes TPU. The section file is not closed as part of the cleanup ; for efficiency on subsequent calls. ; ;- .PSECT _TPU_EDIT_CODE,EXE,NOWRT,LONG,PIC,SHR .ENTRY TPU_EDIT,^M<R2,R3,R4,R5> CMPW #2,(AP) ; Were at least 2 parms given? BGTRU 10$ ; Yes - we're OK CMPW #6,(AP) ; Were at most 6 parms given? BGEQU 20$ ; Yes - we're OK 10$: MOVL #LIB$_WRONUMARG,R0 ; No - return insufficient args RET ; ... to caller ; 20$: MOVAB G^TPU$HANDLER,(FP) ; Set up condition handler to be ; ... the default TPU handler MOVZWL (AP),R0 ; Get the number of args ASHL #2,R0,R0 ; Multiply by 4 ADDL2 #4,R0 ; Bump R0 by 4 MOVC3 R0,(AP),ORIG_ARGS ; Copy argument list ; CALLG INIT_ARGS,G^TPU$INITIALIZE ; Initialize TPU BLBC R0,30$ ; Error? Return it ; CALLS #0,G^TPU$EXECUTE_INIFILE ; Execute the initialization BLBC R0,30$ ; Error? Return it ; CALLS #0,G^TPU$CONTROL ; Turn control over to VAXTPU BLBC R0,30$ ; Error? Return it PUSHL R0 ; Save the status ; CALLG CLEAN_ARGS,G^TPU$CLEANUP ; Clean up BLBC R0,30$ ; Error? Return it ; POPL R0 ; Restore TPU$CONTROL status 30$: BICL2 #STS$M_INHIB_MSG,R0 ; Turn off inhibit message ; ... on image exit RET ; Return to caller ;+ ; ; Routine: INITIALIZE_CALLBACK ; ; Functional description: ; ; This routine is called by TPU$INITIALIZE to set up the initialization ; parameters item list. The address of the item list is returned to ; TPU$INITIALIZE. ; ; This routine builds the item list from the arguments passed in to the ; main routine, TPU_EDIT. It accesses the argument list copy made by ; TPU_EDIT. ; ; The item list always contains at least 4 items: the input file, the ; output file, the options mask, and the FILEIO routine (TPU$FILEIO). ; ; Register usage: ; ; R2 - Points to current location in item list buffer ; R3 - Copy of the OPTIONS mask passed to TPU ; R4 - Points to copy of TPU_EDIT's argument list (acts as AP) ; ;- .ENTRY INITIALIZE_CALLBACK,^M<R2,R3,R4> MOVAL ORIG_ARGS,R4 ; Get address of original args MOVAB VAR_ITEM_LIST,R2 ; Get the item list address ; ; Branch to subroutines to build the item list descriptors for each of the ; arguments passed in. The GET_OPTIONS subroutine must be executed first ; because the other routines access the copy of the options mask placed in ; R3 by GET_OPTIONS. ; BSBW GET_OPTIONS ; Get the options to use BSBW GET_JOURNAL ; Get the journal file BSBB GET_SECTION ; Get the section file BSBB GET_COMMAND ; Get the command file ; ; Get the output file ; MOVQ @OUTFILE(R4),R0 ; Get output file descriptor MOVW R0,(R2)+ ; Set the length MOVW #TPU$K_OUTPUTFILE,(R2)+ ; Code is OUTPUTFILE MOVL R1,(R2)+ ; Address of output file name CLRL (R2)+ ; Return address is 0 ; ; Get the input file ; MOVQ @INFILE(R4),R0 ; Get input file descriptor MOVW R0,(R2)+ ; Set the length MOVW #TPU$K_FILENAME,(R2)+ ; Code is FILENAME MOVL R1,(R2)+ ; Address of output file name CLRL (R2)+ ; Return address is 0 CLRQ (R2)+ ; Clear 3 longwords to signal CLRL (R2)+ ; ... the end of the item list MOVAB ITEM_LIST,R0 ; Now return item list address RET ; ... to TPU$INITIALIZE GET_SECTION: ; ; This routine builds the item descriptor for the TPU section file. ; If a file spec is passed in as an argument, it is used as the section ; file. If there is no file spec passed in, TPUSECINI is used. ; BBC #TPU$V_SECTION,R3,30$ ; No SECTION if option bit clear CMPB #4,(R4) ; Were there 4 arguments? BGTRU 10$ ; No - use default TPUSECINI TSTL SEC_FILE(R4) ; Was a section file specified? BEQLU 10$ ; No - use default(s) MOVQ @SEC_FILE(R4),R0 ; Yes - get section descriptor BRB 20$ ; Go clear return addr and RSB 10$: MOVQ TPUSECINI,R0 ; Default is TPUSECINI ; ; Here, a file name descriptor is in R0 & R1 ; 20$: MOVW R0,(R2)+ ; Set the length in item list MOVW #TPU$K_SECTIONFILE,(R2)+ ; Code is SECTIONFILE MOVL R1,(R2)+ ; Address of section file name CLRL (R2)+ ; Return address is 0 30$: RSB ; Return to caller GET_COMMAND: BBC #TPU$V_COMMAND,R3,30$ ; No COMMAND if option bit clear CMPB #3,(R4) ; Were there 3 arguments? BGTRU 10$ ; No - go to next TSTL COM_FILE(R4) ; Was a command file given? BEQLU 10$ ; No - go to next MOVQ @COM_FILE(R4),R0 ; Get command file descriptor BRB 20$ ; Go set up item descriptor 10$: CLRL INICONTEXT ; Clear find file context CALLG FINDINI,G^LIB$FIND_FILE ; Look for initialization file PUSHL R0 ; Save result for a sec CALLG FINDINI2,G^LIB$FIND_FILE_END ; Clean up search context POPL R0 ; Get FIND_FILE result BLBC R0,30$ ; If FNF, don't pass name in MOVQ TPUINI,R0 ; Use TPUINI as the command file 20$: MOVW R0,(R2)+ ; Set the length MOVW #TPU$K_COMMANDFILE,(R2)+ ; Code is COMMANDFILE MOVL R1,(R2)+ ; Address of command file name CLRL (R2)+ ; Return address is 0 30$: RSB ; Return to caller GET_OPTIONS: ;+ ; Inputs: ; ; R2 = Pointer to item list ; ; Outputs: ; ; R3 = The OPTIONS mask that is passed to TPU ;- CMPB #6,(R4) ; Were there 6 arguments? BGTRU 10$ ; No - use default options mask TSTL OPTIONS(R4) ; Were any options given? BEQLU 10$ ; No - use default options mask MOVAL @OPTIONS(R4),R1 ; Yes - put address in R1 BISL2 #TPU$M_OUTPUT,(R1) ; Ensure OUTPUT option is set! BRB 20$ ; Go set up the item descriptor 10$: MOVAL OPTIONS_MASK,R1 ; R1 = addr of default options 20$: MOVW #4,(R2)+ ; Length is 4 MOVW #TPU$K_OPTIONS,(R2)+ ; Code is OPTIONS MOVL R1,(R2)+ ; Address MOVL (R1),R3 ; Copy the options mask to R3 CLRL (R2)+ ; Clear return address RSB ; Return to caller GET_JOURNAL: BBC #TPU$V_JOURNAL,R3,10$ ; No JOURNAL if option bit clear CMPB #5,(R4) ; Were there 5 arguments? BGTRU 10$ ; No - go to next TSTL JOU_FILE(R4) ; Was a journal file given? BEQLU 10$ ; No - go to next MOVQ @JOU_FILE(R4),R0 ; Get journal file descriptor MOVW R0,(R2)+ ; Set the length MOVW #TPU$K_JOURNALFILE,(R2)+ ; Code is JOURNALFILE MOVL R1,(R2)+ ; Address of journal file name CLRL (R2)+ ; Return address is 0 10$: RSB ; Return to caller .END