TITLE RUNOFF - R CLEMENTS - V7
SUBTTL /RCC 11 AUG 70
VRUNOF==7

LOC 137
EXP VRUNOF
RELOC

SUBTTL DEFINITIONS

IFNDEF PURE,<PURE==1>

IFN PURE,<HISEG>

;AC'S
F=0	;FLAGS
A=1	;WORK
B=2
C=3
D=4
X=5
CH=6
C2=7
S1=10
S2=11
N=12
N1=13

PA=15	;POP ARGS

P=17	;STACK

IFN PURE,<
.LOW=140	;FOR STORAGE ALLOCATION

DEFINE UU(NAM,LEN)<NAM=.LOW
.LOW=.LOW+LEN
>
>
IFE PURE,<
.LOW=.
DEFINE UU(NAM,LEN)<NAM:	BLOCK LEN
.LOW=.LOW+LEN
>
>
DEFINE U(NAM)<UU(NAM,1)>
;FLAGS IN LH OF F

JUSTF==1
PJUSTF==2
FILLF==4
FFDSW==10
FOOTFG==20		;ON IF PROCESSING FROM FOOTNOTE STRING
IDXCF==40		;USED TO KEEP CASES REMEMBERED IN INDEX
GCINF==100		;ON IF CHARS IN GCINP TO READ
PAUSF==200
TJUSTF==400
EXSP3==1000
ULMSW==2000		;ON IF UNDERLINE SHIFT-LOCKED ON
NUMBF==4000
SIGNF==10000
ULMODE==20000
ULSUPF==40000		;ON IF USER HAS SUPPRESSED UNDERLINING DUE TO
			;SOME LOSING KIND OF PRINTER
ULBSF==100000		;ON IF UNDERLINING WITH BACKSPACE (ASCII)
IDXRF==200000		;INDEXING REPEATED ITEM

;FLAGS IN RH OF F

R.DOT==1		;DOT SEEN
R.BKT==2		;BRACKETS SEEN (IN FILSPC)
FSEQ==4		;SEQUENCE NUMBER BEING DISCARDED ON INPUT

EXTERN JOBREL,JOBSA,JOBFF
;IMPURE STORAGE


U (RMARG)		;RIGHT MARGIN
U (PRMRG)		;RIGHT PAGE-SIZE
U (CENTC)		;COLUMN TO CENTER AT HALF OF
U (LMARG)		;LEFT MARGIN
U (CAS)		;0 OR 40 TO CONVERT TO LOWER CASE
U (PAGENO)		;PAGE NUMBER FOR OUTPUT FILE
U (PARIND)		;INDENTING FOR PARAGRAPHS
U (NSPNG)
U (LINEC)


TABTL=40
UU (TABTAB,TABTL)
U (NTABS)

U (NLPG)
U (PNLPG)

; GLOBAL VARIABLES

PDLL=50
UU(PLIST,PDLL)

U (FOOTBF)		;ADDRESS OF FOOTNOTE BUFFER (SET AT INITIALIZATION)
U (FOOTC)
U (FOOTP1)
U (FOOTP2)
U (FOOTP3)
U (FOOTP4)

UU(FOOTWB,60)
U (FOOTS1)
U (FOOTS2)
U (FNTOP)

UU(ICBUF,60)		;STORAGE FOR INDEXED ITEM
ICBFE=.LOW-1
U (XFIRST)		;ADDRESS OF ALPHABETICALLY FIRST ITEM
U (XTOP)		;TOP OF INDEX STORAGE
U (XBOT)		;BOTTOM OF INDEX STORAGE
U (OIXC)		;CURRENT ITEM IN OUTPUT INDEX
U (OIXL)		;INITIAL LETTER IN OUTPUT INDEX
; USER-SET TEMPS

U (INDCT)
U (DEVICE)
U (FILE)
U (EXT)
U (PPN)
U (INNAM)

UU (H.FIN,3)
UU (H.FOUT,3)

; GENERAL


U (T1)
U (T2)
U (T5)
U (T6)

U (LCH)
UU (PSTRP,2)

U (INEOFP)		;INPUT END OF FILE STRING POINTER
; LINE TEMPS


U (LINBK)
U (SPCNT)
U (LSTSP)
U (LINNSC)

U (LNIN1)
U (LNIN2)
U (LOUT1)
U (LOUT2)

UU (LINBF,^D100)

U (GCINP)
U (GCIN2)
U (GCSCH)

U (CMSTP)
U (CMST2)

UU (CMBF,40)
ECMBF=.LOW-1

U (TTLP1)
U (TTLP2)
UU(TTLBUF,50)
U (STTLP1)
U (STTLP2)
UU(STTLBF,50)		;SUBTITLE BUFFER

U (EXSP1)
U (EXSP2)
U (ULMCH)

U (NSPCH)
U (LSTNSP)
U (ULPOS)
U (CPOS)
U (ULPT1)
UU (ULPBF,^D100)

;END OF VARIABLES
UU (LOWTOP,0)
;PARAMETERS

SHUP="^"		;UPPER CASE INDICATOR
SHDN="\"		;LOWER CASE INDICATOR
CWARN="_"		;QUOTE NEXT CHARACTER
ULCHI="&"		;UNDERLINE COMMAND IN INPUT DATA
ULCHS=32		;UNDERLINE CHARACTER IN INTERNAL STORAGE
			; MUST BE .LT. C.QTS
QTSP="#"		;QUOTED (NONEXPANDABLE) SPACE IN INPUT FILE

IRMRG=^D60		;INITIAL RIGHT MARGIN
ILMRG=0			;INITIAL LEFT MARGIN
INLPG=^D58		;INITIAL LENGTH OF PAGE
HWPLN=^D66		;HARDWARE PAGE LENGTH OF OUTPUT DEVICE

;CHARACTERS FOR CREF

C.CR=15
C.LF=12
C.SPC=40
C.FF=14
C.TAB=11
C.CMA=","
C.ALT=33
C.BS==10		;BACKSPACE CHARACTER
C.NXS=177		;NON-EXPANDABLE SPACE (INTERNAL)
C.QTS=37		;QUOTED SPACE. MUST BE C.SPC-1 FOR COMPARES
C.PD="."		;PERIOD. FOR SPECIAL SPACING AFTER PERIOD
C.EOF="Z"-100		;END OF FILE
C.EFNT="!"		;END OF FOOTNOTE
C.LPUS=176		;LINE-PRINTER UNDERSCORE IN OUTPUT FILE
			;(NOT RIGHT, THATS SQUIGGLE, BUT ...)

;SOFTWARE CHANNELS

F.FIN==0		;FILE INPUT
F.FOUT==1		;FILE OUTPUT
SUBTTL INPUT SECTION

;INPUT LINE

LIN:
LIN1:	PUSHJ P,GCIN		;READ CHARACTER WITH PRE-TRANSLATE
	CAIN CH,C.TAB		;TAB?
	JRST LTAB		;YES. SPECIAL HANDLING
	CAIN CH,C.CR		;CRR RET?
	JRST LCR		;YES. GO LOOK FOR LF
	CAIGE CH,C.QTS		;SOME OTHER CONTROL CHARACTER?
	 JRST LINNS		;YES. TREAT AS NON-SPACING
	CAIE CH,C.NXS		;NON EXPANDABLE SPACE?
	CAIN CH,C.SPC		;OR REGULAR SPACE?
	JRST LSPAC		;YES. GO HANDLE SPACING
LIN3:	PUSHJ P,WLNIN1		;WRITE CHAR IN INPUT BUFFER
	MOVEM CH,LCH		;SAVE AS LAST CHARACTER
	SOSL LINBK		;TIME TO BREAK LINE YET?
	JRST LIN1		;NO. LOOP FOR MORE
	PUSHJ P,OUTLJ		;YES. OUTPUT LINE,JUSTIFIED IF FLAGS
				; SAY SO, AND SET FOR NEXT LINE
	JRST LIN		;PROCESS NEXT LINE.

LINNS:	PUSHJ P,WLNIN1		;WRITE CHAR IN LINE BUFFER
	MOVEM CH,LCH		;STORE AS LAST CHARACTER
	AOS LINNSC		;COUNT NON-SPACING CHARACTERS
	JRST LIN1		;BACK INTO LOOP
;SUBROUTINE TO INITIALIZE COUNTS AND POINTERS FOR A NEW LINE

LINSET:	MOVE A,RMARG		;COMPUTE REAL WIDTH OF LINE
	SUB A,LMARG		;AS DIFFERENCE OF MARGINS
	SUB A,INDCT		;MINUS INDENTING
	MOVEM A,LINBK		;STORE IN LINE-BREAK COUNT
	SETOM SPCNT		;INITIAL COUNTS OF SPACING
	SETZM NSPCH		; AND NON-SPACING CHARS
	SETZM CPOS		;CARRIAGE POSITION IS FAR LEFT
	SETZM LINNSC		;NO NON-SPACING CHARACTERS
	MOVEI A,ULPBF		;UNDERLINE POSITION BUFFER AT START
	MOVEM A,ULPOS		; ..
	MOVE A,LNIN1		;CLEAR LINE INPUT BUFFER BY MOVING 
	MOVEM A,LNIN2		; END POINTER BACK TO START
	MOVEM A,LSTSP		;SET LAST SPACING CHARACTER BACK HERE
	SOS LSTSP		;MINUS ONE, SO OFF START OF BUFFER
	POPJ P,0		;RETURN FROM LINSET

;SPECIAL CHARACTERS DURING LINE INPUT

LTAB:	MOVE A,LNIN2		;DETERMINE PRESENT POSITION
	SUB A,LNIN1
	SUB A,LINNSC
	ADD A,LMARG
	ADD A,INDCT
	PUSHJ P,TAB		;FIND WHERE NEXT TAB STOP IS
	CAML A,LINBK		;WOULD THAT MANY EQUAL OR EXCEED LINE SIZE?
	JRST LSPAC		;YES. TREAT AS SPACE, NOT TAB
	MOVN X,A		;NO. NEGATE NUMBER OF SPACES
	ADDM X,LINBK		;AND DECREMENT LINBK COUNT BY THAT AMOUNT
	MOVEI CH,C.QTS		;PUT N QUOTED SPACES IN BUFFER
	PUSHJ P,WLNIN1		; ..
	AOJL X,.-1		; ..
	JRST LIN1		;AND BACK INTO LINE INPUT ROUTINE
;HERE ON SPACE IN INPUT FILE, OR ON NON-EXPANDABLE SPACE. ALSO HERE ON
;TAB WHICH COULDNT BE SATISFIED SO IS MADE A SPACE
;NOT HERE ON QUOTED SPACES.

LSPAC:	TLNN F,FILLF		;FILLING INPUT BEYOND BREAKS?
	JRST LSPC1		;NO. SIMPLER PROCESSING
	MOVE A,LNIN2		;FILTER OUT LEADING SPACES
	SUBI A,1		;GET START OF BUFFER MINUS ONE
	CAMG A,LSTSP		;IS THAT WHERE LAST SPACE IS?
	JRST LIN1		;YES. JUST IGNORE THIS SPACE
	MOVE CH,LCH		;GET PREVIOUS CHARACTER. WHAT WAS IT?
	CAIE CH,C.SPC		;A SPACE?
	CAIN CH,C.NXS		;OR NON-EXPANDABLE SPACE?
	JRST LIN1		;YES. FILTER MULTIPLE SPACES
	CAIN CH,C.PD		;PERIOD FOLLOWED BY SPACE?
	SKIPG LINBK		;YES. ANY MOBE ROOM LEFT?
	JRST LSPC1		;NO. JUST STORE THE SPACE
	MOVE A,LNIN2		;YES. FORCE DOUBLE SPACE ON OUTPUT FILE
	MOVEM A,LSTSP		;SAVE POINTER AT LAST (THIS) SPACE.
	MOVE A,LINNSC		;POSITION OF LAST NON-SPACING CHARACTER
	MOVEM A,LSTNSP		;SAVE AS LST ...
	AOS SPCNT		;COUNT SPACING CHARACTER
	MOVEI CH,C.SPC		;WRITE THIS SPACE INTO BUFFER
	PUSHJ P,WLNIN1		; ..
	SOS LINBK		;AND COUNT FOLLOWING CHARACTER
	MOVEI CH,C.NXS		;NON-EXPANDABLE SPACE
	JRST LIN3		; TO BUFFER. THUS 2 IF ANY AT ALL AFTER PD

