	.TITLE RUNOFF
	.IDENT	/BL3.11/

;
; COPYRIGHT (C) 1976
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A
; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE INCLU-
; SION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ANY
; OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE MADE
; AVAILABLE TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH SYSTEM
; AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE TO AND
; OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
; NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
; EQUIPMENT CORPORATION.
;
; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
;
; VERSION M02
;
; AUTHOR: L. WADE 1-JUN-72
;
; MODIFIED BY:
;
;	E. POLLACK U. OF W. 19-DEC-73
;
;	D. N. CUTLER 27-JUL-75
;
; SIG MODIFICATIONS					
;	SIG01		CLEAN UP OPERATOR WAIT		
;
;
;	BONNER LAB MODIFACATIONS
;		ADDED OPTIONAL ESCAPE SEQUENCE HANDLING
;		Substitution flags, Layout, Most DSR commands
;		Table driven parsing, Rewrote most sections!!!!
;
;				J. CLEMENT 	November 1982
;
; THIS PROGRAM WAS TRANSLATED FROM THE PDP-10 VERSION OF RUNOFF
; AUTHORED BY B. CLEMENTS.

;	NOTES ON REGISTER USAGE
;		R0 IS COMPLETELY VOLATILE
;		R1-R3	SUBROUTINE PARAMETER PASSING
;			R1	IS CURRENT CHARACTER
;			R2	IS SPACE/LINE COUNT
;			R3	IS USED AS BUFFER HEADER ADDRESS
;		R4	SUBROUTINE ADDRESS FOR COMMAND EXECUTION
;				J. CLEMENT	AUG 82
;
;	LOCAL MACROS
;
;
;	Initial switch setting tables
;
	.PSECT	$CONST,LCL,RO,D,CON
RMTAB:	.BYTE	'I,'V,'X,'L,'C,'D,'M,' 	; Roman numeral table
.even
INI$SW:: .WORD	HYPSW!SPLSW!CRSW	; INITIAL VALUE FOR $SWTCH
IUL::	.WORD	'N		; INITIAL UNDERLINE SWITCH
IPARIN:: .WORD	5		; INITIAL PARAG INDENTATION
HWLPP::	.WORD	HWPLN		; INITIAL VALUE FOR LPPG
	.PSECT	$VARS,LCL,RW,D,CON
;
;	UP/DOWN escape sequences
;
UPTAB::	.BYTE	ESC,ES.NUL	; Multiple escape processing
UPMOV::	.BYTE	ESC,'D,0	; Move text up 1/2 space
	.BLKB	CH.HD1-2
DNTAB::	.BYTE	ESC,ES.NUL	; Multiple escape processing
DNMOV::	.BYTE	ESC,'U,0	; Move text down 1/2 space
	.BLKB	CH.HD1-2
VARESC:: .BLKB	2*CH.HD1+1	; Holds variable spacing string
	.EVEN
;
;	General input switches and variables
;
VARBEG::			; This marks first variable
F.1::	.BLKW	1		; Flag word
$HDRSW:: .BLKB	1		; DISABLE PAGE HEADER (0=NO)
$FIRPG:: .BLKB	1		; Non zero if first page of document
$PAGPD:: .BLKB	1		; Page pending
$PAGBR:: .BLKB	1		; 0=AT TOP OF PAGE
$ULMSW:: .BLKB	1		; UNDERLINE MODE (0=NO BACKSPACE)
$ULSSW:: .BLKB	1		; UNDERLINE SIMULATE (0=NO)
$FOTPD:: .BLKB	1		; FOOTNOTE PENDING (0=NO)
$PFOOT:: .BLKB	1		; Permanent footnote in progress
$ULOSW:: .BLKB	1		; UNDERLINE OUTPUT? (0=NO)
$ULCH:: .BYTE	'_		; UNDERLINE CHARACTER
$SEPR::	.BYTE	'-		; separator character
EOFSW:: .BLKB	1		; NON ZERO IS END OF FILE
$GCEND:: .BLKB	1		; Non zero for immediate input stop
$BFSTC:: .BLKB	1		; SETBF, keep line intact if non zero
$AUTSW:: .BLKB	1		; Autoparagraph active (0=NO)
$AUTTL:: .BLKB	1		; Autotitle active (0=yes)
$AUSTL:: .BLKB	1		; Autosubtitle (0=NO)
$AUBRK:: .BLKB	1		; Autobreak disabled (0=yes)
$AUHYP:: .BLKB	1		; Autohyphenation disabled (0=enabled)
$LAYOU:: .BLKB	1		; Layout value
NXLAY::	.BLKB	1		; Next layout parameter
PRLAY::	.BLKB	1		; Permanent layout parameter
CHLAY::	.BLKB	1		; Chapter layout parameter
$ELIPS:: .BLKB	1		; Non zero enables ellipses
$TABLF:: .BLKB	1		; 0=Left justify tabs , Non=Right justify
$TOCSW:: .BLKB	1		; Zero if TOC enabled
$TOCBE:: .BLKB	1		; Non zero if TOC Begun
$OUTSW:: .BLKB	1		; Zero if output enabled
$PERSW:: .BLKB	1		; Double spaces after punctuation (0=NO)
$EQUSW:: .BLKB	1		; Equation mode on ? (0=yes)
$SEQSW:: .BLKB	1		; Separated equation mode on (0=no)
$NOSPC:: .BLKB	1		; If non zero converts spaces to NXS
$HSPSW:: .BLKB	1		; If zero enables half spacing
$TABPD:: .BLKB	1		; Right justified tab pending
$KEPSW:: .BLKB	1		; Keep blank filled lines
RETSW::	.BLKB	1		; Non zero return from GCIN on #=|sp tab
$VARSP:: .BLKB	1		; Non zero if variable spacing active
$UNLRS:: .BLKB	1		; Non zero if must reset underline buffer
	.EVEN
;
;	SWITCH PARAMS
;
LOWPAG:: .BLKW	1		; Lowest page number to print
HGHPAG:: .BLKW	1		; Highest page number to print
LOWCHP:: .BLKW	1		; lowest chapter to print
HGHCHP:: .BLKW	1		; highest chapter to print
LOWAPN:: .BLKW	1		; lowest appendix to print
HGHAPN:: .BLKW	1		; highest appendix to print
CHPMG::	.BLKB	CH.HD1+1	; Chapter header text
CHPM2::	.BLKB	CH.HD1+1	; Appendix trailing text
APNMG::	.BLKB	CH.HD1+1	; Appendix header text
APNM2::	.BLKB	CH.HD1+1	; Appendix trailing text
PAGHD::	.BLKB	CH.HD1+1	; Page number text prototype
PAGH2::	.BLKB	CH.HD1+1	; Second page header prototype
	.EVEN
LPPG::	.BLKW	1		; Hardware lines per page
;
; SWITCH FLAGS (WORD)
;
TJFSW:	.BLKW	1		; TEMPORARY JUSTIFY FLAG (0=NO)
;
;	FLAG WORDS
;
;	BYTE 0=	The character to test (flag character)
;	BYTE 1= 0	Flag enabled
;		200	Disabled by NO FLAG command
;		100	Disabled for literal
;
$AFLSW:: .WORD	'_		; FLAG ACCEPT (-=NO)
$CFLSW:: .WORD	'<+100000	; FLAG CAPITALIZE ENABLE (-=NO)
$UFLSW:: .WORD	'&		; UNDERLINE SWITCH (-=NO)
$LFLSW:: .WORD	'\		; LOWERCASE SWITCH (-=NO)
$SFLSW:: .WORD	'^		; UPPERCASE SHIFT SWITCH (-=NO)
$QFLSW:: .WORD	'#		; QUOTED SPACE SWITCH (-=NO)
$OFLSW:: .WORD	'%+100000	; OVERSTRIKE FLAG ENABLE (-=NO)
$IFLSW:: .WORD	'>+100000	; INDEX FLAG ENABLE (-=NO)
$SIFSW:: .WORD	'>+100000	; Subindex flag enable
$HFLSW:: .WORD	'=+100000	; FLAG HYPHENATE (-=NO)
$EFLSW:: .WORD	100000		; ESCAPE FLAG	
$SBFSW:: .WORD	'$+100000	; substitute flag switch
$BRFSW:: .WORD	'|+100000	; break flag switch
$SPFSW:: .WORD	0		; Special flag switch
$NFLSW:: .WORD	'.		; CONTROL FLAG	
$EQFSW:: .WORD	0		; Equation flag switch
;
;
;	ALL VARIABLES BETWEEN SAVBEG/SAVEND ARE SAVED DURING FOOTNOTING
;
SAVBEG==.
;	DISABLE SWITCHES (0=ENABLED) (200=DISABLED) (100=OFF)(1=OFF FOREVER)
;
$ESCSW:: .BLKB	1		; ESCAPE SEQUENCES DISABLED
$SUBSW:: .BLKB	1		; substitute disabled flag
$UNLSW:: .BLKB	1		; UNDERLINING OFF
$OVRSW:: .BLKB	1		; OVERSTRIKING DISABLED
$HYPSW:: .BLKB	1		; Non zero disable hyphenation
$INXSW:: .BLKB	1		; INDEXING ENABLED
$CBRSW:: .BLKB	1		; CHANGE BAR SWITCH
$TABSW:: .BLKB	1		; NON ZERO DISABLES TABS
$CENSW:: .BLKB	1		; NON ZERO = CENTER TEXT
$RIGSW:: .BLKB	1		; Non zero = right justify text
HYPCT:: .BLKB	1		; Counts hyphenated lines	
HYPOP::	.BLKB	1		; Hyphenation option
	.EVEN
