	.TITLE	START
	.IDENT	/BL4.1/
	.radix	8
;
;	This is the I/O setup for Bonner Lab Runoff
;		RSX-11M version
;
; AUTHOR: L. WADE 1-JUN-72
;
; MODIFIED BY:
;
;	E. POLLACK U. OF W. 19-DEC-73
;
;	D. N. CUTLER 27-JUL-75
;
; RUNOFF START UP INITIALIZATION
;
; MACRO LIBRARY CALLS
;
	.MCALL	CLOSE$,CSI$,CSI$1,CSI$2,EXIT$S,GCMLD$
	.MCALL	GCML$,GPRT$S,GTSK$S,OPEN$R,OPEN$W,PRINT$
	.MCALL	NBOF$L
	CSI$			;DEFINE CSI$ CONTROL BLOCK OFFSETS
	GCMLD$			; Define GCML$ offsets
	NBOF$L			; Define name block offsets
;
; LOCAL DATA
;
; CSI CONTROL BLOCK
;
	.vars
CSIBL2:	.BLKB	C.SIZE		; Block for .REQ input
	.even
I$LPG::	.BLKW	1
I$HLPG::	.BLKW	1
;
;	Switch error table
;
	.const
;
; TASK MEMORY LIMITS
;
LIMIT:	.LIMIT
SWERTB:	.word	39.,PRMRG,MINLN,255.
	.word	40.,PNLPG,MINPG,255.
	.word	41.,LPPG,0,255.
	.word	0
	.text
TOCHD:	.ASCII	/.TOC/
	.even
	.code
;
;	$START-START UP INITIALIZATION
;	This is executed only once
;
$START::MOV	SP,SPSAV			; SAVE INITIAL STACK POINTER
	GTSK$S	#TTBUF				; GET TASK PARAMETERS	
	MOV	TTBUF+G.TSTS,R4			; SIZE OF PARTITION IN BYTES
	GPRT$S	,#TTBUF				; STARTING VIRTUAL ADDRESS
	ADD	$DSW,R4				; ENDING VIRTUAL ADDRESS
	MOV	R4,XTOP				; INITIAL INDEX POINTER
	MOV	LIMIT+2,XBOT			; Xbot = top memory location
	CLR	LNKHD				; New linked list of buffers
	CALL	LNKSET				; Set up linked list of buffers
	OPEN$W	#TTBLK				; Open error output file
	RETURN					; done
;
;	Restart after errors or at end of processing
;
RESTRT::
;
;	Close all files
;
	CLRB	LUNSTK				; Set to LUN=0
	MOVB	LUNSTK+1,R4			; MAX NUMBER OF LUNS*2
15$:	CLOSE$	FDBTAB(R4)			; CLOSE INPUT FILE
	SUB	#2,R4				; NEXT ENTRY?	
	BGE	15$				; YES		
	CLOSE$	#LSTBLK				; Close output file
	CLOSE$	#TOCBLK				; Close TOC file
;
;	Initialize traceback buffer
;
	MOV	#TRCBUF+2,R0			; Initial traceback address
	MOV	R0,TRCBUF			; And save it
	CLR	(R0)+				; No line number
	CLR	(R0)				; No file name
;
;	Get a command
;
	BITNEB	#SW.DIS,$OUTSW,30$		; Second  Pass ?
	GCML$	#TTIBLK				; Get a command
	BCC	30$				; Command ?
	CMPNEB	#GE.EOF,G.ERR(R0),20$		; Not top level eof ?
	CLOSE$	#TTBLK				; Close error output
	CLOSE$	#TTIBLK				; Close command input
	EXIT$S					; EXIT **********
20$:	MOV	#15.,R0				; Command error message
	JMP	ILINP				; Process message