LSPC1:	MOVE A,LNIN2		;HERE TO STORE AND COUNT A SPACE
	MOVEM A,LSTSP		;SAVE POSITION OF THIS SPACE
	MOVE A,LINNSC		;AND NON-SPACING CHAR POSN
	MOVEM A,LSTNSP		; ..
	AOS SPCNT		;COUNT THIS SPACE
	MOVEI CH,C.SPC		;SPACE CHARACTER (EXPANDABLE)
	JRST LIN3		; ..
;HERE ON CARRIAGE RETURN ON INPUT FILE. ASSUMES LF FOLLOWS

LCR:	PUSHJ P,GCIN		;GET FILE CHARACTER
	CAIE CH,C.LF		;IS IT LINEFEED?
	JRST LCR		;SHOULD HAVE BEEN. THROW THIS AWAY.

;ENTER HERE AFTER INITIALIZATION.

LGO:	PUSHJ P,CCIN		;READ INITIAL CHARACTER ON LINE
	CAIN CH,C.EOF		;END OF FILE?
	JRST ENDFIL		;YES. GO WRAP UP.
	CAIN CH,C.CR		;ANOTHER BLANK LINE?
	JRST LCR		;YES. GO DISCARD
	CAIN CH,C.EFNT		;END OF FOOTNOTE?
	JRST FOOTND		;YES. GO FINISH FOOTNOTE PROCESSING
	CAIN CH,C.FF		;FORMFEED ON INPUT?
	JRST LGO		;YES. IGNORE IT.
	CAIN CH,C.PD		;PERIOD AS FIRST CHAR?
	JRST CMN		;YES. GO READ COMMAND LINE
	MOVEM CH,GCSCH		;NONE OF ABOVE SPECIAL CASES. SAVE.
	TLNE F,FILLF		;FILLING FROM INPUT FILE?
	JRST LSPAC		;YES. TREAT AS IF A SPACE WERE INPUT
	PUSHJ P,OUTLIN		;NO. OUTPUT THIS LINE
	JRST LIN		;AND START ANOTHER.
SUBTTL COMMAND SCANNER
;READ AND DISPATCH ON COMMAND

CMN:	MOVEI PA,CMBF		;INITIALIZE POINTER TO HOLD USER COMMAND
	PUSHJ P,CSP		; ..
	MOVEM A,CMSTP		; ..
	MOVEM A,CMST2		; ..
	PUSHJ P,CMCIN		;READ FIRST CHARACTER AFTER DOT
	CAIN CH,C.CR		;BLANK COMMAND?
	JRST LCR		;YES. IGNORE
	MOVSI N,CMTAB-ECTAB	;GET LENGTH OF COMMAND TABLE
	MOVEI PA,CMSTP		;STORE FIRST CHARACTER OF COMMAND
	PUSHJ P,WCI		; ..
CM2:	MOVE S2,CMTAB(N)	;PREPARE TO READ DEFINED COMMAND
	HRLI S2,440700		; ..
	MOVE A,CMSTP		;PREPARE POINTER TO READ USER'S COMMAND
	MOVE B,CMST2		; ..
	MOVEM A,T1		; ..
	MOVEM B,T2		;FROM TEMPORARY POINTER
CM6:	ILDB X,S2		;GET CHARACTER OF DEFINED COMMAND
	JUMPE X,CM7		;MATCHED TO END IF NULL
CM4:	MOVEI PA,T1		;GET USER'S COMMAND CHARACTER
	PUSHJ P,GCI		; ..
	  JRST CM5		;NEED MORE FROM FILE
	CAMN CH,X		;MATCH?
	JRST CM6		;YES. GO READ SOME MORE
	AOBJN N,CM2		;NO. TRY NEXT COMMAND.
	JRST ILCM1		;NO MORE TO TRY. ERROR.

CM5:	PUSHJ P,CMCIN		;READ USER'S COMMAND FROM FILE
	CAIN CH,C.CR		;END OF LINE?
	JRST ILCM		;YES. NO SUCH COMMAND
	MOVEI PA,CMSTP		;NO. STORE CHARACTER IN BUFFER
	PUSHJ P,WCI		; ..
	MOVE B,CMST2		;AND UPDATE TEMPORARY POINTER
	MOVEM B,T2		; ..
	JRST CM4		;GO CHECK NEW CHARACTER

CM7:	HLRZ A,CMTAB(N)		;HERE ON MATCH. GET COMMAND ADDRESS
	JRST 0(A)		;AND DISPATCH TO COMMAND CODE

ENDBCM:	PUSHJ P,LINSET		;SET FOR NEW LINE (BREAK COMMAND)
ENDCM:	JRST LCR		;END OF COMMAND. RETURN TO INPUT.
;SUBROUTINES FOR COMMAND SCANNER

CMCIN:	PUSHJ P,CCIN		;READ FROM INPUT FILE
	CAIG CH,172		;CHECK FOR LOWER CASE LETTERS
	CAIG CH,140		;..
	POPJ P,0		;NO. RETURN CHARACTER
	TRZ CH,40		;YES. MAKE UPPER CASE FOR COMMAND ROUTINE
	POPJ P,0		; AND RETURN UC EQUIVALENT

;ILLEGAL COMMAND ROUTINE

ILCM2:	MOVEI PA,CMSTP		;ADD BAD CHARACTER TO BUFFER
	PUSHJ P,WCI		; ..
ILCM1:	PUSHJ P,CCIN		;NOW ADD REST OF LINE
	CAIE CH,C.CR		;END OF LINE YET?
	JRST ILCM2		;NO. LOOP.
ILCM:	TTCALL 3,ILCMM		;TYPEOUT ILLEGAL COMMAND MESSAGE
ILCM3:	MOVEI PA,CMSTP		;READ OUT COMMAND BUFFER
	PUSHJ P,GCI		; TO TELETYPE
	 JRST ILCM4		;END OF LINE
	TTCALL 1,CH		;TYPE CHARACTER
	JRST ILCM3		;LOOP FOR WHOLE LINE
ILCM4:	TTCALL 3,CRLFM		;AND A CR-LF
	PUSHJ P,ONPAG		;TELL HIM WHAT PAGE ITS ON
	JRST LCR		;GO DISCARD THE REST OF COMMAND LINE

ILCMM:	ASCIZ /
?ILLEGAL COMMAND:
./
CRLFM:	ASCIZ /
/

ONPAG:	TTCALL 3,ILCMM2
	MOVE N,PAGENO
	PUSHJ P,DECTYO		;OUTPUT PAGE NUMBER
	TTCALL 3,CRLFM
	POPJ P,0

ILCMM2:	ASCIZ /ON OUTPUT PAGE /

; COMMAND TABLE

DEFINE CM (A,B) <	XWD A,[ASCIZ \B\]
>

CMTAB:	CM CENTER,<CENTER>
	CM INDENT,<INDENT>
	CM UPCAS,<UPPER CASE>
	CM LWCAS,<LOWER CASE>
	CM BREAK,<BREAK>
	CM CPAGE,<PAGE>
	CM SETTL,<TITLE>
	CM SETSTL,<SUBTITLE>
	CM SETRM,<RIGHT MARGIN>
	CM SETLM,<LEFT MARGIN>
	CM PARAG,<PARAGRAPH>
	CM SSP,<SPACING>
	CM SKIPL,<SKIP>
	CM LINSKP,<BLANK>
	CM JUSTN,<JUSTIFY>
	CM JUSOF,<NOJUSTIFY>
	CM SETTAB,<TAB STOPS>
	CM FILLN,<FILL>
	CM FILOF,<NOFILL>
	CM SETPG,<PAPER SIZE>
	CM TSTPG,<TEST PAGE>
	CM FIGUR,<FIGURE>
	CM INDEX,<INDEX>
	CM PINDX,<PRINT INDEX>
	CM FOOTN,<FOOTNOTE>
	CM NUMON,<NUMBER>
	CM NUMOF,<NONUMBER>
	CM ENDCM,<;>
ECTAB:
;READ SIGNED DECIMAL NUMBER FOR COMMAND DECODER
;NON-SKIP RETURN IF NONE FOUND

RCNO:	MOVEI N,0		;CLEAR ANSWER AC
	TLZ F,SIGNF		;AND SIGN FLAG
RCN1:	PUSHJ P,CCIN		;READ CHARACTER FROM COMMAND LINE
	CAIN CH,C.CR		;LEADING CARRIAGE RETURN?
	JRST RCN5		;YES. NON-SKIP RETURN
	CAIN CH,C.CMA		;COMMA SEPARATING ARGS?
	JRST RCN1		;YES. DISCARD.
	CAIE CH,C.SPC		;SPACES AND TABS?
	CAIN CH,C.TAB		; ..
	JRST RCN1		;YES. SKIP THEM
	CAIE CH,"-"		;MINUS SIGN?
	JRST RCN2		;NO.
	TLC F,SIGNF		;YES. COMPLEMENT SIGN FLAG
	JRST RCN1		;AND SKIP TABS ETC
RCN3:	PUSHJ P,CCIN		;READ ANOTHER CHARACTER
RCN2:	CAIG CH,"9"		;THIS CHAR A DIGIT?
	CAIGE CH,"0"		; ..
	JRST RCN4		;NO. STOP HERE.
	IMULI N,12
	ADDI N,-"0"(CH)		;YES. ADD IN THIS DIGIT
	JRST RCN3		;AND LOOP FOR MORE.

RCN4:	TLNE F,SIGNF		;IF SIGN NEGATIVE?
	MOVNS N			;NEGATE NUMBER
	AOS 0(P)		;NUMBER FOUND. SKIP RETURN
RCN5:	MOVEM CH,GCSCH		;STORE BREAK CHARACTER
	POPJ P,0		;AND RETURN FROM RCNO
SUBTTL OUTPUT SECTION
;LINE OUTPUT ROUTINE. THREE ENTRY POINTS

OUTNJ:	MOVE A,LNIN2		;HERE TO OUTPUT CURRENT LINE, NOT JUSTIFIED
	PUSHJ P,OUTNJ2		;CLEAR TJUSTF, CALL BODY OF ROUTINE
	TLZ F,EXSP3		;CLEAR LEFT/RIGHT SPACING FLAG
	POPJ P,0		;AND RETURN.

OUTLJ:	MOVE A,LSTSP		;END OF LINE IS LAST SPACE, IF ANY
	CAMG A,LNIN1		;..
OUTLIN:	MOVE A,LNIN2		;ELSE END OF INPUT LINE
	TLO F,TJUSTF		;COPY JUSTF TO TJUSTF
	TLNN F,JUSTF
OUTNJ2:	TLZ F,TJUSTF		; ..
	MOVEM A,LOUT2		;SAVE END OF LINE TO CONSIDER
	MOVE B,LNIN1		;AND BEGINNING.
	MOVEM B,LOUT1		; ..
	CAMG A,LOUT1		;LINE EMPTY?
	POPJ P,0		;YES. NO OUTPUT.
	TLNN F,TJUSTF		;JUSTIFYING THIS LINE?
	JRST OUTNJ1		;NO.
	SKIPG SPCNT		;YES. ANY SPACES IN LINE?
	JRST JUSERR		;NO. CAN'T JUSTIFY IT THEN.
	MOVE A,RMARG		;YES. COMPUTE WHERE TO EXPAND THEM
	SUB A,LMARG		;SIZE OF LINE
	SUB A,INDCT		; ..
	ADD A,LOUT1		;SUBTRACT SIZE OF DATA
	SUB A,LOUT2		;..
	ADD A,LSTNSP		;COMPENSATE FOR NON-SPACING CHARACTERS
	IDIV A,SPCNT		;NOW FIND HOW MANY MULT SPACES EACH SPACE IS
	MOVEM A,EXSP1		;MULTIPLIER FOR ALL SPACES
	TLNE F,EXSP3		;EXTRAS TO LEFT OR RIGHT?
	JRST OUTJC1		;LEFT. STORE NUMBER OF EXTRA SPACES
	MOVNS B			;RIGHT. GET SPACES BEFORE EXTRAS
	ADD B,SPCNT		;..
OUTJC1:	MOVEM B,EXSP2		;STORE FOR LATER
OUTNJ1:	MOVE A,INDCT		;GET INDENTING IN CASE OF PARAGRAPH
	SETZM INDCT		;(ONCE ONLY)
	ADD A,LMARG		;PLUS LEFT MARGIN
	PUSHJ P,NSPAC		;OUTPUT THAT MANY SPACES