HYPSV::	.BLKW	1		; Potential savings by hyphenation
HYPLO::	.BLKW	1		; Chars in front of autohyphenation
HYPHI::	.BLKW	1		; Chars in back
HYPSZ::	.BLKW	1		; -Minimum size word for hyphenation
OVRCT::	.BLKW	1		; COUNTS BACKSPACE ABORTS
ESCCNT:: .BLKW	1		; COUNTS ESCAPE SEQUENCES
CASE::	.BLKB	1		; -=LOWER CASE ONLY, +=UPPER CASE ONLY	; ***
ULOCK::	.BLKB	1		; SAVES PERMENANT CASE LOCK
;
;	The following 3 variables are saved by permanent footnotes
;
PFSBEG::
NSPNG::	.BLKW	1		; SPACING BETWEEN LINES
LMARG::	.BLKW	1		; CURRENT LEFT MARGIN
RMARG::	.BLKW	1		; CURRENT RIGHT MARGIN
PFSEND:				; End of permanent footnote save
PFSIZ==PFSEND-PFSBEG		; Number of bytes to save
CMARG::	.BLKW	1		; MARGIN FOR CENTERING TEXT
; LINE TEMPS
SPCNT::	.BLKW	1		; Expandable space count
SPCNSV:: .BLKW	1		; Same before last space
BRCNT:: .BLKW	1		; number of breaks this line
CASSAV:: .BLKW	1		; SAVE CASE AT LAST SPACE
LINBK::	.BLKW	1		; Line break count (+ no break)
SPCH::	.BLKW	1		; Number of spacing characters
LSPCH::	.BLKW	1		; Number of spacing chars before last space
HYPSP::	.BLKW	1		; Spacing chars at last hyphen
LUNLSW:: .BLKW	1		; Underline switch at last space
PHSP::	.BLKW	1		; Permanent horizontal spacing
LPHSP::	.BLKW	1		; Last permanent horizontal spacing
LCH::	.BLKB	1		; LAST CHAR
LSCH::	.BLKB	1		; Last char before space (break)
LSTSP::	.BLKW	1		; Address of char before last space in output
LTAB::	.BLKW	1		; Address of last tab output count
INDCT::	.BLKW	1		; CURRENT INDENTATION
EBSIZ1:: .BLKW	1		; Change bar initital indentation
EBSIZ2:: .BLKW	1		; Change bar second indentation
LESMSK:: .BLKW	1		; Last escape stack
ESMSK:: .BLKW	1		; Address of current location in escape stack
CURVS:: .BLKW	1		; Current vertical spacing
MAXVS::	.BLKW	1		; Max vertical spacing
MINVS::	.BLKW	1		; Min vertical spacing
SAVEND=.
SAVSZ==SAVEND-SAVBEG		; SIZE OF FOOTNOTE SAVE BUFFER
; 
; 	MISC SWITCHES
; 
$NUMSW:: .BLKW	1		; NUMBER PAGES (0=NO)
TESMSK:: .BLKW	1		; Temporary escape mask
$PAGSW:: .BLKW	1		; OUTPUT 'PAGE' SWITCH (0=YES)
$CHPSW:: .BLKW	1		; output chapter (0 = yes)
$SBPSW:: .BLKW	1		; SUBPAGE MODE ACTIVE (0=NO)
; 
; 	ADDRESS POINTERS
; 
ERSTR::	.BLKW	1		; SAVES ADDRESS OF STRING
LNINS::	.BLKW	1		; ADDRESS OF LAST CHAR IN LINE
LSPIN::	.BLKW	4		; ADDRESSES OF LAST INPUT SPACE
LSSTK::	.BLKW	1		; last input stack value

$NTITL:: .BLKW	1		; non zero prevents title in header
TMARG::	.BLKW	1		; CURRENT TOP MARGIN
HSPAC::	.BLKW	1		; CURRENT HEADER SPACING
PRMRG::	.BLKW	1		; PERMANENT RIGHT MARGIN
PLMRG::	.BLKW	1		; PERMANENT LEFT MARGIN
PTMRG::	.BLKW	1		; PERMANENT TOP MARGIN
PSPNG:: .BLKW	1		; Permanent spacing
PHSPOU::.BLKW	1		; Permanent output horizontal spacing
EQSPC::	.BLKW	1		; Equation spacing
$EOPSP::.BLKW	1		; Current End of page spacing
NXEPSP::.BLKW	1		; Next End of page spacing
PREPSP::.BLKW	1		; Permanent End of page spacing
CHEPSP::.BLKW	1		; Chapter End of page spacing
$FIGDF::.BLKW	1		; Number of lines to skip deferred
APNDSP::.BLKW	1		; appendix display format
CHPDSP::.BLKB	10.		; chapter/level display format
PAGDSP::.BLKW	1		; page number display format
SUBDSP::.BLKW	1		; subpage display format (letter)
PAGNX::	.BLKW	1		; next page number
SUBNX::	.BLKW	1		; next subpage
APNNX::	.BLKW	1		; next appendix number
CHPNX::	.BLKW	1		; next chapter number
PAGENO::.BLKW	1		; CURRENT PAGE NUMBER
SUBPGE::.BLKW	1		; current subpage number
APNDN::	.BLKW	1		; Current appendix number(must be before CHPTN)
CHPTN::	.BLKB	8.		; Current chapter number + header levels
CHSK1::	.BLKB	1		; Skip count 1
CHSK2::	.BLKB	1		; Skip count 2
CHSK3::	.BLKB	1		; Skip count 3
CHSP1::	.BLKB	1		; Spacing count 1
CHSP2::	.BLKB	1		; Spacing count 2
CHSP3::	.BLKB	1		; Spacing count 3
LEVEL::	.BYTE	1		; Current level number
LINLV::	.BYTE	3		; Lowest level with text-title run on
CAPLV::	.BYTE	1		; Highest all caps level
MIXLV::	.BYTE	6		; Highest level with first letter in caps
NONLV::	.BYTE	7		; Level - lowest without header number
CENLV::	.BYTE	7		; Level - lowest centered title
BEGLV::	.BYTE	2		; Level begin spacing
ENDLV::	.BYTE	1		; Level end spacing
TPGLV::	.BYTE	8.		; Level test page
SPCLV::	.BYTE	2		; Spaces between number and title
STLLV:: .BLKB	1		; Autosubtitle level number
OUTLV:: .BLKB	1		; Levels enabled (0-6)
TOCLV:: .BLKB	1		; Levels enabled for TOC
	.even
LIDLV::	.BLKW	1		; Left level indent
RIDLV::	.BLKW	1		; Level indentation
PARPT::	.BLKW	1		; Paragraph page test count
PARSP::	.BLKW	1		; Paragraph spacing count
PARIND::.BLKW	1		; Paragraph indentation
LINEC1::.BLKW	1		; Number of lines left to bottom active page
LINEC2::.BLKW	1		; Number of lines left (physical page)
LINEC3::.BLKW	1		; Number of free lines (counts saved data)
FOTLN::	.BLKW	1		; Number of lines permanent footnote
LN3SAV::.BLKW	1		; Saves old LINEC3 during text deferred
TXDHED::.BLKW	1		; Saves current text deferred header
PFOTHD::.BLKW	1		; Permanent footnote header
CMADR::	.BLKW	1		; Next expected command address
LITCM::	.BLKW	1		; SAVED EXPECTED COMMAND ADDRESS (LITERAL)
LITSV::	.BLKW	1		; SAVED FLAGS MASK ON LITERAL PROCESSING
LSTKP::	.BLKW	1		; CURRENT LIST STACK POINTER
LSTK::	.BLKB	5*LS.SIZ	; LIST STACK (5 lists by SIZ saved bytes)
TKPEND::.BLKB	LS.SIZ		; End of list stack
NOTLM::	.BLKW	1		; NOTE SAVED LEFT MARGIN
NOTRM::	.BLKW	1		; NOTE SAVED RIGHT MARGIN
NOTSV::	.BLKW	1		; SAVED FLAG WORD ON NOTE PROCESSING
EXSTAT::.BLKB	1		; I/O status
EXSP1::	.BLKB	1		; REAL SPACES/EXPANDABLE SPACE
EXSP2::	.BLKB	1		; COUNT TO NEXT EXTRA SPACE
EXSP3::	.BLKB	1		; -1=EXTRA SPACES TO LEFT  0=TO RIGHT
EXSP4:	.BLKB	1		; Permanent EXSP3
EXMSP::	.BLKB	1		; Extra micro spaces
CPOS::	.BLKW	1		; CURRENT CHAR POSITION
XFIRST::.BLKW	1		; First index entry (first in alphabet)
EQBOT::	.BLKW	1		; Vertical size of equation denominator
EQTOP:: .BLKW	1		; Vertical size of equation numerator
EQSTK::	.BLKW	62.		; Equation stack
EQSEN::				; End of equation stack

FOTSV::	.BLKB	SAVSZ+4		; FOOTNOTE SAVE PARAM TABLE
PFTSV::	.blkb	PFSIZ+2		; Permanent footnote save table
	.EVEN

ESCTAB:: .BLKB	18.		; Saves locked escape sequences
TABTAB:: .BLKB	TABTL		; Table of tabstops
	.even
NTABS::	.BLKW	1

NLPG::	.BLKW	1		; MAX LINES THIS PAGE
PNLPG::	.BLKW	1		; PERMENANT MAX LINES/PAGE
VAREND:: .BLKW	1		; end of variables
 
	.psect	TEXT,RO,D,LCL,CON
ONPGTX: .ASCIZ	/ file: /
ONLNTX: .ASCIZ	/On input line /
JUSRM1:	.ASCIZ	/RNO -- Can't justify line/
EQERTX: .ASCIZ	/RNO -- Missing right braces (}) in equation/
TXDERR:	.ASCIZ	/RNO -- Deferred page overflow/
	.PSECT	$CODE,RO,I,LCL,CON
;
;	INPUT LINE
;
LINUC::	CALL	SHFUC		; Get input in Uppercase
LIN::	CALL	OUTAD		; GET OUTPUT BUFFER ADDRESS
	CALL	GCIN		; Get input text
	CMPNEB	R1,#LF,10$	; NOT LINE FEED
	RETURN
10$:	TSTNE	BRCNT,11$	; NO SPACES TO ALLOW HYPHENATION
	JMP	70$		; Output
11$:	CMPEQB	LCH,#SPC,60$	; Last char space?
	TST	LINBK		; Line <= max length?
	BGE	70$		; yes, keep it intact
	TSTNEB	$HYPSW,60$	; No hyphenation ?
	CMPB	HYPCT,#2	; Check previous hyphenation count
	BGE	60$		; Prevent 3 in a row
;	Inhibit hyphenation at bottom of page
	MOV	LINEC3,R1	; Check if at bottom of page
	SUB	#LINSP,R1	; Subtract space necessary
	BLT	12$		; Past the bottom ?
	SUB	NSPNG,R1	; Now is lines - 1
	BLT	60$		; Current line at bottom of current ?
;	**********************************************************
	.ifDF	H$$PHN		; Autohyphenation ????
12$:	TSTNEB	$AUHYP,50$	; No autohyphenation ?
	MOV	LNINS,R1	; Char count at last char on line
	SUB	LSPCH,R1	; Subtract char at last break
	MOV	R1,LNINS	; Number of chars from end of lin
	CMP	R1,HYPSV	; Check if too few chars
	BLT	60$		; Too few for hyphenation
	MOV	LSTSP,R1	; Address of last space
	CALL	FNDBF		; SET POINTER TO IT
	MOV	#TTBUF,R2	; GET TEMPORARY BUFFER
	CLRB	(R2)+		; Chock beginning
	MOV	#49.,R4		; Maximum number of chars
14$:	CALL	GBYT		; GET CHARACTER
	BCS	17$		; DONE
	BITEQB	#140,R1,14$	; Non printable char?
	BIC	#^C<177>,R1	; clear extra bits
	CMPEQB	GCTABL(R1),#GC.LC,270$ ; lowercase ?
	CMPEQB	GCTABL(R1),#GC.UC,260$ ; uppercase ?
	BITEQB	CHTABL(R1),#CH.PNC,60$ ; Not legal punctuation ?
	BR	270$		; Save punctuation
