Google
 

Trailing-Edge - PDP-10 Archives - BB-M836C-BM - tools/monrd/monrd.mac
There are 10 other files named monrd.mac in the archive. Click here to see a list.
; UPD ID= 5, SNARK:<6.TOOLS-TAPE>MONRD.MAC.2,  22-Aug-82 18:42:08 by PAETZOLD
;TCO 6.1235 - Add POKE command under control of FTPOKE
	TITLE	MONRD	PROGRAM TO READ WORDS FROM THE RUNNING MONITOR

;THIS PROGRAM IS USED TO TYPE OUT LOCATIONS IN THE MONITOR.
;IF THE LOCATIONS ARE IN THE JSB AREA OR PSB AREA, THE PROGRAM IS ABLE
;TO FIND THE PROPER DATA FOR ANY DESIRED FORK AND JOB NUMBER.  TO DO
;THIS REQUIRES THE EXISTANCE OF A "MONRD" JSYS, WHICH IS INSERTED BY
;THE PROGRAM SYSDPY.

	SEARCH	MONSYM,MACSYM,JOBDAT
	SALL
	IFNDEF FTPOKE,<FTPOKE==0>	;POKE COMMAND IF ON

;VERSION INFORMATION:

	VMAJOR==6	;MAJOR VERSION (MONITOR THIS RUNS ON)
	VMINOR==0	;MINOR VERSION
	VEDIT==115	;EDIT NUMBER

;ACCUMULATORS:

	F=0		;FLAGS
	T1=1		;TEMP ACS
	T2=2
	T3=3
	T4=4
	JOB=5		;JOB NUMBER
	FK=6		;FORK NUMBER
	C=7		;CHARACTER AC
	B=10		;BYTE POINTER TO OUTPUT BUFFER
	S=11		;STACK POINTER FOR EXPRESSION PARSING
	P=17		;STACK

;FLAGS:

	FR.SUP==1	;SUPPRESS OUTPUT TO TTY
	FR.SP2==2	;ALSO SUPPRESS OUTPUT TO TTY, TEMPORARILY
	FR.SCM==4	;SUPPRESS COMMAND LISTING WHEN TAKING
	FR.FER==10	;LOG FILE HAS AN ERROR
	FR.INT==20	;INTERRUPT HAS HAPPENED
	FR.ION==40	;^E INTERRUPT IS ENABLED
	FR.RSN==100	;WE HAVE TO REREAD LAST CHARACTER
	FR.SET==200	;SUPPRESS COMMAND IS SETTING SOMETHING
	FR.SZR==400	;SUPPRESS OUTPUT OF ZERO WORDS
	FR.VER==1000	;MONITOR VERSION HAS CHANGED
	FR.WRN==2000	;USER HAS BEEN WARNED HOW TO ^E BACK
	FR.TMP==4000	;TEMPORARY USE INSIDE SOME LOOPS

;VARIOUS PARAMETERS:

	PDLSIZ==^D100	;PUSH-DOWN STACK SIZE
	STKSIZ==^D30	;EXPRESSION STACK SIZE
	TXTLEN==^D200	;COMND BUFFER SIZES
	COLSEP==2	;NUMBER OF BLANK SPACES BETWEEN COLUMNS
	INTCHN==0	;INTERRUPT CHANNEL
	INTCOD==.TICCE	;CHARACTER CODE FOR ^E
	BUFSIZ==^D30	;OUTPUT BUFFER SIZE
	SYMSIZ==^D2000	;SYMBOL TABLE SIZE
	DEFSIZ==^D1000	;NUMBER OF SYMBOLS WE CAN DEFINE
	MAXFRK==^D50	;MAXIMUM NUMBER OF FORKS OF A JOB
	BRKPAR==-1-<1B8+1B9>	;BREAK MASK BITS FOR "(" AND ")"

;USEFUL OPDEFS:

	OPDEF	CALL	[PUSHJ	P,]		;SUBROUTINE CALLS
	OPDEF	RET	[POPJ	P,]		;RETURN
	OPDEF	RETSKP	[JRST	CPOPJ1]		;SKIP RETURN
	OPDEF	PUTCHR	[CALL	CHROUT]		;CHAR OUTPUT ROUTINES
	OPDEF	GETCHR	[CALL	CHRIN]		;CHAR INPUT ROUTINES
	OPDEF	REREAD	[IORI	F,FR.RSN]	;REREAD LAST CHAR
	OPDEF	STR.	[1B8]			;LUUO TO OUTPUT STRING

;RANDOM MACROS:

	DEFINE	AA(NAME,DATA),<		;;MACRO TO DEFINE COMMAND TABLE
	XWD	[ASCIZ/NAME/],DATA>

	DEFINE	ERROR(TEXT,ADDR<ERRFIN>),<;;MACRO FOR TYPING ERRORS
	JRST	[TXZ	F,FR.SUP+FR.SP2
		 STR.	[ASCIZ/
? TEXT/]
		 JRST	ADDR]>

	DEFINE	TEXT(STRING),<
	XLIST
	ASCIZ/STRING/
	LIST>

;COMND JSYS MACROS:

	DEFINE	CMMD(BLOCK),<
	MOVEI	T2,BLOCK
	CALL	DOCMMD>

	DEFINE	NOISE(TEXT),<
	MOVEI	T2,[FLDDB. (.CMNOI,,<-1,,[ASCIZ/TEXT/]>)]
	CALL	DOCMMD>

	DEFINE	CONFRM,<CALL DOCFM>
	SUBTTL	DEFINITIONS FOR THE MONRD% JSYS

;THESE DEFINITIONS MUST MATCH THOSE IN THE SYSDPY PROGRAM.  THE
;FUNCTIONS ARE BETTER DESCRIBED THERE.

	OPDEF	MONRD%	[JSYS 717]	;THE JSYS

	.RDTST==0		;TEST TO SEE IF JSYS IS THERE
	.RDSYM==1		;RETURN VALUE OF SYMBOL
	.RDJSB==2		;RETURN CONTENTS OF JSB LOCATION
	.RDPSB==3		;RETURN CONTENTS OF PSB LOCATION
	.RDSTS==4		;RETURN FORK STATUS
	.PKMON==15		;POKE MONITOR
	.PKJSB==16		;POKE JSB
	.PKPSB==17		;POKE PSB

	.TSTOK==123456		;VALUE RETURNED BY TEST FUNCTION
	.TSTNO==654321		;ALTERNATE VALUE IF NOT PRIVILEGED

;THE FOLLOWING ARE SYMBOLS KNOWN BY THE MONRD JSYS, WHICH WE NEED
;IN ORDER TO RUN PROPERLY.  THIS IS EXPANDED LATER.

	DEFINE	SYMS,<XX <JSVAR,JSVARZ,PSVAR,PSVARZ,SYSFK,NUFKS>>
	SUBTTL	INITIALIZATION

START:	RESET			;CLEAR EVERYTHING
	MOVE	P,[IOWD PDLSIZ,PDL]	;SET UP STACK
	MOVE	T1,[CALL STRUUO]	;GET LUUO INSTRUCTION
	MOVEM	T1,.JB41	;INITIALIZE IT
	SETZB	F,TAKJFN	;CLEAR FLAGS AND TAKE FILE JFN
	SETZM	LOGJFN		;AND OF LOG FILE
	SETZM	TMPJFN		;NO TEMPORARY JFN EITHER
	SETOB	FK,JOB		;CLEAR JOB AND FORK AC'S
	SETZM	LOC		;CLEAR LAST LOCATION
	SETZM	VAL		;AND LAST VALUE
	SETZM	LSTEXP		;AND LAST EXPRESSION
	MOVE	B,[POINT 7,TTYBUF]	;SET UP BYTE POINTER
	SETZM	TTYEND		;AND CLEAR LAST WORD OF BUFFER
	SETZM	LINPOS		;CLEAR CURRENT LINE POSITION
	SETOM	COLPOS		;GET READY
	CALL	ADDDEF		;INITIALIZE TABLE FOR DEFAULTS
	CALL	FINCOL		;TERMINATE IT
	MOVE	T1,[COLTMP,,COLTAB]	;GET READY
	BLT	T1,COLTAB+COLNUM	;COPY THE COLUMN TABLE
	MOVEI	T1,.FHSLF	;MY PROCESS HANDLE
	MOVE	T2,[LEVTAB,,CHNTAB]	;POINT TO INTERRUPT TABLES
	SIR			;TELL MONITOR WHERE THEY ARE
	 ERJMP	LOSE		;FAILED
	MOVX	T2,1B<INTCHN>	;GET BIT FOR TTY CHANNEL
	AIC			;ACTIVATE IT
	 ERJMP	LOSE		;FAILED
	EIR			;ENABLE THE INTERRUPTS
	 ERJMP	LOSE		;FAILED
	MOVEI	T1,.RDTST	;GET READY
	SETZ	T2,		;TO TEST THE JSYS
	MONRD%			;TRY IT OUT
	 ERJMP	[ERROR	<MONRD JSYS not installed, run SYSDPY to install it>,QUIT]
	CAIN	T2,.TSTNO	;NOT ALLOWED TO DO THIS?
	 ERROR	<WHEEL or OPERATOR capabilities required>,QUIT
	CAIE	T2,.TSTOK	;RETURN THE CORRECT VALUE?
	 ERROR	MONRD JSYS gave wrong answer for test function,QUIT
	CALL	SYMGET		;READ IMPORTANT SYMBOLS
	CALL	CHKVER		;CHECK THE VERSION OF THE MONITOR
	SUBTTL	COMMAND PROCESSING

GETCMD:	MOVE	P,[IOWD PDLSIZ,PDL]	;RESET STACK
	CALL	CLRINT		;TURN OFF ^E INTERRUPTS
	SKIPE	T1,TMPJFN	;ANY LEFT OVER JFN?
	RLJFN			;YES, RELEASE IT
	 ERJMP	.+1		;IGNORE ERROR
	SETZM	TMPJFN		;CLEAR IT NOW
	MOVE	B,[POINT 7,TTYBUF]	;RESET UP POINTER
	SETZM	TTYEND		;AND LAST LOCATION
	MOVEI	T1,CMDBLK	;POINT TO COMMAND BLOCK
	CMMD	[FLDDB. (.CMINI)]	;INITIALIZE COMMAND BLOCK
	MOVEM	P,SAVEP		;SAVE STACK FOR REPARSES

NEWPAR:	MOVE	P,SAVEP		;RESTORE STACK
	MOVEI	T1,CMDBLK	;RESET UP POINTER
	CMMD	[FLDDB. (.CMKEY,,CMDTAB)]	;READ A KEYWORD
	MOVE	T2,(T2)		;GET ADDRESS OF ROUTINE
	CALL	(T2)		;CALL IT
	CALL	PUNT		;FORCE OUT ANY TEXT
	JRST	GETCMD		;THEN GET A NEW COMMAND

CMDTAB:	CMDLEN,,CMDLEN			;NUMBER OF COMMANDS
	AA	CLEAR,CMDCLR		;CLEAR THE SYMBOL TABLE
	AA	CLOSE,CMDCLS		;CLOSE THE LOG FILE
	AA	COLUMNS,CMDCOL		;SPECIFY WHICH COLUMNS TO SHOW
	AA	DEFINE,CMDDEF		;DEFINE AN INTERNAL SYMBOL
	AA	EXIT,CMDXIT		;LEAVE PROGRAM
	AA	FORK,CMDFRK		;FORK TO GET PSB FROM
	AA	HELP,CMDHLP		;GIVE HELP
	AA	LIST,CMDLST		;LIST FORKS OF A JOB
	AA	LOG,CMDLOG		;LOG OUTPUT
	AA	MDDT,CMDDDT		;ENTER MDDT
IFN FTPOKE,<				;ONLY IF WE INCLUDE POKING
	AA	POKE,CMPOKE		;POKE THE MONITOR
>					;END OF IFN FTPOKE
	AA	SUPPRESS,CMDSUP		;SUPPRESS OUTPUT TO THE TTY
	AA	SYSTAT,CMDSYS		;DO A SYSTAT
	AA	TAKE,CMDTAK		;TAKE COMMANDS FROM FILE
	AA	TYPE,CMDTYP		;TYPE OUT WORDS
	AA	UNSUPPRESS,CMDUNS	;UNSUPPRESS OUTPUT
	AA	VALUE,CMDVAL		;TYPE OUT VALUE OF EXPRESSION
	AA	WATCH,CMDWCH		;WATCH A PARTICULAR LOCATION

	CMDLEN==.-CMDTAB-1		;NUMBER OF COMMANDS
	SUBTTL	THE SIMPLE COMMANDS

CMDXIT:	CONFRM			;CONFIRM THE LINE
	SKIPE	LOGJFN		;ARE WE LOGGING?
	STR.	[ASCIZ/
% Log file is not yet closed.
/]				;YES, LET HIM KNOW
	CALL	CRLF		;LOOK NICE
	HALTF			;QUIT NICELY
	JRST	CRLF		;TYPE A CRLF AND RETURN

CMDCLR:	NOISE	<CURRENT IN-CORE SYMBOL TABLE>	;DO NOISE
	CONFRM			;CONFIRM THE COMMAND
	SETZM	SYMCNT		;ZAP THE COUNT
	RET			;DONE

CMDDDT:	CONFRM			;CONFIRM THE COMMAND
	MDDT%			;TRY TO GET INTO MDDT
	 ERJMP	[ERROR	Unable to enter MDDT]	;FAILED
	RET			;DONE
	SUBTTL	COMMANDS TO SUPPRESS VARIOUS OUTPUT

;HERE TO SUPPRESS OR UNSUPPRESS VARIOUS OUTPUT.  WE CAN STOP EITHER
;THE WHOLE OUTPUT TO THE TTY, OR JUST THE ECHOING OF COMMAND LINES
;FROM A COMMAND FILE.

CMDSUP:	TXOA	F,FR.SET	;REMEMBER WE ARE SETTING FLAG
CMDUNS:	TXZ	F,FR.SET	;REMEMBER WE ARE CLEARING FLAG
	NOISE	<OUTPUT OF>	;TYPE SOME NOISE
	CMMD	[FLDDB. (.CMKEY,,SUPTAB,,<TTY-OUTPUT>)]	;GET KEYWORD
	HRRZ	T4,(T2)		;GET BITS TO CHANGE
	CONFRM			;CONFIRM THE LINE
	TXNN	F,FR.SET	;WANT TO SET THE BIT OR CLEAR IT?
	TDZA	F,T4		;CLEAR IT
	IOR	F,T4		;SET IT
	RET			;DONE