OUTL1:	PUSHJ P,GLOUT		;READ A CHARACTER FROM OUTPUT BUFFER
	  JRST OUTLE		;END OF OUTPUT BUFFER
	CAIN CH,C.SPC		;REAL SPACE?
	JRST OUTSP		;YES. GO SEND N OF THEM
	CAIN CH,C.NXS		;NON-EXPANDABLE SPACE?
	MOVEI CH,C.SPC		;YES. MAKE IT ONE SPACE
	PUSHJ P,CCOUT		;OUTPUT THE CHARACTER
	JRST OUTL1		;LOOP BACK FOR MORE.

JUSERR:	TTCALL 3,JUSRM1		;OUTPUT ERROR MESSAGE ON TTY
	MOVE A,LOUT1		;COPY POINTER TO LINE
	MOVE B,LOUT2		; ..
	MOVEM A,T1		; ..
	MOVEM B,T2		; ..
JUSER1:	MOVEI PA,T1		;GET CHAR FROM LINE
	PUSHJ P,GCI		; ..
	 JRST JUSER2		;END OF LINE
	TTCALL 1,CH		;TYPE IT
	JRST JUSER1		;LOOP FOR WHOLE LINE
JUSER2:	TTCALL 3,CRLFM		;TYPE OUT CRLF
	PUSHJ P,ONPAG		;TELL HIM WHERE HE LOST
	TLZ F,TJUSTF		;SAY NOT JUSTIFYING
	JRST OUTNJ1		;AND OUTPUT LINE WITHOUT JUSTIFYING

JUSRM1:	ASCIZ /
?CAN'T JUSTIFY LINE:
/
;HERE TO OUTPUT AN EXPANDABLE SPACE.

OUTSP:	MOVEI CH,C.SPC		;OUTPUT A TRUE SPACE
	PUSHJ P,CCOUT		; ..
	TLNN F,TJUSTF		;ARE WE JUSTIFYING?
	JRST OUTL1		;NO, JUST LOOP
	SKIPLE A,EXSP1		;YES. HOW MANY MULTIPLE SPACES?
	PUSHJ P,NSPAC		;IF ANY, SEND THEM.
	SOSL EXSP2		;TO EXTRA BLANKS YET?
	JRST OUTS1		;NO.
	TLNN F,EXSP3		;YES. SPACES LEFT OR RIGHT?
	JRST OUTS2		;RIGHT. OUTPUT A SPACE
	JRST OUTL1		;LEFT. NO MORE EXTRAS, JUST LOOP
OUTS1:	TLNN F,EXSP3		;LEFT OF BREAK. WANT LEFT SPACES?
	JRST OUTL1		;NO. HOLD FOR LATER
OUTS2:	MOVEI CH,C.SPC		;YES. OUTPUT A SPACE
	PUSHJ P,CCOUT		; ..
	JRST OUTL1		;AND LOOP FOR REST OF LINE
;END OF LINE, AND FOOTNOTE PROCESSING

OUTLE:	TLC F,EXSP3		;COMPLEMENT L-R FLAG FOR EACH LINE
	MOVE A,LNIN1		;CLEAR INPUT LINE BUFFER
	EXCH A,LNIN2		; BY BACKING UP POINTER
	CAMG A,LOUT2		;ANY LEFT TO OUTPUT?
	JRST OUTLE4		;NO.
	MOVEM A,GCIN2		;YES. SAVE POINTER
	MOVE A,LOUT2		; ..
	MOVEM A,GCINP		;FOR GET-CHARACTER ROUTINE
	TLO F,GCINF		;NEED TO INPUT FROM BUFFER FIRST
OUTLE4:	MOVE A,NSPNG		;OUTPUT CRLFS FOR THIS LINE
	PUSHJ P,SKIPN		; ..
	SKIPE FOOTC		;ANY FOOTNOTE LINE COMMANDS DECLARED?
OUTFT:	TLNE F,FOOTFG		;YES. DOING THEM ALREADY?
OUTFT1:	JRST LINSET		;SET UP FOR NEW LINE, RETURN FROM OUTLIN
	MOVE A,NLPG		;SEE IF ROOM FOR FOOTNOTES
	SUB A,FOOTC		; ..
	CAMGE A,LINEC		; ..
	JRST OUTFT1		;NO. HOLD TILL NEXT PAGE
	MOVEM A,NLPG		;REDUCE EFFECTIVE PAGE SIZE
	MOVE B,FOOTP2		;ADD LATEST FOOTNOTES TO POINTER
	MOVEM B,FOOTP4		; ..
	SETZM FOOTC		;CLEAR COUNT OF SAVED FOOTNOTE LINES
	SUB A,NSPNG		;MINUS NORMAL SPACING
	CAMG A,LINEC		;GREATER THAN LINE COUNT?
	PUSHJ P,BPAGE		;YES. BREAK PAGE HERE.
	JRST OUTFT1		; AND RETURN
;SUBROUTINE TO SKIP N LINES ON OUTPUT FILE

SKIPN:	TLNN F,ULMODE		;NEED TO CONSIDER SAVED UNDERLINES?
	JRST CCOUT3		;YES. GO DO SO.
CCOUT5:	ADDM A,LINEC		;COUNT LINES
	SETZM NSPCH		;CLEAR PER-LINE COUNTS
	SETZM CPOS		; ..
CCOUL1:	MOVEI S1,CRLFM		;END-OF-LINE MESSAGE
	PUSHJ P,FMSG		;OUTPUT CRLF TO LINE
	SOJG A,CCOUL1		;OUTPUT AS MANY AS REQUESTED
	MOVE A,LINEC		;CHECK FOR END OF PAGE
	ADD A,NSPNG		;POSITION OF NEXT LINE IF ALLOWED
	CAMLE A,NLPG		;UP TO A FULL PAGE?
	PUSHJ P,BPAGE		;YES. HANDLE HEADING
	POPJ P,0		;RETURN FROM SKIPN

;ROUTINE TO OUTPUT N SPACES TO OUTPUT FILE, N .GE. 0, N IN A.

NSPAC:	JUMPLE A,CPOPJ		;RETURN IF NONE TO OUTPUT
	ADDM A,CPOS		;UPDATE CARRIAGE POSITION
	MOVEI CH,C.SPC		;GET A SPACE
	PUSHJ P,FOUT		;OUTPUT TO FILE
	SOJG A,.-2		;LOOP FOR N SPACES
	POPJ P,0		;AND RETURN.

;ROUTINES TO OUTPUT A STRING TO THE OUTPUT FILE

PSTRPA:	MOVE A,0(PA)		;GET POINTER FROM PA
	MOVE B,1(PA)		; ..
PSTRNG:	MOVEM A,PSTRP		;STORE IN TEMP
	MOVEM B,PSTRP+1		; ..
PSTRL:	MOVEI PA,PSTRP		;GET A CHARACTER FROM THE TEMP POINTER
	PUSHJ P,GCI		; ..
	 POPJ P,0		;NONE LEFT
	PUSHJ P,CCOUT		;OUTPUT CHAR TO FILE
	JRST PSTRL		;LOOP FOR WHOLE STRING

PSTRAZ:	HRLI S1,440700		;OUTPUT ASCIZ FROM S1
PSTRZL:	ILDB CH,S1		;GET A CHARACTER
	JUMPE CH,CPOPJ		;IF END,QUIT
	PUSHJ P,CCOUT		;OUTPUT TO FILE
	JRST PSTRZL		;LOOP FOR WHOLE STRING
SUBTTL CHARACTER PROCESSORS
;SUBROUTINE TO OUTPUT CHARACTER TO FILE,AFTER SOME TESTS

CCOUT:	CAIE CH,ULCHS		;UNDERLINE CHARACTER?
	JRST CCOUT1		;NO.
	TLNN F,ULMODE		;YES. BY LINE?
	JRST CCOUT2		;YES.
	TLNN F,ULBSF		;NO. BY BACKSPACING?
	JRST CCOUT1		;NO. ASSUME NON-SPACING
	MOVEI CH,C.LPUS		;CONVERT TO OUTPUT UNDERLINE
	PUSHJ P,FOUT		;YES. SEND UNDERLINE
	MOVEI CH,C.BS		;AND FOLLOW WITH BACKSPACE
CCOUT1:	CAIN CH,C.QTS		;QUOTED SPACE?
	MOVEI CH,C.SPC		;YES. MAKE REAL SPACE
	PUSHJ P,FOUT		;SEND TO OUTPUT FILE
	AOS CPOS		;COUNT POSITION OF CARRIAGE
	POPJ P,0		;AND RETURN.

CCOUT2:	MOVE B,CPOS		;YES. STORE POSITION IN BUFFER FOR LATER
	MOVEM B,@ULPOS		;INTO UNDERLINE BUFFER
	AOS ULPOS		;STEP BUFFER POINTER. (SHOULD CHECK IT)
	POPJ P,0		;RETURN WITHOUT TYPING THE UNDERLINE.

;CONTINUATION OF OUTPUT N LINES

CCOUT3:	MOVEI B,ULPBF		;START CONSIDERING UNDERLINE BUFFER
	CAMN B,ULPOS		;ANY UNDERLINES IN THE BUFFER?
	JRST CCOUT5		;NO. GO SEND LINE
	PUSH P,A		;SAVE NUMBER OF LINES TO BE OUTPUT
	TLNE F,ULSUPF		;UNDERLINES SUPPRESSED?
	JRST CCOUT4		;YES. SKIP OUTPUT SECTION
	MOVEM B,ULPT1		;STORE START OF BUFFER
	MOVEI CH,C.CR		;OUTPUT CARRIAGE RETURN TO LINE
	PUSHJ P,FOUT		;SEND TO FILE (NO LF YET)
	SETZM CPOS		;START AT BEGINNING OF LINE
CCOUT6:	MOVE A,@ULPT1		;GET POSITION WHERE UNDERLINE GOES
	SUB A,CPOS		;HOW FAR TO IT?
	PUSHJ P,NSPAC		;SPACE TO THE UNDERLINE
	MOVEI CH,C.LPUS		;GET LINE-PRINTER UNDERSCORE CHARACTER
	PUSHJ P,FOUT		;SEND TO FILE
	AOS CPOS		;COUNT POSITION
	AOS A,ULPT1		;COUNT UNDERLINE BUFFER POINTER
	CAME A,ULPOS		;UP THRU LAST UNDERLINE?
	JRST CCOUT6		;NO. GO OUTPUT ANOTHER ONE
CCOUT4:	MOVEI A,ULPBF		;YES. RESET TO START OF BUFFER
	MOVEM A,ULPOS		; ..
	POP P,A			;RESTORE NUMBER OF LINES
	JRST CCOUT5		;AND GO OUTPUT THEM
;GET INPUT CHARACTER FROM SOURCE FILE

GCIN:	TLNE F,GCINF		;STILL READING FROM BUFFER?
	JRST GCIN1		;YES. GO RE-READ CHARACTER
GCIN3:	SKIPL GCSCH		;NO. SAVED A CHARACTER?
	JRST GCIN5		;YES. GO GET IT.
	SKIPL ULMCH		;SAVING CHARACTER DUE TO UNDERLINE?
	JRST ULMC1		;YES. GO GET IT.
GCIN5:	PUSHJ P,CCIN		;NO. GET CHARACTER FROM FILE.
	CAIN CH,CWARN		;QUOTING A CHARACTER?
	JRST CWR1		;YES. GO GET REAL CHARACTER
	CAIN CH,SHUP		;UPSHIFT CHARACTER?
	JRST SHUP1		;YES. SEE IF SHIFT-LOCK
	CAIN CH,SHDN		;DOWNSHIFT CHARACTER?
	JRST SHDN1		;YES. SEE IF SHIFT-UNLOCK
	CAIN CH,ULCHI		;UNDERLINE REQUEST?
	JRST ULCH		;YES. GO PROCESS
	CAIN CH,QTSP		;QUOTED SPACE?
	JRST QTSP1		;YES.
	CAIG CH,"Z"		;UPPER CASE LETTER?
	CAIGE CH,"A"		;..
	SKIPA			;NO.
	ADD CH,CAS		;YES. ADD ON CURRENT CASE
GCINR:	TLNE F,ULMSW		;UNDERLINE SHIFT-LOCK ON?
	JRST ULMC2		;YES. GO HANDLE
	POPJ P,0		;NO. HAVE CHARACTER NOW.

;SPECIAL CASES OF INPUT CHARACTER.

QTSP1:	MOVEI CH,C.QTS		;QUOTED SPACE (NO UNDERLINING)
	POPJ P,0		;RETURN WITHOUT UNDERLINE

ULCH:	AOS NSPCH		;COUNT NON-SPACING INPUT
	MOVEI CH,ULCHS		;CONVERT TO STORAGE UNDERLINE
	POPJ P,0		;AND RETURN

