Google
 

Trailing-Edge - PDP-10 Archives - AP-D483B-SB_1978 - lptspl.mac
Click lptspl.mac to see without markup as text/plain
There are 30 other files named lptspl.mac in the archive. Click here to see a list.
TITLE	LPTSPL  --  Disk to Line-printer Spooler  -  version 102
SUBTTL	D.A. Lewine - L.S. Samberg/LSS	29 Mar 77


;Copyright (C)  1970,71,72,73,74,75,76,77,
;	 Digital Equipment Corp., Maynard, MA.

;ASSEMBLY AND LOADING INSTRUCTIONS
;
;	.COMP LPTSPL
;	.LOAD /REL LPTSPL
;	.SSAVE LPTSPL


	SEARCH	QSRMAC			;SEARCH GALAXY PARAMETERS
	PROLOGUE(LPTSPL)
IFN FTJSYS,<
	SEARCH	RMSSYM
>  ;END IFN FTJSYS

	.REQUIRE	SBSCOM		;SUBSYSTEM COMMON MODULE
	.REQUIRE	CSPQSR		;QUASAR INTERFACE MODULE
	.REQUIRE	CSPMEM		;MEMORY MANAGER

IF1,<
IFN FTJSYS,<PRINTX ASSEMBLING GALAXY-20 LPTSPL>
IFN FTUUOS,<PRINTX ASSEMBLING GALAXY-10 LPTSPL>
>  ;END IF1
	SALL				;SUPPRESS MACRO EXPANSIONS

;VERSION INFORMATION
	LPTVER==102			;MAJOR VERSION NUMBER
	LPTMIN==0			;MINOR VERSION NUMBER
	LPTEDT==2263			;EDIT LEVEL
	LPTWHO==0			;WHO LAST PATCHED

	%LPT==<BYTE (3)LPTWHO(9)LPTVER(6)LPTMIN(18)LPTEDT>

;STORE VERSION NUMBER IN JOBVER
	LOC	137
.JBVER::EXP	%LPT

	TWOSEG				;TWO SEGMENT PROGRAM
	RELOC	400000			;START IN HISEG
	SEG==-1				;AND FLAG US IN HISEG
SUBTTL	Revision History

;2000	First field-test release of GALAXY-10, June,1975.

;2050	Make this version 101, Sept, 1975
;2056	On HELP command, just go thru and give a list
;	of valid commands.
;2060	In initialization, read LPFORM.INI into core, and
;	simply rescan the buffer on a forms change.
;2074	Insert the MONITOR Command as an emergency exit.
;2077	Add new LPFORM switches /ALCNT, /ALSLP.
;2111	Release version 101 on TOPS20, Feb, 1976

;2115
;		START GALAXY 1B DEVELOPMENT
;		MAKE THIS LPTSPL 101A
;	Start converting output device handling to run under
;	TOPS20 without compatibility.
;2122	Start putting in internal LOG code.
;2123	Finish up 2122 and add a new switch to LPFORM, /VFU
;	which is equivalent to /TAPE.
;2124	Change SUPPRESS command to accept keyword argument
;	instead of a switch.
;2125	Add new CSPQSR protocol and new interrupt code.
;2126	Add modifications to allow for new SBSMAC module.
;2133	Remove REQUEUE/C since it is the default.
;2141	Add a mechanism to flush all pending (already buffered)
;	output on KILL.
;2142	Remove station locator option in LPFORM.INI.
;2145	Start putting in support for DAVFUs.
;	 (Direct Access Vertical Forms Unit)
;2147	Rearrange some code so that LPT is always kept open.
;2151	Put in more graceful error recovery for the LP20.
;2154	Invent OUTWON to wait for device to come on-line.
;2156	On TOPS20 allow command processor to run
;	right after interrupt happens.
;2157	Have OPINFL, ACCCHK return TRUE or FALSE
;	rather than diddling DSKOPN.
;2200	Make this version 102, May 1976.
;2201	Fix up control-C handling.
;2202	Ignore line-sequence-numbers in LPFORM.INI.
;2203	Random fixes and cleanup.
;2204	Drive the LPT using non-blocking I/O on -10.
;2205	Change FORMS command to simply tell QUASAR and nothing else.
;2206	More of 2203.
;2207	On TOPS10 build output buffer ring myself.
;	Generate 4 200 word buffers (175+3).
;2210	Start moving operating system dependent code from the START command
;	processor to the OUTGET routine.  Symbolize buffer
;	size parameters for both systems.  Start phasing out the LOCAL
;	macro since it precludes multi-programming LPTSPL.
;2211	Files printed with /HEAD:0 get a blank page
;	between copies because FFSEEN was getting turned off at
;	end-of-file.
;2212	Make KILL work correctly when banners or headers
;	are printing.
;2213	Move more operating system dependent code from START
;	to OUTGET.
;2214	Random code cleanup.
;2215	On -20 dont print LPTDOL  if not busy.
;	On -10 make output buffer 400 words (375+3).
;2216	Rearrange START routine to call OUTGET
;	at the end.  Start putting in hooks for multiple internal
;	log pages.
;2217	Rework log file buffering code again.
;2220	Random code cleanup and bug fixes.
;2221	More of 2220.
;2222	COBOL sixbit files didn't print correctly.
;2223	Remove the MSGLVL command and add the new MESSAGE
;	command.
;2224	More of 2223.
;2225	Make some commands run more reasonably when device is
;	off-line.
;2226	Fix some forms changing problems.
;2227	Start updating LPTSPL to understand the "new" version
;	2 database and -20 structures etc.
;2230	More of 2227.
;2231	Remove all references to P4 and PURGE it.
;2232	Make VFU loading somewhat cleaner and smarter.
;2233	More of 2233 and random cleanup.
;2234	Rework BANNER and TRAILER code.
;2235	Start putting in RMS-20 support.  Make octal number
;	printer produce unsigned numbers.  Recover from
;	front-end reloads on -20.  On -10 turn JACCT off unless
;	I am a remote operator.
;2236	Fix printing of wrong request and file creation time on
;	file header page on -20  [SPR 20-].  New banner page format
;	caused the ruler to print on first data page.
;2237	Clean-up handling of STOP and PAUSE, and put in more RMS support.
;2240	Fix race condition in -20 terminal handler [SPR 20-10042].
;	Finish implementing support for RMS-20 files.
;2241	Take a checkpoint whenever a backspace or forward reaches its
;	destination.  On -10, use normal size buffers for remote printer.
;	Allow Open of LPT on -20 even if off-line.  Fix some RMS
;	releated bugs.
;2242	Fix a number of minor bugs.  Re-read LPFORM.INI on FORMS command.
;2243	Cleanup a number of problems with RMS and other things.
;2244	Add code to load DAVFU.
;2245	Some more RMS fixes.
;2246	Enable for online interrupts on the -10.  Ignore a
;	Request for Checkpoint if lineprinter is off-line.
;2247	Fix a number of minor bugs.
;2250	Use new RMS symbols.

;;First Field-Test Release of GALAXY release 2, Jan. 1977