;
;	Start parsing command
;
30$:	MOV	#TTIBLK,R0			; Command input
	MOV	G.CMLD(R0),R4			; GET BYTE COUNT
	BLE	RESTRT
	MOV	G.CMLD+2(R0),R2			; Buffer with input line
	CALL	SAVIN
	MOV	G.CMLD(R0),R1			; GET BYTE COUNT
	CSI$1	#CSIBL1,TTIBLK+G.CMLD+2,R1	; CHECK SYNTAX
	BCS	20$
	BITEQB	#CS.EQU,C.STAT(R0),20$		; NO Equals sign?
;
;	Parse all input for switches
;
35$:	CLR	I$HLPG				; Clear hardware lines/page
	CLR	I$LPG				; Clear lines/page
	CSI$2	#CSIBL1,INPUT,#SWTBL		; Get input file spec
	BCS	37$				; Not Ok?
	BITNEB	#CS.WLD,C.STAT(R0),37$		; Wild?
	BITEQB	#CS.DVF!CS.NMF,C.STAT(R0),37$	; No input device or filename?
	BITNEB	#CS.MOR,C.STAT(R0),35$		; More files ?
	CSI$1	#CSIBL1,TTIBLK+G.CMLD+2,R1	; Start again
;
;	Parse for input file
;
	CSI$2	#CSIBL1,INPUT,#SWTBL
	BCC	50$
37$:	CALL	TRCGET				; Set up traceback
40$:	MOV	#18.,R0				; Input file error message
45$:	INC	@TRCBUF				; Set line number
	JMP	ILINP				; Process message
50$:	CALL	TRCGET				; Set up traceback
	BITNEB	#CS.WLD,C.STAT(R0),40$		; Wild files?
	BITEQB	#CS.DVF!CS.NMF,C.STAT(R0),40$	; No input device or filename?
	BITEQB	#CS.MOR,C.STAT(R0),55$		; No More files ?
	INCB	CSMOR				; Indicate more to come
;
;	Setup output default filename same as input filename
;
55$:	MOV	C.FILD+2(R0),R2			; Address of Filename
	MOV	C.FILD(R0),R4			; Number of char
	BEQ	57$				; None ?
	MOV	#TTBUF,R1			; Scratch buffer
	MOV	R1,R0				; Save buffer address
56$:	CMPEQB	(R2),#'.,57$			; End of name ?
	MOVB	(R2)+,(R1)+			; Move name to scratch buffer
	SOB	R4,56$				; Till done
57$:	MOV	#10.,R4				; Pad with blanks
58$:	MOVB	#' ,(R1)+			; Chock it with space
	SOB	R4,58$
	MOV	#DOCFIL+N.FNAM,R3		; Output address
	MOV	#TOCFIL+N.FNAM,R5		; Output address
	MOV	#3,R4				; Number of RAD50 words
59$:	CALL	$CAT5B				; Convert to RAD50
	MOV	R1,(R3)+			; Save RAD50 word in DOC
	MOV	R1,(R5)+			; Save RAD50 word in TOC
	SOB	R4,59$				; Loop back 3 x
	OPEN$R	#LUN4,,#CSIBL1+C.DSDS
	BCC	60$
	MOV	#19.,R0				; Input file open error
	br	45$				; Process message
;
;	Setup pass params
;
60$:	BITEQ	#PASSW,$SWTCH,65$		; Single pass only ?
	MOVB	$OUTSW,R2			; Current output switch
	COM	R2				; Reverse switch
	BIC	#^C<SW.DIS>,R2			; Clear extra bits
	MOVB	R2,$OUTSW			; New switch
	BEQ	65$				; output ?
	JMP	100$
;
;	First output file
;
65$:	CLRB	$OUTSW				; Enable output
	CSI$2	#CSIBL1,OUTPUT,#SWTBL		; Get output file spec
	BCC	80$				; Ok?
70$:	MOV	#16.,R0				; Output file error
	JMP	ILINP				; Process message