GCIN1:	PUSHJ P,GGCINP		;GET CHARFROM INPUT BUFFER
	 TLZA F,GCINF		;NONE LEFT.
	POPJ P,0		;RETURN IT.
	JRST GCIN3		;GO READ FROM FILE, ETC.

CWR1:	PUSHJ P,CCIN		;READ CHARACTER, NO TRANSLATION
	JRST GCINR		;AND RETURN IT, MAYBE UNDERLINED

;MORE SPECIAL CASES OF GET-CHARACTER ROUTINE

SHUP1:	PUSHJ P,CCIN		;READ A CHARACTER
	CAIN CH,ULCHI		;UNDERLINE? LOCK ON UNDERLINE?
	JRST ULMON		;YES.
	CAIE CH,SHUP		;DOUBLE UPSHIFT?
	JRST GCINR		;NO. GO RETURN WITH TRUE CASE.
	SETZM CAS		;DOUBLE UPSHIFT. CLEAR CASE OFFSET
	JRST GCIN3		;AND GO READ ANOTHER CHARACTER.

SHDN1:	PUSHJ P,CCIN		;GET ANOTHER CHARACTER
	CAIN CH,ULCHI		;UNLOCK UNDERLINE?
	JRST ULMOF		;YES. GO DO SO.
	CAIN CH,SHDN		;SECOND DOWNSHIFT?
	JRST SHDN2		;YES.
	CAIG CH,"^"		;IN RANGE FOR LOWERING?
	CAIGE CH,"@"		; ..
	SKIPA			;NO.
	ADDI CH,40		;YES. MAKE IT LOWER CASE
	JRST GCINR		;RETURN THIS, UNDERLINED IF NEEDED.
SHDN2:	MOVEI A,40		;SET CASE OFFSET TO LC FOR LETTERS
	MOVEM A,CAS		; ..
	JRST GCIN3		;AND GO READ ANOTHER CHARACTER

ULMC2:		;HERE WHEN RETURNING A CHAR, BUT UNDERLINE LOCKED ON.
	CAIE CH,C.QTS		;QUOTED SPACE?
	CAIG CH,C.SPC		;PRINTING CHARACTER?
	POPJ P,0		;NON-PRINTING OR QUOTED SPACE. DON'T UNDERLINE
	MOVEM CH,ULMCH		;THIS MAY BE UNDERLINED. SAVE IT FOR LATER
	JRST ULCH		;AND PUT OUT UNDERLINE (BUFFER OR FILE)

ULMC1:	MOVE CH,ULMCH		;RESTORE SAVED CHARACTER
	SETOM ULMCH		;NEGATIVE TO INDICATE NOT THERE.
	POPJ P,0		;RETURN WITH THIS SAVED CHARACTER

ULMON:	TLOA F,ULMSW		;UNDERLINE LOCKED ON
ULMOF:	TLZ F,ULMSW		;UNDERLINE LOCKED OFF
	JRST GCIN3		;GO READ ANOTHER CHARACTER

;ROUTINE TO READ INPUT FROM FILE OR FOOTNOTE AS APPROPRIATE

CCIN:	SKIPL CH,GCSCH		;ANY CHARACTER SAVED FROM EARLIER PASS?
	JRST GCIN4		;YES. GO RETURN IT.
	TLNE F,FOOTFG		;CHARACTERS COMING FROM FOOTNOTE?
	JRST FOOTCH		;YES. GO GET ONE
	PUSHJ P,FIN		;NO. READ FROM FILE
	POPJ P,0		;AND RETURN THAT.

GCIN4:	SETOM GCSCH		;NO MORE SAVED CHARACTERS.
	POPJ P,0		;RETURN LAST SAVED ONE.

FOOTCH:	MOVEI PA,FOOTP3		;GET CHARACTER FROM FOOTNOTE STRING
	PUSHJ P,GCI		;GET THE CHARACTER
	  HALT .		;NONE THERE. I HAVE BLOWN IT GOOD
	POPJ P,0		;RETURN THE CHARACTER
SUBTTL COMMANDS

INDENT:	PUSHJ P,OUTNJ		;OUTPUT REST OF CURRENT LINE
	PUSHJ P,RCNO		;READ SIGNED DECIMAL NUMBER
PARAG1:	  MOVE N,PARIND		;NONE. USE CURRENT VALUE
	CAMLE N,RMARG		;LEGITIMATE VALUE?
	JRST ILCM		;NO. COMPLAIN
	MOVEM N,INDCT		;YES. STORE ARGUMENT
	JRST ENDBCM		;END OF BREAK COMMAND

BREAK:	PUSHJ P,OUTNJ		;THE SIMPLE BREAK COMMAND.
	JRST ENDBCM		;RETURN AS ALL BREAK COMMANDS DO

UPCAS:	TDZA A,A		;SET CASE OFFSET TO ZERO
LWCAS:	MOVEI A,40		;SET FOR LOWER CASE OFFSET
	MOVEM A,CAS		;STORE
	JRST ENDCM		;END OF COMMAND (NOT BREAK)

NUMON:	PUSHJ P,RCNO		;NUMBER PAGES. ANY PARTICULAR NUMBER?
	 MOVE N,PAGENO		;NO. LEAVE SAME AS BEFORE
	MOVEM N,PAGENO		;STORE PAGE NUMBER
	TLOA F,NUMBF		;TURN ON FLAG TO CAUSE NUMBERING
NUMOF:	TLZ F,NUMBF		;TURN OFF NUMBERING.
	JRST ENDCM		;END OF NON-BREAK COMMAND

;PAGE COMMAND

CPAGE:	PUSHJ P,OUTNJ		;OUTPUT CURRENT LINE
DPAGE:	PUSHJ P,BPAGE		;BREAK PAGE, HEADING
	JRST ENDBCM		;END OF BREAK-CLASS COMMAND

;TITLE COMMAND

SETTL:	MOVEI PA,TTLBUF		;COMPUTE POINTER TO TITLE BUFFER
	PUSHJ P,CSP		; ..
	MOVEM A,TTLP1		;STORE.
	MOVEM B,TTLP2		; ..
	PUSHJ P,GCIN		;READ CHARACTER AFTER COMMAND
	CAIN CH,C.SPC		;SPACE? SKIP JUST ONE.
SETTL1:	PUSHJ P,GCIN		;READ A CHARACTER
	CAIN CH,C.CR		;END OF COMMAND LINE?
	JRST ENDCM		;YES. QUIT
	MOVEI PA,TTLP1		;NO. PUT CHAR IN STRING BUFFER
	PUSHJ P,WCI		; ..
	JRST SETTL1		;LOOP TILL END
;SET RIGHT MARGIN COMMAND

SETRM:	PUSHJ P,OUTNJ		;BREAK-CLASS COMMAND
	PUSHJ P,RCNO		;GET ARGUMENT
	 MOVE N,PRMRG		;IF NONE, INITIALIZE
	CAMG N,LMARG		;MUST ALSO BE RIGHT OF LEFT MARGIN
	JRST ILCM		;ISNT. ERROR
	MOVEM N,RMARG		;STORE RIGHT MARGIN
	JRST ENDBCM		;END OF COMMAND

;SET LEFT MARGIN COMMAND

SETLM:	PUSHJ P,OUTNJ		;BREAK COMMAND
	PUSHJ P,RCNO		;GET ARGUMENT
	 MOVEI N,ILMRG		;IF NONE,INITIALIZE
	CAML N,RMARG		;AND LESS THAN RIGHT MARGIN?
	JRST ILCM		;NO. ERROR.
	MOVEM N,LMARG		;OK SAVE AS LEFT MARGIN
	JRST ENDBCM		;AND END BREAK-CLASS COMMAND

;PAGE SIZE COMMAND

SETPG:	PUSHJ P,RCNO		;GET ARGUMENT
	  JRST ILCM		;MUST BE ONE
	CAIG N,12		;LONG ENOUGH TO BE REASONABLE FOR HEADING
	  JRST ILCM		;NO. ERROR
	MOVEM N,NLPG		;SAVE AS LENGTH OF THIS PAGE
	MOVEM N,PNLPG		;AND PERMANENT PAGE LENGTH
	PUSHJ P,RCNO		;SEE IF SECOND ARGUMENT
	 MOVE N,PRMRG		;NO
	CAMG N,LMARG
	JRST ILCM
	MOVEM N,PRMRG		;STORE PAGE WIDTH
	MOVEM N,RMARG
	JRST ENDCM		;END OF COMMAND

;PARAGRAPH COMMAND

PARAG:	PUSHJ P,OUTNJ		;FINISH CURRENT LINE
	PUSHJ P,RCNO		;OPTIONAL INDENTING ARGUMENT
	  MOVE N,PARIND		;NO. USE OLD VALUE
	MOVEM N,PARIND		;STORE PARA INDENT VALUE
	MOVE A,LINEC		;GET LINE COUNT USED ON THIS PAGE
	CAIG A,5		;BEYOND HEADING YET?
	JRST PARAG1		;NO. GO CHECK ARGUMENT AND RETURN
	MOVE A,NSPNG		;GET NORMAL LINE-SPACING
	ADDI A,1		;COMPUTE SIZE OF PARAGRAPH BREAK
	ASH A,-1		; ..
	MOVE N,LINEC
	ADD N,A			;CHECK FOR END OF PAGE
	ADD N,NSPNG		; ..
	CAML N,NLPG		;PAGE TOO FULL FOR THE BREAK NEEDED?
	JRST PARAG2		;YES. GO BREAK PAGE HERE.
	PUSHJ P,SKIPN		;NO. GO SKIP N LINES (N IN A)
	JRST PARAG1		;CHECK ARGUMENT AND RETURN

PARAG2:	PUSHJ P,BPAGE		;BREAK PAGE, ADD HEADING
	JRST PARAG1		;AND RETURN
;TEST PAGE COMMAND

TSTPG:	PUSHJ P,OUTNJ		;BREAK LINE FIRST
	PUSHJ P,RCNO		;GET ARGUMENT OF TEST
	  JRST ILCM		;MUST BE ONE
	ADD N,LINEC		;ADD ON CURRENT LINE POSITION
	CAMLE N,NLPG		;COMPARE TO LENGTH W/O FOOTNOTES
	PUSHJ P,BPAGE		;TEST SHOWS NEAR END. BREAK PAGE.
	JRST ENDBCM		;RETURN FROM TSTPG

;SPACING COMMAND

SSP:	PUSHJ P,OUTNJ		;BREAK LINE FIRST
	PUSHJ P,RCNO		;GET ARGUMENT OF SPACING COMMAND
	  JRST ILCM		;MUST BE ONE
	CAIG N,5		;MUST BE IN RANGE 1 TO 5
	CAIG N,0		; ..
	  JRST ILCM		;NOT. ERROR.
	MOVEM N,NSPNG		;OK. STORE AS NORMAL SPACING
	JRST ENDBCM		;END OF SPACING COMMAND

;SUBTITLE COMMAND

SETSTL:	MOVEI PA,STTLBF		;COMPUTE POINTER TO
	PUSHJ P,CSP		; SUBTITLE BUFFER
	MOVEM A,STTLP1		;STORE EMPTY POINTER
	MOVEM B,STTLP2		; ..
	PUSHJ P,GCIN		;GET CHARACTER FROM INPUT LINE
	CAIN CH,C.SPC		;SKIP ONE LEADING SPACE
SETST1:	PUSHJ P,GCIN		;GET CHARACTER FROM INPUT LINE
	CAIN CH,C.CR		;END OF LINE ON INPUT?
	JRST ENDCM		;YES. END OF SUBTITLE COMMAND
	MOVEI PA,STTLP1		;NO. WRITE INTO BUFFER
	PUSHJ P,WCI		; ..
	JRST SETST1		;LOOP TILL END OF LINE
;LINE SKIPPING COMMANDS

SKIPL:	SKIPA S2,NSPNG		;SKIP COMMAND. N CURRENT LINES
LINSKP:	MOVEI S2,1		;BLANK COMMAND. N REAL LINES
	PUSH P,S2		;SAVE S2 FOR SAFETY
	PUSHJ P,OUTNJ		;OUTPUT CURRENT LINE
	POP P,S2		;RESTORE S2
	MOVE A,LINEC		;CHECK CURRENT POSITION
	CAIG A,5		;AT TOP OF PAGE?
	JRST ENDBCM		;YES. IGNORE BLANK COMMAND.
	PUSHJ P,RCNO		;GET OPTIONAL ARGUMENT
	 MOVEI N,1		;IF NONE, ASSUME 1
	IMUL N,S2		;MULTIPLY BY 1 OR NSPNG
	MOVE A,N		;CHECK IF ROOM ON PAGE
	ADD N,LINEC		;ADD CURRENT LINE
	ADD N,NSPNG		;PLUS SPACING TO NEXT LINE
	CAML N,NLPG		;ROOM FOR ANOTHER?
	JRST DPAGE		;NO. MAKE A NEW PAGE
	PUSHJ P,SKIPN		;YES. SPACE OUT C(A) LINES
	JRST ENDBCM		;END OF COMMAND