SUPTAB:	SUPLEN,,SUPLEN			;HEADER
	AA	COMMAND-ECHOING,FR.SCM	;SUPPRESS COMMAND LINE LOGGING
	AA	TTY-OUTPUT,FR.SUP	;SUPPRESS ALL TTY OUTPUT
	AA	ZERO-WORDS,FR.SZR	;SUPPRESS ZERO WORDS
	SUPLEN==.-SUPTAB-1	;NUMBER OF COMMANDS
	SUBTTL	COMMANDS TO SET AND CLEAR THE LOG FILE

;HERE TO SPECIFY THE LOG FILE WHERE OUTPUT GOES IN ADDITION TO THE
;USER'S TERMINAL.  THIS WILL CLOSE THE PREVIOUS LOG FILE FIRST IF IT
;IS OPEN.  ALSO THE CLOSE COMMAND TO FINISH IT OFF.

CMDLOG:	NOISE	<OUTPUT TO FILE>	;TYPE NOISE
	CMMD	[FLDDB. (.CMOFI,,,,<MONRD.LOG.>)]	;READ FILE NAME
	HRRZM	T2,TMPJFN	;SAVE THE JFN FOR AWHILE
	CONFRM			;THEN CONFIRM THE LINE
	CALL	CLSLOG		;CLOSE ANY PREVIOUS LOG FILE
	MOVE	T1,TMPJFN	;GET THE NEW JFN
	MOVX	T2,7B5+OF%WR	;WE WANT TO WRITE ASCII CHARS TO IT
	OPENF			;OPEN IT
	 ERJMP	LOSE		;FAILED
	MOVEM	T1,LOGJFN	;OK, SAVE THE LOG FILE JFN
	SETZM	TMPJFN		;NO LONGER TEMPORARY
	RET			;DONE

CMDCLS:	NOISE	<LOG FILE>	;TYPE NOISE
	CONFRM			;CONFIRM THE LINE

CLSLOG:	SKIPN	T1,LOGJFN	;WAS A JFN THERE?
	RET			;NO, ALL DONE
	CLOSF			;YES, CLOSE IT
	 ERJMP	FILLOS		;FAILED, HANDLE SPECIAL
	SETZM	LOGJFN		;CLEAR THE JFN
	TXZ	F,FR.FER	;CLEAR ERROR FLAG
	RET			;DONE
	SUBTTL	COMMAND TO GET COMMANDS FROM A COMMAND FILE

;THIS COMMAND IS USED TO EXECUTE A FILE OF COMMANDS.  USEFUL FOR LOADING
;THE SYMBOL TABLE WITH NECESSARY SYMBOLS.  TERMINATES ON ANY ERROR OR
;END OF FILE.

CMDTAK:	NOISE	<COMMANDS FROM FILE>	;TYPE NOISE
	HRROI	T2,[ASCIZ/CMD/]		;GET DEFAULT EXTENSION
	MOVEM	T2,JFNBLK+.GJEXT	;SET IT
	MOVX	T2,GJ%OLD		;GET DESIRED FLAG BITS
	MOVEM	T2,JFNBLK+.GJGEN	;SET THEM
	CMMD	[FLDDB. (.CMFIL)]	;GET AN INPUT FILE SPEC
	HRRZM	T2,TMPJFN	;SAVE THE JFN
	CONFRM			;CONFIRM THE LINE
	SKIPE	TAKJFN		;ALREADY DOING A TAKE FILE?
	 ERROR	Command files cannot be nested
	MOVE	T1,TMPJFN	;GET JFN READY
	MOVX	T2,7B5+OF%RD	;WANT TO READ ASCII CHARS
	OPENF			;OPEN THE COMMAND FILE
	 ERJMP	LOSE		;FAILED
	MOVEM	T1,TAKJFN	;SAVE THE JFN FOR REAL
	SETZM	TMPJFN		;NO TEMPORARY JFN ANYMORE
	RET			;RETURN

;SUBROUTINE TO CALL WHEN SOME ERROR OCCURS IN THE TAKE FILE.  THIS
;INCLUDES THE END OF FILE WHICH OCCURS WHEN THE COMMAND FILE IS EXHAUSTED.

UNTAK:	SKIPE	T1,TAKJFN	;GET COMMAND FILE JFN IF ANY
	CLOSF			;CLOSE THE FILE
	 ERJMP	.+1		;IGNORE ERROR
	SETZM	TAKJFN		;THEN CLEAR IT
	RET			;DONE
	SUBTTL	COMMAND TO DO A SIMPLE SYSTAT OF A USER OR A JOB

;THIS COMMAND ALLOWS THE USER TO GET A GENERAL STATUS OF A PARTICULAR JOB,
;A PARTICULAR USER, OR ALL JOBS.

CMDSYS:	ANDCMI	F,FR.TMP	;CLEAR CRLF FLAG
	CMMD	SYSBLK		;READ THE TYPE OF ARGUMENT
	MOVEM	T2,SYSARG	;SAVE THE ARGUMENT
	MOVE	T4,-1(T3)	;SAVE ROUTINE TO CALL FOR THIS ARGUMENT
	CAIE	T4,SYSALL	;NEED TO DO CONFIRMATION STILL?
	CONFRM			;YES, DO SO
	CALL	(T4)		;CALL THE PROPER SUBROUTINE
	JRST	CRLF		;THEN END IN A CRLF

;THE COMMAND BLOCK FOR PARSING THE ARGUMENT FOR THE SYSTAT COMMAND.
;DISPATCH ADDRESS FOR EACH TYPE OF ARGUMENT PRECEEDS THE FUNCTION BLOCK
;FOR THAT ARGUMENT.

	EXP	SYSALL		;ROUTINE TO DO ALL JOBS
SYSBLK:	FLDDB.	(.CMCFM,CM%SDH,,<CRLF for all jobs>,,SYSBK1)

	EXP	SYSONE		;ROUTINE TO DO A SINGLE JOB
SYSBK1:	FLDDB.	(.CMNUM,CM%SDH,^D10,<job number>,,SYSBK2)	;JOB NUMBER

	EXP	SYSUSR		;ROUTINE TO SHOW JOBS OF A USER
SYSBK2:	FLDDB.	(.CMUSR)	;USER NAME

;ROUTINES CALLED BY THE PROPER COMMAND TO DO THE RIGHT SYSTAT.

SYSONE:	MOVE	T1,SYSARG	;GET THE ARGUMENT
	MOVE	T2,[-<.JIPNM+1>,,JIBLK]	;POINT TO STORAGE
	SETZ	T3,		;START AT FIRST WORD
	GETJI			;READ THE INFORMATION
	 ERJMP	LOSE		;FAILED
	JRST	SYSTAT		;GO DO A SYSTAT

SYSALL:	SETZM	SYSARG		;SAY SHOW ALL JOBS
SYSUSR:	SETOM	SYSJOB		;INITIALIZE COUNTER
SYSALP:	AOS	T1,SYSJOB	;MOVE TO NEXT JOB
	MOVE	T2,[-<.JIPNM+1>,,JIBLK]	;POINT TO STORAGE
	SETZ	T3,		;START AT FIRST WORD
	GETJI			;READ INFORMATION
	 ERJMP	SYSALF		;FAILED, GO SEE WHY
	SKIPE	T1,SYSARG	;ANY PARTICULAR USER GIVEN?
	CAMN	T1,JIBLK+.JIUNO	;YES, IS THIS THE ONE?
	CALL	SYSTAT		;WANT TO SHOW THE JOB
	JRST	SYSALP		;LOOP UNTIL DONE

SYSALF:	CAIN	T1,GTJIX4	;NO SUCH JOB?
	JRST	SYSALP		;YES, TRY NEXT ONE
	CAIE	T1,GTJIX3	;ILLEGAL JOB NUMBER?
	JRST	LOSE		;NO, FAIL
	RET			;YES, DONE

;SUBROUTINE TO DO SIMPLE SYSTAT OF A JOB WHICH HAS DATA ABOUT IT READ
;INTO THE JIBLK AREA.

SYSTAT:	TRON	F,FR.TMP	;BEEN HERE BEFORE?
	CALL	CRLF		;NO, TYPE A CRLF FIRST
	MOVE	T1,JIBLK+.JIJNO	;GET JOB NUMBER
	CALL	DECOUT		;OUTPUT IT
	MOVEI	T1,^D6		;GET COLUMN
	CALL	JUSTFY		;MOVE TO PROPER COLUMN
	SKIPGE	JIBLK+.JITNO	;SEE IF ANY TERMINAL NUMBER
	STR.	[ASCIZ/Det/]	;NO, SAY DETACHED
	SKIPL	T1,JIBLK+.JITNO	;ANY?
	CALL	OCTOUT		;YES, OUTPUT IT
	MOVEI	T1,^D14		;GET NEW COLUMN
	CALL	JUSTFY		;MOVE THERE
	SKIPN	T1,JIBLK+.JIPNM	;GET PROGRAM NAME IF ANY
	MOVE	T1,JIBLK+.JISNM	;NONE, GET SUBSYSTEM NAME
	CALL	SIXOUT		;OUTPUT IT
	MOVEI	T1,^D25		;GET NEW COLUMN
	CALL	JUSTFY		;MOVE THERE
	SKIPGE	T1,JIBLK+.JITNO	;GET TERMINAL NUMBER AGAIN
	JRST	SYSRUN		;NONE, SAY RUN STATE
	MOVSI	T1,(T1)		;PUT IN LEFT HALF
	IORI	T1,.TTYJO	;GET INDEX
	GETAB			;READ GETAB ENTRY FOR TTY
	 ERJMP	LOSE		;FAILED
	ANDI	T1,-1		;KEEP ONLY RIGHT HALF
	CAIN	T1,-1		;ANYBODY WAITING FOR INPUT?
SYSRUN:	SKIPA	T2,[ASCIZ/RUN/]	;NO, GET RUN STATE
	MOVE	T2,[ASCIZ/TI/]	;YES, GET TI STATE
	STR.	T2		;OUTPUT THE STATE
	MOVEI	T1,^D33		;GET COLUMN
	CALL	JUSTFY		;MOVE THERE
	SKIPN	JIBLK+.JIUNO	;ANY USER NUMBER?
	STR.	[ASCIZ/Not logged in/]	;NO, SAY NOT LOGGED IN
	SKIPN	T2,JIBLK+.JIUNO	;CHECK AGAIN
	JRST	CRLF		;DONE, TYPE CRLF
	HRROI	T1,TMPBUF	;POINT TO TEMPORARY BUFFER
	DIRST			;CONVERT NUMBER TO STRING
	 ERJMP	LOSE		;FAILED
	STR.	TMPBUF		;OUTPUT THE NAME
	JRST	CRLF		;END LINE WITH A CRLF
	SUBTTL	COMMAND TO DEFINE A SYMBOL FOR EASE IN USING THE PROGRAM

;THIS COMMAND LETS THE USER DEFINE A SYMBOL HIMSELF SO HE CAN SAVE
;TIME TYPING THEM IN.