80$:	BITNEB	#CS.WLD,C.STAT(R0),70$		; Wild?
	CLRB	LSTBLK+F.RATT			; No file attributes
	BITNEB	#CRSW,$SWTCH,81$		; Imbedded carriage control?
	MOVB	#FD.CR,LSTBLK+F.RATT		; File mode is "CR"
	MOVB	#-1,$HSPSW			; Disable half spacing
81$:	OPEN$W	#LSTBLK,,#CSIBL1+C.DSDS		; Open output file
	BCC	90$				; No error?
85$:	MOV	#17.,R0				; Output file open error
	JMP	ILINP				; Process message
;
;	Second output file
;
90$:	BITEQB	#CS.MOR,CSIBL1+C.STAT,100$	; No more files ?
	CSI$2	#CSIBL1,OUTPUT,#SWTBL		; Get output file spec
	BCS	70$				; Bad spec
	BITNEB	#CS.MOR!CS.WLD,C.STAT(R0),70$	; Wild or more files ?
	OPEN$W	#TOCBLK,,#CSIBL1+C.DSDS		; Open output file
	BCS	85$				; Bad output file
	CLRB	$TOCSW				; Set TOC switch
	MOV	#TOCHD,R1			; TOC header
	MOV	#4,R2				; Number of char
	CALL	OUTTOC				; Into TOC file
;
;	Check switches
;
100$:	MOV	PRMRG,	RMARG			; SET RIGHT MARGIN
	MOV	I$LPG,R0
	ASL	R0				; Lines per/active page in hl.
	BLE	105$				; None ?
	MOV	R0,PNLPG			; Permanent length
	MOV	R0,NLPG				; Current page length
105$:	MOV	I$HLPG,R0			; Harware length input ?
	ASL	R0
	BLE	106$				; None ?
	MOV	R0,LPPG				; Lines per/page in half lines
106$:	MOVB	#'_,$ULCH			; Underline char as underscore
	MOVB	ULSWT,R0			; Get underline char
	BEQ	130$				; No underline switch
	CMPNEB	#'L,R0,110$			; NOT Line mode ?
	COMB	$ULMSW				; SET Line mode
	BR	130$
110$:	CMPNEB	#'S,R0,120$			; NOT SIMULATE MODE?
	INCB	$ULMSW				; SET SIMULATE SWITCH
	MOVB	#'-,$ULCH			; Set underline char to hyphen
	BR	130$
120$:	CMPNEB	#'N,R0,125$			; Not No mode ?
	COMB	$UNLSW				; SET NO UNDERLINE SWITCH
	BR	130$
125$:	CMPEQB	#'B,R0,130$			; Backspace mode ?
	MOV	#38.,R0				; Bad switch
	JMP	ILINP				; Tell user
130$:	MOV	#SWERTB,R1			; Get switch error table
134$:	MOV	(R1)+,R0			; Get error number
	BEQ	136$				; Done ?
	MOV	(R1)+,R2
	CMP	(R2),(R1)+			; Check switch
	BLT	135$				; Less than low limit ?
	CMP	(R2),(R1)+			; Check switch
	BLE	134$				; Less tha or equal to hi ?
135$:	JMP	ILINP				; No !
136$:	CLR	R1				; SET TO CLEAR CASE SHIFT
	BITEQ	#UPCSW,$SWTCH,140$		; NO UPPER CASE REQUIRED?
	MOV	#401,R1				; REQUIRED UPPER	
140$:	MOV	R1,CASE				; SET CASE		
	BITNE	#HYPSW,$SWTCH,150$		; HYPHENATION SWITCH?
	MOVB	#-1,$HYPSW			; SET IT PERMENANTLY OFF
150$:	CLR	TTBLK+F.NRBD			; CLEAR OUTPUT BUFFER
	MOV	HFOUT,HFOUT+4			; Set char counter in out buff
	MOV	#OUBUF,HFOUT+2			; And address
	MOV	BUFADD,R3			; Get input buffer
	CALL	CLRBF				; Get first line
	JMP	LGO				; AND INTO MAIN LOOP