FIGUR:	PUSHJ P,OUTNJ		;BREAK COMMAND
	PUSHJ P,RCNO		;GET ARGUMENT
	  MOVEI N,1		;IF NONE,ASSUME ONE LINE
	CAMG N,NLPG		;CHECK FOR RATIONAL ARGUMENT
	CAIG N,0		; ..
	  JRST ILCM		;BAD. ERROR.
	PUSH P,N		;SAVE DESIRED SPACE
	ADD N,LINEC		;SEE IF NEED NEW PAGE FOR FIGURE
	CAML N,NLPG		;WOULD THIS OVERFLOW PAGE
	PUSHJ P,BPAGE		;YES. BREAK PAGE
	POP P,A			;GET BACK DESIRED SIZE
	PUSHJ P,SKIPN		;SPACE THAT OUT
	JRST ENDBCM		;END OF BREAK COMMAND
JUSTN:	PUSHJ P,OUTNJ		;BREAK COMMAND
	TLO F,PJUSTF+JUSTF	;TURN ON JUSTIFYING
	JRST ENDBCM		;AND RETURN FROM COMMAND

JUSOF:	PUSHJ P,OUTNJ		;BREAK CURRENT LINE
	TLZ F,PJUSTF+JUSTF	;TURN OFF JUSTIFY BITS
	JRST ENDBCM		;AND FINISH COMMAND

FILLN:	PUSHJ P,OUTNJ		;BREAK COMMAND
	TLO F,FILLF+JUSTF	;TURN ON FILLING, COPY PJUSTF TO JUSTF
	TLNN F,PJUSTF		;COPY PERMANENT FLAG
	TLZ F,JUSTF		;TO CURRENT ONE.
	JRST ENDBCM		;AND OF COMMAND

FILOF:	PUSHJ P,OUTNJ		;BREAK CURRENT LINE
	TLZ F,FILLF+JUSTF	;TURN OFF FILLING AND JUSTIFYING
	JRST ENDBCM		;END OF COMMAND

SETTAB:	SETZM NTABS		;CLEAR NUMBER OF TABS
SETT1:	PUSHJ P,RCNO		;GET ANOTHER STOP IF ANY
	  JRST ENDCM		;NO, RETURN
	AOS X,NTABS		;GET POINTER
	MOVEM N,TABTAB-1(X)	;STORE THIS TABSTOP
	CAIGE X,TABTL		;CHECK TABLE SIZE
	JRST SETT1		;OK.
	JRST ILCM		;TOO MANY TABS

;ROUTINE TO FIND NEXT TABSTOP FOR OUTLIN ROUTINE. CALL
;WITH CURRENT POSITION IN A.

TAB:	MOVEI X,0		;START AT FIRST TABSTOP
	JRST TAB1		;PRE-ENDCHECK, IN CASE NONE.
TAB2:	MOVE C,TABTAB-1(X)	;GET CURRENT TAB STOP
	CAMGE A,C		;THIS STOP BEYOND CURRENT POS?
	JRST TAB3		;YES. GET DIFFERENCE
TAB1:	CAMGE X,NTABS		;LOOKED AT ALL TAB STOPS?
	AOJA X,TAB2		;NO. LOOK AT ANOTHER
	MOVE C,RMARG		;YES. ASSUME A TABSTOP AT RIGHT END
TAB3:	SUB C,A			;GET DISTANCE TO TABSTOP
	MOVE A,C		;ANSWER IN A
	POPJ P,0		;RETURN
;ROUTINE TO SPACE TO TOP OF FORM

FORM:	SKIPG N,LINEC		;GET CURRENT LINE POSITION
	POPJ P,0		;ALREADY AT TOP. RETURN.
	TLNN F,FFDSW		;SPACING WITH FF OR LFS
	JRST BPG2		;LINEFEEDS
	MOVEI CH,C.FF		;OUTPUT FORMFEED TO FILE
	PUSHJ P,FOUT		; ..
	JRST BPG3		;ADJUST COUNTS
BPG2:	IDIVI N,HWPLN		;IN CASE CURRENT PAGE OVER ONE REAL PAGE
	SUBI N1,HWPLN		;GET - NUMBER OF LINES TO TOP OF PAGE
	MOVEI CH,C.LF		;OUTPUT LINEFEEDS
	PUSHJ P,FOUT		; ..
	AOJL N1,.-2		; ..
BPG3:	SETZM LINEC		;CURRENT LINE NOW ZERO
	AOS PAGENO		;COUNT PAGE NUMBER
	TLNE F,PAUSF		;WAIT FOR NEW PAPER?
	TTCALL 0,A		;YES. READ AND DISCARD COMMAND CHAR
	POPJ P,0		;RETURN FROM FORM ROUTINE
;ROUTINE TO BREAK PAGE AND OUTPUT HEADING

BPAGE:	MOVE A,LINEC		;CURRENT LINE POSITION
	CAIG A,5		;IN HEADING AREA?
	POPJ P,0		;YES. DON'T DO IT AGAIN.
	MOVE A,FOOTP3		;SEE IF ANY DATA IN FOOTNOTE BUFFER
	CAME A,FOOTP4		; ..
	JRST FOOTGO		;YES. GO PROCESS THAT FIRST
FOOTX:	PUSHJ P,FORM		;OUTPUT FORMFEED OR LINEFEEDS
	MOVEI A,1		;SKIP A LINE
	PUSHJ P,SKIPN		; ..
	MOVEI PA,TTLP1		;OUTPUT TITLE TO FILE
	PUSHJ P,PSTRPA		;PRINT STRING FROM PA
	TLNN F,NUMBF		;WANT PAGE NUMBER?
	JRST BPGN		;NO.
	MOVE A,PRMRG		;FIND POSITION WHERE THIS LEFT US
	ADD A,ULPOS		; ..
	SUBI A,ULPBF		;ADD IN ANY UNDERLINES
	SUB A,TTLP2		;AND TITLE CHARACTERS
	ADD A,TTLP1		; ..
	SUBI A,10		;MINUS 8 FOR "PAGE NNN"
	PUSHJ P,NSPAC		;SPACE OVER TO THERE
	MOVEI S1,[ASCIZ /PAGE /]	;PAGE MESSAGE
	PUSHJ P,FMSG		;OUTPUT TO FILE
	MOVE N,PAGENO		;OUTPUT PAGE NUMBER
	PUSHJ P,PPGNO		;3 DIGIT DECIMAL PRINT
BPGN:	MOVEI A,1		;OUTPUT THE LINE WITH TITLE
	PUSHJ P,SKIPN		; ..
	MOVEI PA,STTLP1		;OUTPUT THE SUBTITLE, IF ANY
	PUSHJ P,PSTRPA		; ..
	MOVEI A,3		;AND OUTPUT THIS LINE,
	JRST SKIPN		;INCLUDING SUBTITLE, AND RETURN FROM BPAGE

;SUBROUTINE FOR PAGE NUMBER OUTPUT

PPGNO:	MOVEI CH,C.SPC		;LEADING SPACES IF NEEDED
	CAIG N,^D99		;3 DIGITS?
	PUSHJ P,FOUT		;NO. SPACE.
	CAIG N,^D9		;2 DIGITS?
	PUSHJ P,FOUT		;NO. SPACE AGAIN.
DECPRT:	IDIVI N,12		;STANDARD DECIMAL PRINT ROUTINE
	HRLM N1,0(P)		; ..
	SKIPE N			;DONE?
	PUSHJ P,DECPRT		;NO
	HLRZ CH,0(P)		;GET A DIGIT
	ADDI CH,"0"		;MAKE ASCII DIGIT
	JRST FOUT		;OUTPUT TO FILE.
;CENTER COMMAND

CENTER:	PUSHJ P,RCNO		;SEE IF ANY ARGUMENT
	  MOVE N,PRMRG		;NO. DEFAULT IS RIGHT SIDE OF PAPER
	MOVEM N,CENTC		;STORE
	PUSHJ P,OUTNJ		;OUTPUT CURRENT LINE
	PUSHJ P,GCIN		;DISCARD REST OF THIS COMMAND
	CAIE CH,C.LF		; ..
	JRST .-2		; ..
	MOVE A,LNIN1		;CLEAR INPUT BUFFER
	MOVEM A,LNIN2		; ..
CENT1:	PUSHJ P,GCIN		;READ LINE TO BE CENTERED
	CAIN CH,C.CR		;THROUGH CR
	JRST CENT2		; CR. DONE.
	PUSHJ P,WLNIN1		;PUT IN LINE INPUT BUFFER
	JRST CENT1		;LOOP FOR MORE

CENT2:	MOVE A,CENTC		;COMPUTE SPACING BEFORE LINE
	ADD A,LNIN1		;AS HALF RIGHT MARGIN
	SUB A,LNIN2		;MINUS HALF OF LINE SIZE
	ADD A,NSPCH		; INCLUDING UNDERLINES, ETC.
	ASH A,-1		;TAKE HALF
	PUSHJ P,NSPAC		;OUTPUT SPACES
	MOVEI PA,LNIN1		;THEN OUTPUT LINE BUFFER TO FILE
	PUSHJ P,PSTRPA		;..
	MOVE A,NSPNG		;THEN SPACE TO NEXT LINE
	PUSHJ P,SKIPN		; ..
	JRST ENDBCM		;AND RETURN AFTER COMMAND
SUBTTL INDEX OPERATIONS
;ROUTINE TO ADD ITEM TO INDEX DATA AT TOP OF CORE

INDEX:	SETZM ICBUF		;FIRST, PUT ITEM IN COMPARISON BUFFER
	MOVE A,[XWD ICBUF,ICBUF+1]
	BLT A,ICBFE		;CLEAR COMPARISON BUFFER
	MOVE S1,[POINT 7,ICBUF]
	MOVEI N,<ICBFE-ICBUF>*5	;END TEST ON BUFFER
	TLZ F,IDXRF		;CLEAR REPEATED ITEM FLAG
	PUSHJ P,GCIN		;GET CHARACTER OF INDEX DATA
	CAIE CH,C.SPC		;SKIP LEADING SPACES OR TABS
	CAIN CH,C.TAB		; ..
	JRST .-3		; ..
INDX1:	CAIN CH,C.CR		;COPY THROUGH END OF LINE
	JRST INDX2		;END.
	IDPB CH,S1		;STORE CHARACTER OF INDEX DATA
	PUSHJ P,GCIN		;GET NEXT CHARACTER
	SOJG N,INDX1		;LOOP IF ROOM
INDX2:	IBP S1			;SECOND, FIND PLACE FOR ITEM IN INDEX
	MOVEI S1,1(S1)		;SIZE OF BLOCK TO BE ADDED
	SUBI S1,ICBUF		; ..
	HRRZ A,XFIRST		;GET ADDRESS OF FIRST ITEM SO FAR
	JUMPE A,INDXV		;IF NONE, LIST IS EMPTY. START IT.
INDXL2:	TLZ F,IDXCF		;CLEAR CASE-DIFFERENCE CATCHER
	HRRZ B,1(A)		;ADDRESS OF ASCIZ OF OLD ITEM
	HRLI B,440700		;POINTER TO IT.
	MOVE C,[POINT 7,ICBUF]	;POINTER TO NEW ITEM
INDXL1:	ILDB CH,B		;GET CHAR OF OLD
	ILDB C2,C		;AND ONE OF NEW
	CAME CH,C2		;SAME BEFORE CASE MERGE?
	TLO F,IDXCF		;NO. REMEMBER THAT.
	CAIL CH,141		;CONVERT LC TO UC
	TRZ CH,40		; ..
	CAIL C2,141		; ..
	TRZ C2,40		; ..
	CAMN CH,C2		;SAME?
	JUMPN CH,INDXL1		;YES. LOOP UNLESS END OF STRINGS
	CAMLE CH,C2		;WHICH IS FIRST?
	JRST INDX3		;NEW ONE IS FIRST, AND DIFFERENT
	CAMN CH,C2		;ARE THEY IDENTICAL?
	JRST INDX4		;YES. NO NEED FOR NEW COPY. ADJUST POINTERS