260$:	ADD	#40,R1		; make it lowercase
270$:	MOVB	R1,(R2)+	; SAVE CHAR
	SOB	R4,14$		; CONTINUE TILL DONE
17$:	CLRB	(R2)+		; NULL FOR END OF STRING
	MOV	#TTBUF+1,R0	; BUFFER WITH HYPHENATION INFO
	CALL	HYPHEN		; TRY TO HYPHENATE THE WORD
	BEQ	60$		; No hyphenation ?
	MOV	#TTBUF+1,R0
	ADD	LNINS,R0	; POINTS TO END OF WORD
30$:	TSTB	-(R0)		; HYPHENATION?
	BMI	40$		; YES
	BNE	30$		; Not done ?
	BR	60$		; NO HYPHENATION
40$:	SUB	#TTBUF+1,R0	; Now is number of chars to transfer
	BR	55$
	.endc			;
;	***********************************************
50$:	MOV	HYPSP,R0	; Spacing at hyphenation
	SUB	LSPCH,R0	; Subtract off last spacing char count
55$:	MOV	R0,LINBK	; NUMBER OF CHAR TO TRANSFER
	BLE	60$		; No hyphenation set up ?	
	CALL	BKUP		; BACKUP TO LAST SPACE
	DECB	$GCEND		; Immediate return on LINBK=0
	CALL	GCSPC		; AT BEGINNING INSERT SPACE
	CLRB	$GCEND		; Regular return restored
	MOV	#'-,R1		; INSERT HYPHEN
56$:	CALL	PUBYT		; OUTPUT IT
	INC	SPCH		; ONE MORE CHAR
	INCB	HYPCT		; Count this hyphenation
	BR	70$		; hyphenation done
60$:	CALL	BKUP		; BACKUP TO CORRECT LOCATION
	CLRB	HYPCT		; Reset hyphenation count
70$:	CALL	OUTLIN		; OUTPUT LINE,JUSTIFIED IF FLAGS
LINFIL:	BITEQ	#FILLF,F.1,110$	; No fill ?
90$:	CALL	CCIN		; Get a char
	CMPEQB	R1,#SPC,90$	; Space ?
	CMPEQB	R1,#CR,90$	; Carriage return
	CMPNEB	R1,#LF,100$	; Not line feed
	RETURN			; Kill input line
100$:	CALL	BKSPI		; Backspace 1
110$:	CALL	LINBEG		; BEGIN A NEW LINE
	JMP	LIN		; START NEXT LINE

BKSPI::	MOVB	SUBSTK,R0
	MOV	BUFADD(R0),R0	; current input header
	TSTEQ	BF.FUL(R0),10$	; at beginning?
	DEC	BF.FUL(R0)	; Decrement index
	DEC	BF.ADD(R0)	; Previous address
	INC	BF.CNT(R0)	; Increment count
10$:	RETURN
;
;	ROUTINE TO BACKUP OVER LAST SPACE (INPUT + OUTPUT)
;
BKUP::	CALL	LSINRS		; Restore input stack
	CALL	OUTAD		; OUTPUT BUFFER ADDRESS
BKOUT:	MOV	LSTSP,R1	; LAST SPACE ADDRESS
	CALL	RSTBF		; GO BACK TO PREVIOUS POINT IN BUFFER
	MOV	LSPCH,SPCH	; RESTORE CHAR COUNT
	MOV	LESMSK,ESMSK	; Restore escape stack
	MOVB	LUNLSW,$UNLSW	; Restore underline switch
	MOV	CASSAV,CASE	; RESTORE PREVIOUS CASE
	MOV	SPCNSV,SPCNT	; Restore previous space count
	MOVB	LSCH,LCH	; RESTORE LAST CHAR BEFORE SPACE
	MOV	LPHSP,PHSP	; Restore character spacing
	DEC	BRCNT		; One fewer break
10$:	RETURN
;
;	The .NO SPACE COMMAND
;
NOSPC::	CMPNE	LCH,#SPC,10$	; Last char space ?
	BITNE	#FILLF,F.1,BKOUT	; Fill on ?
10$:	RETURN
;
; ENDBCM--END OF BREAK COMMAND
;

ENDBCM::CALL	LINSET		; SET FOR NEW LINE (BREAK COMMAND)

;
; ENDCM--END OF COMMAND
;
ENDCM::	CALL	$FRCND		; FORCE TO LOGICAL END OF LINE
	CMPEQ	$NFLSW,R1,LGO	; COMMAND FLAG NEXT CHARACTER?
	CMPEQ	#SEMI,R1,LGO	; MORE TEXT ON LINE?
	CMPEQ	R1,#CR,LCR	; END OF LINE	
	CMPEQ	R1,#LF,LGO	; FINAL END OF LINE
	CALL	CCIN		; Advance pointer for extra char.
	MOV	#27.,R0		; Error message
	CALL	ILMSG
KILCM::	CALL	CCIN		; FORCE TO LOGICAL END OF LINE
	CMPEQ	$NFLSW,R1,10$	; COMMAND FLAG NEXT CHARACTER?
	CMPEQ	#SEMI,R1,LGO	; MORE TEXT ON LINE?
	CMPEQ	R1,#CR,LCR	; END OF LINE	
	CMPEQ	R1,#LF,LGO	; FINAL END OF LINE
	BR	KILCM
10$:	CALL	BKSPI		; Backspace over this char
	BR	LGO		; Process next command
;
; END OF LINE PROCESSING
;
COMNT::				; Process comment lime
LCR::	CALL	CCIN		; GET FILE CHARACTER
LCR1:	CMPNE	R1,#LF,LCR	; NOT A LINEFEED?

;
;	READ AND PROCESS NEXT LINE
;
	.ENABL	LSB
LGO::	MOV	SPSAV,SP	; RELOAD STACK POINTER
	CALL	CCIN		; READ INITIAL CHARACTER ON LINE
	MOV	BUFADD,R0	; INPUT BUFFER
	MOV	BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT
	TSTEQB	EOFSW,20$	; NOT END OF FILE?
	BIC	#TEXF,F.1	; No deferred text now
	CALL	OUTNJ		; FLUSH OUT LAST LINE
	TSTEQ	$FIGDF,10$	; No deferred figures ?
	CALL	PAGEC
10$:	MOVB	#-1,$HDRSW	; SET NO HEADER
	CLR	TMARG		; No top margin
	CALL	PAGEC		; FORCE A PAGE
	JMP	ENDFIL		; END OF FILE
20$:	CMPEQ	R1,#LF,LGO	; FORMFEED ON INPUT?
	BITNE	#LITFG,F.1,70$	; PROCESSING LITERAL?
	BITEQ	#FILLF,F.1,60$	; NOT FILLING FROM INPUT FILE?
	TSTEQB	$AUTSW,70$	; AUTOPARAGRAPH NOT ACTIVE?
	CMPEQ	#CR,R1,40$	; NULL LINE?
	CMPEQ	#TAB,R1,30$	; LEADING TAB?
	CMPNE	#SPC,R1,70$	; NOT LEADING SPACE?
30$:	CALL	CCIN		; READ NEXT CHARACTER
35$:	CMPEQ	#SPC,R1,30$	; SPACE?
	CMPEQ	#TAB,R1,30$	; TAB?
	CMPNE	#CR,R1,50$	; NOT CARRIAGE RETURN?
40$:	CALL	CCIN		; BYPASS LINE FEED
45$:	CALL	CCIN		; READ NEXT CHARACTER
	MOV	BUFADD,R0	; INPUT BUFFER HEADER
	MOV	BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT
	CMPEQ	$NFLSW,R1,90$	; LEADING PERIOD?
	BR	35$		; Now kill spaces
50$:	CALL	OUTNJ		; BREAK CURRENT LINE
	CALL	PARTP		; PERFORM PARAGRAPH BREAK
	CALL	LINSET		; RESET LINE PARAMETERS
	BR	TEXT		; PROCESS TEXT
60$:	TSTNEB	$KEPSW,70$	; Keep on ?
	CMPEQ	#CR,R1,LCR	; NULL LINE?
70$:	CMPEQ	R1,$NFLSW,90$	; PERIOD AS FIRST CHAR?
TEXT::	CALL	BKSPI		; BACKSPACE THE INPUT
	CALL	LSINSV		; Save address of last space
	CALL	OUTAD		; GET OUTPUT BUFFER
80$:	TSTNEB	$CENSW,81$	; Centered text?
	TSTNEB	$RIGSW,81$	; Right justified text?
	BITNE	#FILLF,F.1,TEXTF; Filling from input file?
81$:	CALL	OUTNJ		; Output either not just, cent, or right just.
TEXTF:: CALL	LINFIL		; Start input
	BR	LGO		; End of input line
90$:	CALL	CMN		; PARSE COMMAND
	MOV	#ENDCM,-(SP)	; ASSUME NONBREAK COMMAND
	MOV	(R3),-(SP)	; SET ADDRESS OF COMMAND ROUTINE
	MOVB	(R2),-(SP)	; GET FLAG BYTE
	BITEQB	#BRKF,(SP),100$	; NOT BREAK COMMAND?
	CALL	OUTNJ		; BREAK CURRENT LINE
	MOV	#ENDBCM,4(SP)	; SET FOR BREAK COMMAND
100$:	MOV	#RCNO,R4	; SET ADDRESS OF NUMBER CONVERSION ROUTINE
	BITEQB	#RELF,(SP)+,120$ ;ABSOLUTE CONVERSION REQUIRED?
	MOV	#RCNR,R4	; SET ADDRESS OF RELATIVE CONVERSION ROUTINE
120$:	JMP	@(SP)+		; DISPATCH TO COMMAND ROUTINE
	.DSABL	LSB
 

;
;	ERROR OUTPUT
;
HLTER::	MOV	#9.,R0		; Error message
ILINP::	CALL	ERMSG		; Output error message
	JMP	RUNOFF		; And begin again
ILCM::	MOV	#4,R0		; Illegal command message
ILCMA::	MOV	#KILCM,(SP)	; Finish up by finding next command
	BR	ILMSG		; After printing line and page number
ILTXT:	MOV	#LCR,(SP)	; FINISH UP SECTION
ILMSG::	CALL	ERMSG		; Output error message
;
;	Here we generate traceback through the substitutions
;
ONLIN::	MOVB	SUBSTK,R4	; Get substitute stack
20$:	TSTEQB	R4,70$		; No substitutions
	MOV	BUFADD(R4),R2	; Now have substitute header
	SUB	#2,R4		; Next subs.
	CALL	GETTBF		; Get temporary buffer into R3
	MOV	BF.FUL(R3),R1	; Current index
	CALL	RSTBF		; Terminate buffer at current index
	MOV	BF.SPC(R3),R1	; Start of substitution
	CALL	FNDBF
	MOV	#TTBUF,R2	; Temporary output buffer