;
;	End of input file routine
;
ENDFIL::TSTEQB	CSMOR,50$			; No more input ?
	CLOSE$	#LUN4
	MOV	#CSIBL1,R0			; Get input block
	CALL	SAVCML				; And save string in line
	CSI$2	#CSIBL1,INPUT,#SWTBL		; Parse next input file
	BCS	20$				; Bad input file ??
	CALL	TRCGET				; Set up traceback
	BITNEB	#CS.WLD,C.STAT(R0),25$		; Wild files?
	BITNEB	#CS.DVF!CS.NMF,C.STAT(R0),30$	; No input device or filename?
20$:	CALL	TRCGET				; Set up traceback
25$:	MOV	#18.,R0				; Input file error message
26$:	INC	@TRCBUF				; Set line number
	JMP	ILINP				; Process message
30$:	BITNEB	#CS.MOR,CSIBL1+C.STAT,45$	; more files?
	CLRB	CSMOR				; Set no more files
45$:	OPEN$R	#LUN4,,#CSIBL1+C.DSDS
	BCC	40$
	MOV	#19.,R0				; Input file open error
	BR	26$				; Process message
40$:	CLRB	EOFSW				; Set no end of file
	MOV	BUFADD,R3			; Get input buffer
	CALL	CLRBF				; Get first line
	JMP	LGO				; More input

50$:	.IF	NDF	RSTS			; not RSTS code
	BITEQ	#SPLSW,$SWTCH,60$		; DON'T SPOOL TEXT FILE?
	BITNEB	#SW.DIS,$OUTSW,60$		; first Pass ?
	PRINT$	#LSTBLK,,,,,,,,#1		; SUBMIT FILE TO PRINT SYMBIONT
	.ENDC

60$:	JMP	RUNOFF				; START AT TOP AGAIN

SAVCML:	MOV	C.CMLD(R0),R4			; Size
	MOV	C.CMLD+2(R0),R2			; Command line address
SAVIN:	TSTEQ	R4,40$				; No command line ?
	MOV	R0,-(SP)
	MOV	BUFADD,R3			; Get input buffer
	CALL	CLRBF
30$:	MOVB	(R2)+,R1			; Save line
	CALL	PBYT
	SOB	R4,30$				; Till done
	MOV	#CR,R1
	CALL	PBYT
	MOV	#LF,R1
	CALL	PBYT
	CALL	BEGBF
	MOV	(SP)+,R0
40$:	RETURN
;
;	THIS IS INCLUDED HERE SINCE IT USES CSI$
;
;	REQUIRE command
;
REQUR::	MOVB	LUNSTK,R0	; GET POINTER	
	CMPB	R0,LUNSTK+1	; AT END OF STACK?
	BHIS	50$		; YES		
	MOV	FDBTAB+2(R0),R0	; GET FDB BLOCK	
	CLOSE$	R0		; Close previous file
	CALL	GETFIL		; Get input file
	MOVB	LUNSTK,R0	; GET POINTER	
	MOV	FDBTAB+2(R0),R0	; GET FDB BLOCK	
	OPEN$R	R0,,#CSIBL2+C.DSDS	; OPEN FILE
	BCS	BADOP		; NOT OPEN	
10$:	MOVB	LUNSTK,R0	; GET STACCK	
	ADD	#2,R0		; NEXT ENTRY	
	MOVB	R0,LUNSTK	; SAVE CURRENT STACK
	MOV	BUFADD,R3	; Current buffer address
	CALL	CLRBF		; CLEAR THE BUFFER
	MOV	#CR,R1		; GET CARRIAGE RET TO SIGNAL END OF LINE
	CALL	PBYT		; INTO BUFFER
	MOV	#LF,R1		; PUT LF INTO BUFFER AS END LINE
	CALL	PBYT		; INTO BUFFER
	CALL	BEGBF		; SET TO TOP OF BUFFER
	ADD	#TRCLN,TRCBUF	; Next traceback buffer
	MOV	#CSIBL2,R0
	CALL	TRCGET		; Set up traceback
	RETURN