IDX4A:	HRRZ B,0(A)		;NO. OLD ONE IS FIRST. LOOK FURTHER
	JUMPE B,INDX5		;END OF LIST. NEW IS LAST
	MOVEI A,0(B)		;MOVE LINK TO A
	JRST INDXL2		;LOOK FURTHER
INDX3:	TLNE F,IDXRF		;AFTER REPEATED ITEM?
	JRST IDX4B		;YES. GO PUT IN REPEAT.
	PUSHJ P,INDXAD		;ADD ITEM WITH PAGE NO TO STORAGE (UNLINKED)
	HLRZ B,0(A)		;WHO PRECEDED OLD?
	SKIPN B			;ANYONE?
	HRRZM PA,XFIRST		;NO. NEW IS FIRST OF ALL.
	HRLM PA,0(A)		;NEW IS PREDECESSOR OF OLD
	HRRM A,0(PA)		;OLD IS SUCCESSOR OF NEW, NO PREDECESSOR
	SKIPE B			;IF ANYONE PRECEDED OLD,
	HRRM PA,0(B)		;MAKE NEW ONE BE HIS SUCCESSOR
	HRLM B,0(PA)		;AND OLD'S PRED IS NOW NEW'S PRED
	JRST ENDCM		;RETURN FROM INDEX COMMAND

INDX4:	TLNE F,IDXCF		;SEEM THE SAME. WERE CASES DIFFERENT?
	JRST INDX3		;YES. ASSUME THESE ARE DIFFERENT
	TLO F,IDXRF		;FLAG REPEATED ITEM
	JRST IDX4A		;GO LOOK FOR LAST OCCURRENCE.

IDX4B:	HLRZ A,0(A)		;AT END OF REPEAT. GET LAST ONE.
IDX4C:	PUSHJ P,INDXAP		;ADD POINTERS ONLY (WITH PAGE, NO LINK)
	HRRZ B,1(A)		;NEW POINTS TO SAME TEXT AS OLD
	HRRM B,1(PA)		; ..
	HRRZ B,0(A)		;GET PREVIOUS SUCCESSOR OF OLD
	HRRM PA,0(A)		;MAKE NEW SUCCEED OLD
	SKIPE B			;IF THERE WAS AN OLD NEXT,
	HRLM PA,0(B)		;NEW IS NOW PRED OF OLD NEXT.
	HRRM B,0(PA)		;OLD SUCCESSOR IS SUCCESSOR OF NEW
	HRLM A,0(PA)		;OLD IS PREDECESSOR OF NEW
	JRST ENDCM		;END OF INDEX COMMAND

INDX5:	TLNE F,IDXRF		;AFTER REPEATS?
	JRST IDX4C		;YES. GO ADD AT END.
	PUSHJ P,INDXAD		;CREATE TEXT AND POINTER BLOCK WITH PAGENO
	HRRM PA,0(A)		;MAKE NEW FOLLOW OLD
	HRLZM A,0(PA)		;AND OLD PRECEDE NEW.
	JRST ENDCM		;RETURN FROM INDEX COMMAND

INDXV:	PUSHJ P,INDXAD		;CREATE TEXT AND POINTER BLOCK, PAGE NO
	HRRZM PA,XFIRST		;THIS IS FIRST ITEM (AND ONLY)
	SETZM 0(PA)		;NO LINKS AT ALL
	JRST ENDCM		;END OF INDEX COMMAND
INDXAP:	HRRZ PA,XTOP		;GET CURRENT TOP OF INDEX
	ADDI PA,2		;NEED TWO WORDS FOR LINKS
	CAML PA,FOOTBF		;SPACE BEFORE FOOTNOTES?
	PUSHJ P,EXPAND		;NEED MORE CORE
	HRRZ PA,XTOP		;NEW VALUE OF XTOP, IF GREW
	MOVEI B,2(PA)		;NEW TOP
	HRRZM B,XTOP		;NOW UP TWO WORDS.
INDXAX:	HRRZ B,PAGENO		;GET PAGE NUMBER
	HRLM B,1(PA)		;INTO NEW ITEM
	POPJ P,0		;AND RETURN.

INDXAD:	HRRZ PA,XTOP		;GET TOP OF INDEX STORAGE
	ADDI PA,2(S1)		;NEED 2 WORDS PLUS TEXT
	CAML PA,FOOTBF		;LESS THAN BASE OF FOOTNOTES?
	PUSHJ P,EXPAND		;NO. TRY TO EXPAND
	HRRZ PA,XTOP		;GET TOP OF INDEX
	PUSH P,PA		;SAVE BASE OF NEW ITEM
	MOVE B,PA		;COMPUTE NEW TOP OF INDEX
	ADDI B,2(S1)		; ..
	HRRZM B,XTOP		;STORE IN TOP OF INDEX POINTER
	HRLI B,ICBUF		;TRANSFER TEXT INTO BUFFER
	HRRI B,2(PA)		;INTO TEXT AREA
	HRRM B,1(PA)		;STORE TEXT ADDRESS
	ADDI PA,1(S1)		;FINAL "TO" ADDRESS
	BLT B,0(PA)		;TRANSFER INDEX ITEM
	POP P,PA		;RESTORE BASE OF INDEX
	SETZM 0(PA)		;NO POINTERS YET.
	JRST INDXAX		;PUT PAGE NUMBER IN ITEM AND RETURN
;PRINT INDEX ONTO FILE

PINDX:	PUSHJ P,OUTNJ		;BREAK COMMAND. OUTPUT LINE.
	HRRZ A,XFIRST		;GET FIRST ITEM IN INDEX
	JUMPE A,PINDXX		;QUIT IF NONE.
	HRRZM A,OIXC		;SAVE CURRENT POINTER
	SETZM OIXL		;CLEAR CURRENT LETTER
PINDL1:	HRRZ B,OIXC		;GET POINTER TO TEXT OF THIS ITEM
	HRRZ B,1(B)		; ..
	HRLI B,440700		;ASCIZ POINTER
	ILDB CH,B		;GET FIRST LETTER
	CAIL CH,141		;LOWER CASE?
	TRZ CH,40		;YES. MAKE UPPER.
	CAMN CH,OIXL		;SAME AS INITIAL LETTER OF PREVIOUS ONE?
	JRST PINDX1		;YES. SKIP THIS
	MOVEI A,1		;NO. OUTPUT AN EXTRA LINE
	MOVEM CH,OIXL		;SAVE THIS CHARACTER
	PUSHJ P,SKIPN
PINDX1:	MOVE A,LMARG		;SPACE IN TO LEFT MARGIN
	PUSHJ P,NSPAC		; ..
	HRRZ A,OIXC		;GET POINTER TO ASCII
	HRRZ S1,1(A)		;..
	PUSHJ P,PSTRAZ		;OUTPUT STRING OF ASCIZ
	MOVE A,RMARG		;NOW GO TO MIDDLE OF LINE
	SUB A,LMARG		;IF NOT THERE YET
	ASH A,-1		; ..
	SUB A,CPOS		;MINUS CURRENT POSITION
	JUMPLE A,PIND2		;THERE ALREADY
	MOVEI CH,C.SPC		;GET A SPACE
	TRNE A,1		;MAKE DOTS LINE UP
	PUSHJ P,FOUT		;OUTPUT A SPACE
	ASH A,-1		;OUTPUT ALTERNATE DOTS AND SPACES
	MOVEI S1,[ASCIZ / ./]	; ..
	PUSHJ P,FMSG		; ..
	SOJG A,.-2		;OUTPUT TILL MIDDLE OF LINE
PIND2:	MOVEI CH,C.SPC		;OUTPUT ONE SPACE
	PUSHJ P,FOUT		; ..
	HRRZ B,OIXC		;GET PAGE NUMBER OF THIS INTRY
	HLRZ N,1(B)		; ..
	PUSHJ P,DECPRT		;OUTPUT PAGE NUMBER
PINDX2:	HRRZ C,0(B)		;GET SUCCESSOR OF THIS ENTRY
	MOVEM C,OIXC		;STORE CURRENT ENTRY FOR NEXT PASS
	JUMPE C,PINDXX		;END OF LIST? JUMP IF SO.
	HRRZ A,1(B)		;TEXT OF CURRENT ITEM
	HRRZ D,1(C)		;TEXT OF NEXT ITEM
	CAME D,A		;SAME AS CURRENT?
	JRST PINDX3		;NO. ON TO NEXT.
	HLRZ N,1(C)		;SAME. GET PAGE NUMBERS OF BOTH
	HLRZ N1,1(B)		;..
	CAME N1,N		;PAGES SAME TOO?
	JRST PINDX4		;NO. OUTPUT NEW PAGE NUMBER
	HRRZ B,C		;YES. DONT REPEAT PAGE NUMBER
	JRST PINDX2		; ..

PINDX4:	MOVEI CH,","		;PUT COMMA BETWEEN PAGE NUMBERS
	PUSHJ P,FOUT
	JRST PIND2		;AND THEN OUTPUT NUMBER

PINDX3:	MOVE A,NSPNG		;OUTPUT SPACING FOR END OF LINE
	PUSHJ P,SKIPN		; ..
	JRST PINDL1		;GO ON TO NEXT ITEM IN LIST

PINDXX:	MOVE A,NSPNG		;BLANK LINE AT END
	PUSHJ P,SKIPN		; ..
	HRRZ A,XBOT		;CLEAR INDEX POINTERS
	MOVEM A,XTOP		; ..
	SETZM XFIRST		; ..
	JRST ENDBCM		;RETURN FROM PINDX COMMAND
SUBTTL FOOTNOTE OPERATIONS

;FOOTNOTE N COMMAND

FOOTN:	PUSHJ P,RCNO		;HOW MANY LINES TO RESERVE?
	  JRST ILCM		;MUST HAVE SPEC
	IMUL N,NSPNG		;RESERVE N TIMES SPACING
	ADDM N,FOOTC		;ADD TO RESERVED FOOTNOTE LINES
	PUSHJ P,CCIN		;SKIP REST OF COMMAND LINE
	CAIE CH,C.LF		; ..
	JRST .-2		; ..
	JRST FOOTN3		;YES. END OF LINE.

FOOTN2:	PUSHJ P,CCIN		;READ A CHARACTER
FOOTN1:	PUSHJ P,WCIFTN		;WRITE CHARACTER IN BUFFER
	CAIE CH,C.LF		;END OF LINE?
	JRST FOOTN2		;NO.
FOOTN3:	PUSHJ P,CCIN		;YES. SEE WHAT CHAR AFTER LF IS
	CAIN CH,C.EOF		;END OF FILE?
	MOVEI CH,C.EFNT		;YES. FAKE END OF FOOTNOTE CHAR.
	CAIE CH,C.EFNT		;END FLAG (EXCL) ?
	JRST FOOTN1		;NO. STORE ANOTHER LINE
	PUSHJ P,WCIFTN		;YES. STORE THIS CHARACTER
	JRST ENDCM		;AND RETURN TO COMMAND ROUTINE

;START PROCESSING FOOTNOTE BUFFER. CALLED FROM BPAGE WHEN FOOTP3 POINTER
;NOT EMPTY

FOOTGO:	MOVEI A,^D100		;SET HUGE PAGE SIZE TO PREVENT EXTRA FORMS
	EXCH A,NLPG		;AND GET CURRENT LENGTH
	SUB A,LINEC		;DISTANCE TO END
	SKIPLE A		;IF SOME LEFT TO GO,
	PUSHJ P,SKIPN		; SKIP TO END OF PAGE BEFORE FOOTNOTES
	PUSH P,RMARG		;SAVE THESE ITEMS OVER FOOTNOTE PROCESSING
	PUSH P,LMARG
	PUSH P,PARIND		;SAVE PARA INDENTING
	PUSH P,NSPNG
	PUSH P,GCSCH
	TLO F,FOOTFG		;FLAG IN FOOTNOTE PROCESSING
	SETOM GCSCH		;CLOBBER ANY SAVED CHARACTERS
	MOVEI PA,FOOTWB		;PREPARE END-OF-LINE-HOLDING-BUFFER
	PUSHJ P,CSP		; ..
	MOVEM A,FOOTS1		; ..
	MOVEM B,FOOTS2		; BUFFER IS EMPTY
	TLZN F,GCINF		;NO SAVED INFO. WAS THERE ANY?
	JRST FOOTS3		;NO. LEAVE.
FOOTSB:	PUSHJ P,GGCINP		;GET A CHARACTER FROM SAVED BUFFER
	  JRST FOOTS3		;NO MORE
	MOVEI PA,FOOTS1		;SAVE BUFFER
	PUSHJ P,WCI
	JRST FOOTSB		;LOOP UNTIL SAVED BUFFER ALL MOVED