30$:	CALL	GBYT		; Get 1 byte
	BEQ	40$		; Till done
	MOVB	R1,(R2)+	; Move it
	BR	30$		; Continue till whole label trans.
40$:	MOVB	#':,(R2)+	; And colon
50$:	CALL	GBYT		; And next substitute
	BCS	60$		; Done ?
	MOVB	R1,(R2)+	; Save char
	CMP	R2,#TTBUF+79.	; Too much ?
	BLO	50$		; No ?
60$:	MOV	#TTBUF,R1	; Address to output
	SUB	R1,R2
	CALL	TTOUT		; Output traceback
	BR	20$
;
;	Print input line
;
70$:	MOV	BUFADD,R3	; GET CURRENT BUFF ADDRESS
	MOV	ERSTR,R1	; POINTS TO BUFFER
	MOV	BF.ADD(R3),R2	; CURRENT CHAR ADDRESS
	SUB	R1,R2		; NUMBER OF BYTES
	INC	R2
	CMP	R2,#79.		; OK?
	BLE	80$		; YES
	MOV	#79.,R2		; YES		
80$:	CALL	TTOUT		; PRINT OFFENDING LINE
	CALL	TTINOU		; Type whole line for ident.
;
;	Tracback through the input files
;
ONPAG::	BISB	#20,$UNLSW	; No underlining
	MOV	TRCBUF,-(SP)	; Traceback begin
1$:	MOV	#TTBF,R3	; BUFFER FOR OUTPUT
	CALL	CLRBF		; CLEAR BUFFER
	MOV	#ONLNTX,R0	; On line text string
	CALL	PSTRZB		; MOVE IT TO BUFFER
	MOV	(SP),R4		; Get line
	MOV	(R4)+,R0	; Input Line number
	CALL	DECTY		; Convert to number
	MOV	#ONPGTX,R0	; ON PAGE STRING
	CALL	PSTRZB		; Into buffer
10$:	MOVB	(R4)+,R1	; Get byte
	BEQ	20$		; Done
	CALL	PBYT
	BR	10$
20$:	MOV	#TTBUF,R1	; BUFFER ADDRESS
	MOV	BF.FUL(R3),R2	; SIZE OF STRING
	CALL	TTOUT		; OUTPUT IT
	SUB	#TRCLN,(SP)	; Next string ?
	CMP	(SP),#TRCBUF	; At end ?
	BHI	1$		; No
	BICB	#20,$UNLSW	; underlining
	TST	(SP)+
	RETURN
;
;	Put converted page number into buffer
;
PUTPAG:: CLR	-(SP)		; stop for conversion routine
	MOVB	#'-,$SEPR	; specify separator character
	TSTNEB	$CHPSW,20$	; no chapter print?
	MOV	APNDN,R1	; GET CURRENT APPENDIX LEVEL
	BEQ	10$		; IF EQ NONE
	BIS	APNDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
	BR	20$		; 
10$:	MOVB	CHPTN,R1	; GET CURRENT CHAPTER NUMBER
	BEQ	20$		; IF EQ NONE
	BIS	CHPDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
20$:	MOV	PAGENO,R1
	BIS	PAGDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
	TSTEQ	$SBPSW,40$	; NO SUBPAGE?	
	MOV	SUBPGE,R1	; SUB PAGE NUMBER
	BEQ	40$		; none
	BIS	SUBDSP,R1	; set format
	MOV	R1,-(SP)	; Save for conversion
40$:	CALL	PAGCV		; convert numbers
	RETURN			; 

;
;	CONVERTS PAGENUMBERS on stack terminated by null
;		R3 = buffer header to recieve the final string
;		Format	NUMBER
;			+100000 = Letters (upper case)
;			+120000 = Letters (lower case)
;			+140000	= Roman numeral (upper case)
;			+160000 = Roman (lower case)
;			+010000 = (upper  case first letter)
;	Roman numerals go from 0-2047
;
;		- sign appears after letters, before numbers.
;		ex.  10-5  A-10  10A  A-10B
;
;
PAGCV::	MOV	(SP),-(SP)	; save stack
	MOV	SP,R2		; To find base entry
1$:	TST	(R2)+		; base entry?
	BNE	1$		; not yet
	CLR	2(SP)		; clear old return address
;		now reverse stack between R1,R2
	MOV	SP,R1		; current stack pointer
2$:	MOV	(R1),R0		; save lower entry
	MOV	-(R2),(R1)+	; move upper to lower
	MOV	R0,(R2)		; move lower to upper
	CMP	R1,R2		; not done?
	BLO	2$		; yes
	TST	(SP)+		; unstack extra entry
3$:	MOV	(SP)+,R0	; number?
	BNE	10$		; YES
5$:	RETURN
10$:	MOV	R0,R4		; save status
	BITNE	#100000,R0,20$	; Is it letter?
	CALL	DECTY		; convert number
	BR	50$		; next!
20$:	BIC	#170000,R0	; clear extra
	BITNE	#40000,R4,70$	; Roman?
	CLR	-(SP)
30$:	MOV	#26.,R1		; 26 letters/ alphabet
	CMP	R0,R1		; last letter?
	BHI	31$		; No
	DEC	R0		; yes, decrement it
31$:	CALL	$DIV		; get rhand digit
	ADD	#'A,R1		; convert to letter
	MOV	R1,-(SP)	; save it
	TSTNE	R0,30$		; more?
	BR	110$		; no, put into buffer
50$:	MOV	(SP)+,R2	; end?
	BEQ	5$		; yes
	BGT	60$		; Number?
	BITNE	#40000,R2,60$	; Roman numeral?
	TST	R4		; last one letter?
	BGT	65$		; no
60$:	MOVB	$SEPR,R1	; output a separator
	CALL	PUBYT
	INC	BF.SPC(R3)	; Count spacing chars
65$:	MOV	R2,R0		; save char
	BR	10$
70$:	CLR	-(SP)		; end of stack table
	MOV	#RMTAB,R2
	BR	85$
80$:	ADD	#2,R2		; Next numeral
85$:	TSTEQ	R0,110$		; done yet?
	MOV	#10.,R1		; Divide by 10
	CALL	$DIV		; convert
	TSTEQ	R1,80$		; none this letter?
	CMPEQ	R1,#4,100$	; reversed letters?
	BLT	90$		; Less than 4 ?
	SUB	#5,R1		; Now is less 5
	BEQ	88$
	CMPNE	R1,#4,86$	; reversed letters?
	MOVB	2(R2),-(SP)	; ex. IX
	BR	101$
86$:	MOVB	(R2),-(SP)	; save letters
87$:	SOB	R1,86$		; till done
88$:	MOVB	1(R2),-(SP)	; Save 5 char
	BR	80$
90$:	MOVB	(R2),-(SP)	; save letters
	SOB	R1,90$		; till done
	BR	80$
100$:	MOVB	1(R2),-(SP)	; output next higher letter
101$:	MOVB	(R2),-(SP)	; and current one ex. 4 = IV
	BR	80$
110$:	MOVB	(SP)+,R1	; unstack numerals
	BEQ	50$		; done?
	BITEQ	#20000,R4,120$	; NOT (lower case)?
	BITNE	#10000,R4,120$	; Not (lower case first char)?
	ADD	#40,R1		; make it lower
120$:	CALL	PUBYT		; save in buffer
	INC	BF.SPC(R3)	; Count spacing chars
	BIC	#10000,R4	; set lower? after first byte
	BR	110$
;
;	CONVERTS R0 TO NUMERIC STRING
;		R3=BUFFER HEADER TO PUT STRING
;
DECTY: 	CLR	-(SP)		; SET INDICATOR
10$:	MOV	#12,R1		; SET DIVISOR
	CALL	$DIV		; DIVIDE
	ADD	#60,R1
	MOV	R1,-(SP)	; SAVE RH DIGIT	
	TSTNE	R0,10$		; CONTINUE IF NON ZERO
20$:	MOVB	(SP)+,R1	; 1 DIGIT	
	BEQ	30$		; DONE		
	CALL	PUBYT		; PUT INTO BUFFER
	INC	BF.SPC(R3)	; Count spacing chars
	BR	20$		; CONTINUE TILL DONE
30$:	RETURN			; 		

;
; EXPAND MEMORY
;

EXPAND::MOV	#12.,R0		; Insufficient memory error
	JMP	ILINP		;  Give message and kill program
;
;	SUBROUTINE TO INITIALIZE COUNTS AND POINTERS FOR A NEW LINE
;
LINSET::MOV	RMARG,R2	; COMPUTE REAL WIDTH OF LINE
	SUB	LMARG,R2	; AS DIFFERENCE OF MARGINS
	SUB	INDCT,R2	; MINUS INDENTING
	MOV	R2,LINBK	; STORE IN LINE-BREAK COUNT
	MOVB	ULOCK,CASE	; RESTORE PERMENANT CASE
	CLR	BRCNT		; no breaks yet this line
	CLR	SPCNT		; INITIAL COUNTS OF SPACING
	CLR	SPCNSV
	CLR	SPCH		; AND NON-SPACING CHARS
	CLR	LSPCH
	MOV	ESMSK,LESMSK	; Current end of escape stack
	MOVB	$UNLSW,LUNLSW	; Save underline switch
	CLR	ESCCNT		; NO ESCAPES PENDING
	CLR	OVRCT		; NO BACKSPACE ABORTION
	MOV	#1,CPOS		; CARRIAGE POSITION IS FAR LEFT
	CLR	LCH		; CLEAR LAST CHARACTERs
	CLR	LTAB		; Address of last tab char
	CLRB	$TABPD		; Set no tab pending
	CALL	OUTAD		; GET OUTPUT BUFFER ADDRESS
	BITNE	#FOTF!TEXF,F.1,10$	; Footnote or text in progress?
	CALL	CLRBF		; RESET IT
	BR	20$		; 
10$:	CALL	ENDBF
	MOV	BF.HED(R3),R1	; GET ADDRESS OF CURRENT HEADER
	ADD	#BFHED-1,R1	; POINT TO START OF TEXT
	CMPEQ	R1,BF.FUL(R3),40$ ; Current header unused ? (keep it)
20$:	MOV	BF.FUL(R3),BF.HED(R3) ; LAST HEADER ADDRESS
	INC	BF.HED(R3)	; CORRECT ADDRESS
	MOV	#BFHED,R2	; NUMBER OF TIMES THRU
	CLR	R1		; NULL FOR HEADER
30$:	CALL	PBYT		; DEPOSIT PART OF HEADER
	SOB	R2,30$		; TILL DONE