50$:	CALL	GETLIT		; Skip the literal
	MOV	#20.,R0		; Too many nested .REQ
	JMP	ILCMA
BADOP:	MOVB	F.ERR(R0),R1	; GET ERROR	
	CLOSE$	R0		; CLOSE BAD FILE
	MOV	#18.,R0		; Open failure
	JMP	ILCMA
;
;	REQUIRE BINARY
;
REQBIN::CALL	(R4)		; Get number
	CALL	CVSP		; Get half line count
	MOV	R3,-(SP)	; Save it for later
	MOV	R3,R5		; Vertical spacing
	CLR	R4
	CALL	PARTS		; Check if space available
	SUB	(SP),LINEC1	; Subtract from spacing
	SUB	(SP),LINEC2	; ""
	SUB	(SP)+,LINEC3	; ""
	CALL	REQUR		; Get input file
	MOVB	LUNSTK,-(SP)	; Save current lun
10$:	CALL	FIN		; Get input line
	CMPNEB	LUNSTK,(SP),50$	; No longer in required file ?
	MOV	BUFADD,R3	; Buffer address
	SUB	#2,BF.MAX(R3)	; Skip CR/LF
	SUB	#2,BF.CNT(R3)	; Skip CR/LF
20$:	CALL	GBYT		; Get single byte of input
	BCS	30$		; No more this buffer
	CALL	FOUT		; Output it
	BR	20$		; And more ...
30$:	CALL	OUTPUT		; End the line
	BR	10$
50$:	TST	(SP)+		; Pop stack
	RETURN
;
;	Subroutine to set up input file
;
GETFIL:	CALL	GETLIT		; GET LITERAL ADDRESS
	BCS	30$		; NONE TO GET	
	MOV	R0,R2		; Address of literal
	CSI$1	#CSIBL2,R2,R1	; INIT CSI BLOCK TO PARSE INPUT
	BCS	40$		; BAD INPUT
	CSI$2	#CSIBL2,OUTPUT	; GET FILE SPEC	
	BCS	40$		; BAD FILE	
	BITNEB	#CS.MOR!CS.WLD!CS.EQU,C.STAT(R0),40$	; More,wild, or =?
	BITEQB	#CS.DVF!CS.NMF,C.STAT(R0),40$	; No input device or filename?
	RETURN
30$:	JMP	ILCM		; ILLEGAL COMMAND
40$:	MOV	#18.,R0		; Illegal file spec
	JMP	ILCMA
;
;	Subroutine to set up traceback info
;	R0 contains Device info
;	All registers are destroyed
;
TRCGET:	MOV	TRCBUF,R3			; Buffer to save in
	CLR	(R3)+				; Set line count
	MOV	#TRCLN-2,R4			; Maximum number of bytes
	BITEQB	#CS.DVF,C.STAT(R0),10$		; Dev ?
	MOV	C.DEVD+2(R0),R1			; File name
	MOV	C.DEVD(R0),R2			; Byte count
	CALL	50$				; Put into buffer
	DEC	R4
	BLE	60$
	MOVB	#':,(R3)+			; Put in :
10$:	BITEQB	#CS.DIF,C.STAT(R0),20$		; Dir ?
	MOV	C.DIRD+2(R0),R1			; File name
	MOV	C.DIRD(R0),R2			; Byte count
	CALL	50$				; Put into buffer
20$:	BITEQB	#CS.NMF,C.STAT(R0),60$		; File ?
	MOV	C.FILD+2(R0),R1			; File name
	MOV	C.FILD(R0),R2			; Byte count
50$:	BLE	60$				; Count = 0
	DEC	R4
	BLE	60$
	MOVB	(R1)+,(R3)+			; Save 1 byte
	SOB	R2,50$
60$:	CLRB	(R3)				; Terminal byte
	RETURN
	.END