;2251	The guarenteed log file limit was no being granted due to
;	a bad compare.  A FORMS command given before a START command
;	caused some very strange results (QAR#2).  Setup the LUUO
;	handler before calling OPNFRM (QAR#1).
;2252	Start inserting code for loading DAVFU on -10.
;2253	Fix time printer on -10 to be more accurate (esp.
;	around midnite).  Fix some problems with forms changes.
;2254	Allow 2 (assembly parameter LPTERR) hard lineprinter errors
;	per copy of a file before giving up and resetting.
;2255	More code to load DAVFU on the -10.
;2256	Fix some bugs in 2255 and do some code cleanup.
;2257	Fix the command scanner to see commands which begin with
;	lower-case alphabetics (QAR #5).  If output device is a
;	magtape, write a tape-mark at EOJ.
;2260	Log files which were to be deleted but not printed
;	weren't deleted. If NORMAL/TAPE is found in LPFORM,
;	make that tape the default.  More code for DAVFU on -10.
;2261	Fix a number of minor problems (inc. qar #18).
;2262	More of the same (qar #22 and #23).
;2263	Fix a few minor bugs.
SUBTTL	AC and I/O Channel Definitions

;ACCUMULATOR DEFINITIONS
	S=0		;STATUS FLAGS
	AP=13		;USED TO INTERFACE WITH QSRMEM (AND AS A TEMP)
	E=14		;POINTS TO CURRENT FILE
	N=15		;HOLDS A NUMBER - ALMOST NEVER PRESERVED
	C=16		;HOLDS A CHARACTER - ALMOST NEVER PRESERVED
	J=P4		;JOB PARAMETER BLOCK POINTER

	PURGE	P4	;NOW GET RID OF P4 FOREVER

;INPUT-OUTPUT CHANNELS
	DSK==1		;SPOOLED DATA ON DSK
	LOGF==2		;LOG FILE ON DISK
	LPT==3		;LINEPRINTER
	ALP==5		;FOR ALIGN COMMAND
	VFC==6		;FOR READING DAVFU FILE
	FRM==7		;READ LPFORM.INI
SUBTTL	Parameters

;PARAMETERS WHICH MAY BE CHANGED AT ASSEMBLY TIME
	ND	PDSIZE,200	;SIZE OF PUSHDOWN LIST
	ND	SLTIME,^D5000	;MS TO WAIT ON ?DEVICE OK
	ND	MAXERR,5	;NUMBER OF DISK I/O ERRS BEFORE PUNTING
	ND	LPTERR,2	;NUMBER OF LPT I/O ERRS BEFORE QUITTING
	ND	FTDPM,0		;OUTPUT TO LPT IN "LINE" MODE.
				;THIS ALLOWS LPT TO BE TURNED OFF AND
				;ON WITHOUT DATA LOSS, AT SOME COST IN
				;CPU TIME.
	ND	LOGPAG,12	;PAGE LIMIT FOR LOG IF OVER QUOTA
	ND	ACCTSW,-1	;-1 TO INCLUDE ACCOUNTING
	ND	TABSIZ,^D50	;SIZE OF BACKSPACE TABLE
	ND	AUTTIM,^D20	;AUTO-TIMEOUT IN MINUTES
	ND	MAXLIM,^D10000	;DEFAULT VALUE OF MLIMIT

IFN FTJSYS,<
	ACCTSW==0		;NO ACCOUNTING YET ON -20
>  ;END IFN FTJSYS



;CONSTANT PARAMETERS
	XP	FCTHDR,<251000,,13>	;FACT ENTRY CODE AND LENGTH
	XP	.EQNOT,.EQLM2+1		;NOTE FIELD IN EXTERNAL REQUEST

;CHECKPOINT BLOCK OFFSETS
	XP	CKFIL,0			;NUMBER OF FILES PRINTED
	XP	CKCOP,1			;NUMBER OF COPIES OF LAST FILE
	XP	CKPAG,2			;NUMBER OF PAGES OF LAST COPY
	XP	CKTPP,3			;TOTAL PAGES PRINTED
	XP	CKFLG,4			;FLAGS
		XP CKFREQ,1B0		;JOB WAS REQUEUED BY OPR
		XP CKFCHK,1B1		;JOB WAS CHECKPOINTED


	SYSPRM	BUFNUM,2,1		;NUMBER OF BUFFERS
	SYSPRM	BUFSPC,1000,1000	;SPACE ALLOCATED FOR BUFFERS
	SYSPRM	BUFSIZ,<1000/BUFNUM>,<1000/BUFNUM>
					;SIZE OF EACH BUFFER
	SYSPRM	BUFCHR,<BUFSIZ-3>*5,<BUFSIZ*5>
					;NUMBER OF CHARS PER BUFFER
	BUFSPC==BUFNUM*BUFSIZ
	SYSPRM	DEFLPT,<SIXBIT/LPT/>,<SIXBIT/PLPT0/>  ;DEFAULT LPT NAME
SUBTTL	MACROS

IFN FTJSYS,<

;MACROS TO MANIPULATE FIELDS IN THE FAB AND RAB FOR RMS-20 FILES

DEFINE $STFAB(AC,FLD),<
	IFNDEF .OF'FLD,<PRINTX FAB FIELD FLD IS UNDEFINED>
	IFDEF  .OF'FLD,<
	..MASK=MASK.(.SZ'FLD,.PS'FLD)
	STORE	AC,J$DFAB+.OF'FLD'(J),..MASK
	>
>  ;END DEFINE $STFAB

DEFINE $LDFAB(AC,FLD),<
	IFNDEF .OF'FLD,<PRINTX FAB FIELD FLD IS UNDEFINED>
	IFDEF  .OF'FLD,<
	..MASK=MASK.(.SZ'FLD,.PS'FLD)
	LOAD	AC,J$DFAB+.OF'FLD'(J),..MASK
	>
>  ;END DEFINE $LDFAB

DEFINE $STRAB(AC,FLD),<
	IFNDEF .OF'FLD,<PRINTX RAB FIELD FLD IS UNDEFINED>
	IFDEF  .OF'FLD,<
	..MASK=MASK.(.SZ'FLD,.PS'FLD)
	STORE	AC,J$DRAB+.OF'FLD'(J),..MASK
	>
>  ;END DEFINE $STRAB

DEFINE $LDRAB(AC,FLD),<
	IFNDEF .OF'FLD,<PRINTX RAB FIELD FLD IS UNDEFINED>
	IFDEF  .OF'FLD,<
	..MASK=MASK.(.SZ'FLD,.PS'FLD)
	LOAD	AC,J$DRAB+.OF'FLD'(J),..MASK
	>
>  ;END DEFINE $LDRAB

	PURGE	$STORE,$LOAD		;PURGE CONFUSING RMS MACROS
>  ;END OF IFN FTJSYS

;FREQUENTLY USED INSTRUCTIONS SEQUENCES

DEFINE	ACTCHR	(CH,A)<
	CAIN	C,"CH"			;;IS THIS A CH
	XLIST
	JRST	A			;YES
	LIST
	SALL
	>




;RELOC TO HISEG

DEFINE	TOPSEG,<
	IFE	SEG,<
	XLIST
	LIT
	SEG==-1
	RELOC>
	LIST
	SALL>

;RELOC TO LOWSEG

DEFINE	LOWSEG,<
	IFN	SEG,<
	XLIST
	LIT
	LIST
	SALL
	RELOC>
	SEG==0>


;MACRO TO ASSIGN BITS WITHIN A WORD (NOTE: BIT 0 = 400000 000000)

DEFINE	BIT(AC,SYMBOL)<
	IF1,<			;;DO NOT REDEFINE IN PASS2
	IFDEF AC'..<		;;SET UP COUNTER
	AC'..==AC'.._<-1>	;;AND MOVE TO NEXT BIT
	>
	IFNDEF AC'..<		;;ON FIRST CALL
	AC'..==1B0>		;;GIVE AWAY FIRST BIT
	SYMBOL==AC'..		;;DEFINITION OF SYMBOL
	IFE	AC'..,<		;;NO MORE ROOM
	PRINTX	? AC IS FULL
>>>
;BIT TESTING MACROS
DEFINE ON(AC,FLAG),<TXO AC,FLAG>

DEFINE OFF(AC,FLAG),<TXZ AC,FLAG> ;TURN OFF A FLAG



DEFINE LP(SYM,VAL),<
	IF1,<
		XLIST
		IFNDEF J...X,<J...X==1000>
		IFDEF SYM,<PRINTX  ?PARAM SYM USED TWICE>
		SYM==J...X
		J...X==J...X+VAL
	IFL 2000-J...X,<PRINTX ?PARAMETER AREA LONGER THAN A PAGE>
		LIST
		SALL
	>  ;END IF 1
>  ;END DEFINE LP
SUBTTL	Special Forms Handling Parameters



	LOWSEG		;DOWN TO LOWSEG


;FORMS SWITCHES:
;	BANNER:NN	NUMBER OF JOB HEADERS
;	TRAILER:NN	NUMBER OF JOB TRAILERS
;	HEADER:NN	NUMBER OF FILE HEADERS (PICTURE PAGES)
;	LINES:NN	NUMBER OF LINES PER PAGE
;	WIDTH:NN	NUMBER OF CHARACTERS PER LINE
;	ALIGN:SS	NAME OF ALIGN FILE
;	ALCNT:NN	NUMBER OF TIMES TO PRINT ALIGN FILE
;	ALSLP:NN	NUMBER OF SECS TO SLEEP BETWEEN COPIES OF ALIGN
;	RIBBON:SS	RIBBON TYPE
;	TAPE:SS		VFU CONTROL TAPE
;	VFU:SS		(SAME AS /TAPE)
;	DRUM:SS		DRUM TYPE
;	CHAIN:SS	CHAIN TYPE (DRUM/CHAIN ARE THE SAME)
;	NOTE:AA		TYPE NOTE TO THE OPERATOR
;	PAUSE		PAUSE BETWEEN JOBS ON THIS TYPE OF FORM
;	WHAT		PRINT A SHORT "WHAT" TO OPERATOR ON EACH JOB


;IN THE ABOVE AND BELOW EXPLANATIONS:
;	NN	IS A DECIMAL NUMBER
;	SS	IS A 1-6 CHARACTER STRING
;	AA	IS A STRING OF 1 TO 50 CHARACTERS
;	OO	IS AN OCTAL NUMBER



;LOCATION SPECIFIERS
;	ALL		ALL LINEPRINTERS
;	CENTRAL		ALL LINEPRINTERS AT THE CENTRAL SITE
;	REMOTE		ALL REMOTE LINEPRINTERS
;	LPTOOO		LINEPRINTER OOO ONLY

;NOTE:  LPTSPL WILL USE THE FIRST ENTRY WHICH MEETS THE LOCATION
;	SPECIFICATION FOR ITS LINEPRINTER.
DEFINE F,<
	FF	BANNER,2
	FF	TRAILER,2
	FF	HEADER,2
	FF	LINES,^D60
	FF	WIDTH,^D132
	FF	ALIGN,0
	FF	ALCNT,25
	FF	ALSLP,5
	FF	RIBBON,FRMNOR
	FF	TAPE,FRMNOR
	FF	VFU,FRMNOR
	FF	DRUM,FRMNOR
	FF	CHAIN,FRMNOR
	FF	NOTE,0
	FF	PAUSE,0
	FF	WHAT,0
>


;GENERATE TABLE OF SWITCH NAMES
DEFINE FF(A,B),<
	XLIST
	<<SIXBIT /A/>&777777B17>+S$'A
	LIST
	SALL
>

FFNAMS:	F

;GENERATE TABLE OF DEFAULT PARAMTERS
DEFINE FF(X,Y),<
	XLIST
D$'X:	EXP	Y
	LIST
	SALL
>

FFDEFS:	F
	F$NSW==.-FFDEFS
	PURGE	D$VFU,D$CHAI

	F$CL1==^D60	;WIDTH CLASS ONE IS 1 TO F$CL1
	F$CL2==^D100	;WIDTH CLASS TWO IS F$CL1 TO F$CL2
SUBTTL	Flag Definitions
IF1	<

	BIT	S,RUNB,		;ON IF I/O IN PROGRESS TO OUTDEV
	BIT	S,TELOPR,	;PRINT ON OPERATORS TTY (SET BY TELL)
	BIT	S,TELLOG,	;PLACE IN LOG (SET BY TELL)
	BIT	S,XTRA,		;XTRA BIT
	BIT	S,TELUSR,	;SENT DIRECTLY TO OUDEV(SET BY TELL)
;******* DO NOT MOVE BITS DEFINED ABOVE THIS LINE *******
	BIT	S,PAUSEB,	;(5) PAUSE AT EOJ
	BIT	S,TNOACT,	;(6) NO ACTION CHARACTERS
	BIT	S,STARTD,	;(7) START COMMAND GIVEN
	BIT	S,ARROW,	;(8) ARROW MODE IN EFFECT
	BIT	S,SUPRES,	;(9) NO USER FORM CONTROL
	BIT	S,DSKOPN,	;(10) DISK DATA READ GOING ON
	BIT	S,RQB,		;(11) JOB HAS BEEN REQUED
	BIT	S,SUPJOB,	;(12) SUPPRESS /JOB
	BIT	S,NOTYPE,	;(13) CNTRL O THE OUTPUT DEVICE
	BIT	S,XXX,		;(14)
	BIT	S,XXX,		;(15)
	BIT	S,PLOCK,	;(16) DO NOT CLEAR THE PAUSE BIT
	BIT	S,FFSEEN,	;(17) FORM FEED SEEN (LPTOUT)
	BIT	S,FROZE,	;(18) DON'T ASK TO CHANGE FORMS TYPE
	BIT	S,ABORT,	;(19) THE SHIP IS SINKING
	BIT	S,FCONV,	;(20) THE NEXT CHAR IS FORTRAN FORMAT DATA
	BIT	S,NEWLIN,	;(21) FLAG FOR THE BEGINING OF LINE
	BIT	S,MNTBIT,	;(22) REQUEST FOR FORMS TO BE MOUNTED
	BIT	S,JOBLOG,	;(23) THIS JOB HAS A LOG FILE
	BIT	S,BUSY,		;(24) JOB IN PROGRESS
	BIT	S,LOGOPN,	;(25) LOG FILE IS OPEN
	BIT	S,TTYBRK,	;(26) BREAK WAS SEEN ON TTY
	BIT	S,XXX,		;(27)
	BIT	S,BANDUN,	;(28) WE WENT THRU THE BANNER SEQUENCE

;STILL IN IF1
SUBTTL	LUUO	Definitions

	OPDEF	TELL	[001000,,0]
	OPDEF	TELLN	[002000,,0]
	OPDEF	STAMP	[004000,,0]

;AC FIELD OF TELL UUO

OPR==10				;SEND TO OPERATOR
LOG==4				;SEND TO LOG
USR==1				;ALSO PUT ON USER DEVICE

;BIT POSITION (FOR BYTE POINTERS)

SFRLOC==4			;LOCATION OF TELL BITS IN S
SFSBIT==4			;NUMBER OF TELL BITS
UURLOC==14			;LOCATION OF AC IN UUO
UUSBIT==4			;NUMBER OF BITS IN AC FIELD


	ASUPPRESS

>	;END OF IF1 CONDITIONAL


;LUUO BYTE POINTERS
PAC:	POINT	UUSBIT,.JBUUO##,UURLOC	;POINTER TO AC IN LUUO
PS:	POINT	SFSBIT,S,SFRLOC		;SAME FIELD IN S
SUBTTL	Job Parameter Area

	LP	J$$BEG,0		;BEGINNING OF PARAMETER AREA

;REQUEST PARAMETERS
	LP	J$RFLN,1		;NUMBER OF FILES IN REQUEST
	LP	J$RFLP,1		;NUMBER OF FILES TO BE PRINTED
	LP	J$RLIM,1		;JOB LIMIT IN PAGES
	LP	J$RLFS,1		;ADR OF LOG FILE SPEC
	LP	J$RNFP,1		;NUMBER OF FILES PRINTED
	LP	J$RNCP,1		;NUMBER OF COPIES OF CURRENT FILE
	LP	J$RNPP,1		;NUMBER OF PAGES IN CURRENT COPY PRINTED
	LP	J$RACS,20		;CONTEXT ACS
	LP	J$RPDL,50		;CONTEXT PUSHDOWN LIST

;ALIGN FILE PARAMETERS
	LP	J$ABRH,1		;BUFFER RING HEADER
	LP	J$ABPT,1		;BYTE POINTER
	LP	J$ABCT,1		;BYTE COUNT
	LP	J$APAG,1		;ALIGN SCRATCH PAGE NUMBER

;LPT PARAMETERS
	LP	J$LBUF,1		;ADDRESS OF LPT BUFFER
	LP	J$LBRH,1		;BUFFER RING HEADER
	LP	J$LBPT,1		;BYTE POINTER
	LP	J$LBCT,1		;BYTE COUNT
	LP	J$LDEV,1		;ACTUAL OUTPUT DEVICE NAME
	LP	J$LGNM,1		;DEV NAME SPEC ON START CMD
	LP	J$LSDV,1		;SCHEDULING DEVICE
	LP	J$LERR,1		;LPT ERROR DOWNCOUNTER
	LP	J$LLCL,1		;-1 IF UPPER/LOWER CASE PRINTER
	LP	J$LHNG,1		;-1 IF OUTPUT DEVICE IS HUNG
	LP	J$LDVF,1		;-1 IF DAVFU ON PRINTER
	LP	J$LPCR,1		;-1 IF DEVICE HAS A PAGE CNTR
	LP	J$LREM,1		;-1 IF REMOTE PRINTER
	LP	J$LIOA,1		;-1 IF WE ARE IN A SOUT OR OUT

IFN FTJSYS,<
	LP	J$LJFN,1		;JFN FOR THE LPT
	LP	J$LSTG,2		;DEVICE NAME STRING
	LP	J$LIBC,1		;INITIAL BYTE COUNT
	LP	J$LIBP,1		;INITIAL BYTE POINTER
>  ;END IFN FTJSYS




			;CONTINUED ON NEXT PAGE
			;CONTINUED FROM PREVIOUS PAGE

;CURRENT FORMS PARAMETERS

	LP	J$FORM,1		;CURRENT FORMS TYPE
	LP	J$FPFM,1		;PREVIOUS FORMS TYPE
	LP	J$FSFM,1		;TYPE OF FORMS QUASAR IS SCHEDULING

DEFINE	FF(X,Y),<
	LP	J$F'X,1
>

	LP	J$FCUR,0		;START OF FORMS PARAMS
	F				;CURRENT FORMS PARAMS

	LP	J$FWCL,1		;CURRENT WIDTH CLASS
	LP	J$FLVT,1		;CURRENTLY 'LOADED' VFU TYPE
	LP	J$FNBK,16		;OPERATOR NOTE BLOCK

	PURGE	J$FVFU,J$FCHA		;DON'T USE THESE



;MISCELLANY
	LP	J$XSBC,1		;SAVE BYTE-COUNT FOR FAST BAKSPC
	LP	J$XDPG,1		;FORW/BACK DESTINATION PAGE
	LP	J$XPOS,1		;CURRENT VERTICAL POSITION
	LP	J$XSPC,1		;CURRENT SPACING
	LP	J$XHIP,1		;HEADER-IN-PROGRESS
	LP	J$XHBF,<45>		;BUFFER TO BUILD HEADER LINE
	LP	J$XCOD,<^D49>		;COMPILE A ROUTINE TO CHECK
					; FOR MATCH ON /REPORT
	LP	J$XHUN,3		;PLACE TO BUILD USER NAME
	LP	J$XHUW,1		;NUMBER OF WORDS IN USER NAME
	LP	J$XHNO,3		;PLACE TO BUILD THE NOTE
	LP	J$XCOP,1		;NUMBER OF COPIES TO PRINT
	LP	J$XPG1,1		;START PAGE FOR FIRST COPY
	LP	J$XPG2,1		;START PAGE FOR SUBSEQENTS
	LP	J$XMLM,1		;MLIMIT FOR PRINTER
	LP	J$XPCB,1		;BLOCKSIZE FOR "PICTURE"
	LP	J$XPCS,1		;NUMBER OF SIG CHARS FOR "PICTURE"

IFN FTUUOS,<
	LP	J$XPTB,<TABSIZ>		;PAGE TABLE FOR BACKSPACE
	LP	J$XVFP,1		;SCRATCH PAGE FOR READING VFUS
	LP	J$XVFB,3		;BUFFER RING HEADER FOR READING VFUS
>  ;END IFN FTUUOS
IFN FTJSYS,<
	LP	J$XUNO,1		;OWNER'S USER NUMBER
	LP	J$XSFO,<10>		;SCRATCH FOR FORMATTED OUTPUT RTNS
>  ;END IFN FTJSYS
;ACCOUNTING BLOCK

IFN FTUUOS,<
	LP	J$AFNC,1		;DAEMON FUNCTION
	LP	J$AHED,1		;TYPE,,LENGTH (251B8,,13)
	LP	J$APPN,1		;PPN
	LP	J$ADAT,1		;DATE (FILLED BY DAEMON)
	LP	J$AQUE,1		;0-11 = QUEUE NAME
					;12-17 = STATION
					;18-35 = SERIAL # OF MASTER CPU
	LP	J$ARTM,1		;RUNTIME IN SECS*100
	LP	J$ACTI,1		;CORE-TIME INTEGRAL IN KCS*100
	LP	J$ADRD,1		;DISK READS
	LP	J$ADWT,1		;DISK WRITES
	LP	J$ADEV,1		;PROCESSING DEVICE
	LP	J$ASEQ,1		;JOB SEQUENCE NUMBER
	LP	J$APRT,1		;NUMBER OF PAGES PRINTED
		J$AEND==J$APRT		;END OF BLOCK
		J$ALEN==J$AEND-J$AHED+1
>  ;END IFN FTUUOS


IFN FTJSYS,<
	LP	J$AHED,1		;CODE,JOB,LINE,SIZE
	LP	J$ADIR,1		;0,,DIRECTORY
	LP	J$ADAT,1		;DATE,,TIME
	LP	J$ARTM,1		;RUNTIME USED
	LP	J$ADEV,1		;DEVICE USED
	LP	J$APRT,1		;# PAGES PRINTED
	LP	J$AFRM,1		;FORMS TYPE
	LP	J$AANO,1		;ACCOUNT NUMBER (OR -BYTE COUNT)
	LP	J$ASTG,10		;ACCOUNT STRING
		J$AEND==J$ASTG+7	;END OF BLOCK
		J$ALEN==J$AEND-J$AHED+1


	LP	J$AFIL,J$ALEN		;ACCOUNTING BLOCK FOR CURRENT FILE
	LP	J$ASVP,1		;SAVE AMOUNT PRINTED
	LP	J$ASVR,1		;SAVE RUNTIME
>  ;END IFN FTJSYS
;DISK FILE PARAMETERS

IFN FTUUOS,<
	LP	J$DPAT,<10>		;PATH BLOCK
	LP	J$DUUO,<.RBTIM+1>	;UUO BLOCK
	LP	J$DFLP,.FOPPN+1		;FILOP. BLOCK
>  ;END IFN FTUUOS

IFN FTJSYS,<
	LP	J$DSTG,1		;ADDRESS OF CURRENT FILENAME
	LP	J$DJFN,1		;JFN OF CURRENT FILE
	LP	J$DBIF,1		;#BYTES LEFT IN FILE (36BIT)
					; IF RMS FILE, -1 MEANS NORMAL READ
					; AND 0 MEANS EOF SET EXTERNALLY
	LP	J$DMOD,1		;POINT <BYTE-SIZE>,<BYTES/WORD>
	LP	J$DNAM,10		;PLACE TO JFNS THE FILENAME
	LP	J$DFDB,.FBLEN		;FDB FOR THE DISK FILE
	LP	J$DCAB,5		;CHKAC BLOCK

;--RMS PARAMETERS
	LP	J$DRMS,1		;-1 IF THIS IS AN RMS FILE
	LP	J$DFAB,FA$LNG		;FILE ACCESS BLOCK (FAB)
	LP	J$DRAB,RA$LNG		;RECORD ACCESS BLOCK (RAB)
	LP	J$DRFA,1		;RFA OF FIRST RECORD
	LP	J$DRME,1		;RMS ERROR FLAG SET BY RMSERR
>  ;END IFN FTJSYS

	LP	J$DBUF,1		;ADDRESS OF DSK BUFFERS
	LP	J$DINF,1		;CURRENT DISK BLK OR PAGE NUMBER
	LP	J$DRNM,2		;DISK FILE'S REFERENCE NAME
	LP	J$DREX,2		;FILE'S REFERENCE EXTENSION
	LP	J$DRBS,1		;CONTAINS BLOCK SIZE FOR HEADER
	LP	J$DERR,1		;NUMBER OF DEVICE ERRORS

	LP	J$DBRH,3		;BUFFER RING HEADER
		J$DBPT==J$DBRH+1	;BUFFER BYTE POINTER
		J$DBCT==J$DBRH+2	;BUFFER BYTE COUNT
;LOG FILE PARAMETERS

IFN FTUUOS,<
	LP	J$GPAT,<10>		;PATH BLOCK
	LP	J$GUUO,<.RBPRV+1>	;LOOKUP BLOCK
	LP	J$GFLP,<6>		;FILOP. UUO BLOCK
	LP	J$GBRH,1		;BUFFER RING HEADER
	LP	J$GBPT,1		;BYTE-POINTER
	LP	J$GBCT,1		;BYTE-COUNT
>  ;END IFN FTUUOS

IFN FTJSYS,<
	LP	J$GSTG,1		;POINTER TO GTJFN STRING
	LP	J$GJFN,1		;THE JFN
>  ;END IFN FTJSYS

	LP	J$GBUF,10		;ADDRESS OF LOG FILE BUFFERS
	LP	J$GNLN,1		;NUMBER OF LINES WRITTEN IN LOG
	LP	J$GIBC,1		;INTERNAL LOG BYTE COUNT
	LP	J$GIBP,1		;INTERNAL LOG BYTE POINTER
	LP	J$GINP,1		;NUMBER OF INTERNAL LOG PAGES


	LP	J$$END,1		;END OF PARAMETER AREA
		J$$LEN==J$$END		;LENGTH OF PARAMETER AREA
SUBTTL	Random Impure Storage

NXTJOB:	BLOCK	1		;NEXT JOB TO RUN
MESSAG:	BLOCK	1		;ADDRESS OF MESSAGE JUST RECEIVED
MSGBLK:	BLOCK	15		;PLACE TO BUILD MESSAGES TO QUASAR
TTYFLG:	BLOCK	1		;SET TO -1 ON TTY INTERRUPT
XITFLG:	BLOCK	1		;-1 IF PENDING EXIT
RSTFLG:	BLOCK	1		;-1 IF PENDING RESET
ACTFLG:	BLOCK	1		;-1 IF DOING ACCOUNTING
LPTPID:	BLOCK	1		;MY PID (RETURN BY CSPINI)
QRYFLG:	BLOCK	1		;ADR OF WORD TO SETOM WHEN AN IPCF INTERRUPT
				; COMES IN

MSGJOB:	BLOCK	1		;-1 ON MESSAGE JOB
MSGFIL:	BLOCK	1		;-1 ON MESSAGE FILE
MSGERR:	BLOCK	1		;-1 ON MESSAGE ERROR

FMBPT:	BLOCK	1		;BYTE POINTER
FMADR:	BLOCK	1		;ADDRESS OF BUFFER
FMNEW:	BLOCK	1		;SET TO -1 AFTER RE-READING LPFORM
LPCNF:	BLOCK	10		;SYSNAME


PDL:	BLOCK	PDSIZE		;PUSHDOWN LIST
CNTSTA:	BLOCK	1		;NUMBER OF THE CENTRAL STATION
MYSTA:	BLOCK	1		;MY STATION
JOBPAG:	BLOCK	1		;ADDRESS OF A TWO PAGE BLOCK
				; ONE FOR REQUEST, ONE FOR JOB PARAMS
NORMAL:	EXP	FRMNOR		;NAME OF STD FORMS

IFN FTJSYS,<
BLOKED:	BLOCK	1		;SET WHEN WE GO TO SLEEP
AWOKEN:	BLOCK	1		;SET WHEN WE GET AN INTERRUPT
GJBLK:	BLOCK	10		;BLOCK FOR LONG GTJFN

TTYFRK:	BLOCK	1		;FORK HANDLE FOR TTY PROCESS
TTYRUN:	BLOCK	1		;-1 IF TTY PROCESS IS RUNNING
TTYPTR:	BLOCK	1		;POINTER TO TTY BUFFER
TTYBUF:	BLOCK	30		;TTY BUFFER (FILLED BY LOWER FORK)
>  ;END IFN FTJSYS

IFN FTUUOS,<
SEGBLK:	BLOCK	6		;GETSEG BLOCK
JIFSEC:	BLOCK	1		;JIFFIES/SEC
>  ;END IFN FTUUOS
IFN FTJSYS,<
DDEV:	-1,,[ASCIZ /SYS/]		;DEFAULT DEVICE FOR VFU AND TRM
DVFU:	-1,,[ASCIZ /VFU/]		;DEF. EXT FOR VFU FILE
DTRM:	-1,,[ASCIZ /TRM/]		;DEF. EXT FOR LP20 TRANS RAM FILE
DJFN:	.NULIO,,.NULIO			;DEFAULT I/O JFNS
>  ;END IFN FTJSYS
SUBTTL	Idle Loop

	TOPSEG

MAIN:	MOVE	P,[IOWD PDSIZE,PDL]	;SETUP A NEW PDL
	SKIPE	XITFLG			;EXIT PENDING?
	JRST	DOEXIT			;YES, DO IT
	SKIPE	RSTFLG			;NO, WHAT ABOUT A RESET
	JRST	DOREST			;YUP!
	TXNN	S,PLOCK			;SKIP IF PAUSE LOCK IS SET
	TXNE	S,PAUSEB		;TIME TO PAUSE?
	PUSHJ	P,DOPAUS		;YES, PAUSE NOW

SLP0:	AND	S,[RUNB+STARTD+PLOCK+FROZE+TTYBRK]
					;CLEANUP FLAGS
	PUSHJ	P,CHKALL		;SOMETHING THERE?
	HRRZ	AP,MESSAG		;GET ADDRESS OF MESSAGE
	JUMPE	AP,SLP1			;NO. GO TO SLEEP
	LOAD	T1,.MSTYP(AP),MS.TYP	;GET THE MESSAGE TYPE
	CAIE	T1,.QONEX		;IS IT A JOB FOR ME?
	JRST	[MOVX	S1,1B0		;LOAD A BIT
		 TDNN	S1,MESSAG	;WAS IT A PAGE?
		 JRST	SLP0		;NO, JUST IGNORE IT
		 ADR2PG	AP		;MAKE A PAGE NUMBER
		 PUSHJ	P,M$RELP##	;RELEASE IT
		 JRST	SLP0]		;AND LOOP
	HRRZ	S2,J			;YES, GET ADR OF JOB BLOCK
	HRL	S2,AP			;MAKE A BLT POINTER
	LOAD	T1,.MSTYP(AP),MS.CNT	;GET SIZE OF REQUEST
	ADDI	T1,-1(J)		;GET END OF BLT ADR
	BLT	S2,(T1)			;BLT THE REQEST
	ADR2PG	AP			;MAKE A PAGE NUMBER
	PUSHJ	P,M$RELP##		;RELEASE THE PAGE
	JRST	SETJOB			;AND GO DO IT

SLP1:	PUSHJ	P,M$CLNC##		;CLEAN UP BEFORE RESTING
	MOVEI	S1,^D60			;60 SECONDS
	PUSHJ	P,SUSPND		;GO WAIT
	JRST	SLP0			;AND LOOP
SUBTTL	Job Setup

SETJOB:	ON	S,BUSY			;WE'VE GOT A JOB!!
	PUSHJ	P,M$ACQP##		;GET A DSK BUFFER PAGE
	PG2ADR	AP			;MAKE AN ADDRESS
	MOVEM	AP,J$DBUF(J)		;SAVE AS DISK BUFFER ADDRESS
	PUSHJ	P,ACTBEG		;SETUP ACCOUNTING INFO
	LOAD	T1,.EQSEQ(J),EQ.SEQ	;GET THE SEQUENCE NUMBER
	CAMN	T1,NXTJOB		;IS THE SPECIFIED NXTJOB?
	CLEARM	NXTJOB			;YES, CLEAR IT
	PUSHJ	P,CHKJOB		;CHECK OUT THE JOB
	PUSHJ	P,FNDLOG		;GO SETUP THE LOG-FILE
	PUSHJ	P,STALOG		;START THE LOG FILE
	LOAD	T1,.EQLM2(J),EQ.PGS	;GET LIMIT IN PAGES
	SUB	T1,.EQCHK+CKTPP(J)	;SUBRTRACT AMT PRINTED
	MOVEM	T1,J$RLIM(J)		;SAVE IT
	SETZM	J$RNFP(J)		;CLEAR FILES PRINTED
	SETZM	J$RNCP(J)		;CLEAR COPIES PRINTED
	SETZM	J$RNPP(J)		;CLEAR PAGES PRINTED

	PUSHJ	P,MOUNT			;MOUNT THE CORRECT FORMS
	SKIPN	MSGJOB			;MESSAGE JOB?
	SKIPE	J$FWHA(J)		;OR /WHAT?
	SKIPA				;YES!!
	JRST	SETJ.1			;NO, CONTINUE
	TELL	OPR,[ASCIZ /Starting /]
	PUSHJ	P,WHAT			;AND SOME MORE
SETJ.1:	SKIPE	J$FPAU(J)		;/PAUSE?
	PUSHJ	P,DOPAUS		;AND PAUSE
	LOAD	T1,.EQSEQ(J),EQ.RDE	;GET "IGNORE REQUEST" BIT
	SKIPE	T1			;IS IT SET?
	TXO	S,ABORT			;YES, SET ABORT
	SKIPE	J$RFLP(J)		;SKIP IF NO FILES TO BE PRINTED
	TXNE	S,ABORT			;WERE WE ABORTED?
	SKIPA				;EITHER 0 FILES, OR ABORTED
	PUSHJ	P,JOBHDR		;NO, GIVE THE BANNER
SUBTTL	Do the Job

DOJOB:	LOAD	E,.EQLEN(J),EQ.LOH	;GET LENGTH OF HEADER
	ADD	E,J			;POINT TO FIRST FILE
	SKIPN	.EQCHK+CKFLG(J)		;IS THIS A RESTARTED JOB?
	JRST	DOJO.4			;NO, SKIP ALL THIS STUFF
	STAMP	LPMSG			;STAMP THE LOG
	TELL	LOG,%%JBR		;JOB WAS RESTARTED
	MOVEI	T1,%%JBR1		;AFTER CRASH
	MOVX	T2,CKFREQ		;GET REQUEUE BIT
	TDNE	T2,.EQCHK+CKFLG(J)	;CHECK IT
	MOVEI	T1,%%JBR2		;YES, REQ
	TELL	LOG,(T1)		;FINISH THE MESSAGE
	MOVE	T1,.EQCHK+CKFIL(J)	;YES, GET NUMBER OF FILES DONE
	MOVEM	T1,J$RNFP(J)		;STORE FOR NEXT CHECKPOINT
	SKIPGE	T1			;IS IT DURING THE LOG FILE?
	JRST	DOJO.7			;YES, GO DO THE LOG
DOJO.1:	SOJL	T1,DOJO.2		;DECREMENT AND JUMP IF SKIPED ENUF
	PUSH	P,T1			;ELSE, SAVE T1
	PUSHJ	P,NXTFIL		;BUMP E TO NEXT SPEC
	POP	P,T1			;RESTORE T1
	JUMPE	E,ENDJOB		;EASY JOB
	JRST	DOJO.1			;LOOP SOME MORE

DOJO.2:	MOVE	T1,.EQCHK+CKCOP(J)	;GET NUMBER OF COPIES PRINTED
	MOVEM	T1,J$RNCP(J)		;SAVE FOR NEXT CHECKPOINT

DOJO.3:	SKIPA	T1,.EQCHK+CKPAG(J)	;GET CHKPNT'ED PAGE
DOJO.4:	LOAD	T1,.FPFST(E)		;GET /START PARAMETER
	MOVEM	T1,J$XPG1(J)		;SAVE FOR FIRST COPY
DOJO.5:	LOAD	T1,.FPFST(E)		;GET START PARAMETER
	MOVEM	T1,J$XPG2(J)		;SAVE FOR SUBSEQUET COPIES
	CAME	E,J$RLFS(J)		;IS IT THE LOG FILE?
	PUSHJ	P,FILE			;NO, PRINT THE FILE
DOJO.6:	PUSHJ	P,NXTFIL		;BUMP TO NEXT FILE
	JUMPN	E,DOJO.4		;AND LOOP

DOJO.7:	PUSHJ	P,RIDLOG		;CLOSE AND RELEASE THE LOG
	SKIPN	E,J$RLFS(J)		;GET ADR OF LOG-SPEC
	JRST	ENDJOB			;NO, FINISH JOB
	SETZM	J$RLFS(J)		;CLEAR SOME LOCATIONS
	SETZM	J$RFLN(J)		; TO AVOID POSIBILITY OF LOOPS
	SETOM	J$RNFP(J)		;AND MAKE CHECKPOINT WORK RIGHT
	MOVE	S1,J$APRT(J)		;GET NUMBER OF PAGES PRINTED
	ADDI	S1,LOGPAG		;ADD IN GUARANTEED LOG LIMIT
	CAMLE	S1,J$RLIM(J)		;DOES HE HAVE AT LEAST THAT MANY?
	MOVEM	S1,J$RLIM(J)		;NO, GIVE HIM THAT MANY
	OFF	S,ABORT			;CLEAR ABORT FLAG
	PUSHJ	P,FILE			;PRINT THE FILE
	JRST	ENDJOB			;AND FINISH UP

NXTFIL:	SETZM	J$RNCP(J)		;CLEAR COPIES PRINTED
	SOSG	J$RFLN(J)		;DECREMENT FILE COUNT
	JRST	NXTF.1			;DONE, RETURN A ZERO
	PUSHJ	P,CLSLOG		;CLOSE OUT THE LOG
	LOAD	T1,.FPSIZ(E),FP.FHD	;GET SIZE OF THE FP
	LOAD	T2,.FPSIZ(E),FP.FFS	;GET SIZE OF THE FD
	ADD	E,T1			;BUMP E ONCE
	ADD	E,T2			;AND AGAIN
	AOS	J$RNFP(J)		;ONE MORE FILE DOWN
	POPJ	P,			;AND RETURN

NXTF.1:	SETZ	E,			;CLEAR E
	POPJ	P,			;AND RETURN
SUBTTL	Print a File

FILE:	PUSHJ	P,OPINFL		;OPEN THE FILE UP
	PJUMPE	S1,CLSFIL		;LOSE, CLOSE FILE AND RETURN
	TXNE	S,ABORT			;HAVE WE KILLED HIM?
	JRST	FILDIS			;YES, CLEAN UP SOME
	LOAD	T1,.FPINF(E),FP.IGN	;WAS FILE /REMOVE'D?
	JUMPN	T1,FILDIS		;YES, GO DISPOSE OF IT
	PUSHJ	P,ACCCHK		;CHECK FILE ACCESS
	PJUMPE	S1,CLSFIL		;NO ACCESS...
	PUSHJ	P,SETREF		;YES, GO SETUP REF-NAME

	STAMP	LPMSG			;GIVE A STAMP
	TELL	LOG,%%STF		;AND GIVE A START MESSAGE
	SKIPE	MSGFIL			;OPR WANT ONE TOO?
	TELL	OPR,%%STF		;YES,
	LOAD	T1,.FPINF(E),FP.FCY	;GET NUMBER OF COPIES
	SUB	T1,J$RNCP(J)		;SUBRTRACT THOSE ALREADY PRINTED
	MOVEM	T1,J$XCOP(J)		;AND STORE IT
	SETZM	J$RNCP(J)		;CLEAR NUMBER OF COPIES WORD
	PUSHJ	P,ACTBFL		;DO PRE-FILE ACCOUNTING
	PUSHJ	P,COPY			;DO THE COPY LOOP
	PUSHJ	P,ACTEFL		;DO POST-FILE ACCOUNTING
	TXNE	S,ABORT			;HAVE WE ABORTED?
	JRST	FILDIS			;YES, SKIP THE MESSAGE
	STAMP	LPMSG			;GIVE A STAMP
	TELL	LOG,%%FPF		;GIVE A MESSAGE

FILDIS:	LOAD	T1,.FPINF(E)		;GET THE INFO WORD
	TXNE	T1,FP.SPL		;IS IT SPOOLED?
	JRST	FILD.1			;YES, DELETE IT
	TXNE	T1,FP.IGN		;IS IT IGNORED
	JRST	CLSFIL			;YES, JUST CLOSE IT OFF
	TXNN	T1,FP.DEL		;IS IT /DELETE?
	PJRST	CLSFIL			;NO, JUST CLOSE IT OFF
	TXNE	T1,FP.FLG		;YES, IS IT THE LOG FILE?
	TXNE	T1,FP.FCY		;YES, IS IT /COPIES:0
	SKIPA				;NO, NORMAL FILE
	JRST	FILD.1			;YES, DELETE IT
	TXNN	S,ABORT			;ITS ORDINARY, IS JOB ABORTED?
FILD.1:	PUSHJ	P,DELFIL		;NO, GO DELETE THE FILE
	PJRST	CLSFIL			;CLOSE THE FILE AND RETURN
SUBTTL	Per Copy Loop

COPY:	SOSGE	J$XCOP(J)		;COUNT DOWN COPIES
	POPJ	P,			;RETURN WHEN DONE
	PUSHJ	P,HEAD			;PUT ON A HEADER
	PUSHJ	P,OUTDMP		;DUMP THE REST OUT AND WAIT
	ON	S,DSKOPN		;TURN ON FILE-OPEN FLAG
	TXNE	S,ABORT			;KILLED WHILE PRINTING?
	POPJ	P,			;YES, RETURN
	PUSHJ	P,REWIND		;REWIND THE FILE
	CLEARM	J$XSBC(J)		;CLEAR SAVED BYTE COUNT
	TXNE	S,SUPJOB		;SUPRES /JOB?
	ON	S,SUPRES		;YES.LIGHT A BIT
	MOVEI	T1,MAXERR		;NUMBER OF I/O ERROR BEFORE QUITTING
	MOVEM	T1,J$DERR(J)		;STORE
	SETZM	J$RNPP(J)		;CLEAR THE PAGE WORD
	MOVE	N,J$XPG1(J)		;GET PAGE FOR 1ST COPY
	MOVE	T1,J$XPG2(J)		;GET PAGE FOR SUBSEQENTS
	MOVEM	T1,J$XPG1(J)		;SAVE SO WE GET IT NEXT TIME
	SOSLE	N			;JUMP IF NONE
	PUSHJ	P,FORWD1		;CALL FORWARD TO SET EVERYTHING UP

	PUSHJ	P,FILOUT		;PRINT THE FILE
	OFF	S,NOTYPE!DSKOPN		;CLEAR SOME FLAGS
	TXNE	S,ABORT			;ABORTED?
	POPJ	P,			;YES, RETURN
	AOS	J$RNCP(J)		;INCREMENT COPIES WORD
	JRST	COPY			;STILL MORE TO DO
SUBTTL	End of Job

ENDJOB:	PUSHJ	P,ACTEND		;DO THE NECESSARY ACCOUTING
	MOVX	T1,<REL.SZ,,.QOREL>
	MOVEM	T1,MSGBLK		;SETUP MESSAGE HEADER
	LOAD	T1,.EQITN(J)		;GET THE JOBS ITN
	STORE	T1,MSGBLK+REL.IT	;STORE IN THE MESSAGE
	MOVEI	T1,MSGBLK		;LOAD ADDRESS
	TXNN	S,RQB			;DON'T SEND REL IF WE HAVE REQ'D
	PUSHJ	P,SNDQSR##		;SEND IT

ENDJ.1:	STAMP	LPSUM			;GENERATE A SUMMARY STAMP
	MOVE	N,J$ARTM(J)		;GET CP TIME USED
	IDIVI	N,^D1000		;DIVIDE BY MILLI-SECS PER SEC
	TELL	LOG,[ASCIZ /Spooler runtime # Seconds, /]

IFN FTUUOS,<
	MOVE	N,J$ACTI(J)		;GET # OFKCS USED
	IDIVI	N,144			;CONVERT TO SECONDS
	TELL	LOG,[ASCIZ /# KCS, /]
	MOVE	N,J$ADRD(J)		;READ COUNT
	TELL	LOG,[ASCIZ /# disk reads, /]
>  	;END IFN FTUUOS

	MOVE	N,J$APRT(J)		;GET PAGES 
	TELL	LOG,[ASCIZ /# pages printed
/]
	PUSHJ	P,JOBTRL		;PRINT THE TRAILER
	MOVE	AP,J$DBUF(J)		;GET ADR OF DSK BUFFER
	ADR2PG	AP			;MAKE IT A PAGE NUMBER
	PUSHJ	P,M$RELP##		;RETURN IT
	PUSHJ	P,CLNLOG		;CLEAN UP LOG PAGES
	SKIPN	MSGJOB			;WANT JOB MESSAGES?
	JRST	ENDJ.2			;NO, CONTINUE ON
	TELL	OPR,[ASCIZ /Finished /]
	PUSHJ	P,WHAT			;JOB ID
ENDJ.2:	OFF	S,BUSY			;NOT BUSY
	JRST	MAIN			;AND LOOP TO THE BEGINNING
SUBTTL	CHKJOB - Check the files and count them

;CHKJOB IS CALLED DURING JOB SETUP.  IT FILLS IN 3 LOCATIONS:
;	J$RFLN	-	NUMBER OF FILES IN REQUEST
;	J$RFLP	-	NUMBER OF FILES WHICH WILL BE PRINTED
;	J$RLFS	-	ADDRESS OF THE LOG FILE SPEC

CHKJOB:	SETZM	J$RLFS(J)		;ASSUME NO LOG FILE
	LOAD	T1,.EQSPC(J),EQ.NUM	;GET NUMBER OF FILES IN REQUEST
	MOVEM	T1,J$RFLN(J)		;AND SAVE IT
	MOVEM	T1,J$RFLP(J)		;AND START AS NUMBER TO PRINT
	LOAD	T2,.EQLEN(J),EQ.LOH	;GET LENGTH OF HEADER
	ADD	T2,J			;AND POINT TO FIRST FILE

CHKJ.1:	LOAD	T3,.FPINF(T2)		;GET INFO WORD
	TXNE	T3,FP.FLG		;IS IT THE LOG FILE?
	MOVEM	T2,J$RLFS(J)		;YES, SAVE ITS ADDRESS
	TXNE	T3,FP.FCY		;/COP:0?
	TXNE	T3,FP.IGN		;NO, IS IT IGNORED?
	SOS	J$RFLP(J)		;EITHER 0 COPIES OR IGNORED
	LOAD	T3,.FPSIZ(T2),FP.FHD	;GET LENGTH OF THE FP
	LOAD	T4,.FPSIZ(T2),FP.FFS	;GET LENGTH OF THE FD
	ADD	T2,T3			;BUMP T2 ONCE
	ADD	T2,T4			;BUMP T2 AGAIN
	SOJG	T1,CHKJ.1		;AND LOOP
	LOAD	T1,.EQSEQ(J),EQ.RDE	;GET THE RDE BIT
	SKIPE	T1			;SKIP IF NOT AN RDE JOB
	SETZM	J$RLFS(J)		;ELSE, NO LOG FILE
	POPJ	P,			;DONE, RETURN
SUBTTL	Message Check Routines

	LOWSEG				;PLACE IN LOW SEGMENT

;THREE ROUTINES ARE USED TO CHECK FOR VARIOUS MESSAGES:
;	CHKALL	--  CHECKS FOR BOTH OPERATOR TYPEIN AND IPCF MESSAGES
;	CHKOPR	--  CHECKS FOR OPERATOR TYPE IN
;	CHKQUE	--  CHECKS FOR IPCF MESSAGES

;LOCATION "MESSAG" IS RETURNED WITH THE ADDRESS OF ANY MESSAGE RECEIVED.

CHKALL:	PUSHJ	P,CHKSEG		;CHECK TO SEE IF WE HAVE A HISEG
	PUSHJ	P,CHKOP0		;SEE IF OPR WANTS SOMETHING
	PUSHJ	P,CHKQU0		;SEE IF ANYTHING'S IN THE QUEUE
	POPJ	P,			;AND RETURN


;CHKSEG SIMPLY RETURNS IF THE HISEGMENT EXISTS, AND CALLS ITS CALLER
;	IF NOT.  HENCE, WHEN THE CALLER RETURNS WE GET TO DELETE THE
;	HISEG.
;
CHKSEG:	SKIPE	.JBHRL##		;IS THERE A HISEG?
	POPJ	P,			;YES, JUST RETURN
	EXCH	S1,0(P)			;NO, SAVE S1 GET CALLERS ADDRESS
	PUSHJ	P,(S1)			;AND CALL HIM
	POP	P,S1			;RESTORE S1
	PJRST	CLRSEG			;AND CLEAR THE HISEG
CHKOPR:	PUSHJ	P,CHKSEG		;CHECK THE HISEG
CHKOP0:					;ENTER HERE FROM CHKALL

IFN FTUUOS,<
	SETZ	S1,			;LOAD A 0
	EXCH	S1,TTYFLG		;LOAD TTYFLG AND SET FOR NEXT TIME
	JUMPE	S1,.POPJ##		;NO, RETURN IF NOTHING THERE
	SKPINL				;CHECK
	  POPJ	P,			;NOTHING THERE FOR REAL
	PUSHJ	P,GETSPL		;GET THE HISEG
	PUSHJ	P,SAVALL		;SAVE ALL ACS
CHKOP1:	PUSHJ	P,COMIN			;DO ONE COMMAND
	SKPINL				;IS THERE ONE?
	  POPJ	P,			;NO, RETURN
	JRST	CHKOP1			;YES, GET ANOTHER COMMAND
>  ;END IFN FTUUOS

IFN FTJSYS,<
	SKIPN	TTYFLG			;HAS HE TYPED ANYTHING?
	POPJ	P,			;NO, RETURN
	PUSHJ	P,SAVALL		;YES, SAVE ACS
	PJRST	COMIN			;GET A COMMAND
>  ;END IFN FTJSYS

CHKQUE:	PUSHJ	P,CHKSEG		;SEE IF WE HAVE A HISEG
CHKQU0:					;ENTER HERE FROM CHKALL
	PUSHJ	P,CSPRCV##		;RECEIVE A MESSAGE
	MOVEM	S1,MESSAG		;SAVE ADDRESS OF MESSAGE
	JUMPE	S1,.POPJ##		;RETURN NOTHING THERE, RETURN
	LOAD	S2,.MSTYP(S1),MS.TYP
	CAIE	S2,.QONEX		;IS IT A JOB FOR ME?
	JRST	CHKQU1			;NO, CONTINUE
	POPJ	P,

CHKQU1:	TXNN	S,BUSY			;ARE WE BUSY?
	POPJ	P,			;NO, JUST IGNORE THE WHOLE THING
	PUSHJ	P,SAVALL		;SAVE THE T REGS
	CAIE	S2,.QOABO		;IS IT ABORT??
	JRST	CHKQU2			;NO, SEE IF QUASAR IS REQUESTING A CHKPNT
	PUSHJ	P,GETSPL		;YES, GET THE HISEG
	PJRST	UKILL			;AND KILL OFF THE JOB

CHKQU2:	CAIE	S2,.QORCK		;CHECKPOINT REQUEST?
	POPJ	P,			;NO, RETURN
	PJRST	TAKCHK			;AND TAKE A CHECKPOINT
SUBTTL	Core and Segment Handling Routines

;	GETSPL	--		GET THE SPOOLER'S HISEG
;	CLRSEG	--		CLEAR THE SPOOLER'S HISEG


	LOWSEG			;THESE ARE IN THE LOWSEG
SUBTTL	GETSPL  -  Routine to get the spooler's hiseg

;GETSPL IS CALLED TO MAP THE SPOOLER'S HISEG IN
;CALL WITH:
;	PUSHJ	P,GETSPL
;	  RETURN HERE

IFN FTUUOS,<
GETSPL:	SKIPE	.JBHRL		;SKIPE IF NO HISEG
	POPJ	P,		;ELSE SKIP SEGCON
	PUSHJ	P,SAVALL	;SAVE THE AC'S
	PUSHJ	P,INTOFF	;TURN OFF INTERRUPTS
GETSP1:	MOVEI	T1,SEGBLK	;POINT TO SEGBLK
	PUSH	P,S
	MOVEM	P,SAVP#
	GETSEG	T1,		;GET IT
	  HALT	[MOVE P,SAVP
		 POP  P,S
		 JRST GETSP1]
	MOVE	P,SAVP
	POP	P,S
	PJRST	INTON		;TURN ON INTERRUPTS AND RETURN
>  ;END IFN FTUUOS


IFN FTJSYS,<
GETSPL:	POPJ	P,
>  ;END IFN FTJSYS
SUBTTL	CLRSEG  -  Routine to clear the spooler's hiseg

;CLRSEG IS CALLED TO MAP THE SPOOLER'S HISEG OUT
;CALL:
;	PUSHJ	P,CLRSEG
;	  RETURN HERE

IFN FTUUOS,<
CLRSEG:	SKIPN	.JBHRL		;IS THERE A HISEG?
	POPJ	P,		;NO, DON'T GET RID OF IT
	PUSH	P,T1		;SAVE T1
	MOVSI	T1,1		;SET SIZE OF HISEG TO 1 WORD
	CORE	T1,		;CALL CORE0
	  JFCL			;IGNORE ANY ERROR
	POP	P,T1		;RESTORE T1
	POPJ	P,		;IGNORE SUCCESS
>  ;END IFN FTUUOS

IFN FTJSYS,<
CLRSEG:	POPJ	P,
>  ;END IFN FTJSYS
SUBTTL	Input File Facilities


;	OPINFL		--	OPEN THE INPUT FILE
;	ACCCHK		--	CHECK USER'S ACCESS TO THE INPUT FILE
;	DELFIL		--	DELETE THE INPUT FILE
;	CLSFIL		--	CLOSE THE INPUT FILE
;	TELCAF		--	REPORT FILE ACCESS ERROR
;	SETREF		--	SETUP REFERENCE NAME FOR FILE

	TOPSEG			;PUT THEM ALL IN THE HISEG
SUBTTL	OPINFL  -  Routine to open the input file

;OPINFL IS CALLED WITH AC "E" POINTING TO THE FP AREA FOR THE FILE
;	TO BE OPENED.
;
;CALL:
;	PUSHJ P,OPINFL
;	  ALWAYS RETURN HERE
;
;RETURNS S1 =  "TRUE" ON SUCCESS, "FALSE" OTHERWISE.

IFN FTUUOS,<
OPINFL:	LOAD	S1,.FPSIZ(E),FP.FHD	;GET SIZE OF THE FP AREA
	ADD	S1,E			;AND POINT S1 TO THE FD AREA
	MOVE	T2,.FDNAM(S1)		;GET THE FILENAME
	MOVEM	T2,J$DUUO+.RBNAM(J)	;SAVE IN LOOKUP BLOCK
	HLLZ	T2,.FDEXT(S1)		;GET THE EXTENSION
	MOVEM	T2,J$DUUO+.RBEXT(J)	;SAVE IN THE UUO BLOCK
	MOVSI	T1,J$DPAT(J)		;ADR OF PATH BLOCK,,0
	HRRI	T1,J$DPAT+1(J)		;BLT POINTER TO ZERO IT OUT
	CLEARM	J$DPAT(J)		;CLEAR THE FIRST WORD
	BLT	T1,J$DPAT+7(J)		;CLEAR THE REST
	MOVEI	T1,J$DPAT+2(J)		;POINT TO PPN WORD
	HRLI	T1,.FDPPN(S1)		;SETUP TO BLT THE PATH
	LOAD	T2,.FPSIZ(E),FP.FFS	;GET SIZE OF FD AREA
	ADDI	T2,-FDMSIZ(J)		;SUB FDMSIZ, ADD AP
	BLT	T1,J$DPAT+2(T2)		;BLT THE PATH
	MOVEI	T1,J$DPAT(J)		;ADDRESS OF PATH BLOCK
	SKIPN	J$DPAT+3(J)		;IS THERE AN SFD?
	MOVE	T1,J$DPAT+2(J)		;NO, LOAD THE PPN
	MOVEM	T1,J$DUUO+.RBPPN(J)	;AND SAVE IN THE UUO BLOCK
	MOVEI	T1,.RBTIM		;GET THE SIZE OF THE BLOCK
	MOVEM	T1,J$DUUO+.RBCNT(J)	;AND SAVE IT IN RIBCNT
	MOVX	T1,FO.PRV+.FORED+<DSK>B17 ;FILOP SETUP
	MOVEM	T1,J$DFLP+.FOFNC(J)	;STORE THE FUNCTION WORD
	MOVEI	T1,.IOASC		;ASSUME ASCII MODE
	LOAD	T2,.FPINF(E),FP.FFF	;GET /FILE:
	LOAD	T3,.FPINF(E),FP.FPF	;GET /PAPER:
	CAIE	T2,.FPFCO		;/FILE:COBOL?
	CAIN	T3,%FPLOC		;OR /PAPER:OCTAL?
	MOVEI	T1,.IOBIN		;YES, USE BINARY MODE
	MOVEM	T1,J$DFLP+.FOIOS(J)	;SAVE IOS


				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

	SKIPN	T1,.FDSTR(S1)		;GET THE STRUCTURE
	MOVSI	T1,'DSK'		;GUARD AGAINST CONKLIN
	MOVEM	T1,J$DFLP+.FODEV(J)	;AND SAVE IT
	MOVEI	T1,J$DBRH(J)		;LOAD ADR OF BUFFER RING HDR
	MOVEM	T1,J$DFLP+.FOBRH(J)	;AND STORE IT
	MOVEI	T1,<1000/203>		;NUMBER OF INPUT BUFFERS
	MOVEM	T1,J$DFLP+.FONBF(J)	;STORE IT
	MOVEI	T1,J$DUUO(J)		;ADDRESS OF THE LOOKUP BLOCK
	MOVEM	T1,J$DFLP+.FOLEB(J)	;AND STORE IT
	MOVE	T4,J$DBUF(J)		;GET ADR OF BUFFERS
	EXCH	T4,.JBFF		;AND SAVE IT AS JOBFF
	MOVEI	T1,J$DFLP(J)		;LOAD ADR OF FILOP BLOCK
	HRLI	T1,6			;LOAD THE LENGTH
	FILOP.	T1,			;GET THE FILE
	  JRST	[MOVEM T4,.JBFF		;RESTORE JOBFF
		 JRST	OPIN.1]		;TYPE MESSAGE AND GO ON
	MOVEM	T4,.JBFF		;RESTORE JOBFF
	PJRST	.TRUE##			;WIN RETURN

OPIN.1:	MOVE	S1,T1			;GET THE ERROR CODE
	MOVX	S2,LOG			;TELL LOG
	SKIPE	MSGERR			;AND IF OPR WANTS ERRORS
	IORX	S2,OPR			;TELL HIM TOO
	PUSHJ	P,TELCAF		;TELL THEM
	PJRST	.FALSE##		;AND LOSE RETURN
>  ;END IFN FTUUOS
IFN FTJSYS,<
OPINFL:	LOAD	S2,.FPSIZ(E),FP.FHD	;GET SIZE OF FP AREA
	ADD	S2,E			;S2 POINTS TO FD
	MOVEM	S2,J$DSTG(J)		;AND SAVE THE POINTER
	HRLI	S2,(POINT 7,0)		;MAKE IT A BYTE POINTER
	MOVX	S1,<GJ%OLD!GJ%SHT>	;SHORT GTJFN, OLD FILE ONLY
	GTJFN				;FIND THE FILE
	  JRST	OPIN.3			;FAILED?
	MOVEM	S1,J$DJFN(J)		;SAVE THE JFN
	SETZM	J$DRMS(J)		;ASSUME NOT AN RMS FILE
	MOVE	S1,J$DJFN(J)		;GET THE JFN
	MOVX	S2,<.FBLEN,,.FBHDR>	;GET ENTIRE FDB
	MOVEI	T1,J$DFDB(J)		;LOAD ADDRS OF BLOCK
	GTFDB				;AND GET IT
	LOAD	T1,J$DFDB+.FBCTL(J),FB%FCF
	CAIN	T1,.FBRMS		;LOAD FILE CLASS AND TEST IT
	SETOM	J$DRMS(J)		;IT IS AN RMS FILE
	MOVE	S1,J$DJFN(J)		;NOW, GET THE JFN
	MOVX	S2,<OF%RD+44B5>		;READ 36BIT BYTES
	SKIPL	J$DRMS(J)		;SKIP IF RMS FILE
	OPENF				;ELSE, OPEN THE FILE
	ERJMP	OPIN.3			;LOSE

	LOAD	T2,.FPINF(E),FP.FFF	;GET /FILE
	LOAD	T3,.FPINF(E),FP.FPF	;GET /PAPER
	MOVX	T1,<POINT 7,5>		;ASSUME 5 7BIT-BYTES/WORD
	CAIE	T2,.FPFCO		;/FILE:COBOL
	CAIN	T3,%FPLOC		;OR /PAPER:OCTAL?
	MOVX	T1,<POINT 36,1>		;YES, 1 36BIT-BYTE/WORD
	MOVEM	T1,J$DMOD(J)		;SAVE IT FOR "FILL"
	SKIPN	J$DRMS(J)		;SKIP IF RMS FILE
	PJRST	.TRUE##			;WIN RETURN


					;MORE OF "OPINFL" ON FOLLOWING PAGE
;HERE IF OPENING AN RMS-20 FILE, FIRST SETUP THE FAB
	MOVSI	T1,J$DFAB(J)		;GET FAB,,0
	HRRI	T1,J$DFAB+1(J)		;GET FAB,,FAB+1
	SETZM	J$DFAB(J)		;CLEAR THE FIRST WORD
	BLT	T1,J$DFAB+FA$LNG-1(J)	;CLEAR THE REST
	MOVX	T1,FA$TYP		;BLOCK TYPE
	$STFAB	T1,BID			;STORE THE BLOCK ID
	MOVX	T1,FA$LNG		;BLOCK LENGTH
	$STFAB	T1,BLN			;AND STORE IN FAB
	MOVX	T1,FB$GET		;GET "GET" ACCESS CODE
	$STFAB	T1,FAC			;STORE IN FILE ACCESS FIELD
	SETZ	T1,			;CLEAR T1
	$STFAB	T1,SHR			;AND STORE IT IN SHARE FIELD
	MOVE	T1,J$DJFN(J)		;GET THE JFN
	$STFAB	T1,JFN			;STORE IT IN JFN FIELD
	PUSHJ	P,SETRMS		;SETUP TO CALL RMS
	MOVEI	AP,J$DFAB(J)		;LOAD ADDRESS OF FAB
	$OPEN	<(AP)>,RMSERR		;OPEN THE FAB
	SKIPE	J$DRME(J)		;ERROR?
	JRST	OPIN.3			;YES, GO HANDLE IT
	$LDFAB	S1,BSZ			;GET THE BYTE SIZE
	LSH	S1,6			;POSITION IT
	TRO	S1,440000		;MAKE A BYTE POINTER
	HRLZ	S1,J$DMOD(J)		;AND STORE IT

;NOW SETUP THE RAB
	MOVSI	T1,J$DRAB(J)		;GET RAB,,0
	HRRI	T1,J$DRAB+1(J)		;GET RAB,,RAB+1
	SETZM	J$DRAB(J)		;CLEAR THE FIRST WORD
	BLT	T1,J$DRAB+RA$LNG-1(J)	;CLEAR THE REST
	MOVX	T1,RA$TYP		;GET BLOCK TYPE
	$STRAB	T1,BID			;STORE IT
	MOVX	T1,RA$LNG		;GET BLOCK LENGTH
	$STRAB	T1,BLN			;STORE IT
	MOVX	T1,RB$SEQ		;LOAD SEQUENTIAL ACCESS
	$STRAB	T1,RAC			;STORE RECORD ACCESS TYPE
	MOVX	T1,RB$LOC		;DONT MOVE RECORD
	$STRAB	T1,ROP			;REQUESTED OPERATION
	MOVEI	T1,1000			;LOAD THE BUFFER SIZE
	$STRAB	T1,USZ			;SAVE IT
	MOVE	T1,J$DBUF(J)		;LOAD ADDRESS OF BUFFER
	$STRAB	T1,UBF			;STORE IT
	MOVEI	T1,J$DFAB(J)		;LOAD ADDRESS OF FAB
	$STRAB	T1,FAB			;STORE IT
	PUSHJ	P,SETRMS		;SETUP TO CALL RMS
	MOVEI	AP,J$DRAB(J)		;LOAD ADDRESS OF RAB
	$CONNEC	<(AP)>,RMSERR		;CONNECT IT TO THE FAB
	SKIPE	J$DRME(J)		;ANY ERROR?
	JRST	OPIN.3			;YES, HANDLE IT
	SETOM	J$DRFA(J)		;INDICATE NO RFA YET
	PJRST	.TRUE##			;AND RETURN TRUE

				;OPINFL IS CONTINUED ON FOLLOWING PAGE
				;CONTINUED FROM PREVIOUS PAGE

OPIN.3:	MOVX	S2,LOG			;TELL LOG
	SKIPE	MSGERR			;AND IF OPR WANTS ERRORS
	IORX	S2,OPR			;TELL HIM TOO
	PUSHJ	P,TELCAF		;TELL THEM
	PJRST	.FALSE##		;AND LOSE
>  ;END IFN FTJSYS
SUBTTL	ACCCHK  -  Check access to current file

;ACCCHK IS CALLED TO CHECK THE USER'S ACCESS TO THE CURRENT FILE.
;
;THERE ARE FOUR CASES:
;	1) IF THE REQUEST CREATOR WAS PRIVILEGED, SUCCESS IS RETURNED
;	2) IF THE FILE IS SPOOLED, SUCCESS IS AUTOMATICALLY RETURNED
;	3) IF THE FILE IS NOT TO BE DELETED, "READ" ACCESS IS CHECKED
;	4) IF THE FILE IS TO BE DELETED:
;		A) DELETE ACCESS IS CHECKED.  IS THIS SUCCEEDS, SUCCESS
;			IS RETURNED.
;		B)  IF THIS FAILS, THE DISPOSITION IS CHANGED TO
;			PRESERVE AND WE GO BACK TO STEP 3.
;
;ON SUCCESS, S1 IS RETURNED "TRUE", OTHERWISE IT IS RETURNED "FALSE".

IFN FTUUOS,<
ACCCHK:	LOAD	S1,.EQSEQ(J),EQ.PRV	;GET PRIV BIT
	PJUMPN	S1,.TRUE##		;AND RETURN IF CREATOR WAS PRIV'ED
	LOAD	S1,.FPINF(E),FP.SPL	;GET SPOOLED BIT
	JUMPN	S1,.TRUE##		;IT'S SPOOLED, JUST RETURN
	HRLZI	T2,.ACRED		;ASSUME READ ACCESS
	LOAD	S2,.FPINF(E),FP.DEL	;ARE WE DELETING IT?
	SKIPE	S2			;SKIP IF NO
	HRLZI	T2,.ACREN		;YES, WE ARE
	HLRZ	T3,J$DUUO+.RBPRV(J)	;GET PROTECTION CODE
	LSH	T3,-^D9			;SHIFT IT OVER
	HRR	T2,T3			;AND COPY IT INTO T2
	MOVE	T3,J$DUUO+.RBPPN(J)	;GET THE FILE'S DIRECTORY
	TLNN	T3,-1			;A PATH?
	MOVE	T3,2(T3)		;YES, GET PPN FROM PATH BLOCK
	MOVE	T4,.EQOWN(J)		;GET USER'S PPN
	MOVE	T1,[3,,T2]		;LOAD BLOCK POINTER
	CHKACC	T1,			;TRY IT!
	  JRST	ACCC.1			;FAILURE
	JUMPE	T1,.TRUE##		;SUCCESS!!
	CLEAR	S2,			;CLEAR A REG
	STORE	S2,.FPINF(E),FP.DEL	;CLEAR THE DELETE BIT
	HRLI	T2,.ACRED		;TRY READ ONLY
	MOVE	T1,[3,,T2]		;LOAD ARG POINTER
	CHKACC	T1,			;TRY AGAIN
	  JRST	ACCC.1			;THAT'S FUNNY?
	JUMPE	T1,.TRUE##		;WIN!

ACCC.1:	MOVX	S1,ERPRT%		;LOAD ERROR CODE
	MOVX	S2,LOG			;TELL LOG
	SKIPE	MSGERR			;AND IF OPR WANTS ERRORS
	IORX	S2,OPR			;TELL HIM TOO
	PUSHJ	P,TELCAF		;TELL THEM
	PJRST	.FALSE##		;AND LOSE
>  ;END IFN FTUUOS
IFN FTJSYS,<
ACCCHK:	LOAD	S1,.EQSEQ(J),EQ.PRV	;GET PRIV BIT
	PJUMPN	S1,.TRUE##		;RETURN IF HE WAS PRIV'ED
	LOAD	S1,.FPINF(E),FP.SPL	;GET SPOOL BIT
	PJUMPN	S1,.TRUE##		;RETURN IF IT IS SPOOLED
	MOVX	S1,.CKARD		;GET "READ" CODE
	LOAD	S2,.FPINF(E),FP.DEL	;GET DELETE BIT
	SKIPE	S2			;WAS IT SET?
	MOVX	S1,.CKAWT		;YES, CHECK "WRITE" CODE
	MOVEM	S1,J$DCAB+.CKAAC(J)	;STORE IN CHKAC BLOCK
	MOVE	S1,J$DJFN(J)		;GET THE FILE'S JFN
	MOVEM	S1,J$DCAB+.CKAUD(J)	;STORE IN BLOCK
	HRROI	S1,.EQOWN(J)		;POINT TO USER'S DIRECTRY
	STORE	S1,J$DCAB+.CKALD(J)	;STORE IT
	HRROI	S1,.EQCON(J)		;POINT TO CONNECTED DIR
	STORE	S1,J$DCAB+.CKACD(J)	;STORE IT
	ZERO	J$DCAB+.CKAEC(J)
	MOVEI	S1,.CKAUD+1		;LOAD ARG COUNT
	TXO	S1,CK%JFN		;SET JFN ARG BIT
	MOVEI	S2,J$DCAB(J)		;LOAD BLOCK ADR
	CHKAC				;CHECK ACCESS
	  JRST	ACCC.1			;LOSE, NO ACCESS
	PJUMPN	S1,.TRUE##		;RETURN IF SUCCESSFUL
	ZERO	S2			;CLEAR OUT S2
	STORE	S2,.FPINF(E),FP.DEL	;AND CLEAR THE DELETE BIT
	MOVX	S1,.CKARD		;GET READ CODE
	MOVEM	S1,J$DCAB+.CKAAC(J)	;STORE IT
	MOVEI	S1,.CKAUD+1		;NUMBER OF ARGS
	TXO	S1,CK%JFN		;SET JFN ARG BIT
	MOVEI	S2,J$DCAB(J)		;WHERE THEY ARE
	CHKAC				;TRY AGAIN
	  JRST	ACCC.1			;LOSE
	PJUMPN	S1,.TRUE##		;WIN ?

ACCC.1:	MOVX	S1,OPNX3		;LOAD THE ERROR CODE
	MOVX	S2,LOG			;TELL LOG
	SKIPE	MSGERR			;AND IF OPR WANTS ERRORS
	IORX	S2,OPR			;TELL HIM TOO
	PUSHJ	P,TELCAF		;TELL THEM
	PJRST	.FALSE##		;AND LOSE
>  ;END IFN FTJSYS
SUBTTL	DELFIL  -  Routine to delete the current file

;DELFIL SIMPLY DELETES THE CURRENT FILE

IFN FTUUOS,<
DELFIL:	CLEARB	T1,T2			;CLEAR TWO WORDS
	CLEARB	T3,T4			;AND TWO MORE
	RENAME	DSK,T1			;DELETE IT
	  JFCL				;IGNORE THIS
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
DELFIL:	MOVX	S1,1B0			;"DON'T RELEASE JFN"
	HRR	S1,J$DJFN(J)		;GET THE JFN
	CLOSF				;CLOSE THE FILE
	  JFCL				;IGNORE
	MOVX	S1,DF%EXP		;DELETE AND EXPUNGE
	HRR	S1,J$DJFN(J)		;GET THE JFN
	DELF				;DELETE IT
	  JFCL				;IGNORE THIS
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	CLSFIL  -  Routine to close current file

;CLSFIL IS CALLED TO SIMPLY CLOSE OUT THE CURRENT INPUT FILE

IFN FTUUOS,<
CLSFIL:	CLOSE	DSK,100			;CLOSE AND GIVE UP THE A.T.
	RELEAS	DSK,			;RELEASE THE CHANNEL
	OFF	S,DSKOPN		;TURN OFF THE OPEN FLAG
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
CLSFIL:	SKIPE	J$DRMS(J)		;IS THIS AN RMS FILE?
	JRST	CLSF.1			;YES, GO DO SOMETHING DIFFERENT
	HRRZ	S1,J$DJFN(J)		;GET THE JFN
	CLOSF				;CLOSE IT AND RELEASE THE JFN
	  JFCL				;IGNORE THE ERROR
	OFF	S,DSKOPN		;CLEAR THE OPEN FLAG
	POPJ	P,			;AND RETURN

CLSF.1:	MOVEI	T1,J$DRAB(J)		;LOAD ADDRESS OF THE RAB
	$DISCON	<(T1)>			;AND DISCONNECT FROM THE FAB
	MOVEI	T1,J$DFAB(J)		;NO GET ADR OF THE FAB
	$CLOSE	<(T1)>			;AND CLOSE THE FILE
	MOVE	S1,J$DJFN(J)		;GET THE JFN
	RLJFN				;RELEASE IT
	  JFCL				;IGNORE THE ERROR RETURN
	POPJ	P,			;RETURN
>  ;END IFN FTJSYS
SUBTTL	TELCAF   -  Routine to report file access failure

;TELCAF IS CALLED TO REPORT A FAILURE IN ATTEMPTING TO ACCESS A FILE.
;
;CALL:
;	MOVE	S1,[ERROR CODE]
;	MOVE	S2,[AC FIELD (DESTINATION) OF TELL UUO]
;	PUSHJ	P,TELCAF
;	  ALWAYS RETURN HERE

TELCAF:	LOAD	T1,.FPINF(E),FP.IGN	;GET FILE-IGNORE BIT
	LOAD	T2,.EQSEQ(J),EQ.RDE	;AND REQUEST-IGNORE BIT
	IOR	T1,T2			;OR THEM TOGETHER
	JUMPN	T1,.POPJ##		;AND RETURN IF EITHER IS SET
	LSH	S2,^D23			;PUT BITS INTO AC FIELD
	DMOVEM	S1,T3			;AND STORE THE ARGS
	TXNE	S2,LOG_^D23		;IS IT GOING TO THE LOG
	STAMP	LPERR			;YES, STAMPIT
	MOVE	N,T3			;GET THE ERROR CODE
	MOVE	T1,[TELL %%CAF]		;LOAD THE UUO
	IOR	T1,T4			;OR IN THE DESTINATION
	XCT	T1			;AND DO THE UUO

IFN FTUUOS,<
	MOVSI	T1,-ERTBLN		;MAKE AOBJN PTR FOR TABLE
	MOVE	S1,T3			;AND GET ERROR CODE

TELC.1:	MOVE	T2,ERRTAB(T1)		;GET AN ENTRY
	CAIN	S1,(T2)			;CORRECT CODE?
	JRST	TELC.2			;YUP!!
	AOBJN	T1,TELC.1		;NO, LOOP
	MOVSI	T2,[ASCIZ /Unexpected System Error/]
>  ;END IFN FTUUOS

IFN FTJSYS,<
	HRROI	S1,J$XSFO(J)		;GET A SCRATCH BLOCK
	MOVE	S2,T3			;GET THE ERROR CODE
	HRLI	S2,.FHSLF		;AND GET MY FORK HANDLE
	MOVSI	T1,-<<5*10>-1>		;LOAD -VE CHARACTERS TO STORE
	ERSTR				;GET THE ERROR STRING
	  JFCL				;IGNORE ERROR 1
	  JFCL				;IGNORE ERROR 2
	MOVSI	T2,J$XSFO(J)		;LOAD 0,,ADR
>  ;END IFN FTJSYS

TELC.2:	MOVSS	T2			;GET ADR OF MESS IN RH
	HRLI	T2,(TELL)		;PUT IN THE OP-CODE
	IOR	T2,T4			;PUT IN THE DESTINATION
	XCT	T2			;TYPE IT OUT
	MOVE	T2,[TELL CRLF]		;SETUP TO TYPE CRLF
	IOR	T2,T4			;TO THE RIGHT PEOPLE
	XCT	T2			;DO IT
	POPJ	P,			;AND RETURN
;ERROR MESSAGE TABLES

;FORMAT OF TABLE IS XWD  ADR-OF-STRING,ERROR-CODE

IFN FTUUOS,<
ERRTAB:	XWD	[ASCIZ /File Not Found/],	ERFNF%
	XWD	[ASCIZ /No UFD on that Structure/],	ERIPP%
	XWD	[ASCIZ /Protection Failure/],	ERPRT%
	XWD	[ASCIZ /File Being Modified/],	ERFBM%
	XWD	[ASCIZ /RIB or UFD Error/],	ERTRN%
	XWD	[ASCIZ /No such device/],	ERNSD%
	XWD	[ASCIZ /No Room or Quota Exceeded/],	ERNRM%
	XWD	[ASCIZ /Structure is Write-locked/],	ERWLK%
	XWD	[ASCIZ /SFD Not Found/],	ERSNF%
	XWD	[ASCIZ /SFD Nesting too deep/],	ERLVL%

	ERTBLN==.-ERRTAB
>  ;END IFN FTUUOS
SUBTTL	SETREF  -  Setup reference name for file

;SETREF IS CALLED TO SETUP THE REFERENCE NAME FOR THE CURRENT FILE.
;	THIS NAME IS PRIMARILY USED FOR THE HEADER PAGES.
;CALL:
;	PUSHJ P,SETREF
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
SETREF:	SETZB	S1,S2			;CLEAR TWO REGS
	DMOVEM	S1,J$DRNM(J)		;AND CLEAR REF NAME
	DMOVEM	S1,J$DREX(J)		;CLEAR REF EXTENSION
	MOVE	S1,J$FWCL(J)		;GET FORMS WIDTH CLASS
	MOVEM	S1,J$DRBS(J)		;AND SAVE AS BLOCKSIZE FOR HEADER

	SKIPN	S1,.FPFR1(E)		;IS THERE A /REPORT?
	JRST	SETR.1			;NO, CONTINUE
	MOVE	S2,.FPFR2(E)		;YES, GET THE SECOND HALF
	MOVEM	S1,J$DRNM(J)		;STORE FIRST HALF
	MOVEM	S2,J$DREX(J)		;AND SECOND HALF
	POPJ	P,			;AND RETURN

SETR.1:	LOAD	S1,.FPINF(E),FP.SPL  	;GET SPOOL BIT
	JUMPE	S1,SETR.2		;AND JUMP IF NOT SPOOLED
	SKIPN	S1,J$DUUO+.RBSPL(J)  	;GET SPOOLED NAME
	JRST	SETR.2			;NONE, USE REAL FILENAME
	MOVEM	S1,J$DRNM(J)		;STORE THE NAME
	POPJ	P,			;AND RETURN

SETR.2:	MOVE	S1,J$DUUO+.RBNAM(J)  	;GET FILE NAME
	MOVEM	S1,J$DRNM(J)		;AND SAVE IT
	HLLZ	S1,J$DUUO+.RBEXT(J)  	;AND THE EXTENSION
	MOVEM	S1,J$DREX(J)		;SAVE IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS
IFN FTJSYS,<
SETREF:	SETZB	S1,S2			;CLEAR SOME REGS
	DMOVEM	S1,J$DRNM(J)		;CLEAR THE REF NAME
	DMOVEM	S1,J$DREX(J)		;CLEAR THE REF EXTENSION
	MOVE	S1,J$FWCL(J)		;START WITH THE WIDTH CLASS
	MOVEM	S1,J$DRBS(J)		;AS THE BLOCK SIZE

	SKIPN	S1,.FPFR1(E)		;IS THERE A /REPORT?
	JRST	SETR.1			;NO, CONTINUE
	MOVE	S2,.FPFR2(E)		;YES, GET SECOND HALF
	MOVEM	S1,J$DRNM(J)		;SAVE THE FIRST HALF
	MOVEM	S2,J$DREX(J)		;SAVE THE SECOND HALF
	POPJ	P,			;AND RETURN

SETR.1:	HRROI	S1,J$DNAM(J)		;GET POINTER TO NAME BLOCK
	MOVE	S2,J$DJFN(J)		;GET THE JFN
	MOVX	T1,1B8			;FILENAME ONLY
	JFNS				;GET IT

	LOAD	S1,.FPINF(E),FP.SPL	;GET THE SPOOL BIT
	JUMPN	S1,SETR.4		;AND JUMP IF SPOOLED
SETR.2:	MOVE	S1,[POINT 7,J$DNAM(J)]	;POINT TO FILENAME
	MOVE	S2,[POINT 6,J$DRNM(J)]	;AND SOME PLACE TO STORE IT
	SETZ	T1,			;AND CLEAR A COUNTER
SETR.3:	ILDB	T2,S1			;GET A CHARACTER
	JUMPE	T2,SETR.7		;JUMP TO GET EXTENSION
	SUBI	T2,40			;CONVERT TO SIXBIT
	IDPB	T2,S2			;AND DEPOSIT IT
	CAIGE	T1,10			;GET 9 YET?
	AOJA	T1,SETR.3		;NO, LOOP
	JRST	SETR.7			;GO GET EXTENSION

;HERE ON A SPOOLED FILE
SETR.4:	MOVE	S1,[POINT 7,J$DNAM(J)]	;POINT TO THE NAME
	MOVE	S2,[POINT 6,J$DRNM(J)]	;AND A PLACE TO STORE IT
	SETZ	T1,			;AND CLEAR A COUNTER

SETR.5:	ILDB	T2,S1			;GET A CHARACTER
	CAIN	T2,"-"			;GOT A DASH?
	JRST	SETR.6			;YES, HAVE TO SKIP 3 OF THEM
	JUMPE	T2,SETR.2		;END, GIVE FULL FILENAME
	JRST	SETR.5			;LOOP
SETR.6:	CAIE	T1,2			;GOT 3 DASHES YET?
	AOJA	T1,SETR.5		;NO, KEEP LOOKING
	SETZ	T1,			;YES, CLEAR T1
	JRST	SETR.3			;AND NOW PICK UP THE NAME


				;"SETREF" IS CONTINUED ON THE NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

SETR.7:	LOAD	S1,.FPINF(E),FP.SPL	;SPOOLED FILE?
	SKIPN	J$DRNM(J)		;IS THE NAME NULL?
	JUMPN	S1,SETR.2		;IF YES TO BOTH, GET SPOOLED NAME
	HRROI	S1,J$DNAM(J)		;POINT TO TEMP EXTENSION BLOCK
	MOVE	S2,J$DJFN(J)		;GET THE JFN
	MOVX	T1,1B11			;EXTENSION ONLY
	JFNS				;GET IT
	MOVE	S1,[POINT 7,J$DNAM(J)]	;ELSE, POINT TO EXTENSION
	MOVE	S2,[POINT 6,J$DREX(J)]	;AND A PLACE TO STORE IT
	SETZ	T1,			;AND CLEAR A COUNTER

SETR.8:	ILDB	T2,S1			;GET A CHARACTER
	JUMPE	T2,SETR.9		;END!!
	SUBI	T2,40			;CONVERT TO 6BIT
	IDPB	T2,S2			;AND STORE IT
	CAIGE	T1,7			;GET 8 YET?
	AOJA	T1,SETR.8		;NO, LOOP

SETR.9:	SKIPN	J$DRNM+1(J)		;.GT. 6 CHAR NAME?
	SKIPE	J$DREX+1(J)		;OR .GT. 6 CHAR EXT?
	SKIPA				;YES, ADJUST THINGS A LITTLE
	POPJ	P,			;NO, JUST RETURN
	DMOVE	S1,J$DREX(J)		;YES, LOAD EXTENSION
	LSHC	S1,-6			;SHIFT OVER SOME
	DMOVEM	S1,J$DREX(J)		;AND STORE IT
	SOS	J$DRBS(J)		;DECREMENT THE BLOCK SIZE
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	Accounting Routines

;	ACTBEG		--		SETUP ACCOUNTING AT JOB-START
;	ACTBFL		--		DO PRE-FILE ACCOUNTING
;	ACTEFL		--		DO POST-FILE ACCOUNTING
;	ACTEND		--		FINISH ACCOUNTING AT JOB-END
;	ACTERR		--		HANDLE ACCOUNTING ERROR


	TOPSEG				;THESE ARE IN THE HISEG
SUBTTL	ACTBEG  -  Routine to setup accounting

;ACTBEG IS CALLED AT THE BEGINNING OF EACH JOB TO SETUP THE ACCOUNTING
;	FOR THE JOB.
;
;CALL:
;	PUSHJ P,ACTBEG
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
ACTBEG:	MOVSI	S1,J$AFNC(J)		;GET ADR,,0
	HRRI	S1,J$AFNC+1(J)		;GET ADR,,ADR+1
	SETZM	J$AFNC(J)		;ZERO FIRST WORD OF ACCT BLOCK
	BLT	S1,J$AEND(J)		;ZERO THE REST
	MOVEI	T1,.FACT		;GET CORRECT DAEMON FUNCTION
	MOVEM	T1,J$AFNC(J)		;AND STORE IT
	MOVNI	T1,1			;GET THIS JOB'S TTY NUMBER
	GETLCH	T1			; ..
	TXNE	T1,GL.CTY		;CTY?
	MOVNI	T1,1			;YES
	GETLIN	T2,			;SEE IF DETACHED
	TLNN	T2,-1			; ..
	MOVNI	T1,2			;YES. FLAG AS DETACHED
	ANDI	T1,7777			;AND DOWN TO 12 BITS
	LSH	T1,6			;AND PUT INTO BITS 18-29
	PJOB	T2,			;GET JOB NUMBER
	HRL	T1,T2			;PUT INTO LH OF T1
	IOR	T1,[FCTHDR]		;OR IN FUNCTION AND LENGTH
	MOVEM	T1,J$AHED(J)		;AND STORE IN FACT BLOCK
	MOVE	S1,J$LDEV(J)		;GET THE PROCESSING DEVICE
	MOVEM	S1,J$ADEV(J)		;AND STORE IT
	HRROI	T1,.GTTIM	 	;GET THE RUNTIME
	GETTAB	T1,			; FROM THE MONITOR
	  SETZ	T1,			;FAILED!!!
	MOVNM	T1,J$ARTM(J)		;-VE TO FACT BLOCK
	HRROI	T1,.GTKCT	 	;GET THE TOTAL KCT'S
	GETTAB	T1,			; FROM THE MONITOR
	  SETZ	T1,			;FAILED!!!
	MOVNM	T1,J$ACTI(J)	 	;STORE -VE (SO ADDB WILL CAUSE SUB)
	HRROI	T1,.GTRCT		;BLOCKS READ
	GETTAB	T1,			; FROM THE MONITOR
	  SETZ	T1,			;FAILED!!!
	TLZ	T1,777700		;CLEAR INCR.
	MOVNM	T1,J$ADRD(J)		;STORE -VE IN BLOCK
	HRROI	T1,.GTWCT		;DISK WRITES
	GETTAB	T1,		 	;ASK THE MONITOR
	  SETZ	T1,			;EGAD!! MUST BE LEVEL C
	TLZ	T1,777700		;CLEAR INCREMENTAL
	MOVNM	T1,J$ADWT(J)		;STORE -VE FOR TESTQ
	LOAD	T1,.EQSEQ(J),EQ.SEQ	;GET THE SEQUENCE NUMBER
	MOVEM	T1,J$ASEQ(J)		;STORE IT
	LOAD	T1,.EQOWN(J)		;GET REQUEST DIRECTORY
	MOVEM	T1,J$APPN(J)		;AND STORE IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS
IFN FTJSYS,<
ACTBEG:	MOVSI	S1,J$AHED(J)		;GET FIRST ADR,,0
	HRRI	S1,J$AHED+1(J)		;MAKE A BLT POINTER
	SETZM	J$AHED(J)		;CLEAR THE FIRST WORD
	BLT	S1,J$AEND(J)		;AND ZERO THE BLOCK
	GJINF				;GET JOB INFORMATION
	DPB	T1,[POINT 9,J$AHED(J),17]  ;STORE JOB NUMBER
	DPB	T2,[POINT 9,J$AHED(J),26]  ;STORE LINE NUMBER
	MOVX	S1,<401B8+J$ALEN>	;LOAD REST OF THE HEADER WORD
	IORM	S1,J$AHED(J)		;STORE IT
;	LOAD	S1,.EQDIR(J),DI.OWN	;GET OWNER
;	MOVEM	S1,J$ADIR(J)		;SAVE IN FACT BLOCK
	GTAD				;GET DATE AND TIME
	MOVEM	S1,J$ADAT(J)		;AND SAVE IT
	MOVX	S1,.FHSLF		;GET FORK HANDLE
	RUNTM				;GET RUNTIME IN MS
	MOVNM	S1,J$ARTM(J)		;AND STORE NEGATED
	MOVE	S1,J$LDEV(J)		;GET PROCESSING DEVICE
	MOVEM	S1,J$ADEV(J)		;SAVE IT
	MOVE	S1,.EQLM1(J)		;GET FORMS
	MOVEM	S1,J$AFRM(J)		;SAVE IT
	POPJ	P,			;RETURN
>  ;END IFN FTJSYS
SUBTTL	ACTBFL  --  Do Pre-file Accounting

ACTBFL:	POPJ	P,
SUBTTL	ACTEFL  --  Do Post-file Accounting

ACTEFL:	POPJ	P,
SUBTTL	ACTEND  -  Routine to do accounting at end-of-job

;ACTEND IS CALLED AT THE END OF A JOB TO DO THE NECESSARY ACCOUNTING
;	FOR THE JOB.
;
;CALL:
;	PUSHJ P,ACTEND
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
ACTEND:	HRROI	T1,.GTTIM	;RUNTIME
	GETTAB	T1,		;GET FROM MONITOR
	  SETZ	T1,		;FAILED???
	ADDB	T1,J$ARTM(J)	;ADD TO -VE START TIME
	IMULI	T1,^D1000	;CONVERT TO MILLI-JIFFIES
	IDIV	T1,JIFSEC	;AND THEN TO MILLI-SECONDS
	MOVEM	T1,J$ARTM(J)	;AND STORE AGAIN
	HRROI	T1,.GTKCT	;GET THE NUMBER OF KCT'S
	GETTAB	T1,		; FROM THE MONITOR
	  SETZ	T1,		;FAILED!!!
	ADDB	T1,J$ACTI(J)	;COMPUTE ELAPSED KCT'S
	IMULI	T1,144		;CONVERT TO CENTI-JIFFIES
	IDIV	T1,JIFSEC	;CONVERT TO CENTI-SECONDS
	MOVEM	T1,J$ACTI(J)	;AND STORE
	HRROI	T1,.GTRCT	;GET THE NUMBER OF READS
	GETTAB	T1,		; FROM THE MONITOR
	  SETZ	T1,		;FAILED...
	TLZ	T1,777700	;CLEAR INCREMENTAL
	ADDM	T1,J$ADRD(J)	;GET ELAPSED READS
	HRROI	T1,.GTWCT	;GET THE NUMBER OF DISK WRITES
	GETTAB	T1,		; FROM THE MONITOR
	  SETZ	T1,		;FAILED,,,
	TLZ	T1,777700	;CLEAR INCREMENTAL
	ADDM	T1,J$ADWT(J)	;COMPUTE ELAPSED WRITES
	HRROI	T1,.GTLOC	;WHERE WE ARE
	GETTAB	T1,		;ASK THE MONITOR
	  SETZ	T1,		;WE ARE LOST DON'T SWEAT
	HRLZ	T2,T1		;SAVE OUR PLACE
	MOVE	T1,[%CNSER]	;APR SERIAL NUMBER (MASTER IF MORE
	GETTAB	T1,		; THAN ONE IN M/S)
	  SETZ	T1,		;EGAD!!
	HRR	T2,T1		;COPY APRSN
	MOVSI	T1,'LP '	;QUEUE NAME
	IOR	T1,T2		;MUSH TOGETHER
	MOVEM	T1,J$AQUE(J)	;SAVE FOR FACT ENTRIES
	SKIPN	ACTFLG		;CAN WE CALL THE DAEMON?
	POPJ	P,		;NO, RETURN
	MOVSI	N,14		;GET THE BLOCK LENGTH IN LH
	HRRI	N,J$AFNC(J)	;AND THE ADDRSS IN RH
	DAEMON	N,		;ACTIVATE THE DAEMON
	  JFCL			;IGNORE THE ERROR
	POPJ	P,		;AND RETURN
>  ;END IFN FTUUOS
IFN FTJSYS,<
ACTEND:	MOVX	S1,.FHSLF	;LOAD FORK HANDLE
	RUNTM			;GET RUNTIME
	ADDM	S1,J$ARTM(J)	;STORE IT
	SKIPN	ACTFLG		;ARE WE DOING ACCT?
	POPJ	P,		;NO, RETURN
;EFACT STUFF
	POPJ	P,		;AND RETURN
>  ;END IFN FTJSYS
SUBTTL COMMAND TABLES AND DISPATCHER
;FLAG BITS
	BIT	T2,IOACT,	;DISK FILE MUST BE OPEN

;COMMANDS

DEFINE 	NAMES,<
	C	EXIT,XITCOM,0
	C	MESSAGE,MESSGE,0
	C	STOP,STOP,0
	C	KILL,KILL,0
	C	FORMS,FRMCOM,0
	C	GO,GO,0
	C	ST,START,0
	C	START,START,0
	C	RESET,RESETC,0
	C	REQUEU,REQUE,0
	C	CURRENT,CURDEF,0
	C	CHKPNT,TAKCHK,IOACT
	C	PAUSE,PAUSE,0
	C	LOCK,SETLOK,0
	C	UNLOCK,CLRLOK,0
	C	WHAT,WHAT,0
	C	MLIMIT,MLIMIT,0
	C	LIMIT,LIMIT,0
	C	NEXT,NXTCOM,0	
	C	HELP,HELP,0
	C	FREEZE,FREEZE,0
	C	UNFREE,UNFREE,0
	C	REPRIN,REPRNT,IOACT
	C	SKPFIL,SKPFIL,IOACT
	C	SKPCOP,SKPCOP,IOACT
	C	SUPPRE,SUPPRE,IOACT
	C	NOSUPP,NOSUPR,IOACT
	C	BACKSP,BACKSP,IOACT
	C	FORWAR,FORWAR,IOACT
IFN FTUUOS,<
	C	ALIGN,ALIGN,0
>  ;END IFN FTUUOS
>  ;END OF NAMES MACRO
;TABLES
DEFINE	C(A,B,C),<
	XALL
	<SIXBIT	/A/>
	SALL
>
	TOPSEG
COMTAB:	NAMES

DEFINE	C(A,B,D),<
	EXP	D+B
>
DSPTAB:	NAMES
DISPL=.-DSPTAB
	SALL			;BACK TO SHORT FORM

	
UUMASK==TELOPR!TELUSR!TELUSR!TNOACT	;UUO BITS
						;ALL IN THE LH

;HERE WHEN A COMMAND HAS BEEN TYPED

COMIN:	PUSHJ	P,SETNL		;SETUP FOR A NEW LINE
	MOVX	T1,UUMASK	;BITS TO SAVE AROUND COMMAND
	AND	T1,S		;EXTRACT THE BITS
	TXZ	S,UUMASK	;CLEAR THE BITS
	MOVEM	T1,UUSAVE#	;SAVE THEM.
	PUSHJ	P,SIXIN		;GET COMMAND
	  PJRST	CUE		;NULL COMMAND
	CAMN	T1,['MONITO']	;EMERGENCY EXIT?
	JRST	DOEXIT		;YES, DO IT
	MOVE	T2,T1		;COPY COMMAND
	SETO	T3,		;SET MASK TO ONES
	LSH	T3,-6		;SHIFT MASK
	LSH	T2,6		;SHIFT OFF 1 CHAR
	JUMPN	T2,.-2		;ANYTHING LEFT?
	MOVEI	N,0		;CLEAR FLAGS
	MOVSI	T2,-DISPL	;SET UP LENGTH OF TABLE
COMLP:	MOVE	T4,COMTAB(T2)	;GET A COMMAND
	CAMN	T4,T1		;AN EXACT MATCH?
	JRST	COMFND		;YES. THIS IS IT
	TDZ	T4,T3		;CLEAR PART NOT TYPED
	CAME	T4,T1		;PARTIAL MATCH
	JRST	COMNEQ		;NO. TRY NEXT
	TLOE	N,1		;FIRST OCCURENCE
	JRST	NOCOM		;NO. CAN'T BE UNIQUE
	HRR	N,T2		;YES. SAVE INDEX
COMNEQ:	AOBJN	T2,COMLP	;ANY MORE COMMANDS
	TLNN	N,-1		;NO. EXACTLY 1 MATCH?
	JRST	NOCOM		;NO, LOSE!
	HRR	T2,N		;YES, COPY INDEX
COMFND:	MOVE	T2,DSPTAB(T2)		;GET ADDRESS AND BITS

COMCK2:	TXNN	T2,IOACT		;DO WE HAVE TO BE IOACTIVE?
	JRST	COMCK3			;NO, GO ON
	TXNN	S,DSKOPN		;YES, ARE WE?
	JRST	CMSG2C			;NO, GIVE A MESSAGE

COMCK3:	PUSHJ	P,(T2)			;DISPATCH THE COMMAND
	JRST	CUE			;WAKE UP THE OPERATOR

NOCOM:	TELL	OPR,%%URC		;NOT UNIQUE
	PJRST	CUE			;RETURN


CMSG2C:	PUSHJ	P,NOTBSY		;TELL HIM WE'RE NOT BUSY

CUE:	PUSHJ	P,EAT			;EAT THE REST OF THE LINE
	TXNE	S,RUNB			;IF RUN IS ON
	TELL	OPR,EXCLPT		; TYPE A !
	TXNN	S,RUNB			;IF RUN IS OFF
	TELL	OPR,STAR		; TYPE A *
	TDZ	S,[UUMASK]		;CLEAR SAVED BITS
	IOR	S,UUSAVE		;PUT BACK ANY NEEDED
	TXNN	S,RUNB			;ARE WE RUNNABLE?
	JRST	COMIN			;NO, GET NEXT COMMAND
	POPJ	P,


NOTBSY:	MOVEI	T1,%%LII		;WE ARE IDLE
	TXNN	S,STARTD		;BUT IF WE'RE NOT STARTED,
	MOVEI	T1,%%WFS		;TELL HIM THAT INSTEAD
	TELL	OPR,(T1)		;GIVE SOME MESSAGE
	POPJ	P,			;AND RETURN
SUBTTL	Operator Commands -- START

;SUBROUTINE TO SELECT OUTPUT DEVICE AND START SPOOLER
;CALL WITH
;	PUSHJ	P,START
;	RETURN HERE
;
START:	TXNN	S,STARTD		;HAVE WE BEEN STARTED ALREADY?
	JRST	STAR.3			;NO, CONTINUE
	SKIPN	XITFLG			;IS THERE A PENDING EXIT?
	SKIPE	RSTFLG			;OR A PENDING RESET?
	JRST	STAR.1			;YES, CLEAR IT
	TXZN	S,PAUSEB		;NO, PENDING PAUSE?
	JRST	STAR.2			;NO, GIVE AN ERROR
STAR.1:	TELL	OPR,%%CPC		;TELL HIM
	SETZM	XITFLG			;CLEAR EXIT
	SETZM	RSTFLG			;AND RESET
	POPJ	P,			;AND RETURN

STAR.2:	TELL	OPR,%%LAS		;TELL HIM
	POPJ	P,			;AND RETURN

STAR.3:	PUSHJ	P,SIXIN			;GET A DEVICE NAME
	  MOVX	T1,DEFLPT		;USE THE DEFAULT
	MOVEM	T1,J$LGNM(J)		;SAVE AS GIVEN NAME
	PUSHJ	P,OUTGET		;OPEN THE DEVICE

STAR.4:	CAIE	C,"="			;DID HE SAY DEV=DEV?
	  JRST	STAR.5			;NO SCAN AHEAD
	PUSHJ	P,SIXIN			;YES, GET THE DEVICE
	  MOVSI	T1,'LPT'		;DEFAULT DEVICE
	MOVEM	T1,J$LSDV(J)		;STORE IT
	JRST	STAR.6			;AND CONTINUE

STAR.5:	PUSHJ	P,SIXIN			;SCAN AHEAD
	  JFCL				;THAT'S OK
	CAIN	C,"="			;FIND AN EQUAL?
	JRST	STAR.4			;YES, LOOP AROUND
STAR.6:	HLRZ	T1,J$LSDV(J)		;GET SCHEDULING DEVICE
	CAIN	T1,'LPT'		;IS IT A LPT?
	JRST	STAR.7			;YES, CONTINUE
	PUSHJ	P,EAT			;CLEAR TYPE AHEAD
	TELL	OPR,[ASCIZ /Specified device is not a LPT
What device do you want to schedule jobs for: /]
	PUSHJ	P,SETNL			;SET NEW LINE
	PUSHJ	P,SIXIN			;AND GET A DEVICE
	  JFCL				;IGNORE THIS
	MOVEM	T1,J$LSDV(J)		;STORE IT
	JRST	STAR.6			;AND LOOP

STAR.7:	PUSHJ	P,EAT			;EAT THE REST OF THE LINE
	ON	S,STARTD!RUNB		;FLAG THAT WE ARE STARTED
	PUSHJ	P,SETHEL		;SETUP HELLO BLOCK
	MOVEI	T1,MSGBLK		;LOAD ADR OF BLOCK
	PJRST	SNDQSR##		;AND SEND IT
SUBTTL	Operator Commands -- ALIGN

IFN FTUUOS,<

;SUBROUTINE TO ALLOW FORMS TO BE SET UP
;CALL WITH:
;	PUSHJ	P,ALIGN
;	HERE WHEN DONE
;
ALIGN:	TXNN	S,STARTD	;HAVE WE BEEN STARTED
	JRST	[TELL OPR,%%WFS	;NO TELL HIM
		 POPJ P,]	;AND RETURN
ALIGN1:	PUSHJ	P,SIXIN		;GET FILENAME
	  MOVE	T1,J$FALI(J)	;USE DEFAULT
	MOVE	P1,T1		;SETUP FOR LOOKUP
	MOVSI	P2,'ALP'	;EXTENSION .ALP
	CLEARB	P3,P4		;...
	SETZ	T1,		;ASCII MODE
	MOVEI	T3,J$ABRH(J)	;BUFFERS FOR ALIGN
	MOVSI	T2,'DSK'	;TRY DSK FIRST
ALOPN:	OPEN	ALP,T1		;INIT THE DEVICE
	  HALT	.		;???
	LOOKUP	ALP,P1		;LOOK FOR FILE
	  SKIPA			;SKIP IF LOOKUP FAILED
	JRST	ALGOT		;GOT IT!!

	CAMN	T2,[SIXBIT /SYS/]  ;DID WE LOOK ON SYS?
	JRST	[MOVE T1,P1	;GET FILE NAME
		 TELL OPR,%%CFA
		 POPJ P,]	;GUESS WE CAN'T FIND IT
	MOVSI	T2,'SYS'	;NO, TRY SYS
	JRST	ALOPN		;AND LOOP

ALGOT:	PUSHJ	P,M$ACQP##	;GET A PAGE
	MOVEM	AP,J$APAG(J)	;SAVE PAGE NUMBER
	PG2ADR	AP		;MAKE AN ADDRESS
	EXCH	AP,.JBFF	;SAVE AS JOBFF
	INBUF	ALP,2		;ALLOCATE BUFFERS
	MOVEM	AP,.JBFF	;RESTORE JOBFF
	OUTPUT	LPT,		;CLEAN UP
	TELL	OPR,STAR	;TELL THE OP TO DO SOMETHING
	MOVE	T1,J$FALC(J)	;GET LOOP COUNTER
ALNXT:	SOSGE	T1		;COUNT DOWN
	JRST	ALDIE		;DONE, RETURN
	USETI	ALP,1		;REWIND THE FILE
	SKPINL			;ANYTHING THERE?
	JRST	ALOOP		;NO, PRINT FILE AGAIN
	JRST	ALDIE		;YES, THAT'S ALL

ALOOP:	SOSLE	J$ABCT(J)	;ROOM IN BUFFERS
	JRST	ALDB		;YES--SHOVE IT
	IN	ALP,		;READ SOME FILE
	  JRST	ALDB		;NO ERRORS, CONTINUE
	STATO	ALP,IO.EOF	;IS IT END OF FILE?
	  JRST	ALDIE		;NO, STOP
	OUTPUT	LPT,		;DUMP THE PARTIAL BUFFER
	MOVE	T2,J$FALS(J)	;YES, GET SLEEP TIME
	SLEEP	T2,		;SLEEP
	  JFCL
	JRST	ALNXT		;LOOP

ALDB:	ILDB	C,J$ABPT(J)	;GET THE CHAR
	PUSHJ	P,DEVOUT	;PRINT THE CHAR
	JRST	ALOOP		;NOT SAVED
ALDIE:	RELEAS	ALP,		;GIVE UP THE DISK
	MOVE	AP,J$APAG(J)	;GET THE PAGE NUMBER BACK
	PUSHJ	P,M$RELP##	;RELEAS IT
	POPJ	P,		;AND RETURN

>  ;END IFN FTUUOS
SUBTTL	Operator Commands  --  HELP - MLIMIT
;SUBROUTINE TO TYPE THE HELP TEXT
;CALL WITH:
;	PUSHJ	P,HELP
;	RETURN HERE
;
HELP:	TELL	OPR,[ASCIZ /
Available Commands Are:
/]
	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	MOVSI	P1,-DISPL		;SETUP AOBJN POINTER
	SETZ	P2,			;AND COMMAND COUNTER IS CLEAR

HELP.1:	MOVEI	C,.CHTAB		;LOAD A TAB
	SKIPE	P2			;FIRST COMMAND OF A LINE?
	PUSHJ	P,SEND			;NO, TYPE THE COMMA
	MOVE	T1,COMTAB(P1)		;GET THE COMMAND
	CAMN	T1,[SIXBIT /ST/]
	MOVE	T1,[SIXBIT /MONITO/]
	PUSHJ	P,SIXOUT		;TYPE IT
	CAIGE	P2,6			;TYPED SEVEN?
	AOJA	P2,HELP.2		;NO, KEEP GOING
	TELL	OPR,CRLF		;YES, TYPE A CRLF
	SETZ	P2,			;CLEAR THE COUNTER
HELP.2:	AOBJN	P1,HELP.1		;AND LOOP
	TELL	OPR,CRLF		;AND A FINAL CRLF
	POPJ	P,			;RETURN WHEN DONE


;SUBROUTINE TO SET MAX OUTPUT LIMIT FOR ALL JOBS
; ANY JOB OVER LIMIT WILL SIT IN QUEUE.
;CALL WITH:
;	PUSHJ	P,MLIMIT
;	RETURN HERE
;
MLIMIT:	PUSHJ	P,DECARG		;GET N
	  JRST	BADNBR			;BAD NUMBER
	JUMPE	N,LIMERR		;CAN'T BE ZERO
	MOVEM	N,J$XMLM(J)		;STORE AWAY
	PJRST	SNDSTC			;SEND A STATUS CHANGE AND RETURN
SUBTTL	Operator Commands  --  EXIT

;SUBROUTINE TO EXIT FROM SPOOLER
;CALL WITH:
;	PUSHJ	P,XITCOM
;	RETURN ONLY IF ERROR
;
XITCOM:	SETOM	XITFLG			;SET THE EXIT FLAG
	TXNN	S,BUSY			;ARE WE BUSY?
	JRST	DOEXIT			;NO, GO EXIT
	TELL	OPR,%%LWE		;YES, MAKE IT PEND
	POPJ	P,			;TELL OPR AND RETURN

DOEXIT:	PUSHJ	P,SETHEL		;SETUP HELLO BLOCK
	MOVX	T1,HELBYE!HELSTC;GOODBYE+STATUS CHANGE
	IORM	T1,MSGBLK+HEL.ST	;STORE THEM
	MOVEI	T1,MSGBLK		;ADDRESS OF BLOCK
	PUSHJ	P,SNDQSR##		;SEND IT
	RESET				;CLEAR ALL DEVICE PROBLEMS
IFN FTUUOS,<
	EXIT				;AND BACK TO MONITOR
>  ;END IFN FTUUOS
IFN FTJSYS,<
	HALTF				;AND BACK TO MONITOR
>  ;END IFN FTJSYS
SUBTTL	Operator Commands  --  LIMIT


;SUBROUTINE TO CHANGE LIMIT FOR THIS JOB ONLY
;CALL WITH:
;	PUSHJ	P,LIMIT
;	RETURN HERE
;
LIMIT:	TXNN	S,BUSY			;ARE WE BUSY?
	PJRST	NOTBSY			;NO, TELL HIM AND RETURN
	PUSHJ	P,DECARG		;GET ARGUMENT
	  JRST	BADNBR			;OOPS
	JUMPE	N,LIMERR		;CAN'T BE ZERO
	MOVEM	N,J$RLIM(J)		;STORE
	STAMP	LPOPR			;STAMP THE LOG
	TELL	LOG,%%OCL		;AND TELL THE LOG FILE
	POPJ	P,

LIMERR:	TELL	OPR,%%ICA		;ILLEGAL COMMAND ARGUMENT
	POPJ	P,


BADNBR:	TELL	OPR,BADNMS
	POPJ	P,
SUBTTL	Operator Commands  --  FORMS

;SUBROUTINE TO DECLARE A NEW TYPE OF FORMS TO BE MOUNTED
;CALL FROM COMAND DISPATCH
;

FRMCOM:	PUSHJ	P,SIXIN			;GET SPECIFIED TYPE
	  MOVX	T1,FRMNOR		;USE NORMAL BY DEFAULT
	TXNN	S,STARTD		;IS LPTSPL STARTED?
	JRST	FRMC.1			;NO, JUST SAVE FORMS AND RETURN
	MOVEM	T1,J$FSFM(J)		;SAVE AS SCHED TYPE
	PUSHJ	P,SNDSTC		;TELL QUASAR
	PJRST	OPNFRM			;RE-READ LPFORM.INI AND RETURN

FRMC.1:	MOVEM	T1,J$FORM(J)		;STORE FORMS TYPE
	MOVEM	T1,J$FSFM(J)		;AND SCHED FORMS TYPE
	POPJ	P,			;AND RETURN
SUBTTL	Operator Commands  --  KILL

;SUBROUTINE TO KILL THE CURRENT JOB
;
;CALL	KILL	-	ON OPERATOR KILL MESSAGE
;	UKILL	-	ON ABORT MESSAGE FROM USER

KILL:	SKIPA	P1,[EXP OPRKIL]		;LOAD ADR OF ROUTINE AND SKIP
UKILL:	MOVEI	P1,USRKIL		;LOAD ADDRESS

	TXNN	S,BUSY			;ARE WE DOING A JOB?
	PJRST	NOTBSY			;NO, TELL HIM AND RETURN
	TXNN	S,MNTBIT		;NO, ARE WE IN MOUNT WAIT?
	JRST	KILL2			;NO, JUST DO THE REGULAR THINGS
	MOVE	T1,J$FPFM(J)		;YES, GET PREVIOUS FORMS TYPE
	MOVEM	T1,J$FORM(J)		;SAVE A CURRENT FORMS
	MOVEM	T1,J$FSFM(J)		;SAVE AS SCHEDULING FORMS
	PUSHJ	P,SNDSTC		;AND TELL QUASAR
	PUSHJ	P,FRMINI		;INITIALIZE FORMS PARAMTERS

KILL2:	TXNE	S,DSKOPN		;ARE WE PRINTING A FILE?
	PUSHJ	P,OUTFLS		;YES, FLUSH ALL OUTPUT
	PUSHJ	P,(P1)			;CALL TYPE DEPENDENT ROUTINE
KILL3:	OFF	S,FFSEEN		;TURN OFF FF FLAG
	PUSHJ	P,SETEOF		;CAUSE AN EOF TO HAPPEN
	ON	S,ABORT			;AND SET ABORT BIT
	JRST	GO			;GO!


;HERE FOR OPERATOR KILL STUFF
OPRKIL:	TXNN	S,BANDUN		;HAVE WE PRINTED A BANNER?
	PUSHJ	P,JOBHDR		;NO, DO SO
	STAMP	LPOPR			;STAMP THE LOG
	TELL	LOG,%%KBO		;PUT IN A MESSAGE
	POPJ	P,			;AND RETURN

;HERE FOR USER KILL STUFF
USRKIL:	MOVE	S1,MESSAG		;GET ADDRESS OF MESSAGE
	MOVE	T1,ABO.CD(S1)		;GET ABORT CODE
	CAIN	T1,ABOOPR		;ABORT BY OPR?
	JRST	OPRKIL			;YES, SWITCH GEARS
	STAMP	LPMSG			;STAMP THE LOG
	TELL	LOG,%%CBU		;KILLED BY USER
	MOVE	T1,ABO.ID(S1)		;GET ID OF KILLER
	PUSHJ	P,TYPUID		;TYPE IT ON THE LOG
	TELL	LOG,CRLF		;PLACE A CRLF
	POPJ	P,			;AND RETURN
SUBTTL	Operator Commands  --  PAUSE - STOP - GO


PAUSE:	TXNE	S,BUSY			;PAUSE=STOP IFN BUSY
	TXOA	S,PAUSEB		;SET PAUSE BIT AND SKIP
STOP:	OFF	S,RUNB			;TURN OFF THE RUN BIT
	PJRST	SNDSTC			;STOP SCHEDULING AND RETURN

GO:	TXNE	S,STARTD
	ON	S,RUNB
	OFF	S,PAUSEB!MNTBIT
	PJRST	SNDSTC			;START SCHEDULING AGAIN


;HERE AT END-OF-JOB WHEN WE MUST PAUSE
DOPAUS:	TELL	OPR,[ASCIZ /Spooler is PAUSE'ing ON $, type GO to continue
/]
	JRST	STOP			;AND GO STOP
SUBTTL	Operator Commands  --  REPRINT - SKPCOPY - SKPFILE

;REPRINT -- ROUTINE TO START THE CURRENT COPY OF THE CURRENT
;	FILE OVER AGAIN.
;CALL WITH:
;	PUSHJ	P,REPRNT
;	RETURN HERE
;
REPRNT:	PUSHJ	P,OUTFLS		;FLUSH OUTPUT
	AOS	J$XCOP(J)		;INCREMENT COPY COUNT
	STAMP	LPOPR			;STAMP THE LOG
	MOVE	N,J$RNCP(J)		;GET COPY-1
	ADDI	N,1			;GET COPY #
	TELL	LOG,%%ORC		;AND A MESSAGE
	MOVN	T1,J$RNPP(J)		;GET -VE PAGES PRINTED THIS COPY
	ADDM	T1,J$APRT(J)		;AND DECREMENT THE TOTAL PRINTED
	SOS	J$RNCP(J)		;AND DECREMENT COPIES PRINTED
	JRST	SKPCP1			;AND MAKE AN END-OF-FILE


;SKPCOP -- ROUTINE TO START THE NEXT COPY OF THE CURRENT FILE
;CALL WITH:
;	PUSHJ P,SKPCOP
;	RETURN HERE
;
SKPCOP:	PUSHJ	P,OUTFLS		;FLUSH OUTPUT
	STAMP	LPOPR			;STAMP THE LOG
	MOVE	N,J$RNCP(J)		;GET COPY NUMBER-1
	ADDI	N,1			;MAKE IT COPY NUMBER
	TELL	LOG,%%OSC		;AND TELL HIM
SKPCP1:	PUSHJ	P,SETEOF		;CAUSE AN EOF TO HAPPEN
	POPJ	P,			;AND RETURN



;SKPFIL -- ROUTINE TO START THE NEXT FILE
;CALL WITH:
;	PUSHJ	P,SKPFIL
;	RETURN HERE
;
SKPFIL:	PUSHJ	P,OUTFLS		;FLUSH OUTPUT
	STAMP	LPOPR			;STAMP THE LOG
	TELL	LOG,%%OSF		;AND TELL HIM
	PUSHJ	P,SETEOF		;CAUSE AN EOF
	SETZM	J$XCOP(J)		;CAUSE END OF COPIES LOOP
	POPJ	P,			;AND RETURN
SUBTTL	Operator Commands  --  (UN)LOCK - (UN)FREEZE


;SUBROUTINES TO SET OR CLEAR BOTH PAUSE AND PAUSE LOCK
;CALL WITH:
;	PUSHJ	P,SETLOK (CLRLOK)
;	RETURN HERE
;
SETLOK:	TXOA	S,PLOCK			;SET THE LOCK
CLRLOK:	TXZ	S,PLOCK			;CLEAR THE LOCK
	POPJ	P,			;AND RETURN


;SUBROUTINES TO SET AND CLEAR FORMS LOCK.  CALLED ON THE FREEZE AND
;UNFREEZE COMMANDS.
;CALL WITH
;	PUSHJ P,FREEZE (OR UNFREE)
;	RETURN HERE
;
FREEZE:	TXOA	S,FROZE			;TURN ON FROZE BIT
UNFREE:	OFF	S,FROZE			;TURN OFF FROZE BIT
	PJRST	SNDSTC			;SEND A STATUS CHANGE AND RETURN
SUBTTL	Operator Commands  --  NEXT

;SUBROUTINE TO FORCE JOB #N TO BE RUN NEXT
;CALL WITH:
;		PUSHJ	P,NXTCOM
;		RETURN HERE
;
NXTCOM:	PUSHJ	P,DECARG	;READ A DECIMAL ARGUMENT
	  PJRST	BADNBR		;OOPS...
	MOVEM	N,NXTJOB	;SAVE FOR LATER
	PJRST	SNDSTC		;AND SEND A STATUS CHANGE
SUBTTL	Operator Commands  --  REQUEUE

;SUBROUTINE TO REQUEUE AN ENTRY
;CALL WITH:
;	PUSHJ	P,REQUE
;
REQUE:	TXNN	S,BUSY			;ARE WE BUSY?
	PJRST	NOTBSY			;NO, RETURN
	TXZN	S,MNTBIT		;ARE WE IN MOUNT WAIT?
	JRST	REQUE0			;NO, SKIP THIS STUFF
	MOVE	T1,J$FPFM(J)		;YES, LOAD OLD FORMS
	MOVEM	T1,J$FORM(J)		;AND STORE
	MOVEM	T1,J$FSFM(J)		;SAVE AS SCHEDULING FORMS
	ON	S,RQB!RUNB		;TURN ON REQUE AND RUN
	PUSHJ	P,SNDSTC		;AND SEND A STATUS CHANGE
	PUSHJ	P,FRMINI		;AND INITALIZE PARAMETERS
REQUE0:	PUSHJ	P,SETCHP		;SETUP CHECKPOINT INFO
	MOVEI	T1,5			;/AFTER:5 IS DEFAULT
	MOVEM	T1,MSGBLK+REQ.AF	;STORE IT
	MOVX	T1,CKFREQ		;GET REQUEUE BIT
	MOVEM	T1,MSGBLK+REQ.IN+CKFLG	;STORE IT

REQUE1:	PUSHJ	P,DOSW			;SCAN FOR A /
	TXNE	S,TTYBRK		;HIT EOL?
	JRST	REQUE2			;YES, DONE
	ACTCHR	A,RQAFT			;AFTER
	ACTCHR	H,RQHOLD		;HOLD
	ACTCHR	T,RQTOP			;TOP OF JOB
	ACTCHR	B,RQBACK		;BACK N UNITS
	ACTCHR	F,RQFOR			;FORWARD N UNITS
	TELL	OPR,BADSW		;BAD SWITCH
	POPJ	P,			;PUNT THE COMMAND
RQHOLD:	MOVEI	T1,^D720		;12 HOURS (720 MINUTES)
	MOVEM	T1,MSGBLK+REQ.AF	;NEW AFTER PARAM
	JRST	REQUE1			;DO NEXT SWITCH
RQBACK:	PUSHJ	P,GTARGU		;GET ARGUMENT
	MOVN	N,N			;BACK
	SKIPA				;THE REST IS LIKE /FORWARD
RQFOR:	PUSHJ	P,GTARGU		;GET THE ARGUMENT
	ADDM	N,MSGBLK+REQ.IN+CKPAG	;ADD TO CURRENT POSITION
	JRST	REQUE1			;AND LOOP
RQAFT:	PUSHJ	P,FNDELM		;GET THE DELIMITER
	  SKIPA				;NONE
	PUSHJ	P,DECARG		;GET THE NUMBER
	  MOVEI	N,^D30			;ASSUME 30 MIN.
	MOVEM	N,MSGBLK+REQ.AF		;STORE AWAY
	JRST	REQUE1			;LOOP FOR MORE COMPLEX STUFF
RQTOP:	SETZM	MSGBLK+REQ.IN+CKFIL	;CLEAR THE FILE WORD
	SETZM	MSGBLK+REQ.IN+CKCOP	;CLEAR THE COPIES WORD
	SETZM	MSGBLK+REQ.IN+CKPAG	;CLEAR THE PAGES WORD
	SETZM	MSGBLK+REQ.IN+CKTPP	;CLEAR THE TOTAL PAGES WORD
	JRST	REQUE1			;LOOK FOR MORE SWITCHES

REQUE2:	PUSHJ	P,RIDLOG		;RELEASE THE LOG FILE
	STAMP	LPOPR			;TELL USER WHAT OPR DID
	TELL	LOG,%%RBO		;SEND THE REQUEUE MESSAGE
	MOVX	T1,<REQ.SZ,,.QOREQ>	;GET MESSAGE HEADER
	MOVEM	T1,MSGBLK		;STORE IT
	MOVEI	T1,MSGBLK		;ADR OF REQUEUE BLOCK
	PUSHJ	P,SNDQSR##		;SEND IT TO QUASAR
	PUSHJ	P,CLSFIL		;AND CLOSE INPUT FILE
	PUSHJ	P,EAT			;EAT TILL EOL
	TELL	OPR,EXCLPT		;AND GIVE OPR THE PROMPT
	JRST	ENDJOB			;AND GO FINISH UP

GTARGU:	PUSHJ	P,FNDELM		;GET HTE DELIMITER
	  JFCL				;NONE DON'T SWEAT
	PUSHJ	P,DECARG		;GET A DECNAL NUMBER
	  JFCL				;LOSS DO NOT WORRY
	POPJ	P,			;RETURN
SUBTTL	Operator Commands  --  WHAT

;SUBROUTINE TO GIVE CURRENT STATUS OF SPOOLER

WHAT:	TXNN	S,STARTD		;ARE WE STARTED?
	PJRST	CURINF			;NO, JUST GIVE USEFUL INFO
	TXNN	S,BUSY			;DO WE HAVE A JOB?
	JRST	WHATC			;NO, SKIP ALLLLLLL OF THIS
WHATA:	LOAD	T1,.EQJOB(J)		;GET JOB NAME
	LOAD	N,.EQSEQ(J),EQ.SEQ	;AND SEQUENCE NUMBER
	TELL	OPR,[ASCIZ \$:+/SEQ:#/USER:]  \]

	MOVE	N,J$APRT(J)		;GET AMOUNT PRINTED
	TELL	OPR,WHAT6		;AND TYPE AMOUNT PRINTED
	MOVE	N,J$RLIM(J)		;GET LIMIT
	TELL	OPR,WHAT7		;AND TYPE IT

	TXNN	S,DSKOPN		;IS A FILE OPEN?
	JRST	WHATB			;NO, SKIP THIS STUFF
	TELL	OPR,WHAT10		;TYPE THE FILE NAME
	LOAD	T2,.FPINF(E),FP.DEL	;GET THE DISPOSITION
	MOVX	T1,'PRESER'		;ASSUME PRESERVED
	SKIPE	T2			;SKIP IF PRESERVED
	MOVX	T1,'DELETE'		;NO, DELETE
	LOAD	T2,.FPINF(E),FP.SPL	;GET SPOOL BIT
	SKIPE	T2			;IS IT SET?
	MOVX	T1,'SPOOL '		;YES, TELL HIM
	TELL	OPR,WHAT11		;AND PRINT IT
	TXNE	S,SUPRES		;ARE WE SUPPRESSED?
	TELL	OPR,[ASCIZ ?/SUPPRESS?]
	MOVE	N,J$RNCP(J)		;GET NUMBER OF COPIES PRINTED
	AOS	N			;GET CURRENT COPY NUMBER
	TELL	OPR,WHAT8		;AND PRINT IT
	LOAD	N,.FPINF(E),FP.FCY	;GET TOTAL NUMBER OF COPIES
	TELL	OPR,WHAT9		;PRINT IT
	MOVE	N,J$RNPP(J)		;GET NUMBER OF PAGES PRINTED
	TELL	OPR,WHAT12		;AND TEEL THE OPERATOR

WHATB:	SKIPN	T1,.EQNOT(J)		;IS THERE A USER NOTE?
	JRST	WHATC			;NO, CONTINUE ON
	TELL	OPR,[ASCIZ /![User note: +/]
	MOVE	T1,.EQNOT+1(J)		;GET THE SECOND HALF
	TELL	OPR,[ASCIZ /+!]
/]

WHATC:	TXNN	S,BUSY			;ARE WE BUSY?
	TELL	OPR,%%LII		;NO, TELL HIM
	MOVE	T1,J$FORM(J)		;LOAD THE FORMS TYPE
	TXNE	S,MNTBIT		;ARE WE IN MOUNT WAIT?
	TELL	OPR,%%WFF		;YES, TELL HIM
	PJRST	CURINF			;AND GIVE THE REST OF CURRENT INFO
SUBTTL	Operator Commands  --  CURRENT

;SUBROUTINE TO GIVE THE CURRENT DEFAULTS

CURDEF:	MOVE	N,J$XMLM(J)		;PICK UP MLIMIT
	TELL	OPR,CURMS1		;GIVE THE FIRST MESSAGE
	TELL	OPR,[ASCIZ /Messages on:/]
	SKIPE	T1,MSGJOB		;JOB?
	TELL	OPR,[ASCIZ / JOB/]
	SKIPE	T2,MSGFIL		;FILE?
	TELL	OPR,[ASCIZ / FILE/]
	SKIPE	T3,MSGERR 		;ERRORS?
	TELL	OPR,[ASCIZ / ERRORS/]
	ADD	T1,T2			;COMBINE JOB+FILE
	ADD	T1,T3			;ADD IN ERROR
	SKIPN	T1			;ANY OF THE ABOVE?
	TELL	OPR,[ASCIZ / No Conditions/]
	TELL	OPR,CRLF		;AND AN EOL

	SKIPE	N,NXTJOB		;GET NEXT-JOB
	TELL	OPR,CURMS2		;TELL HIM

	MOVE	T1,J$FORM(J)		;GET CURRENT FORMS TYPE
	TXNE	S,MNTBIT		;ARE WE WAITING FOR MOUNT?
	MOVE	T1,J$FPFM(J)		;YES, USE PREVIOUS TYPE
	MOVEI	T2,%%TFM		;LOAD FORMS MOUNTED MESSAGE
	TXNE	S,FROZE			;ARE WE FROZEN?
	MOVEI	T2,%%FAF		;YES, GET FROZEN MESSAGE
	TELL	OPR,(T2)		;AND TYPE A MESSAGE
	MOVE	T1,J$FSFM(J)		;TYPE OF FORM QUASAR BELIEVES IN
	CAME	T1,J$FORM(J)		;IS IT THE TYPE MOUNTED?
	TELL	OPR,%%FHB		;NO, TELL HIM
	SKIPE	J$FNOT(J)		;IS THERE A NOTE?
	TELLN	OPR,@J$FNOT(J)		;YES, TYPE IT


				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

CURINF:	TXNE	S,STARTD		;ARE WE STARTED?
	JRST	CURD.1			;YES, CONTINUE
	TELL	OPR,%%WFS		;NO, TELL HIM
	POPJ	P,			;AND RETURN

CURD.1:	TXNN	S,RUNB			;ARE WE RUNNING?
	TELL	OPR,%%SIS		;NO, TELL HIM

CURD.3:	SKIPE	XITFLG			;WILL WE EXIT
	TELL	OPR,%%LWE		;YES, TELL HIM

CURD.4:	SKIPE	RSTFLG			;WILL WE RESET?
	TELL	OPR,%%LWR		;YES, TELL HIM

CURD.5:	TXNE	S,PAUSEB!PLOCK		;WILL WE PAUSE?
	TELL	OPR,%%LWP		;YES

CURD.7:	SKIPE	J$LHNG(J)		;IS THE LPT HUNG?
	TELL	OPR,%%DOL		;YES, TELL HIM

	POPJ	P,			;RETURN
SUBTTL	Operator Commands  --  BACKSPACE

;(NOTE: ENTER AT "IBACK" WITH N CONTAINING NUMBER OF PAGES)


BACKSP:	TXNE	S,NOTYPE	;IS BACK OR FORWARD IN PROGRESS?
	JRST	BFINPR		;YES, GIVE AN ERROR
	PUSHJ	P,DECARG	;GET THE ARGUMENT
	  POPJ	P,		;ZERO OR ILLEGAL
BACK.1:	CAMLE	N,J$RNPP(J)	;BACKING UP PAST BEGINNING?
	MOVE	N,J$RNPP(J)	;YES, MAKE IT A REWIND
	STAMP	LPOPR		;STAMP THE MESSAGE
	TELL	LOG,%%BSF	;PUT MESSAGE IN THE LOG
IFN FTUUOS,<
	CAIG	N,TABSIZ	;IS BACK-SKIP WITHIN TABLE?
	JRST	BSPCF		;YES, TRY FOR FAST BACKSPACE
>  ;END IFN FTUUOS

BACKS1:	PUSHJ	P,REWIND	;REWIND THE FILE
	MOVNS	N		;GET NEGATIVE PAGES TO SKIP
	ADD	N,J$RNPP(J)	;ADD TO CURRENT PAGE = DESTINATION PAGE
	SETZM	J$RNPP(J)	;SET CURRENT PAGE TO 0
	SOJG	N,FORWD1	;AND SKIP THE PAGES IF GT 1
	POPJ	P,		;AND RETURN

;ENTER HERE FOR INTERNAL BACKSPACE CALL WITH N CONTAINING THE NUMBER OF PAGES
IBACK:	JRST	BACK.1		;JUMP INTO MIDDLE OF ROUTINE



BFINPR:	TELL	OPR,WHATB7	;BACKSPACE OR FORWARD IN PRGRESS
	POPJ	P,		;RETURN
IFN FTUUOS,<

;HERE IS ACTUAL "FAST BACKSPACE" CODE

BSPCF:	MOVN	T1,N		;GET NEGATIVE ARGUMENT
	ADD	T1,J$RNPP(J)	;GET DESTINATION PAGE
	CAIG	T1,1		;ARE WE JUST DOING A REWIND?
	JRST	BACKS1		;YES, USE REGULAR CODE
	IDIVI	T1,TABSIZ	;DIVIDE BY SIZE OF TABLE
	MOVE	T1,T2		;SAVE THE INDEX IN T1
	ADD	T2,J		;POINT INTO JOB-INFO PAGE
	SKIPN	T2,J$XPTB(T2)	;GET THE TABLE ENTRY
	JRST	BACKS1		;ITS ZERO!! USE OLD CODE
	MOVEI	T3,DSK		;DSK CHANNEL
	WAIT	T3,		;AND WAIT FOR IO TO COMPLETE

	PUSHJ	P,REWIND	;REWIND THE FILE
	USETI	DSK,(T2)	;SET THE BLOCK
	HRRZM	T2,J$DINF(J)	;SAVE FOR NEXT TIME
	HLRZM	T2,J$XSBC(J)	;AND STORE THE BYTE COUNT
	SOS	J$DINF(J)	;SAVE DECREMENTED.
	MOVNS	N		;GET -VE PAGES
	ADDM	N,J$RNPP(J)	;SET CURRENT PAGE
	MOVNS	N		;RE-NEGATE
	ADDM	N,J$RLIM(J)	;HOW MANY TO SKIP

BSPCF3:	ADDI	T1,1		;POINT TO NEXT INVALID PAGE
	IDIVI	T1,TABSIZ	;GET IT MODULO TABSIZ
	ADD	T2,J		;POINT INTO JOB INFO PAGE
	CLEARM	J$XPTB(T2)	;CLEAR IT
	MOVE	T1,T2		;RESTORE THE INDEX
	SUB	T1,J		;SUBTRACT OUT THE ADR OF J-I PAGE
	SOJG	N,BSPCF3	;AND LOOP FOR ALL SKIPPED PAGES
	POPJ	P,		;AND RETURN




;ROUTINE TO CLEAR OUT THE PAGE-LOCATION TABLE
CLRTAB:	HRRI	T4,J$XPTB(J)	;GET ADR OF FIRST WORD
	HRL	T4,T4		;XWD ADR,ADR
	CLEARM	(T4)		;CLEAR THE FIRST WORD
	ADDI	T4,1		;MAKE XED ADR,ADR+1
	MOVEI	T3,J$XPTB(J)	;GET ADDRESS OF BLOCK
	BLT	T4,TABSIZ-1(T3)	;BLT THE BLOCK
	POPJ	P,		;AND RETURN

>  ;END IFN FTUUOS
SUBTTL	Operator Commands  --  FORWARD

;SUBROUTINE TO SPACE FORWARD N PAGES
;CALLED FROM COMIN:
;	PUSHJ	P,FORWAR
;	RETURN WITH SOME LOCATIONS FIXED
;

FORWAR:	PUSHJ	P,DECARG		;GET THE ARGUMENT
	  POPJ	P,			;ILLEGAL OR ZERO
	STAMP	LPOPR			;STAMP THE LOG
	TELL	LOG,%%FSF		;PUT MESSAGE IN THE LOG
FORWD1:	TXOE	S,NOTYPE		;SET NOTYPE AND SKIP IF IT WASN'T ALREADY
	JRST	FORWD2			;IT WAS, WE'RE MOVING FORWARD ALREADY
	MOVN	T1,N			;GET -VE NUMBER OF PAGES TO SKIP
	ADDM	T1,J$APRT(J)		;AND DECREMENT NUMBER PRINTED BY IT
	ADD	N,J$RNPP(J)		;ADD CURRENT PAGE NUMBER
	MOVEM	N,J$XDPG(J)		;SAVE AS DESTINATION PAGE
	POPJ	P,			;AND RETURN

FORWD2:	ADDM	N,J$XDPG(J)		;JUST PUSH DESTINATION AHEAD
	POPJ	P,			;AND RETURN
SUBTTL	Operator Commands  --  MESSAGE

MESSGE:	SETZ	AP,			;CLEAR ARGUMENT COUNTER
MESS.0:	SETZM	MSGJOB			;START WITH A CLEAN SLATE
	SETZM	MSGFIL			; DITTO
	SETZM	MSGERR			; DITTO AGAIN

MESS.1:	PUSHJ	P,SIXIN			;GET A WORD
	  JRST	MESS.4			;NO MORE, CHECK FOR NULL ARG AND RET
	LDB	T2,[POINT 6,T1,5]	;GET THE FIRST CHARACTER
	CAIN	T2,'A'			;IS IT 'ALL'?
	JRST	MESS.5			;YES, HANDLE SPECICAL CASE
	MOVSI	T4,-MSGTLN		;MAKE AN AOBJN POINTER TO TABLE

MESS.2:	HLRZ	T3,MSGTBL(T4)		;GET AN ENTRY
	CAMN	T2,T3			;IS IT A MATCH?
	JRST	MESS.3			;YES, GO DO SOMETHING
	AOBJN	T4,MESS.2		;NO, LOOP
	TELL	OPR,%%ICAS		;NO MATCH, ERROR
	JRST	MESS.4			;BUT CONTINUE ANYWAY

MESS.3:	AOJ	AP,			;FLAG THAT WE GOT AN ARGUMENT
	HRRZ	T3,MSGTBL(T4)		;GET WORD TO SET
	SETZ	T1,			;DUMMY FOR 'NONE'
	SETOM	(T3)			;SET IT
	JUMPN	T1,MESS.0		;JUMP IF 'NONE'
MESS.4:	CAIN	C,","			;IS THERE MORE?
	JRST	MESS.1			;YES, LOOP
	SKIPN	AP			;DID WE GET AN ARGUMENT?
	SETOM	MSGERR			;NO, SET DEFAULT
	POPJ	P,			;NO, RETURN

MESS.5:	SETOM	MSGFIL			;SET JOB
	SETOM	MSGJOB			;SET FILE
	SETOM	MSGERR			;SET ERROR
	JRST	MESS.4			;AND CONTINUE


MSGTBL:	XWD	'J',MSGJOB
	XWD	'F',MSGFIL
	XWD	'E',MSGERR
	XWD	'N',T1		;DUMMY FOR 'NONE'

	MSGTLN==.-MSGTBL
SUBTTL	Operator Commands  -- (NO)SUPPRESS

;SUBROUTINE TO IMPLEMENT THE SUPPRESS COMMAND
;CALL WITH:
;	PUSHJ	P,SUPPRE
;	RETURN HERE
;
SUPPRE:	OFF	S,SUPJOB!SUPRES		;START CLEAN
	PUSHJ	P,SIXIN			;GET ARGUMENT
	  MOVSI	T1,'FIL'		;GET DEFAULT ARGUMENT
	LDB	T2,[POINT 6,T1,5]	;GET THE FIRST CHARACTER
	CAIN	T2,'F'			;"FILE"
	ON	S,SUPRES		;YES, LIGHT THE BIT
	CAIN	T2,'J'			;"JOB"
	ON	S,SUPJOB		;YES, SET THE BIT
	TXNN	S,SUPJOB!SUPRES		;DID WE LIGHT ONE?
	TELL	OPR,%%ICAS		;NO, GIVE AN ERROR
	POPJ	P,			;YES, RETURN


;ROUTINE TO IMPLEMENT THE NOSUPPRESS COMMAND
;CALL WITH
;	PUSHJ P,NOSUPR
;	RETURN HERE ALWAYS
;
NOSUPR:	OFF	S,SUPJOB!SUPRES	;TURN OFF LOCAL AND GLOBAL FLAGS
	POPJ	P,		;AND RETURN
SUBTTL	LOWSEG Operator Commands  --  RESET - CHECKPOINT


	LOWSEG

;SUBROUTINE TO DO A RESET
;CALL WITH:
;	PUSHJ	P,RESETC
;	NEVER RETURNS
;ALL AC'S REFRESHED
RESETC:	SETOM	RSTFLG			;SET THE RESET FLAG
	TXNE	S,BUSY			;ARE WE BUSY?
	POPJ	P,			;YES, MAKE IT PEND

DOREST:	PUSHJ	P,GETSPL		;GET THE HISEG
	PUSHJ	P,SETHEL		;SETUP HELLO BLOCK
	MOVX	T1,HELSTC!HELBYE	;GOODBYE+STATUS CHANGE
	IORM	T1,MSGBLK+HEL.ST	;STORE FLAGS
	MOVEI	T1,MSGBLK		;LOAD ADR OF BLOCK
	PUSHJ	P,SNDQSR##		;SEND IT
	TELL	OPR,%%LIR		;LPTSPL IS RESET
	JRST	LPTSPL


;SUBROUTINE TO TAKE A CHECKPOINT

TAKCHK:	SKIPN	J$LHNG(J)		;RETURN IF DEVICE IS OFF-LINE
	TXNE	S,ABORT			;ARE WE ABORTED?
	POPJ	P,			;YES, DON'T CHECKPOINT
	PUSHJ	P,SETCHP		;SETUP THE CHECKPOINT BLOCK
	PUSHJ	P,CLSLOG		;AND CLOSE THE LOG
	MOVX	T1,<CHE.SZ,,.QOCHE>	;LOAD THE MESSAGE HEADER
	MOVEM	T1,MSGBLK		;STORE IT
	MOVEI	T1,MSGBLK		;LOAD THE BLOCK ADDRESS
	PJRST	SNDQSR##		;AND SEND IT


SETCHP:	STAMP	LPMSG			;GIVE A STAMP
	MOVEI	T2,MSGBLK		;LOAD ADDRESS OF MSG BLOCK
	MOVE	N,J$RNFP(J)		;GET NUMBER OF FILES
	MOVEM	N,CHE.IN+CKFIL(T2)	;STORE IT
	MOVE	N,J$RNCP(J)		;GET NUMBER OF COPIES
	MOVEM	N,CHE.IN+CKCOP(T2)	;AND STORE IT
	AOS	N			;INCREMENT IT
	TELL	LOG,%%CPT		;AND TYPE FIRST PART OF MESSAGE
	MOVE	N,J$RNPP(J)		;GET NUMBER OF PAGES
	MOVEM	N,CHE.IN+CKPAG(T2)	;AND STORE IT
	TELL	LOG,%%CPT1		;AND SECOND PART OF MESSAGE
	MOVE	N,J$APRT(J)		;NUMBER OF PAGES PRINTED
	MOVEM	N,CHE.IN+CKTPP(T2)	 ;AND STORE IT
	LOAD	N,.EQITN(J)		;GET JOBS ITN
	MOVEM	N,MSGBLK+CHE.IT		;AND STORE IT
	MOVX	N,CKFCHK		;CHKPOINT FLAG
	MOVEM	N,CHE.IN+CKFLG(T2)	;STORE IT
	POPJ	P,			;AND RETURN
SUBTTL	TTY I/O Routines

	TOPSEG
;SUBROUTINE TO FIND A DELIMITER (ANY OF :,=)
;CALL WITH:
;	PUSHJ	P,FNDELM
;	  CAN'T FIND A DELIMITER
;	RETURN HERE WITH DELIMITER IN C
;
FNDELM:	PUSHJ	P,GETCHR	;GET A CHAR
	CAIN	C,12		;LINE FEED?
	POPJ	P,		;YES. NO DELIMITER
	CAIE	C,":"		;COLON?
	CAIN	C,"="		; OR EQUALS
	JRST	.POPJ1##		;YES. WE HAVE A DELIMITER
	JRST	FNDELM		;NO KEEP LOOKING

;SUBROUTINE TO INSERT THE FIRST CHAR AFTER A / IN C
;CALL WITH
;	PUSHJ	P,DOSW
;	  RETURN HERE IF NO SWITCHES
;	RETURN HERE WITH C SET UP
;
DOSW:	CAIE	C,"/"		;GOT A SLASH?
DOSW.1:	PUSHJ	P,GETCHR	;NO, GET A CHARACTER
	TXNE	S,TTYBRK	;HIT EOL?
	POPJ	P,		;YES, RETURN
	CAIE	C,"/"		;DO WE HAVE A SLASH?
	JRST	DOSW.1		;NO, LOOP
	PJRST	GETCHR		;YES, GET THE NEXT CHRACTER AND RETURN
;SUBROUTINE TO INPUT A DECMAL NUMBER
;CALL WITH:
;	PUSHJ	P,DECARG
;	  INVALID DATA
;	RETURN HERE WITH NUMBER IN N
;MUST RESPECT T2
DECARG:	SETZ	N,		;CLEAR RESULT
	PUSHJ	P,SPACES	;FLUSH SPACES
	SKIPA			;AND SKIP INTO LOOP
DECAR1:	PUSHJ	P,GETCHR	;GET A CHAR
	CAIG	C,71		;IS THIS CHAR A DIGIT
	CAIGE	C,60		; ..
	JRST	ACH		;NO. MUST BE END OF NUMBER
	IMULI	N,12		;ADJUST N FOR NEXT DECADE
	ADDI	N,-60(C)	;NIFTY INSTRUCTION, TO INCR. N
	JRST	DECAR1		;GET NEXT DIGIT
ACH:	CAIE	C," "		;BLANKS TABS
	CAIN	C,12		; AND LINE FEEDS ARE VALID AFTER NUMBER
	AOS	(P)		;GOOD DELIMITER IN C
	POPJ	P,		;INVALID DELIMITER
;SUBROUTINE TO INPUT A SIXBIT WORD (A-Z AND 0-9 ONLY VALID CHARS.)
;CALL WITH:
;	PUSHJ	P,SIXIN
;	  RETURN HERE IF NOTHING FOUND
;	RETURN HERE WITH WORD IN T1
;
SIXIN:	SETZ	T1,		;CLEAR RESULT
	MOVE	T2,[POINT 6,T1];SET UP A BYTE POINTER
	PUSHJ	P,SPACES	;SKIP SPACES
	SKIPA			;AND GET INTO LOOP WITH 1ST CHAR
SIXLPI:	PUSHJ	P,GETCHR	;GET A CHAR
	TXNE	S,TTYBRK	;GOT A BREAK CHAR?
	JRST	CKT1		;YES. CHECK RESULT
	CAIL	C,"0"		;STANDARD CHECK
	CAILE	C,"Z"		; FOR ALPHABETIC
	JRST	CKT1		; OR NUMERIC DATA
	CAILE	C,"9"		; ANYTHING THAT FAILS
	CAIL	C,"A"		; IS CONSIDERED A TERMINAL
	JRST	.+2
	JRST	CKT1		; CHARACTOR
	SUBI	C,40		;CONVERT TO SIXBIT
	TLNE	T2,770000	;MORE THAN 6 CHARS?
	IDPB	C,T2		;STORE
	JRST	SIXLPI		;LOOP GO MORE
CKT1:	JUMPN	T1,.POPJ1##	;DID WE FIND A CHAR
	POPJ	P,		;NO. PUNT
;SUBROUTINE TO INPUT ONE CHAR HANDLING SYNTAX
;CALL WITH:
;	PUSHJ	P,GETCHR
;	RESULT IN C

GETCHR:	PUSHJ	P,TTYIN			;GET A CHARACTER
	CAIL	C,"A"+40		;CHECK TO SEE IF IT IS
	CAILE	C,"Z"+40		; A LOWER CASE CHARACTER
	SKIPA				;IT'S NOT
	SUBI	C,40			;IT IS, MAKE IT UPPER CASE
	CAIE	C,.CHCRT		;CARRAGE RETURN
	CAIN	C,177			;RUBOUT
	JRST	GETCHR			;GET A NEW CHAR
	CAIN	C,11			;TAB?
	MOVEI	C,40			;YES. SAME AS BLANK
	CAIE	C,";"			;COMMENT
	CAIN	C,"!"			; "  "
	SKIPA				;YES, SKIP
	POPJ	P,			;NO, RETURN

EAT:	PUSHJ	P,TTYIN			;GET A CHARACTER
	TXNN	S,TTYBRK		;GET A BREAK YET?
	JRST	EAT			;NO, LOOP
IFN FTJSYS,<
	PUSHJ	P,TTYSTA		;START THE TTY PROCESS GOING
>  ;END IFN FTJSYS
	POPJ	P,			;YES, RETURN

SPACES:	PUSHJ	P,GETCHR		;SKIP A CHARACTER
	CAIN	C," "			;IS IT A SPACE?
	JRST	SPACES			;NO, LOOP
	POPJ	P,			;AND RETURN
SUBTTL	SETNL  --  Setup to read a new line from TTY

IFN FTUUOS,<
SETNL:	OFF	S,TTYBRK		;CLEAR THE BREAK FLAG
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
SETNL:	OFF	S,TTYBRK		;CLEAR THE BREAK FLAG
	MOVE	S1,[POINT 7,TTYBUF]	;POINT TO THE BUFFER
	MOVEM	S1,TTYPTR		;SAVE THE POINTER
	SKIPE	TTYFLG			;IS THERE ANYTHING?
	POPJ	P,			;YES, RETURN
	PUSHJ	P,TTYSTA		;NO, START IT
	MOVEI	S1,^D60			;LOAD A MINUTE
	PUSHJ	P,SUSPND		;GO SLEEP
	JRST	SETNL			;AND LOOP
>  ;END IFN FTJSYS
SUBTTL	TTYIN  --  Read a character from the TTY

;TTYIN ROUTINE TO GET A CHARACTER FROM THE OPERATOR'S CONSOLE
;	RETURNS CHARACTER IN C

	IFN FTUUOS,<OPDEF  GTCHR.  [INCHWL C]>
	IFN FTJSYS,<OPDEF  GTCHR.  [ILDB C,TTYPTR]>

TTYIN:	TXNN	S,TTYBRK		;GOT A BREAK?
	JRST	TTYI.1			;NO, CONTINUE
	MOVEI	C,.CHLFD		;YES, LOAD A LF
	POPJ	P,			;AND RETURN

TTYI.1:	GTCHR.				;GET A CHARACTER
	CAIE	C,.CHCNZ		;IS IT A CONTROL-Z OR A
	CAIN	C,.CHCNC		; CONTROL-C?
	JRST	DOEXIT			;YES, GO EXIT
	CAIE	C,.CHESC		;IS IT AN ESCAPE?
	CAIN	C,.CHLFD		; OR A LINEFEED?
	ON	S,TTYBRK		;YES, SET FLAG
	POPJ	P,			;RETURN
SUBTTL	TTYOUT  --  Type out a character on the TTY

;TTYOUT ROUTINE TO TYPE A CHARACTER ON THE OPERATOR'S CONSOLE
;	CALL WITH CHARACTER IN AC C

IFN FTUUOS,<
TTYOUT:	OUTCHR	C			;TYPE IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
TTYOUT:	EXCH	C,S1			;GET CHARACTER IN S1
	PBOUT				;OUTPUT IT
	EXCH	C,S1			;EXCHANGE BACK
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	LUUO Handler

;HERE FROM LOCATOIN 40 ON THE TELL AND TELLN AND STAMP UUO.

	LOWSEG
UUOL:	MOVEM	N,SAVN#			;SAVE N
	MOVEM	T1,SAVT1#		;SAVE T1
	PUSHJ	P,SAVALL		;SAVE THE AC'S
	PUSHJ	P,GETSPL		;GET THE SPOOLER
	PJRST	UUOH			;PROCESS THE UUO

	TOPSEG

UUOH:	OFF	S,TNOACT		;CLEAR SOME BITS
	MOVE	P1,.JBUUO##		;PICK UP THE UUO
	TXNE	P1,STAMP		;IS IT A STAMP UUO?
	JRST	STPLOG			;YES, DO IT
	TXNE	P1,TELLN		;IS IT A TELLN UUO?
	ON	S,TNOACT		;YES, DON'T ALLOW ACTION CHARACTERS
	HRLI	P1,440700		;CONVERT TO BYTE POINTER
	LDB	T1,PAC			;PICK UP THE AC BITS
	DPB	T1,PS			;SAV3 IN STATUS REG.
	TXNE	S,TELUSR		;IF THIS IS FOR THE USER
	OFF	S,FFSEEN		; THEN WE ARE NOT AT TOP OF FORM
TLOOP:	ILDB	C,P1			;GET A CHAR
TLOOP0:	JUMPE	C,UUORST		;JUMP IF NULL
	CAIE	C,"!"			;THE ESCAPE CHAR?
	JRST	TLOOP1			;NO, CONTINUE
	ILDB	C,P1			;YES, GET NEXT CHAR
	JUMPE	C,UUORST		;FINISH UP IF NULL
	PUSHJ	P,SEND			;ELSE, SEND IT
	JRST	TLOOP			;AND LOOP
TLOOP1:	TXNN	S,TNOACT		;ACTION ALLOWED?
	PUSHJ	P,DOACT			;YES. IS THIS ACTIVE
	SKIPE	C			;C=0 IF IT WAS AN ACTION CHAR
	PUSHJ	P,SEND			;NO. JUST PRINT
	JRST	TLOOP			;DO NEXT CHAR
UUORST:	OFF	S,TNOACT		;CLEAR A BIT
	POPJ	P,			;RETURN
;SUBROUTINE TO PROCESS ACTION CHARS
;CALL WITH:
;	MOVE	C,CHAR-TO-CHECK
;	PUSHJ	P,DOACT
;	ACTION TAKEN IF (C) = 0
;ALL ACS PRESERVEVED UNLESS ACTION SAYS OTHERWISE
DOACT:	PUSHJ	P,DOACT1	;GO DO THE CHECKS
	SETZ	C,		;HERE IF IT WAS AN ACTION CHARACTER
	POPJ	P,		;HERE IF IT WASN'T AN ACTION CHAR

DOACT1:	ACTCHR	<^>,A5		;PRINT FILE NAME
	ACTCHR	<]>,PRUSER	;PRINT USER IDENTIFICATION
	ACTCHR	<+>,A9		;PRINT T1 AS SIXBIT
	ACTCHR	<#>,A10		;PRINT N AS DECMAL NUMBER
	ACTCHR	<@>,PRDTC	;PRINT CURRENT DATE AND TIME
	ACTCHR	<&>,A13		;PRINT N AS OCTAL
	ACTCHR	<$>,PRDEV	;PRINT CURRENT PROCESSING DEVICE
	PJRST	.POPJ1##	;SKIP RETURN - NOTHING DONE


;SUBROUTINE TO PRINT A SIXBIT VALUE PASSED TO MESSAGE HANDLER
;CALL WITH:
;	PUSHJ	P,A9
;	RETURN	HERE
;
A9:	MOVE	T1,SAVT1	;PICK UP WORD
	PJRST	SIXOUT		;PRINT IT


;SUBROUTINE TO PRINT N AS DECMAL
A10:	MOVE	T1,SAVN		;GET ARGUMENT
	PJRST	DECOUT		;PRINT AND RETURN



;SUBROUTINE TO PRINT N IN OCTAL
A13:	MOVE	T1,SAVN
	PJRST	OCTOUT
;SUBROUTINE TO PRINT A FILE NAME
;CALL WITH:
;	PUSHJ	P,A5
;	  ALWAYS RETURN HERE


IFN FTUUOS,<
A5:	MOVE	T1,J$DFLP+.FODEV(J)	;GET STR NAME
	JUMPE	T1,A5A			;DON'T PRINT ":" ON NULL DEVICE
	PUSHJ	P,SIXOUT		;PRINT IT
	MOVEI	C,":"			;DELIMIT WITH A
	PUSHJ	P,SEND			; DOUBLE DECKER PERIOD
A5A:	MOVE	T1,J$DUUO+.RBNAM(J)	;PICK UP FILE NAME
	PUSHJ	P,SIXOUT		;AND PRINT IT
	HLLZ	T1,J$DUUO+.RBEXT(J)	;GET EXTENSION
	JUMPE	T1,A5.1			;GO AWAY IF NULL
	MOVEI	C,"."			;PRINT A DOT
	PUSHJ	P,SEND			; ..
	PUSHJ	P,SIXOUT		;AND PRINT EXT
A5.1:	MOVEI	C,74			;LOAD OPEN WIDGET
	PUSHJ	P,SEND			;SEND IT
	LDB	T1,[POINT 9,J$DUUO+.RBPRV(J),8]
	MOVEI	C,"0"			;READY TO PAD
	CAIL	T1,100			;LESS THAN 3 DIGITS?
	JRST	A5.2			;NO, TYPE IT
	PUSHJ	P,SEND			;YES, PAD IT
	CAIL	T1,10			;LESS THAN TWO DIGITS?
	JRST	A5.2			;NO, TYPE IT
	PUSHJ	P,SEND			;YES, MORE PADDING
A5.2:	PUSHJ	P,OCTOUT		;TYPE IT NOW
	MOVEI	C,76			;LOAD A CLOSE WIDGET
	PUSHJ	P,SEND			;SEND IT
	MOVEI	T1,J$DPAT(J)		;GET ADDRESS OF PATH BLOCK
	PUSHJ	P,TYPUID		;AND TYPE IT
	SKIPN	T1,J$DUUO+.RBSPL(J)	;GET RIBSPL
	POPJ	P,			;NONE, RETURN
	MOVEI	C,"("			;LOAD OPEN PAREN
	PUSHJ	P,SEND			;SEND IT
	PUSHJ	P,SIXOUT		;SEND THE SPOOLED NAME
	MOVEI	C,")"			;LOAD A CLOSE PAREN
	PJRST	SEND			;SEND IT AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
A5:	MOVE	T1,J$DSTG(J)		;GET ADR OF THE STRING
	HRLI	T1,(POINT 7,0)		;MAKE A BYTE POINTER
A5.1:	ILDB	C,T1			;GET A BYTE
	JUMPE	C,.POPJ##		;RETURN WHEN DONE
	PUSHJ	P,SEND			;ELSE, SEND IT
	JRST	A5.1			;AND LOOP
>  ;END IFN FTJSYS
;SUBROUTINE TO TYPE A USER ID SPECIFICATION
;
;CALL:
;	MOVE T1,[DIRECTORY SPEC] (T10=PPN-PATH, T20=DIRECT #)
;	PUSHJ P,TYPUID
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
TYPUID:	PUSHJ	P,.SAVE2##		;SAVE P1 & P2
	MOVE	P1,T1			;AND SAVE THE ARG
	TLNN	T1,-1			;IS IT A PATH?
	MOVE	T1,2(T1)		;YES, GET THE PPN
	PUSHJ	P,TYPPPN		;AND TYPE THE PPN
	TLNE	P1,-1			;DID HE SUPPLY A PATH?
	JRST	TYPU.2			;NO, FINISH OFF AND RETURN
	MOVEI	P1,3(P1)		;POINT TO FIRST SFD

TYPU.1:	SKIPN	T1,(P1)			;GET NEXT SFD
	JRST	TYPU.2			;DONE
	MOVEI	C,","			;GET A COMMA
	PUSHJ	P,SEND			;SEND IT
	PUSHJ	P,SIXOUT		;SEND THE SFD NAME
	AOJA	P1,TYPU.1		;AND LOOP

TYPU.2:	MOVEI	C,"]"			;LOAD THE CLOSER
	PJRST	SEND			;AND SEND IT

TYPPPN:	MOVEI	C,"["			;LOAD THE OPENER
	PUSHJ	P,SEND			;SEND IT
	MOVE	P2,T1			;AND COPY THE PPN
	HLRZS	T1			;GET THE PROJECT NUMBER
	PUSHJ	P,OCTOUT		;TYPE IT
	MOVEI	C,","			;LOAD A COMMA
	PUSHJ	P,SEND			;SEND IT
	HRRZ	T1,P2			;GET PROGRAMMER NUMBER
	PJRST	OCTOUT			;SEND IT AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
TYPUID:	MOVE	S2,T1			;GET USER NUMBER IN S2
	HRROI	S1,J$XSFO(J)		;AND POINT TO THE BLOCK
	DIRST				;MAKE A STRING
	  JFCL				;AND IGNORE THE FAIL
	MOVE	T1,[POINT 7,J$XSFO(J)]	;POINT TO THE BLOCK

TYPU.1:	ILDB	C,T1			;GET A CHARACTER
	JUMPE	C,.POPJ##		;RETURN IF DONE
	PUSHJ	P,SEND			;ELSE SEND IT
	JRST	TYPU.1			;AND LOOP
>  ;END IF FTJSYS
;SUBROUTINE TO PRINT A NUMBER IN ANY RADIX
;CALL WITH:
;	MOVE	T1,NUMBER-TO-PRINT
;	PUSHJ	P,OCTOUT
;
;	-OR-
;
;	MOVE	T1,NUMBER-TO-PRINT
;	PUSHJ	P,DECOUT
;
;	-OR-
;
;	MOVEI	T4,RADIX
;	MOVE	T1,NUMBER-TO-PRINT
;	PUSHJ	P,ANYRDX
;
;
DECOUT:	MOVEI	T4,^D10		;BASE TEN
ANYRDX:	JUMPGE	T1,RDXOUT	;JUMP IF POSITIVE
	MOVEI	C,"-"		;LOAD A MINUS
	PUSHJ	P,SEND		;PRINT IT
	MOVM	T1,T1		;MAKE POSITIVE
RDXOUT:	IDIVI	T1,(T4)		;FIND THE REMAINDER
	HRLM	T2,(P)		;PUSH ONTO STACK
	SKIPE	T1		;FINISHED?
	PUSHJ	P,RDXOUT	;NO. RECUR
	HLRZ	C,(P)		;YES. POP OFF A DIGIT
	ADDI	C,60		;CONVERT TO ASCII
	PJRST	SEND		;PRINT THE DIGIT



OCTOUT:	LSHC	T1,-3		;SHIFT OUT THREE BITS
	HLLM	T2,(P)		;STACK IT
	SKIPE	T1		;SKIP IF DONE
	PUSHJ	P,OCTOUT	;ELSE RECURSE
	HLRZ	C,(P)		;GET A DIGIT
	LSH	C,-^D15		;RIGHT JUSTIFY IT
	ADDI	C,60		;MAKE IT ASCII
	PJRST	SEND		;AND PRINT IT
;SUBROUTINE TO PRINT AC AS SIXBIT
;CALL WITH:
;	MOVE	T1,WORD-TO-PRINT
;	PUSHJ	P,SIXOUT
;	RETURN IS ALWAYS HERE

SIXOUT:	MOVE	T2,T1		;COPY OVER THE ARG
SIXO.1:	SETZ	T1,		;ZERO OUT T1
	JUMPE	T2,.POPJ##	;ANYTHING LEFT?
	LSHC	T1,6		;SHIFT IN ANOTHER CHAR
	MOVEI	C,40(T1)	;PUTCHAR IN C
	PUSHJ	P,SEND
	JRST	SIXO.1		;LOOP FOR MORE
SUBTTL	PRUSER  -  Print out user identification

;PRUSER PRINTS OUT THE CURRENT USER'S IDENTIFICATION WHICH CONSISTS
;	OF USER NAME AND PPN ON TOPS10 AND USER DIRECTORY NAME ON
;	TOPS20
;
;CALL:
;	PUSHJ P,PRUSER
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
PRUSER:	MOVE	T1,.EQUSR(J)		;GET 1ST HALF OF NAME
	PUSHJ	P,SIXOUT		;SEND IT
	MOVEI	C," "			;LOAD A BLANK
	MOVE	T1,.EQUSR(J)		;AND GET FIRST HALF BACK
	TRNN	T1,77			;WAS LAST CHAR A BLANK?
	PUSHJ	P,SEND			;YES, SEND ONE BLANK
	MOVE	T1,.EQUSR+1(J)		;GET 2ND HALF
	PUSHJ	P,SIXOUT		;TYPE IT
	MOVEI	C," "			;LOAD A BLANK
	PUSHJ	P,SEND			;SEND IT
	MOVE	T1,.EQOWN(J)		;GET PPN
	PJRST	TYPUID			;AND TYPE IT
>  ;END IFN FTUUOS

IFN FTJSYS,<
PRUSER:	MOVEI	T1,.EQOWN(J)		;POINT TO USER NAME
	HRLI	T1,(POINT 7,0)		;MAKE A BYTE POINTER
PRUS.1:	ILDB	C,T1			;LOAD A CHACTER
	JUMPE	C,.POPJ##		;DONE, RETURN
	PUSHJ	P,SEND			;SEND IT
	JRST	PRUS.1			;AND LOOP
>  ;END IFN FTJSYS
SUBTTL	PRDEV - Print out current processing device

PRDEV:	MOVE	T1,J$LDEV(J)	;GET THE DEVICE
	PJRST	SIXOUT		;AND PRINT IT
SUBTTL	PRDTC - Print current date and time

;CALL WITH:
;	PUSHJ 	P,PRDTC
;	  RETURN HERE ALWAYS

PRDTC:	PUSHJ	P,PRDATE	;PRINT THE DATE
	MOVEI	C," "		;LOAD A BLANK
	PUSHJ	P,SEND		;SEND IT
	PJRST	PRTIME		;SEND THE TIME AND RETURN



SUBTTL	PRDTA - Print an arbitrary date and time

;CALL WITH:
;	MOVE T1,[DATE,,TIME]
;	PUSHJ P,PRDTA
;	  RETURN HERE ALWAYS

PRDTA:	PUSHJ	P,.SAVE1##	;SAVE P1
	PUSH	P,T1		;SAVE T1 FOR A WHILE
IFN FTJSYS,<
	MOVE	P1,T1		;GET THE DATE
>  ;END IFN FTJSYS

IFN FTUUOS,<
	HLRZ	P1,T1		;GET THE DATE
	MOVX	T1,%CNDTM	;GETTAB TO DATE-TIME
	GETTAB	T1,		;GET IT
	  HALT
	HLRZS	T1		;GET DATE
	SUB	T1,P1		;GET THE DIFFERENCE
	DATE	P1,		;GET TODAY'S DATE
	SUB	P1,T1		;SUBTRACT THE DIFFERENCE
>  ;END IFN FTUUOS
	PUSHJ	P,PRDAT1	;PRINT THE DATE
	MOVEI	C," "		;LOAD A BLANK
	PUSHJ	P,SEND		;SEND IT
	POP	P,P1		;GET THE TIME BACK
	PJRST	PRTIM1		;AND PRINT THE TIME
SUBTTL	PRDATE - Print the date

;CALL WITH:
;	PUSHJ	P,PRDATE
;	RETURN HERE

IFN FTUUOS,<
PRDATE:	PUSHJ	P,.SAVE3##	;SAVE 3 AC'S
	DATE	P1,		;GET THE DATE
	JRST	.+2		;SKIP THE SAVE
PRDAT1:	PUSHJ	P,.SAVE4##	;SAVE THE PRESERVED AC'S
	IDIVI	P1,^D31		;GET THE DAY
	MOVEI	T1,1(P2)		;ADD AND MOVE
	PUSHJ	P,TWODIG	;PRINT THE DAY
	IDIVI	P1,^D12		;GET THE MONTH
	MOVE	T1,P2		;GET MON-1 IN T1
	MOVE	P2,[POINT 7,MNTAB(T1)] ;LOAD A BYTE POINTER
	MOVEI	P3,5		;CHAR COUNT
	ILDB	C,P2		;LOAD A CHAR
	PUSHJ	P,SEND		;SHIP IT
	SOJG	P3,.-2		;LOOP OVER WORD
	MOVEI	T1,^D64(P1)	;ADD YEAR ZERO
	PJRST	DECOUT		;AND PRINT IT AND RETURN

MNTAB:	ASCII	/-Jan-/
	ASCII	/-Feb-/
	ASCII	/-Mar-/
	ASCII	/-Apr-/		;OR IS IT CPU
	ASCII	/-May-/	
	ASCII	/-Jun-/	
	ASCII	/-Jul-/
	ASCII	/-Aug-/
	ASCII	/-Sep-/
	ASCII	/-Oct-/
	ASCII	/-Nov-/
	ASCII	/-Dec-/
>  ;END IFN FTUUOS

IFN FTJSYS,<
PRDATE:	PUSHJ	P,.SAVE1##	;SAVE P1
	SETO	P1,		;AND SET TO -1
PRDAT1:	PUSHJ	P,.SAVET##	;SAVE T1-T4
	MOVE	S2,P1		;GET DATE TO PRINT
	HRROI	S1,J$XSFO(J)	;GET PTR TO BLOCK
	MOVX	T1,1B9		;DONT PRINT THE TIME
	ODTIM			;AND DO IT!!
	MOVE	T1,[POINT 7,J$XSFO(J)]

PRDA.2:	ILDB	C,T1		;GET A CHARACTER
	JUMPE	C,.POPJ##	;RETURN WHEN DONE
	PUSHJ	P,SEND		;SEND IT
	JRST	PRDA.2		;AND LOOP
>  ;END IFN FTJSYS
SUBTTL	PRTIME - Print the time

;CALL WITH:
;	PUSHJ	P,PRTIME
;	RETURN HERE

IFN FTUUOS,<
PRTIME:	PUSHJ	P,.SAVE2##	;GET SOME SCRATCH AC'S
	MOVX	P1,%CNDTM	;GET UNIVERSAL DATE-TIME
	GETTAB	P1,		;GET IT
	  HALT .
PRTIM1:	HRRZS	P1		;JUST TIME HALF
	MULI	P1,^D86400	;MULIPLY BY SECS/DAY
	ASHC	P1,^D17		;DIVIDE BY 2^18 YIELDING SECONDS
	IDIVI	P1,^D3600	;MAKE HOURS
	PUSHJ	P,PRT2		;PRINT HOURS AS TWO DIGITS
	MOVEI	C,":"		;PRINT A DELIMITER
	PUSHJ	P,SEND		; ..
	MOVE	P1,P2		;GET REMAINDER
	IDIVI	P1,^D60		;DIVIDE OUT THE MINUTES
	PUSHJ	P,PRT2		; ..
	MOVEI	C,":"		; DELIMIMIT THE HOURS
	PUSHJ	P,SEND		; FROM THE SECONDS
	MOVE	P1,P2		;GET THE SECONDS
PRT2:	MOVE	T1,P1		;SETUP FOR DECOUT
;FALL INTO TWODIG

;SUBROUTION TO PRINT AT LEASE 2 DECMAL DIGITS
;CALL WITH:
;	MOVE	T1,NUMBER-T0-PRINT
;	PUSHJ	P,TWODIG
;	RETURN HERE
;
TWODIG:	MOVEI	C,"0"		;ALWAYS PRINT 2 DIGITS
	CAIGE	T1,12		;IF LESS TAN 10
	PUSHJ	P,SEND
	PJRST	DECOUT		;PRINT N AS DECMAL
>  ;END IFN FTUUOS

IFN FTJSYS,<
PRTIM1:	SKIPA	S2,P1		;GET ARBITRARY TIME
PRTIME:	SETO	S2,		;GET CURRENT TIME
	HRROI	S1,J$XSFO(J)	;POINT TO THE BLOCK
	MOVX	T1,1B0		;AND FORMAT FLAGS
	ODTIM			;AND DO THE JSYS
	MOVE	T1,[POINT 7,J$XSFO(J)]

PRTI.1:	ILDB	C,T1		;GET A CHARACTER
	JUMPE	C,.POPJ##	;RETURN WHEN DONE
	PUSHJ	P,SEND		;SEND IT
	JRST	PRTI.1		;AND LOOP
>  ;END IFN FTJSYS
	;SUBROUTINE TO PLACE A CHAR IN ALL THE PROPER BUFFERS
;CALL WITH:
;	PUSHJ	P,SEND (CHAR IN C, FLAGS IN S)
;	RETURN HERE
;ALL AC'S RESPECTED (AT SOME PAIN)
;
SEND:	TXNE	S,TELOPR		;SHOULD WE GIVE TO OPER?
	PUSHJ	P,TTYOUT		;YES, GO AHEAD
SLOG:	TXNE	S,TELLOG		;LOG THIS MESSAGE?
	PUSHJ	P,CHRLOG		;YES, DO IT
SDEV:	TXNN	S,TELUSR		;PRINT DIRECTLY?
	POPJ	P,			;RETURN

	OFF	S,NOTYPE!FFSEEN		;MAKE IT SEEN
	CAIN	C,.CHFFD		;IS IT A FORM FEED?
	ON	S,FFSEEN		;YES, TURN ON A FLAG
	PJRST	DEVOUT			;PRINT THE CHAR AND RETURN
SUBTTL	LOG File Routines

;	FNDLOG	--	FIND THE LOG FILE AND SET IT UP
;	STALOG	--	PUT STARTUP MESSAGES IN USERS LOG FILE
;	STPLOG	--	PUT A TIMESTAMP IN THE LOG FILE
;	CHRLOG	--	PUT A CHARACTER IN THE LOG FILE
;	OPNLOG	--	OPEN THE LOG FOR WRITING
;	CLSLOG	--	CLOSE THE LOG FILE OUT
;	RIDLOG  --	RELEASE THE LOG FILE
;	BUFLOG	--	ALLOCATE A BUFFER PAGE FOR LOG
;	CLNLOG	--	CLEAN-UP LOG BUFFER PAGES


	TOPSEG
SUBTTL	FNDLOG  --  Setup the LOG File

;FNDLOG  --  ROUTINE TO FIND THE LOG FILE SPEC, AND SETUP THE
;	VARIOUS UUO BLOCKS.

FNDLOG:	OFF	S,JOBLOG!LOGOPN		;START WITH NO LOG
	SETZM	J$GNLN(J)		;AND 0 LINES
	SETZM	J$GINP(J)		;AND NO INTERNAL LOG YET
	PUSHJ	P,BUFLOG		;GET A BUFFER PAGE
	SKIPN	T1,J$RLFS(J)		;IS THERE A LOG FILE SPEC
	POPJ	P,			;NO, RETURN


IFN FTJSYS,<
FNDL.2:	ON	S,JOBLOG		;THERE IS A LOG FILE
	LOAD	S2,.FPSIZ(T1),FP.FHD	;GET LENGTH OF FP
	ADD	S2,T1			;ADD IN ADR OF FP
	MOVEM	S2,J$GSTG(J)		;AND SAVE ADDRESS OF NAME
	HRRO	S2,S2			;GET POINTER TO STRING
	MOVX	S1,GJ%SHT!GJ%OLD	;SHORT GTJFN, OLD FILE ONLY
	GTJFN				;FIND IT
	  JRST	FNDL.3			;NOPE!!
	MOVEM	S1,J$GJFN(J)		;GOT IT, SAVE THE JFN
	POPJ	P,			;AND RETURN

FNDL.3:	MOVX	S1,GJ%SHT!GJ%FOU	;SHORT GTJFN, FOR OUTPUT USE
	HRRO	S2,J$GSTG(J)		;GET THE STRING
	GTJFN				;MAKE IT
	  JRST	FNDL.4			;REALLY SHOULDN'T HAPPEN
	MOVEM	S1,J$GJFN(J)		;SAVE THE JFN
	POPJ	P,			;AND RETURN

FNDL.4:	OFF	S,JOBLOG		;MAKE NO LOG FILE
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
IFN FTUUOS,<
FNDL.2:	ON	S,JOBLOG		;THERE IS A LOG FILE
	LOAD	T3,.FPSIZ(T1),FP.FHD	;GET SIZE OF THE FP
	LOAD	T4,.FPSIZ(T1),FP.FFS	;GET SIZE OF FD
	SUBI	T4,FDMSIZ		;SUB THE MIN, YIELDING #SFDS
	ADD	T1,T3			;AND POINT TO THE FD
	MOVEI	T2,.RBPRV		;GET SIZE OF UUO BLOCK
	MOVEM	T2,J$GUUO+.RBCNT(J)	;AND SAVE THE BLOCK SIZE
	LOAD	T2,.FDNAM(T1)		;GET THE FILE NAME
	MOVEM	T2,J$GUUO+.RBNAM(J)	;AND SAVE IT
	LOAD	T2,.FDEXT(T1)		;GET THE EXTENSION
	HLLZM	T2,J$GUUO+.RBEXT(J)	;AND SAVE IT
	MOVSI	T2,J$GPAT(J)		;GET ADDRESS OF PATH BLOCK
	HRRI	T2,J$GPAT+1(J)		;AND MAKE A BLT POINTER
	CLEARM	J$GPAT(J)		;CLEAR THE FIRST WORD
	BLT	T2,J$GPAT+7(J)		;AND ZERO THE BLOCK OUT
	MOVEI	T2,J$GPAT+2(J)		;SETUP TO BLT THE PATH
	HRLI	T2,.FDPPN(T1)		;T2 HAS A BLT POINTER
	ADD	T4,J			;T4 HAD NUMBER OF SFDS
	BLT	T2,J$GPAT+2(T4)		;AND BLT THE PATH
	MOVEI	T2,J$GPAT(J)		;GET ADDRESS OF PATH BLOCK
	SKIPN	J$GPAT+3(J)		;IS THERE AN SFD?
	MOVE	T2,J$GPAT+2(J)		;NO, GET THE PPN
	MOVEM	T2,J$GUUO+.RBPPN(J)	;AND SAVE IN LOOKUP BLOCK

	MOVX	T2,FO.PRV+.FOAPP+<LOGF>B17;APPEND AND USE MY PRIVS ON CHN LOGF
	MOVEM	T2,J$GFLP+.FOFNC(J)	;STORE THE FUNCTION
	MOVEI	T2,.IOASC		;ASCII MODE
	MOVEM	T2,J$GFLP+.FOIOS(J)	;STORE IT
	LOAD	T2,.FDSTR(T1)		;GET THE STRUCTURE
	MOVEM	T2,J$GFLP+.FODEV(J)	;AND STORE IT
	MOVSI	T2,J$GBRH(J)		;OBUF,,0
	MOVEM	T2,J$GFLP+.FOBRH(J)	;SAVE IT
	MOVSI	T2,1			;ONE OUTPUT BUFFER
	MOVEM	T2,J$GFLP+.FONBF(J)	;SAVE IT
	MOVEI	T2,J$GUUO(J)		;ADDRESS OF LOOKUP BLOCK
	MOVEM	T2,J$GFLP+.FOLEB(J)	;STORE IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS
SUBTTL	STALOG  --  Put startup messages in the log

STALOG:	STAMP	LPDAT			;PUT IN A DATE STAMP
	TELL	LOG,%%LSJ		;AND AN INTRO MESSAGE
	STAMP	LPDAT			;ANOTHER STAMP
	MOVE	T1,.EQJOB(J)		;GET JOB NAME
	LOAD	N,.EQSEQ(J),EQ.SEQ	;AND THE SEQUENCE NUMBER
	TELL	LOG,%%SJS		;AND GIVE JOB INFO
	MOVE	T1,.EQAFT(J)		;GET REQUEST CREATED TIME
	PUSHJ	P,PRDTA			;PRINT IT
	MOVEI	C,"]"			;AND A CLOSE BRACKET
	PUSHJ	P,SEND			;SEND IT
	TELL	LOG,CRLF		;SEND A CRLF
	POPJ	P,			;AND RETURN
SUBTTL	CHRLOG  --  Type a character in the log file

;CALL WITH THE CHARACTER TO TYPE IN ACCUMULATOR C.  ASSUMES THAT
;	THE LOG IS OPEN FOR WRITING.

IFN FTUUOS,<
CHRLOG:	TXNN	S,JOBLOG		;IS THERE A LOG FILE?
	JRST	CHRL.2			;NO, USE INTERNAL LOG
	SOSG	J$GBCT(J)		;ANY ROOM IN THE BUFFER?
	PUSHJ	P,CHRL.1		;NO, ADVANCE
	IDPB	C,J$GBPT(J)		;DEPOSIT A BYTE
	POPJ	P,			;AND RETURN

CHRL.1:	OUT	LOGF,			;OUTPUT THE BUFFER
	  POPJ	P,			;AND RETURN
	TELL	OPR!USR,%%EWL		;ERROR WRITING LOG
	OFF	S,JOBLOG		;NO MORE LOG FILE
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
CHRLOG:	TXNN	S,JOBLOG		;IS THERE A LOG?
	JRST	CHRL.2			;NO, USE INTERNAL LOG
	MOVE	S1,J$GJFN(J)		;GET THE JFN
	MOVE	S2,C			;GET THE CHARACTER
	BOUT				;OUTPUT IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS


;HERE TO PLACE A CHARACTER IN THE INTERNAL LOG
CHRL.2:	SOSGE	J$GIBC(J)		;IS THERE ROOM?
	JRST	CHRL.3			;NO, GET ANOTHER PAGE
	IDPB	C,J$GIBP(J)		;YES, DEPOSIT THE CHARACTER
	POPJ	P,			;AND RETURN

CHRL.3:	PUSH	P,C			;SAVE C
	SETZ	C,			;AND CLEAR IT
	IDPB	C,J$GIBP(J)		;TERMINATE WILL A NULL
	PUSHJ	P,BUFLOG		;GET ANOTHER PAGE
	POP	P,C			;RESOTRE C
	JRST	CHRL.2			;AND TRY AGAIN
SUBTTL	STPLOG  --  Timestamp the LOG File

;SUBROUTINE TO PUT A TIME STAMP IN THE LOG
;
;CALLED BY THE STAMP LUUO

STPLOG:	PUSH	P,.JBUUO##	;SAVE THE UUO ON THE STACK
	PUSHJ	P,OPNLOG	;OPEN THE LOG FILE UP
	LDB	P2,PS		;SAVE SOME BITS FROM
	MOVEI	P1,LOG		; THE STATUS AC AND
	DPB	P1,PS		; PUT IN OUR OWN BITS
	PUSHJ	P,PRTIME	;PRINT THE TIME
	HRRZ	T1,0(P)		;GET ADR OF STAMP
	MOVE	T1,(T1)		;GET THE STAMP
	MOVEI	C," "		;PRINT A SPACE
	PUSHJ	P,SEND		;.. 
	PUSHJ	P,SIXOUT	;PRINT THE KEY WORD
	MOVEI	C,11		;PRINT A TAB
	PUSHJ	P,SEND		; ..
	POP	P,0(P)		;CLEAR TOP OF STACK
	AOS	J$GNLN(J)	;ONE MORE LINE
	POPJ	P,0		;AND RETURN


LPMSG:	SIXBIT	/LPMSG/
LPDAT:	SIXBIT	/LPDAT/
LPOPR:	SIXBIT	/LPOPR/
LPERR:	SIXBIT	/LPERR/
LPSUM:	SIXBIT	/LPSUM/
SUBTTL	OPNLOG  --  Open the LOG File

;CALLED TO OPEN THE LOG FILE AND APPEND TO IT

IFN FTUUOS,<
OPNLOG:	TXNE	S,JOBLOG	;IS THERE A LOG FILE?
	TXNE	S,LOGOPN	;YES, IS IT OPEN ALREADY?
	POPJ	P,		;NO LOG, OR ITS OPEN ALREADY - RETURN
	MOVE	S2,J$GBUF(J)	;GET ADDRESS OF LOG BUFFER
	EXCH	S2,.JBFF	;FAKE OUT THE MONITOR
	MOVEI	S1,J$GFLP(J)	;GET ADDRESS OF FILOP BLOCK
	HRLI	S1,6		;AND BLOCK LENGTH
	FILOP.	S1,		;OPEN THE FILE
	  JRST OPNL.1		;CAN'T DO IT?
	MOVEM	S2,.JBFF	;RESTORE JOBFF
	ON	S,LOGOPN	;ITS OPEN
	POPJ	P,		;RETURN

OPNL.1:	MOVEM	S2,.JBFF	;RESTORE JOBFF
	PJRST	RIDLOG		;CLOSE OFF LOG AND GET RID OF IT
>  ;END IFN FTUUOS

IFN FTJSYS,<
OPNLOG:	TXNE	S,JOBLOG	;IS THERE A LOG FILE
	TXNE	S,LOGOPN	;WHICH IS NOT OPEN
	POPJ	P,		;NO
	MOVE	S1,J$GJFN(J)	;GET THE JFN
	MOVX	S2,<7B5+OF%APP>	;7 BIT BYTES, APPEND
	OPENF			;OPEN IT
	  PJRST	RIDLOG		;LOSE, GET RID OF LOG
	ON	S,LOGOPN	;FLAG SUCCESS
	POPJ	P,		;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	CLSLOG  --  Close the LOG File

;ROUTINE TO CLOSE OFF THE LOG FILE, DUMPING ALL BUFFERS ETC.

IFN FTUUOS,<
CLSLOG:	CLOSE	LOGF,		;CLOSE THE CHANNEL
	OFF	S,LOGOPN	;CLEAR THE FLAG
	POPJ	P,		;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
CLSLOG:	TXC	S,JOBLOG!LOGOPN	;COMPLEMENT THESE TWO BITS
	TXCE	S,JOBLOG!LOGOPN	;RE-COMPLEMENT AND TEST
	POPJ	P,		;NOTHING TO CLOSE
	MOVE	S1,J$GJFN(J)	;GET THE LOG'S JFN
	TXO	S1,1B0		;SET "DON'T" RELEASE THE JFN
	CLOSF			;CLOSE THE FILE
	  JFCL			;IGNORE ANY ERRORS
	OFF	S,LOGOPN	;CLEAR THE FLAG
	POPJ	P,		;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	RIDLOG  --  Release the LOG File

;ROUTINE TO RELEASE THE LOG FILE, DUMPING ALL BUFFERS ETC.

IFN FTUUOS,<
RIDLOG:	TXNN	S,JOBLOG		;IS THERE A LOG?
	POPJ	P,			;NO, JUST RETURN
	RELEAS	LOGF,			;RELEASE THE CHANNEL
	OFF	S,LOGOPN!JOBLOG		;CLEAR THE FLAGS
	SETZM	J$GNLN(J)		;CLEAR LINE COUNT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
RIDLOG:	TXNN	S,JOBLOG		;IS THERE A LOG?
	POPJ	P,			;NOTHING TO CLOSE
	PUSHJ	P,CLSLOG		;MAKE SURE ITS CLOSED
	MOVE	S1,J$GJFN(J)		;GET THE LOG'S JFN
	RLJFN				;RELEASE THE JFN
	  JFCL				;IGNORE ANY ERRORS
	OFF	S,LOGOPN!JOBLOG		;CLEAR THE FLAGS
	SETZM	J$GNLN(J)		;CLEAR THE LINE COUNT
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	BUFLOG  --  Get a buffer page for LOG

BUFLOG:	PUSHJ	P,.SAVE1##		;SAVE P1
	AOS	P1,J$GINP(J)		;INCREMENT BUFFER PAGE COUNT
	CAIL	P1,^D10			;WITHIN RANGE?
	  HALT				;NO, DIE FOR NOW
	PUSHJ	P,M$ACQP##		;GET A PAGE
	PG2ADR	AP			;MAKE AN ADDRESS
	ADDI	P1,-1(J)		;POINT TO LOCATION IN J$GBUF
	MOVEM	AP,J$GBUF(P1)		;STORE THE ADDRESS
	HRLI	AP,(POINT 7,0)		;MAKE A BYTE POINTER
	MOVEM	AP,J$GIBP(J)		;AND STORE IT
	MOVEI	S1,<5*1000>-1		;GET A COUNT
	MOVEM	S1,J$GIBC(J)		;STORE IT
	POPJ	P,			;AND RETURN
SUBTTL	CLNLOG  --  Cleanup the LOG File buffers

CLNLOG:	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	MOVE	P1,J$GINP(J)		;GET NUMBER OF PAGES IN P1
	MOVEI	P2,J$GBUF(J)		;GET ADR OF ADR OF 1ST PAGE IN P2

CLNL.1:	JUMPE	P1,.POPJ##		;DONE IF NO MORE PAGES
	MOVE	AP,0(P2)		;GET ADDRESS OF PAGE
	ADR2PG	AP			;MAKE A PAGE NUMBER
	PUSHJ	P,M$RELP##		;RETURN IT
	SOJ	P1,			;DECREMENT PAGE COUNT
	AOJA	P2,CLNL.1		;BUMP POINTER AND LOOP
SUBTTL	Utility Routines

;	SUSPND	--		ROUTINE TO SUSPEND JOB FOR TIME PERIOD
;	SNDSTC	--		SEND A STATUS CHANGE
;	SETHEL	--		SETUP A HELLO BLOCK


	LOWSEG				;THESE ARE IN THE LOWSEG
SUBTTL	SUSPND  --  Suspend job for a given length of time

;CALL WITH THE NUMBER OF SECONDS IN S1

IFN FTUUOS,<
SUSPND:	IMULI	S1,^D1000		;CONVERT TO MILLISECS
	HIBER	S1,			;AND SLEEP
	  HALT
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
SUSPND:	IMULI	S1,^D1000		;CONVERT TO MILLISECS
	SETOM	BLOKED			;WE ARE SLEEPING
	SKIPN	AWOKEN			;INTERRUPTED SINCE LAST INSTRUCTION?
	DISMS				;SLEEP
	JFCL				;**DO NOT REMOVE THIS INSTRUCTION**
SUSP.1:	SETZM	AWOKEN			;WE ARE UP
	SETZM	BLOKED			;INSURE THAT EVERYONE KNOWS IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	Subroutines  --  Send a Status Change

;SNDSTC CALLS SETHEL TO SETUP THE HELLO BLOCK, ORS IN THE STATUS
;	CHANGE FLAG, AND SENDS IT TO QUASAR.

;SNDSTC WILL TURN OFF THE SCHEDULING BIT IF EITHER RUNB IS OFF OR
;	PAUSEB IS ON.

SNDSTC:	TXNN	S,STARTD		;ARE WE STARTED?
	POPJ	P,			;NO, WE ARE NOT KNOWN COMPONENT
	PUSHJ	P,SETHEL		;SET UP THE HELLO BLOCK
	MOVX	T1,HELSTC		;GET THE STATUS CHANGE FLAG
	IORM	T1,MSGBLK+HEL.ST	;STORE IT IN
	MOVX	T1,HELSCH		;LOAD THE BIT
	TXNE	S,RUNB			;IS RUNB OFF?
	TXNE	S,PAUSEB		;NO, IS PAUSEB ON?
	ANDCAM	T1,MSGBLK+HEL.ST	;YES, CLEAR THE BIT
	MOVEI	T1,MSGBLK		;LOAD ADDRESS OF HELLO BLOCK
	PJRST	SNDQSR##		;AND SEND IT OFF
SUBTTL	Subroutines  --  Setup HELLO Block

;SETHEL SETS UP THE ENTIRE HELLO BLOCK EXCEPT FOR THE STATUS WORD.
;	IT CORRECTLY SETS THE HELSCH, HELFRZ, HELLLP BITS IN THE STATUS WORD.

SETHEL:	MOVX	T1,<HEL.SZ,,.QOHEL>	;GET LENGTH,,FUNCTION
	MOVEM	T1,MSGBLK		;SAVE AS FIRST WORD

	MOVX	T1,'LPTSPL'		;GET PROGRAM NAME
	MOVEM	T1,MSGBLK+HEL.NM	;SAVE IT

	MOVE	T1,J$LSDV(J)		;GET SCHEDULING DEVICE
	MOVEM	T1,MSGBLK+HEL.SD	;SAVE IT

	MOVE	T1,J$LDEV(J)		;GET PHYSICAL DEVICE NAME
	MOVEM	T1,MSGBLK+HEL.PD	;SAVE PROCESSING DEVICE

	MOVE	T1,J$FSFM(J)		;GET SCHEDULING FORMS
	MOVEM	T1,MSGBLK+HEL.I1	;SAVE IT

	MOVS	T1,J$XMLM(J)		;GET MLIMIT,,0
	HRR	T1,NXTJOB		;GET MLIMIT,,NXTJOB
	MOVEM	T1,MSGBLK+HEL.I2	;SAVE IT

	SETZM	MSGBLK+HEL.I3		;CLEAR UNUSED WORD

	MOVEI	T1,%%.QSR		;START WITH NO FLAGS,,VERSION
	TXNE	S,FROZE			;ARE FORMS FROZEN?
	TXO	T1,HELFRZ		;YES, OR IN THE FREEZE BIT
	TXNE	S,STARTD		;HAS HE SAID START?
	TXO	T1,HELSCH		;YES, SET SCHEDUABLE BIT
	SKIPE	J$LLCL(J)		;IS IT A LOWER CASE PRINTER?
	TXO	T1,HELLLP		;YES, SET THE FLAG
	TXO	T1,HELRDE		;ALSE, WE CAN HANDLE RDE JOBS
	MOVEM	T1,MSGBLK+HEL.ST	;STORE IT
	MOVE	T1,MYSTA		;GET MY STATION NUMBER
	STORE	T1,MSGBLK+HEL.ST,HELDSN	;STORE AS DEFAULT
	POPJ	P,			;AND RETURN
SUBTTL	Disk File Input Routines


;	FILL	--		FILL THE INPUT BUFFER
;	SETEOF	--		CAUSE EOF ON NEXT INPUT
;	REWIND	--		REWIND THE INPUT FILE
;	DSKIN	--		READ A BYTE FROM THE INPUT FILE
;	SETRMS  --		SETUP TO MAKE AN RMS CALL
;	RMSERR  --		SET AN RMS ERROR


	LOWSEG			;THESE ARE IN THE LOWSEG
SUBTTL	FILL  -  Fill the input buffer

;SUBROUTINE TO FILL DISK INPUT BUFFER
;CALL WITH:
;	PUSHJ	P,FILL
;	  EOF RETURN
;	DATA RETURN

IFN FTUUOS,<
FILL:	PUSHJ	P,CHKQUE		;SEE IF WE'VE RECEIVED ANY MSGS
	SKIPE	J$XSBC(J)		;IS THERE A SAVED BYTE COUNT?
	JRST	FILLB			;YES, XCT FAST BACKSPACE CODE
	AOS	J$DINF(J)		;INCREMENT BLOCK COUNT
	IN	DSK,			;READ BLOCK
	  PJRST	.POPJ1##		;SKIP BACK OK
	JRST	FILL1			;I/O ERROR

FILLB:	PUSHJ	P,.SAVE2##		;SAVE P1 AND P2
	MOVSI	P1,(IN DSK,)		;LOAD THE UUO
	HRR	P1,J$DBRH(J)		;MAKE BELIEVE WE'RE CHANGING RINGS
	XCT	P1			;DO THE UUO
	  SKIPA				;WIN!!
	JRST	FILL1			;LOSE
	MOVE	P1,J$XSBC(J)		;GET SAVED BYTE COUNT
	EXCH	P1,J$DBCT(J)		;SAVE IT AS BYTE COUNT, LOAD REAL ONE
	SUB	P1,J$XSBC(J)		;CALCULATE AN OFFSET
	CLEARM	J$XSBC(J)		;AND CLEAR THE FLAG
	IDIVI	P1,5			;CONVERT TO WORDS
	ADDM	P1,J$DBPT(J)		;ADD IN WORDS
	AOS	J$DBPT(J)		;AND MOVE UP ONE MORE
	MOVE	P1,[440700
		    350700
		    260700
		    170700
		    100700](P2)		;LOAD THE BYTE OFFSET
	HRLM	P1,J$DBPT(J)		;STORE IT
	PUSHJ	P,TAKCHK		;TAKE A CHECKPOINT
	PJRST	.POPJ1##		;AND RETURN


				;"FILL" IS CONTINUED ON THE NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

FILL1:	PUSHJ	P,.SAVE1##		;SAVE P1
	STATZ	DSK,IO.EOF		;END OF FILE?
	  POPJ	P,			;YES, TAKE NON-SKIP
	GETSTS	DSK,N			;NO, GET DEVICE STATUS
	MOVE	P1,N			;GET STATUS INTO P1
	STAMP	LPERR			;GIVE A STAMP
	TELL	LOG,%%IDE		;GIVE A MESSAGE
	SKIPE	MSGERR			;SHOULD OPR SEE?
	TELL	OPR,%%IDE		;YES, SHOW HIM
	TXZ	P1,IO.ERR		;TURN OFF ERROR BITS
	SETSTS	DSK,(P1)		;AND SET STATUS
	SOSLE	J$DERR(J)		;TOO MANY??
	JRST	.POPJ1##		;NO, RETURN OK
	TELL	LOG,%%FSD
	SKIPE	MSGERR
	TELL	OPR,%%FSD
	MOVEI	P1,1			;MAKE THIS THE LAST COPY
	MOVEM	P1,J$XCOP(J)		;AND STORE IT SO WE DON'T REPRINT IT
	POPJ	P,			;YES, PUNT
>  ;END IFN FTUUOS
IFN FTJSYS,<
FILL:	PUSHJ	P,.SAVET##		;SAVE T1-T4
	PUSHJ	P,CHKQUE		;SEE IF WE'VE RECEIVED ANY MESSAGES
	SKIPE	J$DRMS(J)		;IS IT AN RMS FILE?
	JRST	FILL.3			;YES, GO A DIFFERENT ROUTE
	MOVE	S1,J$DBIF(J)		;GET #BYTES LEFT TO READ
	JUMPE	S1,.POPJ##		;NONE, EOF!!
	CAIL	S1,1000			;LESS THAN A FULL PAGE?
	JRST	FILL.1			;NO, CONTINUE
	SETZM	J$DBIF(J)		;YES, CAUSE EOF ON NEXT ONE
	JRST	FILL.2			;AND MEET AT THE PASS

FILL.1:	MOVNI	T1,1000			;LOAD NEGATIVE NUMBER OF WORDS
	ADDM	T1,J$DBIF(J)		;AND DECREMENT NUMBER LEFT
	MOVN	S1,T1			;AND GET NUMBER BACK

FILL.2:	MOVN	T1,S1			;GET NEGATIVE WORD COUNT
	HRRZ	T2,J$DMOD(J)		;GET BYTES/WORD
	IMUL	S1,T2			;CONVERT TO NUMBER OF BYTES
	MOVEM	S1,J$DBCT(J)		;AND STORE FOR PRINTING LOOP
	MOVE	S1,J$DJFN(J)		;GET THE JFN
	MOVE	S2,J$DBUF(J)		;GET POINTER TO THE BUFFER
	HRLI	S2,(POINT 36,0)		;AND MAKE A BYTE POINTER
	SIN				;GET THE DATA
	MOVE	S1,J$DBUF(J)		;GET ADDRESS OF BUFFER
	HLL	S1,J$DMOD(J)		;MAKE A BYTE POINTER
	MOVEM	S1,J$DBPT(J)		;STORE IT
	AOS	J$DINF(J)		;INCREMENT PAGE COUNT
	PJRST	.POPJ1##		;AND SKIP BACK

FILL.3:	SKIPN	J$DBIF(J)		;WAS EOF SET EXTERNALLY?
	POPJ	P,			;YES, RETURN EOF
	PUSHJ	P,SETRMS		;SETUP TO CALL RMS
	MOVEI	AP,J$DRAB(J)		;GET ADDRESS OF THE RAB
	$GET	<(AP)>,RMSERR		;GET A RECORD
	SKIPE	J$DRME(J)		;AN ERROR?
	POPJ	P,			;YES, ASSUME EOF
	SKIPGE	S1,J$DRFA(J)		;GET FIRST RFA IF SET
	$LDRAB	S1,RFA			;NOT SET, GET THIS ONE
	MOVEM	S1,J$DRFA(J)		;SET FIRST RFA
	$LDRAB	S1,RSZ			;GET THE RECORD SIZE
	PJUMPE	S1,.POPJ##		;RETURN EOF IF ZERO
	MOVEM	S1,J$DBCT(J)		;ELSE SAVE BYTE COUNT
	$LDRAB	S1,RBF			;LOAD ADDRESS OF RECORD
	HLL	S1,J$DMOD(J)		;MAKE A BYTE POINTER
	MOVEM	S1,J$DBPT(J)		;STORE IT
	PJRST	.POPJ1##		;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	SETEOF  -  Cause EOF on next input

;SUBROUTINE TO CAUSE "EOF" TO BE RETURNED ON THE NEXT INPUT CHARACTER
;
;CALL:
;	PUSHJ	P,SETEOF
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
SETEOF:	TXNN	S,DSKOPN		;IS THE DISK-FILE OPEN?
	POPJ	P,			;NO, JUST RETURN
	USETI	DSK,-1			;YES, DO THE USETI
	IN	DSK,			;AND CLEEAR BUFFERS AHEAD
	  JRST	.-1			;GET ALL BUFFERS
	SETOM	J$DBCT(J)		;CAUSE THE SOSG TO FAIL
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
SETEOF:	SETZM	J$DBIF(J)		;0 BYTES LEFT IN THE FILE
	SETZM	J$DBCT(J)		;0 BYTES LEFT IN CURRENT BUFFER
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	REWIND  -  Rewind the input file

;REWIND IS CALLED THE REWIND THE INPUT FILE (I.E CAUSE
;	SUBSEQUENT READS TO COME FROM THE BEGINNING OF THE
;	FILE).
;CALL:
;	PUSHJ P,REWIND
;	  ALWAYS RETURN HERE

IFN FTUUOS,<
REWIND:	PUSHJ	P,SETEOF		;CLEAR ALL BUFFERING AHEAD
	TXNE	S,DSKOPN		;IS THE FILE OPEN?
	USETI	DSK,1			;YES, REWIND IT
	SETOM	J$DBCT(J)		;IGNORE CURRENT BUFFER
	PUSHJ	P,CLRTAB		;CLEAR BACKSPACE TABLE
	SETZM	J$DINF(J)		;CLEAR INFO WORD
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS

IFN FTJSYS,<
REWIND:	TXNN	S,DSKOPN		;IS THE FILE OPEN?
	POPJ	P,			;NO, JUST RETURN
	SKIPE	J$DRMS(J)		;RMS FILE?
	JRST	REWI.1			;YES, DO DIFFERENT THINGS
	MOVE	S1,J$DJFN(J)		;YES, GET THE JFN
	SETZ	S2,			;SET POINTER TO BYTE 0
	SFPTR				;DO IT!!
	  HALT
	SETZM	J$DINF(J)		;CLEAR INFO WORD
	MOVEI	S1,^D36			;LOAD A 36
	LDB	S2,[POINT 6,J$DFDB+.FBBYV(J),11]
	IDIV	S1,S2			;GET 36/<FILES BYTE SIZE>
	MOVE	S2,J$DFDB+.FBSIZ(J)	;GET SIZE OF FILE
	IDIV	S2,S1			;CONVERT TO # 36BIT BYTES
	SKIPE	S2+1			;ANY RESIDUE?
	AOS	S2			;YES ADD ANOTHER WORD
	MOVEM	S2,J$DBIF(J)		;AND INITIALIZE THE COUNTER
	SETZM	J$DBCT(J)		;AND THE BUFFER
	POPJ	P,			;AND RETURN

REWI.1:	SETOM	J$DBIF(J)		;CLEAR EOF INDICATOR
	SKIPGE	S1,J$DRFA(J)		;GET RFA OF FIRST RECORD
	POPJ	P,			;FIRST TIME THRU, JUST RETURN
	$STRAB	S1,RFA			;STORE THE RFA
	MOVX	S1,RB$RFA		;FIND BY RFA
	$STRAB	S1,RAC			;STORE NEW RECORD ACCESS
	PUSHJ	P,SETRMS		;SETUP TO CALL RMS
	MOVEI	AP,J$DRAB(J)		;LOAD ADDRESS OF RAB
	$FIND	<(AP)>,RMSERR		;FIND THE RECORD
	MOVX	S1,RB$SEQ		;SEQUENTIAL ACCESS
	$STRAB	S1,RAC			;STORE IT
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	DSKIN  -  Read a byte from the input file

;DSKIN IS CALLED TO READ THE NEXT BYTE FROM THE INPUT FILE.  IN
;	MOST CASES EACH ROUTINE PERFORMS THE SOSG LOOP ITSELF FOR
;	THE SAKE OF EFFICIENCY SINCE THE PUSHJ/POPJ PAIR TO CALL
;	THIS ROUTINE ON EVERY CHARACTER IS EXPENSIVE.  HOWEVER, IN
;	THE CASES WHERE EFFICIENCY IS NOT AN ISSUE, THIS ROUTINE CAN
;	BE USED.
;RETURNS WITH NEXT BYTE IN ACCUMULATOR "C".
;
;CALL:
;	PUSHJ P,DSKIN
;	  RETURN HERE ON EOF
;	  RETURN HERE NORMALLY

DSKIN:	SOSLE	J$DBCT(J)	;COUNT DOWN WORDS
	JRST	DSKI.1		;SOME LEFT
	PUSHJ	P,FILL		;REFILL
	  POPJ	P,
DSKI.1:	ILDB	C,J$DBPT(J)	;GET A CHAR
	JRST	.POPJ1##	;RETURN
SUBTTL	SETRMS - RMSERR	-   RMS Interface Routines

IFN FTJSYS,<
;CALL SETRMS BEFORE EXECUTING ANY RMS MACRO TO CLEAR THE ERROR INDICATOR

SETRMS:	SETZM	J$DRME(J)		;CLEAR THE ERROR FLAG
	POPJ	P,			;AND RETURN

;RMSERR SHOULD BE THE ERROR ADDRESS ON ALL RMS MACRO CALLS.  RMS WILL
;	CALL RMSERR ON AN ERROR.  ON RETURN FROM AN RMS CALL, J$DRME
;	WILL BE -1 IF AN ERROR OCCURED, AND S1 WILL CONTAIN THE ERROR
;	CODE.

RMSERR:	SETOM	J$DRME(J)		;SET THE ERROR
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
SUBTTL	Forms MOUNT Routines

;SUBROUTINE TO ASK OPR TO CHANGE OUTPUT FORMS
;CALL WITH:
;	PUSHJ	P,MOUNT
;	RETURN HERE WITH DEVICE READY

	TOPSEG			;PUT THIS IN THE HISEG

MOUNT:	SKIPGE	FMNEW			;HAVE WE RE-READ LPFORM.INI?
	PUSHJ	P,FRMINI		;YES, REINIT FORMS PARAMETERS
	SETZM	FMNEW			;CLEAR THE FLAG
	MOVE	T1,J$FORM(J)		;GET CURRENT FORMS
	MOVEM	T1,J$FPFM(J)		;SAVE AS OLD FORMS TYPE
	MOVE	T1,.EQLM1(J)		;GET FORMS TYPE
	MOVEM	T1,J$FSFM(J)		;SAVE AS SCHEDULED TYPE
	CAMN	T1,J$FORM(J)		;SAME AS CURRENTLY MOUNTED?
	POPJ	P,			;YES, RETURN
	MOVEM	T1,J$FORM(J)		;SAVE NEW FORMS TYPE
	XOR	T1,J$FPFM(J)		;XOR WITH OLD ONES
	TXZ	T1,FRMSK2		;ZAP INSIGNIFICANT BITS
	JUMPE	T1,MOUNT0		;THE SAME, DON'T TELL OPR
	MOVE	T1,J$FORM(J)		;LOAD FORMS NAME AGAIN
	TELL	OPR,MOUNTM		;ASK OPR TO MOUNT 'EM
	ON	S,MNTBIT		;FLAG THAT WE WAIT
MOUNT0:	PUSHJ	P,FRMINI		;INITIALIZE FORMS
	TXNN	S,MNTBIT		;DO WE WAIT FOR OPR?
	POPJ	P,			;NO, JUST RETURN

MOUNT1:	SKIPE	J$LHNG(J)		;IS THE DEVICE OFF-LINE?
	JRST	MOUNT2			;YES, FORGET THE FORMFEED
	PUSHJ	P,SENDFF		;SEND A FORMFEED
	PUSHJ	P,OUTDMP		;AND DUMP IT OUT
MOUNT2:	OFF	S,RUNB			;TURN OFF RUN FLAG
	TELL	OPR,STAR		;AND TYPE A STAR
	MOVEI	T1,<AUTTIM>-1		;LOAD NUMBER OF SLEEPS
MOUNT3:	JUMPE	T1,MOUNT4		;TIMEOUT IF ZERO
	MOVEI	S1,^D60			;1 MINUTE
	PUSHJ	P,SUSPND		;DO IT
	SKIPN	TTYFLG			;DID OPR TYPE SOMETHING?
	SOJA	T1,MOUNT3		;DECREMENT COUNT AND LOOP
	PUSHJ	P,CHKOPR		;WAIT FOR A GO COMMAND
	PJRST	LODVFU			;LOAD THE VFU AND RETURN
MOUNT4:	TELLN	OPR,WAITED		;I TRIED!!
	PUSHJ	P,FREEZE		;FREEZE FORMS
	JRST	REQUE			;AND REQUE IT

WAITED:	ASCIZ /[Automatically requeuing job and Freezing forms]
/
SUBTTL	Special Forms Handler

FRMINI:	PUSHJ	P,SETDFF		;SET DEFAULT PARAMTERS
	SKIPN	C,FMADR			;IS THERE AN LPFORM.INI?
	POPJ	P,			;NO, JUST RETURN
	HRLI	C,440700		;YES, MAKE A BYTE POINTER
	MOVEM	C,FMBPT			;AND SAVE IT
	PUSHJ	P,FRMIN1		;DO EVERYTHING
	PJRST	LODVFU			;LOAD THE VFU AND RETURN

FRMIN1:	PUSHJ	P,FH$SIX		;GET THE FORMS NAME
	  POPJ	P,			;EOF!!
	CAMN	T1,J$FORM(J)		;MATCH??
	JRST	FRMIN2			;YES!!
FRMI1A:	PUSHJ	P,FH$EOL		;NO, FIND NEXT LINE
	  POPJ	P,			;EOF!!
	JRST	FRMIN1			;AND LOOP


FRMIN2:	CAIN	C,"/"			;BEGINNING OF SWITCH?
	JRST	FRMIN5			;YES, LOCATOR IS "ALL"
	CAIN	C,":"			;BEGINNING OF LOCATOR?
	JRST	FRMIN3			;YES, GO GET IT
	CAIN	C,.CHLFD		;EOL?
	JRST	FRMIN1			;YES, GO THE NEXT LINE
	PUSHJ	P,FH$CHR		;ELSE, GET A CHARACTER
	  POPJ	P,			;EOF
	JRST	FRMIN2			;AND LOOP

FRMIN3:	PUSHJ	P,FH$SIX		;GET A LOCATOR
	  POPJ	P,			;EOF!!
	JUMPE	T1,FRMI3A		;MAYBE PAREN??
	JRST	FRMIN4			;AND DO THE LIST

FRMI3A:	CAIN	C,"/"			;A SWITCH?
	JRST	FRMIN5			;YES!
	CAIE	C,"("			;A LIST?
	JRST	FRMIN9			;NO, ERROR
FRMIN4:	HLRZ	T2,T1			;GET THE FIRST THREE CHARS
	CAIN	T2,'ALL'		;IS IT "ALL"?
	JRST	FRMIN5			;YES, STOP CHECKING
	CAIN	T2,'LOC'		;IS IT LOCAL?
	SKIPGE	J$LREM(J)		;YES, ARE WE?
	  SKIPA				;NO, NO
	JRST	FRMIN5			;YES, YES!
	CAIN	T2,'REM'		;DOES IT SAY "REMOTE"?
	SKIPL	J$LREM(J)		;YES, ARE WE REMOTE
	  SKIPA				;NO!!!
	JRST	FRMIN5			;YES!!
	CAIE	T2,'LPT'		;IS IT "LPT"
	JRST	FRMI4B			;NO, TRY ONE LAST THING
	CAMN	T1,J$LDEV(J)		;COMPARE TO OUR DEVNAM
	JRST	FRMIN5			;MATCH!!
	CAMN	T1,J$LGNM(J)		;NO, TRY GIVEN NAME
	JRST	FRMIN5			;WIN!!

FRMI4B:	CAIN	C,.CHLFD		;BREAK ON EOL?
	JRST	FRMIN1			;YES, GET NEXT LINE
	CAIE	C,"/"			;IS IT A SLASH?
	CAIN	C,")"			;NO, CLOSE PAREN?
	JRST	FRMI1A			;YES, GET THE NEXT LINE
	PUSHJ	P,FH$SIX		;ELSE, GET THE NEXT LOCATOR
	  POPJ	P,			;EOF, RETURN
	JUMPE	T1,FRMIN9		;BAD FORMAT
	JRST	FRMIN4			;AND LOOP AROUND
;GET HERE IF THIS LINE IS FOR US

FRMIN5:	CAIN	C,.CHLFD	;WAS THE LAST CHARACTER A LINEFEED?
	POPJ	P,		;YES, RETURN
	CAIN	C,"/"		;ARE WE AT THE BEGINNING OF A SWITCH?
	JRST	FRMI5A		;YES, DO IT!
	PUSHJ	P,FH$CHR	;NO, GET A CHARACTER
	  POPJ	P,		;EOF!!
	JRST	FRMIN5		;AND LOOP AROUND
FRMI5A:	PUSHJ	P,FH$SIX	;GET THE SWITCH
	  POPJ	P,		;EOF!!
	JUMPN	T1,FRMIN6	;JUMP IF WE'VE GOT SOMETHING
	CAIN	C,.CHLFD	;EOL?
	POPJ	P,		;YES, RETURN
	JRST	FRMIN5		;ELSE, KEEP TRYING

FRMIN6:	MOVE	T4,T1		;SAVE SWITCH NAME FOR LATTER
	HLLZS	T1		;GET FIRST THREE CHARACTERS OF SWITCH
	MOVSI	T2,-F$NSW	;MAKE AOBJN POINTER

FRMIN7:	HLLZ	T3,FFNAMS(T2)	;GET A SWITCH NAME
	CAMN	T3,T1		;MATCH??
	JRST	FRMIN8		;YES, DISPATCH
	AOBJN	T2,FRMIN7	;NO, LOOP
	MOVE	T4,T1		;GET SWITCH NAME
	TELL	OPR,[ASCIZ /Unrecognized switch + in LPFORM.INI ignored
/]
	JRST	FRMIN5		;AND LOOP

FRMIN8:	HRRZ	T3,FFNAMS(T2)	;GET DISPATCH ADDRESS
	PUSHJ	P,(T3)		;GO!!
	JRST	FRMIN5		;AND LOOP


FRMIN9:	TELLN	OPR,[ASCIZ /Bad format in LPFORM.INI
/]
	POPJ	P,		;AND RETURN
SUBTTL	Forms Switch Subroutines


S$BANN:	PUSHJ	P,FH$DEC		;GET DECIMAL ARGUMENT
	MOVEM	T1,J$FBAN(J)		;STORE IT
	POPJ	P,			;AND RETURN

S$TRAI:	PUSHJ	P,FH$DEC		;GET DECIMAL ARGUMENT
	MOVEM	T1,J$FTRA(J)		;STORE IT
	POPJ	P,			;AND RETURN

S$HEAD:	PUSHJ	P,FH$DEC		;GET A DECIMAL ARGUMENT
	MOVEM	T1,J$FHEA(J)		;STORE IT
	POPJ	P,			;AND RETURN

S$LINE:	PUSHJ	P,FH$DEC		;GET DECIMAL ARGMENT
	MOVEM	T1,J$FLIN(J)		;STORE IT
	POPJ	P,			;AND RETURN

S$WIDT:	PUSHJ	P,FH$DEC		;GET DECIMAL ARGUMENT
	MOVEM	T1,J$FWID(J)		;SAVE IT
	MOVEI	T2,3			;ASSUME WIDTH CLASS 3
	MOVEM	T2,J$FWCL(J)		;SAVE WIDTH CLASS
	CAIG	T1,F$CL2		;LE CLASS 2 LIMIT?
	SOS	J$FWCL(J)		;YES, DECREMENT
	CAIG	T1,F$CL1		;LE CLASS 1 LIMIT
	SOS	J$FWCL(J)		;YES, DECREMENT AGAIN!
	POPJ	P,			;AND RETURN

S$RIBB:	PUSHJ	P,FH$SIX		;GET SIXBIT ARGUMENT
	  POPJ	P,			;EOF
	TELL	OPR,[ASCIZ /Ribbon: +
/]
	MOVEM	T1,J$FRIB(J)		;SAVE IT
	POPJ	P,			;AND RETURN
S$DRUM:
S$CHAI:	PUSHJ	P,FH$SIX		;GET SIXBIT ARG
	  POPJ	P,			;EOF!
	TELL	OPR,[ASCIZ /Drum (chain): +
/]
	MOVEM	T1,J$FDRU(J)		;SAVE IT
	POPJ	P,			;AND RETURN

S$NOTE:	MOVEI	T1,J$FNBK(J)		;ADDRESS OF NOTE BLOCK
	MOVEM	T1,J$FNOT(J)		;IS THE ADDRESS OF THE NOTE
	MOVE	T1,[POINT 7,J$FNBK+2(J)]
	CLEAR	T2,			;T1 IS POINTER, T2 IS COUNTER
	MOVE	C,[ASCII /[NOTE/]
	MOVEM	C,J$FNBK(J)
	MOVE	C,[ASCII /:    /]
	MOVEM	C,J$FNBK+1(J)

S$NOT1:	PUSHJ	P,FH$CHR		;GET A CHARACTER
	  JRST	S$NOT2			;EOF, FINISH UP!!
	CAIGE	C,40			;MAKE SURE ITS GREATER THAN SPACE
	  JRST	S$NOT2			;ITS NOT!, FINISH UP
	CAIN	C,"/"			;ALSO STOP ON SLASH
	JRST	S$NOT2			;IT IS!!
	IDPB	C,T1			;DEPOSIT IT
	CAIGE	T2,^D49			;LOOP FOR 50 CHARACTERS
	AOJA	T2,S$NOT1		;INCR AND LOOP

S$NOT2:	MOVEI	T2,"]"			;CLOSE BRACKET
	IDPB	T2,T1			;DEPOSIT IT
	MOVEI	T2,.CHCRT		;LOAD A CARRIAGE RETURN
	IDPB	T2,T1			;DEPOSIT IT
	MOVEI	T2,.CHLFD		;LOAD A LINEFEED
	IDPB	T2,T1			;DEPOSIT IT
	CLEAR	T2,			;LOAD A NULL
	IDPB	T2,T1			;DEPOSIT IT
	TELLN	OPR,J$FNBK(J)		;AND TYPE IT TO THE OPERATOR
	POPJ	P,			;AND RETURN

S$PAUS:	SETOM	J$FPAU(J)		;SET THE PAUSE FLAG
	POPJ	P,			;AND RETURN

S$WHAT:	SETOM	J$FWHA(J)		;SET WHAT FLAG
	POPJ	P,			;AND RETURN

S$ALCN:	PUSHJ	P,FH$DEC		;GET DECIMAL ARG
	MOVEM	T1,J$FALC(J)		;STORE IT
	POPJ	P,			;RETURN

S$ALSL:	PUSHJ	P,FH$DEC		;GET DECIMAL ARG
	MOVEM	T1,J$FALS(J)		;SAVE IT
	POPJ	P,			;AND RETURN
S$ALIG:	PUSHJ	P,FH$SIX		;GET SIXBIT ARGUMENT
	  POPJ	P,			;EOF
	MOVEM	T1,J$FALI(J)		;SAVE IT
	POPJ	P,			;AND RETURN

S$VFU:
S$TAPE:	PUSHJ	P,FH$SIX		;GET SIXBIT ARGUMENT
	  POPJ	P,			;EOF
	MOVEM	T1,J$FTAP(J)		;SAVE IT
	MOVE	T2,J$FORM(J)		;GET FORMS NAME
	CAMN	T2,NORMAL		;IS IT NORMAL?
	MOVEM	T1,D$TAPE		;YES, MAKE THIS THE DEFAULT
	POPJ	P,			;AND RETURN
SUBTTL	LODVFU  --  Load the Vertical Forms Unit

LODVFU:	MOVE	T1,J$FTAP(J)		;GET VFU TYPE
	CAMN	T1,J$FLVT(J)		;SAME AS CURRENT ONE?
	POPJ	P,			;YES, RETURN
	SKIPE	J$LDVF(J)		;NO, DOES DEVICE HAVE A DAVFU?
	JRST	LODV.0			;YES, AUTO-LOAD
	MOVE	T1,J$FTAP(J)		;GET DESIRED TAPE
	MOVE	T2,T1			;IN BOTH T1 AND T2
	EXCH	T2,J$FLVT(J)		;MAKE IT THE CURRENT ONE
	SKIPN	T2			;IF PREVIOUS WAS NULL
	CAME	T1,D$TAPE		; AND THIS IS THE DEFAULT
	SKIPA				; THEN
	POPJ	P,			;DON'T TYPE A MESSAGE
	TELL	OPR,[ASCIZ /Please put VFU Tape + in $
/]
	ON	S,MNTBIT		;CAUSE A WAIT
	POPJ	P,			;AND RETURN

LODV.0:	TELL	OPR,%%LVF		;TELL OPR WE ARE LOADING
	PUSHJ	P,OUTWON		;WAIT FOR ONLINE


				;AND FALL INTO OS DEPENDENT CODE
IFN FTUUOS,<
	MOVE	T1,[2,,T2]		;ARG POINTER
	MOVX	T2,.DFRDS		;READ DEVICE STATUS
	MOVEI	T3,LPT			;FOR CHANNEL LPT
	DEVOP.	T1,			;DO IT
	  JRST	NODAVF			;ASSUME NO DAVFU
	TXNE	T1,DF.LVE		;CURRENT VFU IN ERROR?
	JRST	LODV.9			;YES, DONT SEND A FF
	TXZ	S,FFSEEN		;CLEAR FFSEEN
	PUSHJ	P,SENDFF		;SEND THE FORMFEED
	PUSHJ	P,OUTDMP		;AND FORCE IT OUT
LODV.9:	PUSHJ	P,OUTFLS		;FLUSH OUTPUT BUFFERS
	MOVX	T1,.IOASL		;LOAD ASCII MODE
	MOVSI	T2,'SYS'		;AND LOAD DEVICE
	MOVEI	T3,J$XVFB(J)		;AND ADDRRES OF BUFFER RING HEADER
	OPEN	VFC,T1			;OPEN SYS
	  HALT	.			;THIS REALLY SHOULDN'T HAPPEN
	MOVE	T1,J$FTAP(J)		;GET TAPE NAME
	MOVSI	T2,'VFU'		;AND EXTENSION
	SETZB	T3,T4			;AND CLEAR THE REST
	LOOKUP	VFC,T1			;FIND THE FILE
	  JRST	NOVFU			;LOSE, TELL HIM
	MOVE	T1,[2,,T2]		;ARGS FOR DEVOP
	MOVX	T2,.DFENV		;ENABLE VFU LOAD
	MOVEI	T3,LPT			;FOR I/O CHANNEL
	DEVOP.	T1,			;DO IT
	  JRST	NODAVF			;ASSUME NO DAVFU
	PUSHJ	P,M$ACQP##		;GET A PAGE
	PUSH	P,AP			;SAVE NUMBER FOR LATER
	PG2ADR	AP			;MAKE AN ADDRESS
	EXCH	AP,.JBFF		;AND FAKE OUT THE MONITOR
	INBUF	VFC,2			;FOR BUFFERS
	MOVEM	AP,.JBFF		;RESTORE JOBFF

LODV.1:	SOSGE	J$XVFB+.BFCNT(J)	;COUNT DOWN
	JRST	LODV.2			;GET ANOTHER BUFFER
	ILDB	C,J$XVFB+.BFPTR(J)	;GET A BYTE
	PUSHJ	P,DEVOUT		;OUTPUT IT
	JRST	LODV.1			;AND LOOP

LODV.2:	IN	VFC,			;GET A BUFFER
	  JRST	LODV.1			;SUCCESS, BACK TO LOOP
	PUSHJ	P,OUTDMP		;FORCE OUT THE BUFFERS
	MOVE	T1,[2,,T2]		;LOAD ARG POINTER
	MOVX	T2,.DFDVL		;DISABLE VFU LOAD
	MOVEI	T3,LPT			;AND CHANNEL NUMBER
	DEVOP.	T1,			;DO IT!
	  JRST	NODAVF			;LOSE
	RELEAS	VFC,			;RELEASE VFU CHANNEL
	POP	P,AP			;GET SCRATCH PAGE BACK
	PUSHJ	P,M$RELP##		;RELEASE IT
	MOVE	T1,J$FTAP(J)		;GET TAPE NAME
	MOVEM	T1,J$FLVT(J)		;SAVE AS TYPE LOADED
	POPJ	P,			;AND RETURN
>  ;END IFN FTUUOS
IFN FTJSYS,<
	OFF	S,FFSEEN		;CLEAR FFSEEN
	PUSHJ	P,SENDFF		;SEND A FORM-FEED
	PUSHJ	P,OUTDMP		;AND FORCE IT OUT
	MOVE	T1,[GJBLK,,GJBLK+1]	;SETUP A BLT POINTER
	SETZM	GJBLK			;CLEAR THE FIRST WORD
	BLT	T1,GJBLK+7		;ZERO THE BLOCK
	MOVX	T1,GJ%OLD		;GET THE FLAGS
	MOVEM	T1,GJBLK+.GJGEN		;STORE THEM
	MOVE	T1,DJFN			;GET I/O JFN
	MOVEM	T1,GJBLK+.GJSRC		;SAVE 'EM
	MOVE	T1,DDEV			;GET DEFAULT DEVICE
	MOVEM	T1,GJBLK+.GJDEV		;SAVE IT
	MOVE	T1,DVFU			;AND THE  DEFAULT EXTENSION
	MOVEM	T1,GJBLK+.GJEXT		;SAVE IT

	MOVE	T3,[POINT 6,J$FTAP(J)]	;POINT TO THE NAME IN 6BIT
	MOVE	T4,[POINT 7,T1]		;POINT TO RESULT IN ASCII
	SETZB	T1,T2			;CLEAR DESTINATION WORDS

LODV.1:	ILDB	S1,T3			;GET A CHARACTER
	JUMPE	S1,LODV.2		;NULL MEANS DONE
	ADDI	S1,"A"-'A'		;ELSE CONVERT TO ASCII
	IDPB	S1,T4			;AND DEPOSIT IT
	TLNE	T3,770000		;DONE?
	JRST	LODV.1			;NO, LOOP AROUND

LODV.2:	MOVEI	S1,GJBLK		;POINT TO BLOCK
	HRROI	S2,T1			;POINT TO STRING
	GTJFN				;GET THE JFN
	  JRST	NOVFU			;LOSE
	MOVE	T3,S1			;COPY THE JFN OVER
	MOVE	S1,J$LJFN(J)		;GET THE LPT JFN
	MOVX	S2,.MOLVF		;GET LOAD VFU FUNCTION
	MOVEI	T1,T2			;ADDRESS OF ARG BLOCK
	MOVEI	T2,2			;LENGTH OF ARG BLOCK
	MTOPR				;LOAD THE VFU
	MOVE	T1,J$FTAP(J)		;GET THE VFU TYPE
	MOVEM	T1,J$FLVT(J)		;SAVE AS CURRENTLY LOADED
	POPJ	P,			;AND RETURN
>  ;END IFN FTJSYS
;HERE IF VFU FILE THAT WE ARE LOOKING FOR IS NOT AROUND

NOVFU:	MOVE	T1,J$FTAP(J)		;TYPE WE TRIED TO LOAD
	CAMN	T1,D$TAPE		;IS IT THE DEFAULT
	JRST	NOVF.1			;YES, GIVE UP
	TELL	OPR,%%CFV		;CAN'T FIND VFU
	JRST	REQUE			;AND REQUE THE JOB

IFN FTUUOS,<
NOVF.1:	TELL	OPR,%%CFD		;CANT LOAD DEFAULT
	MOVE	T1,[2,,T2]		;ARGS FOR DEVOP
	MOVEI	T2,.DFLLV		;LOAD HARDWARE VFU
	MOVEI	T3,LPT			;FOR CHANNEL
	DEVOP.	T1,			;DO IT
	  JRST	NOVF.2			;LOSE
	MOVX	T1,FRMNOR		;GET NAM