FOOTS3:	PUSHJ P,LINSET		;INITIALIZE LINE FOR START OF FOOTNOTE
	JRST LGO		;AND GO PROCESS SAVED FOOTNOTE COMMANDS

;HERE WHEN LINE ROUTINE DISCOVERS INITIAL EXCLAMATION

FOOTND:	TLNN F,FOOTFG		;PROCESSING FOOTNOTES?
	JRST FOOTX		;NO. EXTRANEOUS CUE.
	PUSHJ P,OUTNJ		;YES. FINISH UP LINE
	MOVE A,FOOTP3		;ANY MORE FOOTNOTES COMING?
	CAME A,FOOTP4		; ..
	JRST LGO		;YES. GO READ SOME MORE
	CAML A,FOOTP2		;ANY UNPROCESSED FOOTNOTES TO ADD?
	JRST FOOTN6		;NO.
	MOVEM A,T5		;YES. ADD THEM TO LIST.
	MOVE B,FOOTP2		;SAVE POINTER TO REMAINING COMMANDS
	MOVEM B,T6		; ..
	MOVE A,FOOTP1		;CLEAR OUT BUFFERS
	MOVEM A,FOOTP2		; ..
	MOVEM A,FOOTP3		; ..
	MOVEM A,FOOTP4		; ..
FOOTN4:	MOVEI PA,T5		;COPY T5 STRING TO FOOTP1
	PUSHJ P,GCI		;GET A CHARACTER
	  JRST FOOTN5		;NO MORE.
	PUSHJ P,WCIFTN		;WRITE IN FOOTNOTE POINTER 1
	JRST FOOTN4		;LOOP TILL DONE
FOOTN6:	MOVE A,FOOTP1		;CLEAR FOOTNOTE BUFFERS
	MOVEM A,FOOTP2		; ..
	MOVEM A,FOOTP3		; ..
	MOVEM A,FOOTP4		; ..
FOOTN5:	TLZ F,EXSP3+FOOTFG	;INITIALIZE LEFT/RIGHT FLAG
				; AND MARK NOT IN FOOTNOTE MODE NOW
	POP P,GCSCH		;RESTORE SAVED PARAMETERS
	POP P,NSPNG
	POP P,PARIND
	POP P,LMARG
	POP P,RMARG
	MOVE A,PNLPG		;RESET LENGTH OF PAGE
	MOVEM A,NLPG		; ..
	MOVE A,FOOTS1		;WAS PARTIAL LINE SAVED?
	CAMN A,FOOTS2		; ..
	JRST FOOTS4		;NO.
	MOVE B,FOOTS2		;YES. PUT POINTER IN GCINP
	MOVEM A,GCINP		; ..
	MOVEM B,GCINP+1		; ..
	TLO F,GCINF		;AND FLAG TO LOOK AT THAT BUFFER
FOOTS4:	JRST FOOTX		;RETURN TO LINE PROCESSOR

WCIFTN:	MOVE A,FOOTP2		;WRITE IN FOOTNOTE BUFFER, CHECKING SIZE
	IDIVI A,5		; ..
	ADDI A,1		;IS THIS ADDRESS HITTING TOP OF CORE?
	HRRZ B,JOBREL		; ..
	CAMGE A,B		; ..
	JRST WCIFT1		;OK. NO PROBLEM.
	MOVEI B,2000(B)		;NEED ANOTHER K
	CALLI B,11		;ASK FOR IT
	  JRST EXPERR		;CAN'T HAVE IT. GIVE UP.
WCIFT1:	MOVEI PA,FOOTP1		;NOW WRITE CHARACTER
	JRST WCI		; ..
SUBTTL HANDY-DANDY SUBROUTINES

;ROUTINE TO COMPUTE EMPTY STRING POINTER

CSP:	MOVE A,PA		;GET ARGUMENT
	IMULI A,5		;CONVERT TO CHARACTERS
	SOS B,A			;BACK UP ONE, COPY TO B
	POPJ P,0		;RETURN

;ROUTINES TO GET CHARACTER AND INCREMENT STRING POINTER

GGCINP:	SKIPA PA,[EXP GCINP]
GLOUT:	MOVEI PA,LOUT1		;PARTICULAR ARGUMENTS
GCI:	MOVE A,0(PA)		;GET FIRST POINTER
	CAML A,1(PA)		;ANYTHING IN STRING?
	POPJ P,0		;NO. NON-SKIP RETURN.
	AOS A,0(PA)		;YES. COUNT AND GET FIRST POINTER
	IDIVI A,5		;CONVERT TO WORD AND BYTE
	LDB CH,CBYTAB(B)	;GET THE CHARACTER
CPOPJ1:	AOS 0(P)		;SKIP RETURN
CPOPJ:	POPJ P,0		;RETURN.

;ROUTINES TO WRITE CHARACTER AND INCREMENT POINTERS

WLNIN1:	MOVEI PA,LNIN1		;STANDARD ARG
WCI:	AOS A,1(PA)		;COUNT POINTER AND GET IT.
	IDIVI A,5		;CONVERT TO WORD AND BYTE
	DPB CH,CBYTAB(B)	;STORE CHARACTER
	POPJ P,0		;RETURN

CBYTAB:	POINT 7,0(A),6
	POINT 7,0(A),13
	POINT 7,0(A),20
	POINT 7,0(A),27
	POINT 7,0(A),34
;I/O SUBRS

FMSG:	HRLI S1,440700		;MAKE BYTE POINTER
FMSGL:	ILDB CH,S1
	JUMPE CH,CPOPJ		;RETURN ON NULL
	PUSHJ P,FOUT		;OUTPUT CHARACTER
	JRST FMSGL		;LOOP

FOUT:	SOSLE H.FOUT+2		;ROOM IN BUFFER?
	JRST FOUTOK		;YES.
	OUTPUT F.FOUT,0		;NO. SEND BUFFER
	STATZ F.FOUT,740000	;ERRORS?
	JRST WRERR3		;YES.
FOUTOK:	IDPB CH,H.FOUT+1	;PUT CHAR IN BUFFER
	POPJ P,0		;AND RETURN

FINSEQ:	TRO F,FSEQ		;REMEMBER TO DISCARD CHAR AFTER SEQ NO

FIN:	SOSLE H.FIN+2		;ANYTHING IN BUFFER?
	JRST FINOK		;YES.
	INPUT F.FIN,0		;NO. GET BUFFER FULL
	STATZ F.FIN,740000	;ERRORS?
	JRST RDERR3		;YES.
	STATZ F.FIN,20000	;END OF FILE?
	JRST FINEOF
FINOK:	IBP H.FIN+1		;POINT TO CHARACTER
	MOVE CH,@H.FIN+1	;CHECK FOR SEQ NO.
	TRNE CH,1		; ..
	JRST FINSEQ		;YES. DISCARD.
	LDB CH,H.FIN+1		;NO. GET CHAR.
	TRZE F,FSEQ		;IS THIS TAB AFTER SEQ NO?
	JRST FIN		;YES. DISCARD IT TOO
	JUMPE CH,FIN		;JUNK NULLS
	CAIN CH,177		;AND RUBOUTS
	JRST FIN		;GET ANOTHER
	POPJ P,0		;RETURN CHARACTER

FINEF1:	MOVE CH,EOFPTR		;INITIAL EOF POINTER
	MOVEM CH,INEOFP
FINEOF:	ILDB CH,INEOFP		;GET LITERAL CHARACTER
	JUMPE CH,FINEF1		;IF NONE, RESTART LITERAL
	POPJ P,0		;NO. RETURN CHARACTER

EOFPTR:	POINT 7,EOFDAT
EOFDAT:	BYTE (7) C.CR,C.LF,C.EOF
;READ WORD OF SIXBIT INTO A FROM TYI

SIXBRD:	MOVEI A,0		;INITIALIZE ANSWER
	MOVE B,[XWD 440600,A]	;POINTER TO A
SIXBRL:	PUSHJ P,TYI		;GET A CHARACTER
	CAIG CH,"Z"		;LETTER?
	CAIGE CH,"A"		; ..
	SKIPA			;NO
	JRST SIXBR1		;YES
	CAIG CH,"9"		;DIGIT?
	CAIGE CH,"0"		; ..
	POPJ P,0		;NO. RETURN BREAK
SIXBR1:	TRC CH,40		;MAKE SIXBIT
	TLNE B,770000		;ROOM IN ANSWER?
	IDPB CH,B		;YES. STORE CHARACTER
	JRST SIXBRL		;LOOP

;READ CHARACTER FROM TTY. CONVERT ALTMODES, LC. DISCARD CR AND NULL

TYI:	TTCALL 4,CH		;READ A CHARACTER
	CAIG CH,172		;LOWER CASE?
	CAIGE CH,141		; ..
	SKIPA			;NO
	TRZ CH,40		;YES. MAKE UPPER
	CAIE CH,15		;CARRIAGE RETURN?
	CAIN CH,0		;OR NULL?
	JRST TYI		;YES. DISCARD.
	CAIE CH,176		;ALTMODES?
	CAIN CH,175		; ..
	MOVEI CH,33		;YES. MAKE ESCAPE.
	POPJ P,0		;RETURN CHARACTER

YESNO:	PUSHJ P,SIXBRD		;READ A WORD
	LDB CH,[POINT 6,A,5]	;GET FIRST CHAR
	CAIE CH,"Y"-40		;IS FIRST CHAR A Y?
	AOS 0(P)		;NO. SKIP.
	POPJ P,0		;YES. DON'T SKIP.

WRERR3:	TTCALL 3,[ASCIZ /
?ERROR ON OUTPUT FILE.
/]
	CALLI 12

RDERR3:	TTCALL 3,[ASCIZ /
?ERROR ON INPUT DEVICE
/]
	CALLI 12
;ROUTINE TO GET A FILE SPECIFIER. ANSWERS IN CORE CELLS, SKIP
; IF OK. READS FROM TTY. BREAK CHARACTER IN CH.

FILSPC:	SETZM FILE		;CLEAR ANSWER CELLS
	SETZM EXT		; ..
	SETZM PPN		; ..
	SETZM DEVICE		; ..
	TRZ F,R.DOT+R.BKT		;CLEAR EXTENSION FLAG

FILSPL:	PUSHJ P,SIXBRD		;READ A WORD
	CAIN CH,":"		;WHAT IS BREAK?
	JRST FILDEV		;DEVICE NAME
	CAIN CH,"."		;DOT?
	JRST FILDOT
	CAIN CH,"["		;PPN?
	JRST FILLBK
	TRZE F,R.DOT		;DOT SEEN?
	JRST FILSP1		;YES.
	TRZN F,R.BKT		;BRACKET SEEN?
	MOVEM A,FILE		;NO. STORE FILE NAME
	SKIPA
FILSP1:	HLLOM A,EXT		;SAVE EXTENSION (NON-ZERO EVEN IF NULL)
	JRST CPOPJ1		;OK RETURN.

FILDEV:	MOVEM A,DEVICE		;STORE DEVICE NAME.
	JRST FILSPL		;SEE WHAT ELSE

FILDOT:	TRON F,R.DOT		;SET DOT-SEEN FLAG
	MOVEM A,FILE
	JRST FILSPL		;SEE WHAT ELSE
FILLBK:	TRZE F,R.DOT		;SEEN A DOT?
	JRST FILBK1		;YES.
	MOVEM A,FILE		;STORE FILENAME
	SKIPA			; ..
FILBK1:	HLLOM A,EXT		;YES. STORE EXTENSION
	TRO F,R.BKT		;SET BRACKET-SEEN BIT
	PUSHJ P,OCTIN		;READ OCTAL NUMBER
	CAIE CH,","		;MUST BE COMMA
	JRST FILERR		;NO. ERROR.
	HRLM N,PPN		;STORE OCTAL.
	PUSHJ P,OCTIN		;GET PROG NO.
	HRRM N,PPN		;STORE IT.
	CAIN CH,"]"		;CLOSING BRACKET?
	JRST FILSPL		;NO.
	CAIGE CH,40		;BREAK CHARACTER?
	JRST CPOPJ1		;OK. RETURN
FILERR:	TTCALL 11,0		;CLEAR INPUT BUFFER
	TTCALL 3,[ASCIZ /
?EH?
/]
	POPJ P,0		;ERROR RETURN

