Trailing-Edge
-
PDP-10 Archives
-
decuslib10-12
-
43,50547/pltlib/tek/runlib.mac
There is 1 other file named runlib.mac in the archive. Click here to see a list.
TITLE RUNLIB - FORTRAN callable routines to do TMPCOR and RUN UUO's
SUBTTL By Joe Smith 22-Oct-81
;In order to load easily with FORTRAN routines, RUNLIB is assembled into
;the LOWSEG only. To make a REL file to go in the HISEG, do the following:
; .R MACRO
; *TOPLIB,RUNLIB/C=TTY:,DSK:RUNLIB
; TOPSEG=-1
; ^Z
; [MCREP1 END OF PASS 1]
; TOPSEG=-1 ;Put these routines in the HISEG
; ^Z
; *CREF!
; *RUNLIB
; *^Z
;
; The above commands are in RUNLIB.MIC
SEARCH MACTEN,UUOSYM ;Standard TOPS-10 definitions
LIBWHO==2 ;Non-DEC program
LIBVER==4 ;Major version number
LIBMIN=="A"-"@" ;Minor version
LIBEDT==17 ;Edit level
MODSHW (LIB) ;Define %%LIB as version number
;; NOTE: Don't let the size of this file throw you, it is more than 2/3
;; comments. The start of executable code is on page 23.
; Table of Contents for FORTRAN callable RUN library
;
;
; Section Page
;
; 1. Table of Contents . . . . . . . . . . . . . . . . . . 2
; 2. Definitions . . . . . . . . . . . . . . . . . . . . . 3
; 3. Revision History . . . . . . . . . . . . . . . . . . . 5
; 4. Documentation - RUNLIB.DOC . . . . . . . . . . . . . . 6
; 5. Calling sequence
; 5.1 Introduction . . . . . . . . . . . . . . . . . 7
; 5.2 RESCAN . . . . . . . . . . . . . . . . . . . . 9
; 5.3 INCHWL . . . . . . . . . . . . . . . . . . . . 10
; 5.4 TMPCOR and RUNUUO . . . . . . . . . . . . . . 11
; 5.5 OUTSTR . . . . . . . . . . . . . . . . . . . . 12
; 5.6 SAVRUN . . . . . . . . . . . . . . . . . . . . 13
; 5.7 JBINFO . . . . . . . . . . . . . . . . . . . . 14
; 5.8 EXIT0, EXIT1, and EXITGO . . . . . . . . . . . 15
; 5.9 HELPER . . . . . . . . . . . . . . . . . . . . 16
; 5.10 MATCH . . . . . . . . . . . . . . . . . . . . 17
; 5.11 Examples . . . . . . . . . . . . . . . . . . . 18
; 5.12 Writing a FORTRAN program that compiles itse . 19
; 6. Appendix - Calling RUNLIB from MACRO programs . . . . 21
; 7. LOWSEG data area . . . . . . . . . . . . . . . . . . . 23
; 8. TMPCOR
; 8.1 Write TEMP file . . . . . . . . . . . . . . . 24
; 9. RUNUUO
; 9.1 Run next program . . . . . . . . . . . . . . . 25
; 9.2 Prepare to go . . . . . . . . . . . . . . . . 26
; 9.3 Error recovery . . . . . . . . . . . . . . . . 27
; 10. INCHWL
; 10.1 Give prompt and input a full line from TTY . . 28
; 10.2 Prompt the user . . . . . . . . . . . . . . . 29
; 11. RESCAN
; 11.1 Check monitor line, TMPCOR or DSK:nnnPRG.TMP . 30
; 11.2 Do RESCAN uuo . . . . . . . . . . . . . . . . 31
; 12. HELPER
; 12.1 Subroutine to output SYS:??????.HLP %5(42) . 33
; 12.2 Try the other ersatz devices . . . . . . . . . 34
; 12.3 I/O routines . . . . . . . . . . . . . . . . . 35
; 13. EXITGO
; 13.1 Return to the monitor . . . . . . . . . . . . 36
; 13.2 Close any open channels . . . . . . . . . . . 37
; 14. OUTSTR
; 14.1 Output a string on the TTY . . . . . . . . . . 38
; 15. JBINFO
; 15.1 Return info about the job . . . . . . . . . . 39
; 16. SAVRUN
; 16.1 Save the /RUN switch and clean up buffer . . . 41
; 16.2 Look for /RUN . . . . . . . . . . . . . . . . 42
; 17. MATCH
; 17.1 Check if command matches list . . . . . . . . 43
; 18. Subroutines
; 18.1 Read TMPCOR or DSK:nnnxxx.TMP . . . . . . . . 44
; 18.2 Read file from disk . . . . . . . . . . . . . 45
; 18.3 TSTABR - Test if T1 is an abbreviation . . . . 46
; 18.4 GETWRD - Get alphameric word in T1, input vi . 47
; 18.5 SCAN - read DEV:FILENAME . . . . . . . . . . . 48
; 18.6 CLRBUF - clear BUFFER, KOUNT, LASTC, set up . 49
; 18.7 COMCH and TTYIN - character input routines . . 50
; 18.8 GETNAM - Returns 3 SIXBIT characters for pro . 51
; 19. Data area
; 19.1 Constants and literals . . . . . . . . . . . . 52
SUBTTL Definitions
;Ac definitions
F=0 ;Flag
T1=1 ;Temp
T2=2
T3=3
T4=4
C=5 ;Counter
C2=C+1 ;Second counter, stop IOWD
BP=7 ;ASCII byte pointer
CH=10 ;Holds character
L=16 ;Link to arg list
P=17 ;PDL pointer
.XCREF T1,T2,T3,T4,C,C2,CH,BP,P ;CREF only F and L
;Argument indices
NAM==0 ;TMPCOR name or prompt
COD==0 ;Error code/SAVRUN flags
BUF==1 ;Addr of buffer
CNT==2 ;Number of chars in buffer
LEN==3 ;Size of buffer or RUNOFFSET
CHR==4 ;Last character
IDX==4 ;Index returned from MATCH
DNM==5 ;Double precision name from MATCH
;Character definitions
BEL==7
TAB=11
LF=12
VT=13
FF=14
CR=15
CZ=32 ;Control-Z
ESC=33
SP=" "
;Flag bits, right half (Must match the options for SAVRUN)
F.RUN== 1 ;1 Look for @CCLFIL/RUN/RUNOFF/EXIT/HELP
F.COM== 2 ;2 Ignore comments
F.CTL== 4 ;4 Ignore control chars
F.LSP== 10 ;8 Ignore leading spaces
F.SSP== 20 ;16 Convert tabs and multiple spaces to 1 space
F.UC== 40 ;32 Convert lower case to upper
F.BRK==100 ;64 Convert <> to [] (APPLEs and 2741)
F.TAB==200 ;128 Convert tabs to multiple spaces
F.ALL= 377 ;All defined bits for SAVRUN
F.SP== 400000 ;Ignore further spaces
F.CZ== 200000 ;Control-Z or /EXIT was seen
F.QUO==100000 ;Inside quotes, leave ; ! / alone
;More definitions
;Define OPCODEs which have the same name as entry points
OPDEF TMPCOR [TMPCOR]
OPDEF OUTSTR [OUTSTR]
OPDEF INCHWL [INCHWL]
OPDEF RESCAN [RESCAN]
;Misc definitions
;Set FT603==1 if you plan to use RUNLIB with the 6.03A monitor.
ND FT701,-1 ;Use 7.01 extended FILOP channels for I/O
ND FT603,-1 ;Include code for using channel 0 for I/O
IFE FT603!FT701,< FT603==-1 > ;Must have one or the other or both
ND CBUFSZ,^D512 ;Size of COMBUF, can be 128 for 6.03A
IFN <CBUFSZ&177>,<PRINTX ?CBUFSZ must be a multiple of 128>
CBUFS5=CBUFSZ*5 ;Max bytes in COMBUF
%0==0 ;Temporary I/O channel
DEFINE HELLO (.NAME.),< LALL
ENTRY .NAME. ;For library searches
ENTRY $'.NAME. ;Alternate name for MACRO subroutines
$'.NAME.==.NAME. ;...
SIXBIT /.NAME./ ;For subroutine TRACE.
.NAME.: MOVEM F,SAVE0 ;Save the AC's
MOVE F,[T1,,SAVE1] ; ...
BLT F,SAVEND ; AC's 1 thru 17
sall ;(End of HELLO expansion) >
SUBTTL Revision History
; Created by Joe Smith, Colorado School of Mines Computing Center.
;1(1) First versions written Oct 77. TMPCOR and RESCAN in separate files.
;2(2) Combined into one file Nov 77.
;3(3) Put in library, RUNLIB. Separated RUNUUO from TMPCOR. Added
; mode 3 to SAVRUN. 12-Sep-78.
;4(4) Rewrote SAVRUN completely. 14-Dec-78
;4(5) Implemented /RUNOFF, added more comments. 30-Dec-78.
;4(6) Fixed bug in CHKRUN, code cleanup. 14-Aug-79.
;4(7) Fix bug in OUTSTR. 17-Apr-80.
;4A(10) RESCAN returns data only if TTCALL succeeded. If it found a CCL
; file, it sets KOUNT=-1. INCHWL must be used to read the CCL file,
; one line at a time. INCHWL returns KOUNT=-1 when it hits end of CCL
; file. 13-Jun-81.
;(11) General clean up. 12-Aug-81
;(12) Added subroutine MATCH. 9-Sep-81
;(13) Add option in RESCAN to read binary TMP files. 25-Sep-81
;(14) Have MATCH return the unabbreviated command in A6 format. 17-Oct-81
;(15) Add IOPT to SAVRUN. 5-Nov-81
;(16) Replaced all RESET uuos in RUNUUO with RELEAS %0 to not wipe out
; FOROT6 (version 6 of FOROTS). 9-Sep-82
;(17) Fix to use CH instead of C in GETOCT. 20-May-83
SUBTTL Documentation - RUNLIB.DOC
XLIST ;RUNLIB.DOC is extracted from the following 17 pages
COMMENT | RUNLIB.DOC - Description of routines in FOR:RUNLIB.REL
This library of routines was started in 1976 for use by the DRAW package.
The DRAW package is a set of FORTRAN programs which require some monitor calls
not available in FORLIB. RUNLIB fills this requirement by including subroutines
to read and write TMPCOR files, get the user's name and job number, and execute
the RUN UUO. The subroutines originally used by DRAW were:
EXITGO Exit to the monitor unless a /RUN: switch was specified.
HELPER Type the help file.
INCHWL Read in one line from the terminal, or from an indirect file.
JBINFO Job info, such as job number and user name.
MATCH Check if a word matches a list of commands.
RESCAN Read TMPCOR, or the monitor command line.
RUNUUO Run the next .EXE file in the package.
SAVRUN Check for /RUN:, /RUNOFF, /HELP, or /EXIT in command line.
TMPCOR Write files in TMPCOR, giving commands to the next program.
Later on, more routines were added to increase functionality. These are:
EXIT0 Return to monitor level, type "EXIT".
EXIT1 Return to monitor level quietly, the "CONTINUE" command will work.
OUTSTR Type a string on the terminal, complement of INCHWL.
SUBTTL Calling sequence -- Quick summary
CALL EXIT0
CALL EXIT1
CALL EXITGO
CALL HELPER (0)
CALL INCHWL (NAME, BUFFER, KOUNT, LENGTH, LASTC)
CALL MATCH ('LIST,OF,COMMANDS,ETC',BUFFER,KOUNT,LENGTH,INDEX,DNAME)
GOTO (100, 200, 300, 400) INDEX
CALL OUTSTR (ICC, BUFFER, KOUNT)
CALL RESCAN (NAME, BUFFER, KOUNT, LENGTH, LASTC)
CALL RUNUUO (IERR, PRGNAM, KOUNT, ICCL)
CALL SAVRUN (IOPT, BUFFER, KOUNT, LENGTH, LASTC)
CALL TMPCOR (NAME, BUFFER, KOUNT)
IVALUE = JBINFO(ITABLE)
SUBTTL Calling sequence -- Introduction
These routines are provided to allow FORTRAN programs to act like
CUSP's (Commonly Used System Programs). In particular, these routines
can be used to check for command-input, exit to the monitor, or
chain-off to another program.
=============== Introduction to TMPCOR and RESCAN ====================
Commonly Used System Programs have many ways to pick up commands.
Let's take DIRECT for example. You can give commands to DIRECT in 5
different ways. 1) Monitor command; ".DIRECT TEST.FOR". 2) The R or
RUN command; ".R DIRECT (TEST.FOR)". 3) The temp-core file 'DIR';
"TEST.FOR". 4) Temp disk file 'nnnDIR.TMP'; "TEST.FOR". 5) When the
program prompts; "*TEST.FOR".
1) The monitor recognizes the word "DIRECT" and runs SYS:DIRECT.
DIRECT does a RESCAN to re-read the same command that the monitor read.
It skips over the first word, and takes the rest of the line as a
command.
2) The monitor recognizes the "R" command to run a program off of
SYS:. It ignores anything in parentheses. DIRECT does a RESCAN,
recognizes the "R", and expects its command to be enclosed in
parentheses.
3) The monitor has space for short files in temp-core (TMPCOR).
Each file goes by a three letter name, such as 'DIR' for DIRECT, 'FOR'
for FORTRAN, 'LNK' for LINK, 'MCR' for MACRO, etc. When your program
writes the words "TEST.FOR" into the 'DIR' temp-file. DIRECT reads
'TMP:DIR' and uses it as a command.
4) If TMPCOR is full, the temp-file can be put on DSK:. If your job
is number 12, then the name of the file is 'DSK:012DIR.TMP'. DIRECT
searches for this file if it cannot find anything in TMPCOR.
5) If DIRECT connot find a command anywhere, it prints a prompt and
waits for you to type a command. DIRECT uses an asterisk "*" as its
prompt. Only in case 5 will DIRECT expect more commands. As soon as it
is dones with the first command, it will give another prompt and wait
for another one, it does not return to the monitor. Typing a Control-Z
or "/EXIT" will get you to the monitor. If you type "TEST.FOR^Z", DIRECT
will give a listing for the file TEST.FOR and then return to the monitor.
The temp files in steps 3 and 4 are often referred to as CCL files.
CCL stands for Concise Command Language, and were first used by the
COMPIL program.
The RESCAN routine handles cases 1 through 4. For case 5, RESCAN
will report that it could not find anything, and your program will have
to call INCHWL to give a prompt and pick up a command.
============== Common Switches (Commands to SAVRUN) ==================
Most system programs understand comments and at least three
switches. The routine SAVRUN scans an array (buffer) and interprets the
standard switches and comments. A comment is anything after a semicolon
or an exclaimation point, ";" and "!". SAVRUN will remove comments,
remove leading spaces, convert tabs to spaces, reduce multiple
spaces to a single space, and convert lowercase to upper.
SAVRUN recognizes four switches; /HELP, /EXIT, /RUN:, and /RUNOFF.
When SAVRUN sees "/H" or "/HELP", it will type the help file for the
program. "/EXIT" and "/RUN:PROGRAM" cause LASTC to be set to 26, as a signal
to call the EXITGO routine.
SUBTTL Calling sequence -- RESCAN
RESCAN checks for command input. The commands may come from monitor
level, from a TMPCOR file, or from the temp file on disk.
CALL RESCAN (NAME, BUFFER, KOUNT, LENGTH, LASTC)
NAME = (INPUT) Three letter name of the temp-core file.
-1 means to use the name of the program, 0 to not check CCL files.
BUFFER = (OUTPUT) Array receiving the command, 5 characters per word.
KOUNT = (OUTPUT) Number of characters read in. Zero if nothing was found,
negative if a CCL file was input, to be read by INCHWL.
LENGTH = (INPUT) Size that BUFFER is dimensioned for. RESCAN will read
binary data if LENGTH is negative.
LASTC = (OUTPUT) ASCII code for the last character read in.
RESCAN first trys checking for the monitor command which started
your program. Then it checks temp-core, and finally the disk file for
commands. Because the CCL files in temp-core and disk can have more than
one line of commands, RESCAN will only check for the existance of such files
if LENGTH is positive. When this occurs, your program should call INCHWL to
get lines from the command file. Each call to INCHWL will read one line from
the CCL file, your program should continue reading until LASTC=26 (End of File).
In order to make it possible to read arbitrary binary data from TMPCOR
files, RESCAN will do input differently if you specify a negative number for
LENGTH. In this case, the entire file is read in all at once, KOUNT is 5
times the number of words read in, and LASTC is set to zero. RESCAN will not
check the monitor command line when LENGTH is negative.
KOUNT = 0 means that no command was found. This is the usual case.
KOUNT positive means that RESCAN has read the command into BUFFER.
KOUNT negative means that RESCAN found a CCL file for INCHWL to read.
SUBTTL Calling sequence -- INCHWL
INCHWL gets a line of input from the terminal (or command file). <<
CALL INCHWL (NAME, BUFFER, KOUNT, LENGTH, LASTC)
NAME = (INPUT) Three letter prompt, such as 'ABC' for "ABC>".
A value of zero or all blanks will suppress the prompt.
If NAME = -1, INCHWL will use the first three letters of the
name of your program.
BUFFER = (OUTPUT) Array receiving the command, 5 characters per word.
KOUNT = (OUTPUT) Number of characters read in. 0 for a blank line,
-1 (and LASTC=26) at end of CCL file read in by RESCAN.
LENGTH = (INPUT) Size that BUFFER is dimensioned for.
LASTC = (OUTPUT) ASCII code for the last character read in.
Your program should call EXITGO if LASTC=26 (End-Of-File).
INCHWL reads commands from the terminal, or from the CCL file if
RESCAN found one. When reading from the terminal, INCHWL prompts the
user if NAME is not zero or blanks, and then waits for the user to type
in a line. If NAME='ABC', then INCHWL would type "ABC>" on the terminal
to signify that it is waiting for input. If the user types in a blank
line (just hits the RETURN key), then INCHWL will return BUFFER as
blanks, KOUNT=0, and LASTC=13 (the code for RETURN). The only time
INCHWL returns with KOUNT negative is if it was reading from a command
file, and hit the end of file.
The end-of-line character gets stored in LASTC, right justified in
an (R1) format. Usually the user will type a carriage return so LASTC
will be 13. Other characters often used is the 'ESCape' to signal
special processing and Control-Z to exit when done.
Character Code Decimal Octal
-------- ------ ------- -----
Bell CTRL-G 7 "07
Linefeed CTRL-J 10 "12
Vertical Tab CTRL-K 11 "13
Formfeed CTRL-L 12 "14
Return CTRL-M 13 "15
End-of-file CTRL-Z 26* "32 *Control-Z means "/EXIT"
Escape $ CTRL-[ 27 "33
SUBTTL Calling sequence -- TMPCOR and RUNUUO
TMPCOR can be used to leave temporary messages for other programs.
CALL TMPCOR (NAME, BUFFER, KOUNT)
NAME = (INPUT) Three letter name of the temp-core file.
BUFFER = (INPUT) Array or literal containing the message.
KOUNT = (INPUT) Number of characters in the message.
In the 6.03A and previous monitors, temp-core was limited to 8
blocks of 20 characters each. TMPCOR was easily filled by medium length
messages. In the 7.01 monitor, the maximum size of any single TMPCOR
file is 2550 characters, and there is no limit to the number of TMPCOR
files.
-----------------------------------------------------------
RUNUUO will start the execution of another program.
CALL RUNUUO (IERR, PRGNAM, KOUNT)
CALL RUNUUO (IERR, PRGNAM, KOUNT, ICCL)
IERR = (OUTPUT) Error code if the next program cannot be run.
Error codes are 0=No such program, 1=No such PPN, 2=Protection
failure, 12 octal (10 decimal)=No such device.
PRGNAM = (INPUT) Array or literal containing the name of the program to
run. Must be in the form of 'DEV:PROG.EXT[ppn]'. EXT is
usually left off. If a PPN is given, it must be last. DEV is
optional and defaults to 'DSK:', so you may run your programs.
You must specify 'SYS:' for system programs. Examples:
'SYS:FORTRA', 'DSK:TEST.SAV[60,60]'.
KOUNT = (INPUT) Number of characters in the program name.
ICCL = (Optional INPUT) RUN-offset. If you leave a TMPCOR file for a
system program, ICCL must be 1 or else the program will not even
look for the TMPCOR file.
All files must be explicitly closed befor calling RUNUUO. Another
way to run a new program is by calling EXITGO. See the descriptions of
SAVRUN and EXITGO.
SUBTTL Calling sequence -- OUTSTR
OUTSTR outputs the buffer, with or without a <CR><LF> at the end.
This routine is not intended to replace FORTRAN formatted output, but
provides a simple way of typing character strings to the TTY.
CALL OUTSTR (ICRLF, BUFFER, KOUNT)
ICRLF = (INPUT) Carriage control. ICRLF=0 works like $ format.
-2 = Output a formfeed before BUFFER, but no CRLF after.
-1 = Output a formfeed before BUFFER, and a CRLF after.
0 = Do not output CRLF after BUFFER, used as a prompt.
1 = Output a CRLF after BUFFER, this is the normal case.
N = Output N CRLFs, creating N-1 blank lines after BUFFER.
BUFFER = (INPUT) Literal or array of characters to be output
KOUNT = (INPUT) Number of characters in BUFFER. If the characters to
be output are in a literal, KOUNT can be zero. Example:
CALL OUTSTR (0, 'What is your answer? ', 0)
SUBTTL Calling sequence -- SAVRUN
The primary function of SAVRUN is to look for a /RUN: command. It also
does general clean-up on the BUFFER.
CALL SAVRUN (IOPT, BUFFER, KOUNT, LENGTH, LASTC)
IOPT = (INPUT) Options. These may be added, ie, IOPT=2+4+8+16
0 or -1 = Do everything
1 = Act upon /RUN, /RUNOFFSET, /EXIT, or /HELP switches and start
reading an indirect file if the first character is "@".
2 = Remove comments which start with ";" or "!".
4 = Remove all control characters except tab.
8 = Remove leading spaces and/or tabs.
16 = Change tabs or multiple spaces to a single space.
32 = Convert lowercase to upper.
64 = Convert <> to [] (for APPLEs and 2741 terminals).
128 = Convert tabs to multiple spaces, if option 16 is not included.
BUFFER = (INPUT) The array of characters to be searched.
(OUTPUT) The cleaned-up array.
KOUNT = (INPUT) The number of characters to search.
(OUTPUT) The number of character left in BUFFER.
LENGTH = (INPUT) Number for the size of BUFFER in words.
LASTC = (INPUT) The last character in the BUFFER. If the user typed
Control-Z or if /EXIT was seen for IOPT=32, LASTC will be 26.
IF (LASTC.EQ.26) CALL EXITGO ! Time to exit
This routine will allow your FORTRAN programs to respond to commands
much like the system CUSPS. After SAVRUN gets done, the significant
characters in the BUFFER will be shifted to the left and all extra
characters removed. You can then check what's left and let your program
decide what to do. Note that you will not have to worry about checking
for lowercase or tabs since SAVRUN has converted these characters.
The /HELP switch can be abbreviated to /H. SAVRUN uses the name of
your program in finding help, which can be in your disk area or on HLP:.
The /RUN switch must be followed by the name of a program, such as
"/RUN:SYS:FORTRA". The device defaults to SYS: since that is the
behavior of the system CUSPS. The /RUN command is not executed
immediately, but sets LASTC to 26.
For all you RSTS/E users, you can call SAVRUN with "PUSHJ P,CVT$$".
Options 4, 8, 16, 32, and 64 work like RSTS, but trailing spaces are
always suppressed and characters in quotes are never changed. (RSTS
option 1 trims the parity bit, 2 discards all spaces and tabs, 4 discards
CR+LF+FF+ESC+RUBOUT+NULL, 8 discards leading spaces, 16 reduces tabs to
1 space, 32 converts to uppercase, 64 converts [] to (), 128 discards
trailing spaces, 256 does not alter characters in quotes.)
If you want to output a message but without trailing blanks, use
option 4 to set KOUNT, the number of words to output is (KOUNT+4)/5.
KOUNT = LENGTH * 5 ! Set to max, scan entire BUFFER
CALL SAVRUN (4,BUFFER,KOUNT,LENGTH,LASTC) ! Throw away control chars
IWORDS = (KOUNT + 4) / 5 ! Get number of A5 words in message
TYPE 10,(BUFFER(I),I=1,IWORDS) ! Suppress all but last 4 spaces
SUBTTL Calling sequence -- JBINFO
JBINFO will return information about your job.
IVALUE = JBINFO(ICODE)
IVALUE = (OUTPUT) The information returned.
ICODE = (INPUT) The code for what piece of information to return.
"0 = 0 = The value in the KA or KI CPU console switches (0 for KL or KS)
"1 = 1 = Your job number
"2 = 2 = Your PPN (octal in both halves)
"3 = 3 = Name of your program (in SIXBIT)
"4 = 4 = The runtime your job has accumulated since LOGIN
"5 = 5 = The kilo-core ticks charged to your job
"6 = 6 = Your privilege bits (octal)
"7 = 7 = Causes your job to sleep for one second
"10 = 8 = Get line characteristics and number, ITTY=(JBINFO(8).AND."777)
"11 = 9 = The date as (((year-1964)*12 + month-1)*31 + day-1
"12 = 10 = Time of day, in integer milliseconds since midnight
"13 = 11 = Universal date/time, divide by 262144 to get days since 17-Nov-1858
"14 = 12 = The day of the week (Sunday=1, Saturday=7)
(GETTAB values for 13-18)
"23 = 19 = Check typeahead, 0=none, 1=some characters, 2=complete line ready
(I=JBINFO(19) also cancels the effect of Control-O)
"24 = 20 = Input a single character (for 'Y' or 'N' answer) in an A1 format
"25 = 21 = Input a single character, right justified in an R1 format (1-127)
"26 = 22 = Node number. At CSM, KL1091 = 1 and KS2020 = 2
"30 = 24 = Get first 5 letters of user name, in an A5 format
"31 = 25 = Get next 5 letters of user name
"32 = 26 = Get last 2 letters of user name and 3 blanks
Other codes match those for the GETTAB TOPS10 Monitor Call.
SUBTTL Calling sequence -- EXIT0, EXIT1, and EXITGO
All files must be explicitly closed before calling these routines.
CALL EXIT0
CALL EXIT1
CALL EXITGO
EXIT0 Returns to the monitor and types the message "EXIT". Cannot be
continued. The standard FORTRAN routine "CALL EXIT" is the one
that closed all files and types "END OF EXECUTION ...". EXIT0
is a little quieter. NOTE: RANDOM and BINARY output files must
be closed by CLOSE(UNIT=n).
EXIT1 Returns to the monitor by typing a dot. Can be continued. EXIT1
does not check for open files. If you type anything other than
".CONTINUE", any open files may be lost.
EXITGO Stops execution of the program. Returns to the monitor if there
is not another program to run. The program to run is set up by
SAVRUN if it receives a command like "/RUN:FORTRA". EXITGO will
complain if it finds any files open, and close them for you.
EXITGO is the suggested way of to stop your program.
SUBTTL Calling sequence -- HELPER
HELPER types the help file for your program.
CALL HELPER (0)
CALL HELPER (IARG)
IARG = (INPUT) Octal number representing the name in SIXBIT, or zero
to use the name of your program.
Ask a MACRO programmer if you need to know the translation of a
particular name. For example, 'DIRECT' is 445162454364 so you could use
CALL HELPER ("445162454364)
Usually you want to use zero. This means that if your program has been
saved as TEST01, HELPER will look for DSK:TEST01.HLP
SUBTTL Calling sequence -- MATCH
MATCH checks to see if the command typed in by the user matches a
list of commands. It accepts valid abbreviations to commands.
CALL MATCH ('LIST,OF,COMMANDS,ETC',BUFFER,KOUNT,LENGTH,INDEX)
GOTO (100, 200, 300, 400) INDEX
CALL MATCH ('ONE111,TWO222',BUFFER,KOUNT,LENGTH,INDEX,DNAME)
GOTO ( 1000, 2000) INDEX
LIST = (INPUT) A list of commands in quotes, separated by commas. The
commands can be up to 6 letters and numbers each, no spaces.
BUFFER = (INPUT) The array with the command, usually read in by INCHWL.
= (OUTPUT) The array with the command removed, if there is a match.
KOUNT = (INPUT) The number of characters in BUFFER.
= (OUTPUT) The number of characters left in BUFFER.
LENGTH = (INPUT) The size of BUFFER.
INDEX = (OUTPUT) Small positive number if a match was found.
DNAME = (optional OUTPUT) The matched command is stored in this
DOUBLE PRECISION variable in an (A6) format.
If INDEX is returned as +1, it means that the command matched the 1st
one on the list, +2 for the second, etc. DNAME gets the full command,
even if it was abbreviated in the BUFFER.
INDEX= 0 means that BUFFER is all blanks.
INDEX=-1 means that the command in BUFFER does not match any on the list.
INDEX=-2 means that the command is ambiguous.
The MATCH routine always removes any leading spaces or tabs from BUFFER.
If a match was found, the command and the first space or tab is removed from
BUFFER. This is so that MATCH can be called with a second list to decode
any sub-commands.
SUBTTL Calling sequence -- Examples
CC This shows how to use SAVRUN
100 CALL INCHWL ('*', BUFFER, KOUNT, LENGHT, LASTC) ! Get command
CALL SAVRUN (-1, BUFFER, KOUNT, LENGTH, LASTC) ! Look at it
CALL MYPROG (BUFFER) ! Do your processing
IF (LASTC.EQ.26) CALL EXITGO ! Stop if we should
GOTO 100 ! Else loop
END
---------------------------------------------------------------------
CC This shows a complete program using the RUNLIB routines
CC This program understands only "STOP" and "CHAIN" (and /EXIT/HELP/RUN)
DIMENSION BUFFER(27) !135 characters
LENGTH=27 !Size of buffer in words
CCLNAM='ABC' !Prompt and name of file
CALL RESCAN (CCLNAM, BUFFER, KOUNT, LENGTH, LASTC) !Fill buffer
IF (KOUNT .GT. 0) GOTO 110 !Skip INCHWL if have command
100 CALL INCHWL (CCLNAM, BUFFER, KOUNT, LENGTH, LASTC) !Get another command
CC Here with a command, process it
110 CALL SAVRUN (-1, BUFFER, KOUNT, LENGTH, LASTC)
LEN = (KOUNT + 4) / 5 !Round up to next full word
TYPE 120, (BUFFER(JJ), JJ=1,LEN) !No trailing spaces
120 FORMAT (' You typed: ', 27A5)
CALL MATCH ('CHAIN,STOP',BUFFER,KOUNT,LENGTH,INDEX,DNAME)
IF (INDEX.GT.0) TYPE 130, DNAME
130 FORMAT (' The command was ', A6)
GOTO ( 200, 300 ) INDEX !Go of INDEX=1 or 2
IF (LASTC.EQ.26) CALL EXITGO !Stop on Control-Z or /EXIT
GOTO 100 !Loop until done
CC Here if we get a "CHAIN" command
200 CALL RUNUUO (IERR, BUFFER, KOUNT) !Run next program
TYPE 210, IERR, (BUFFER(JJ), JJ=1, LEN) !Type error message
210 FORMAT (' ?Error code ', O2, 3X, 27A5)
CALL EXIT0 !Return to the monitor, never to continue
CC Here if we get a "STOP" command
300 CALL EXITGO !Give /RUN a chance
END
SUBTTL Calling sequence -- Writing a FORTRAN program that compiles itself
PROGRAM TESTER
CC To run this program, do the following:
CC .COPY = FOR:TESTER.REL, F.FOR, RUNLIB.REL
CC .EXECUTE TESTER.REL, F.FOR, RUNLIB.REL
CC If you type in an illegal function, you must start over by:
CC .COPY = FOR:F.FOR
CC .EXECUTE
DIMENSION BUFFER(27) !135 characters
LENGTH=27 !Size of BUFFER
CALL RESCAN ('TST', BUFFER, KOUNT, -LENGTH, LASTC) !Check for F(X)
IF (KOUNT .GE. 0) GOTO 2000 !If first time thru
IWORDS = (KOUNT + 4) / 5 !Number of words
1000 TYPE 1010, (BUFFER(I), I=1,IWORDS) !Type the function
1010 FORMAT ('0The function is F(X) = ', 27A5)
TYPE 1015 !Ask for values
1015 FORMAT ('0What are XMIN, XMAX, and XINC? ',$)
ACCEPT 1020, XMIN, XMAX, XINC !Get parameters
1020 FORMAT (3G)
IF (XINC .EQ. 0.0) XINC = 1.0 !Default increment
TYPE 1030, (BUFFER(I), I=1,IWORDS) !Print heading
1030 FORMAT ('0 X', 14X, 27A5)
DO 1040 XX = XMIN, XMAX, XINC !Set up loop
X = XX !Prevents "Possible modification of index in loop"
Y = F(X) !Evaluate function
1040 TYPE 1020, X, Y !Show the values
CALL OUTSTR (0,Do you want more values? ',0)
IANS = JBINFO(20) ! Get single letter ans
IF (IANS .EQ. 'Y' .OR. IANS .EQ. 'y') GOTO 1000 !Lowercase too
CALL OUTSTR (0,' Do you want to try another function? ',0)
IANS = JBINFO(20) !Get answer
IF (IANS .EQ. 'Y' .OR. IANS .EQ. 'y') GOTO 2000 !Lowercase too
CALL EXITGO !Return to monitor
Continued on next page
Compiler program continued
CC Here to get a new function
CC Note that this section does not use any FORTRAN I/O to the TTY
2000 CALL OUTSTR (0, 'Type in the function; F(X) = ', 0) !Give prompt
CALL INCHWL (' ', BUFFER, KOUNT, LENGTH, LASTC) !Get reply
CALL SAVRUN (-1,BUFFER, KOUNT, LENGTH, LASTC) !Clean it up
IF (KOUNT .LE. 0) GOTO 2000 !Ask again
IF (LASCT.EQ.26) CALL EXITGO !Stop if /EXIT
IWORDS = (KOUNT + 4) / 5 !Number of words
OPEN (UNIT=1, DEVICE='DSK', FILE='F.FOR', ACCESS='SEQOUT')
WRITE (1,2010) (BUFFER(I), I=1,IWORDS) !Write the function
2010 FORMAT (' FUNCTION F(X)', /, ' F = ', 27A5)
WRITE (1,2030) !Finish it up
2030 FORMAT (' RETURN', /, ' END')
CLOSE (UNIT=1) !Finish the file
CALL TMPCOR ('TST', BUFFER, KOUNT) !Remember the function
CALL TMPCOR ('LNK', 'TESTER,F,RUNLIB/E/G', 19) !Message for LINK
CALL TMPCOR ('FOR', 'F=F/RUN:LINK/RUNOFF', 19) !Message for FORTRA
CALL RUNUUO (IERR, 'SYS:FORTRA', 10, 1) !Run the compiler
STOP '?Cannot run SYS:FORTRA'
END !Of TESTER
SUBTTL Appendix - Calling RUNLIB from MACRO programs
These routines preserve all accumulators.
Most routines have alternate entry names, so that MACRO programs can
avoid using names of monitor calls when referring to subroutines. The
alternate names start with a dollar-sign and have the first five
characters of the FORTRAN entry names. For instance, "$INCHW" is the
alternate name for "INCHWL" - a subroutine which does TTCALL's and more.
The MACRO calling sequences are:
L=16 ;Link to arg list
P=17 ;Push-down-list pointer
MOVEI L,TMPARG ;Args for TMPCOR
PUSHJ P,$TMPCO ;Call TMPCOR
MOVEI L,RUNARG ;Args for RUNUUO
PUSHJ P,$RUNUU ;Call RUNUUO
MOVEI L,CMDARG ;Args for RESCAN
PUSHJ P,$RESCA ;Call RESCAN
MOVEI L,CMDARG ;Same args for INCHWL
PUSHJ P,$INCHW ;Call INCHWL
MOVEI L,SAVARG ;Args for SAVRUN
PUSHJ P,$SAVRU ;Call SAVRUN (also known as CVT$$)
PUSHJ P,EXITGO ;No args for EXITGO
PUSHJ P,EXIT0 ;No args for EXIT0
PUSHJ P,EXIT1 ;No args for EXIT1
MOVE 1,[SIXBIT /NAME/] ;Put name in AC1
PUSHJ P,.HELPR ;Call HELPER
MOVEI L,OUTARG ;Args for OUTSTR
PUSHJ P,$OUTST ;Call OUTSTR
MOVEI L,MATARG ;Args for MATCH
PUSHJ P,$MATCH ;Call MATCH
;Example of argument blocks for MACRO routines
-3,,0 ;3 args for TMPCOR
TMPARG: NAME ;Addr of name of TMP file
BUFFER ;Starting addr of array for buffer
KOUNT ;Addr of integer for count
-3,,0 ;Or -4,,0 ;3 or 4 args for RUNUUO
RUNARG: IERR ;Addr to put error code
PRGNAM ;Start of program name in ASCII
KOUNT1 ;Addr of number of chars in PRGNAM
ICCL ;Optional addr of the run offset
-5,,0 ;5 args for RESCAN and INCHWL
CMDARG: NAME ;Addr of prompt text
BUFFER ;Start addr of array
KOUNT ;Addr of integer
LENGTH ;Addr of word containing size of BUFFER
LASTC ;Addr to store last character
-5,,0 ;5 args for SAVRUN
SAVARG: FLAG ;Addr of flag, bit 0 gets set (negative=.TRUE.)
BUFFER ;Starting addr of array
KOUNT ;Addr of integer, count of characters
LENGTH ;Addr of word containing size of BUFFER
LASTC ;Addr to store last character
-3,,0 ;3 args for OUTSTR
OUTARG: ICC ;Addr of carriage control
BUFFER ;Starting addr of array
KOUNT ;Addr of number of chars
-6,,0 ;6 args for MATCH (the last 1 is optional)
MATARG: [ASCIZ /LIST,OF,COMMANDS,SEPARATED,BY,COMMAS/]
BUFFER ;Array with command to be processed
KOUNT ;Addr of integer
LENGTH ;Addr of word containing size of BUFFER
INDEX ;Addr of integer for match
DNAME ;(optional) Addr of double-precision variable
NAME: ASCII /ABC / ;Prompt or name of TMP file
BUFFER: BLOCK BUFSIZ ;Array
KOUNT: BLOCK 1 ;Integer character count
LENGTH: BUFSIZ ;Word containing size of BUFFER
LASTC: BLOCK 1 ;Integer for last char, right justified
FLAG: -1 ;-1 to do everything
PRGNAM: ASCII /DSKB:TESTER.EXE[10,10]/ ;Name of program in ASCII
KOUNT1: ^D22 ;Number of characters in PRGNAM
IERR: BLOCK 1 ;Gets error code if RUNUUO fails
ICC: 0 ;0 for CRLF, -1 to suppress CRLF
ICCL: 1 ;Run-offset, 0 or 1
INDEX: BLOCK 1 ;Number denoting match
DNAME: BLOCK 2 ;Command name stored in A6 format
| ;End of comment
LIST
SUBTTL LOWSEG data area
IFDEF TOPSEG,< TWOSEG > ;Make these routines reentrant
RELOC 0 ;Put COMBUF in the LOWSEG
COMBUF: BLOCK CBUFSZ ;Temp buffer (TMPCOR in 701 is 510 words max)
CBUFND: BLOCK 1 ;Zero word at end of COMBUF for ASCIZ
CPOINT: BLOCK 1 ;Byte pointer into COMBUF
SAVECH: BLOCK 1 ;Left-over character from COMBUF
OLDBP: BLOCK 1 ;Old byte pointer
OLDC: BLOCK 1 ;Old byte count
CCLNAM: BLOCK 1 ;Name of DSK:nnnxxx.TMP file
CCLSIZ: BLOCK 1 ;Number of blocks in file, 0 at EOF
CCLBLK: BLOCK 1 ;Block to read into COMBUF next
TEMP20: BLOCK ^D20 ;COMCH - Place to save all ACs
;MATCH - Commands in SIXBIT
;SAVRUN - Used when expanding tabs
HLPPPN==TEMP20+0 ;HELPER - UFD program came from
HLPBFR==TEMP20+1 ;HELPER - Buffer header
HIDEV==TEMP20+0 ;RUNUUO - Data about old HISEG,
HINAM==HIDEV+1 ;RUNUUO - in case RUN uuo fails
HIPPN==HINAM+3 ;RUNUUO - ...
ERCODE==HIPPN+2 ;RUNUUO - Error code
JOBHRL==ERCODE+1 ;RUNUUO - Nonzero if HISEG present
SAVE0: BLOCK 1 ;Place to store AC0
SAVE1: BLOCK 17 ;Area to save AC1 through AC17
SAVEND=.-1 ;Last loc of save area
GOFSET: BLOCK 1 ;Run-offset, set by SAVRUN for EXITGO
GODEV: BLOCK 1 ;Device for EXITGO
GOPROG: BLOCK 5 ;Program to run
GOEND=.-1 ;End of BLT
PRGZER==. ;Start of area to zero, set by SCAN
PRGDEV: BLOCK 1 ;Device name
PRGNAM: BLOCK 1 ;Program name
PRGEXT: BLOCK 2 ; extension
PRGPPN: BLOCK 2 ;Directory and core assignment
PRGLST==.-1 ;End of area to zero
MYPPN: BLOCK 1 ;Default for [,]
SUBTTL Actual start of routines
IFDEF TOPSEG,< RELOC 400000 > ;Put code in HISEG
SUBTTL TMPCOR -- Write TEMP file
; CALL TMPCOR (NAME, BUFFER, KOUNT)
HELLO (TMPCOR) ;Set up entry point
PUSHJ P,GETNAM ;Get CCL name in left half of T1
SKIPG T2,@CNT(L) ;Get size of message
JRST RETURN ;Must have positive byte count
MOVNI T2,4(T2) ;Round up to next word, make negative
IDIVI T2,5 ;Make into a word count
MOVEI C,@BUF(L) ;Get addr of message
SUBI C,1 ;Form an IOWD
HRL C,T2 ; in C
MOVE T2,C ;Get the IOWD
MOVE T3,[.TCRWF,,T1] ;Write file, args start at T1
TMPCOR T3, ;Write message into TMPCOR
SKIPA ;TMPCOR failed, try DSK:
JRST RETURN ;File written OK, return from TMPCOR
;Here when TMPCOR UUO failed.
IFN FT603,< ;Since FOROTS doesn't use channel 0, we can use it temporarily
PUSHJ P,OPNDSK ;Open channel 0 in dump mode, set up T1-T4
ENTER %0,T1 ;Create the file
JRST RETURN ;We tried
OUTPUT %0,C ;Write the message
CLOSE %0, ;Finish the file
RELEAS %0, ;Done with channel 0
> ;End of IFN FT603
IFE FT603,<PRINTX ?The 701-only TMPCOR input has not been debugged, @TMPCOR>
;Return from TMPCOR
SUBTTL RETURN -- Return to main program
;Note: "JRST RETURN" works at any time, regardless of what is on the stack
RETURN: MOVE F,[SAVE1,,T1] ;Restore the AC's
BLT F,P ;This takes an extra instruction,
MOVE F,SAVE0 ; but always keeps P as a valid PDL pointer
POPJ P, ;Return to caller (using original PDL)
SUBTTL RUNUUO -- Run next program
; CALL RUNUUO (IERR, PRGNAM, KOUNT, ICCL)
HELLO (RUNUUO) ;Set up entry point
PUSHJ P,CLOSFL ;Close files, type CRLF if needed
SKIPG C,@CNT(L) ;Get count of chars in filespec
JRST RETURN ;No program to run
IFDEF TOPSEG,< ;The CORE UUO and RUN UUO must be in the LOWSEG
MOVE T1,[RUNIT,,COMBUF];Copy the routine into the LOWSEG
BLT T1,RUNEND ; ...
SETZM CPOINT ;Any data in COMBUF has been wiped out
> ;End of IFDEF TOPSEG
MOVEI BP,@BUF(L) ;Get addr of buffer
HRLI BP,(POINT 7,) ;Make into a byte pointer
MOVE T1,(BP) ;Get the first word
JUMPE T1,NOPROG ;First word can be spaces, but not null
PUSHJ P,FILENM ;Scan for file name
;If extension was given, try to LOOKUP the .EXE file
MOVE T1,PRGNAM ;Get the program name
JUMPE T1,NORUN ;File not found, error code 0
SKIPN T3,PRGDEV ;Get the PRGDEV
MOVSI T3,'DSK' ;None given, let user run his other programs
MOVEM T3,PRGDEV ;Default to DSK
SKIPN PRGEXT ;Was an extension given
JRST NOLOOK ;No, let the monitor track down the extension
;Since the RUN uuo will reset I/O channel 0, it is OK to use it here
SETZB T2,T4 ;ASCII mode, no buffers
OPEN %0,T2 ;Open a channel
JRST [MOVEI T1,ERNSD% ;No such device
JRST NOPROG ] ;Return error code
MOVE T2,PRGEXT ;Get the extension
SETZ T3, ;Make a 4 word LOOKUP block
MOVE T4,PRGPPN ;Look in the right directory
LOOKUP %0,T1 ;See if the EXE file is there
JRST [HRRZ T1,T2 ;Get error code
CAIE T1,ERPRT% ;Check for protection failure
JRST NOPROG ;No, give up
JRST NOLOOK] ;Yes, may be execute only
SUBTTL RUNUUO -- Prepare to go
NOLOOK: RELEAS %0, ;Undo the LOOKUP (and everything else)
MOVE T1,[-2,,.GTPPN] ;Get the directory the HISEG came from
GETTAB T1, ; ...
SETZ T1, ;Assume default directory
MOVEM T1,HIPPN ;Save it
MOVE T3,[-2,,.GTPRG] ;Get the name of the HISEG
GETTAB T3, ; ...
SETZ T3, ;No HISEG
MOVEM T3,HINAM ;Save it
MOVE T1,[-2,,.GTDEV] ;Get the device that the HISEG came from
GETTAB T1, ; ...
MOVSI T1,'DSK' ;Assume DSK
MOVEM T1,HIDEV ;Save it
HRRZ T1,.JBHRL## ;Get highest addr of HISEG
MOVEM T1,JOBHRL ;Save it to be tested later for nonzero
SETZ T2, ;Assume runoff of 0
HLRZ T1,-1(L) ;Get number of args
CAIGE T1,-LEN ;Is there a run-offset?
MOVE T2,@LEN(L) ;Yes, get it
IFDEF TOPSEG,<
JRST COMBUF ;Say bye-bye to this HISEG
RUNIT: PHASE COMBUF ;Assemble addresses for the LOWSEG
> ;End of IFDEF TOPSEG
MOVSI T1,1 ;1 in left half and 0 in right
CAMN T3,[SIXBIT/FOROTS/] ;Version 5A or earlier?
CORE T1, ; gets rid of the HISEG
JFCL ;Ignore error
MOVEI T1,PRGDEV ;Point to args
HRL T1,T2 ;Runoffset of 1 or 0
RUN T1, ;Call next program
;ERROR return
;The accumulators and all I/O channels have been blown
;Still in PHASE COMBUF
SUBTTL RUNUUO -- Error recovery
;If your HISEG was nonsharable and not FOROTS, you will die horribly!
;No problem if your HISEG was sharable.
MOVE T2,HINAM ;Get name of HISEG
CAME T2,[SIXBIT/FOROTS/] ;OK if version 5A or earlier,
JRST NOPROG ; do not play with FOROT6 or FOROT7
MOVE T2,JOBHRL ;Was there a HISEG?
JUMPE T2,NOPROG ;No, don't even try a GETSEG
MOVEM T1,ERCODE ;Save the error code
MOVEI T1,HIDEV ;Point to HISEG args
GETSEG T1, ;Restore HISEG
SKIPA ;Error
JRST GOTSEG ;Success
OUTSTR TMPCRH ;GETSEG failed
MOVEI T1,FOROTS ;This is a FORTRAN callable routine
GETSEG T1, ; so try for FOROTS
OUTSTR TMPNOT ;"not "
OUTSTR TMPFOR ;"set up"
GOTSEG: MOVE T1,ERCODE ;Get error code
NOPROG: RELEAS %0, ;Reset the I/O channel
NORUN: MOVE L,SAVE0+L ;Restore AC16
MOVEM T1,@COD(L) ;Return error code
MOVSI P,SAVE1 ;Source addr
HRRI P,T1 ;Dest addr
BLT P,P ;Restore the AC's, especially P
POPJ P, ;Return to caller
;Remember, this routine expects a sharable HISEG
.DIRECTIVE FLBLST ;List only first line of binary
TMPCRH: ASCIZ /%TMPCRH cannot restore HISEG
%TMPFOR FOROTS is /
TMPNOT: ASCIZ /not /
TMPFOR: ASCIZ /set up
/
FOROTS: SIXBIT /SYS/ ;In case we can't get the original HISEG back
SIXBIT /FOROTS/
EXP 0,0,0,0 ;Must have 4 zeros
IFDEF TOPSEG,<
RUNEND=.-1 ;End of BLT
DEPHASE ;End of PHASE COMBUF
IFG <RUNEND-COMBUF>-CBUFSZ,<PRINTX ?COMBUF is not big enough for RUNIT code>
> ;End of IFDEF TOPSEG
SUBTTL INCHWL -- Give prompt and input a full line from TTY
; CALL INCHWL (NAME, BUFFER, KOUNT, LENGTH, LASTC)
HELLO (INCHWL) ;Set up entry point
SKIPE CPOINT ;CCL file already in COMBUF?
JRST INCHW0 ;Yes, go get it
PUSHJ P,PROMPT ;Output prompt if necessary
PUSHJ P,REDTTY ;Get a line from the terminal into COMBUF
;Here when a command is in COMBUF.
INCHW0: PUSHJ P,CLRBUF ;Clear BUFFER, KOUNT, LASTC, set up C and BP
;Copy one line from COMBUF to BUFFER
INCHW1: PUSHJ P,COMCH ;Get a char from COMBUF
JRST INCHW2 ;End of line
SOJL C,INCHW1 ;Look for end of line if BUFFER is full
IDPB CH,BP ;Put in user's buffer
AOS @CNT(L) ;Count this char
JRST INCHW1 ;Loop till end of line
;Here at when one line from COMBUF has been transfered to the caller
INCHW2: MOVEM CH,@CHR(L) ;Return the end-of-line char in LASTC
SKIPN CCLNAM ;If not reading CCL file,
SETZM CPOINT ; COMBUF is now empty
JUMPN CH,RETURN ;Return if not end of CCL file
;Here at end of CCL file. If it did not end with a linefeed, set LASTC=0
;and return real EOF next time.
SKIPN @CNT(L) ;If nothing in BUFFER at EOF,
JRST [SETOM @CNT(L) ; show EOF by KOUNT=-1
MOVEI CH,CZ ; and by LASTC=26
MOVEM CH,@CHR(L); (Control-Z is EOF from terminal)
JRST RETURN ] ;CPOINT is zero, so INCHWL will prompt
MOVE T1,[POINT 7,CBUFND] ;Point to 5 nulls at end of CBUF
MOVEM T1,CPOINT ;Set up to recognize EOF next time
JRST RETURN ;Return with KOUNT#0 and LASTC=0
SUBTTL INCHWL -- Prompt the user
PROMPT: SKIPE T1,@NAM(L) ;Get the prompt
CAMN T1,BLANKS ;Is it all blanks?
POPJ P, ;Yes, punt the prompt
PUSHJ P,TCRLF ;Type CRLF if needed
PUSHJ P,GETNAM ;Convert prompt to SIXBIT in T1 <
HRRI T1,'> ' ;Make a prompt
MOVE T2,[POINT 6,T1] ;SIXBIT in T1
MOVEI T3,5 ;3 + bracket + space
PROMP1: ILDB CH,T2 ;Get a char
ADDI CH,SP ;Convert to ASCII
OUTCHR CH ;Type it
TLNE T1,007777 ;Don't loop if single char prompt
SOJG T3,PROMP1 ;Loop
POPJ P, ;Return from PROMPT
;Routine to output CRLF if not at left margin already, and cancel Control-O
TCRLF: PJOB T2, ;Get job number
TRMNO. T2, ;Now the TTY UDX
JRST TCRLF3 ;If detached, go into 'TO' wait state
MOVEI T1,.TOSOP ;Skip if output in progress
TCRLF1: MOVE T3,[2,,T1] ;2 args starting in T1
TRMOP. T3, ;Is output buffer empty?
JRST TCRLF2 ;Yes
MOVEI T3,^D250 ;No, wait a quarter second
HIBER T3, ;ZZZ
JRST TCRLF2 ;Cannot fail
JRST TCRLF1 ;Check now
;Cancel Control-O
TCRLF2: IFN FT701,< ;Watch out for deferred echo
MOVEI T1,.TOOSU+.TOSET;Change output suppression (.TOOSU==1045)
MOVEI T3,0 ;Clear the bit
MOVE T4,[3,,T1] ;Point to args
TRMOP. T4, ;Clear Control-O without starting deferred echo
> ;End of IFN FT701
SKPINL ;Do it the 6.03 way
JFCL
;Type CRLF if not already at left margin
MOVE T3,[2,,T1] ;2 args starting in T1
MOVEI T1,.TOHPS ;To read horizontal position
TRMOP. T3, ;Read position
MOVEI T3,0 ;Should not happen
SKIPE T3 ;Position zero is left margin
TCRLF3: OUTSTR CRLF ;Send <CR><LF>
POPJ P, ;Return from TCRLF
SUBTTL RESCAN -- Check monitor line, TMPCOR or DSK:nnnPRG.TMP
; CALL RESCAN (NAME, BUFFER, KOUNT, LENGTH, LASTC)
HELLO (RESCAN) ;Set up entry point
PUSHJ P,CLRBUF ;Clear BUFFER, KOUNT, and LASTC
SETZB C,CCLNAM ;Clear CCL file flag and byte count
SKIPGE @LEN(L) ;Negative size means
JRST REDBIN ; to read in binary mode
PUSHJ P,RSCAN ;Try rescanning the command line
JUMPN C,INCHW0 ;Jump to INCHWL code if something there
PUSHJ P,REDTMP ;Try reading TMPCOR
MOVEM C,CCLNAM ;Make nonzero if anything there
JUMPN C,RESCA1 ;Set KOUNT to -1 for TMPCOR CCL file
PUSHJ P,READSK ;Try reading DSK:nnnXXX.TMP, success sets CCLNAM
SKIPN C ;If nothing was found,
SETZM CPOINT ; clear the pointer so INCHWL will prompt
JUMPE C,RETURN ;Leave KOUNT zero if no command anywhere
SOS @CNT(L) ;Set KOUNT to -2 for disk CCL file
;Here if CCL file was found. Tell user to call INCHWL to read command file
;one line at a time.
RESCA1: SOS @CNT(L) ;Set KOUNT negative to signify CCL input
JRST RETURN ;Return from RESCAN
SUBTTL RESCAN -- Read binary data when LENGTH is negative
;Here to read binary file, data goes directly into BUFFER.
REDBIN: PUSHJ P,GETNAM ;Get CCL name in T1
MOVEI T2,@BUF(L) ;Get addr of buffer
SUBI T2,1 ;IOWDs need addr-1
HRL T2,@LEN(L) ;Get negative word length
MOVE C,[.TCRDF,,T1] ;Read and delete file, args in T1
TMPCOR C, ;Try to input file
PUSHJ P,DSKBIN ;Not there, try disk
IMULI C,5 ;Convert words to bytes
MOVEM C,@CNT(L) ;Tell user the byte count
JRST RETURN ;Let user decode binary data
DSKBIN: MOVE C,T2 ;Save the IOWD
PUSHJ P,OPNDSK ;Open %0 to DSK in dump mode
IFE FT603,<PRINTX ?The 701-only binary input has not been debugged, @DSKBIN>
LOOKUP %0,T1 ;Read the file
TDZA T4,T4 ;Pretend it's 0 words long
INPUT %0,C ;Read data into BUFFER
RELEAS %0, ;Done with channel
HLRE C,T4 ;Get negative length in words
MOVMS C ;Positive word count
POPJ P, ;Tell user and return
SUBTTL RESCAN -- Do RESCAN uuo
;Check for ".PROGRAM COMMAND", ".RUN PROGRAM-COMMAND" or ".RU PROGRAM(COMMAND)"
;Remove matching close parenthesis
RSCAN: SETZB C,CCLSIZ ;In case this fails, and don't read old CCL file
MOVEI C2,0 ;Clear parenthesis counter
RESCAN 1 ;Is there a rescannable line?
SKPINL ;Yes, is it really there?
POPJ P, ;No, return with C=0
PUSHJ P,REDTTY ;Read a line from terminal into COMBUF
MOVE BP,CPOINT ;Set to read from COMBUF
MOVEI C,CBUFS5 ;Set byte count very high
PUSHJ P,GETWRD ;Get first word into T1, ignoring leading blanks
MOVEM CH,SAVECH ;Save terminator for later
MOVEM BP,CPOINT ;Update pointer
HRROI T2,.GTPRG ;Get the name
GETTAB T2, ; of this program
MOVSI T2,'???' ;Can never happen
MOVEM T2,PRGNAM ;Save for a while
HRROI T2,PRGNAM ;MOVE T2,[-1,,PRGNAM]
PUSHJ P,TSTABR ;Test for match
SKIPA ;No match
JRST RSCAN2 ;It matches, get rid of leading spaces
MOVE T2,[-2,,[SIXBIT /RUN/
SIXBIT /START/]]
PUSHJ P,TSTABR ;See if it matches
JRST RSCAN4 ;No, return with C=0
;Here when the monitor command was ".RUN" or ".START"
RSCAN1: PUSHJ P,COMCH ;Get a char from COMBUF
JRST RSCAN4 ;End of line already, no command
CAIN CH,"-" ;Hypen?
JRST RSCAN2 ;Yes, command follows
CAIE CH,"(" ;Or open paren?
JRST RSCAN1 ;No, keep looking
MOVEI C2,1 ;1 unmatched parenthisis
;Here at start of command. Remove leading blanks
RSCAN2: MOVE BP,CPOINT ;Save pointer to start of command
PUSHJ P,COMCH ;Get a char from COMBUF using CPOINT
JRST RSCAN4 ;End of line already, no command
CAIE CH,SP ;Space?
CAIN CH,TAB ; or tab?
JRST RSCAN2 ;Yes, ignore it
JUMPE C2,RSCANX ;Return with C nonzero
;Here if started by open paren, search for matching close paren
RSCAN3: CAIN CH,"(" ;Open paren?
ADDI C2,1 ;Yes, count it
CAIN CH,")" ;Close paren?
SOJE C2,RSCANP ;Yes, decrement count, stop at end
PUSHJ P,COMCH ;Keep looking for matching close paren
JRST RSCANX ;End of line is good enough
JRST RSCAN3 ;Keep looking
;Found matching close paren
RSCANP: MOVEI CH,LF ;Get a linefeed
DPB CH,CPOINT ;Store on top of close paren
;Remember pointer to good command
RSCANX: MOVEM BP,CPOINT ;Reset CPOINT to start of command
JRST RSCAN5 ;Return success
;Here when no command was found
RSCAN4: TDZA C,C ;C=0 to signify failure
RSCAN5: MOVEI C,1 ;Set C nonzero
POPJ P, ;Return from RSCAN
SUBTTL HELPER -- Subroutine to output HLP:xxxxxx.HLP
; This code was taken from HELPER.MAC %5(41).
;Because HELPER is called from user programs, first LOOKUP the help file
;in the same area that the program came from, then try HLP:.
ENTRY .HELPR ;Entry point for MACRO
.HELPR: MOVEM F,SAVE0 ;Save the AC's
MOVE F,[T1,,SAVE1] ; (Clear flags)
BLT F,SAVEND
JRST HLP0 ;Name must already be in T1
; CALL HELPER (0)
HELLO (HELPER) ;Set up entry point
MOVE T1,@NAM(L) ;Fetch first arg
HLP0: PUSHJ P,HLP ;Do the dirty work
JRST RETURN ;Restore ACs and return
;Output help file whose SIXBIT name is in T1.
;Uses T1-T4
HLP: OUTSTR CRLF ;Start a new line
PUSH P,.JBFF## ;Save .JBFF
HRROI T2,.GTPRG ;Get the program name
GETTAB T2, ; ...
MOVE T2,['HELP '] ;Should never happen
SKIPN T1 ;Do we have an arg?
MOVE T1,T2 ;No, use the name of this program
HRROI T3,.GTRDV ;Get the device this program came from
GETTAB T3, ; ...
MOVEI T3,0 ;FILDAE not implemented
SKIPN T3 ;See if we got a real device name
MOVSI T3,'DSK' ;Try the user's area
HRROI T4,.GTRDI ;Get directory program was run from
GETTAB T4, ; ...
SETZ T4, ;FILDAE not implemented
HLPUSR: MOVEI T2,.IOASC ;ASCII mode (device in T3)
MOVEM T4,HLPPPN ;Save PPN for a while
MOVEI T4,HLPBFR ;Buffer header, input only
IFE FT603,<PRINTX ?The 701-only HELP input has not been debugged, @HLPUSR>
OPEN %0,T2 ;INIT device
JRST HLPHLP ;Only if DSKU: was dismounted
MOVSI T2,'HLP' ;Extension
SETZ T3, ;Clean LOOKUP block
MOVE T4,HLPPPN ;PPN
LOOKUP %0,T1 ;Find file
SKIPA ;Not there
JRST HLPMOR ;Go read file
HLPHLP: MOVSI T3,'HLP' ;File not found on DSK:,
MOVE T4,HLPPPN ;Get PPN used in LOOKUP (T4 may have 2,,5)
TDZE T4,T4 ;Clear it, if non-zero,
JRST HLPUSR ; try HLP:[0,0]
OUTSTR [ASCIZ /%HLRCFF Cannot find help file, sorry/]
JRST HLPDON ;Been here twice now, give up
HLPMOR: IN %0, ;Read a buffer
JRST HLPGCH ;Get a char
;Treat any I/O error as EOF
HLPDON: OUTSTR CRLF ;Finish the line
RELEAS %0,
POP P,.JBFF## ;Restore .JBFF
POPJ P, ;Return from HLP section of HELPER
HLPGCH: SOSGE T2,HLPBFR+2 ;Decrement count of chars in buffer
JRST HLPMOR ;Get another buffer
ILDB T1,HLPBFR+1 ;Get next char
OUTCHR T1 ;Type it
JRST HLPGCH ;Do all chars in buffer
SUBTTL EXITGO -- Return to the monitor
ENTRY EXIT0, EXIT1, EXITGO
SIXBIT /EXIT0/
EXIT0: EXIT ;Cannot continue
SIXBIT /EXIT1/
EXIT1: EXIT 1, ;Quiet return to monitor
POPJ P, ;In case of continue
SIXBIT /EXITGO/
EXITGO: PUSHJ P,CLOSFL ;Close files, type CRLF if needed
IFDEF TOPSEG,< ;Put the routine in the LOWSEG
MOVE T1,[EXITG2,,COMBUF]
BLT T1,COMBUF+<EXITG3-RUNIT2>
> ;End of IFDEF TOPSEG
SKIPN GOPROG ;Is there a program to run?
JRST EXIT2 ;No, exit to monitor
SKIPN T1,GODEV ;Get the device
MOVSI T1,'SYS' ;The default is SYS
MOVEM T1,GODEV ;Put device back
IFDEF TOPSEG,<
JRST COMBUF ;Go to it
EXITG2: PHASE COMBUF ;This routine gets BLT'ed down
> ;End of IFDEF TOPSEG
RUNIT2: MOVSI T1,1 ;1 in the left half and 0 in the right
CORE T1, ;Gets rid of our HISEG
JFCL ;Ignore the error
MOVEI T1,GODEV ;Point to saved program name
HRL T1,GOFSET ;Runoffset of 1 or 0
RUN T1, ;Exit to this program
;In case of error, stop
EXIT2: EXIT 1, ;Return to monitor
EXITG3: EXIT ;Cannot continue
IFDEF TOPSEG,< DEPHASE > ;End of RUNIT2 routine
SUBTTL EXITGO -- Close any open channels
CLOSFL: PUSHJ P,TCRLF ;Type CRLF if not at margin
MOVSI T3,-17 ;Check all 17 channels in order
CLOSF1: MOVEI T2,(T3) ;Copy channel number
DEVNAM T2, ;See if this channel is open
JRST CLOSF3 ;Not open
OUTSTR [ASCIZ /%EXITGO Channel /]
MOVEI T1,(T3) ;Copy channel number
TRZE T1,10 ;2 digits?
OUTCHR ["1"] ;Yes
ADDI T1,"0" ;Convert to ASCII
OUTCHR T1 ;Type it
OUTSTR [ASCIZ / open to /]
CLOSF2: SETZ T1, ;Clear junk
LSHC T1,6 ;Get a byte
ADDI T1,SP ;Convert to ASCII
OUTCHR T1 ;Type it
JUMPN T2,CLOSF2 ;Loop
OUTSTR [ASCIZ /: closed
/]
HRLZ T1,T3 ;Copy channel number
LSH T1,5 ;Put in the accumulator field
TLO T1,(RELEAS 0,) ;Make UUO
XCT T1 ;Release the channel
CLOSF3: AOBJN T3,CLOSF1 ;Loop for all channels
POPJ P, ;Return from CLOSEF
SUBTTL OUTSTR -- Output a string on the TTY
; CALL OUTSTR (ICC, BUFFER, KOUNT)
HELLO (OUTSTR) ;Set up entry point
MOVEI BP,@BUF(L) ;Get starting addr
HRLI BP,(POINT 7,) ;Make into byte pointer
SKIPGE @COD(L) ;Is carriage control code negative?
OUTCHR [FF] ;Yes, output formfeed first
MOVE C,@CNT(L) ;Get length of string
SOJGE C,OUTST0 ;If non-zero, force ASCIZ first
OUTSTR (BP) ;Otherwise, assume ASCIZ literal
JRST OUTST1 ;Finish up
OUTST0: IDIVI C,5 ;Get number of words
ADDI C,(BP) ;Get addr of last word
SETZB T1,T2 ;2 zero words
EXCH T1,(C) ;Force ASCIZ at end of array
OUTSTR (BP) ;Output first part
OUTSTR T1 ;And last part
EXCH T1,(C) ;Restore original data
OUTST1: SKIPE T1,@COD(L) ;Get the carriage control
CAMN T1,[-2] ;0 or -2?
JRST RETURN ;Yes, no CRLFs
MOVMS T1 ;Get absolute value
OUTSTR CRLF ;Type a CRLF
SOJG T1,.-1 ;Do as many as requested
JRST RETURN ;Return from OUTSTR
SUBTTL JBINFO -- Return info about the job
; IVALUE = JBINFO(ICODE)
HELLO (JBINFO) ;Set up entry point
MOVSI T1,-CODLEN ;Make AOBJN pointer
JBINF1: HRRZ T2,CODTAB(T1) ;Get dispatch address
HLRE T3,CODTAB(T1) ;Get code from table
CAMN T3,@COD(L) ;Match?
JRST (T2) ;Yes
AOBJN T1,JBINF1 ;No, keep trying
;Here if no match, do a GETTAB with [-1,,CODE]
HRRO T1,@COD(L) ;Get GETTAB table number, this job
GETTAB T1, ;Get info from monitor table
MOVEI T1,0 ;Reasonable default
RETUR0: MOVEM T1,SAVE0 ;Function value will be returned in AC0
JRST RETURN ;Return from JBINFO
;Some GETTAB values are worthless to FORTRAN programs, return something useful
CODTAB: ^D0,,GSWITC ;Get value of switches on KA or KI (usually 0)
^D1,,GPJOB ;Job number
;2=PPN, 3=Program name, 4=Runtime, 5=KCS, 6=Priv bits
^D7,,GSLEEP ;Sleep for 1 second
^D8,,GTLCH ;Terminal number and characteristics
^D9,,GDATE ;Date in 15 bit format
^D10,,GMSTIM ;Time in milliseconds
^D11,,GUDT ;Universal date/time
^D12,,GWEEKD ;Day of week, 1=Sunday, 7=Saturday
^D19,,GSKPIN ;Return 1 if char of typeahead, 2 if whole line
^D20,,GINCHA ;Input one character in A1 format
^D21,,GINCHW ;Input one character
^D24,,GNAME0 ;Get first 5 letters of user name
^D25,,GNAME1 ;Get next 5 letters of user name
^D26,,GNAME2 ;Get last 2 letters, padded with 3 blanks
CODLEN==.-CODTAB ;Length of this table
GSWITC: SWITCH T1, ;(0) Read console switches (usually zero)
JRST RETUR0 ;Store value
GUDT: MOVE T1,[%CNDTM] ;(11) Get universal date time
GETTAB T1, ;This always skips
GPJOB: PJOB T1, ;(1) Get job number
JRST RETUR0 ;Store value
GSLEEP: MOVEI T1,1 ;(7) Sleep for 1 second
SLEEP T1, ;ZZZ
JRST RETUR0 ;Store 1 as value
GTLCH: SETO T1, ;(8) Indicate this line
GETLCH T1, ;Get terminal number and line characteristics
JRST RETUR0 ;Store value
GDATE: DATE T1, ;(9) Get date in 15 bit format
JRST RETUR0 ;Store value
GMSTIM: MSTIME T1, ;(10) Get time of day, milliseconds past midnite
JRST RETUR0 ;Store value
GWEEKD: MOVE T1,[%CNDTM] ;(12) Get universal date/time
GETTAB T1, ; ...
MOVEI T1,0 ;Can never happen
HLRZS T1 ;Put date portion in right half
IDIVI T1,7 ;Get weekday in T2
HRREI T1,-3(T2) ;T1=1 if its Sunday
SKIPG T1 ;If Wed, Thu, Fri, or Sat,
ADDI T1,7 ;Make Wed=4, Sat=7
JRST RETUR0 ;Store value
GSKPIN: MOVEI T1,2 ;(19) Assume a whole line has been typed in
SKPINC ;Partial line input?
MOVEI T1,1 ;No, SKPINL will not skip either, T1=0
SKPINL ;Entire line?
SUBI T1,1 ;No, T1=0 if no input, =1 if partial line
JRST RETUR0 ;Store value
GINCHA: INCHRW T1 ;(20) Input a single character
LSH T1,^D29 ;Shift over
IOR T1,[BYTE (7) 0,SP,SP,SP,SP] ;Add 4 spaces
JRST RETUR0 ;Return character in A1 format
GINCHW: INCHRW T1 ;(21) Input char, wait char mode
JRST RETUR0 ;Store value
;JBINFO continued
GNAME0: HRROI T1,.GTNM1 ;(24) Get first 5 letters of user name
GETTAB T1, ;Get 6 SIXBIT bytes
MOVSI T1,'???' ;Can never fail
JRST GNAME3 ;Convert to ASCII
GNAME1: HRROI T1,.GTNM1 ;(25) Get next 5 letters of user name
GETTAB T1, ;Get 6th byte
MOVEI T1,'???' ;Can never fail
HRROI T2,.GTNM2 ;Get next 4
GETTAB T2, ; from second word
MOVSI T2,'???' ;Can never fail
LSHC T1,5*6 ;Left justify wanted bytes in T1
JRST GNAME3 ;Convert to ASCII
GNAME2: HRROI T1,.GTNM2 ;(26) Get last 2 letters of user name
GETTAB T1, ;Get 11th and 12th bytes
MOVEI T1,'???' ;Can never fail
LSH T1,4*6 ;2 bytes plus 4 blanks
GNAME3: MOVE T3,[POINT 7,SAVE0] ;Where to store results
SETZM SAVE0 ;Clear bit 35
GNAME4: SETZ T2, ;Clear junk
ROTC T1,6 ;Put byte in T2
ADDI T2," "-' ' ;Convert to ASCII
IDPB T2,T3 ;Store in SAVE0
TLNE T3,760000 ;If byte pointer is not exhausted,
JRST GNAME4 ; loop for all 5
JRST RETURN ;Restore AC0 and return
SUBTTL SAVRUN -- Save the /RUN switch and clean up buffer
; CALL SAVRUN (IOPT, BUFFER, KOUNT, LENGTH, LASTC)
;IOPT 1=/RUN, 2=;Comment, 4=No CTRL, 8=Leading SP, 16=Reduce SP
; 32=Upper case, 64=Brackets, 128=Expand tabs
CVT$$==SAVRUN ;For all you PDP-11 RSTS freaks
HELLO (SAVRUN) ;Set up entry point
MOVM T1,@LEN(L) ;Get the length of the buffer
JUMPE T1,RETURN ;Punt if nothing there
SETZB C2,GOFSET ;Zero the output char count, no /RUNOFF
IMULI T1,5 ;Get max possible char count
MOVEI BP,@BUF(L) ;Get addr of buffer
HRLI BP,(POINT 7,) ;Make into byte pointer
MOVE T4,BP ;Copy to make an output byte pointer
MOVE C,@CNT(L) ;Get the character count
SETZM @CNT(L) ;Zero it for now (in case of all blanks)
CAMLE C,T1 ;Do KOUNT and LENGTH agree?
MOVE C,T1 ;No, KOUNT was too big, use LENGTH*5
MOVE F,@COD(L) ;Get the IOPT code
TRNN F,F.ALL ;Any bits set?
MOVEI F,F.ALL ;No, do everything
ANDI F,F.ALL ;Set only the defined bits
TRNE F,F.LSP ;Ignore leading spaces?
TRO F,F.SP ;Yes
TRNE F,F.SSP ;Convert to single spaces?
TRZ F,F.TAB ;Yes, don't expand tabs
TRNN F,F.TAB ;Expanding tabs?
JRST RUNLOP ;No
HRRI T4,TEMP20 ;Yes, do conversion in 2 steps. First copy to
CAILE C,^D20*5 ; to TEMP20, then back to BUFFER
MOVEI C,^D20*5 ;Can only do 100 chars this way
;Use BP and C to read from BUFFER, use T4 and C2 to write back into it
RUNLOP: SOJL C,ENDBUF ;Stop at end of buffer
ILDB CH,BP ;Get a character
RUNLP0: CAIN CH,CZ ;Control-Z?
JRST [TRO F,F.CZ ;Yes, remember that fact
JRST RUNLOP ] ;Skip over the char
CAIN CH,"""" ;Double quote?
TRC F,F.QUO ;Yes, toggle flag
TRNE F,F.QUO ;Inside quotes?
JRST OK.QUO ;Yes, don't convert anything
CAIE CH,TAB ;Tab?
TRNN F,F.CTL ;No, suppressing control chars?
JRST OK.CTL ;Let this one go
CAIGE CH,SP ;Control char?
JRST RUNLOP ;Yes, ignore it
OK.CTL: TRNN F,F.LSP!F.SSP ;Leading spaces or single space?
JRST OK.LSP ;No
CAIN CH,TAB ;Yes, convert tabs
MOVEI CH,SP ; to spaces
CAIE CH,SP ;Is this a space?
JRST OK.LSP ;No, clear space flag
TROE F,F.SP ;Yes, set space flag, skip if was off
JRST RUNLOP ;Second or later space, ignore it
SKIPA ;Keep the space flag set
OK.LSP: TRZ F,F.SP!F.LSP ;Clear space flags
TRNN F,F.RUN ;Searching for @ or /RUN?
JRST OK.RUN ;No
CAIN CH,"/" ;Search for a slash
PUSHJ P,GETSWT ;Get switch value, skip if known
JRST OK.RUN ;Not a known switch
JRST RUNLP0 ;Check terminator, may be another "/"
OK.RUN: TRNN F,F.COM ;Ignore comments?
JRST OK.COM ;No
CAIE CH,"!" ;Comment
CAIN CH,";" ; ...
JRST ENDBUF ;Yes, ignore what follows
OK.COM: TRNN F,F.UC ;Doing upper case conversion?
JRST OK.UC ;No
CAILE CH,"_" ;Upper case?
SUBI CH,40 ;No, make it so
OK.UC: CAIE CH,"<" ;Angle brackets?
CAIN CH,">" ; ...
TRNN F,F.BRK ;Yes, converting them?
JRST OK.BRK ;Don't convert
ADDI CH,"["-"<" ;> Convert < to [ and > to ]
OK.BRK:
OK.QUO: IDPB CH,T4 ;Put the character back
ADDI C2,1 ;Increment output byte count
CAIE CH,SP ;If not a trailing space,
MOVEM C2,@CNT(L) ; remember the KOUNT
JRST RUNLOP ;Process rest of input buffer
SUBTTL SAVRUN -- Look for /RUN/RUNOFF/HELP/EXIT
GETSWT: MOVEM BP,OLDBP ;Save input pointer
MOVEM C,OLDC ;Save count
PUSHJ P,GETWRD ;Get the switch
MOVE T2,[-4,,[SIXBIT /RUN/
SIXBIT /RUNOFF/
SIXBIT /HELP/
SIXBIT /EXIT/]]
AOS (P) ;Set for success
PUSHJ P,TSTABR ;Test for abbreviation
JRST UNKSWT ;Not recognized
JRST @[EXP RUNSWT,OFFSWT,HLPSWT,EXISWT](T2) ;Go to it
;Unknown switch, reset pointers
UNKSWT: MOVE BP,OLDBP ;Restore pointer
MOVE C,OLDC ; and byte count
LDB CH,BP ;Re-get the slash at start of switch
SOS (P) ;Unknown or bad /RUN switch
POPJ P, ;Error return from GETSWT
;/RUN:PROGRAM - get file name
RUNSWT: CAIE CH,":" ;Did it end with a colon?
JRST UNKSWT ;No, ignore it
PUSHJ P,FILENM ;Evaluate the program name
MOVE T1,[PRGDEV,,GODEV];Copy into our area
BLT T1,GOEND ; ...
SETZ T1, ;In case no program
SKIPE GOPROG ;If there was a name,
EXISWT: TRO F,F.CZ ;Set the Control-Z flag
POPJ P, ;Keep searching for other switches
OFFSWT: MOVEI T1,1 ;Default value
CAIN CH,":" ;Value to follow?
PUSHJ P,GETWRD ;Yes, get first digit
ANDI T1,7 ;0 to 7
MOVEM T1,GOFSET ;Save the runoffset
POPJ P, ;Now see what's in CH
HLPSWT: SETZ T1, ;Use name of program
PUSH P,T4 ;.HELPR uses T1-T4
PUSHJ P,HLP ;Read the file
POP P,T4 ;Restore output byte pointer
POP P, ;Examine the delimiter in CH
SUBTTL SAVRUN -- Fix up the buffer
ENDBUF: MOVE CH,@CHR(L) ;Get the last character
CAIN CH,CZ ;Is it a Control-Z?
TRO F,F.CZ ;Yes, flag the fact
MOVEI CH,CZ ;Get the Control-Z character
TRZE F,F.CZ ;Is the flag set? (via /EXIT or /RUN)
MOVEM CH,@CHR(L) ;Yes, set LASTC
MOVM C,@LEN(L) ;Get size of BUFFER
IMULI C,5 ;Total byte count
CAML C2,C ;Is the buffer full after conversion?
JRST ENDBF2 ;Yes, every single char is nonblank
MOVEI CH,SP ;Get a space
ENDBF1: IDPB CH,T4 ;Store in buffer
CAMGE C2,C ;Finished?
AOJA C2,ENDBF1 ;No
ENDBF2: MOVEI BP,@BUF(L) ;Addr of array
HRLI BP,(POINT 7,) ;Make into output pointer
TRZN F,F.TAB ;Expanding tabs?
JRST ENDBF7 ;No
MOVE T4,BP ;Output pointer
MOVE BP,[POINT 7,TEMP20] ;Input pointer
MOVE C,@CNT ;Get byte count
MOVN C2,C ;Negate it
HRLZS C2 ;Make AOBJN pointer
ENDBF3: SOJL C,ENDBF6 ;Stop at end of TEMP20
ILDB CH,BP ;Get a char
CAIE CH,TAB ;Control-I?
JRST ENDBF5 ;No
MOVEI CH,SP ;Yes, convert to space
ENDBF4: AOBJP C2,ENDBF6 ;Increment count
IDPB CH,T4 ;Store in BUFFER
TRNE C2,7 ;At a tab stop?
JRST ENDBF4 ;No
JRST ENDBF3 ;Yes, get next char
ENDBF5: AOBJP C2,ENDBF6 ;Test for buffer overflow
IDPB CH,T4 ;Store in buffer
JRST ENDBF3 ;Loop
ENDBF6: HRRZM C2,@CNT(L) ;Store expanded KOUNT
ENDBF7: TRZN F,F.RUN ;Looking for @?
JRST RETURN ;No
MOVEI BP,@BUF(L) ;BP may have been trashed by ENDBF3
HRLI BP,(POINT 7,) ;Make into output pointer
ILDB CH,BP ;Get first char
CAIE CH,"@" ;At sign?
JRST RETURN ;No
SUBI C,1 ;Yes, decrement byte count
PUSHJ P,FILENM ;Get the file name
OUTSTR [ASCIZ /% @-indirect not yet finished
/]
;Open the specified file, and read 4 blocks into COMBUF, copy first
;line into BUFFER, and go through SAVRUN cleanup again
JRST RETURN ;Return from SAVRUN
SUBTTL MATCH -- Check if command matches list
; CALL MATCH ('LIST,OF,COMMANDS,ETC',BUFFER,KOUNT,LENGTH,INDEX,DNAME)
; GOTO ( 100, 200, 300, 400 ) INDEX
HELLO (MATCH)
MOVEI BP,@NAM(L) ;Get addr of list of command names
HRLI BP,(POINT 7,) ;Make into byte pointer
MATCH0: MOVEI C,CBUFS5 ;Set byte count very high
SETZM OLDBP ;Clear old pointer
MOVSI C2,-^D20 ;AOBJN pointer into TEMP20
MATCH1: PUSHJ P,GETWRD ;Get SIXBIT word in T1
MOVEM T1,TEMP20(C2) ;Store
CAIN CH,"," ;Comma?
AOBJN C2,MATCH1 ;Yes, get another (up to 20)
SKIPL C2 ;More than 20 in the list?
MOVEM BP,OLDBP ;Yes, do this in 2 passes
MOVNI C2,1(C2) ;Get negative number of commands in list
MOVEI BP,@BUF(L) ;Get addr of command line
HRLI BP,(POINT 7,) ;Make into byte pointer
MOVE C,@CNT(L) ;Get byte count
PUSHJ P,GETWRD ;Get the first word of command line in T1
JUMPN T1,MATCH2 ;Jump if first char alphameric
SETZM @IDX(L) ;Pretend blank line
CAIN CH,"?" ;Delimiter a question mark?
JRST [OUTSTR [ASCIZ /Commands are: /] ;And nothing in front of it
OUTSTR @NAM(L) ;Type string
OUTSTR CRLF ;Make it nice looking
JRST RETURN] ;Continue
CAIE CH,SP ;Totally blank line?
SETOM @IDX(L) ;No, command did not start with letter or number
JRST RETURN ;Unknown or blank command
MATCH2: MOVEI T2,TEMP20 ;Point to list of SIXBIT commands
HRL T2,C2 ;Negative count
PUSHJ P,TSTABR ;Check for abbreviations
JRST [SKIPE BP,OLDBP ;Is there more to check?
JRST MATCH0 ;Yes, try next 20 on list
MOVEM T2,@IDX(L);0=blank, -1=unknown, -2=ambiguous
JRST RETURN ]
MOVEM T2,@IDX(L) ;Tell user which command matched
AOS @IDX(L) ;FORTRAN starts arrays at 1 not 0
HLRZ T1,-1(L) ;Get argument count
CAIL T1,-DNM ;Is DNAME requested?
JRST MATCH4 ;No
MOVEI T1,@DNM(L) ;Yes, get addr of double word
MOVE T2,TEMP20(T2) ;Get full command name
MOVEI T3,0 ;6 SIXBIT blanks
PUSHJ P,ASC10 ;Convert SIXBIT to 10 ASCII bytes
JRST MATCH4 ;Jump into loop
;Remove command from BUFFER
MATCH3: PUSHJ P,GETBP ;Get a char
MATCH4: CAIE CH,SP ;Space?
CAIN CH,TAB ; or Tab?
JUMPG C,MATCH3 ;Yes, ignore it (but don't loop forever)
MOVEI T1,@BUF(L) ;Get addr of BUFFER
HRLI T1,(POINT 7,) ;Destination byte pointer
MOVM T2,@LEN(L) ;Get word count
IMULI T2,5 ;Make into byte count
SETZM @CNT(L) ;Clear returned byte count
MATCH5: SKIPL C ;If this is a significant character,
AOS @CNT(L) ; tell caller how many
IDPB CH,T1 ;Store char
PUSHJ P,GETBP ;Get a char (or a space if empty)
SOJG T2,MATCH5 ;Loop till BUFFER has been shuffled
JRST RETURN ;Return from MATCH
;Routine to convert SIXBIT to ASCII
;Call with destination pointer in T1, and SIXBIT doubleword in T2 and T3
;Uses T1 and T4, preserves T2 and T3
ASC5: SKIPA T4,[5] ;Do 5 chars
ASC10: MOVEI T4,^D10 ;Do 10 chars
TLCE T1,-1 ;Is left half zero?
TLCE T1,-1 ;Or all ones?
HRLI T1,(POINT 7,) ;Yes, make into byte pointer
PUSH P,T1 ;Save pointer
PUSH P,[POINT 6,T2] ;Set source pointer
ASC1: ILDB T1,0(P) ;Get a byte
ADDI T1,SP ;Make into ASCII
IDPB T1,-1(P) ;Store it
SOJG T4,ASC1 ;Loop for all
POP P,(P) ;Dump source pointer
POP P,(P) ;Dump dest pointer
POPJ P, ;Return from ASC5 or ASC10
SUBTTL Subroutines -- Read TMPCOR or DSK:nnnxxx.TMP
;Here to read the temp-core file, putting it in COMBUF.
;The TMPCOR file name is stored @NAM(L).
REDTMP: PUSHJ P,GETNAM ;Get CCL name into T1
MOVE T2,[IOWD CBUFSZ,COMBUF]
MOVE C,[.TCRDF,,T1] ;Read and delete file, args start at T1
TMPCOR C, ;Try to input file
MOVEI C,0 ;Not there
MOVE T1,[POINT 7,COMBUF]
MOVEM T1,CPOINT ;Set up byte pointer
SKIPE C ;Monitor bug returns nonzero data for null file
ILDB C,T1 ; so get first character if not zero-length file
POPJ P, ;Return with C=0 if no input
;Routine to open a channel to the disk.
;Call OPNDSK with TMPCOR name in left half of T1
;Call OPNDS1 with disk file name in T1
;Returns with 4 word LOOKUP/ENTER block in T1-T4, 0 in C2 (for IOWD)
OPNDSK: MOVSS T1 ;Put PRG in right half
HRLI T1,'000' ;Set up bits in T1 (This code taken from LOGOUT)
PJOB T2, ;Get the job number
IDIVI T2,^D10 ;Get low order digit in T3
MOVS T4,T3 ;Save in T4
IDIVI T2,^D10 ;High order in T2, middle in T3
LSH T2,^D12+^D18 ;Put high char where it belongs
LSH T3,^D6+^D18 ; and middle char
ADD T1,T2 ;Add the digits to '000PRG'
ADD T1,T3 ; ...
ADD T1,T4 ; ...
OPNDS1: MOVEI T2,.IODMP ;Dump mode
MOVSI T3,'DSK' ;Device DSK
SETZB T4,C2 ;No buffers, STOP IOWD
IFE FT603,<PRINTX ?The 701-only TMPCOR input has not been debugged, @OPNDS1>
OPEN %0,T2 ;Init channel 0
POPJ P, ;?Cannot init DSK:??
MOVSI T2,'TMP' ;File extension
SETZB T3,T4 ;Default directory
POPJ P, ;Return from OPNDSK
SUBTTL Subroutines -- Read file from disk
READSK: PUSHJ P,GETNAM ;Get CCL name in T1
PUSHJ P,OPNDSK ;Open disk file, get file name in T1,T2
MOVEM T1,CCLNAM ;Save in case file greater than 512 words long
SETZM COMBUF ;Clear first word in case LOOKUP or INPUT fails
IFE FT603,<PRINTX ?The 701-only TMPCOR input has not been debugged, @READSK>
LOOKUP %0,T1 ;Find the file
JRST READS1 ;Not there, set C=0 and return
MOVE C,[IOWD CBUFSZ,COMBUF]
INPUT %0,C ;Read in up to 4 blocks
HLRE T3,T4 ;Get size of file
JUMPGE T3,READS0 ;Should be negative word count
SUBI T3,1 ;Make 128 show up as 0 blocks left
IDIV T3,[-200] ;Make into positive block count
READS0:
IFN CBUFSZ-200,< IDIVI T3,CBUFSZ/200 > ;Convert to pages
MOVEM T3,CCLSIZ ;Non-zero if greater than 1 page
SETZM CCLBLK ;No name, clear current page number
SKIPN T3 ;Don't delete if more to come
DELTMP: SETZB T1,CCLNAM ;CCL file no longer open
RENAME %0,T1 ;Delete the CCL file
JFCL ;Ignore error
;Return with C=0 if nothing was read in
READS1: RELEAS %0, ;Done with channel 0
MOVE T1,[POINT 7,COMBUF]
MOVEM T1,CPOINT ;Set up byte pointer
SKIPN C,COMBUF ;If nothing was read in,
SETZM CCLNAM ; clear the CCL flag
POPJ P, ;C is non-zero if command is in COMBUF
;Here to reopen CCL file and read next 4 blocks. Preserves all ACs
REOPEN: MOVE T1,CCLNAM ;Get disk file name
MOVE C,[IOWD CBUFSZ,COMBUF]
PUSHJ P,OPNDS1 ;Open disk channel, set up T1-T4, and C2
IFE FT603,<PRINTX ?The 701-only TMPCOR input has not been debugged, @REOPEN>
LOOKUP %0,T1 ;Find file again
JRST [SETZM CCLSIZ ;Error, forget about CCL file
JRST READS1 ] ;Release channel
AOS T1,CCLBLK ;Page number to read in
IFN CBUFSZ-200,< IMULI T1,CBUFSZ/200 > ;Convert page number to block number
USETI %0,1(T1) ;Set to read proper block
INPUT %0,C ;Get 512 words
MOVE T1,CCLBLK ;Get current page number again
CAMGE T1,CCLSIZ ;More yet to come?
JRST READS1 ;Yes, keep file around a little longer
SETZM CCLSIZ ;No, forget about the file
JRST DELTMP ;Delete it and set up pointer to COMBUF
SUBTTL Subroutines -- TSTABR - Test if T1 is an abbreviation
;Test if word in T1 matches any in a list pointed to by T2
;Return CPOPJ with T2 = match number
;Return POPJ with T2 = 0 for blank, -1 for unknown, -2 for ambiguous
;Changes T2, preserves all other ACs
TSTABR: JUMPE T1,[MOVEI T2,0 ;If T1 is blank,
POPJ P, ] ;Give error return with T2=0
PUSH P,T3 ;Save ACs
PUSH P,T4 ; ...
PUSH P,C ; ...
PUSH P,T2 ;Save original pointer
SETO T3, ;Set full mask
;First generate a mask in T3 with ones where T1 has blanks
TSTAB1: LSH T3,-6 ;Shift mask to the right
TDNE T3,T1 ;Skip if masking only spaces
JRST TSTAB1 ;Loop till finished
MOVEI C,0 ;Clear flag
TSTAB2: MOVE T4,(T2) ;Get word to match
XOR T4,T1 ;Clear chars that do match
JUMPE T4,TSTAB4 ;Exact match
ANDCM T4,T3 ;Look only at chars typed in
JUMPN T4,TSTAB3 ;Jump if not a proper abbreviation
TLON C,1 ;Skip if not first match
TROA C,(T2) ;Put pointer in RH if first match
TRZ C,-1 ;2nd match, clear pointer
TSTAB3: AOBJN T2,TSTAB2 ;Try next possiblity
MOVE T2,C ;Get possible match
TRNE T2,-1 ;Was one abbreviation found?
JRST TSTAB4 ;Yes, use it
POP P,T3 ;No, dump the original pointer
MOVNI T2,1 ;Assume unknown
TLNE C,1 ;Any matches at all?
MOVNI T2,2 ;Yes, ambiguous
JRST TSTAB5 ;Finish up
TSTAB4: POP P,T3 ;Get original pointer off stack
AOS -3(P) ;Make skip return
ANDI T2,-1 ;Clear count in left half
SUBI T2,(T3) ;Find relative offset
TSTAB5: POP P,C ;Restore ACs
POP P,T4 ; ...
POP P,T3 ;T1 has remaind unchanged
POPJ P,
SUBTTL Subroutines -- GETWRD - Get alphameric word in T1, input via BP and C
GETWRD: MOVEI T1,0 ;Clear out result
MOVE T2,[POINT 6,T1] ;Returns SIXBIT result in T1
GETWR1: SOSGE C ;Any more chars?
JRST GETWR3 ;No, but the delimiter is a space
ILDB CH,BP ;Get a char
CAIE CH,SP ;Space?
CAIN CH,TAB ;Or tab?
JRST GETWR1 ;Yes, ignore leading blanks
GETWR2: CAILE CH,"_" ;Lower case?
SUBI CH,40 ;Convert to upper
CAIL CH,"0" ;Alphanumeric?
CAILE CH,"Z" ; ...
POPJ P, ;No, end of first word
CAILE CH,"9" ;More on alphanumeric
CAIL CH,"A" ; ...
SKIPA ;OK, is alphanumeric
POPJ P, ;Delimiter
SUBI CH,SP-' ' ;Convert to SIXBIT
TLNE T2,770000 ;Any room in word?
IDPB CH,T2 ;Yes, put char in T1
SOJL C,GETWR3 ;Decrement byte count
ILDB CH,BP ;Get a char
JRST GETWR2 ;Loop
GETWR3: MOVEI CH,SP ;Assume an infinite supply of blanks when
POPJ P, ; byte count goes negative
SUBTTL Subroutines -- FILENM - read DEV:FILENAME[P,PN]
FILENM: SETZB T3,PRGZER ;Zero out PRG area
MOVE T1,[PRGZER,,PRGZER+1] ;Source,,destination
BLT T1,PRGLST ;Zero out our data area
GETFIL: PUSHJ P,GETWRD ;Get word in T1
CAIN CH,":" ;Colon?
JRST [MOVEM T1,PRGDEV ;Yes, that was the device
JRST GETFIL ] ;Go for file
MOVEM T1,PRGNAM ;No, file name
CAIN CH,"." ;Period?
JRST [PUSHJ P,GETWRD ;Yes, get extension
HLLZM T1,PRGEXT ;Store it
JRST .+1 ] ;Check out delimiter
CAIE CH,"[" ;Open bracket?
POPJ P, ;No, all done
SKIPN T1,MYPPN ;Is PPN set up?
GETPPN T1, ;No, get it
MOVEM T1,MYPPN ; ...
PUSHJ P,GETOCT ;Get octal number
SKIPN T1 ;Project specified?
HLRZ T1,MYPPN ;No, default to logged in project
HRLZM T1,PRGPPN ;Store project number
CAIE CH,"," ;Should have comma next
POPJ P, ;No, stop now
PUSHJ P,GETOCT ;Get octal number
SKIPN T1 ;Programmer specified?
HRRZ T1,MYPPN ;No, default to logged in PN
HRRM T1,PRGPPN ;Store it
CAIN CH,"," ;Another comma?
OUTSTR [ASCIZ /%SFDs not supported
/]
POPJ P, ;Return from FILENM
GETOCT: MOVEI T1,0 ;Clear result
GETOC1: SOSGE C ;Any more chars?
POPJ P, ;No
ILDB CH,BP ;Yes, get a char
CAIL CH,"0" ;Is it an octal digit?
CAILE CH,"7" ; ...
POPJ P, ;No
IMULI T1,8 ;Shift over accumulated result
ADDI T1,-"0"(CH) ;Reduce to binary and add
JRST GETOC1 ;Go for more
SUBTTL Subroutines -- CLRBUF - clear BUFFER, KOUNT, LASTC, set up C and BP
;Get the byte pointer, character count, and set the buffer to all spaces
CLRBUF: MOVEI BP,@BUF(L) ;Get the address of the buffer
HRLI BP,(POINT 7,) ;Make into a byte pointer
SETZM @CHR(L) ;Clear LASTC
SETZM @CNT(L) ;No characters read in yet
MOVM C,@LEN(L) ;Get buffer size in words
JUMPE C,RETURN ;Size cannot be zero, RETURN restores P
MOVE T1,BLANKS ;5 spaces
MOVEM T1,0(BP) ;Clear first word of buffer
MOVSI T1,0(BP) ;Source
HRRI T1,1(BP) ;Destination
MOVEI T2,-1(C) ;Calculate addr of end of buffer
ADD T2,BP ; ...
CAIE C,1 ;Only one word?
BLT T1,(T2) ;No, clear all of them
IMULI C,5 ;Make into byte count
POPJ P, ;Return from CLRBUF
SUBTTL Subroutines -- REDTTY - clear COMBUF and fill it with line from terminal
REDTTY: SETZB CH,SAVECH ;Clear saved character
SETZM COMBUF ;Store zeros in COMBUF
MOVE T1,[COMBUF,,COMBUF+1] ;BLT pointer
BLT T1,CBUFND ;Propagate zero through all of COMBUF
MOVE T1,[POINT 7,COMBUF] ;Set up byte pointer
MOVEM T1,CPOINT ;Save
MOVEI C,CBUFS5 ;Max characters
REDTT1: PUSHJ P,TTYIN ;Get a char
JRST REDTT2 ;End of line
SKIPLE C ;Skip if more than 2550 chars type in
IDPB CH,T1 ;Store in COMBUF
SOJA C,REDTT1 ;Loop till end of line
REDTT2: SKIPLE C ;Not likely to skip
IDPB CH,T1 ;Store last char in COMBUF
POPJ P, ;Extra word at CBUFND ensures ASCIZ
SUBTTL Subroutines -- COMCH and TTYIN - character input routines
;COMCH and TTYIN get the next character into CH, non-skip return if end of line
;COMCH reads from COMBUF, TTYIN reads from terminal
COMCH: SKIPN CH,CPOINT ;See if byte pointer is set up
POPJ P, ;No, non-skip return with 0 in CH
SKIPN CH,SAVECH ;Get left-over character if any
ILDB CH,CPOINT ;Get a char from COMBUF
SETZM SAVECH ;No more saved char
JUMPE CH,CBUFMT ;There are at least 2 nulls at end of COMBUF
CAIE CH,CR ;Carriage return?
JRST BREAKC ;No, check for break char
IBP CPOINT ;Yes, increment pointer past linefeed
POPJ P, ;Non-skip return with CR in CH
CBUFMT: SETZM CPOINT ;In case no more
SKIPN CCLSIZ ;Reading a large CCL file?
POPJ P, ;No, end of COMBUF
MOVEI CH,TEMP20 ;Save ACs
BLT CH,TEMP20+BP ;F, T1-T4, C, C2, BP
PUSHJ P,REOPEN ;Reopen disk file and read in another page
MOVSI CH,TEMP20 ;Restore ACs
BLT CH,BP ;F, T1-T4, C, C2, BP
JRST COMCH ;Try again
;Here to read a char from the TTY, give non-skip if End-of-Line
TTYIN: INCHWL CH ;Get a char from terminal
;Then check for end-of-line
;Routine to skip if character in CH is not a break (end of line) char
BREAKC: CAIE CH,LF ;Linefeed?
CAIN CH,ESC ;Escape?
POPJ P, ;Yes, nonskip for usual break characters
CAIE CH,FF ;Formfeed?
CAIN CH,VT ;Vertical tab?
POPJ P, ;Yes, break char
CAIE CH,CZ ;Control-Z?
CAIN CH,BEL ;Bell?
POPJ P, ;Yes, also break
CAIE CH,3 ;Did a Control-C happen to sneak in?
AOS (P) ;None of the above
POPJ P, ;Non-skip return for break character
;GETBP - Routine to get a char from string pointed to by BP, byte count in C.
GETBP: MOVEI CH,SP ;In case no more
SOSL C ;Any more bytes?
ILDB CH,BP ;Yes, get one
POPJ P,
SUBTTL Subroutines -- GETNAM - Returns 3 SIXBIT characters for program name
;If NAM is all blanks or a small integer the name returned is taken
;from the name of the program (via GETTAB).
GETNAM: MOVE T1,@NAM(L) ;Get the name
JUMPE T1,NONAME ;Must be nonzero
CAMN T1,BLANKS ;Is it all blanks?
JRST NONAME ;Not an allowable name
;Name can be ASCII, left justified, or SIXBIT, 3 chars in right half
TLCN T1,771000 ;Any bits on in the first char position?
JRST GETNM6 ;No, try for SIXBIT in right half
TLCN T1,771000 ;Is first char a RUBOUT
JRST NONAME ;Yes, T1 is small negative number.
MOVE T2,[POINT 7,T1] ;Take chars from T1
MOVE T3,[POINT 6,T1] ;And put result back in T1
MOVEI T4,3 ;Pick up only 3 characters
GETNM0: ILDB CH,T2 ;Get a char
CAILE CH,"_" ;Lower case?
SUBI CH,40 ;Convert to upper
SUBI CH,SP-' ' ;Convert to SIXBIT
IDPB CH,T3 ;Store back in T1
SOJG T4,GETNM0 ;Loop for 3 chars
JRST .+2 ;Skip over the swap
GETNM6: MOVSS T1 ;Make left justified SIXBIT
TRZ T1,-1 ;Clear right half
TLNE T1,770000 ;Is the first letter nonblank?
POPJ P, ;Yes, return from GETNAM
NONAME: HRROI T1,.GTPRG ;Program name is in table 3
GETTAB T1, ;Get it
MOVSI T1,'CCL' ;Fake it
TRZ T1,-1 ;Clear right half
POPJ P, ;Return from GETNAM
SUBTTL Data area -- Constants and literals
CRLF: ASCIZ /
/ ;<CR><LF>
BLANKS: ASCII / / ;5 spaces
;End of constants
LITS: END ;Of RUNLIB