40$:	MOV	BF.FUL(R3),LSTSP;SET LAST SPACING CHARACTER BACK HERE
	CLR	BF.SPC(R3)
	MOV	CASE,CASSAV	; SAVE CASE
;
;	Save/restore current input stack
;
LSINSV::MOVB	SUBSTK,R1	; input stack
	MOV	R1,LSSTK	; save old value
10$:	MOV	BUFADD(R1),R0	; INPUT BUFFER
	MOV	BF.FUL(R0),LSPIN(R1) ; LAST SPACE ON INPUT
	SUB	#2,R1		; next member
	BGE	10$		; save more
	RETURN
LSINRS::MOV	R3,-(SP)	; Save regs
	MOV	R4,-(SP)
	MOVB	LSSTK,R4	; stack at last space
	MOVB	R4,SUBSTK	; restore previous substitute stack
10$:	MOV	BUFADD(R4),R3	; CURRENT BUFFER ADDRESS
	MOV	LSPIN(R4),R1	; LAST SPACE ADDRESS
	CALL	FNDBF		; GO BACK TO PREVIOUS POINT IN BUFFER
	SUB	#2,R4		; more in stack?
	BGE	10$		; yes
	MOV	(SP)+,R4	; Restore
	MOV	(SP)+,R3	; Restore
	RETURN
;
;	BEGINS A LINE OR CONTINUES LINE AFTER COMMANDS BY SETTING FLAGS
;		R3 is set to point to output buffer
;		All other registers are destroyed
;
LINBEG::CALL	OUTAD		; GET OUTPUT ADDRESS
	MOV	BF.HED(R3),R1	; HEADER BYTE
	CALL	FNDBF		; get the location
	CALL	GBYT		; get status byte
	MOV	R1,-(SP)	; Save current status
	BISB	#HD.LIN,@BF.ADD(R3)	; Output line
	TSTNEB	$CBRSW,10$	; NO CHANGE BAR NEEDED?
	BISB	#HD.BAR,@BF.ADD(R3)	; SET CHANGE BAR BIT
10$:	TSTEQB	$VARSP,20$	; No variable spacing
	BISB	#HD.VAR,@BF.ADD(R3)
20$:	CALL	ENDBF		; go to end of buffer
	BITNE	#HD.LIN,(SP)+,30$	; Escape sequences already set ?
	MOV	ESMSK,R4	; Escape sequences locked on
	BEQ	30$		; None ?
	CALL	ESCBEG		; Begin them
30$:	RETURN			; 
;
;	RESET UNDERLINE BUFFER
;		R0,R1 are destroyed
;
ULBSET::MOV	#UBUFF,R0	; UNDERLIN BUFFER
	MOV	#ULNSZ,R1	; SIZE OF BUFFER
	MOV	#SPC,R2		; Char to transfer
10$:	MOVB	R2,(R0)+	; PUT SPACE INTO IT
	SOB	R1,10$		; TILL FULL
20$:	CLR	ULNMAX
	CLRB	$UNLRS
	MOV	#1,CPOS
	RETURN			; 

;+
; RCNR--RELATIVE DECIMAL CONVERSION ROUTINE
;
; INPUTS:
;
;	R3=BASE VALUE TO BE AUGMENTED.
;
; OUTPUTS:
;
;	NONSKIP RETURN IF NO NUMBER IS PRESENT.
;
;	SKIP RETURN WITH R3 UPDATED TO NEW VALUE.
;		All other registers destroyed
;-

	.ENABL	LSB
RCNR::	MOV	R3,-(SP)	; SAVE BASE VALUE
	CALL	RCNO		; CONVERT DECIMAL NUMBER
	JMP	40$		; NONSKIP RETURN IF NULL
	BEQ	30$		; IF EQ NO SIGN SPECIFIED
	ADD	(SP),R3		; AUGMENT BASE VALUE
	BR	30$		; SKIP RETURN

;
; READ SIGNED DECIMAL NUMBER FOR COMMAND DECODER
; NON-SKIP RETURN IF NONE FOUND
;

RCNO::	CLR	R3		; CLEAR ANSWER AC
	CLR	R5		; Count number of chars converted
	CLR	-(SP)		; AND SIGN FLAG
	CALL	SKPSP		; skip spaces
	BCS	40$		; null param
	CMPNE	#'+,R1,10$	; NOT PLUS SIGN?
	INC	(SP)		; SET PLUS SIGN PRESENT
10$:	CMPNE	R1,#'-,20$	; NOT MINUS SIGN?
	COM	(SP)		; SET NEGATE FLAG
20$:	TSTEQ	(SP),22$	; SIGN NOT SPECIFIED?
21$:	CALL	CCIN		; READ ANOTHER CHARACTER
22$:	CMPNEB	GCTABL(R1),#GC.DIG,23$ ; NOT A DIGIT?
	INC	R5
	ASL	R3		; MULTIPLY BY 10.
	MOV	R3,-(SP)	; 
	ASL	R3		; 
	ASL	R3		; 
	ADD	(SP)+,R3	; 
	SUB	#60,R1		; SUBTRACT OUT CHARACTER BIAS
	ADD	R1,R3		; ADD IN DIGIT
	BR	21$		; AND LOOP FOR MORE.
23$:	TSTNE	R5,24$		; Number?
	CALL	BKSPI		; back over param
	BR	40$		; And signal no input
24$:	CALL	NEXPAR		; SKIP TO NEXT PARAM
	TST	(SP)		; NEGATIVE SIGN?
	BPL	30$		; IF PL NO
	NEG	R3		; NEGATE NUMBER
30$:	ADD	#4,2(SP)	; SET SKIP RETURN
40$:	TST	(SP)+		; CLEAN STACK
	RETURN			; 
	.DSABL	LSB
SKPSP::	CALL	CCIN		; READ CHARACTER FROM COMMAND LINE
	CMPEQ	R1,#CR,10$	; LEADING CARRIAGE RETURN?
	CMPEQ	$NFLSW,R1,10$	; LEADING CONTROL CHARACTER?
	CMPEQ	#SEMI,R1,10$	; LEADING CHARACTER SEMICOLON?
	CMPEQ	R1,#CMA,20$	; LEADING COMMA?
	CMPEQ	R1,#SPC,SKPSP	; SPACES AND TABS?
	CMPEQ	R1,#TAB,SKPSP	; LEADING TAB?
	CLC			; done, no null params
	RETURN
10$:	CALL	BKSPI		; BACKUP TO SAVE CHAR.
20$:	SEC			; null param
	RETURN
;
;	SKIP OVER SPACE,BLANKS, AND 1 COMMA ONLY
;
NEXPAR:	CMPEQ	R1,#CMA,30$	; COMMA?	
	CMPEQ	R1,#SPC,10$	; SPACE?	
	CMPNE	R1,#TAB,20$	; TAB? (DISCARD ALL TABS + SPACES)
10$:	CALL	CCIN		; NEXT CHAR	
	BR	NEXPAR		; AND WHAT IS IT?
20$:	CALL	BKSPI		; NEXT CHAR FOR NEXT TIME AROUND
30$:	RETURN			; 

;
;	routine to get up to 3 char alphameric string
;	String is in right justified RAD50 format
;		C = SET IF No param + R3 = 0
;		R3 = Result + Carry clear
;		Null param leaves R3 unchanged, but C clear
;
;
ALPGT::	CALL	SKPSP		; skip leading spaces
	BCC	10$		; no null param?
5$:	CLC
	RETURN			; null param
10$:	CLR	-(SP)		; initial number
20$:	CMP	(SP),#3100	; Done ?
	BHIS	40$		; Found 3 letters ?
	CMPB	GCTABL(R1),#GC.LC ; letter?
	BGT	40$		; no
	BNE	30$		; upper case?
	SUB	#40,R1		; convert to upper
30$:	SUB	#'@,R1		; convert letter to number
	MOV	(SP),R0		; previous sum
	MOV	R1,(SP)		; save current char
	MOV	#50,R1		; multiplier
	CALL	$MUL		; mult R0 by R1
	ADD	R1,(SP)		; new total
	CALL	CCIN		; next
	BR	20$
40$:	CALL	NEXPAR		; set up for next param
	MOV	(SP)+,R3	; get result
	BNE	5$		; Input ?
	SEC			; no
	RETURN
;
;
;	SUBROUTINE TO PARSE INPUT FOR LITERAL
;		R2=ADDRESS OF LITERAL	R1=LENGTH OF LITERAL
;		CARRY CLEAR IF SUCCESS	SET IF NONE FOUND
;
GETLIT:: CALL	CCIN		; GET 1 CHAR	
	BCS	50$		; BAD, NO FILE SPEC
	CMPEQ	R1,#SPC,GETLIT	; IGNORE	
	CMPEQ	R1,#TAB,GETLIT	; IGNORE	
	CMPEQ	R1,#'',10$	; START OF LITERAL
	CMPNE	R1,#'",40$	; NOT START OFF LITERAL?
10$:	MOV	BUFADD,R0	; GET BUFFER HEADER
	MOV	R1,-(SP)	; char to compare
	MOV	BF.ADD(R0),R2	; ADDRESS OF START OF BUFF
	INC	R2		; FIRST BYTE	
20$:	CALL	CCIN		; NEXT CHAR	
	BCS	50$		; NO MORE	
	CMPEQB	R1,(SP),30$	; END OF LITERAL?
	CMPNE	R1,#CR,20$	; not end of buffer?
	CALL	BKSPI		; backspace over carriage return
30$:	MOV	BUFADD,R0	; BUFFER ADDRESS
	TST	(SP)+		; unstack test char
	MOV	BF.ADD(R0),-(SP) ; SAVE CURRENT ADDRESS
31$:	CALL	CCIN		; GET NEXT CHAR	
	CALL	NEXPAR		; SKIP TO NEXT PARAM
	MOV	(SP)+,R1	; LAST CHAR IN LIT +1 ADDRESS
	SUB	R2,R1		; NUMBER OF BYTES
	CLC			; OK!		
	RETURN
40$:	CALL	BKSPI		; BACKUP 1 CHAR
50$:	SEC			; NOT OK	
	RETURN
;

;+
; $FRCND-FORCE TO LOGICAL END OF COMMAND
;-

$FRCND::CALL	CCIN		; READ CHARACTER FROM FILE
	CMPEQ	#SPC,R1,$FRCND	; SPACE?
	CMPEQ	#TAB,R1,$FRCND	; TAB?
	CMPEQ	#SEMI,R1,10$	; SEMICOLON?
	CALL	BKSPI		; BACKSPACE 1 CHAR
10$:	RETURN			; 

;LINE OUTPUT ROUTINE. TWO ENTRY POINTS