CMDDEF:	NOISE	<SYMBOL>	;TYPE SOME NOISE
	CMMD	[FLDBK. (.CMFLD,CM%HPP,,symbol,,<[BRMSK. (KEYB0.,KEYB1.,KEYB2.,KEYB3.,<%$.>)]>)]
	MOVE	T2,[POINT 7,ATMBUF]	;GET POINTER TO ATOM BUFFER
	MOVEM	T2,INPTR	;INITIALIZE IT
	TXZ	F,FR.RSN	;CLEAR RESCAN FLAG
	CALL	PARSYM		;GO GET A SYMBOL
	GETCHR			;THEN READ TERMINATING CHAR
	SKIPN	C		;ERROR IF FIELD NOT FULLY PARSED
	SKIPN	T2		;OR IF NO SYMBOL WAS GIVEN
	 ERROR	Bad symbol typed
	MOVEM	T2,NEWSYM	;IS OK, SAVE TEMPORARILY
	NOISE	<TO HAVE THE VALUE>	;MORE NOISE
	CMMD	[FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL	PARSE		;PARSE THE EXPRESSION
	MOVEM	T2,LOC		;SAVE IT
	CONFRM			;THEN CONFIRM THE LINE
	MOVE	T1,NEWSYM	;GET THE NEW SYMBOL
	HRLZ	T2,DEFCNT	;GET COUNT OF ALREADY DEFINED SYMBOLS
	JUMPE	T2,DEFINS	;IF NONE, JUST INSERT THIS ONE
	MOVN	T2,T2		;MAKE INTO AOBJN POINTER
	CAME	T1,DEFTAB(T2)	;SEARCH FOR SYMBOL IN TABLE
	AOBJN	T2,.-1		;KEEP LOOPING
	JUMPL	T2,DEFREP	;JUST REPLACE VALUE IF OLD SYMBOL
DEFINS:	CAIL	T2,DEFSIZ	;IS TABLE FULL?
	 ERROR	Symbol table is full
	MOVEM	T1,DEFTAB(T2)	;SAVE THE SYMBOL NAME
	AOS	DEFCNT		;ADD TO COUNT OF DEFINED SYMBOLS
DEFREP:	MOVE	T1,LOC		;GET THE VALUE
	MOVEM	T1,DEFVAL(T2)	;SAVE IT TOO
	RET			;DONE
	SUBTTL	SUBROUTINE TO LIST ALL OF THE FORKS OF A JOB

;THIS COMMAND IS USED TO LIST THE FORKS OF A JOB, SO THAT WE CAN
;TYPE OUT THE FORK STRUCTURE OF A JOB.  THIS IS SO THAT HE CAN
;SPECIFY WHICH FORK OF THE JOB IS TO BE EXAMINED.

CMDLST:	NOISE	<FORK STRUCTURE OF JOB>	;DO SOME NOISE
	CMMD	[FLDDB.	(.CMNUM,,^D10)]	;OBTAIN THE JOB NUMBER
	MOVEM	T2,LISTJB	;SAVE JOB NUMBER
	CONFRM			;NOW CONFIRM THE LINE
	MOVE	T1,LISTJB	;GET JOB NUMBER
	HRROI	T2,T4		;PLACE TO STORE ANSWER
	MOVEI	T3,.JIJNO	;ONLY WANT TO LOOK AT JOB NUMBER
	GETJI			;SEE IF JOB EXISTS
	 ERJMP	LOSE		;NO SUCH JOB, GO LOSE
	MOVE	T1,NUFKS	;GET MAXIMUM FORK NUMBER
	CAIL	T1,MAXFRK	;SEE IF OUR TABLE IS LARGE ENOUGH
	 ERROR	<Fork tables are too small, reassemble with larger MAXFRK>
	SETZ	T3,		;GET READY FOR THE LOOP

LSTLOP:	MOVEI	T1,.RDJSB	;WANT TO READ FROM JSB
	MOVE	T2,['SYSFK ']	;THE FORK TABLE
	MOVE	T4,LISTJB	;AND THE JOB NUMBER
	CALL	DOJSYS		;FIND THE CONTENTS
	 ERROR	MONRD JSYS failed to get word of SYSFK table
	MOVEM	T1,FRKTAB(T3)	;SAVE INFO ON THIS FORK
	MOVEI	T1,.RDJSB	;SAME FUNCTION AGAIN
	MOVE	T2,['FKPTRS']	;THE TABLE OF POINTERS
	CALL	DOJSYS		;DO THE JSYS AGAIN
	 ERROR	MONRD JSYS failed to get word of FKPTRS table
	MOVEM	T1,FRKPTR(T3)	;SAVE THE POINTER INFO
	ADDI	T3,1		;MOVE TO NEXT JOB FORK NUMBER
	CAMGE	T3,NUFKS	;LOOKED AT ALL FORKS YET?
	JRST	LSTLOP		;NO, KEEP GOING
	MOVEI	T1,MAXFRK*2+1	;GET MAXIMUM NUMBER OF NODES TO VISIT
	MOVEM	T1,SAFETY	;SAVE IN CASE TREE IS BAD
	SETZB	S,DEPTH		;INITIALIZE TOP NODE AND DEPTH
	CALL	CRLF		;START WITH A CRLF

;HERE TO LOOP OVER TREE, TYPING THE STRUCTURE:

TRAVEL:	HRRZ	T2,FRKTAB(S)	;GET FORK NUMBER
	CALL	FRKSTS		;TYPE OUT THE STATUS
	MOVE	T1,DEPTH	;GET CURRENT DEPTH
	IMULI	T1,3		;MULTIPLY BY NICE AMOUNT
	ADDI	T1,^D15		;ADD IN AMOUNT TO SPACE OVER TOO
	CALL	JUSTFY		;MOVE TO RIGHT COLUMN
	HRRZ	T1,FRKTAB(S)	;GET FORK NUMBER AGAIN
	CALL	OCTOUT		;OUTPUT IT
	CALL	CRLF		;THEN A CRLF
	LDB	T1,[POINT 12,FRKPTR(S),35]	;GET THE SON TO THIS NODE
	CAMGE	T1,NUFKS	;MAKE SURE IS LEGAL
	SOSG	SAFETY		;DECREMENT SAFETY COUNTER
	JRST	BADTRE		;TREE IS BAD
	JUMPE	T1,NOSON	;JUMP IF NO SON EXISTS
	MOVE	S,T1		;MOVE TO THE SON
	AOS	DEPTH		;INCREMENT DEPTH
	JRST	TRAVEL		;AND LOOP

NOSON:	LDB	T1,[POINT 12,FRKPTR(S),23]	;GET THE BROTHER OF THIS NODE
	CAMGE	T1,NUFKS	;RANGE CHECK THE FORK NUMBER
	SOSG	SAFETY		;DECREMENT SAFETY COUNTER
	JRST	BADTRE		;BAD TREE, GO COMPLAIN
	JUMPE	T1,NOBROT	;JUMP IF THERE IS NO BROTHER
	MOVE	S,T1		;MOVE TO THE BROTHER
	JRST	TRAVEL		;AND LOOP

NOBROT:	SOSGE	DEPTH		;HAVE TO GO UP, DECREMENT DEPTH
	JRST	CRLF		;ALL DONE, TYPE CRLF AND RETURN
	LDB	S,[POINT 12,FRKPTR(S),11]	;MOVE TO FATHER NODE
	CAMGE	S,NUFKS		;VERIFY THE FORK IS GOOD
	JRST	NOSON		;THEN TRY TO GO RIGHT

BADTRE:	STR.	[ASCIZ/
% Structure of tree is bad, try command again

/]				;TYPE MESSAGE
	RET			;RETURN
;SUBROUTINE TO TYPE THE STATUS OF A FORK.  THE SYSTEM FORK NUMBER
;IS IN AC T2.

FRKSTS:	MOVEI	T1,.RDSTS	;FUNCTION TO READ STATUS
	CALL	DOJSYS		;DO THE FUNCTION
	 JRST	FRKUNK		;FAILED, TYPE UNKNOWN
	MOVE	T4,T1		;SAVE THE STATE
	HLRZ	T2,T1		;GET CODE BY ITSELF
	ANDI	T2,(RF%STS)	;KEEP ONLY THE CODE
	CAILE	T2,STSMAX	;LEGAL FUNCTION CODE?
FRKUNK:	MOVEI	T2,-1		;NO, SAY UNKNOWN
	MOVE	T1,STSTAB(T2)	;GET STATUS TEXT
	CALL	STROUT		;OUTPUT IT
	TXNE	T4,RF%FRZ	;IS IT FROZEN?
	STR.	[ASCIZ/ (^C)/]	;YES, TYPE MORE TEXT
	RET			;DONE

	EXP	[ASCIZ/unknown/]	;STATUS MESSAGES
STSTAB:	EXP	[ASCIZ/running/]
	EXP	[ASCIZ/IO wait/]
	EXP	[ASCIZ/halt/]
	EXP	[ASCIZ/error halt/]
	EXP	[ASCIZ/fork wait/]
	EXP	[ASCIZ/sleep/]
	EXP	[ASCIZ/JSYS trap/]
	EXP	[ASCIZ/addr break/]
	STSMAX==.-STSTAB-1	;HIGHEST KNOWN CODE
	SUBTTL	SUBROUTINE TO SELECT THE FORK TO BE PROCESSED

;HERE FOR COMMAND WHICH SELECTS WHAT SYSTEM FORK NUMBER TO LOOK AT.
;THIS ALSO SELECTS WHICH JOB IS BEING LOOKED AT.

CMDFRK:	NOISE	<TO READ PSB AND JSB OF IS>	;TYPE NOISE
	CMMD	[FLDDB. (.CMNUM,,^D8)]	;GET AN OCTAL NUMBER
	SKIPGE	T2		;MAKE SURE IS NICE
	 ERROR	Negative fork numbers are illegal
	MOVEM	T2,FRKTMP	;SAVE TEMPORARILY
	CONFRM			;GET THE END OF LINE
	MOVE	T2,[RADIX50 0,JOBNO]	;GET SYMBOL
	CALL	SYMVAL		;OBTAIN THE VALUE OF THE SYMBOL
	 ERROR	Failed to get value of JOBNO
	MOVEM	T2,LOC		;SAVE IT
	EXCH	FK,FRKTMP	;SET NEW FORK NUMBER
	CALL	GETWRD		;GET THE WORD
	 JRST	[MOVE	FK,FRKTMP	;RESTORE OLD FORK
		 ERROR	Fork is not in use]	;AND GIVE ERROR
	MOVE	JOB,VAL		;SET JOB NUMBER
	STR.	[ASCIZ/
Fork belongs to job /]		;TYPE STRING
	MOVE	T1,JOB		;GET READY
	CALL	DECOUT		;OUTPUT THE NUMBER
	MOVE	T1,JOB		;GET JOB NUMBER
	HRROI	T2,T4		;ONE WORD STORED IN T4
	MOVEI	T3,.JIUNO	;WANT TO GET THE USER NUMBER
	GETJI			;READ INFO ABOUT THE JOB
	 ERJMP	LOSE		;FAILED
	SKIPN	T2,T4		;SOMETHING THERE?
	STR.	[ASCIZ/, not logged in/]	;NO, SAY NOT LOGGED IN
	JUMPE	T4,USRDON	;IF NO USER, GO FINISH UP
	STR.	[ASCIZ/, user /]	;TYPE STRING
	HRROI	T1,TMPBUF	;POINT TO BUFFER
	SETZM	TMPBUF		;CLEAR BUFFER IN CASE OF FAILURE
	DIRST			;CONVERT THE STRING
	STR.	[ASCIZ/???/]	;SAY WE DON'T KNOW
	STR.	TMPBUF		;OUTPUT THE USER NAME
USRDON:	STR.	[ASCIZ/

/]				;TYPE ENDING STRING
	RET			;DONE
	SUBTTL	COMMAND TO WATCH A PARTICULAR LOCATION

;HERE TO LOOK AT A PARTICULAR LOCATION TO SEE IF IT CHANGES.
;EVERY CHANGE IS TYPED OUT AS IT IS FOUND.

CMDWCH:	NOISE	<LOCATION>	;ASK FOR WHAT WE WANT
	CMMD	[FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL	PARSE		;GO PARSE IT
	MOVEM	T2,LOC		;SET AS LOCATION TO BE USED
	NOISE	<WITH SLEEP INTERVAL OF>	;MORE NOISE
	CMMD	[FLDDB. (.CMNUM,,^D10,,<1000>)]	;PARSE NUMBER
	MOVEM	T2,SLPTIM	;SAVE SLEEP TIME
	NOISE	<MILLISECONDS>	;LAST NOISE
	CONFRM			;CONFIRM THE LINE
	TRON	F,FR.WRN	;HAS HE BEEN WARNED YET?
	STR.	[ASCIZ/
[Type ^E to return to command level]
/]				;NO, SO SAY WHAT TO DO
	CALL	GETWRD		;READ THE WORD
	 JRST	READFL		;FAILED
	CALL	SETINT		;TURN ON ^E INTERRUPT NOW
	CALL	CRLF		;SPACE DOWN
	MOVE	T1,VAL		;GET CONTENTS

WCHLOP:	MOVEM	T1,OLDVAL	;SAVE IT FOR NEXT TIME
	CALL	WRDOUT		;OUTPUT THE WORD

WCHSLP:	TXNE	F,FR.INT	;SEE IF HE WANTS TO STOP
	JRST	CRLF		;YES, TYPE CRLF AND QUIT
	MOVEI	T1,UNDISM	;GET PLACE TO GO TO ON ^E
	MOVEM	T1,TRAPPC	;SET IT
	SKIPE	T1,SLPTIM	;GET SLEEP TIME
	DISMS			;WAIT THAT LONG
UNDISM:	SETZM	TRAPPC		;CLEAR PLACE TO GO TO
	CALL	GETWRD		;READ WORD AGAIN
	 JRST	READFL		;FAILED
	MOVE	T1,VAL		;GET NEW VALUE
	CAMN	T1,OLDVAL	;SAME AS LAST TIME?
	JRST	WCHSLP		;YES, JUST WAIT
	JRST	WCHLOP		;NO, GO TYPE IT
	SUBTTL	SUBROUTINE TO GET VALUE OF AN EXPRESSION

CMDVAL:	NOISE	<OF EXPRESSION>	;ASK FOR WHAT WE WANT
	CMMD	[FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL	PARSE		;GO PARSE IT
	MOVE	T4,T2		;SAVE VALUE
	CONFRM			;CONFIRM THE LINE
	STR.	[ASCIZ/
Value  =  /]			;TYPE STRING
	MOVE	T1,T4		;GET VALUE
	TLNN	T1,-1		;LEFT HALF ZERO?
	JRST	VALSML		;YES, SKIP ON
	HLRZ	T1,T1		;NO, GET LEFT HALF
	CALL	OCTOUT		;OUTPUT IT
	STR.	[ASCIZ/,,/]	;THEN GIVE TWO COMMAS
	HRRZ	T1,T4		;AND GET RIGHT HALF
VALSML:	CALL	OCTOUT		;OUTPUT IT
	MOVM	T1,T4		;GET POSITIVE VALUE
	CAIGE	T1,^D8		;WOULD DECIMAL BE DIFFERENT THAN OCTAL?
	JRST	VALDON		;NO, JUST TYPE CRLF THEN
	STR.	[ASCIZ/  =  /]	;TYPE MORE
	MOVE	T1,T4		;GET BACK NUMBER
	CALL	DECOUT		;OUTPUT IT IN DECIMAL
VALDON:	STR.	[ASCIZ/.

/]				;MORE SPACING
	RET			;DONE
	SUBTTL	HELP COMMAND

CMDHLP:	CONFRM			;CONFIRM THE LINE
	STR.	HLPTXT		;OUTPUT THE HELP TEXT
	RET			;DONE

HLPTXT:	TEXT	<
This program is able to type words from the running monitor, whether
or not that data is in the resident monitor, swappable monitor, or
is in some fork's PSB or a job's JSB.  Commands are:


CLEAR		Zero the internal symbol table.  This should only be
		done if you have reason to think that the program's
		symbol table is incorrect.  Symbols are added to this
		table whenever they are found.

CLOSE		Close log file if one was in progress.

COLUMNS c1 ...	Specify what kind of output is typed when showing a
		location.  The default is to show the address, the
		value in octal, and the value in halfword symbols.

DEFINE s e1	Define the symbol s to have the value of the expression
		e1.  This is used only for ease in typing in of other
		expressions.  Typeout will never print the symbol.

FORK n		Set which system-wide fork handle we are interested in.
		This must be specified if locations in a PSB or JSB
		are to be typed.  A list of the forks for a job is
		obtained by using the LIST command.

LIST n		List all the system-wide fork handles of a job.  The
		output is ordered so that you can tell the fork
		structure of the job.

LOG file	Make a log file showing all valid commands and output.

MDDT		Enter MDDT.  MRETN$G will return.

SUPPRESS arg	Specify that certain output is to be suppressed.  Arg
		can be one of the following:

		COMMAND-ECHOING  Don't show the command line in the
				 log file or to the terminal.
		TTY-OUTPUT	 Don't type anything to the terminal.
				 An error will clear this.
		ZERO-WORDS	 Don't type locations which are zero.

SYSTAT arg	Do a systat of the indicated jobs.  Arg can be any of
		a job number, a user name, or just CRLF for all jobs.

TAKE file	Take commands from the specified file.

TYPE e1 e2	Type out words from location e1 to location e2, where
		e1 and e2 are expressions containing symbol names and
		integers using the normal arithmetic operators.  Typing
		a ^E will abort the typeout.

UNSUPPRESS arg	Undoes effects of the SUPPRESS command.

WATCH e1 n	Continuously watch the contents of location e1,
		typing it whenever it changes, sleeping n milliseconds
		between checks.  Typing a ^E will abort the watching.

VALUE e1	Find the value of the expression e1.

EXIT		Leave the program.

HELP		Type this message.

---------
Examples:	1.  To type the JSYS stack for fork 0:

			FORK  0
			TYPE  UPDL  UPDL+NUPDL-1

		2.  To type the schedular tests for all forks:

			TYPE  FKSTAT  FKSTAT+NFKS-1

		3.  To type the JFN block of JFN 3 for the current fork:

			TYPE  JFN0+3*MLJFN  JFN0+4*MLJFN-1

		4.  To watch the process PC of the current fork:

			WATCH  PPC


Notes:		There are some quantities which can be used in
		expressions which are useful.  These are the following:

		'J	The currently selected job number.
		'F	The currently selected fork number.
		'E	The value of the latest expression typed in.
		'V	The value of the location last typed out.
		'R	The right half of the location last typed out.
		'L	The left half of the location last typed out.
		'A	The address of the last location typed out.


		Numbers in expressions are in octal, unless they contain
		the digits 8 or 9 or are followed by a period, in which
		case they are decimal.

>
	SUBTTL	COMMAND TO SPECIFY COLUMNS IN OUTPUT

;THIS COMMAND IS USED TO FORMAT THE OUTPUT OF LOCATIONS.  THE VARIOUS
;KINDS OF OUTPUT ARE THINGS LIKE OCTAL, HALFWORD-SYMBOLIC, DECIMAL,
;ASCII, INSTRUCTIONS, AND SIXBIT.

CMDCOL:	NOISE	(TO SELECT FOR OUTPUT ARE)	;DO NOISE
	SETOM	COLPOS		;INITIALIZE COUNTER
	CMMD	[FLDDB. (.CMKEY,,COLNAM,,DEFAULT)]	;READ KEYWORD
NEWCOL:	CALL	ADDCOL		;GO ADD IN THE COLUMN
	NOISE	(AND)		;THEN ASK FOR MORE
	CMMD	[FLDDB. (.CMCFM,,,,,[FLDDB. (.CMKEY,,COLNAM)])]
	TSC	T3,T3		;SEE IF DONE
	JUMPN	T3,NEWCOL	;GO IF HAVE ANOTHER COLUMN
	CALL	FINCOL		;TERMINATE IT
	MOVE	T1,[COLTMP,,COLTAB]	;GET READY
	BLT	T1,COLTAB+COLNUM	;COPY THE COLUMN TABLE
	RET			;DONE

COLNAM:	XWD	COLNUM,COLNUM			;HEADER
DEF1:	AA	ADDRESS,[^D11,,ADROUT]		;TYPE ADDRESSES
	AA	ASCII,[^D5,,ASCOUT]		;TYPE ASCII CHARACTERS
	AA	DEFAULT,0			;TYPE ALL DEFAULT COLUMNS
	AA	INSTRUCTION,[^D21,,INSOUT]	;TYPE INSTRUCTION FORMAT
DEF2:	AA	OCTAL,[^D14,,FULOUT]		;TYPE OCTAL HALFWORDS
	AA	SIXBIT,[^D6,,SIXOUT]		;TYPE IN SIXBIT
DEF3:	AA	SYMBOLIC,[^D24,,SYMOUT]		;TYPE SYMBOLS
	COLNUM==.-COLNAM-1		;NUMBER OF ENTRIES

;SUBROUTINE CALLED TO ADD COLUMNS TO THE TABLE.  ASSUMES THAT THE
;COLUMN TABLE HAS JUST BEEN READ BY COMND.

ADDCOL:	HRRZ	T2,(T2)		;GET POINTER TO DATA
	JUMPE	T2,ADDDEF	;GO IF WE WANT TO CREATE DEFAULT COLUMNS
	SKIPA	T2,(T2)		;THEN GET THE DATA WORD
FINCOL:	SETZ	T2,		;GET A NULL TO TERMINATE LIST
	AOS	T3,COLPOS	;GET NEXT COLUMN
	CAIGE	T3,COLNUM	;OVERFLOWING?
	MOVEM	T2,COLTMP(T3)	;NO, STORE THE COLUMN
	RET			;DONE

;HERE TO ADD THE DEFAULT COLUMNS TO THE DISPLAY:

ADDDEF:	MOVEI	T2,DEF1		;GET FIRST COLUMN
	CALL	ADDCOL		;ADD IT
	MOVEI	T2,DEF2		;SECOND
	CALL	ADDCOL		;ADD IT
	MOVEI	T2,DEF3		;LAST
	JRST	ADDCOL		;GO FINISH
	SUBTTL	COMMAND TO TYPE OUT MONITOR LOCATIONS

;HERE TO DO THE TYPE COMMAND, WHICH WILL OUTPUT THE DATA THE
;USER ASKS FOR.  ALL LOCATIONS BETWEEN A SPECIFIED RANGE ARE TYPED.

CMDTYP:	NOISE	<WORDS FROM LOCATION>	;TYPE NOISE
	CMMD	[FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL	PARSE		;GO PARSE THE EXPRESSION
	MOVEM	T2,FIRST	;SAVE IT
	MOVE	T2,[ATMBUF,,DEFBUF]	;GET READY
	BLT	T2,DEFBUF+TXTLEN/5	;COPY BUFFER AS DEFAULT STRING
	HRROI	T2,DEFBUF	;GET POINTER TO DEFAULT TEXT
	MOVEM	T2,SYMBLK+.CMDEF	;SET IT
	NOISE	<TO LOCATION>	;MORE NOISE
	CMMD	SYMBLK		;PARSE IT
	CALL	PARSE		;PARSE THIS EXPRESSION TOO
	MOVEM	T2,LAST		;SAVE IT
	CONFRM			;CONFIRM THE LINE
	MOVE	T1,FIRST	;GET FIRST LOCATION TO DO
	MOVEM	T1,LOC		;SET AS LOCATION TO DO
	CALL	GETWRD		;READ THE FIRST WORD
	 JRST	READFL		;FAILED
	CALL	SETINT		;TURN ON ^E INTERRUPT
	CALL	CRLF		;TYPE A CRLF
	JRST	READOK		;JOIN MAIN LOOP

;HERE TO LOOP OVER DESIRED WORDS, TYPING THEM:

TYPLOP:	CALL	GETWRD		;GO READ THE WORD
READFL:	 ERROR	Failed to read specified word
READOK:	TXNE	F,FR.SZR	;DO WE WANT TO SUPPRESS ZERO WORDS?
	SKIPE	VAL		;AND IS THE WORD ZERO?
	CALL	WRDOUT		;NO, THEN TYPE THE WORD
	MOVE	T1,LOC		;GET LOCATION JUST TYPED
	CAMN	T1,LAST		;DID THEM ALL?
	JRST	CRLF		;YES, TYPE CRLF AND DONE
	CAMG	T1,LAST		;MOVING DOWN OR UP?
	AOSA	LOC		;DOWN, BUMP ADDRESS
	SOS	LOC		;UP, DECREMENT ADDRESS
	TXNE	F,FR.INT	;SEE IF WE SHOULD STOP YET
	JRST	CRLF		;YES, GO QUIT
	JRST	TYPLOP		;NO, DO NEXT LOCATION

SYMBLK:	FLDBK. (.CMFLD,CM%HPP!CM%DPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)
	SUBTTL COMMAND TO POKE MONITOR, PSB, AND JSB LOCATIONS

IFN FTPOKE,<			;ONLY IF WE HAVE THE POKE FEATURE

CMPOKE:				;POKE COMMAND
	NOISE <ADDRESS>		;HELP OUT THE USER
	CMMD [FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL PARSE		;PARSE THE ADDRESS
	MOVEM T2,LOC		;SAVE THE LOCATION
	NOISE <WITH VALUE>	;HELP OUT THE USER SOME MORE
	CMMD [FLDBK. (.CMFLD,CM%HPP,,symbolic expression,,<[BRMSK. (KEYB0.,KEYB1.&BRKPAR,KEYB2.,KEYB3.,<%$.+-'*/>)]>)]
	CALL PARSE		;PARSE THE VALUE
	MOVEM T2,VAL		;SAVE THE VALUE
	CONFRM			;MAKE SURE THE USER WANTS THIS
	CALL POKWRD		;GO POKE THE WORD
	 ERROR Failed to POKE the specified word
	CALL CRLF		;DO A CRLF
	CALL WRDOUT		;OUTPUT THE OLD VALUE
	CALL GETWRD		;GET THE CURRENT VALUE
	 ERROR Failed to READ the specified word after POKING
	CALL WRDOUT		;OUTPUT THE CURRENT VALUE
	CALL CRLF		;DO A CRLF
	RET			;AND RETURN FOR ANOTHER COMMAND
>				;END OF IFN FTPOKE
	SUBTTL	SUBROUTINE TO PARSE A SYMBOLIC EXPRESSION

;ROUTINE TO EVALUATE AN EXPRESSION IN THE ATOM BUFFER, AND RETURN THE
;COMPUTED VALUE IN AC T2.  AN EXPRESSION IS MADE UP OF CONSTANTS AND
;SYMBOLS, RELATED IN THE USUAL WAY WITH PLUS, MINUS, MULTIPLY, DIVIDE
;AND PARANTHESIS SYMBOLS.  AC T1 IS PRESERVED.

PARSE:	MOVE	T2,[POINT 7,ATMBUF]	;GET BYTE POINTER TO ATOM BUFFER
	MOVEM	T2,INPTR	;INITIALIZE THE POINTER
	TXZ	F,FR.RSN	;CLEAR RESCAN FLAG
	MOVE	S,[IOWD	STKSIZ,STACK]	;SET UP EXPRESSION STACK
	CALL	EXPR		;GO GET AN EXPRESSION
	GETCHR			;READ TERMINATING CHARACTER
	SKIPE	C		;SEE IF REACHED END OF FIELD
PARBAD:	 ERROR	Illegal expression typed
	MOVEM	T2,LSTEXP	;SAVE LAST EXPRESSION TYPED IN
	RET			;DONE

;HERE TO PARSE AN EXPRESSION.

EXPR:	PUSH	S,[0]		;INITIALIZE VALUE
	GETCHR			;READ FIRST CHARACTER
	CAIN	C,"+"		;PLUS SIGN?
	JRST	EXPRPL		;YES, GO ADD A TERM
	CAIN	C,"-"		;MINUS SIGN?
	JRST	EXPRSB		;YES, GO SUBTRACT A TERM
	REREAD			;NO, PUT BACK THE CHARACTER

EXPRPL:	CALL	TERM		;READ IN A TERM
EXPRXX:	ADDM	T2,(S)		;ADD VALUE INTO OUR TOTAL
	GETCHR			;GET TERMINATING CHARACTER
	CAIN	C,"+"		;A PLUS SIGN?
	JRST	EXPRPL		;YES, GET ANOTHER TERM
	CAIN	C,"-"		;A MINUS SIGN?
	JRST	EXPRSB		;YES, ALSO GET ANOTHER TERM
	REREAD			;NO, RESTORE CHARACTER
	POP	S,T2		;RESTORE VALUE OBTAINED
	RET			;DONE

EXPRSB:	CALL	TERM		;READ A TERM
	MOVN	T2,T2		;NEGATE THE RESULT
	JRST	EXPRXX		;AND ADD IT IN

;HERE TO PARSE A TERM.

TERM:	PUSH	S,[1]		;INITIALIZE VALUE
TERMML:	CALL	FACTOR		;READ IN A FACTOR
	IMULM	T2,(S)		;MULTIPLY OUR RESULT BY IT
TERMXX:	GETCHR			;GET TERMINATOR
	CAIN	C,"*"		;MULTIPLICATION SIGN?
	JRST	TERMML		;YES, GET ANOTHER FACTOR
	CAIN	C,"/"		;DIVISION SIGN?
	JRST	TERMDV		;YES, ALSO GET A FACTOR
	REREAD			;NO, RESTORE CHAR
	POP	S,T2		;RESTORE VALUE
	RET			;DONE

TERMDV:	CALL	FACTOR		;GET THE FACTOR TO DIVIDE BY
	EXCH	T2,(S)		;SWAP THE TWO NUMBERS
	IDIVM	T2,(S)		;COMPUTE THE DIVIDEND
	JRST	TERMXX		;AND LOOK FOR MORE

;HERE TO PARSE A FACTOR.

FACTOR:	CALL	PARNUM		;TRY TO READ AN OCTAL OR DECIMAL NUMBER
	JUMPL	T4,CPOPJ	;IF HAVE ONE, DONE
	CALL	PARSYM		;TRY READING A SYMBOL NAME
	JUMPN	T2,FACSYM	;GOT ONE, GO RETURN ITS VALUE
	GETCHR			;NO, GET TERMINATING CHARACTER
	CAIN	C,"'"		;SPECIAL QUOTE CHARACTER?
	JRST	QUOTE		;YES, GO HANDLE IT
	CAIE	C,"("		;START OF A NESTED EXPRESSION?
	JRST	PARBAD		;NO, BAD EXPRESSION
	CALL	EXPR		;COMPUTE THE NESTED EXPRESSION
	GETCHR			;GET TERMINATOR
	CAIE	C,")"		;CLOSING PARANTHESIS?
	JRST	PARBAD		;NO, INVALID EXPRESSION
	RET			;YES, DONE

;HERE TO PARSE THE SPECIAL QUOTED FACTORS:

QUOTE:	GETCHR			;READ NEXT CHARACTER
	MOVSI	T2,-QUONUM	;GET READY FOR SEARCHING
QUOSRC:	HLRZ	T3,QUOTAB(T2)	;GRAB NEXT LETTER FROM TABLE
	CAME	C,T3		;FOUND IT?
	AOBJN	T2,QUOSRC	;NO, KEEP LOOKING
	SKIPL	T2		;DONE, WAS IT FOUND?
	 ERROR	Illegal quote quantity typed
	HRRZ	T2,QUOTAB(T2)	;YES, GET DISPATCH ADDRESS
	JRST	(T2)		;GO DO IT

;TABLE OF POSSIBLE QUOTE QUANTITES AND DISPATCH ADDRESSES:

QUOTAB:	XWD	"A",QUOADR	;ADDRESS LAST TYPED OUT
	XWD	"E",QUOEXP	;LAST EXPRESSION TYPED IN
	XWD	"F",QUOFRK	;FORK NUMBER THAT WAS SPECIFIED
	XWD	"J",QUOJOB	;JOB NUMBER THAT WAS SPECIFIED
	XWD	"L",QUOLFT	;LEFT HALF OF LAST VALUE TYPED
	XWD	"R",QUORHT	;RIGHT HALF OF LAST VALUE TYPED
	XWD	"V",QUOVAL	;WHOLE VALUE LAST TYPED
	QUONUM==.-QUOTAB	;SIZE OF TABLE

;HERE TO RETURN EACH OF THE QUOTE QUANTITIES:

QUOADR:	SKIPA	T2,LOC		;GET LAST LOCATION
QUOEXP:	MOVE	T2,LSTEXP	;OR LAST EXPRESSION
	RET			;RETURN IT

QUOFRK:	SKIPA	T2,FK		;GET FORK NUMBER
QUOJOB:	MOVE	T2,JOB		;OR JOB NUMBER
	JUMPGE	T2,CPOPJ	;DONE IF ONE WAS SELECTED
	ERROR	No fork number is selected yet

QUORHT:	SKIPA	T2,VAL		;GET RIGHT HALF OF VALUE READY
QUOLFT:	MOVS	T2,VAL		;OR LEFT HALF READY
	TLZA	T2,-1		;KEEP ONLY THAT HALF
QUOVAL:	MOVE	T2,VAL		;OR GET WHOLE WORD
	RET			;DONE

;HERE WHEN HAVE A SYMBOL, TO RETURN ITS VALUE.

FACSYM:	CALL	SYMVAL		;GO GET THE VALUE
	 ERROR	Unknown symbol typed
	RET			;GOT IT, RETURN

;ROUTINE TO PARSE AN OCTAL OR DECIMAL NUMBER.  VALUE RETURNED IN T2,
;WITH T4 NEGATIVE IF A NUMBER WAS ACTUALLY TYPED.  OTHERWISE T4 IS
;NONNEGATIVE.  A NUMBER WHICH INCLUDES "8" OR "9" OR ENDS IN A PERIOD IS
;DECIMAL, OTHERWISE IT IS OCTAL.  IF THE NUMBER ENDS IN A SYMBOL CHARACTER,
;THEN WE DON'T HAVE A NUMBER AT ALL, BUT A SYMBOL.

PARNUM:	MOVE	T2,INPTR	;GET CURRENT BYTE POINTER
	MOVE	T3,F		;AND RESCAN FLAG
	DMOVEM	T2,INSAVE	;SAVE THEM IN CASE WE HAVE TO REPARSE
	SKIPA	T4,[^D8]	;FIRST PASS, ASSUME GETTING OCTAL NUMBER
PARDEC:	MOVEI	T4,^D10		;SECOND PASS, ASSUME GETTING DECIMAL NUMBER
	DMOVE	T2,INSAVE	;RESET POINTER TO START OF NUMBER
	MOVEM	T2,INPTR	;SO CAN REPARSE IT
	TXNN	T3,FR.RSN	;SEE IF RESCAN FLAG SHOULD BE SET
	TXZE	F,FR.RSN	;NO, CLEAR IT
	TXO	F,FR.RSN	;YES, SET IT
	SETZ	T2,		;INITIALIZE NUMBER

PARNML:	GETCHR			;READ NEXT CHARACTER
	CAIL	C,"0"		;IS IT A DIGIT?
	CAIL	C,"0"(T4)	;WELL?
	JRST	PAROCD		;NO, GO SEE IF DONE
	TLOE	T4,-1		;YES, SET FLAG SAYING HAVE NUMBER
	IMULI	T2,(T4)		;SHIFT NUMBER BY A COLUMN
	ADDI	T2,-"0"(C)	;ADD IN THE DIGIT
	JRST	PARNML		;LOOP

PAROCD:	CAIE	C,"8"		;TRYING TO USE DECIMAL DIGITS?
	CAIN	C,"9"		;WELL?
	JRST	PARDEC		;YES, REPARSE TO GET DECIMAL NUMBER
	CAIE	C,"."		;PERIOD FOLLOWING THE NUMBER?
	JRST	CHKSYM		;NO, SEE IF A SYMBOL CHAR
	TRNN	T4,-1-^D8	;DID WE READ A DECIMAL NUMBER YET?
	JRST	PARDEC		;NO, REPARSE TO GET DECIMAL NUMBER
	GETCHR			;YES, GET NEXT CHAR NOW

CHKSYM:	CAIL	C,"A"		;IS THIS A LETTER?
	CAILE	C,"Z"		;WELL?
	CAIN	C,"."		;OR ONE OF THE SPECIAL SYMBOL CHARS?
	JRST	ISSYM		;YES, NUMBER IS ACTUALLY A SYMBOL THEN
	CAIL	C,"0"		;A DIGIT?
	CAILE	C,"9"		;WELL?
	CAIN	C,"%"		;NO, MAYBE ANOTHER SPECIAL CHAR?
	JRST	ISSYM		;YES
	CAIN	C,"$"		;FINAL CHAR FOR A SYMBOL?
	JRST	ISSYM		;YES
RESCAN:	REREAD			;A TRUE NUMBER, RESTORE CURRENT CHAR
	RET			;AND RETURN

ISSYM:	DMOVE	T2,INSAVE	;GET BACK SAVED POINTER
	MOVEM	T2,INPTR	;SO CAN REPARSE IT AS A SYMBOL
	TXNN	T3,FR.RSN	;WAS RESCAN FLAG SET?
	TXZE	F,FR.RSN	;NO, SO CLEAR IT
	TXO	F,FR.RSN	;YES, SET IT
	SETZB	T2,T4		;ACT LIKE NO NUMBER SEEN
	RET			;DONE

;ROUTINE TO READ IN A SYMBOL NAME.  RADIX50 NAME OF SYMBOL RETURNED IN T2.
;AC T2 CONTAINS ZERO IF NO SYMBOL WAS FOUND.

PARSYM:	SETZ	T2,		;CLEAR ANSWER
R50INL:	GETCHR			;GET NEXT CHARACTER
	CAIL	C,"A"		;A LETTER?
	CAILE	C,"Z"		;WELL?
	JRST	R50DGT		;NO, TRY FOR A DIGIT
	IMULI	T2,50		;MAKE ROOM
	ADDI	T2,-<"A"-13>(C)	;ADD IN THIS DIGIT
	JRST	R50INL		;LOOP

R50DGT:	CAIL	C,"0"		;DIGIT?
	CAILE	C,"9"		;WELL?
	JRST	R50SPL		;NO, TRY FOR SPECIAL CHARS
	IMULI	T2,50		;YES, MULTIPLY
	ADDI	T2,-<"0"-1>(C)	;ADD IN THIS DIGIT
	JRST	R50INL		;LOOP

R50SPL:	CAIN	C,"."		;DOT?
	HRROI	C,45		;YES
	CAIN	C,"$"		;DOLLAR SIGN?
	HRROI	C,46		;YES
	CAIN	C,"%"		;PERCENT SIGN?
	HRROI	C,47		;YES
	JUMPGE	C,RESCAN	;IF DONE, RESTORE CHAR AND RETURN
	IMULI	T2,50		;MAKE ROOM
	ADDI	T2,(C)		;ADD IN THIS DIGIT
	JRST	R50INL		;LOOP
;INPUT ROUTINE FOR THE CHARACTERS WE ARE PARSING.  LOWER CASE IS
;CONVERTED TO UPPER CASE, AND RESCANS OF THE LAST CHARACTER IS
;PROVIDED FOR.  CHARACTER RETURNED IN AC C.  A NULL INDICATES THE
;END OF THE ATOM BUFFER.

CHRIN:	TXZN	F,FR.RSN	;WANT TO REREAD A CHAR?
	IBP	INPTR		;NO, ADVANCE POINTER
	LDB	C,INPTR		;READ THE CHARACTER
	CAIN	C,15		;CARRIAGE RETURN?
	JRST	CHRIN		;YES, EAT IT
	CAIL	C,"A"+40	;LOWER CASE?
	CAILE	C,"Z"+40	;WELL?
	RET			;NO, DONE
	SUBI	C,40		;YES, CONVERT TO UPPER CASE
	RET			;RETURN
	SUBTTL	ROUTINE TO READ WORDS FROM MONITOR

;HERE TO READ THE WORD FROM THE JSB OR PSB.  THE LOCATION OF THE WORD
;IN IN LOC, AND WE RETURN THE ANSWER IN LOCATION VAL.  SKIP RETURN
;IF SUCCESSFUL.

GETWRD:	MOVE	T1,LOC		;GET ADDRESS TO EXAMINE
	CAML	T1,PSVAR	;IS THIS ADDRESS IN THE PSB?
	CAMLE	T1,PSVARZ	;WELL?
	JRST	TRYJSB		;NO, GO CHECK FOR JSB
	MOVEI	T1,.RDPSB	;FUNCTION FOR PSB
	MOVE	T2,['PSVAR ']	;KNOWN SYMBOL THERE
	MOVE	T3,LOC		;GET THE ADDRESS
	SUB	T3,PSVAR	;COMPUTE OFFSET
	SKIPGE	T4,FK		;GET FORK NUMBER
	 ERROR	No fork was specified
	CALL	DOJSYS		;DO THE MONRD JSYS
	RET			;FAILED
	MOVEM	T1,VAL		;SAVE THE WORD
	RETSKP			;GOOD RETURN

TRYJSB:	CAML	T1,JSVAR	;IS THIS ADDRESS IN THE JSB?
	CAMLE	T1,JSVARZ	;WELL?
	JRST	TRYPEK		;NO, GO TRY PEEKING
	MOVEI	T1,.RDJSB	;FUNCTION FOR JSB
	MOVE	T2,['JSVAR ']	;KNOWN SYMBOL
	MOVE	T3,LOC		;GET LOCATION TO READ
	SUB	T3,JSVAR	;SUBTRACT KNOWN LOCATON
	SKIPGE	T4,JOB		;SET UP JOB NUMBER
	 ERROR	No fork was specified
	CALL	DOJSYS		;TRY THE READ
	 RET			;FAILED
	MOVEM	T1,VAL		;SAVE THE ANSWER
	RETSKP			;GOOD RETURN

TRYPEK:	TLNE	T1,-1		;CAN ONLY PEEK IN SECTION 0
	RET			;SO IF LARGER, LOSE
	HRLI	T1,1		;WANT ONE WORD
	MOVEI	T2,VAL		;LOCATION WHERE ANSWER GOES
	PEEK			;READ WORD
	 ERJMP	LOSE		;FAILED
	RETSKP			;GOOD RETURN
	SUBTTL ROUTINE TO DEPOSIT WORDS INTO THE MONITOR

IFN FTPOKE,<			;ONLY IF WE HAVE THE POKE FEATURE

; ADR TO POKE IS IN LOC, NEW VALUE IS IN VAL, OLD VALUE IS RETURNED IN VAL

POKWRD:				;HERE TO POKE THE MONITOR
	MOVE T1,LOC		;GET THE ADDRESS TO POKE
	CAML T1,PSVAR		;IS ADR IN THE PSB?
	 CAMLE T1,PSVARZ	;WELL IS IT?
	  JRST POKWRJ		;NO SO TRY THE JSB
	MOVEI T1,.PKPSB		;IN PSB SO GET PSB POKE FUNCTION
	MOVE T2,LOC		;GET THE ADDRESS
	MOVE T3,VAL		;GET THE NEW VALUE
	SKIPGE T4,FK		;GET THE FORK
	 ERROR No fork specified for PSB POKE
	CALL DOJSYS		;DO THE MONRD JSYS
         RET			;ERROR RETURN
	MOVEM T1,VAL		;SAVE THE OLD VALUE
	RETSKP			;AND RETURN SUCCESS
POKWRJ:				;HERE IF THE ADR WAS NOT IN THE PSB
	CAML T1,JSVAR		;IS THE ADR IN THE JSB?
	 CAMLE T1,JSVARZ	;WELL IS IT?
	  JRST POKWRM		;NO SO MUST BE NORMAL MONITOR
	MOVEI T1,.PKJSB		;YES SO GET JSB POKE FUNCTION
	MOVE T2,LOC		;GET THE ADR TO POKE
	MOVE T3,VAL		;GET THE NEW VALUE
	SKIPGE T4,JOB		;GET THE JOB TO POKE
	 ERROR No fork specified for JSB POKE
	CALL DOJSYS		;DO THE MONRD JSYS
	 RET			;ERROR RETURN
	MOVEM T1,VAL		;SAVE THE OLD VALUE
	RETSKP			;AND RETURN SUCCESS
POKWRM:				;HERE TO POKE THE NON JSB AND NON PSB MONITOR
	MOVEI T1,.PKMON		;GET MONITOR POKE FUNCTION
	MOVE T2,LOC		;GET THE ADDRESS
	MOVE T3,VAL		;GET THE NEW VALUE
	CALL DOJSYS		;DO THE MONRD JSYS
	 RET			;ERROR RETURN
	MOVEM T1,VAL		;SAVE THE OLD VALUE
	RETSKP			;AND RETURN SUCCESS

>				;END OF IFN FTPOKE
	SUBTTL	SUBROUTINE TO TYPE OUT A WORD IN VARIOUS WAYS

;SUBROUTINE TO TYPE OUT A LOCATION AND ITS CONTENTS IN VARIOUS
;WAYS.  CALLED WITH THE LOCATION OF THE WORD IN LOC, AND THE VALUE
;CONTAINED THERE IN VAL.  THE FORMAT OF OUTPUT IS DETERMINED BY THE
;PREVIOUS USE OF THE COLUMNS COMMAND.

WRDOUT:	SETOM	COLIDX		;INITIALIZE THE INDEX
	SETZM	COLPOS		;AND CURRENT LOCATION

WRDLOP:	AOS	T4,COLIDX	;MOVE TO NEXT COLUMN
	SKIPN	T4,COLTAB(T4)	;GET ITS DATA IF ANY
	JRST	CRLF		;NO MORE, END IN CRLF
	MOVE	T1,COLPOS	;GET CURRENT DESIRED POSITION
	CALL	JUSTFY		;MOVE THERE
	HLRZ	T1,T4		;GET SIZE OF THIS COLUMN
	ADDI	T1,COLSEP	;LEAVE ROOM BETWEEN COLUMNS
	ADDM	T1,COLPOS	;SAY WHERE WE WANT TO BE NEXT TIME
	MOVE	T1,VAL		;GET THE DATA
	CALL	(T4)		;TYPE THIS COLUMN
	JRST	WRDLOP		;LOOP
	SUBTTL	INSTRUCTION FORMAT OUTPUT ROUTINE

;HERE TO TYPE A QUANTITY IN T1 AS AN INSTRUCTION.

INSOUT:	MOVEM	T1,INSDAT	;SAVE IT FOR AWHILE
	LDB	T1,[POINT 9,T1,8]	;GET OPCODE OF INSTRUCTION
	MOVE	T1,OPTAB(T1)	;THEN GET THE NAME
	CALL	SIXOUT		;TYPE IT
	MOVEI	C," "		;GET A SPACE
	PUTCHR			;TYPE IT
	LDB	T1,[POINT 4,INSDAT,12]	;GET AC FIELD
	JUMPE	T1,INSNOA	;SKIP IF NO AC FIELD
	CALL	OCTOUT		;OUTPUT IT
	MOVEI	C,","		;GET A COMMA
	PUTCHR			;OUTPUT IT
INSNOA:	MOVEI	C,"@"		;GET INDIRECT CHARACTER
	MOVX	T1,<Z @>	;GET THE INDIRECT BIT
	TDNE	T1,INSDAT	;IS IT SET?
	PUTCHR			;YES, TYPE IT
	HRRZ	T1,INSDAT	;GET RIGHT HALF
	CALL	OCTOUT		;OUTPUT IT
	LDB	T1,[POINT 4,INSDAT,17]	;GET INDEX FIELD
	JUMPE	T1,CPOPJ	;RETURN IF NONE THERE
	MOVEI	C,"("		;GET LEFT PARENTHESIS
	PUTCHR			;TYPE IT
	CALL	OCTOUT		;THEN TYPE THE AC NUMBER
	MOVEI	C,")"		;GET CLOSING PARENTHESIS
	PUTCHR			;TYPE IT
	RET			;DONE
	SUBTTL	HALFWORD SYMBOLIC OUTPUT ROUTINE

;HERE TO TYPE A FULL WORD QUANTITY AS TWO HALFWORDS, WHERE EACH
;HALFWORD IS SYMBOLIC.  THIS USES THE SNOOP JSYS TO CONVERT A
;QUANTITY TO ITS SYMBOLS.

SYMOUT:	MOVEM	T1,SYMWRD	;SAVE IT FOR LATER
	HLRZ	T1,T1		;GET LEFT HALF
	JUMPE	T1,SYMRHT	;IF ZERO, JUST TYPE RIGHT HALF
	CALL	SNPSYM		;TYPE OUT THE LEFT HALF
	MOVEI	C,","		;GET A COMMA
	PUTCHR			;OUTPUT IT
	PUTCHR			;TWICE
SYMRHT:	HRRZ	T1,SYMWRD	;GET RIGHT HALF READY

SNPSYM:	CAIL	T1,20		;IN THE ACCUMULATORS?
	CAIN	T1,-1		;OR IS IT MINUS ONE?
	JRST	OCTOUT		;YES, ALWAYS TYPE AS OCTAL
	MOVEM	T1,SYMOFF	;SAVE IT
	MOVE	T2,SYMOFF	;GET VALUE
	CALL	VALSYM		;GO GET SYMBOL FOR THIS VALUE
	 JRST	SYMOCT		;NOT FOUND, TYPE AS OCTAL
	CAIL	T3,1000		;REASONABLY CLOSE?
	JRST	SYMOCT		;NO, TYPE AS OCTAL
	MOVEM	T3,SYMOFF	;SAVE OFFSET
	MOVE	T1,T2		;GET SYMBOL NAME
	CALL	R50OUT		;OUTPUT IT
	SKIPN	SYMOFF		;ANY OFFSET?
	RET			;NO, DONE
	MOVEI	C,"+"		;GET PLUS READY
	PUTCHR			;NO, TYPE THE PLUS
SYMOCT:	MOVE	T1,SYMOFF	;GET OFFSET
	JRST	OCTOUT		;OUTPUT IT
	SUBTTL	STANDARD OUTPUT ROUTINES

;CALLED TO OUTPUT A SYMBOLIC ADDRESS WHICH IS ASSUMED TO BE IN
;LOCATION LOC.

ADROUT:	MOVE	T1,LOC		;GET LOCATION
	CALL	SYMOUT		;OUTPUT THE SYMBOL
	MOVEI	C,"/"		;GET THE SLASH
	PUTCHR			;TYPE IT
	RET			;DONE

;CALLED TO OUTPUT A WORD OF ASCII TEXT IN AC T1.  BAD CHARACTERS ARE
;TRANSLATED TO HARMLESS SPACES SO THAT OUTPUT IS NOT DESTROYED.

ASCOUT:	MOVE	T2,[POINT 7,T1]	;GET BYTE POINTER READY
	MOVEI	T3,5		;AND NUMBER OF CHARACTERS IN A WORD
ASCOUL:	ILDB	C,T2		;GET NEXT CHARACTER
	CAIL	C," "		;CONTROL CHARACTER?
	CAIN	C,177		;OR RUBOUT?
	MOVEI	C," "		;YES, TURN INTO SPACE
	PUTCHR			;OUTPUT IT
	SOJG	T3,ASCOUL	;LOOP OVER ALL 5 LETTERS
	RET			;DONE

;FULL WORD OCTAL OUTPUT ROUTINE.  CALLED TO TYPE A WORD IN THE FORM
;OF TWO HALFWORDS, WHERE EACH HALFWORD ALWAYS HAS 6 DIGITS.

FULOUT:	MOVE	T4,T1		;PRESERVE IT
	HLRZ	T1,T1		;GET LEFT HALF
	CALL	HLFOUT		;OUTPUT IT
	STR.	[ASCIZ/,,/]	;THEN TYPE TWO COMMAS
	HRRZ	T1,T4		;GET RIGHT HALF
	JRST	HLFOUT		;FINISH WITH THAT

;ROUTINE TO OUTPUT A STRING.  CALLED EITHER FROM THE STR. LUUO,
;OR DIRECTLY WITH ADDRESS OF THE STRING IN T1.

STRUUO:	SKIPA	T1,.JBUUO	;GET ADDRESS OF STRING
CRLF:	MOVEI	T1,[BYTE (7)15,12]	;POINT TO A CRLF
STROUT:	HRLI	T1,(POINT 7,)	;MAKE A BYTE POINTER
STROUL:	ILDB	C,T1		;GET NEXT CHAR
	JUMPE	C,CPOPJ		;DONE WHEN GET A NULL
	PUTCHR			;OTHERWISE OUTPUT IT
	JRST	STROUL		;LOOP UNTIL DONE

;SUBROUTINE TO TYPE OUT OCTAL OR DECIMAL NUMBERS.

DECOUT:	SKIPA	T3,[^D10]	;SET RADIX TO DECIMAL
OCTOUT:	MOVEI	T3,^D8		;OR TO OCTAL
	JUMPGE	T1,NUMOUT	;JUMP IF NONNEGATIVE
	MOVEI	C,"-"		;GET A MINUS SIGN
	PUTCHR			;OUTPUT IT
	MOVN	T1,T1		;MAKE POSITIVE
NUMOUT:	IDIVI	T1,(T3)		;GET A DIGIT
	JUMPE	T1,NUMFIN	;DONE WHEN GET NULL
	HRLM	T2,(P)		;SAVE DIGIT
	CALL	NUMOUT		;LOOP
	HLRZ	T2,(P)		;GET BACK A DIGIT
NUMFIN:	MOVEI	C,"0"(T2)	;PRODUCE ASCII CHARACTER
	PUTCHR			;OUTPUT IT
	RET			;DONE

;ROUTINE TO OUTPUT A SIXBIT WORD IN T1, SUPPRESSING TRAILING
;BLANKS.

SIXOUT:	JUMPE	T1,CPOPJ	;DONE IF HAVE A NULL
	SETZ	T2,		;CLEAR NEXT AC
	ROTC	T1,6		;SHIFT NEXT CHAR INTO T2
	MOVEI	C," "(T2)	;TURN INTO ASCII CHAR
	PUTCHR			;OUTPUT IT
	JRST	SIXOUT		;AND LOOP

;ROUTINE TO JUSTIFY THE LINE TO A DESIRED COLUMN POSITION.
;POSITION TO MOVE TO IS IN T1.

JUSTFY:	CAMG	T1,LINPOS	;ALREADY THERE?
	RET			;YES, DONE
	MOVEI	C," "		;GET A SPACE
	PUTCHR			;STORE IT
	JRST	JUSTFY		;LOOP

;ROUTINE TO OUTPUT A HALFWORD OCTAL NUMBER WHICH PRINTS ALL SIX
;DIGITS.  NUMBER IS IN T1.

HLFOUT:	MOVE	T2,[POINT 3,T1,17]	;GET A POINTER
	MOVEI	T3,6		;AND A COUNT
HLFOUL:	ILDB	C,T2		;GET NEXT CHAR
	MOVEI	C,"0"(C)	;CONVERT TO ASCII
	PUTCHR			;OUTPUT IT
	SOJG	T3,HLFOUL	;LOOP UNTIL DONE
	RET			;DONE

;SUBROUTINE TO OUTPUT A RADIX50 VALUE IN AC T1.

R50OUT:	TLZ	T1,740000	;CLEAR JUNK IN HIGH ORDER BITS
R50OUL:	IDIVI	T1,50		;GET A DIGIT
	JUMPE	T1,R50FIN	;IF ZERO, HAVE ALL DIGITS
	HRLM	T2,(P)		;MORE, SAVE THIS ONE
	CALL	R50OUL		;LOOP
	HLRZ	T2,(P)		;GET BACK A DIGIT

R50FIN:	SETZ	C,		;START WITH A NULL
	CAIL	T2,1		;IN RANGE OF A DIGIT?
	CAILE	T2,12		;WELL?
	SKIPA			;NO
	MOVEI	C,"0"-1(T2)	;YES, GET ASCII CHAR
	CAIL	T2,13		;IN RANGE OF A LETTER?
	CAILE	T2,44		;WELL?
	SKIPA			;NO
	MOVEI	C,"A"-13(T2)	;YES, GET ASCII CHAR
	CAIN	T2,45		;PERIOD?
	MOVEI	C,"."		;YES
	CAIN	T2,46		;DOLLAR SIGN?
	MOVEI	C,"$"		;YES
	CAIN	T2,47		;PERCENT SIGN?
	MOVEI	C,"%"		;YES
	PUTCHR			;OUTPUT THE CHAR
	RET			;DONE
	SUBTTL	SUBROUTINE TO CHECK THE MONITOR VERSION

;HERE TO SEE IF OUR SYMBOL TABLE IS VALID.  WE CLEAR THE SYMBOL TABLE
;IF THE CURRENT MONITOR VERSION DIFFERS FROM THE VERSION WE LAST
;READ SYMBOLS FROM.  THIS PREVENTS AWFUL PROBLEMS WITH INCORRECT
;SYMBOLS.

CHKVER:	HRROI	T1,.SYSVE	;GET READY
	GETAB			;ASK FOR LENGTH OF VERSION TABLE
	 ERJMP	LOSE		;FAILED
	MOVSI	T4,(T1)		;MAKE AN AOBJN POINTER
	ANDCMI	F,FR.VER	;CLEAR FLAG FIRST

VERLOP:	MOVSI	T1,(T4)		;GET INDEX
	IORI	T1,.SYSVE	;AND TABLE NUMBER
	GETAB			;READ A WORD OF THE VERSION
	 ERJMP	LOSE		;FAILED
	CAME	T1,MONVER(T4)	;SAME AS PREVIOUSLY?
	IORI	F,FR.VER	;NO, REMEMBER DIFFERENT VERSION
	MOVEM	T1,MONVER(T4)	;SAVE THE NEW WORD
	AOBJN	T4,VERLOP	;LOOP OVER ALL WORDS
	TRNN	F,FR.VER	;SAME MONITOR VERSION?
	RET			;YES, RETURN HAPPILY
	SETZM	SYMCNT		;NO, CLEAR SYMBOL TABLE
	HRROI	T1,[ASCIZ/
% Symbols do not match current monitor, clearing symbol table

/]				;GET THE STRING
	AOS	T2,VIRGIN	;SEE IF FIRST TIME HERE
	CAIE	T2,1		;IS IT?
	PSOUT			;NO, WARN HIM SYMBOLS WERE BAD
	RET			;DONE
	SUBTTL	SUBROUTINE TO READ IMPORTANT SYMBOLS

;HERE AT START OF PROGRAM TO OBTAINS THE FEW SYMBOLS WHICH WE NEED
;INTERNALLY IN ORDER TO RUN PROPERLY.  THESE SYMBOLS ARE ALREADY
;KNOWN BY THE MONRD JSYS, SO THAT WE DO NOT HAVE TO SNOOP THEM.
;NO RETURN IF FAIL TO FIND A SYMBOL.

SYMGET:	MOVSI	T4,-SYMSNM	;GET A COUNTER READY
	JUMPE	T4,CPOPJ	;IF NO SYMBOLS, ALL DONE

SYMGLP:	MOVEI	T1,.RDSYM	;FUNCTION TO READ A SYMBOL
	MOVE	T2,SYMSTB(T4)	;GET THE SYMBOL NAME
	CALL	DOJSYS		;ASK MONRD FOR THE VALUE
	 JRST	SYMBFL		;FAILED
	MOVEM	T1,SYMSVL(T4)	;SAVE THE VALUE
	AOBJN	T4,SYMGLP	;LOOP OVER ALL SYMBOLS
	RET			;DONE

SYMBFL:	STR.	[ASCIZ/
? MONRD JSYS failed to find value of /]	;TYPE STARTING STRING
	STR.	@SYMSTX(T4)	;OUTPUT NAME OF SYMBOL
	JRST	QUIT		;LOSE BIG
	SUBTTL	SUBROUTINE TO FIND THE SYMBOL FOR A VALUE

;SUBROUTINE TO FIND THE SYMBOL AND OFFSET GIVEN THE OCTAL VALUE.
;TO INCREASE SPEED, WE HAVE A TABLE OF KNOWN SYMBOLS AND OFFSETS
;TO THAT REPEATED REFERENCES WILL BE QUICK.  CALL WITH VALUE IN T2,
;RETURNS SYMBOL NAME IN T2 AND OFFSET FROM SYMBOL IN T3.  T1 IS
;UNCHANGED.  SKIP RETURN IF SUCCESSFUL.

VALSYM:	HRLZ	T4,SYMCNT	;GET COUNT OF KNOWN VALUES
	JUMPE	T4,VALSNP	;IF NO VALUES, MUST SNOOP
	MOVN	T4,T4		;MAKE INTO AOBJN COUNTER
	CAML	T2,MINVAL(T4)	;SEARCH TABLE OF VALUES
	CAMLE	T2,MAXVAL(T4)	;LOOKING FOR RANGE WHICH WORKS
	AOBJN 	T4,.-2		;LOOP UNTIL DONE
	JUMPGE	T4,VALSNP	;IF NOT FOUND, HAVE TO SNOOP
	MOVE	T3,T2		;COPY SYMBOL VALUE
	SUB	T3,MINVAL(T4)	;SUBTRACT VALUE TO GET OFFSET
	MOVE	T2,SYMTAB(T4)	;GET SYMBOL NAME
	AOS	(P)		;GOOD RETURN
	RET			;DONE

VALSNP:	MOVEM	T2,VALTMP	;SAVE VALUE FOR AWHILE
	SETZ	T3,		;NO MODULE NAME
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,.SNPAD	;FUNCTION TO LOOKUP VALUE
	SNOOP			;FIND IT
	 ERJMP	VALRET		;FAILED
	TLZ	T2,740000	;CLEAR HIGH ORDER BITS
	HRLZ	T4,SYMCNT	;GET COUNT AGAIN
	MOVN	T4,T4		;TURN INTO AOBJN WORD AGAIN
	CAME	T2,SYMTAB(T4)	;LOOK FOR THE SYMBOL
	AOBJN	T4,.-1		;KEEP LOOKING
	JUMPGE	T4,VALINS	;IF NOT THERE, GO INSERT IT
	MOVE	T1,VALTMP	;GET BACK VALUE
	CAMLE	T1,MAXVAL(T4)	;HIGHER RANGE THAN PREVIOUSLY?
	MOVEM	T1,MAXVAL(T4)	;YES, REMEMBER NEW MAXIMUM
VALSKP:	AOS	-1(P)		;SET FOR SKIP RETURN
VALRET:	POP	P,T1		;RESTORE AC
	RET			;DONE

VALINS:	CAIL	T4,SYMSIZ		;TABLE STILL HAVE ROOM?
	JRST	VALSKP		;NO, CAN'T INSERT ANY MORE
	MOVE	T1,VALTMP	;GET VALUE LOOKING FOR
	SUB	T1,T3		;SUBTRACT OFFSET TO GET VALUE OF SYMBOL
	MOVEM	T1,MINVAL(T4)	;SAVE MINIMUM
	MOVEM	T2,SYMTAB(T4)	;SAVE SYMBOL NAME TOO
	MOVEM	T3,MAXVAL(T4)	;SAVE MAXIMUM TOO
	AOS	SYMCNT		;BUMP COUNTER OF SYMBOLS
	JRST	VALSKP		;DONE
	SUBTTL	SUBROUTINE TO GET VALUE OF A SYMBOL

;CALLED WITH A SYMBOL NAME IN T2, TO RETURN THE VALUE OF THE SYMBOL
;IN AC T2.  WE HAVE A TABLE OF KNOWN SYMBOLS SO WE CAN RETURN THIS
;REAL FAST.

SYMVAL:	HRLZ	T4,DEFCNT	;GET COUNT OF DEFINED SYMBOLS
	JUMPE	T4,SYMNRM	;IF NONE, SEARCH OTHER TABLE
	MOVN	T4,T4		;MAKE AOBJN POINTER
	CAME	T2,DEFTAB(T4)	;LOOK FOR THE SYMBOL
	AOBJN	T4,.-1		;THE WHOLE TABLE
	JUMPGE	T4,SYMNRM	;JUMP IF NOT FOUND
	MOVE	T2,DEFVAL(T4)	;FOUND IT, GET VALUE
	RETSKP			;GOOD RETURN

SYMNRM:	HRLZ	T4,SYMCNT	;GET COUNT OF SYMBOLS
	JUMPE	T4,SYMSNP	;IF NONE, HAVE TO SNOOP
	MOVN	T4,T4		;MAKE AOBJN COUNTER
	CAME	T2,SYMTAB(T4)	;LOOK FOR THE SYMBOL
	AOBJN	T4,.-1		;WHOLE TABLE
	JUMPGE	T4,SYMSNP	;GO SNOOP IF NOT FOUND
	MOVE	T2,MINVAL(T4)	;FOUND IT, GET VALUE
	RETSKP			;GOOD RETURN

SYMSNP:	MOVEM	T2,VALTMP	;SAVE SYMBOL NAME FOR AWHILE
	SETZ	T3,		;NO MODULE NAME
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,.SNPSY	;FUNCTION TO LOOKUP SYMBOL
	SNOOP			;READ SYMBOL VALUE
	 ERJMP	VALRET		;FAILED
	CAIL	T4,SYMSIZ	;IS TABLE FULL?
	JRST	VALSKP		;YES, CAN'T SAVE THIS ONE
	MOVE	T1,VALTMP	;NO, GET SYMBOL NAME
	MOVEM	T1,SYMTAB(T4)	;INSERT IN TABLE
	MOVEM	T2,MINVAL(T4)	;SAVE VALUE AS MINIMUM
	MOVEM	T2,MAXVAL(T4)	;AND AS MAXIMUM
	AOS	SYMCNT		;BUMP NUMBER OF SYMBOLS
	JRST	VALSKP		;RETURN
	SUBTTL	ROUTINES WHICH HANDLE THE TERMINAL INTERRUPTS

;HERE TO SET UP THE ^E INTERRUPT.

SETINT:	SETZM	TRAPPC		;CLEAR PC TO BE TRAPPED TO
	TXZ	F,FR.INT	;CLEAR FLAG SAYING INTERRUPT HAPPENED
	TXOE	F,FR.ION	;ALREADY HAVE INTERRUPTS SET UP?
	RET			;YES, RETURN
	MOVE	T1,[INTCOD,,INTCHN]	;GET READY
	ATI			;SET THE CHARACTER FOR INTERRUPTING
	 ERJMP	LOSE		;FAILED
	RET			;DONE

;HERE TO CLEAR THE ^E INTERRUPT.

CLRINT:	TXNN	F,FR.ION	;WERE INTERRUPTS ON?
	RET			;NO, JUST RETURN
	MOVEI	T1,INTCOD	;GET CODE FOR ASSIGNED CHANNEL
	DTI			;DISCONNECT THE CHANNEL
	 ERJMP	LOSE		;FAILED
	TXZ	F,FR.ION	;INTERRUPTS NO LONGER ON
	RET			;DONE

;HERE WHEN INTERRUPTED.

TTYINT:	PUSH	P,T1		;SAVE AC AC
	SKIPE	T1,TRAPPC	;IS THERE A LOCATION TO TRAP TO?
	MOVEM	T1,CHNPC1	;YES, SET TO GO BACK THERE
	SETZM	TRAPPC		;CLEAR TRAPPING ADDRESS
	TXO	F,FR.INT	;SET FLAG SAYING INTERRUPT HAPPENED
	POP	P,T1		;RESTORE THE AC
	DEBRK			;RETURN
	 ERJMP	LOSE		;FAILED
	SUBTTL	RANDOM SUBROUTINES

;ROUTINE TO DO A COMND FUNCTION.  RETURNS IF OK, OTHERWISE RESTARTS
;THE PROGRAM AFTER TYPING THE PROPER ERROR MESSAGE

DOCMMD:	HRLZ	T3,TAKJFN	;SET UP TAKE FILE JFN IF ANY
	SKIPE	T3		;IS THERE ANY?
	TROA	T3,.NULIO	;YES, COMPLETE IT
	MOVE	T3,[.PRIIN,,.PRIOU]	;NO, USE NORMAL JFNS
	MOVEM	T3,CMDBLK+.CMIOJ	;SET IT UP
	COMND			;DO THE JSYS FOR REAL
	 ERJMP	LOSE		;FAILED
	TXNE	T1,CM%NOP	;DID IT PARSE CORRECTLY?
	JRST	LOSE		;NO, ALSO FAIL
	RET			;SUCCESSFUL, RETURN

;ROUTINE TO CONFIRM THE LINE.  THE BUFFER IS TYPED OUT IF WE ARE
;DOING A TAKE FILE, SO THAT THE USER CAN SEE WHAT IS BEING DONE.

DOCFM:	MOVEI	T2,[FLDDB. (.CMCFM)]	;CONFIRM FUNCTION
	CALL	DOCMMD		;DO IT
	TXNE	F,FR.SCM	;WANT TO TOTALLY SUPPRESS COMMAND LISTING?
	RET			;YES, STOP
	SKIPN	TAKJFN		;READING FROM COMMAND FILE?
	TXO	F,FR.SP2	;NO, STOP TTY OUTPUT FOR AWHILE
	STR.	[ASCIZ/MONRD>/]	;OUTPUT PROMPT
	STR.	TXTBUF		;THEN OUTPUT COMMAND LINE JUST READ
	TXZ	F,FR.SP2	;CLEAR TEMPORARY SUPPRESS FLAG
	RET			;DONE

;ROUTINE TO DO THE MONRD JSYS FOR REAL.  SKIP RETURN IF SUCCESSFUL,
;WITH DATA ALSO RETURNED IN AC T1.

DOJSYS:	MONRD%			;DO THE JSYS
	 ERJMP	CPOPJ		;FAILED, NON-SKIP
	JUMPL	T1,CPOPJ	;NEGATIVE ALSO MEANS FAILED
	MOVE	T1,T2		;COPY DATA TO T1
CPOPJ1:	AOS	(P)		;DO A SKIP RETURN
CPOPJ:	RET			;DONE

;ROUTINE TO TYPE OUT AN ERROR MESSAGE, AND THEN RESTART THE PROGRAM.

FILLOS:	TXO	F,FR.FER	;NO MORE OUTPUT TO THIS JFN
	TXZ	F,FR.SUP+FR.SP2	;CLEAR SUPPRESSION FLAGS
	STR.	[ASCIZ/
? Aborting log file because of error:/]	;SAY SOMETHING BAD HAPPENED
LOSE:	TXZ	F,FR.SUP+FR.SP2	;CLEAR SUPPRESSION OF OUTPUT
	MOVEI	T1,.FHSLF	;MY PROCESS
	GETER			;READ LAST ERROR
	ANDI	T2,-1		;REMOVE PROCESS HANDLE
	CAIN	T2,IOX4		;IS THE ERROR END OF FILE?
	JRST	HAVEOF		;YES, GO SAY HAVE END OF FILE
	MOVEI	T1,.PRIIN	;GET READY
	CFIBF			;CLEAR INPUT BUFFER
	STR.	[ASCIZ/
? /]				;GET STARTING STRING
	HRROI	T1,TMPBUF	;POINT TO TEMPORARY BUFFER
	HRLOI	T2,.FHSLF	;WANT LAST ERROR IN THIS FORK
	MOVEI	T3,^D250	;MAXIMUM CHARACTERS
	ERSTR			;STORE THE ERROR
	JFCL			;FAILED
	JFCL
	STR.	TMPBUF		;OUTPUT THE ERROR
ERRFIN:	SKIPE	TAKJFN		;WERE WE DOING COMMAND FILE?
	STR.	[ASCIZ/ - command file aborted/]	;YES, SAY DONE
	STR.	[ASCIZ/

/]				;GET SOME MORE SPACES
	CALL	UNTAK		;UNDO THE COMMAND FILE NOW
	JRST	GETCMD		;RESTART COMMAND

HAVEOF:	CALL	UNTAK		;RESTORE ORIGINAL PRIMARY JFNS
	STR.	[ASCIZ/
Command file completed

/]				;SAY WHAT HAPPENED
	JRST	GETCMD		;GET A NEW COMMAND

;HERE TO LEAVE THE PROGRAM PERMANENTLY.

QUIT:	STR.	[ASCIZ/

/]				;SPACE DOWN
	RESET			;CLEAR EVERYTHING
	HALTF			;QUIT
	JRST	.-1		;STAY THAT WAY
	SUBTTL	OUTPUT ROUTINE

;THIS ROUTINE IS CALLED FOR ALL NORMAL OUTPUT, TO TYPE THE CHARS
;TO THE TTY, AND POSSIBLY TO A LOG FILE.  CHARACTER TO BE OUTPUT IS IN
;ACCUMULATOR C.  CHANGES NO ACS.

CHROUT:	JUMPE	C,CPOPJ		;IGNORE NULLS
	IDPB	C,B		;STORE THE CHARACTER
	CAIE	C,12		;LINE FEED?
	AOSA	LINPOS		;NO, BUMP POSITION
	SETZM	LINPOS		;YES, CLEAR POSITION
	CAIE	C,12		;LINE FEED?
	SKIPE	TTYEND		;OR WENT INTO LAST WORD?
	SKIPA			;YES, GO FORCE OUTPUT
	RET			;DONE

PUNT:	PUSH	P,T1		;SAVE T1
	PUSH	P,T2		;AND T2
	PUSH	P,T3		;AND T3
	SETZ	T3,		;MAKE A NULL
	IDPB	T3,B		;MAKE STRING ASCIZ
	HRROI	T1,TTYBUF	;POINT TO THE STRING
	TXNN	F,FR.SUP+FR.SP2	;SUPPRESSING TTY OUTPUT?
	PSOUT			;NO, THEN TYPE IT
	HRROI	T2,TTYBUF	;POINT TO BUFFER AGAIN
	SKIPE	T1,LOGJFN	;HAVE THE LOG FILE JFN?
	TXNE	F,FR.FER	;AND NO ERROR IN THE LOG FILE?
	SKIPA			;NO, NO OUTPUT
	SOUT			;YES, TYPE IT THERE TOO
	 ERJMP	FILLOS		;GO TO SPECIAL LOSE CODE
	POP	P,T3		;RESTORE T3
	POP	P,T2		;AND T2
	POP	P,T1		;RESTORE T1
	MOVE	B,[POINT 7,TTYBUF]	;RESET POINTER
	SETZM	TTYEND		;CLEAR LAST WORD
	RET			;DONE
	SUBTTL	DATA

CMDBLK:	0,,NEWPAR		;ADDRESS OF REPARSE ROUTINE
	.PRIIN,,.PRIOU		;INPUT,,OUTPUT JFNS
	-1,,[ASCIZ/MONRD>/]	;CONTROL-R BUFFER
	-1,,TXTBUF		;POINTER TO TEXT BUFFER
	-1,,TXTBUF		;POINTER TO CURRENT POSITION
	TXTLEN			;NUMBER OF CHARS IN BUFFER
	0			;NUMBER OF UNPARSED CHARACTERS
	-1,,ATMBUF		;POINTER TO ATOM BUFFER
	TXTLEN			;NUMBER OF CHARACTERS IN BUFFER
	EXP	JFNBLK		;POINTER TO GTJFN BLOCK

JFNBLK:	GJ%OLD			;FLAGS,,GENERATION NUMBER
	.PRIIN,,.PRIOU		;INPUT,,OUTPUT JFNS
	BLOCK	20		;DEFAULTS

LEVTAB:	EXP	CHNPC1		;PLACE TO STORE THE PC
	BLOCK	2		;OTHER CHANNELS UNUSED

CHNTAB:	XWD	1,TTYINT	;LEVEL 1, INTERRUPT ROUTINE
	BLOCK	^D35		;OTHER CHANNELS UNUSED

ENTVEC:	JRST	START		;START ADDRESS
	JRST	START		;REENTER ADDRESS
	BYTE (3)0(9)VMAJOR(6)VMINOR(18)VEDIT	;VERSION

;NOW EXPAND THE SYMBOLS MACRO FOR USE.

	XALL			;LET EXPANSIONS SHOW

	DEFINE	XX(ARG),<
	IRP	<ARG>,<
	SIXBIT	/ARG/>>

SYMSTB:	SYMS			;PRODUCE THE RADIX50 WORDS
	SYMSNM==.-SYMSTB	;NUMBER OF SYMBOLS

	DEFINE	XX(ARG),<
	IRP	<ARG>,<
ARG:	BLOCK	1>>

SYMSVL:	SYMS			;AND THE VALUES

	DEFINE	XX(ARG),<
	IRP	<ARG>,<
	[ASCIZ/ARG/]>>

SYMSTX:	SYMS			;AND TABLE OF ASCIZ STRINGS

;TABLE OF OPCODES FOR INSTRUCTION TYPEOUT:

	DEFINE	XX(LIST),<
	IRP	<LIST>,<
	SIXBIT	/LIST/>>

	SALL			;NO EXPANSIONS HERE

OPTAB:	XX	<Z,OP1,OP2,OP3,OP4,OP5,OP6,OP7>
	XX	<OP10,OP11,OP12,OP13,OP14,OP15,OP16,OP17>
	XX	<OP20,OP21,OP22,OP23,OP24,OP25,OP26,OP27>
	XX	<OP30,OP31,OP32,OP33,OP34,OP35,OP36,OP37>
	XX	<CALL,INIT,OP42,OP43,OP44,OP45,OP46,CALLI>
	XX	<OPEN,TTCALL,OP52,OP53,OP54,RENAME,IN,OUT>
	XX	<SETSTS,STATO,STATUS,STATZ,INBUF,OUTBUF,INPUT,OUTPUT>
	XX	<CLOSE,RELEAS,MTAPE,UGETF,USETI,USETO,LOOKUP,ENTER>
	XX	<UJEN,OP101,OP102,OP103,JSYS,ADJSP,OP106,OP107>
	XX	<DFAD,DFSB,DFMP,DFDV,DADD,DSUB,DMUL,DDIV>
	XX	<DMOVE,DMOVN,FIX,EXTEND,DMOVEM,DMOVNM,FIXR,FLTR>
	XX	<UFA,DFN,FSC,ADJBP,ILDB,LDB,IDPB,DPB>
	XX	<FAD,FADL,FADM,FADB,FADR,FADRI,FADRM,FADRB>
	XX	<FSB,FSBL,FSBM,FSBB,FSBR,FSBRI,FSBRM,FSBRB>
	XX	<FMP,FMPL,FMPM,FMPB,FMPR,FMPRI,FMPRM,FMPRB>
	XX	<FDV,FDVL,FDVM,FDVB,FDVR,FDVRI,FDVRM,FDVRB>
	XX	<MOVE,MOVEI,MOVEM,MOVES,MOVS,MOVSI,MOVSM,MOVSS>
	XX	<MOVN,MOVNI,MOVNM,MOVNS,MOVM,MOVMI,MOVMM,MOVMS>
	XX	<IMUL,IMULI,IMULM,IMULB,MUL,MULI,MULM,MULB>
	XX	<IDIV,IDIVI,IDIVM,IDIVB,DIV,DIVI,DIVM,DIVB>
	XX	<ASH,ROT,LSH,JFFO,ASHC,ROTC,LSHC,OP247>
	XX	<EXCH,BLT,AOBJP,AOBJN,JRST,JFCL,XCT,MAP>
	XX	<PUSHJ,PUSH,POP,POPJ,JSR,JSP,JSA,JRA>
	XX	<ADD,ADDI,ADDM,ADDB,SUB,SUBI,SUBM,SUBB>
	XX	<CAI,CAIL,CAIE,CAILE,CAIA,CAIGE,CAIN,CAIG>
	XX	<CAM,CAML,CAME,CAMLE,CAMA,CAMGE,CAMN,CAMG>
	XX	<JUMP,JUMPL,JUMPE,JUMPLE,JUMPA,JUMPGE,JUMPN,JUMPG>
	XX	<SKIP,SKIPL,SKIPE,SKIPLE,SKIPA,SKIPGE,SKIPN,SKIPG>
	XX	<AOJ,AOJL,AOJE,AOJLE,AOJA,AOJGE,AOJN,AOJG>
	XX	<AOS,AOSL,AOSE,AOSLE,AOSA,AOSGE,AOSN,AOSG>
	XX	<SOJ,SOJL,SOJE,SOJLE,SOJA,SOJGE,SOJN,SOJG>
	XX	<SOS,SOSL,SOSE,SOSLE,SOSA,SOSGE,SOSN,SOSG>
	XX	<SETZ,SETZI,SETZM,SETZB,AND,ANDI,ANDM,ANDB>
	XX	<ANDCA,ANDCAI,ANDCAM,ANDCAB,SETM,XMOVEI,SETMM,SETMB>

	XX	<ANDCM,ANDCMI,ANDCMM,ANDCMB,SETA,SETAI,SETAM,SETAB>
	XX	<XOR,XORI,XORM,XORB,IOR,IORI,IORM,IORB>
	XX	<ANDCB,ANDCBI,ANDCBM,ANDCBB,EQV,EQVI,EQVM,EQVB>
	XX	<SETCA,SETCAI,SETCAM,SETCAB,ORCA,ORCAI,ORCAM,ORCAB>
	XX	<SETCM,SETCMI,SETCMM,SETCMB,ORCM,ORCMI,ORCMM,ORCMB>
	XX	<ORCB,ORCBI,ORCBM,ORCBB,SETO,SETOI,SETOM,SETOB>
	XX	<HLL,XHLLI,HLLM,HLLS,HRL,HRLI,HRLM,HRLS>
	XX	<HLLZ,HLLZI,HLLZM,HLLZS,HRLZ,HRLZI,HRLZM,HRLZS>
	XX	<HLLO,HLLOI,HLLOM,HLLOS,HRLO,HRLOI,HRLOM,HRLOS>
	XX	<HLLE,HLLEI,HLLEM,HLLES,HRLE,HRLEI,HRLEM,HRLES>
	XX	<HRR,HRRI,HRRM,HRRS,HLR,HLRI,HLRM,HLRS>
	XX	<HRRZ,HRRZI,HRRZM,HRRZS,HLRZ,HLRZI,HLRZM,HLRZS>
	XX	<HRRO,HRROI,HRROM,HRROS,HLRO,HLROI,HLROM,HLROS>
	XX	<HRRE,HRREI,HRREM,HRRES,HLRE,HLREI,HLREM,HLRES>
	XX	<TRN,TLN,TRNE,TLNE,TRNA,TLNA,TRNN,TLNN>
	XX	<TDN,TSN,TDNE,TSNE,TDNA,TSNA,TDNN,TSNN>
	XX	<TRZ,TLZ,TRZE,TLZE,TRZA,TLZA,TRZN,TLZN>
	XX	<TDZ,TSZ,TDZE,TSZE,TDZA,TSZA,TDZN,TSZN>
	XX	<TRC,TLC,TRCE,TLCE,TRCA,TLCA,TRCN,TLCN>
	XX	<TDC,TSC,TDCE,TSCE,TDCA,TSCA,TDCN,TSCN>
	XX	<TRO,TLO,TROE,TLOE,TROA,TLOA,TRON,TLON>
	XX	<TDO,TSO,TDOE,TSOE,TDOA,TSOA,TDON,TSON>
	XX	<APR0,APR1,APR2,OP703,UMOVE,UMOVEM,OP706,OP707>
	XX	<TIOE,TION,RDIO,WRIO,BSIO,BCIO,OP716,OP717>
	XX	<TIOEB,TIONB,RDIOB,WRIOB,BSIOB,BCIOB,OP716,OP727>
	XX	<OP730,OP731,OP732,OP733,OP734,OP735,OP736,OP737>
	XX	<OP740,OP741,OP742,OP743,OP744,OP745,OP746,OP747>
	XX	<OP750,OP751,OP752,OP753,OP754,OP755,OP756,OP757>
	XX	<OP760,OP761,OP762,OP763,OP764,OP765,OP766,OP767>
	XX	<OP770,OP771,OP772,OP773,OP774,OP775,OP776,OP777>

	OPNUM==.-OPTAB		;TOTAL NUMBER OF OPCODES

PDL:	BLOCK	PDLSIZ		;SUBROUTINE CALL STACK
JIBLK:	BLOCK	.JIPNM+1	;DATA READ ABOUT A JOB
SYSJOB:	BLOCK	1		;THE CURRENT JOB DOING SYSTAT ON
SYSARG:	BLOCK	1		;ARGUMENT READ BY SYSTAT COMMAND
STACK:	BLOCK	STKSIZ		;EXPRESSION STACK
SAVEP:	BLOCK	1		;SAVED STACK FOR REPARSING
TXTBUF:	BLOCK	TXTLEN/5+1	;COMND JSYS BUFFER
ATMBUF:	BLOCK	TXTLEN/5+1	;ATOM BUFFER
DEFBUF:	BLOCK	TXTLEN/5+1	;DEFAULT BUFFER AREA
TTYBUF:	BLOCK	BUFSIZ		;TTY OUTPUT BUFFER
TMPBUF:	BLOCK	^D50		;TEMPORARY BUFFER
TTYEND:	BLOCK	1		;LAST WORD IN BUFFER
SYMWRD:	BLOCK	1		;WORD TO BE TYPED AS SYMBOLS
SYMOFF:	BLOCK	1		;OFFSET FROM SYMBOL TO BE TYPED
FIRST:	BLOCK	1		;FIRST LOCATION TO BE TYPED
LAST:	BLOCK	1		;LAST LOCATION TO BE TYPED
LOC:	BLOCK	1		;CURRENT ADDRESS TO BE TYPED
VAL:	BLOCK	1		;CONTENTS TO BE TYPED
LINPOS:	BLOCK	1		;LINE POSITION
INPTR:	BLOCK	1		;BYTE POINTER TO INPUT CHARACTERS
INSAVE:	BLOCK	2		;SAVED INPTR AND INFLAG FOR REPARSES
VALTMP:	BLOCK	1		;TEMPORARY STORAGE
MONVER:	BLOCK	^D30		;THE MONITOR VERSION SYMBOLS CAME FROM
VIRGIN:	BLOCK	1		;FIRST TIME FLAG
SYMCNT:	BLOCK	1		;NUMBER OF SYMBOLS IN TABLE
SYMTAB:	BLOCK	SYMSIZ		;TABLE OF KNOWN SYMBOLS
MINVAL:	BLOCK	SYMSIZ		;CORRESPONDING VALUES
MAXVAL:	BLOCK	SYMSIZ		;HIGHEST VALUE STILL USING SYMBOL
DEFTAB:	BLOCK	DEFSIZ		;TABLE OF DEFINED SYMBOLS
DEFVAL:	BLOCK	DEFSIZ		;TABLE OF VALUES OF DEFINED SYMBOLS
DEFCNT:	BLOCK	1		;NUMBER OF SYMBOLS DEFINED
OLDVAL:	BLOCK	1		;OLD CONTENTS OF A LOCATION
SLPTIM:	BLOCK	1		;TIME TO SLEEP BETWEEN WATCHES
FRKTMP:	BLOCK	1		;TEMPORARY STORAGE FOR FORK COMMAND
LISTJB:	BLOCK	1		;JOB NUMBER LIST COMMAND IS ACTING ON
FRKTAB:	BLOCK	MAXFRK		;TABLE OF FORK INDEXES
FRKPTR:	BLOCK	MAXFRK		;TABLE OF STRUCTURE OF A FORK
DEPTH:	BLOCK	1		;CURRENT DEPTH IN TREE TRAVERSAL
SAFETY:	BLOCK	1		;LIMIT OF NUMBER OF NODES TO VISIT
CHNPC1:	BLOCK	1		;PC OF INTERRUPT
TRAPPC:	BLOCK	1		;LOCATION TO GO ON INTERRUPT
LOGJFN:	BLOCK	1		;JFN OF LOG FILE IF ANY
TAKJFN:	BLOCK	1		;JFN OF TAKE FILE IF ANY
TMPJFN:	BLOCK	1		;NEW JFN BEFORE READY FOR USE
NEWSYM:	BLOCK	1		;SYMBOL TO BE DEFINED
LSTEXP:	BLOCK	1		;VALUE OF LAST EXPRESSION TYPED IN
INSDAT:	BLOCK	1		;DATA FOR INSTRUCTION TYPEOUT
COLTAB:	BLOCK	COLNUM+1	;TABLE OF COLUMN DATA
COLIDX:	BLOCK	1		;CURRENT INDEX INTO THE COLUMNS
COLPOS:	BLOCK	1		;CURRENT COLUMN POSITION
COLTMP:	BLOCK	COLNUM+1	;AREA TO BUILD NEW COLUMN DATA IN

	END	<3,,ENTVEC>	;LOCATION OF ENTRY VECTOR