OCTIN:	MOVEI N,0		;CLEAR ANSWER
OCTINL:	PUSHJ P,TYI		;READ A CHARACTER
	CAIG CH,"7"		;OCTAL DIGIT?
	CAIGE CH,"0"		; ..
	POPJ P,0		;NO
	ASH N,3			;YES. COLLECT NUMBER
	ADDI N,-"0"(CH)		; ..
	JRST OCTINL		;LOOP FOR BREAK.
;ROUTINE TO GRAB ANOTHER K OF CORE.

EXPAND:	PUSH P,A		;SAVE AN AC
	HRRZ A,JOBREL		;GET CURRENT CORE
	MOVEI A,2000(A)		;ANOTHER K
	PUSH P,B		;SAVE ANOTHER AC
	MOVEI B,-2000(A)	;GET OLD TOP OF CORE
	CALLI A,11
	 JRST EXPERR		;CAN'T GET IT.
EXPL:	MOVE A,0(B)		;GET WORD
	MOVEM A,2000(B)		;MOVE IT UP
	CAME B,FOOTBF		;ALL MOVED?
	SOJA B,EXPL		;NO. LOOP.
	MOVEI A,2000		;ADD A K TO POINTERS NEEDING IT.
	ADDM A,FOOTBF		; ..
	IMULI A,5		;AND TO THESE CHARACTER POINTERS
	ADDM A,FOOTP1
	ADDM A,FOOTP2
	ADDM A,FOOTP3
	ADDM A,FOOTP4
	POP P,B			;RESTORE AC'S
	POP P,A			; ..
	POPJ P,0		;AND RETURN

EXPERR:	TTCALL 3,[ASCIZ /
?NOT ENOUGH CORE
/]
	CALLI 12

DECTYO:	IDIVI N,12
	HRLM N+1,0(P)
	SKIPE N
	PUSHJ P,DECTYO
	HLRZ CH,0(P)
	ADDI CH,60
	TTCALL 1,CH
	POPJ P,0
SUBTTL INITIALIZATION

INTERN RUNOFF

RUNOFF:	MOVE P,[IOWD PDLL,PLIST]	;STACK
IFN PURE,<
	MOVEI A,LOWTOP		;SET UP JOBFF
	HRLM A,JOBSA		;PAST VARIABLES
>
	CALLI 0			;RESET FILES AND JOBFF
	TTCALL 3,TITL		;ANNOUNCE YOURSELF
	MOVSI F,JUSTF+PJUSTF+FILLF+FFDSW+NUMBF	;INITIAL FLAGS

	SETOM GCSCH		;NO SAVED CHARACTER
	SETOM ULMCH		; ..
	MOVEI A,INLPG		;INITIAL LENGTH OF PAGE
	MOVEM A,PNLPG
	MOVEM A,NLPG
	MOVEI A,IRMRG		;INITIAL RIGHT MARGIN
	MOVEM A,PRMRG
	MOVEM A,RMARG
	MOVEI A,ILMRG		;INITIAL LEFT MARGIN
	MOVEM A,LMARG		; ..
	MOVEI A,40		;INITIAL CASE SETTING IS LOWER
	MOVEM A,CAS
	MOVEI A,1		;INITIAL PAGE NUMBER
	MOVEM A,PAGENO
	MOVEI A,2		;INITIAL SPACING
	MOVEM A,NSPNG		; ..
	MOVEI A,5		;INITIAL PARAGRAPH INDENTING
	MOVEM A,PARIND
	SETZM TTLP1		;NO TITLE TO START WITH
	SETZM TTLP2
	SETZM STTLP1		;CLEAR SUBTITLE TOO
	SETZM STTLP2		; ..
	SETZM LINEC		;START AT TOP OF PAGE
	SETZM INDCT		;AND LEFT OF PAPER
	SETZM NTABS		;NO TABS YET
	SETZM FOOTC		;NO FOOTNOTE LINES HELD YET
	SETZM XFIRST		;NOTHING IN THE INDEX
	SETZM INEOFP		;PREPARE FOR END OF FILE
	MOVEI PA,LINBF		;INITIALIZE LINE INPUT POINTER
	PUSHJ P,CSP
	MOVEM A,LNIN1		;STORE.
	MOVEM B,LNIN2		; ..
;GET FILE NAMES AND OPTIONS

SETUP0:	TTCALL 3,SETM1		;ASK FOR INPUT FILE
	PUSHJ P,FILSPC		;GET HIS ANSWER
	 JRST SETUP0		;BAD. LOOP.
	MOVEI A,0		;ASCII MODE
	SKIPN B,DEVICE		;GET DEVICE IF ANY
	MOVSI B,(SIXBIT /DSK/)	;IF NONE, ASSUME DISK
	MOVEI C,H.FIN		;BUFFER HEADER FOR INPUT
	OPEN F.FIN,A		;TRY TO GET DEVICE
	 JRST RDERR1		;CAN'T. QUIT.
	MOVE A,FILE		;GET FILE NAME (NO DEFAULT)
	MOVEM A,INNAM		;SAVE FOR OUTPUT
	HLLZ B,EXT		;AND EXTENSION
	MOVEI C,0		;..
	MOVE D,PPN		; AND PPN
	LOOKUP F.FIN,A		;IS IT THERE?
	 SKIPA		;NO.
	JRST SETUP1		;YES. GO ON.
	SKIPE EXT		;HAD HE SPECIFIED EXTENSION?
	JRST RDERR2		;YES. HE LOSES.
	MOVSI B,(SIXBIT /RNO/)	;NO. TRY STANDARD
	MOVEI C,0		; ..
	MOVE D,PPN		;RESTORE PPN
	LOOKUP F.FIN,A		;TRY AGAIN
	 JRST RDERR2		;NO. GIVE UP.
SETUP1:	INBUF F.FIN,2		;RESERVE THE BUFFERS
	HLRZ B,EXT		;SEE IF NEED TO ASK FOR OUTPUT FILE
	CAIE B,(SIXBIT /LST/)	;IS HIS FILE .LST?
	CAIE CH,C.ALT		;AND NOT ALTMODE?
	JRST SETUP2		;NEED TO ASK.
	SETZM EXT		;USE STANDARD
	MOVSI A,(SIXBIT /DSK/)	;STANDARD DEVICE
	MOVEM A,DEVICE		; ..
	SETZM PPN		;IN OWN DIRECTORY
	JRST SETUP3		;GO WRITE IT.
SETUP2:	TTCALL 3,SETM2		;ASK FOR OUTPUT
	PUSHJ P,FILSPC		;GET IT
	 JRST SETUP2		;ERROR. TRY AGAIN.
SETUP3:	MOVEI A,0		;ASCII OUTPUT
	SKIPN B,DEVICE		;DEVICE
	MOVSI B,(SIXBIT /DSK/)	;NONE. USE DEFAULT.
	MOVSI C,H.FOUT		;OUTPUT HEADER
	OPEN F.FOUT,A		;TRY TO GET IT.
	 JRST WRERR1		;CAN'T.
	SKIPN A,FILE		;GET FILE NAME
	MOVE A,INNAM		;IF NONE, USE INPUT NAME
	SKIPN B,EXT		;EXTENSION IF ANY
	MOVSI B,(SIXBIT /LST/)	;NO. USE STANDARD
	MOVEI C,0		;NO DATE
	MOVE D,PPN		;PPN, IF ANY.
	ENTER F.FOUT,A		;TRY TO WRITE IT
	 JRST WRERR2		;CAN'T
	OUTBUF F.FOUT,2		;RESERVE THE BUFFERS
	CAIN CH,C.ALT		;FAST START?
	JRST RNGO		;YES, START RUNOFF
	TTCALL 3,SETM5		;ASK ABOUT UNDERLINES
	PUSHJ P,SIXBRD		;GET ANSWER
	LDB CH,[POINT 6,A,5]	;GET FIRST LETTER
	CAIN CH,"B"-40		;BACKSPACE AFTER UNDERLINE?
	TLO F,ULBSF+ULMODE	;YES. SET 2 FLAGS
	CAIN CH,"C"-40		;CHARACTER?
	TLO F,ULMODE		;YES. SET FLAG.
	CAIN CH,"N"-40		;NONE?
	TLO F,ULSUPF		;YES. SET FLAG.
	TTCALL 3,SETM3		;ASK ABOUT FORMFEEDS
	PUSHJ P,YESNO		;ANSWER YES OR NO
	  TLZ F,FFDSW		;YES. CLEAR FORMFEED SWITCH
	TTCALL 3,SETM4		;ASK ABOUT PAUSE
	PUSHJ P,YESNO		;ANSWER YES OR NO
	  TLO F,PAUSF		;YES. SET PAUSE BIT
	TTCALL 3,CRLFM		;TYPE CRLF
	JRST RNGO		;START PROGRAM
;ERRORS DURING SPECIFICATIONS

RDERR1:	TTCALL 3,[ASCIZ /
?CAN'T INITIALIZE DEVICE
/]
	JRST SETUP0

RDERR2:	TTCALL 3,[ASCIZ /
?CAN'T READ THAT FILE
/]
	JRST SETUP0

WRERR1:	TTCALL 3,[ASCIZ /
?CAN'T INITIALIZE DEVICE
/]
	SKIPA
WRERR2:	TTCALL 3,[ASCIZ /
?CAN'T ENTER FILE
/]
	TTCALL 11,0		;CLEAR INPUT BUFFER
	JRST SETUP2		;TRY AGAIN
SETM1:	ASCIZ '
INPUT FILE:	'
SETM2:	ASCIZ '
OUTPUT FILE:	'
SETM3:	ASCIZ '
SIMULATE FORM FEED (Y OR N)? '
SETM4:	ASCIZ '
PAUSE? '
SETM5:	ASCIZ /
UNDERSCORE (L,C,B OR N)? /

DEFINE .TITL (N) <ASCIZ /RUNOFF V N/>
TITL:	.TITL (\VRUNOF)
;HERE WHEN OPTIONS ALL SPECIFIED

RNGO:	HRRZ PA,JOBFF		;GET FREE AREA
	MOVEM PA,XTOP		;INITIAL INDEX POINTERS
	MOVEM PA,XBOT		; ..
	HRRZ PA,JOBREL		;INITIALIZE FOOTNOTE STUFF
	SUBI PA,^D200		;SPACE FOR SOME FOOTNOTES?
	HRRZ A,JOBFF		; ..
	CAIGE A,0(PA)		; ..
	JRST RNG3		;YES
	ADDI PA,^D1000		;NO. ASK FOR MORE CORE
	CALLI PA,11		; ..
	  JFCL			;BUT DONT PANIC IF NOT THERE
RNG3:	HRRZ PA,JOBREL		;GIVE HALF OF CORE TO FOOTNOTES
	SUBI PA,0(A)		;AND HALF TO INDEX
	ASH PA,-1		; ..
	ADDI PA,0(A)		;JOBFF PLUS HALF DIFFERENCE
	HRRZM PA,FOOTBF		;SAVE FOR COMPARISON LATER
	PUSHJ P,CSP		; ..
	MOVEM A,FOOTP1		;STORE
	MOVEM B,FOOTP2
	MOVEM A,FOOTP3		;IN BOTH POINTERS
	MOVEM B,FOOTP4
	TTCALL 3,CRLFM		;TYPE A CRLF
	TLNN F,FFDSW		;FORMFEED OR LF'S?
	JRST RNG1		;LINEFEEDS. REQUEST POSITIONING
	MOVEI CH,C.FF		;OUTPUT FORMFEED
	PUSHJ P,FOUT
RNG2:	PUSHJ P,LINSET		;SET UP FOR LINE
	MOVEI A,5		;NO TITLE YET, SO SKIP HEADING AREA
	PUSHJ P,SKIPN		; ..
	JRST LGO		;AND INTO MAIN LOOP, LINE INPUT

RNG1:	TTCALL 3,RNGM1		;ASK FOR POSITIONING
	TTCALL 0,A		;WAIT FOR A CHARACTER
	JRST RNG2		;AND GO.

ENDFIL:	PUSHJ P,OUTNJ		;FINISH LAST LINE
	PUSHJ P,FORM		;TO TOP OF FORM
	RELEAS F.FIN,0		;LET GO OF FILES
	RELEAS F.FOUT,0		; ..
	TTCALL 3,DONM		;COMMENT DONE
	CALLI 1,12		;MONRET
	JRST RUNOFF		;IN CASE OF CONTINUE
RNGM1:	ASCIZ /
POSITION PAPER, TYPE SPACE.
/
DONM:	ASCIZ /
DONE.
/

	XLIST ;LITERALS
	LIT
	LIST

IFE PURE,<
PATCH:	BLOCK 100
>

RUNEND:	END RUNOFF
                                                       