OUTLIN:	MOVB	#-1,TJFSW	; SET JUSTIFYY FLAG
	COMB	EXSP4
	TSTNEB	$CENSW,OUTNJ0	; CENTERED/NOT JUSTIFIED?
	TSTNEB	$RIGSW,OUTNJ0	; Not justify if right justified
	BITNE	#JUSTF,F.1,OUTJ2 ;JUSTIFYING?
OUTNJ::	CLRB	HYPCT		; Clear hyphenation count
OUTNJ0:	CLRB	TJFSW		; CLEAR JUSTIFY FLAG
	CLRB	EXSP4		; CLEAR LEFT RIGHT SPACING
OUTJ2:	CLRB	EXSP2
	CLRB	EXSP1
	MOVB	#-1,EXMSP
	CLR	HYPSP		; Reset hyphenation spacing
	TSTEQ	SPCH,10$	; No spacing chars ?
	CALL	TESTL		; Test and break page if necessary
10$:	TSTNE	SPCH,20$	; Spacing chars ?
	CALL	OUTAD		; GET BUFF ADDRESS
	MOV	BF.HED(R3),R1	; GET LIN HEADER
	CALL	FNDBF		; Set to point to it
	CALL	GBYT		; Get the line count
	BITNEB	#HD.LIN,R1,20$	; Output line ?
	JMP	OUTNJ3		; Do not process output line
20$:	CALL	OUTAD		; GET BUFF ADDRESS
	TSTEQ	@EQSTK,40$	; Is equation not being formatted ?
	MOV	#EQERTX,R0	; Error message for equation
	CALL	EROUT		; Output message
	CALL	ONLIN		; INDICATE WHAT PAGE
	MOV	#EQSTK+2,EQSTK	; Reset equation stack
	BICB	#20,$TABSW	; Allow tabs
	BICB	#20,$NOSPC	; And expandable spaces
40$:	MOV	ESMSK,R4	; Escapes locked on
	BEQ	50$		; None ?
	CALL	ESCEND
50$:	TSTEQB	TJFSW,OUTNJ1	; NOT JUSTIFYING LINE?
	CLRB	TJFSW		; IN CASE	
	MOV	RMARG,R0	; YES. COMPUTE WHERE TO EXPAND THEM
	SUB	LMARG,R0	; SIZE OF LINE
	SUB	INDCT,R0	; ..
	SUB	SPCH,R0		; SUBTRACT NUMBER OF SPACING CHARS
	BEQ	OUTNJ1		; No justifacation needed ?
	MOV	SPCNT,R1	; NOW FIND HOW MANY MULT SPACES EACH SPACE IS
	BNE	60$		; Spaces present to allow justif. ?
	MOV	#JUSRM1,R0	; Can't justify line message
	CALL	EROUT		; Output message
	CALL	ONLIN		; INDICATE WHAT PAGE
	BR	OUTNJ1		; 
60$:	ADD	R1,R0		; ADD NUMBER OF SPACES
	CALL	$DIV		; Divide tot spac/SPCNT = R0/R1
	MOVB	R0,EXSP1	; MULTIPLIER FOR ALL SPACES
	TSTEQB	$VARSP,70$	; No variable spacing ?
	MOVB	VARESC,R0	; Number of steps per space
	BLE	70$		; Bad value ?
	CALL	$MUL		; Now is total number of steps
	MOV	R1,R0		; Into R0
	MOV	SPCNT,R1	; Get number of spaces again
	CALL	$DIV		; DIVIDE
	MOVB	R0,EXMSP	; Number of extra micro spaces
70$:	TSTNEB	EXSP4,80$	; EXTRAS TO LEFT?
	NEG	R1		; RIGHT. GET SPACES BEFORE EXTRAS
	ADD	SPCNT,R1	; ..
80$:	MOVB	R1,EXSP2	; STORE FOR LATER
OUTNJ1:	CALL	OUTAD		; GET BUFF ADDRESS
	MOV	BF.HED(R3),R1	; GET LIN HEADER
	DEC	R1		; Points to first byte
	CALL	FNDBF		; Set to point to it
	CALL	GBYT		; Get the line count
	MOV	EQTOP,R2	; Get top spacing
	BEQ	30$		; None ?
	SUB	R2,LINEC3	; Account for extra lines
	ADD	R2,BF.VSP(R3)	; And vertical spacing this buffer
	ADD	EQTOP,R1	; Add on bottom of equation
	MOVB	R1,@BF.ADD(R3)	; And save it
	CLR	EQTOP		; No more pre spacing
30$:	CALL	GBYT		; Set status byte
	MOVB	R1,EXSTAT	; Save status
	MOV	LMARG,R2	; GET LEFT MARGIN
	TSTEQB	$RIGSW,50$	; Not right justify?
	BICB	#SW.TDS,$RIGSW	; Reset temporary right justify
	MOV	RMARG,R2	; right margin
	SUB	SPCH,R2		; Now have indentation for right justify
	NEG	INDCT		; Switch indentation
50$:	ADD	INDCT,R2	; GET INDENTING IN CASE OF PARAGRAPH
	CLR	INDCT		; (ONCE ONLY)			
	TSTEQB	$CENSW,60$	; NO CENTERING?
	BICB	#SW.TDS,$CENSW	; CLEAR TEMPORARY CENTERING
	MOV	CMARG,R2	; CENTERING MARGIN
	MOV	SPCH,R0		; NUMBER OF CHAR IN LINE
	CLC			; CLEAR C JUST IN CASE
	ASR	R0		; DIVIDE BY 2
	SUB	R0,R2		; NOW IS CHARS TO CENTER
60$:	ADD	EBSIZ2,R2	; ADD ON CHANGE BAR SIZE
	BITEQB	#HD.BAR,EXSTAT,70$	; CHANGE BAR PENDING?
	DEC	R2		; 1 CHAR IS OUT SO STOP ITS SPACE
70$:	MOV	RIGSHI,R1	; Right shift
	ADD	EBSIZ1,R1	; Plus bar spacing #1
	CALL	PBYT		; Output for initial spacing
	MOV	R2,R1		; Spacing after bar
	BGT	80$		; Margin ok?
	CLR	R1		; No, make it 0
80$:	CALL	PBYT		; in buffer
	MOVB	EXSP1,R1
	CALL	PBYT		; in buffer
	MOVB	EXSP2,R1
	CALL	PBYT		; in buffer
	MOVB	EXSP4,R1	; SAVED EXPANSIONS
	CALL	PBYT		; in buffer
	MOVB	EXMSP,R1	; Saved micro expansion
	CALL	PBYT
	CALL	OUTNJ3		; Now do output ?
	JMP	SKIPS		; Set up next line skip
OUTNJ3:	CALL	ENDBF		; go back to end of buffer
	CLR	R1		; Null terminates the line
	CALL	PBYT		; Put at end of line
	MOV	EQBOT,R1	; Get bottom spacing
	BEQ	110$		; None ?
	SUB	R1,LINEC3	; Account for extra lines
	ADD	R1,BF.VSP(R3)	; Account for vertical spacing
	CALL	PBYT		; Put skip count into buffer
	MOV	#200,R1		; Mark it skip only
	CALL	PBYT		; Into buffer
110$:	CLR	EQBOT		; Clear bottom
	BITNE	#FOTF!TEXF,F.1,120$	; Footnote or deferred text?
	CALL	OUTL0		; NO OUTPUT THE LINE
120$:	JMP	LINSET		; Reset line params
;
;	DO ACTUAL OUTPUT TO PRINTER OF TEXT STRING
;
OUTL0::	CALL	OUTAD		; GET HEADER ADDRESS
	TSTNEB	$OUTSW,100$	; No output ?
	CALL	BEGBF		; SET TO TOP OF BUFFER
10$:	CLRB	$ULOSW		; No underlining yet
	CALL	GBYT		; Get skip count
	BCS	100$		; Done ?
	MOV	R1,R2		; Now is skip count
	CALL	GBYT		; Get status
	MOVB	R1,EXSTAT	; Save status
	BITEQB	#HD.TXD,R1,17$	; Not end of text deferred buffer ?
;handle text deferred
17$:	BIC	#177400,R2	; Mask skip count
	BEQ	20$		; None ?
	CALL	$SKIP0		; Skip R2 lines
20$:	TSTB	EXSTAT		; Is this skip only ?
	BGE	25$		; Yes !
	BR	10$		; Get next entry
25$:	CALL	GBYT		; Get initial spacing
	MOV	R1,R2		;
	BIC	#177400,R2	; Clear extra bits
	CALL	NSPAC		; Output n spaces
	BITEQB	EXSTAT,#HD.BAR,30$	; NO BAR?
	MOVB	#'|,R1		; NOPE
	CALL	FOUT		; Output change bar
	INC	CPOS		; Increment position counter
30$:	CALL	GBYT		; Spaces after bar
	MOV	R1,R2		; MARGIN
	BIC	#177400,R2	; Clear extra bits
	CALL	NSPAC		; OUTPUT SPACES
	CALL	GBYT		; Get spacing control parameters
	MOVB	R1,EXSP1
	CALL	GBYT
	MOVB	R1,EXSP2
	CALL	GBYT
	MOVB	R1,EXSP3
	CALL	GBYT
	MOVB	R1,EXMSP
	CALL	CCOUT		; Output + format text
	BCC	10$		; Not end of buffer ?
;
;	END OF LINE, AND FOOTNOTE PROCESSING
;
100$:	CLRB	EXSTAT		; Clear status
	CLRB	EXSP1		; Clear spacing controls
	CLRB	EXSP2
	CLRB	EXSP3
	MOVB	#-1,EXMSP
	BITEQ	#FOTF,F.1,110$	; No footnote in progress?
	MOV	PFOTHD,R1	; Permanent footnote header
	MOV	R1,BF.HED(R3)	; Restore header address
	DEC	R1
	CALL	RSTBF
	MOV	#BFHED,R2	; NUMBER OF TIMES THRU
	CLR	R1		; NULL FOR HEADER
105$:	CALL	PBYT		; DEPOSIT PART OF HEADER
	SOB	R2,105$		; TILL DONE
	MOV	FOTLN,BF.VSP(R3); Permanent footnote size
	RETURN
110$:	JMP	CLRBF		; CLEAR THE BUFFER
;
;	Subroutine to skip N text lines
;		R1=skip count
;	SKIPL	is unconditional skip
;	SKPLIF	is conditional on if not at top of page
;
SKPLIF:: TSTEQB	$PAGBR,SKRET	; Not at top of page
SKIPL::	CALL	MULSP		; Adjust spacing by the line spacing
	MOV	R1,R2		; Now is correct spacing
	BR	SKIPN
;
;	SUBROUTINE TO SKIP N LINES ON OUTPUT FILE
;	R2 = NUMBER OF LINES TO SKIP
;
SKIPS::	MOV	NSPNG,R2	; SET TO SKIP TO NEXT LINE
	BR	SKIPN		; 
SKIP1::	MOV	#LINSP,R2	; SET TO SKIP ONE LINE
SKIPN::	TST	R2		; TOO BIG?
	BLE	SKRET		; YES DO NOT SKIP
	TSTB	$PFOOT		; Permanent footnote
	BLT	40$		; in progress ?
10$:	CMP	R2,LINEC3	; LINE COUNT
	BLT	30$		; Skip count not too many ?
	MOV	LINEC3,R2	; Skip to bottom
	BGT	20$		; Good skip?
	MOV	#LINSP,R2	; No, make it 1
20$:	DECB	$PAGPD		; New page pending
30$:	SUB	R2,LINEC3	; Now line count
	BITEQ	#FOTF!TEXF,F.1,$SKIP0 ; No footnote or deferred text?
40$:	CALL	OUTAD		; GET BUFFER ADDRESS
	ADD	R2,BF.VSP(R3)	; Add to vertical spacing this buffer
	MOV	BF.HED(R3),R1	; GET LAST NUMBER OF LINES
	CALL	FNDBF		; get the location
	MOVB	@BF.ADD(R3),R0	; get old skip
	ADD	R2,R0		; new skip
	MOVB	R0,@BF.ADD(R3)	; TOTAL NUMBER NOW
	CALL	ENDBF		; return buuffer to end
SKRET:	RETURN
$SKIP:	SUB	R2,LINEC3	; ADD LINES TO TOTAL
$SKIP0:	MOV	R3,-(SP)	; SAVE R3
	MOV	R2,-(SP)	; SAVE NUMBER OF LINES TO BE OUTPUT
	INCB	$PAGBR		; NOT AT TOP OF PAGE
	TSTNEB	$ULMSW,50$	; NO NEED TO CONSIDER SAVED UNDERLINES?
	TSTNEB	$OUTSW,40$	; No output ?
	TSTEQ	ULNMAX,40$	; NO UNDERLINES IN BUFFER?
	TSTEQB	$ULSSW,10$	; USE UNDERLINE CHARACTER?
	SUB	#LINSP,LINEC3	; ACCOUNT FOR EXTRA LINE
	CALL	CRLF		; SPACE TO NEXT LINE
	BR	20$		; 
10$:	MOV	#CR,R1		; OUTPUT A CARRIAGE RETURN
	BITEQB	#CRSW,$SWTCH,15$	; No CRLF output?
	CALL	FOUT		; 
15$:	CALL	OUTPUT		; Start a new line
20$:	MOVB	#-1,$UNLRS	; Set up reset underline
	MOV	#UBUFF,R3	; GET UNDERLINE BUFFER
	MOV	ULNMAX,R2	; MAX CHAR
30$:	MOVB	(R3)+,R1	; GET UNDERLINE CHAR
	BGT	36$		; Not microspace ?
	BIC	#177600,R1	; Strip extra bits
	MOV	R1,-(SP)	; Save counter
31$:	MOV	#VARESC+1,R4	; Microspace escape seq.
	DEC	(SP)		; ANother time through ?
	BGE	32$		; Yes ?
	TST	(SP)+		; Pop stacke
	BR	37$
32$:	MOVB	(R4)+,R1	; Get char
	BEQ	31$		; Done yet ?
	CALL	FOUT		; Output it
	BR	32$
36$:	CALL	FOUT
37$:	SOB	R2,30$		; TILL DONE
40$:	TSTEQB	$UNLRS,50$	; No changes in underline buffer ?
	CALL	ULBSET		; RESET UNDERLINE BUFFER POINTER
50$:	MOV	#1,CPOS
	BITEQ	#1,(SP),55$	; No half lines required ?
	DEC	LINEC1		; Account for half lines
	DEC	LINEC2
	MOV	#DNMOV,R2	; Get buffer to transfer
53$:	MOVB	(R2)+,R1	; Get char
	BEQ	54$		; Done ?
	CALL	FOUT
	BR	53$
54$:	CALL	OUTPUT		; Now output the line
55$:	MOV	(SP)+,R2	; RESTORE NUMBER OF LINES
	BIC	#1,R2		; Clear half bit
	BLE	65$		; No more to output
60$:	CALL	CRLF		; SPACE TO NEXT LINE
	SUB	#LINSP,R2	; Lines left
	BGT	60$		; Not done ?
65$:	MOV	(SP)+,R3	; RESTORE R3
70$:	RETURN			; 
;
; ROUTINE TO OUTPUT SPACES TO FILE
;
NSPAC::	DEC	R2		; ANY MORE SPACES TO OUTPUT?
	BLT	SKRET		; IF LT NO
	CALL	CCSPC		; OUTPUT A SPACE
	BR	NSPAC		; 

;
;	SUBROUTINE PUTS CURRENT CHAR ADDRESS INTO R3
;
OUTAD::	BITNE	#FOTF!TXDEF,F.1,10$ ; Deferred or footnote ?
	MOV	#TX2BF,R3	; NORMAL SECONDARY BUFFER
	RETURN			; 		
10$:	BITEQ	#FOTF,F.1,20$	; NOT FOOTNOTE BUFFER?
	MOV	#FOTBF,R3	; GET FOOTNOTE BUFFER ADDRESS
	RETURN			; 
20$:	MOV	#TXDBF,R3	; Text deferred buffer
	RETURN

;
;ROUTINE TO SPACE TO TOP OF FORM
;
FORM:	CLRB	$PAGPD		; No longer page pending
;
;	Output FF or adjust to correct page height
;

	TSTNEB	$FIRPG,40$	; First page?
	TSTNEB	$OUTSW,45$	; No output ?
	BITEQ	#FFDSW,$SWTCH,25$ ;SPACING WITH LINE FEEDS?
	MOV	#FF,R1		; OUTPUT A FORMFEED
	CALL	FOUT				
	CALL	OUTPUT		; Output separate line
	BR	40$		; ADJUST COUNTS	
25$:	MOV	LINEC2,R2	; Number of lines to skip
30$:	BGT	35$		; Go skip em
	BEQ	40$		; Already at bottom
	ADD	LPPG,R2		; GET - NUMBER OF LINES TO TOP OF PAGE
	BR	30$		; 
35$:	CALL	CRLF		; SPACE TO NEXT LINE
	SOB	R2,35$
40$:	CALL	OPRWAT		; WAIT FOR OPERATOR TO POSITION FORMS	
;
;	Setup current page number
;
45$:	TSTEQ	$SBPSW,10$	; NO SUBPAGE?
	MOVB	SUBNX,SUBPGE	; set to current subpage
	MOV	PAGNX,PAGENO	; now current page number
	INCB	SUBNX		; yes increment it
	BNE	20$		; Non zero?
	INCB	SUBNX		; No, make it 1
	BR	20$
10$:	MOV	PAGNX,PAGENO	; now current page number
	INC	PAGNX		; increment next page number
	BNE	20$		; Non zero?
	INC	PAGNX		; No, set to 1
;
;	Test if this page output
;
20$:	DECB	$OUTSW		; Set for no output
	CMP	PAGENO,LOWPAG	; ONLY PRINT IN THE SELECTED PAGE
	BLO	50$		; RANGE
	CMPB	CHPTN,LOWCHP	; chapter # too small?
	BLO	50$		; yes
	CMPB	APNDN,LOWAPN	; appendix too small?
	BLO	50$		; yes
	CMP	PAGENO,HGHPAG	; page number too big?
	BHI	23$		; yes
	CMPB	CHPTN,HGHCHP	; too big?
	BHI	23$		; yes
	CMPB	APNDN,HGHAPN	; appendix too big?
	BLOS	24$		; No ?
23$:	MOV	#ENDFIL,(SP)	; Set to terminate file
24$:	CLRB	$OUTSW		; Set output on
;
;	Set up params next page
;
50$:	MOVB	NXLAY,$LAYOU	; Current layout is now Next layout
	MOVB	PRLAY,NXLAY	; Next is permanent layout
	MOV	NXEPSP,$EOPSP	; Next end-of-page spacing
	MOV	PREPSP,NXEPSP	; Permanent eop spacing
	MOV	NLPG,LINEC1	; Active lines this page
	SUB	$EOPSP,LINEC1	; Subtract off bottom lines
	MOV	LINEC1,LINEC3	; Potential lines per page
	BITEQ	#FOTF,F.1,60$	; Footnote not in progress ?
	SUB	FOTBF+BF.VSP,LINEC3	; Subtract off header size
60$:	MOV	LPPG,LINEC2	; Number of lines this page
	SUB	TX2BF+BF.VSP,LINEC3	; Subtract off deferred lines
	BIC	#TEXF,F.1	; Clear out deferred text flag
	RETURN

;
;	Routine to convert vetical spacing to appropriate number
;
CVSP::	TSTEQB	$HSPSW,10$	; Half spacing ?
	ASL	R3		; Convert to half space count
10$:	RETURN
;
;	Find actual adjusted lines
;		R1=# of text lines
;		R0,R1=hi,low order result
;
MULSP::	MOV	NSPNG,R0	; Get line spacing
	CALL	$MUL		; Find adjusted lines to skip
	RETURN
;
;	Test if room for lines of text
;
TESTT::	CALL	MULSP		; Convert to actual spacing
	BR	TESTP
; 
;	Test if enough room for 1 more line, and if not break page
;
TESTL::	MOV	#LINSP,R1	; Number of lines to test
	ADD	EQBOT,R1	; Add on extra equation lines
	ADD	EQTOP,R1
	BITEQB	#FOTF,F.1,TESTP	; No footnote or deferred text?
	ADD	NSPNG,R1	; Add in line spacing
;
;	R1 = number of lines requested, check if break page?
;
TESTP::	TSTB	$PFOOT		; Permanent footnote in progress?
	BLT	10$		; Yes ?
	CMP	R1,LINEC3	; COMPARE TO LENGTH 
	BGT	BPAGE		; START A NEW PAGE
10$:	SEC			; NO PAGE BROKEN
	RETURN			; 
;
; SUBPAGE command
;
TPAGE::	BISB	#SW.DIS,$SBPSW	; Set subpage flag
	BR	BPAGE
;
;	Reset to page # 0 and begin new page
;
PAGRST:: TSTNEB	$CHPSW,PAGEC	; Not chapter oriented?
	MOV	#1,PAGNX	; Next page number is 1
;
;	END SUBPAGE command
;
PAGEC::	CLR	$SBPSW		; CLEAR SUBPAGE FLAG
	CLR	SUBPGE		; reset subpage
	MOVB	#1,SUBNX	; clear next subpage
	BR	BPAGE
;
;	PAGE command (new page only if not already at top-of-page)
;
CPAGE::	TSTNEB	$PAGBR,BPAGE	; Page not already boken?
	CLC			; Signify page broken
;
; BREAK COMMAND
;
BREAK::	RETURN

;
;	Start new page routine
;
BPAGE::	BITEQ	#FOTF,F.1,10$	; No footnote in progress?
	CALL	OUTL0		; Do footnote output
	CALL	LINSET		; Reset line params
	BR	30$
10$:	TSTEQB	$FOTPD,30$	; NO FOOTNOTE PENDING?
	MOV	LINEC3,R2	; LINES LEFT
	BLE	20$		; NONE
	CALL	$SKIP		; SKIP THEM
20$:	BIS	#FOTF,F.1	; SET FLAG
	CLRB	$FOTPD		; CLEAR PENDING
	CALL	OUTL0		; OUTPUT IT
	BIC	#FOTF,F.1	; CLEAR FLAG
30$:	CLRB	$ULOSW		; No underlining of headers!
	TSTNEB	$FIRPG,35$	; First page?
	BITEQB	#LAY.NB,$LAYOU,35$	; Not number at bottom of page?
	MOV	LINEC1,R2	; Lines remaining this page
	ADD	$EOPSP,R2	; Add on end of page spacing
	SUB	#LINSP,R2	; Compensate for number to print
	BLE	32$		; None?
	CALL	$SKIP		; Skip em
32$:	CALL	HDMRG		; Set up left margin
	CALL	HDPAG		; Get page to output
	MOV	#LINSP,R2	; Skip 1 line
	CALL	$SKIP		; To end number at bottom of page
35$:	CALL	FORM		; OUTPUT FORMFEEDS OR LINEFEEDS
	MOV	TMARG,R2	; LINES TO SKIP	
	BLE	40$		; NONE
	CALL	$SKIP		; SKIP N LINES
40$:	TSTNEB	$HDRSW,90$	; NO HEADERS TO BE PRINTED?
	CALL	HDMRG		; Set up left margin
	TSTNE	$NTITL,50$	; no title?
	MOV	#TTLBF,R3	; HEADER BUFFER
	CALL	CENTIT		; Center title if necessary
	CALL	PSTRPA		; PRINT STRING FROM PA
50$:	BITNEB	#LAY.NB,$LAYOU,60$ ; Page number at bottom?
	CALL	HDPAG		; Get page number
60$:	MOV	#LINSP,R2	; LINES TO SKIP
	CALL	$SKIP		; DO IT
	TSTNE	$NTITL,70$	; no title?
	MOV	#STLBF,R3	; OUTPUT THE SUBTITLE, IF ANY
	CALL	HDMRG		; Set up margins
	CALL	CENTIT		; Center the subtitle?
	CALL	PSTRPA		; ..
70$:	MOV	HSPAC,R2	; LINES TO SKIP
	BGT	80$
	MOV	#LINSP,R2	; Only 1 skip
80$:	CALL	$SKIP		; DO IT
90$:	BICB	#SW.TDS,$HDRSW	; Reset temporary header disable
	CLRB	$ULOSW		; No underlining
	CLRB	$PAGBR		; INDICATES AT TOP OF PAGE
	MOV	$FIGDF,R2	; Lines to skip at end
	BLE	110$		; None
	CMP	R2,LINEC3	; Compare
	BLT	100$		; Not too many
	MOV	LINEC3,R2	; Make it enough
100$:	CALL	$SKIP		; Skip them
110$:	CLR	$FIGDF		; Clear deferred lines
	CLRB	$FIRPG		; Indicates not first page of document
	CLC			; INDICATE PAGE BROKEN
	RETURN			; 
HDMRG:	MOV	EBSIZ1,R2	; SPACE FOR CHANGE BAR OFFSET
	ADD	EBSIZ2,R2
	ADD	RIGSHI,R2	; ADD ON RIGHT SHIFT
	ADD	PLMRG,R2	; ADD ON PERMENANT LEFT MARGIN
	CALL	NSPAC		; SPACE TO MARGIN	
	RETURN			;
CENTIT:	MOV	PRMRG,R2	; Permanent right margin
	SUB	PLMRG,R2
	SUB	BF.SPC(R3),R2	; Subtract off char count
	BLE	50$		; None to do
	BITNEB	#LAY.CT,$LAYOU,10$	; Center title?
	BITEQB	#LAY.LR,$LAYOU,50$	; No odd even layout
	BITEQB	#1,PAGENO,50$	; Not odd page number?
	BR	20$			; Shift to right justify
10$:	CLC
	ASR	R2
20$:	CALL	NSPAC		; Space over to margin
50$:	RETURN
HDPAG:	TSTEQ	$NUMSW,60$	; NO PAGE NUMBER?
	MOV	#TTBF,R3	; GET TEMPORARY BUFFER
	CALL	CLRBF		; CLEAR IT
	TSTNEB	$PAGSW,50$	; OUTPUT 'PAGE'?
	MOV	#PAGHD,R0	; PAGE HEADER
	CALL	PSTRZB		; MOVE IT TO BUFFER
50$:	BISB	#20,$UNLSW	; No underlining
	CALL	PUTPAG		; PUT PAGE INTO BUFFER ALSO
	BICB	#20,$UNLSW	; Restore underlining
	MOV	#PAGH2,R0	; And second header
	CALL	PSTRZB		; Put it also
	MOV	PRMRG,R2	; PERMENANT RIGHT MARGIN
	SUB	CPOS,R2		; Minus current position
	ADD	EBSIZ1,R2
	ADD	EBSIZ2,R2
	ADD	RIGSHI,R2
	INC	R2		; Compensate for CPOS
	SUB	BF.FUL(R3),R2	; Minus number size
	BITNEB	#LAY.CP,$LAYOU,51$	; Centered page number?
	BITEQB	#LAY.LR,$LAYOU,55$	; No odd even layout
	BITEQB	#1,PAGENO,57$	; Not odd page number?
	BR	55$
51$:	CLC
	ASR	R2			; Center it
55$:	CALL	NSPAC		; SPACE TO PAGE NUMBER
57$:	CALL	PSTRPA		; OUTPUT STRING IN BUFFER
60$:	RETURN

;
; SUBTITLE COMMAND
;
SETSTL:: MOV	#STLBF,R3	; SUBTITLE BUFFER
	BR	SETBF		; 
;
;	no title command
;
NTITL::	MOV	SP,$NTITL	; set no title print
	RETURN
;
; FIRST TITLE COMMAND
;
UCTTL:: CALL	SHFUC		; Set mode to uppercase
	BR	SETTL
FTITL::	BITNE	#LCKF,F.1,SETTL	; Params locked?
	CLRB	$HDRSW		; ENABLE HEADER ON FIRST PAGE
;
; TITLE COMMAND
;
SETTL::	MOV	#TTLBF,R3	; SET FOR TITLE BUFFER
	BITEQ	#LCKF,F.1,SETBF	; param not locked?
	CLR	$NTITL		; set for print of titles
SETBF::	CALL	CLRBF		; SET BUFFER EMPTY
	CLRB	$BFSTC		; Clear the buffer counters
	CLR	BF.SPC(R3)	; NO SPACING CHAR
SETB1::	MOVB	#40,R0
	BISB	R0,$TABSW	; DISABLE TABS
	BISB	R0,$ESCSW	; DISABLE ESCAPE SEQ.
	BISB	R0,$EQFSW+1	; Disable equation mode
	BISB	R0,$HYPSW	; Disable hyphenation
SETB2::	CALL	$FRCND		; FORCE TO LOGICAL END OF COMMAND
	TSTNEB	$BFSTC,10$	; Keep buffer structure same
	MOV	BRCNT,-(SP)	; Save break count
	MOV	LCH,-(SP)	; SAVE LAST CHAR
	MOV	LSTSP,-(SP)	; location of last space
	MOV	LTAB,-(SP)	; Location of last tab
	MOVB	$TABPD,-(SP)	; And pending tab
	MOV	SPCH,-(SP)	; SAVE SPACIN CHAR
	MOV	LSPCH,-(SP)	; char count at last space
	MOVB	$UNLSW,-(SP)	; Save current underline switch
	MOVB	LUNLSW,-(SP)	; Last underline switch
	MOV	SPCNT,-(SP)	; SPACES/LINE
	MOV	SPCNSV,-(SP)
	MOV	LINBK,-(SP)	; LINE COUNTER
	MOV	F.1,-(SP)	; SAVE MORE FLAGS
	BIS	#FILLF,F.1	; SET TO FILL (GET RID OF SPACES)
	CLRB	LCH		; START OF LINE
	CLR	SPCH		; No spacing chars 
	CLR	LSPCH
	CLR	SPCNT		; Space count
	CLR	SPCNSV
	CLR	BRCNT
	CLR	LTAB		; No tabs pending
	CLRB	$TABPD
	MOV	PRMRG,LINBK	; Max number of char in buffer
	SUB	PLMRG,LINBK	; Minus permanent right margin
	SUB	#8.,LINBK	; Minus a little bit for numbers
10$:	CALL	GCIN		; READ TITLE OR SUBTITLE
	CMPNE	R1,#LF,11$	; End of line?
	CALL	BKSPI		; Backspace over LF
	CALL	BKSPI		; Backspace over CR
11$:	TST	LINBK		; Past end of line?
	BLT	15$		; No
	CMPNEB	LCH,#SPC,20$	; Last char in buffer not space?
15$:	CALL	BKOUT		; Back up over last space
20$:	MOV	SPCH,BF.SPC(R3) ; SPACING CHAR COUNT
	TSTNEB	$BFSTC,30$	; Keep buffer structure?
	MOV	(SP)+,F.1	; RESTORE
	MOV	(SP)+,LINBK
	MOV	(SP)+,SPCNSV
	MOV	(SP)+,SPCNT
	MOVB	(SP)+,LUNLSW
	MOVB	(SP)+,$UNLSW
	MOV	(SP)+,LSPCH
	MOV	(SP)+,SPCH
	MOVB	(SP)+,$TABPD
	MOV	(SP)+,LTAB
	MOV	(SP)+,LSTSP
	MOV	(SP)+,LCH
	MOV	(SP)+,BRCNT	; Restore break count
30$:	MOVB	#40,R0
	BICB	R0,$TABSW	; ENABLE TABS
	BICB	R0,$ESCSW	; ENABLE ESCAPE SEQ.
	BICB	R0,$EQFSW+1
	BICB	R0,$UNLSW	; ENABLE UNDERLINING
	BICB	R0,$OVRSW	; ENABLE OVERSTRIKING
	BICB	R0,$HYPSW	; Enable hyphenation
	BICB	R0,$AUBRK	; Enable autobreak
	CLRB	$BFSTC		; Clear the buffer counters
	RETURN			;
;
; START OF RUNOFF
;
START:	CALL	$START		; Set up to receive commands 
RUNOFF::MOV	SPSAV,SP	; Reset stack
	CALL	INITL		; INITIALIZE VARIABLES
	JMP	RESTRT		; Continue
	.END	START
