Google
 

Trailing-Edge - PDP-10 Archives - ap-c796e-sb - qmangr.mac
There are 29 other files named qmangr.mac in the archive. Click here to see a list.
	TITLE	QMANGR -- SYSTEM SPOOLING QUEUE MANAGER -- V005
	SUBTTL	P.CONKLIN/PFC/DJB/DAL/SIP/CER/CDO  10-OCT-73


;***COPYRIGHT 1970, 1971, 1972, 1973  DIGITAL EQUIPMENT CORP.,  MAYNARD, MASS.***


VWHO==0			;WHO LAST EDITED THIS FILE
%QMNGR==5		;VERSION NUMBER
VMINOR==1		;MINOR VERSION NUMBER
VEDIT==67		;EDIT NUMBER
;REVISION HISTORY, ADDED 11-SEP-73 BY C. ROMASH
;LAST EDIT BEFORE THIS WAS 44
;
;EDIT 45-RESTORE COMPARE OF CORE ON EXIT AGAINST ORIGINAL.DOES NOT
;	 AFFECT CHANGE TO LET USER SAY KEEP EXTRA CORE
;
;EDIT 46-IOWD TO PARAMETER AREA GETS COMPUTED BADLY IN LOOK.FIX.
;
;EDIT 47-MODIFY SETS UP M WRONG.FIX IT.
;
;EDIT 50-REMOVE EDIT 46 WHICH LOST BADLY
;
;EDIT 51-FIX MASTER QUEUE INTERLOCK AS PER SPR 10-11710
;
;EDIT 52-FIX ERROR MESSAGES TO REPORT PROPER CODES SPR 10-11731
;
;EDIT 53-REMOVE EDIT 47 (M WAS RIGHT)
;
;EDIT 54-REMOVE EXTRA CODE AT SCHED1, IT CONFLICTS WITH EDIT 51
;
;EDIT 55-FIX LOG FILE CHECK IN DISPOSITION ROUTINES - PCO MPB-4
;
;EDIT 56-INCLUDE CODE TO MODIFY NOTE FIELD - PCO MPB-5
;
;EDIT 57-FIX RACE CONDITION WITH LOGOUT CLEARING QUE FILE
;
;EDIT 60-CHANGE CODE IN VALPPN TO ALLOW FOR [100+S,2]
;
;EDIT 61-DO GETPPN IN CHKRNM INSTEAD OF USING Q.PPN(A)
;
;EDIT 62-INCLUDE DATE-75 CHANGES
;
;EDIT 67-FIX DATE 75 PROBLEM FOR .QUF FILES.  SPR 13043
;  AREA AFFECTED: UPMRN1

;THIS CUSP CONSISTS OF TWO PARTS.  THE FIRST IS THE QUEUE MANAGER
;AND IS THIS FILE.  IT CONSISTS STRICTLY OF A HIGH SEGMENT SUITABLE
;ONLY FOR GETSEGGING.  THIS PART IS THE CENTER OF ALL DISK BASED
;QUEUE MANAGING FOR THE TOPS-10 MONITOR.  THE SECOND IS THE QUEUE
;COMMAND PROCESSOR AND APPEARS AS FILE QUEUE.MAC.
;THERE IS A THIRD PART, WHICH IS SIMPLY A SUBROUTINE WHICH WILL
;CALL THE QUEUE MANAGER.  IT APPEARS AS FILE QUEUER.MAC.
;FOR A FULL DESCRIPTION, REFER TO THE DETAILED DESIGN
;SPECIFICATION (FILE QUEUE.RNO OR QUEUE.MAN).  THAT FILE IS THE
;ARBITER OF THE SPECIFICATION AND SHOULD BE UPDATED TO REFLECT
;ANY SPEC CHANGES.

;DEVELOPED AS A TOOL FOR THE MULTI-PROGRAMMED BATCH PROJECT
;JULY, 1970.

;ASSEMBLY INSTRUCTIONS:
;TO AID DEBUGING, IT IS CONVENIENT TO KEEP THE SYMBOL TABLE
;IN THE HIGH SEGMENT.
;	.LOAD /CREF %S %1B QMANGR.MAC
;	.SSAVE DSK:QMANGR
;	.E 116
;WRITE DOWN THE CONTENTS OF 116.  THEN, TO DEBUG THE HIGH SEGMENT,
;PLACE A BREAKPOINT AT LOCATION "GOLOW" IN QUEUER.  AT THE BREAKPOINT,
;REMOVE ALL HI-SEG BREAKPOINTS, AND PLACE A BREAKPOINT AT C(R)+CLHISG.
;AT THIS BREAKPOINT, MOVE THE BREAKPOINT DOWN ONE TO CATCH THE RETURN.
;EXAMINE JOBSYM AND CHANGE IT TO THE CONTENTS OF 116 FROM THE ABOVE
;EXAMINATION AND OPEN SYMBOL TABLE QMANGR.  AT THE LATER BREAKPOINT, RESTORE
;THE JOBSYM CONTENTS AND REMOVE ANY HI-SEG BREAKPOINTS.
;NOTE THAT BREAKPOINTS SHOULD BE PLACED IN THE HI-SEG ONLY IF IT IS
;NOT SHARABLE.  (.SAVE INSTEAD OF .SSAVE, AND .ASSIGN DSK SYS).
	SUBTTL	PARAMETERS AND DEFAULTS

;ND SYMBOL,VALUE	DEFINES SYMBOL TO HAVE VALUE IF NOT ALREADY DEFINED

	DEFINE	ND(SYMBOL,VALUE),<
	IFNDEF SYMBOL,<SYMBOL==VALUE>
				LALL
				T.==SYMBOL
				XALL>

;ASSEMBLY PARAMETERS

ND REQPRT,177		;PROTECTION FOR REQUEST FILES, 0=STANDARD
ND LN.PDL,20		;MINIMUM LENGTH OF SUPPLIED PUSH-DOWN LIST
ND DEBUG,1		;1=INCLUDE DEBUGGING FEATURES
ND PURESW,1		;1=REENTRANT VERSION
ND LN.MAS,1000		;LENGTH OF MASTER QUEUE WINDOW
ND LN.LOP,100		;MAX LOOP COUNT FOR RETRIES BEFORE BOMB OUT
ND SEQUNC,-1		;1=OVERRIDE USER'S SEQUENCE
			;0=NO AUTOMATIC SEQUENCE
			;-1=AUTOMATIC SEQUENCE IF NO USER SUPPLIED ONE

	IFNDEF QUEUES,<DEFINE QUEUES<X <INP,LPT,CDP,PTP,PLT,JNH>>>
	SUBTTL	STANDARD MNEMONICS--REGISTERS, BITS, UUOS

;AC NAMES

F=0		;FLAGS
A=1		;ARGUMENT BLOCK POINTER
T1=2		;TEMPORARIES
T2=3
T3=4
T4=5
T5=6

I=10		;GENERAL PURPOSE INDEX REGISTERS
J=11
K=12
L=13

M=14		;USED FOR TYPING CHARACTERS
S=15		;FIXED ALLOCATION SCRATCH AREA
		;  UNDER DEBUG, LH = INITIAL PDL
AL=16		;ARGUMENT LIMIT SET BY CALLER
P=17		;PUSH-DOWN POINTER (ESTABLISHED BY CALLER)

;I/O CHANNELS

IO==0		;ONLY CHANNEL TO USE EXCEPT ON A CREATE CALL
CC==17		;CREATION CHECKING CHANNEL


;FLAGS (LH)

L.LST==1B35	;1=LISTING, 0=SCHEDULE (USED IN "PASS:")
L.LEVD==1B34	;1=LEVEL D, 0=LEVEL C
L.CHNG==1B33	;1=CHANGE WITHIN THIS WINDOW OF MASTER QUEUE
L.FMRD==1B32	;1=FAST (1 BLOCK) READ OF MASTER QUEUE
L.FLOK==1B31	;1=FAST (SHORT FORM) LOOKUP
L.MAST==1B30	;1=MASTER QUEUE INTERLOCKED (DEBUG MODE TEST)
L.NEWQ==1B29	;1=CREATING MASTER QUEUE (LEVEL C ONLY)
L.FLST==1B28	;1=FAST LISTING - DONT UPDATE MAST QUEUE, DONT READ REQUESTS
L.KLMD==1B27	;1=FOUND A REQUEST DURING KILL OR MODIFY
L.SFD==1B26	;1=5.04 WITH FTSFD TURNED ON
L.CHK==1B25	;1=CHKPNT NOT REQUEUE
L.SYSQ==1B24	;1=SYSTEM QUEUE IN USE
L.UMSI==1B23	;1=LOOKUP MASTER IN RDMAST, DONT READ IT YET

;FLAGS LH OF A

;BITS 0-2 ARE USED BY QUEUER
L.NCOR==1B3	;1=DONT RETURN CORE IF EXPANDED DURING QMANGR

;THEREFORE SIZE OF PARAMETER AREA IS A 14 BIT QUANTITY

	USRSIZ==^D14	;NUMBER OF BITS
;DEVCHR BITS

D.INIT==1B19	;RH -- INITED BY PROGRAM
D.DSK==1B1	;LH -- DEVICE TYPE DISK
D.TTY==1B5	;LH -- DEVICE IS TTY


;GETTABS

G.QSTR==15,,16	;STRUCTURE CONTAINING SYSTEM QUEUES
G.QDIR==4,,16	;DIRECTORY CONTAINING SYSTEM QUEUES
G.FFAP==2,,16	;USER WHICH HAS FULL FILE ACCESS
G.MDIR==0,,16	;DIRECTORY WHICH IS THE MFD
G.SYSP==1,,16	;DIRECTORY FOR DEVICE SYS:
G.STNP==12,,16	;STANDARD FILE PROTECTION
G.STAT==17,,11	;SYSTEM STATES WORD
G.MNVR==34,,11	;MONITOR VERSION
G.JSTS==0	;JBTSTS TABLE (USED FOR JLOG, JNA PRE 5.2)
G.JPPN==2	;JBTPPN TABLE (PPN OF USER)
G.JPRG==3	;JBTPRG TABLE (NAME OF CUSP)
G.TTIM==4	;TTIME TABLE (RUN TIME OF JOB)


;JOBSTS UUO BITS

JB.JNA==1B0	;JOB NUMBER ASSIGNED
JB.LOG==1B1	;JOB IS LOGGED IN


;GETTAB BITS

ST.JNA==1B3	;IN JBTSTS, JOB NUMBER ASSIGNED
ST.LOG==1B15	;IN JBTSTS, JOB IS LOGGED IN

;DSKCHR VALUES

DC.NAM==4	;NAME OF FILE STRUCTURE


;DEVTYP VALUES

.TYSPL==1B13	;THIS IS A SPOOLED DEVICE
;JOB DATA LOCATIONS OF INTEREST

	LOC	137
.JBVER:	BYTE	(3)VWHO(9)%QMNGR(6)VMINOR(18)VEDIT
	RELOC

	EXTERN	.JBFF,.JBREL,.JBINT


	IFN	PURESW,<TWOSEG
			RELOC 400000>



;USEFUL OPDEFS

OPDEF	MONRET	[EXIT 1,]	;MONITOR RETURNS
OPDEF	PJRST	[JRST]		;PUSHJ/POPJ PAIR
OPDEF	PJSP	[JSP]		;MOVEI .+1  PUSHJ/POPJ
OPDEF	ENTPNT	[JRST 1,]	;CONVENTION FOR SEGMENT ENTRY POINT

;NEW UUOS NOT YET IN MACRO

OPDEF	WAKE	[CALLI 73]	;WAKEUP A JOB IN HIBERNATE
OPDEF	PATH.	[CALLI 110]	;SET/RETURN FILE PATH

;MACROS


;GET FOO PICKS UP ARGUMENT Q.FOO FROM USER (USES T2) INTO T1

DEFINE	GET (A),<
	XLIST
	MOVEI	T2,Q.'A
	PUSHJ	P,GET.
	LIST
>

;PUT FOO STORES T1 TO USER Q.FOO (USES T2)

DEFINE	PUT (A),<
	XLIST
	MOVEI	T2,Q.'A
	PUSHJ	P,PUT.
	LIST
>

	OPDEF CHKACC [CALLI 100]
;IOERR FOO TYPES % FOO ERROR XXXXXX IN QUEUE MANAGER, CLEARS ERROR AND RETURNS

DEFINE	IOERR (A),<
	XLIST
	MOVEI	T1,[ASCIZ \A\]
	PUSHJ	P,IOERR.
	LIST
>

;WARN FOO TYPES % FOO IN QUEUE MANAGER AND CONTINUES

DEFINE	WARN (A),<
	XLIST
	PUSHJ	P,WARN.
	ASCIZ	\A\
	LIST
>

;LWARN FOO TYPES % LOOKUP FAILURE X FOO IN QUEUE MANAGER AND CONTINUES

DEFINE	LWARN (A),<
	XLIST
	PUSHJ	P,LWARN.
	ASCIZ	\A\
	LIST
>

;FAIL FOO TYPES ? FOO IN QUEUE MANAGER AND ABORTS

DEFINE	FAIL (A),<
	XLIST
	PJSP	AL,FAIL.
	ASCIZ	\A\
	LIST
>

;GCORE N GETS N MORE WORDS OF CORE AND ADVANCES .JBFF
;CORE WILL BE EXPANDED IF NECESSARY
;USES T1

DEFINE	GCORE (A),<
	XLIST
	MOVEI	T1,A
	PUSHJ	P,GCORE.
	LIST
>
	SUBTTL	INITIALIZE

;HERE BY CONVENTION ON A QUEUE MANAGER CALL

	ENTRY	QMANGR		;MUST BE 400010 IF REENTRANT

QMANGR:	ENTPNT	.+1		;FLAG STARTING ADDRESS
	PUSH	P,.JBREL	;SAVE CURRENT CORE ALLOCATION FOR LATER
	PUSH	P,.JBFF		;SAVE CURRENT .JBFF FOR END
	PUSH	P,.JBINT	;DON'T ALLOW ^C FOR JACCT CUSPS
	SETZM	.JBINT		;SO USER CANT ^C OUT WITH QUEUE LOCKED
	MOVE	S,.JBFF		;GRAB AREA FOR SCRATCH PURPOSES
	IFN	DEBUG,<HLL	S,P	;SAVE VALUE FOR PHASE CHECK>
	GCORE	S.LEN		;ALLOCATE IT
	SETZB	F,TYPCHR(S)	;CLEAR ADDR OF ROUTINES FOR TYPING CHARS AND FLAGS
	HLRZ	T1,P		;VERIFY PDL OK
	SKIPGE	P		;SKIP IF NO ROOM OR JUNK
	CAILE	T1,-LN.PDL	;COMPARE WITH STATED LENGTH
	JRST	E.PTS		;TOO SHORT

	LDB	AL,[POINT USRSIZ,A,17]	;SET ARGUMENT LIMIT FOR GET/PUT
	CAIGE	AL,QUEBLL	;MAKE SURE AREA EXISTS
	JRST	E.PATS		;NO--ERROR TOO SMALL


	MOVEI	T1,LN.LOP	;PRESET LOOP COUNTER SAFETY VALVE
	MOVEM	T1,LOPCNT(S)	;  TO PREVENT INFINITE LOOPS

	MOVE	T1,[G.STAT]	;GET STATE WORD
	GETTAB	T1,		;  FROM THE MONITOR
	  MOVEI	T1,0		;(UNLIKELY, BUT ASSUME LEVEL C)
	TLNE	T1,(7B9)	;SEE WHAT FLAVOR OF DISK SYSTEM
	TLOA	F,L.LEVD	;LEVEL D OR BETTER--SET FLAG
	JRST	OLDMON		;LEVEL C DOES NOT HAVE SFD'S
	SETOM	PATH(S)		;ASK FOR DEFAULT PATH
	MOVE	T1,[+10,,PATH]	;POINTER TO BLOCK
	ADDI	T1,(S)		;POINT TO RELOACTED AREA
	PATH.	T1,		;GET THE DEFAULT PATH
	  JRST	OLDMON		;NOT 5.04 OR FTSFD==0
	TLO	F,L.SFD		;WE HAVE SFD'S
	GETPPN	T1,		;GET OUT PPN
	CAMN	T1,PATH+2(S)	;SAME AS DEFAULT?
	JRST	OLDMON		;YES--NO SWEAT
	WARN	<Default PPN is not your PPN found>
OLDMON:	MOVEI	T1,G.MDIR	;GET NAME OF MFD
	GETTAB	T1,		;FROM THE MONITOR
	  MOVE	T1,[1,,1]	;(FOR LEV.C)
	MOVEM	T1,MFDPPN(S)	;SAVE FOR LATER
	MOVE	T1,[G.FFAP]	;GET USER WITH FULL FILE ACCESS
	GETTAB	T1,		;FROM THE MONITOR
	  MOVE	T1,[1,,2]	;(FOR LEV.C)
	MOVEM	T1,FSFPPN(S)	;SAVE FOR LATER

	MOVE	T1,[G.STNP]	;GET STANDARD FILE PROTECTION
	GETTAB	T1,		;FROM THE MONITOR
	  MOVSI	T1,055000	;DEFAULT STANDARD FILE PROTECTION
	MOVEM	T1,STNPRT(S)	;SAVE FOR LATER

	PUSHJ	P,GETNOW	;GET CURRENT TIME IN SPECIAL FORMAT
	MOVEM	T1,NOW(S)	;SAVE AWAY FOR LATER

	PJOB	T1,		;GET THIS JOB NUMBER
	MOVEM	T1,THSJOB(S)	;SAVE IN CASE NEEDED
	MOVSI	T1,'QUE'	;SEE IF QUE IS A DISK
	DEVCHR	T1,		;  FROM THE MONITOR
	TLNN	T1,(D.DSK)	;CHECK DISK
	JRST	SYSQUE		;NO--USE SYSTEM QUEUE

;HERE WHEN A PRIVATE QUEUE IS SPECIFIED (DISK DEVICE NAMED QUE)

PRVQUE:	MOVSI	T1,'QUE'	;YES--USE DEVICE QUE FOR THIS AREA
	MOVEI	T3,17		;CHANGE TO LOGICAL OPEN
	MOVSI	T2,'QUE'	;GET ITS PPN
	DEVPPN	T2,		;  FROM THE MONITOR
	  GETPPN T2,		;(USER'S AREA IN LEVEL C)
	JFCL			;IN CASE JACCT ON AND DID GETPPN
	MOVE	T4,T2		;MASTER QUEUE IN PRIVATE WORLD ALSO
	TLNN	F,L.LEVD	;IF LEVEL D MAY HAVE MORE TO WORRY ABOUT
	JRST	SAVQUE		;NO, ALREADY HAVE A GOOD DEVICE
	MOVEM	T1,QUEBLK(S)	;STORE FOR DSKCHR
	MOVEI	T5,QUEBLK(S)	;ADDR OF DSKCHR ARGS
	HRLI	T5,DC.NAM+1	;ENUGH TO GET STR NAME
	DSKCHR	T5,		;FIND OUT ABOUT QUE DEVICE
	  JRST	SYSQUE		;GIVE UP ON PRIVATE QUEUE IF NOT A DISK
	TLNE	T5,6		;SKIP IF QUE IS GENERIC DISK
	JRST	SAVQUE		;NO, ITS A GOOD NAME
	SKIPE	T1,QUEBLK+DC.NAM(S) ;GET FIRST STR IN JOB'S SEARCH LIST IF ANY
	JRST	SAVQUE		;IF NO STR, USE SYS QUEUE

;HERE WHEN SYSTEM QUEUE IS SPECIFIED (NO DEVICE NAMED QUE)

SYSQUE:	MOVE	T1,[G.QSTR]	;GET SYSTEM QUEUE STRUCTURE
	GETTAB	T1,		; FROM THE MONITOR
	  MOVSI	T1,'DSK'	;(FOR LEVEL C)
	MOVE	T2,[G.QDIR]	;GET SYSTEM QUEUE DEVICE
	GETTAB	T2,		; FROM THE MONITOR
	  MOVE	T2,[3,,3]	;(FOR LEVEL C)
	PUSHJ	P,MAKQUE	;GO VERIFY SYSTEM QUE UFD IS IN GOOD SHAPE
	MOVE	T3,[400000,,17]  ;SET PHYSICAL OPEN IMAGE MODE
	MOVE	T4,[G.SYSP]	;FIND DIRECTORY FOR SYS:
	GETTAB	T4,		;FROM THE MONITOR
	  MOVE	T4,[1,,1]	;(FOR LEV C)
	TLOA	F,L.SYSQ	;FLAG SYSTEM QUEUE IN USE

SAVQUE:	TLZ	F,L.SYSQ	;CLEAR THE SYSTEM QUEUE BIT
MOVEM	T2,QUEDIR(S)	;SAVE RESULTANT DIRECTORY
	MOVEM	T3,OPNBLK(S)	;  AND MODE
	SETZM	OPNBLK+2(S)	;CLEAR BUFFER POINTERS
	MOVEM	T4,MASDIR(S)	;SAVE LOCATION OF MASTER QUEUE
	MOVEM	T1,OPNBLK+1(S)	;SAVE DEVICE

	OPEN	IO,OPNBLK(S)	;OPEN COMMON CHANNEL
	  JRST	E.UOF		;DIE IF FAILURE
	GET	DEV		;GET THE REQUESTED QUEUE
	HLLZ	T3,T1		;MOVE TO T3 FOR LATER
	TLZ	T3,77		;CLEAR UNUSED BITS

	GET	OPR		;GET THE REQUESTED OPERATION
	HLRZM	T1,SCHDLR(S)	;SAVE ADDRESS OF SCHEDULER OR LISTER
	ANDI	T1,77		;MASK TO REQUEST
	PUSH	P,T1		;SAVE OPERATION FOR BELOW
	CAIE	T1,QO.LST	;LISTING DOESN'T REQUIRE DEVICE
	CAIN	T1,QO.FLS	;FAST LISTING DOESN'T REQUIRE DEVICE
	JRST	.+2
	JUMPE	T3,E.NQS	;NONE SPECIFIED
	MOVEM	T3,QUENM(S)	;SAVE FOR LATER
	IOR	T3,['MAST']	;INCLUDE MASTER FLAG
	MOVEM	T3,MASNAM(S)	;SAVE FOR LATER
	SETZM	PRODV(S)	;FAKE OUT CHKUSE
	MOVE	T1,Q.PDEV(A)	;PICK UP DEVICE NAME
	TLNN	T1,(77B5)	;JOB INTERLOCK
	JRST	SEENIU		;YES USE THAT
	DEVTYP	T1,		;SEE WHAT TYPE
	  JRST	SEENIU		;MAKE SURE NOT IN USE
	JUMPE	T1,E.NIU	;NO SUCH DEVICE IS AN ERROR
	TRNN	T1,77		;SKIP IF NOT DISK
	JRST	JOBNLK		;DISK--INTERLOCK BY JOB
	TLNN	T1,(.TYSPL)	;SKIP IF SPOOLED
	JRST	SEENIU		;NOT SPOOLED SEE REALY IN USE
JOBNLK:	GETPPN	T2,		;GET MY PPN
	  JFCL
	HLRZ	T1,T2		;COPY PROJECT
	ADD	T1,T2		;ADD IN PROGRAMMER
	PJOB	T2,		;PICK UP JOB NUMBER
	HRL	T1,T2		;COPY TO LH
	MOVEM	T1,Q.PDEV(A)	;STORE THE JOB NUMBER
SEENIU:	SKIPE	Q.PDEV(A)	;SEE IF DEVICE GIVEN
	PUSHJ	P,CHKUSE	;YES--SEE IF DEVICE IS IN USE
	  JRST	.+2		;YES--CAN PROCEED
	JRST	E.NIU		;NO--USER ERROR
	MOVE	T1,Q.PDEV(A)	;YES--GET DEVICE
	MOVEM	T1,PRODV(S)	;SAVE FOR LATER

	POP	P,T4		;RESTORE OPERATION
	CAIG	T4,OPRLEN	;COMPARE AGAINST MAX
	JUMPG	T4,@DISPT-1(T4)	;OK--DISPATCH
E.ILRQ:	FAIL	<Illegal request>
;DISPATCH TABLE ON REQUEST TYPE
DISPT:	EXP	CREATE		;1=CREATE
	EXP	E.ILRQ		;2=DEFER
	EXP	E.ILRQ		;3=ZDEFER
	EXP	LIST		;4=LIST
	EXP	MODIFY		;5=MODIFY
	EXP	KILL		;6=KILL
	EXP	SCHED		;7=SCHEDULE
	EXP	RELEAS		;10=RELEASE (AFTER SCHEDULE)
	EXP	REQUEU		;11=REQUEUE (AFTER SCHEDULE)
	EXP	FLIST		;12=FAST LIST (DONT UPDATE MAST QUE OR READ REQUESTS)
	EXP	CHKPNT		;13=CHKPNT (REQUEUE W/O RELEAS)
	EXP	NXTJOB		;14=NXTJOB (RELEASE THIS REQUEST THEN
				; DO A SCHEDULE, SAVE 2 GETSEGS SOME
				; DISK I/O)
OPRLEN==.-DISPT


;HERE TO RETURN TO CALLER
;RESTORE CORE AND PUSH DOWN LIST

RETMAS:	PUSHJ	P,RTMAST	;FIRST, RETURN MASTER QUEUE INTERLOCK

RETURN:	RELEAS	IO,		;RELEASE DEVICE QUE
	IFN	DEBUG,<	TLNE	F,L.MAST  ;SEE IF INTERLOCKED STILL
			JRST	E.MAST	;YES--BOMB
			MOVE	T1,S	;COPY OF S FOR PDL PHASE TEST
			XOR	T1,P	;CHECK PHASING
			TLNE	T1,-1	;SEE IF OK
			JRST	E.PDL	;NO--KILL>
	POP	P,.JBINT	;RESTORE ^C INTERCEPT
	POP	P,.JBFF		;RESTORE ORIGINAL .JBFF
	POP	P,T1		;RESTORE ORIGINAL CORE SIZE
	TLNE	A,(L.NCOR)	;SEE WHAT HE WANTED TO DO ABOUT EXTRA CORE
	POPJ	P,		;SAVE WHAT WE HAVE
	CAME	T1,.JBREL	;[45]SEE IF DIFFERENT
	CORE	T1,		;YES--RESTORE CORE SIZE
	  JFCL			;IGNORE ERROR
	POPJ	P,		;RETURN TO CALLER
	SUBTTL	CREATE REQUEST--REQUEST SETUP IN PARAM AREA

;HERE WHEN USER WANTS US TO CREATE A QUEUE REQUEST.
;THE REQUEST MUST ALREADY BE IN THE PARAMETER AREA.
;HE COULD DO IT HIMSELF, BUT THIS SAVES HIM THE BOTHER OF THE UNIQUE ENTER LOGIC.

CREATE:	GET	MEM		;GET ADDR OF ROUTINES FOR TYPING CHARS
	MOVEM	T1,TYPCHR(S)	;SAVE FOR TYPOUT ROUTINES
	PUSHJ	P,SETLEN	;SET UP LEN.H AND LEN.E
	HRRZ	T1,Q.LEN(A)	;PICK UP NUMBER OF FILES
	JUMPE	T1,E.NOFS	;ERROR IF NONE
	SKIPN	Q.DEV(A)	;MUST GO SOMEPLACE
	JRST	E.DEVS		;NOPLACE
	OPEN	CC,OPNBLK(S)	;OPEN CHECKING CHANNEL
	  JRST	E.UOF		;IF FAILED, BOMB

	GET	AFTR		;GET AFTER PARAMETER
	PUSHJ	P,UPDTIM	;UPDATE IN CASE OF + FORM
	PUT	AFTR		;RESTORE
	GET	DEAD		;GET DEAD PARAMETER
	PUSHJ	P,UPDTIM	;UPDATE IN CASE OF + FORM
	PUT	DEAD		;RESTORE
	GET	DEV		;GET DEVICE TO BE OUTPUT
	HLRZ	T2,T1		;GET DEVICE NAME
	LDB	T3,[POINT 6,T1,23] ;AND NEXT CHAR
	CAIE	T3,'S'		;SKIP IF STATION SPECIFIED
	CAIE	T2,'INP'	;NO STATION AND INPUT REQUEST
	JRST	CREDV1		;STATION OR NOT INPUT - CHECK REMOTE CODE
	MOVSI	T2,'LPT'	;ACT LIKE LPT
	HRR	T2,T1		;AND UNIT SPECIFIED
	JRST	CREDV2		;STORE DEVICE WITH REMOTE CODE
CREDV1:	PUSHJ	P,REMOTE	;CONVERT TO REMOTE
	TRNE	T1,-1		;SKIP IF GENERIC TYPE DEVICE SPECIFIED
	JRST	CREDVS		;NO, LEAVE IT ALONE
	MOVE	T2,T1
CREDV2:	WHERE	T2,		;SEE WHAT STATION IT'S AT
	  SETZ	T2,		;DONT KNOW, PRETEND CENTRAL SITE
	HRR	T1,T2		;STORE WITH DEVICE AS REMOTE STATION CODE
CREDVS:	PUT	DEV		;AND RESET NEW IMPROVED DEVICE

;LOOP HERE TO FIND A SUITABLE NAME FOR THE FILE

	MSTIME	T1,		;GET THE MILLISECOND CLOCK
	IDIVI	T1,^D100	;CONVERT TO TENTHS

CRENM:	MOVE	T2,QUENM(S)	;FIRST TWO CHARS OF NAME=OUTPUT DEV
	MOVE	T3,[POINT 6,T2,11]  ;SET BYTE POINTER FOR NEXT CHAR.
	ADD	T1,THSJOB(S)	;GET GUESS FOR NAME (DIFFERENT FROM LAST)
	MOVE	T4,T1		;AND PLUNK IT IN T4
CRENM1:	IDIVI	T4,^D10		;GET NEXT DIGIT
	ADDI	T5,'0'		;CONVERT TO SIXBIT
	IDPB	T5,T3		;STORE AWAY
	TLNE	T3,(77B5)	;SEE IF DONE YET
	JRST	CRENM1		;NO--LOOP BACK FOR NEXT CHARACTER
	MOVSI	T3,'QUE'	;YES--SET UP EXTENSION
	MOVEM	T2,FILNAM(S)	;SAVE FILE NAME FOR LATER
	MOVE	T5,QUEDIR(S)	;GET DIRECTORY
	LOOKUP	CC,T2		;SEE IF FILE IS THERE
	  TLZA	T3,-1		;CLEAR EXTENSION IF FAILURE
	JRST	CRENM4		;THERE--GO TRY ANOTHER
	CAIN	T3,2		;SEE IF PROTECTION FAILURE
	JRST	CRENM4		;YES--GO TRY ANOTHER
	JUMPN	T3,E.QLK	;ERROR IF ANY OTHER CASE
	MOVE	T2,FILNAM(S)	;SET FILE NAME
	MOVSI	T3,'QUE'	;SET EXTENSION
	MOVSI	T4,(<REQPRT>B8)	;SET PROTECTION CODE
	MOVE	T5,QUEDIR(S)	;SET DIRECTORY
	ENTER	IO,T2		;TRY THE ENTER (INTERLOCK NAME)
	  JRST	.+2		;ERROR--ANALYZE WHY
	JRST	CRENM2		;PROCEED IF NO FAILURE
	MOVEI	T3,-3(T3)	;GET ERROR CODE
	JUMPE	T3,CRENM4	;JUMP IF NOT PROTECTION FAILURE
	JRST	E.QEN		;IF FAILURE

CRENM2:	MOVE	T2,FILNAM(S)	;GET THE FILE NAME AGAIN
	MOVSI	T3,'QUE'	;SETUP EXTENTSION
	MOVE	T5,QUEDIR(S)	;GET THE DIRECTORY
	LOOKUP	CC,T2		;TRY TO FIND IT
	  JRST	CRENM5		;FAILURE IS WHAT WE WANT
CRENM3:	PUSHJ	P,CLO.IO	;CLOSE IO
	CLOSE	IO,50		;FOUND IT--RESET THE ENTER AND
CRENM4:	PUSHJ	P,CLO.CC	;CLOSE CHECK CHAN
	CLOSE	CC,10		;CLEAR THE LOOKUP AND
	TRNN	T1,77		;64*LOOP LIMIT SAFETY VALVE
	PUSHJ	P,LOOPR		;PROTECT AGAINST INF.LOOP
	JRST	CRENM		;GO TRY ANOTHER ONE
CRENM5:	HRRZ	T3,T3		;CLEAR OUT EXTENSION
	CAIN	T3,2		;SEE IF PROTECTION FAILURE
	JRST	CRENM3		;YES--LOOP TO TRY ANOTHER
	JUMPN	T3,E.QLK	;FAILED--ERROR IF OTHER THAN NOT FOUND

;HERE TO DISPOSE OF FILES

	MOVE	T5,LEN.H(S)	;LENGTH OF HEADER
	ADDI	T5,1(A)		;POINT TO FIRST FILE
	GET	LEN		;GET NUMBER OF FILES IN REQUEST
	HRRZ	I,T1		;I=NUMBER OF FILES IN REQUEST
	JUMPE	I,CREWRT	;NONE TO DISPOSE OF
CREDIS:	HLRZ	T1,QUENM(S)	;TYPE OF REQUEST
	CAIE	T1,'IN '	;SKIP IF INPUT REQUEST
	  JRST	CRED.1		;NOT INPUT
	MOVEI	T1,Q.II(A)	;START OF FILES
	ADD	T1,LEN.E(S)	;PLUS CTL FILE
	CAIE	T5,(T1)		;DONT FILDIS LOG FILE
CRED.1:	PUSHJ	P,FILDIS	;TAKE CARE OF DISPOSITION FOR THIS FILE
	ADD	T5,LEN.E(S)	;BUMP T5 TO NEXT FILE
	SOJG	I,CREDIS	;JUMP IF MORE FILES
;HERE TO ACTUALLY WRITE THE FILE

CREWRT:	GET	LEN		;GET USER'S LENGTH WORD
	HRRZ	T2,A		;ADDR OF REQUEST IN CORE
	PUSHJ	P,REQWRT	;WRITE THE FILE
	MOVE	T1,FILNAM(S)	;AND RETURN THE QUEUE ENTRY
	PUT	OPR		;  FILE NAME TO CALLER

;HERE TO WAKE UP ANY JOB WHICH MIGHT PROCESS THIS

	PUSHJ	P,WAKPRC	;WAKE UP ANY JOB THAT MIGHT PROCESS THIS
CREXIT:	JRST	RETURN		;AND RETURN TO USER
	SUBTTL	KILL REQUEST--REQUEST SETUP IN PARAM AREA

;HERE WHEN USER WANTS US TO KILL (DELETE) A QUEUE REQUEST
;THE KILL REQUEST MUST ALREADY BE IN THE PARAMETER AREA

KILL:	PUSHJ	P,SETLEN	;SET UP LEN.H AND LEN.E
	PUSHJ	P,KILEXC	;EXECUTE KILL REQUEST
	JRST	REQREL		;RELEASE REQUEST AND EXIT


;SUBROUTINE TO EXECUTE A KILL REQUEST

KILEXC:	PUSHJ	P,MODSTA	;START BY UPDATING THE MASTER QUEUE, SO THAT
				; ALL PREVIOUS CREATE REQUESTS ARE MOVED TO THE
				; MASTER QUEUE, THEN INTERLOCK THE MASTER QUEUE.
	  POPJ	P,		;GIVE UP IF CANT INTERLOCK MASTER QUEUE
KILEX1:	PUSHJ	P,MODNXE	;FIND THE NEXT ENTRY TO BE KILLED,
				; VERIFY THAT THE USER MAY KILL THE REQUEST,
				; AND READ THE ORIGINAL REQUEST INTO CORE.
	  JRST	KILEXE		;ERROR LOOKING FOR REQUEST

;HERE WHEN THE ORIGINAL REQUEST IS IN CORE, NOW PROCESS REMOVE REQUESTS

	TLO	F,L.KLMD	;NOTE THAT WE FOUND ONE
	PUSHJ	P,MODFIL	;PROCESS FILE SPECIFIC CHANGES (REMOVE ONLY HERE)

;HERE TO DISPOSE OF THE REST OF THE FILES IN THE ORIGINAL REQUEST

	HRRZ	T1,Q.LEN(I)	;NUMBER OF FILES LEFT IN THE ORIGINAL REQUEST
	JUMPE	T1,KILLDN	;EXIT NOW IF ALL REMOVED
	SETZ	T4,		;NOTE NO DISPOSITION FROM MODIFY REQUEST
	MOVEI	T5,Q.II(I)	;ADDR OF FIRST FILE IF INPUT QUEUE
	HLRZ	T1,QUENM(S)	;NAME OF QUEUE
	CAIE	T1,'IN '	;SKIP IF IT REALLY IS INPUT
	MOVEI	T5,Q.FF(I)	;NO, OUTPUT QUEUE OF SOME KIND
KILLN:	PUSHJ	P,MODREM	;DISPOSE OF THE NEXT FILE
	HRRZ	T1,Q.LEN(I)	;NUMBER OF FILES LEFT IN ORIGINAL REQUEST
	JUMPN	T1,KILLN	;LOOP FOR ALL FILES LEFT
KILLDN:	PUSHJ	P,RELESS	;RELEASE REQUEST AND DELETE FROM MASTER QUEUE
	JRST	KILEX1		;LOOP FOR ALL REQUESTS THAT MATCH

;HERE IF SOMETHING WRONG WITH THE REQUEST

KILEXE:	JUMPL	T1,KILEE1	;JUMP IF NO SUCH ENTRY
	TLO	F,L.KLMD	;NOTE FOUND AT LEAST ONE ENTRY
	JUMPE	T1,KILEE2	;JUMP IF REQUEST IS INTERLOCKED
	PUSHJ	P,REQDEL	;LOOKUP FAILED, DELETE REQUEST
	JRST	KILEX1		;AND LOOP FOR ALL MATCHES
KILEE2:	PUSHJ	P,W.MRBS	;TYPE BUSY MESSAGE
	JRST	KILEX1		;AND LOOP FOR ALL MATCHES
KILEE1:	TLNE	F,L.KLMD	;SKIP IF NO ENTRIES WERE FOUND
	POPJ	P,		;YES, ALL DONE
	PJRST	W.MNSE		;NO, CANT FIND ANY ENTRIES
	SUBTTL	MODIFY REQUEST--REQUEST SETUP IN PARAM AREA

;HERE WHEN USER WANTS US TO MODIFY A QUEUE REQUEST
;THE MODIFY REQUEST MUST ALREADY BE IN THE PARAMETER AREA.

MODIFY:	PUSHJ	P,SETLEN	;SET UP LEN.H AND LEN.E
	PUSHJ	P,MODEXC	;EXECUTE THE MODIFY REQUEST
	JRST	REQREL		;RETURN MASTER QUEUE AND EXIT

;THE MODMAC MACRO GENERATES CODE TO CHANGE ONE FIELD IN A MODIFY REQUEST.
;REQUEST IS THE FIELD NAME IN THE QUEUE REQUEST
;MASTER IS THE FIELD NAME IN THE MASTER QUEUE, IF ANY - IF NONE LEAVE BLANK
;LMASK IS THE LEFT HALF OF THE MASK FOR THE FIELD
;RMASK IS THE RIGHT HALF OF THE MASK FOR THE FIELD
;IF THE FIELD IS NOT ALL ONES IN THE MODIFY REQUEST, THE NEW VALUE IS
;STORED IN THE ORIGINAL REQUEST.

	DEFINE	MODMAC (REQUEST,MASTER,LMASK,RMASK,%DUM)<
	XLIST
	GET	REQUEST		;;GET MODIFY REQUEST
	XLIST

.ZZ==<LMASK&RMASK&777777>-777777

IFE .ZZ,<SETCM T2,T1		;;T2=COMPLEMENT OF NEW VALUE
	JUMPE	T2,%DUM		;;JUMP IF NO CHANGE
	MOVEM	T1,Q.'REQUEST(I);;STORE NEW VALUE IN REQUEST
IFNB <MASTER>,<MOVEM	T1,M.'MASTER(J)	;;AND IN QUEUE MANAGER>
>

IFN .ZZ,<IFE LMASK,<HRRZI T2,RMASK	;;RIGHT HALF OF MASK, LEFT HALF=0>
	IFN LMASK,<IFE RMASK,<HRLZI T2,LMASK ;;LEFT HALF OF MASK, RIGHT HALF=0>
		IFN RMASK,<MOVE T2,[XWD LMASK,RMASK] ;;MASK IN BOTH HALVES>
		>
	TDC	T1,T2		;;CLEAR FIELD IF NOT SPECIFIED
	TDCN	T1,T2		;;RESET NEW VALUE AND SKIP IF NOT -1(=NO CHANGE)
	JRST	%DUM		;;NO CHANGE
	AND	T1,T2		;;CLEAR OUT THE REST OF T1
	ANDCAM	T2,Q.'REQUEST(I) ;;CLEAR THE FIELD IN THE ORIGINAL REQUEST
	ADDM	T1,Q.'REQUEST(I) ;;STORE THE NEW VALUE IN THE ORIGINAL
IFNB <MASTER>,<ANDCAM	T2,M.'MASTER(J)	;;CLEAR THE FIELD IN THE MASTER QUEUE
	ADDM	T1,M.'MASTER(J)	;;AND UPDATE THE MASTER QUEUE>
	>
IFNB <MASTER>,<TLO	F,L.CHNG	;;NOTE CHANGE IN MASTER QUEUE>
%DUM:
	LIST
>	;END MACRO DEFINITION OF MODMAC
;SUBROUTINE TO EXECUTE A MODIFY REQUEST

MODEXC:	PUSHJ	P,MODSTA	;START BY UPDATING THE MASTER QUEUE, SO THAT
				; ALL PREVIOUS CREATE REQUESTS ARE MOVED TO THE
				; MASTER QUEUE, THEN INTERLOCK THE MASTER QUEUE
	  POPJ	P,		;GIVE UP IF CANT INTERLOCK MASTER QUEUE
MODEX1:	PUSHJ	P,MODNXE	;FIND THE NEXT ENTRY TO BE MODIFIED,
				; VERIFY THAT THE USER MAY MODIFY THE REQUEST,
				; AND READ THE ORIGINAL REQUEST INTO CORE.
	  JRST	MODEXE		;ERROR LOOKING FOR NEXT ENTRY

;HERE WHEN THE ORIGINAL REQUEST IS IN CORE, NOW MODIFY IT

	TLO	F,L.KLMD	;NOTE FOUND AN ENTRY

	MODMAC	PRI,EPRI,0,77
	MODMAC	AFTR,EAFT,377777,-1
	MODMAC	DEAD,EDED,377777,-1
	MODMAC	CNO,,-1,-1

	HLRZ	T1,QUENM(S)	;NAME OF QUEUE
	CAIE	T1,'IN '	;SKIP IF INPUT QUEUE
	JRST	MODOUQ		;NO, AN OUTPUT QUEUE

	MODMAC	ILIM,ILIM,776000,0
	MODMAC	ILIM,ILIM,0,-1
	MODMAC	ILIM+1,ILIM+1,-1,0
	MODMAC	ILIM+1,ILIM+1,0,-1
	MODMAC	ILIM+2,ILIM+2,-1,0
	MODMAC	ILIM+2,ILIM+2,0,-1
	GET	IDEP		;GET NEW DEPENDENCY VALUE
	LDB	T2,[POINT 2,T1,19] ;TYPE OF CHANGE
	CAIN	T2,3		;SKIP IF TO BE CHANGED
	JRST	MODNDP		;NO, DONT CHANGE
	ANDI	T1,177777	;RIGHT-MOST 16 BITS IS VALUE
	JUMPE	T2,MODSDP	;JUMP IF SET NEW VALUE
	CAIE	T2,1		;NO, SKIP IF ADD, NOT IF SUBTRACT
	MOVNI	T1,(T1)		;SUBTRACT, SET MINUS VALUE
	HRRE	T2,Q.IDEP(I)	;CURRENT VALUE
	ADD	T1,T2		;NEW VALUE
MODSDP:	TRZ	T1,3B19		;CLEAR THE OPERATION CODE
	HRRM	T1,Q.IDEP(I)	;STORE NEW VALUE IN REQUEST
	HRRM	T1,M.IDEP(J)	;STORE IN MASTER QUEUE
	TLO	F,L.CHNG	;MASTER WINDOW HAS CHANGED
MODNDP:	GET	IDEP		;GET THE DEP WORD
	HLLZ	T4,Q.IDEP(I)	;COPY L.H.
	LDB	T2,[POINT 2,T1,2] ;GET /UNIQ:N
	SKIPE	T2		;CHANGE?
	DPB	T2,[POINT 2,T4,2] ;YES--STORE THE NEW VALUE
	LDB	T2,[POINT 3,T1,8] ;GET /OUT:N
	CAIE	T2,7		;CHANGE?
	DPB	T2,[POINT 3,T4,8] ;YES--
	TLNN	T1,(1B3)	;CHANGE /RESTART?
	JRST	MODNDA		;NO--STORE RESULT
	CAIL	T1,0		;YES, WANT A 1	/
	TLZA	T4,(1B0)	;NO--MAKE A ZERO
	TLO	T4,(1B0)	;YES--MAKE A ONE
MODNDA:	XOR	T1,Q.IDEP(I)	;PUT CHANGED BITS IN T1
	HLLM	T4,Q.IDEP(I)	;STORE NEW VALUE
	HLLM	T4,M.IDEP(J)	; ..
				;LOOK AT BITS THAT HAVE BEEN
	TLNE	T1,-1		; CHANGED AND IF ANY
	TLO	F,L.CHNG	; TURN ON L.CHNG SO THAT
				; THE ENTRY WILL BE WRITTEN
	JRST	MODIND		;PROCESS FILE SPECIFIC CHANGES

MODOUQ:	MODMAC	OFRM,OFRM,-1,-1
	MODMAC	OSIZ,OSIZ,-1,0
	MODMAC	ONOT,ONOT,-1,-1
	MODMAC	ONOT+1,ONOT+1,-1,-1
;HERE TO MODIFY FILE SPECIFIC PARAMETERS

MODIND:	PUSHJ	P,MODFIL	;PROCESS FILE SPECIFIC CHANGES

;HERE TO WRITE OUT THE QUEUE REQUEST AGAIN

	TLO	F,L.FLOK	;ONLY NEED SHORT LOOKUP
	PUSHJ	P,LOOKR		;SET UP EVERYTHING AGAIN
	  JRST	MODEE3		;LOOKUP FAILED?
MODEFR:	MOVE	T2,QUEDIR(S)	;NEED TO RESET DIRECTORY
	MOVEM	T2,RB.PPX(S)
	ENTER	IO,(T1)
	  JRST	MODEFL		;ENTER FAILED, CHECK THE REASON
	MOVE	T1,Q.LEN(I)	;NEW LENGTH OF REQUEST
	HRRZ	T2,I		;ADDR OF REQUEST IN CORE
	PUSHJ	P,REQWRT	;WRITE OUT REQUEST
	JRST	MODEX1		;AND LOOP FOR THE REST

MODEFL:	HRRZ	T2,1(T1)	;GET ENTER ERROR CODE
	CAIE	T2,3		;SKIP IF FILE BEING MODIFIED
	JRST	MODEFN		;NO, SOMETHING WRONG
	PUSHJ	P,SLEEPR	;SLEEP AND TRY AGAIN, BUT NOT TOO MANY TIMES
	JRST	MODEFR		;AND TRY AGAIN
MODEFN:	PUSHJ	P,CLO.IO
	CLOSE	IO,34		;RESET LOOKUP
	MOVEI	M,[ASCIZ /
% Enter failure /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,T2
	PUSHJ	P,LWRN1.	;FINISH WARNING
	ASCIZ	\modifying\
	JRST	MODEX1		;AND LOOP FOR THE REST

MODEE3:	PUSHJ	P,MODLFL	;TYPE LOOKUP FAILURE MESSAGE
	JRST	MODEX1		;AND LOOP FOR ALL MATCHES

MODEXE:	JUMPL	T1,MODEE1	;JUMP IF NO MORE ENTRIES
	TLO	F,L.KLMD	;NOTE FOUND ONE
	JUMPE	T1,MODEE2	;JUMP IF ENTRY INTERLOCKED
	PUSHJ	P,REQDEL	;CANT READ ENTRY, DELETE FROM MASTER QUEUE
	JRST	MODEX1		;LOOP FOR ALL MATCHES
MODEE2:	PUSHJ	P,W.MRBS	;REQUEST INTERLOCKED - TYPE BUSY MESSAGE
	JRST	MODEX1		;LOOP FOR ALL MATCHES
MODEE1:	TLNE	F,L.KLMD	;SKIP IF ANY WERE FOUND
	PJRST	WAKPRC		;FOUND SOME AND THERE ARE NO MORE, ALL DONE
				;WAKE ANYONE WHO MIGHT PROCESS
	PJRST	W.MNSE		;CANT FIND ANY ENTRIES
;MODSTA--START UP A MODIFY OR KILL REQUEST
;(1) UPDATE THE MASTER QUEUE SO ALL PREVIOUS CREATE REQUESTS ARE IN MASTER QUEUE
;(2) GET MASTER QUEUE INTERLOCK
;(3) SET UP TO START SEARCHING MASTER QUEUE ENTRIES
;RETURN CPOPJ1 IF ALL SET UP
;NON-SKIP RETURN IF ERROR

MODSTA:	PUSHJ	P,UPMASQ	;FIRST UPDATE THE MASTER QUEUE
	PUSHJ	P,UPMASI	;GET THE MASTER QUEUE INTERLOCK
	  PJRST	W.MMQI		;CANT GET MASTER QUEUE INTERLOCK
	TLZ	F,L.KLMD	;CLEAR FLAG SAYING FOUND ANY ENTRIES
	SETZM	MASIOW(S)	;START AT BEGINNING OF MASTER QUEUE
	PUSHJ	P,CLSRET	;CLOSE MASTER QUEUE
	JRST	CPOPJ1

;WAKPRC--WAKE UP ANY JOB WHICH MIGHT PROCESS THIS

WAKPRC:	SETO	T1,		;FIRST SEARCH FOR NAME OF CUSP
CREDN1:	AOS	T1		;GO TO NEXT IN LIST
	SKIPN	T2,QUENMS(T1)	;SEE IF AT END
	POPJ	P,		;YES--SKIP WAKEUP
	TLZ	T2,77		;ONLY CARE ABOUT FIRST 2 CHARS
	CAME	T2,QUENM(S)	;NO--SEE IF THIS QUEUE
	JRST	CREDN1		;NO--LOOP BACK FOR MORE
	MOVEI	T2,0		;YES--START AT JOB 0
CREDN2:	AOS	T2		;ADVANCE TO NEXT JOB
	HRLZ	T3,T2		;PREPARE TO
	HRRI	T3,G.JPRG	; SEE WHAT CUSP IS UP
	GETTAB	T3,		;ACCORDING TO MONITOR
	  POPJ	P,		;DONE OR CAN'T FIND OUT
	CAME	T3,QUEPRC(T1)	;SEE IF IT IS ONE WE WANT
	JRST	CREDN2		;NO--LOOP TO NEXT JOB
	MOVE	T3,T2		;YES--SETUP JOB NUMBER
	WAKE	T3,		;AND WAKEUP JOB
	  POPJ	P,		;GIVE UP IF WE CAN'T
	JRST	CREDN2		;LOOP BACK FOR NEXT JOB
;MODNXE--FIND NEXT ENTRY THAT MATCHES MODIFY OR KILL REQUEST
;(1) FIND ENTRY TO BE MODIFIED IN THE MASTER QUEUE
;(2) VERIFY THAT THE USER MAY MODIFY THE REQUEST
;(3) READ THE ORIGINAL REQUEST TO BE MODIFIED INTO CORE
;NON-SKIP RETURN IF ERROR - T1=ERROR CODE
;	T1 LT 0 IF NO SUCH ENTRY
;	T1 EQ 0 IF ENTRY INTERLOCKED
;	T1 GT 0 IF LOOKUP FAILED

MODNXE:	PUSHJ	P,UPFNJB	;FIND ENTRY WE ARE SUPPOSED TO MODIFY
	JUMPLE	T1,CPOPJ	;EXIT IF CANT GET ENTRY WITH T1=ERROR
	LDB	T2,[POINT 9,M.EPRI(J),26] ;PICKUP JOB PROTECTION
	TRNN	T2,777		;SKIP IF NON-ZERO
	TRO	T2,100		;MONITOR DOESN'T LIKE 0
	HRLI	T2,3		;ALLOW UPDATE
	MOVE	T3,M.EPPN(J)	;PPN FROM REQUEST
	GETPPN	T4,		;GET PPN OF FELLOW RUNNING US NOW
	JFCL
	MOVEI	T1,T2
	CHKACC	T1,		;CHECK ACCESS
	  JRST	REQRED		;CANT FIND OUT
	JUMPL	T1,W.MPRV	;JUMP IF DONT HAVE PRIVILEGES

;FALL INTO REQRED TO READ THE ORIGINAL REQUEST FILE

;REQRED--READ REQUEST FILE INTO SCRATCH CORE

REQRED:	PUSHJ	P,LOOKR		;DO LOOKUP AND SETUP IOWD
	  JRST	MODLFL		;CANT FIND ENTRY
	MOVEI	T3,QUEBLK-1(S)	;MAKE IOWD POINTING TO QUEBLK
	HRLI	T3,-QUEBLL
	IN	IO,T3		;READ HEADER
	  JRST	REQRD1		;GOOD
	STATO	IO,74B23
	  JRST	REQRD1
	IOERR	<Reqeust read>
REQRD1:	MOVE	T1,QUEBLK+Q.LEN-1(S)
	PUSHJ	P,REQSIZ	;SET UP IOWD
	HRRZ	I,.JBFF		;START AT FREE CORE
	HRR	T1,I
	EXCH	T1,T3
	PUSHJ	P,GCORE.	;MAKE SURE WE HAVE ENOUGH CORE
	SETZ	T4,
	USETI	IO,1		;RESET TO BEGINNING OF FILE
	IN	IO,T3		;READ THE FILE
	  JRST	CPOPJ1		;MADE IT
	STATO	IO,74B23
	  JRST	CPOPJ1		;WELL, OK
	IOERR	<Request read>
	JRST	CPOPJ1		;PRETEND OK

MODLFL:	LWARN	<modifying>
	MOVEI	T1,1		;ERROR CODE - LOOKUP FAILED
	POPJ	P,		;GIVE ERROR RETURN WHICH WILL DELETE REQUEST
;MODFIL--PROCESS FILE SPECIFIC ENTRIES IN MODIFY REQUEST
;ARGS	A=ADDR OF MODIFY REQUEST IN CORE
;	I=ADDR OF ORIGINAL REQUEST IN OCORE

;THE MODMC1 MACRO GENERATES CODE TO MODIFY A FILE SPECIFIC PARAMETER
;IN THE FMOD WORD OF A FILE IN A REQUEST.
;LMASK IS THE LEFT HALF OF THE MASK FOR THE FIELD
;RMASK IS THE RIGHT HALF OF THE MASK FOR THE FIELD
;IF THE FIELD IS NON-ZERO IN THE FMDM WORD IN THE MODIFY REQUEST,
;THE NEW VALUE FROM THE FMOD WORD OF THE MODIFY REQUEST IS STORE IN THE REQUEST.

	DEFINE	MODMC1 (LMASK,RMASK,%DUM)<
	XLIST

.ZZ==<LMASK&RMASK&777777>-777777

IFE .ZZ,<SKIPN Q.FMDM(M)	;;SKIP IF NEW VALUE SPECIFIED
				;; SPR 10-11,102
	JRST	%DUM		;;NO CHANGE
	MOVE	T1,Q.FMOD(T4)	;;NEW VALUE
	MOVEM	T1,Q.FMOD(T5)	;;STORE NEW VALUE IN ORIGINAL
>

IFN .ZZ,<IFE LMASK,<HRRZI T2,RMASK	;;RIGHT HALF OF MASK, LEFT HALF=0>
	IFN LMASK,<IFE RMASK,<HRLZI T2,LMASK ;;LEFT HALF OF MASK, RIGHT HALF=0>
		IFN RMASK,<MOVE T2,[XWD LMASK,RMASK] ;;MASK IN BOTH HALVES>
		>
	TDNN	T2,Q.FMDM(M)	;;SKIP IF NEW VALUE SPECIFIED
				;;SPR 10-11,102
	JRST	%DUM		;;NO CHANGE
	MOVE	T1,Q.FMOD(T4)	;;NEW MODIFY WORD
	AND	T1,T2
	ANDCAM	T2,Q.FMOD(T5) ;;CLEAR FIELD IN ORIGINAL REQUEST
	ADDM	T1,Q.FMOD(T5) ;;STORE NEW VALUE IN ORIGINAL
	>
%DUM:
	LIST
>	;END MACRO DEFINITION OF MODMC1

MODFIL:	HRRZ	T1,Q.LEN(A)	;NUMBER OF FILES IN MODIFY REQUEST
	JUMPE	T1,CPOPJ	;NO WORK IF NO FILES
	MOVE	T4,LEN.H(S)	;GET LENGTH OF HEADER
	ADDI	T4,1(A)		;POINT TO FIRST FILE
;HERE TO FIND A MATCH BETWEEN THE NEXT FILE IN THE MODIFY REQUEST
;(POINTED TO BY T4) AND SOME FILE IN THE ORIGINAL REQUEST.  SET T5=
;ADDRESS OF THE FILE BLOCK IN THE ORIGINAL REQUEST

MODFLN:	PUSHJ	P,SETUPM	;SET UP M
	SKIPN	Q.FMDM(M)	;SKIP IF ANY MODS FOR THIS FILE IN MODIFY
	JRST	MODFF1		;NO, NO POINT IN FINDING FILE IN ORIGINAL
	HRRZ	T1,Q.LEN(I)	;NUMBER OF FILES IN ORIGINAL REQUEST
	JUMPE	T1,CPOPJ	;EXIT NOW IF NO FILES TO BE FOUND
	MOVEM	T1,QUEBLK(S)	;SAVE IN TEMP
	MOVEI	T5,Q.II(I)	;ADDR OF BEGINNING IF INPUT
	HLRZ	T1,QUENM(S)	;NAME OF QUEUE
	CAIE	T1,'IN '	;SKIP IF INPUT
	MOVEI	T5,Q.FF(I)	;NO, ASSUME OUTPUT FORM

;HERE TO FIND NEXT MATCH BETWEEN MODIFY REQUEST AND ORIGINAL REQUEST

MODFN1:	PUSHJ	P,SETUPM	;SET UP M
	SKIPE	T1,Q.FSTR(T4)	;OK IF NONE
	CAMN	T1,[SIXBIT/DSK/] ;OR IF GENERIC DSK
	  JRST	MODFN2		;IS A MATCH
	MOVE	L,T1		;COPY
	SETO	K,		;GENERATE MASK
	LSH	K,-6
	LSH	L,6
	JUMPN	L,.-2
	MOVE	L,Q.FSTR(T5)	;GET ORIGINAL REQUEST STR
	ANDCM	L,K		;NO WILD CARDS FOR STRS BUT CAN USE ABRIEVATIONS
	CAME	T1,L
	JRST	MODFLF		;NO, TRY NEXT IN ORIGINAL
MODFN2:	MOVSI	K,-6		;LENGTH OF PATH
	HRRI	K,(T4)		;POINTER TO MOD REQUEST
	MOVEI	L,(T5)		;POINTER TO ORIGINAL REQUEST
MDFN2A:	MOVE	T1,Q.FDIR(L)	;GET DIRECTORY WORD
	XOR	T1,Q.FDIR(K)	;SET BITS THAT ARE DIFFERENT
	AND	T1,Q.FDRM(M)	;MASK OUT JUNK
	JUMPN	T1,MODFLF	;JUMP IF THEY DO NOT MATCH
	AOS	L		;BUMP POINTER
	AOS	M		; ..
	AOBJN	K,MDFN2A	;LOOP OVER FULL PATH
	SUBI	M,6		;SET M BACK TO PROPER POINT
	MOVE	T1,Q.FNAM(T5)	;FILE NAME FROM ORIGINAL
	XOR	T1,Q.FNAM(T4)	;COMPARE
	AND	T1,Q.FNMM(M)	;MASKED BY MODIFY
	JUMPN	T1,MODFLF	;JUMP IF NO MATCH
	MOVE	T1,Q.FEXT(T5)	;EXTENSION FROM ORIGINAL
	XOR	T1,Q.FEXT(T4)	;COMPARE
	AND	T1,Q.FEXM(M)	;MASKED BY MODIFY
	JUMPN	T1,MODFLF	;JUMP IF NO MATCH
;HERE WHEN FOUND A MATCH

	SKIPGE	Q.FMOD(T4)	;SKIP IF NOT REMOVE REQUEST
	JRST	MODFLR		;REMOVE FILE FROM ENTRY

;HERE TO PROCESS FILE SPECIFIC CHANGES

	MODMC1	0,700000	;SPACING
	MODMC1	0,070000	;PAPER
	MODMC1	0,007000	;FILE TYPE
	MODMC1	0,000700	;DISPOSITION
	TDNN	T2,Q.FMDM(M)	;SKIP IF DISPOSITION WAS SPECIFIED
				;SPR 10-11,102
	JRST	MODFCP		;NO, MOVE AHEAD TO COPIES
	PUSH	P,T4		;SAVE T4
	HLRZ	T1,QUENM(S)	;TYPE OF REQUEST
	CAIE	T1,'IN '	;SKIP IF INPUT REQUEST
	  JRST	CRED.2		;NOT INPUT
	MOVEI	T1,Q.II(A)	;START OF FILES
	ADD	T1,LEN.E(S)	;PLUS CTL FILE
	CAIE	T5,(T1)		;DONT FILDIS LOG FILE
CRED.2:	PUSHJ	P,FILDIS	;TAKE CARE OF NEW DISPOSITION
	POP	P,T4		;RESTORE T4
;HERE TO PROCESS CHANGE IN COPIES BECAUSE CHANGES SIZE OF REQUEST TOO

MODFCP:	MOVE	T1,Q.FMOD(T4)	;GET WORD CONTAING COPIES
	TRC	T1,77		;COMPLEMENT
	TRCN	T1,77		;RESET AND SKIP IF NEW VALUE SPECIFIED
	JRST	MODFLF		;NO CHANGE
	LDB	T2,[POINT 6,Q.FMOD(T5),35] ;GET OLD COPIES FIELD
	ANDI	T1,77
	SKIPN	T2
	MOVEI	T2,1
	SKIPN	T1
	MOVEI	T1,1
	SUB	T1,T2		;T1=NEW-OLD NUMBER OF COPIES
	JUMPE	T1,MODFLF	;NO CHANGE IN NUMBER OF COPIES AFTER ALL
	HRLM	T1,(P)		;SAVE NUMBER OF COPIES
	MOVEI	T1,17
	MOVE	T2,Q.FSTR(T5)	;ORIGINAL STR
	SETZ	T3,
	OPEN	CC,T1		;OPEN STR
	  JRST	MODOFL		;CANT OPEN DEVICE
	PUSH	P,T4		;SAVE T4
	SKIPN	T1,Q.FRNM(T4)	;SKIP IF WAS RENAMED BY MODIFY
	SKIPE	T1,Q.FRNM(T5)	;NO, SKIP IF STILL IN USER'S AREA
	JRST	MODFRN		;FILE WAS RENAMED TO QUE AREA
	MOVE	T1,Q.FNAM(T5)	;USE ORIGINAL NAME
	HLLZ	T2,Q.FEXT(T5)
	MOVE	T4,Q.FDIR(T5)
	PUSHJ	P,MODSFD	;SET UP SFD
	JRST	MODRN1
MODFRN:	HRLZI	T2,'QUD'	;EXTENSION IS QUD
	MOVE	T4,QUEDIR(S)	;QUE DIRECTORY
MODRN1:	LOOKUP	CC,T1		;LOOKUP DATA FILE TO GET LENGTH	
	  JRST	MODLF1		;CANT FIND THE FILE
	MOVEM	T3,SAVPRV(S)	;SAVE PROTECTION CODE
	HLRE	T1,T4		;T1=LENGTH OF DATA FILE
	POP	P,T4		;RESTORE T4
	JUMPGE	T1,.+4
	MOVNS	T1
	ADDI	T1,177
	LSH	T1,-7		;CONVERT TO BLOCKS
	HLRZ	T2,(P)		;NEW-OLD NUMBER OF COPIES
	IMUL	T1,T2		;CHANGE IN NUMBER OF BLOCKS IN REQUEST
	ADDI	T1,7		;ROUND UP TO PREVENT CHEATING
	LSH	T1,-3		;IN 8 BLOCK GROUPS
	ADDM	T1,Q.OSIZ(I)	;REFLECT NEW NUMBER OF COPIES
	LDB	T1,[POINT 6,Q.FMOD(T5),35] ;GET OLD COPIES FIELD
	ADD	T1,T2		;OLD+NEW-OLD=NEW
	DPB	T1,[POINT 6,Q.FMOD(T5),35] ;STORE NEW COPIES FIELD
	JRST	MODFLF		;ALL SET
MODFLR:	PUSHJ	P,MODREM	;REMOVE FILE
	JRST	MODFL1		;SINCE FILE REMOVED T5 ALREADY UPDATED

;HERE WHEN FILE PROCESSED, LOOK FOR NEXT

MODFLF:	LDB	T1,[POINT 9,Q.LEN(I),17]	;GET LENGTH OF ENTRY
	ADDI	T5,(T1)		;GET T5 POINTING TO NEXT FILE IN ORIGINAL REQUEST
				;SPR 10-11,103

MODFL1:	SOSLE	T1,QUEBLK(S)	;SKIP IF NO MORE IN ORIGINAL REQUEST
	JRST	MODFN1		;SEE IF NEXT MATCHES
MODFF1:	ADD	T4,LEN.E(S)	;POINT T4 TO NEXT FILE BLOCK IN MODIFY REQ
				;SPR 10-11,103
	SOS	T1,Q.LEN(A)	;NUMBER OF FILES LEFT IN MODIFY REQUEST
	TRNE	T1,-1		;SKIP IF NO MORE LEFT
	JRST	MODFLN		;DO NEXT
	POPJ	P,		;ALL DONE

MODOFL:	PUSHJ	P,MODOWN	;OUTPUT CANT OPEN DEVICE WARNING
	JRST	MODFLF		;AND DO NEXT FILE

MODLF1:	PUSHJ	P,MODLWN	;OUTPUT LOOKUP FAILURE WARNING
	POP	P,T4		;RESTORE T4
	JRST	MODFLF		;AND DO NEXT FILE

SETUPM:	LDB	T1,[POINT 6,Q.OPR(A),23] ;GET VERSION OF ENTRY
					 ;EDIT 5(43) _ 5(42)
					 ;SPR 10-11,102
	CAIE	T1,1		;IS IT TYPE 1
	MOVEI	M,Q.FMOD+1(T4)	;POINT TO FIRST MOD WORD
	CAIN	T1,1		;IS IT TYPE ONE?
	MOVEI	M,Q.FRPT+2(T4)	;YES--MASKS HAVE MOVED
	POPJ	P,		;RETURN
;MODREM--REMOVE A FILE FROM THE ORIGINAL REQUEST AND GIVE IT
;ITS APPROPRIATE DISPOSTION.  IF A DISPOSITION IS SPECIFIED IN THE MODIFY REQUEST, THAT HAS
;PRECEDENCE OVER THE DISPOSITION SPECIFIED IN THE ORIGINAL REQUEST.
;FOR DISPOSING OF FILES IN A REQUEST TO BE KILLED THAT HAVE NOT BEEN
;REMOVED, THE ORIGINAL DISPOSITION IS USED; IN THIS CASE, T4=0
;ARGS	T4=ADDR OF FILE BLOCK IN MODIFY REQUEST OR 0
;	T5=ADDR OF FILE BLOCK IN ORIGINAL REQUEST
;SAVES T4, T5

MODREM:	MOVEI	T1,17
	MOVE	T2,Q.FSTR(T5)	;ORIGINAL STR
	SETZ	T3,
	OPEN	CC,T1		;OPEN STR
	  JRST	MODORF		;CANT OPEN STR
	PUSH	P,T4		;SAVE T4
	JUMPE	T4,MODRMO	;JUMP IF NO MODIFY FILE SPECIFIED
	LDB	T2,[POINT 3,Q.FMOD(T4),29] ;GET DISPOSITION FROM MODIFY
	JUMPN	T2,MODRO1	;JUMP IF SPECIFIED
MODRMO:	LDB	T2,[POINT 3,Q.FMOD(T5),29] ;GET DISPOSITION FROM ORIGINAL
MODRO1:	JUMPE	T4,MODRO2
	SKIPN	T1,Q.FRNM(T4)	;SKIP IF WAS RENAMED FOR MODIFY
MODRO2:	SKIPE	T1,Q.FRNM(T5)	;SKIP IF WAS NOT RENAMED
	JRST	MODRMR		;FILE WAS RENAMED, T1=NEW NAME
	TRO	T2,400000	;NO, FILE IS STILL IN USER'S AREA
	MOVE	T1,Q.FNAM(T5)	;NAME OF FILE
	HLL	T2,Q.FEXT(T5)	;EXT
	MOVE	T4,Q.FDIR(T5)
	PUSHJ	P,MODSFD	;SET UP FOR SFD
	JRST	MODRR1
MODRMR:	HRLI	T2,'QUD'	;RENAMED TO EXTENSION QUD
	MOVE	T4,QUEDIR(S)	;AND QUEUE DIRECTORY
MODRR1:	TRNN	T2,6		;SKIP IF DELETE OR RENAME
	TRNN	T2,400001	;SKIP IF PRESERVE OR STILL IN USER'S AREA
	JRST	MODRMD		;NO, DELETE FILE
	TRNN	T2,400000	;SKIP IF FILE IS STILL IN USER'S AREA
	JRST	MODRMP		;NO, MUST BE RENAMED
	LOOKUP	CC,T1		;MUST RENAME TO 0XX IF 1XX
	  JRST	MODLRF
	MOVEM	T3,SAVPRV(S)	;SAVE PRIV BITS
	HLLM	T4,-1(P)	;SAVE LENGTH OF FILE
	SKIPL	Q.FBIT(T5)	;YES, SKIP IF WAS ARTIFICIALLY PRESERVED
	JRST	MODRMX		;NO, DO NOTHING
	LDB	T4,[POINT 3,T3,2] ;GET PROTECTION FILED
	SUBI	T4,1
	TLNN	F,L.LEVD	;SKIP IF LEVEL D
	SUBI	T4,3		;COMPENSATE FOR LEVEL C
	JUMPN	T4,MODRMX	;IF NOT WHAT WE MADE IT, USER CHANGED IT
	DPB	T4,[POINT 3,T3,2] ;STORE 0 FOR RENAME
	MOVE	T4,Q.FDIR(T5)
	PUSHJ	P,MODSFD	;SET UP FOR SFD
	JRST	MODRNM
MODRMP:	LOOKUP	CC,T1		;FILE MUST BE RENAMED TO USER'S AREA
	  JRST	MODLRF
	MOVEM	T3,SAVPRV(S)	;SAVE PRIV BITS
	HLLM	T4,0(P)		;SAVE LENGTH OF FILE
				;SPR 10-11,101
	TLZ	T3,777000	;CLEAR OUT CURRENT PROTECTION
	MOVE	T4,0(P)		;PUT BACK POINTER TO FILBLK
				;SPR 10-11,101
	IOR	T3,STNPRT(S)	;SET STANDARD PROTECTION
	PUSHJ	P,MODSF4	;SET UP FOR SFD IF L.SFD IS LIT
	MOVE	T1,Q.FNAM(T5)		;GET FILE NAME TO BE RENAMED TO
	HLL	T2,Q.FEXT(T5)		;AND THE EXTENSION
					;SPR 10-11,101
	JRST	MODRNM


MODRMD:	LOOKUP	CC,T1		;DELETE THE FILE
	  JRST	MODLRF
	MOVEM	T3,SAVPRV(S)	;SAVE PRIV BITS
	HLLM	T4,-1(P)	;SAVE LENGTH OF FILE
	SETZB	T1,T2
MODRNM:	PUSHJ	P,CHKRNM	;CHECK THE RENAME
	RENAME	CC,T1		;FINAL DISPOSITION OF FILE
	  JRST	MODRRF
MODRMX:	RELEASE	CC,
	HLRE	T1,-1(P)	;GET LENGTH OF FILE REMOVED
	JUMPGE	T1,.+4		;JUMP IF BLOCKS
	MOVNS	T1
	ADDI	T1,177
	LSH	T1,-7		;CONVERT TO BLOCKS
	LDB	T2,[POINT 6,Q.FMOD(T5),35] ;GET NUMBER OF COPIES
	JUMPE	T2,MODRX1	;JUMP IF ONE COPY
	IMUL	T1,T2		;TOTAL BLOCKS REMOVED
MODRX1:	LSH	T1,-3		;IN 8 BLOCK GROUPS
	SUBM	T1,Q.OSIZ(I)	;SUBTRACT FROM REQUEST SIZE
	MOVNS	T1,Q.OSIZ(I)
MODRX2:	POP	P,T4		;RESTORE T4
MODRX3:	SOS	T1,Q.LEN(I)	;REDUCE NUMBER OF FILES IN ORIGINAL REQUEST
	PUSHJ	P,REQSIZ	;COMPUTE NEW SIZE OF REQUEST IN T3
	LDB	T1,[POINT 9,Q.LEN(I),17]
				;SPR 10-9139
 				;SPR 10-8719 
				;SPR 10-     
				;SPR 10-9179 
				;SPR 10-11,101 
	ADDI	T1,(T5)
	MOVS	T1,T1		; ..
	HRR	T1,T5		;DESTINATION=CURRENT BLOCK
	ADDI	T3,1(I)		;NEW LAST ADDR IN REQUEST+1
	CAIE	T3,(T1)		;SKIP IF THAT WAS THE LAST FILE
	BLT	T1,-1(T3)	;MOVE UP OVER DISCARDED FILE BLOCK
	POPJ	P,
;SUBROUTINE TO TAKE CARE OF DISPOSITION OF FILE BY RENAMING IT TO PROPER PLACE
;ARGS	T5=ADDR OF FILE BLOCK

FILDIS:	MOVEI	T1,17		;DUMP MODE FOR OPEN
	MOVE	T2,Q.FSTR(T5)	;STR
	SETZ	T3,
	OPEN	CC,T1		;OPEN STR
	  JRST	FILDSO		;CANT
	SKIPN	T1,Q.FRNM(T5)	;SKIP IF WAS RENAMED TO QUE AREA
	JRST	FILDS1		;NO, STILL IN USER'S AREA
	MOVSI	T2,'QUD'	;YES, EXTENSION IS QUD
	MOVE	T4,QUEDIR(S)	;QUE PPN
	JRST	FILDS2		;MOVE UP TO LOOKUP
FILDS1:	MOVE	T1,Q.FNAM(T5)	;ORIGINAL NAME OF FILE
	HLLZ	T2,Q.FEXT(T5)	;EXT
	MOVE	T4,Q.FDIR(T5)	;PPN
	PUSHJ	P,MODSFD	;SET UP FOR SFD IF L.SFD IS LIT
FILDS2:	LOOKUP	CC,T1		;LOOKUP FILE
	  JRST	FILDSL		;CANT LOOKUP FILE
	MOVEM	T3,SAVMOD(S)	;SAVE FOR SPOOLERS
	MOVEM	T2,SAVDAT(S)
	LDB	T1,[POINT 3,Q.FMOD(T5),29] ;GET DISPOSITION OF FILE
	CAIE	T1,2		;SKIP IF RENAME
	JRST	FILDS3		;NO
	SKIPE	Q.FRNM(T5)	;SKIP IF IS STILL IN USER'S AREA
	JRST	FILDSX		;NO, ALREADY RENAMED, OK
	MOVE	T1,QUEDIR(S)	;PPN TO MOVE FILE TO
	PUSHJ	P,GVAWAY	;RENAME TO QUE AREA
	  JFCL			;DONT CARE IF CANT
	JRST	FILDSX		;ALL DONE
FILDS3:	SKIPN	Q.FRNM(T5)	;SKIP IF WAS RENAMED TO QUE AREA
	JRST	FILDS4		;NO, SEE IF SHOULD CHANGE PROTECTION
	PUSHJ	P,FILRCL	;YES, RECLAIM THE FILE
	JRST	FILDSX		;ALL DONE
FILDS4:	MOVE	T4,Q.FDIR(T5)	;DIRECTORY OF FILE
	CAMN	T4,Q.PPN(A)	;SKIP IF NOT USER'S
	TLNE	T3,(7B2)	;SKIP IF USER'S FILE AND UNPRESERVED
	JRST	FILDSX		;NO, DONT CHANGE PROTECTION
	TLO	T3,(1B2)	;SET PRESERVE PROTECTION
	MOVE	T1,Q.FNAM(T5)	;RESET FILE NAME
	PUSHJ	P,MODSFD	;SET UP FOR SFD IF L.SFD IS LIT
	RENAME	CC,T1		;RESET PROTECTION
	  JRST	FILDSX		;CANT - OH WELL
	MOVSI	T1,(1B0)	;ARTIFICIALLY PRESERVED FLAG
	IORM	T1,Q.FBIT(T5)	;STORE IN REQUEST
FILDSX:	RELEASE	CC,		;RELEASE CHANNEL
	POPJ	P,

FILDSO:	PJRST	MODOWN		;TYPE WARNING ABOUT OPEN AND EXIT

FILDSL:	PJRST	MODLWN		;TYPE WARNING ABOUT LOOKUP FAILURE
;SUBROUTINE TO RENAME A FILE TO ANOTHER AREA
;ARGS	T1=DESTINATION PPN
;FILE LOOKED UP ON CHANNEL CC

GVAWAY:	TLNN	F,L.LEVD	;SKIP IF LEVEL D
	POPJ	P,		;CANT DO IF LEVEL C
	PUSH	P,T5		;SAVE T5
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,LN.LOP*2	;LARGE NUMBER OF LOOPS OK
	MOVEM	T1,LOPCNT(S)
	MSTIME	K,

GVWAY1:	MOVE	T1,QUENM(S)	;NAME OF QUEUE FOR FIRST TWO LETTERS
	MOVE	T2,[POINT 6,T1,11] ;BYTE PTR FOR THE OTHER CHARS
	ADD	K,THSJOB(S)	;INCREMENT BY JOB NUMBER TO AVOID CONFLICTS
	MOVE	T3,K

GVWAY2:	IDIVI	T3,^D36
	ADDI	T4,'0'
	CAILE	T4,'9'
	ADDI	T4,'A'-'9'-1
	IDPB	T4,T2		;STORE NEXT CHAR IN NAME
	TLNE	T2,(77B5)
	JRST	GVWAY2
	HRLI	T2,'QUD'
	HRR	T2,SAVDAT(S)
	MOVSI	T3,(177B8)
	IOR	T3,SAVMOD(S)	;PUT MODE BACK IN PLACE
	MOVE	T4,(P)
	PUSHJ	P,NEWLOG	;INFORM CHAR TYPE ROUTINE OF NEW NAME
	PUSHJ	P,CHKRNM	;DO A CHKACC
	RENAME	CC,T1		;RENAME TO NEW AREA
	  JRST	GVWAYE		;DIDN'T MAKE IT
	POP	P,T5		;IGNORE DESTINATION PPN
	POP	P,T5		;RESTORE ADDR OF FILE BLOCK
	MOVEM	T1,Q.FRNM(T5)	;STORE NEW NAME
	JRST	CPOPJ1		;GOOD RETURN
GVWAYE:	TRNE	T2,777773	;ERROR CODE 4 ?
	  JRST	GVWAYP		;NO, REPORT ERRROR
	PUSHJ	P,LOOPR		;GUARD AGAINST INFINITE LOOP
	JRST	GVWAY1		;TRY ANOTHER NAME


;SUBROUTINE TO CHKACC A RENAME UUO
;ARGS T5=POINTER TO QUEUE ENTRY
;	A=POINTER TO REQUEST
;SKIP RETURN WITH RH OF T2=2 IF ERROR
;ELSE NON-SKIP

CHKRNM:	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3
	PUSH	P,T4
	MOVEI	T1,T2		;POINT  TO T2
	HLRZ	T2,SAVPRV(S)	;GET PROTECTION BITS
	LSH	T2,-^D9		;SHIFT TO END OF WORD
	HRLI	T2,1		;CODE FOR RENAME
	MOVE	T3,Q.FDIR(T5)	;GET FILES OWNER
	GETPPN	T4,		;GET USERS PPN
	  JFCL			;SILLY SKIP
	CHKACC	T1,		;SEE IF OK
	  SETZ	T1,		;ASSUME GOOD
	JUMPN	T1,[AOS -4(P)	;CANNOT DO A RENAME GIVE SKIP RETURN
		HRRI T2,2	;FUDGE ERROR CORE 2
		HRRM T2,-2(P)	;STORE INTO SAVED T2
		JRST .+1]	;RESTORE REGS AND EXIT
	POP	P,T4		;RESTORE ACS
	POP	P,T3
	POP	P,T2
	POP	P,T1
	POPJ	P,

GVWAYP:	POP	P,T5		;CORRECT STACK
	POP	P,T5		; ..
	JRST	MODRWN		;INFORM USER
;SUBROUTINE TO RECLAIM A FILE FROM THE WASTELANDS OF THE QUE AREA
;FILE LOOKED UP ON CHANNEL CC

FILRCL:	MOVE	T1,Q.FNAM(T5)	;OLD NAME OF FILE
	HLL	T2,Q.FEXT(T5)	;OLD EXT
	HRR	T2,SAVDAT(S)
	LDB	T3,[POINT 27,SAVPRV(S),35]
	IOR	T3,STNPRT(S)
	TLNE	T3,(7B2)	;SKIP IF NOT NORMALLY PRESERVED
	JRST	FILRC0		;OK, DONT NEED ANYTHING ELSE
	TLO	T3,(1B2)	;NO, MAKE PRESERVED
	MOVSI	T4,(1B0)	;ARTIFICIALLY PRESERVED BIT
	IORM	T4,Q.FBIT(T5)	;SET ARTIFICIALLY PRESERVED BIT
FILRC0:	MOVE	T4,Q.FDIR(T5)	;OLD DIRECTORY
	PUSHJ	P,MODSFD	;SET UP FOR SFD IF L.SFD IS LIT
	PUSHJ	P,NEWLOG	;NOTIFY OUTPUT ROUTINES IF LOG FILE
	RENAME	CC,T1		;RENAME FILE TO USER
	  JRST	FILRC1		;LOST, SIGH
	SETZM	Q.FRNM(T5)	;CLEAR RENAMED FLAG
	POPJ	P,
FILRC1:	TRNE	T2,777773	;ERROR CODE 4
	  POPJ	P,		;EXIT IF NOT FILE ALREADY EXISTS
FILRC2:	MOVE	T1,Q.FDIR(T5)	;GOING TO FAKE IT FOR GVAWAY
	PUSHJ	P,GVAWAY	;TRY TO FIND A GOOD NAME
	  POPJ	P,		;CANT RENAME
	MOVEI	M,[ASCIZ /
% File /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,Q.FNAM(T5)	;OLD NAME OF FILE
	PUSHJ	P,TSIX		;TYPE OLD NAME
	MOVEI	M,"."		;DOT FOR EXTENSION
	PUSHJ	P,CHROUT	;TYPE CHAR
	HLLZ	T1,Q.FEXT(T5)	;OLD EXTENSION
	PUSHJ	P,TSIX		;TYPE OLD EXTENSION
	MOVEI	T1,Q.FDIR(T5)	;OLD DIRECTORY
	PUSHJ	P,TPATH		;TYPE OLD DIRECTORY
	MOVEI	M,[ASCIZ / already exists, new name is /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,Q.FRNM(T5)	;NEW NAME
	PUSHJ	P,TSIX		;TYPE THAT
	MOVEI	M,[ASCIZ /.QUD
/]
	PUSHJ	P,STROUT	;TYPE STRING
	SETZM	Q.FRNM(T5)	;CLEAR RENAMED FLAG
	POPJ	P,
;SUBROUTINE TO NOTIFY OUTPUT CHARACTER ROUTINE OF NEW NAME FOR LOG FILE
;ARGS	T1=FILE NAME
;	T2=EXT
;	T4=PPN
;	T5=ADDR OF FILE BLOCK IN REQUEST

NEWLOG:	MOVE	M,Q.FMOD(T5)	;GET MOD BITS TO CHECK FOR LOG FILE
	TLNN	M,(X.LOG)	;SKIP IF THIS IS LOG FILE
	POPJ	P,		;NO, FORGET IT
	HLRZ	M,TYPCHR(S)	;ADDR OF ROUTINE TO CALL
	JUMPE	M,CPOPJ		;JUMP IF NO ROUTINE TO CALL
	PUSH	P,1		;SAVE 1
	MOVEI	1,QUEBLK(S)	;MUST SAVE QUEBLK - THE REST IS TEMP
NEWLGB:	PUSH	1,Q.FSTR(T5)	;NEW STR=OLD STR
	PUSH	1,T4		;NEW DIRECTORY
	PUSH	1,[0]		;0 FOR REST OF FULL PATH NAME
	PUSH	1,[0]		;0 FOR REST OF FULL PATH NAME
	PUSH	1,[0]		;0 FOR REST OF FULL PATH NAME
	PUSH	1,[0]		;0 FOR REST OF FULL PATH NAME
	PUSH	1,[0]		;0 FOR REST OF FULL PATH NAME
	PUSH	1,T1		;NEW FILE NAME
	PUSH	1,T2		;NEW EXT
	HRLZI	1,.-NEWLGB	;***LENGTH OF BLOCK=NUMBER OF PUSHES
	HRRI	1,QUEBLK+1(S)	;ADDR OF FIRST WORD
	PUSHJ	P,(M)		;CALL ROUTINE
	POP	P,1
	POPJ	P,
MODORF:	PUSHJ	P,MODOWN	;OPEN FAILURE WARNING
	JRST	MODRX3		;AND GIVE UP ON THIS FILE

MODLRF:	PUSHJ	P,MODLWN	;LOOKUP FAILURE WARNING
	JRST	MODRX2		;AND GIVE UP ON THIS FILE

MODRRF:	HRRZ	T3,T2		;T3=ERROR CODE
	CAIE	T3,4		;SKIP IF FILE ALREADY EXISTS
	JRST	MODRF1
	PUSHJ	P,FILRC2	;TRY TO FIND UNIQUE NAME
	JRST	MODRX2
MODRF1:	PUSHJ	P,MODRWN	;RENAME FAILURE WARNING
	JRST	MODRX2		;AND GIVE UP ON THIS FILE

MODOWN:	MOVEI	M,[ASCIZ /
% Open failure for device /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,T2		;DEVICE THAT WOULDNT OPEN
	PUSHJ	P,TSIX		;TYPE IT
	PJRST	MODLW2		;ADD IN QUEUE MANGER MESSAGE AND EXIT

MODRWN:	MOVEI	M,[ASCIZ /
% Rename failure /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,Q.FNAM(T5)	;ORIGINAL NAME OF FILE
	HLL	T2,Q.FEXT(T5)	;AND EXT
	MOVE	T4,Q.FDIR(T5)	;AND PPN
	PUSHJ	P,MODSFD	;SET UP FOR SFD IF L.SFD IS LIT
	JRST	MODLW1		;FINISH LINE SAME AS LOOKUP ERROR

MODLWN:	MOVE	T3,Q.FMOD(T5)
	TLNE	T3,(X.NEW)	;THIS BIT SAYS OK IF FILE DOESNT EXIST YET
	POPJ	P,		;OK, NO MESSAGE
	MOVEI	M,[ASCIZ /
% Lookup failure /]
	PUSHJ	P,STROUT	;TYPE STRING
MODLW1:	HLLM	T2,(P)		;SAVE EXT
	HRRZS	T2		;T2=ERROR CODE
	IDIVI	T2,10
	MOVEI	M,"0"(T2)	;M=HIGHER DIGIT IN ASCII
	CAIE	M,"0"		;BUT DONT TYPE LEADING 0
	PUSHJ	P,CHROUT	;TYPE CHAR
	MOVEI	M,"0"(T3)	;M=LOWER DIGIT IN ASCII
	PUSHJ	P,CHROUT	;TYPE THAT
	MOVEI	M,[ASCIZ / file /]
	PUSHJ	P,STROUT	;TYPE STRING
	PUSH	P,T1		;SAVE FILE NAME
	MOVE	T1,Q.FSTR(T5)	;DEVICE
	PUSHJ	P,TSIX		;TYPE DEVICE
	MOVEI	M,":"		;COLON AFTER DEVICE
	PUSHJ	P,CHROUT	;TYPE COLON
	POP	P,T1		;RESTORE FILE NAME
	PUSHJ	P,TSIX		;TYPE FILE NAME
	MOVEI	M,"."		;DOT AFTER FILE NAME
	PUSHJ	P,CHROUT	;TYPE CHAR
	HLLZ	T1,(P)		;RESTORE EXT
	PUSHJ	P,TSIX		;TYPE THAT
	MOVE	T1,T4		;PPN
	PUSHJ	P,TPATH0	;TYPE THAT
MODLW2:	MOVEI	M,[ASCIZ / in queue manager
/]
	PJRST	STROUT		;TYPE STRING AND EXIT
;UPFNJB--FIND AN ENTRY IN THE MASTER QUEUE
;ARGS	Q.JOB(A)=REQUEST NAME
;	Q.CREA=MASK FOR REQUEST NAME
;	Q.PPN(A)=PPN
;	Q.TIME=MASK FOR PPN
;	Q.SEQ=SEQUENCE NUMBER IF SPECIFIED OR 0
;VALUES	T1=-1 IF NO SUCH ENTRY, =0 IF BUSY, =1 IF FOUND AND NOT BUSY
;	J=ADDR OF ENTRY IN MASTER QUEUE

UPFNJB:	PUSHJ	P,GTMAST	;GET NEXT ENTRY IN MASTER QUEUE
	  JRST	UPFNE1		;NOT THERE
	MOVE	T1,Q.CREA(A)	;MASK FOR REQUEST NAME
	MOVE	T2,T1
	AND	T1,M.EJOB(J)	;MASK NAME FROM MASTER QUEUE
	AND	T2,Q.JOB(A)	;AND FROM REQUEST
	CAME	T1,T2		;SKIP IF MATCH
	JUMPN	T2,UPFNJB	;NO, BUT OK IF NO NAME SPECIFIED
	MOVE	T1,M.EPPN(J)	;PPN OF ENTRY IN MASTER QUEUE
	AND	T1,Q.TIME(A)	;MASK
	CAME	T1,Q.PPN(A)	;SKIP IF MATCHES PPN SPECIFIED
	JRST	UPFNJB		;NO, TRY NEXT
	MOVE	T1,Q.SEQ(A)	;SEQUENCE NUMBER IF SPECIFIED
	CAME	T1,M.ESEQ(J)	;SKIP IF MATCHES ENTRY IN MASTER QUEUE
	JUMPN	T1,UPFNJB	;NO, REJECT IF WAS SPECIFIED, OK IF NOT
	PUSHJ	P,CHKUSM	;FOUND IT, SEE IF IN USE
	  TDZA	T1,T1		;IN USE, RETURN T1=0
	MOVEI	T1,1		;OK, RETURN FOUND
	POPJ	P,
UPFNE1:	MOVNI	T1,1		;INTERLOCKED, RETURN BUSY
	POPJ	P,
;REQWRT--WRITE OUT REQUEST FILE
;ARGS	T1=LEN WORD FROM REQUEST
;	T2=ADDR OF FIRST WORD OF REQUEST

REQWRT:	PUSHJ	P,REQSIZ	;COMPUTE SIZE OF REQUEST
	JUMPE	T1,RELCC	;IF EMPTY REQUEST, RETURN NOW
	HRRI	T1,(T2)		;GET STARTING POINT
	MOVEI	T2,0		;END OF LIST
	OUT	IO,T1		;WRITE THE REQUEST
	  JRST	RELCC		;OK--GO CLOSE
	IOERR	<Request write>
RELCC:	PUSHJ	P,CLO.IO	;CLOSE IO
	CLOSE	IO,		;CLOSE FILE
	STATO	IO,74B23	;LOOK FOR ERRORS
	  JRST	RELSCC		;NONE--GO RELEASE
	IOERR	<Request close>
RELSCC:	RELEAS	CC,		;RELEASE THE CHANNEL
	POPJ	P,

;REQSIZ--COMPUTE LENGTH OF REQUEST FOR IOWD
;ARGS	T1=LEN WORD FROM REQUEST
;VALUES	T1= XWD -LENGTH OF REQUEST,0
;	T3= + LENGTH OF REQUEST FILE

REQSIZ:	LDB	T3,[POINT 9,T1,17]  ;GET LENGTH OF FILE
	IMULI	T3,(T1)		;TIMES NUMBER OF FILES
	LSH	T1,-^D27	;GET HEADER LENGTH
	ADDB	T1,T3		;GET TOTAL
	MOVNS	T1		;COMPLEMENT AS IOWD LENGTH
	HRLZ	T1,T1		;POSITION IT
	POPJ	P,

;SUBROUTINE TO GET LENGTH OF HEADER AND LENGTH OF EACH ENTRY
; CALLED ANY TIME WE HAVE A QUEUE REQUEST AS AN ARGUMENT.
;
SETLEN:	LDB	T1,[POINT 9,Q.LEN(A),8] ;GET LENGTH OF HEADER
	CAIG	T1,Q.USER	;MAKE SURE IT INCLUDES USER NAME
	JRST	E.LOHS		;LENGHT OF HEADER TOO SHORT
	MOVEM	T1,LEN.H(S)	;STORE LENGTH OF HEADER
	LDB	T1,[POINT 9,Q.LEN(A),17] ;GET LENGTH OF EACH ENTRY
	MOVEM	T1,LEN.E(S)	;STORE IT
	CAIGE	T1,Q.FMOD	;DO WE GO AT LEAST TO Q.FMOD
	JRST	E.LOES		;NO--BOMB
	POPJ	P,		;ALL OK -- RETURN
;MODSFD--SET T4 TO POINT TO A FULL PATH NAME
;ARGS	T5=POINTER TO REQUEST
;VALUES	T4=POINTER TO PATH IF SFD MONITOR OR UNCHANGED
;	   IF SFD MONITOR ALSO SET UP PATH
;
MODSFD:	TLNN	F,L.SFD		;TEST FOR SFD BIT
	POPJ	P,		;IT IS OFF - RETURN
	SETZM	PATH(S)		;CLEAR STR NAME
	SETZM	PATH+1(S)	;INHIBIT SCANING
	MOVSI	K,Q.FDIR(T5)	;POINT TO PATH
	HRRI	K,PATH+2(S)	;POINT TO BLOCK
	BLT	K,PATH+10(S)	;COPY PATH
	SETZM	PATH+11(S)	;CLEAR FINAL WORD
	MOVEI	T4,PATH(S)	;SET UP POINTER
	POPJ	P,		;RETURN

;MODSF4--SAME AS MODSFD EXCEPT POINTER IN T4
;ARGS	T4=POINTER TO BLOCK
;VALUES	T4=Q.FDIR(T4) IF L.SFD IS 0
;	T4=POINTER TO PATH IF L.SFD IS 1
;
MODSF4:	PUSH	P,T5		;SAVE T5
	MOVE	T5,T4		;COPY POINTER
	PUSHJ	P,MODSFD	;SET UP T4
	POP	P,T5		;RESTORE T5
	TLNN	F,L.SFD		;IS THIS AN SFD MONITOR?
	MOVE	T4,Q.FDIR(T4)	;NO--SET UP PPN
	POPJ	P,		;RETURN TO CALLER
	SUBTTL	LIST QUEUES

;HERE WHEN THE REQUESTING CUSP WANTS AN ENTRY TO LIST
;GENERAL PLAN IS JUST LIKE SCHEDULING (SEE BELOW) EXCEPT AS FOLLOWS.
;RETURN ALL ENTRIES AND IGNORE THE MAX PRIORITY RESULT.

FLIST:	TLOA	F,L.FLST	;FAST LIST (DONT READ MAST QUEUE OR READ REQUESTS)
LIST:	TLZ	F,L.FLST	;REGULAR LIST, NOT FAST LIST
	GET	MEM		;GET ADDR OF ROUTINES FOR TYPING CHARS
	MOVEM	T1,TYPCHR(S)
	TLO	F,L.LST		;FLAG FOR LISTING
	SKIPE	QUENM(S)	;SEE IF ALL:?
	JRST	LISTON		;NO--LIST JUST ONE QUEUE
	SETZM	QUECNT(S)	;YES--PRESET COUNTER
LISTLP:	AOS	T1,QUECNT(S)	;ADVANCE TO NEXT QUEUE
	SKIPN	T1,QUENMS-1(T1)	;SEE IF AT END YET
	JRST	LISTRT		;YES--RETURN
	TLZ	T1,77		;ONLY CARE ABOUT FIRST 2 CHARS
	MOVEM	T1,QUENM(S)	;NO--STORE THIS PREFIX
	IOR	T1,['MAST']	;MAKE INTO MASTER NAME
	MOVEM	T1,MASNAM(S)	;AND STORE THAT
	PUSHJ	P,PASS		;PASS IT BY THE LISTER
	JRST	LISTLP		;AND LOOP BACK FOR THE NEXT QUEUE

LISTON:	PUSHJ	P,PASS		;SCAN THE QUEUE
LISTRT:	PUSHJ	P,CLRPRM	;WIPE OUT PARAMETER AREA
	JRST	RETURN		;AND RETURN TO USER
;LIST OF QUEUES IN THE ORDER TO BE LISTED

	DEFINE	X(LIST)<
IRP LIST,<SIXBIT \LIST\>>

QUENMS:	QUEUES		;DEFINE NAMES OF QUEUES
	0			;END OF LIST

	DEFINE	X(LIST)<
IRP LIST,<
.ZZ==0
IFIDN <LIST> <INP>,<SIXBIT \BATCON\
.ZZ==1>

IFIDN <LIST> <LPT>,<SIXBIT \LPTSPL\
.ZZ==1>

IFIDN <LIST> <CDP>,<SIXBIT \CDPSPL\
.ZZ==1>

IFIDN <LIST> <PTP>,<SIXBIT \PTPSPL\
.ZZ==1>

IFIDN <LIST> <PLT>,<SIXBIT \PLTSPL\
.ZZ==1>
IFIDN <LIST><JNH>,<SIXBIT \JUSTIF\
.ZZ==1>

IFE .ZZ,<EXP 0
PRINTX ILLEGAL QUEUE NAME LIST>
>>

;LIST OF PROGRAMS WHICH PROCESS EACH QUEUE

QUEPRC:	QUEUES
	SUBTTL	PROCESS SCHEDULE REQUEST

;HERE WHEN REQUESTING CUSP WANTS AN ENTRY TO PROCESS
;FOR EACH ENTRY IN THE QUEUE WHICH IS NOT OBVIOUSLY
;UNINTERESTING NOW, ASK THE CUSP TO ASSIGN A PRIORITY.
;IF THE PRIORITY IS 0, THE ENTRY IS NOT INTERESTING NOW.
;SELECT THE ENTRY WITH MAX NON-ZERO PRIORITY.
;IF NONE, THE PARAMETER AREA WILL BE RETURNED WITH Q.DEV=0.
;IF ONE, THE PARAMETER AREA WILL BE FILLED WITH THE REQUEST.

NXTJOB:	PUSHJ	P,HACREL	;FIRST RELEASE WHAT WE HAVE
SCHED:	TLNN	F,L.SYSQ	;SYSTEM QUEUE?
	JRST	SCHED1		;NO--DO NOT NEED TO CHECK
	GETPPN	I,		;GET MY PPN
	  JFCL			;SILLY SKIP RETURN
	CAMN	I,FSFPPN(S)	;AM I [1,2]
	JRST	SCHED1		;YES--I CAN GO AHEAD
	MOVEI	T1,T2		;NOW I WANT TO SEE
	MOVEI	T2,777		; IF I HAVE FULL FILE
	MOVE	T3,I		; ACCESS
	MOVE	T4,I		; ..
	CHKACC	T1,		; ..
	  JRST	SCHED1		;I DO NOT  -- SO SAFE TO TRY
	JUMPN	T1,SCHED1	;JUMP IF DO NOT HAVE FULL FILE AACCESS
	GETLIN	T1,		;GET MY TTY NAME
	WHERE	T1,		;AND ITS STATION
	  SETZ	T1,		;NO REMOTE LOGIC
	MOVSI	T1,100(T1)	;PROJECT=100+STATION
	HRRI	T1,2		;PROGRAMMER = 2
	CAMN	T1,I		;AM I THE REMOTE OPR?
	JRST	SCHED1		;YES--I WIN
	FAIL	<Can not use system queue unless you are [OPR]
or located at remote station with PPN [100+S,2].
to debug type "AS DSK:QUE"
error was detected >
SCHED1:	MOVSI	T1,'OPR'	;GET TARGET STATION
	HLRZ	T2,QUENM(S)	;SEE IF INPUT QUEUE
	CAIE	T2,'IN '	;  IF SO, NO REMOTE LOGIC
	WHERE	T1,		;CONVERT TO STATION NUMBER
	  MOVEI	T1,0		;IN CASE OF NON-REMOTE
	HRRZM	T1,REMSTA(S)	;STORE FOR EASY TESTS LATER
	MOVE	T1,PRODV(S)	;AND AGAIN
	PUSHJ	P,REMOTE	;CONVERT TO 1000+DEVICE NUMBER
	HRRZM	T1,REMDEV(S)	;AND STORE FOR EASY TESTS
	JRST	SCHEDL		;AND GO ENTER SCHEDULING LOOP

RSCHED:	PUSHJ	P,CLO.IO	;CLOSE IO
	CLOSE	IO,50		;BACK HERE TO TRY AGAIN
	PUSHJ	P,LOOPR		;PROTECT AGAINST INF.LOOP
	IFN	DEBUG,<	TLNE	F,L.MAST  ;SEE IF INTERLOCKED
			JRST	E.MASL	;YES--BOMB>
SCHEDL:	PUSHJ	P,PASS		;GO PASS THE FULL QUEUE PAST THE
				;  SCHEDULER
;HERE AFTER LOOKING AT ENTIRE QUEUE
;CLEAR PARAMETER AREA AND IF A REQUEST, GET IT AND READ IT

SCHEDG:	PUSHJ	P,CLRPRM	;CLEAR PARAMETER AREA
	SKIPE	T1,AFTNUM(S)	;NUMBER OF REQUESTS REJECTED FOR AFTER OR DEPEN
	PUSHJ	P,ASKDAE	;PUT IN CLOCK REQUEST
	PUT	AFTR		;RETURN NUMBER OF REJECTS TO CALLER
	SKIPN	BESTPR(S)	;SEE IF A GOOD ONE FOUND
	JRST	RETURN		;NO--JUST RETURN TO USER

	MOVE	T1,BESTNM(S)	;PREPARE FOR LOOKUP
IFN DEBUG,<SETZM SCHLPF(S)	;FLAG REASON CANT SCHEDULE>
	PUSHJ	P,GETIT		;READ QUEUE WINDOW
	  JRST	RSCHED		;TRY AGAIN IF NOT THERE
IFN DEBUG,<AOS SCHLPF(S)	;FLAG THE OTHER REASON>
	PUSHJ	P,CHKUSM	;SEE IF IT IS IN USE
	  JRST	RSCHMS		;YES--TRY AGAIN
	MOVE	T1,PRODV(S)	;NO--GET OUR DEVICE
	MOVE	T2,T1		;T2=DEVICE
	DEVCHR	T2,		;FIND OUT IF DISK OR TTY
	TLNN	T2,(D.DSK!D.TTY) ;SKIP IF DISK OR TTY
	JRST	SCHDID		;NO, INTERLOCK REQUEST BY DEVICE
	PUSHJ	P,JBLOCK	;YES, INTERLOCK DEVICE BY JOB
	JRST	SCHEDI		;INTERLOCK SET UP
SCHDID:	HRLZ	T3,THSJOB(S)	;THIS JOB
	PUSHJ	P,CPRGPN	;SET UP WORD 2 OF DEVICE INTERLOCK
	HRRZ	T2,T4		;FOLDED PROGRAM NAME+PPN
	HRL	T2,THSJOB(S)	;THIS JOB
SCHEDI:	MOVEM	T1,M.EPDV(J)	;STORE IN REQUEST
	MOVEM	T2,M.EPDV+1(J)	;AND SECOND WORD
	TLO	F,L.CHNG	;FLAG THAT ENTRY IS CHANGED

	PUSHJ	P,REDREQ	;READ REQUEST INTO AREA
	  JRST	SCHFAL		;GIVE UP IF NOT STILL THERE

	MOVE	T1,BESTNM(S)	;SAVE NAME AWAY
	PUT	MEM		;  WHERE RELEASE CAN FIND IT

	MOVE	T1,NOW(S)	;GET CURRENT TIME
	PUT	TIME		;RETURN TO CALLER
	PUSHJ	P,TOPRMP	;MOVE REST OF MASTER QUEUE ENTRY ON TOP
	JRST	RETMAS		;AND GO BACK TO CALLER

;HERE WHEN REQUEST CAN NOT BE FOUND

SCHFAL:	LWARN	<scheduling>
	MOVEI	M,[ASCIZ	/% Request deleted
/]
	PUSHJ	P,STROUT	;TYPE STRING
	PUSHJ	P,CLRMAS	;CLEAR REQUEST FROM QUEUE

RSCHMS:	PUSHJ	P,RTMAST	;RETURN MASTER QUEUE INTERLOCK
	JRST	RSCHED		;AND START AGAIN
	SUBTTL	PROCESS RELEASE REQUEST

;HERE WHEN USER IS DONE WITH THE REQUEST AND IT IS TO BE RELEASED.

HACREL:	PUSHJ	P,PIKREQ		;PICK UP THE REQUEST
	POPJ	P,		;SOMETHING WENT WRONG... GO DO A SCHEDULE NOW



	PUSHJ	P,RELESS		;DELETE GUY
	PJRST	RTMAST		;RETURN MASTER QUEUE INTERLOCK



RELEAS:	PUSHJ	P,PIKREQ	;PICK UP REQUEST AGAIN
	  JRST	REQREL		;CANT FIND IT, GIVE UP
RELES1:	PUSHJ	P,RELESS	;DELETE ENTRY FROM MASTER QUEUE
	JRST	REQREL		;CLEAR PARAMETER AREA AND RETURN


;SUBROUTINE TO DELETE AN ENTRY FROM THE MASTER QUEUE

RELESS:	PUSH	P,M.ENAM(J)	;SAVE REQUEST'S FILE NAME
	PUSHJ	P,CLRMAS	;CLEAR REQUEST IN MASTER QUEUE
	TLO	F,L.CHNG	;FLAG WINDOW AS CHANGED
	POP	P,T1		;RESTORE FILE NAME
	PUSHJ	P,LOOKR1	;AND GO LOOK IT UP
	  JRST	RELFAL		;GIVE UP IF NOT STILL THERE
	SETZB	T1,T2		;CLEAR FILE NAME
	RENAME	IO,T1		;DELETE
	  JRST	W.DF		;IF DELETE FAILED
	POPJ	P,

;HERE WHEN REQUEST CAN NOT BE FOUND

RELFAL:	LWARN	<releasing>
	POPJ	P,
	SUBTTL	PROCESS REQUEUE REQUEST

;HERE WHEN USER IS DONE WITH THE REQUEST AND IT IS TO BE PUT BACK
;INTO THE QUEUE.

CHKPNT:	TLO	F,L.CHK		;FLAG AS CHKPNT
REQUEU:	GET	AFTR		;GET AFTER PARAMETER
	PUSHJ	P,UPDTIM	;HANDLE + FORM
	PUT	AFTR		;RESTORE
	GET	DEAD		;GET DEADLINE
	PUSHJ	P,UPDTIM	;HANDLE + FORM
	PUT	DEAD		;RESTORE
	PUSHJ	P,PIKREQ	;PICK UP REQUEST AGAIN
	  JRST	REQREL		;CANT FIND IT, GIVE UP
	PUSH	P,M.ENAM(J)	;SAVE REQUEST'S FILE NAME
	SETZM	RB.AUT(S)	;CLEAR AUTHOR TO FAKE OUT VALPPN
	MOVEI	I,(A)		;POINT TO PARAMETER AREA
	PUSHJ	P,TOMAS		;COPY NEW MASTER QUEUE ENTRY
	POP	P,T1		;RESTORE FILE NAME
	TLZ	T1,777700	;CLEAR JUNK
	IORM	T1,M.ENAM(J)	;STORE IN MASTER QUEUE
	PUSHJ	P,LOOKR		;LOOK UP REQUEST
	  JRST	REQFAL		;GIVE UP IF NOT STILL THERE
	PUSH	P,T3		;SAVE IOWD TO PARAM AREA
	MOVE	T1,M.ENAM(J)	;MANUFACTURE FILE NAME
	TLZ	T1,777700	;CLEAR JUNK
	IOR	T1,QUENM(S)	;ADD PREFIX
	MOVSI	T2,'QUF'	;RESTORE EXTENSION
	MOVEI	T3,0		;CLEAR GARBAGE
	MOVE	T4,QUEDIR(S)	;GET DIRECTORY
	ENTER	IO,T1		;ENTER
	  JRST	W.REF		;JUMP IF FAILED
	POP	P,T3		;RESTORE IOWD
	MOVEI	T4,0		;SET END OF LIST
	USETO	IO,1		;POSITION TO FIRST BLOCK
	OUT	IO,T3		;WRITE UPDATED REQUEST
	  JRST	REQCLS		;PROCEED IF NO ERROR
	IOERR	<Requeue request write>
REQCLS:	CLOSE	IO,10		;CLOSE REQUEST
	STATO	IO,74B23	;SEE IF ANY CLOSING ERRORS
	  JRST	REQREL		;NO--PROCEED
	IOERR	<Requeue request close>
REQREL:	TLNN	F,L.CHK		;FLAG AS CHKPNT
	PUSHJ	P,CLRPRM	;CLEAR PARAMETER AREA
	JRST	RETMAS		;RETURN TO USER


;HERE WHEN REQUEST CAN NOT BE FOUND

REQFAL:	LWARN	<requeueing>
	MOVEI	M,[ASCIZ /% Request deleted
/]
	PUSHJ	P,STROUT	;TYPE STRING
	JRST	RELES1		;GO HANDLE AS A DELETE

REQDEL:	MOVEI	M,[ASCIZ /% Request deleted
/]
	PUSHJ	P,STROUT	;TYPE STRING
	PJRST	RELESS		;DELETE ENTRY FROM MASTER QUEUE

	SUBTTL	SUBROUTINES

;PASS -- PASS ENTIRE QUEUE PAST THE SCHEDULER OR LISTER
;CALL:	SET FLAG L.LST (0=SCHED, 1=LIST)
;	PUSHJ	P,PASS
;	RETURNS AT END OF QUEUE
;USES T1, T2, T3, T4

PASS:	TLNN	F,L.FLST	;SKIP IF FAST LIST
	PUSHJ	P,UPMASQ	;UPDATE MASTER QUEUE BEFORE PASS
	SETZM	MASIOW(S)	;FLAG TO START AT BEGINNING OF QUEUE
	SETZM	BESTPR(S)	;CLEAR STARTING PRIORITY
	SETZM	MINAFT(S)	;CLEAR MIN /AFTER WAIT TIME
	SETZM	AFTNUM(S)	;CLEAR COUNT OF REJECTS FOR AFTER, ETC

;LOOP TO SEARCH OVER UFD (IN CORE) AND FIND INTERESTING REQUESTS.

DOONE:	PUSHJ	P,GTMAST	;SEARCH FOR ONE MORE
	  POPJ	P,		;IF NO MORE LEFT
	MOVEM	T1,THISNM(S)	;SAVE NAME FOR LATER
	PUSHJ	P,TOPRM		;SET UP PARAMETER AREA
	JUMPE	T1,DOONE	;LOOP IF EMPTY
	MOVE	T1,NOW(S)	;GET CURRENT TIME
	PUT	TIME		;SET INTO ENTRY

;HERE WHEN REQUEST HAS BEEN READ INTO CORE
;CHECK IT OVER BEFORE CALLING SCHEDULER

	TLNE	F,L.LST		;SEE IF LISTING MODE
	JRST	GOLIST		;YES--SKIP REJECTION TESTS
;HERE WHEN THE REQUEST IS TO BE ANALYZED FOR ACCEPTABLITY

	PUSHJ	P,CHKUSM	;SEE IF IN USE
	  JRST	DOONE		;YES--TRY ANOTHER
	GET	AFTR		;GET AFTER PARAMETER
	CAMLE	T1,NOW(S)	;SEE IF UP THERE YET
	JRST	AFTCNT		;NO--TRY ANOTHER
	HLRZ	T1,QUENM(S)	;NAME OF QUEUE
	CAIN	T1,'IN '	;SKIP IF NOT INPUT
	JRST	DOINP		;NO REMOTE CHECKS FOR INPUT

	CAIN	T1,'JN '	;SKIP IF NOT JNH
	JRST	NOTINP		;DON'T BOTHER REMOTE

	HRRZ	T1,Q.DEV(A)	;GET REMOTE CODE
	CAME	T1,REMSTA(S)	;SEE IF FOR THIS STATION
	CAMN	T1,REMDEV(S)	;OR FOR THIS DEVICE
	JRST	NOTINP		;PROCEED IF YES,
	JRST	DOONE		;LOOP BACK IF NO
DOINP:	GET	IDEP		;YES--CHECK DEPENDENCY COUNT
	TRNE	T1,777777	;FOR NON-ZERO
	JRST	AFTCN1		;JUMP IF NON-ZERO
	SKIPE	Q.PDEV(A)	;SEE IF RESTARTING A REQUEST
	JUMPL	T1,DOONE	;YES--JUMP IF NOT RESTARTABLE
	JRST	NOTINP		;GO SCHEDULE

GOLIST:	TLNE	F,L.FLST	;SKIP IF NOT FAST LIST
	JRST	NOTINP		;DONT READ REQUEST FOR FAST LIST
	PUSHJ	P,REDREQ	;READ REQUEST
	  JRST	DOONE		;IF NOT THERE, IGNORE
	PUSHJ	P,TOPRMP	;MOVE REST OF MASTER QUEUE ENTRY
NOTINP:	PUSH	P,A		;LOOKS GOOD--SAVE AC1 BEFORE CALL
	PUSHJ	P,@SCHDLR(S)	;CALL SCHEDULER OR LISTER
	MOVE	T1,A		;SAVE PRIORITY COMPUTED
	POP	P,A		;RESTORE A
	CAMG	T1,BESTPR(S)	;SEE IF THIS IS BETTER THAN BEFORE
	JRST	DOONE		;NO--SKIP IT
	MOVEM	T1,BESTPR(S)	;YES--REMEMBER PRIORITY
	MOVE	T1,THISNM(S)	;REMEMBER NAME
	MOVEM	T1,BESTNM(S)	; ..
	JRST	DOONE		;LOOP FOR MORE

AFTCNT:	SUB	T1,NOW(S)	;GET WAIT TIME
	SKIPE	AFTNUM(S)	;SKIP IF FIRST /AFTER
	CAMGE	T1,MINAFT(S)	;SKIP IF BIGGER THAN MIN
	MOVEM	T1,MINAFT(S)	;STORE NEW MIN
AFTCN1:	AOS	AFTNUM(S)	;COUNT THE AFTER JOB
	JRST	DOONE		;LOOP FOR MORE
;PIKREQ -- PICK UP PREVIOUSLY KNOWN REQUEST
;CALL:	PUSHJ	P,PIKREQ
;RETURNS WITH REQUEST IN WINDOW
;USES T1, T2, T3, T4

PIKRQR:	PUSHJ	P,SLEEPR	;LOOP BACK SLEEPING
	IFN	DEBUG,<	TLNE	F,L.MAST  ;SEE IF INTERLOCKED
			JRST	E.MASL	;YES--BOMB>

PIKREQ:	MOVE	T1,PRODV(S)	;LOOK AT CALLER'S DEVICE
	JUMPE	T1,W.WQR	;ERROR IF NONE
	GET	MEM		;RESTORE MEMORY OF WINDOW
	PUSHJ	P,GETIT		;REPOSITION MASTER QUEUE
	  JRST	PIKRQR		;LOOP IF FAILED
	MOVE	T1,M.EPDV(J)	;PICK UP QUEUE'S PROCESSOR
	TLNE	T1,(77B5)	;SKIP IF INTERLOCK BY JOB
	JRST	PIKRQ1		;NO, CHECK DEVICE
	HLRZS	T1		;JOB NUMBER
	CAMN	T1,THSJOB(S)	;SKIP IF NOT THIS JOB
	JRST	CPOPJ1		;OK
	JRST	W.WQR		;SOMETHING WRONG
PIKRQ1:	CAMN	T1,PRODV(S)	;COMPARE WITH US
	JRST	CPOPJ1		;OK TO PROCEED
	JRST	W.WQR		;ERROR IF NOT US




;GETIT -- READ REMEMBERED WINDOW OF MASTER QUEUE
;CALL:	MOVE	T1,XWD WINDOW BLOCK,INDEX
;	PUSHJ	P,GETIT
;RETURN CPOPJ IF END OF FILE OR ENTER FAILED
;SKIP RETURN IF READ IN WITH J POINTING TO ENTRY
;USES T2, T3, T4

GETIT:	PUSH	P,T1		;SAVE ARGUMENT
	PUSHJ	P,UPMASI	;INTERLOCK MASTER QUEUE
	  JRST	TPOPJ		;FAIL IF BUSY
	HLRZ	T1,(P)		;GET BLOCK
	SUBI	T1,LN.MAS/200	;BACK UP SOMEWHAT
	MOVEM	T1,MASSTI(S)	;SET FOR READ
	SETOM	MASIOW(S)	;FLAG TO NOT RESTART
	PUSHJ	P,RDMAST	;READ WINDOW
	  JRST	GETRET		;EOF RETURN
	POP	P,T1		;RESTORE ARGUMENT
	MOVEI	J,MASBLK(S)	;COMPUTE START OF BLOCK
	ADDI	J,(T1)		;POSITION TO REMEMBERED ENTRY
	JRST	CPOPJ1		;SUCCESS RETURN

GETRET:	PUSHJ	P,RTMAST	;RETURN MASTER QUEUE INTERLOCK
TPOPJ:	POP	P,T1		;RESTORE T1
	POPJ	P,		;RETURN
;UPMASQ -- UPDATE MASTER QUEUE IF WE CAN
;TASKS ARE (1) ADD NEW REQUESTS, (2) MODIFY OLD REQUESTS, (3) RELEASE
;	DEAD INTERLOCKS
;CALL:	PUSHJ	P,UPMASQ
;USES T1, T2, T3, T4

UPMASQ:	PUSHJ	P,UPMASI	;INTERLOCK MASTER QUEUE
	  POPJ	P,		;RETURN IF CANNOT DO IT
	PUSHJ	P,CLSRET	;CLOSE MASTER QUEUE
	SETZM	UIOWD(S)	;CLEAR UFD POINTER FOR WILD SEARCH

UPMASL:	PUSHJ	P,SUFD		;FIND NEXT .QUE FILE
	  JRST	UPMASX		;NO MORE--RETURN MASTER QUEUE
	MOVEM	T1,THISNM(S)	;SAVE FILE NAME
	PUSHJ	P,LOOK		;LOOKUP FILE NAME
	  JRST	UPMASL		;LOOP IF CAN NOT ACCESS IT
	HRLZI	I,-QUEBLL	;PREPARE TO READ FIRST LITTLE BIT
	HRRI	I,QUEBLK-1(S)	;  INTO SPECIAL AREA
	MOVEI	J,0		;LEAVE I AS POINTER FOR BELOW
	IN	IO,I		;READ IT
	  JRST	UPMASK		;PROCEED IF OK
	IOERR	<While updating--request read>
UPMASK:	MOVE	T1,Q.OPR(I)	;SEE WHAT OPERATION
	ANDI	T1,77		; ..
	CAIE	T1,QO.CRE	;IS IT NEW REQUEST?
	JRST	UPMASL		;NO--LOOP BACK
	MOVE	T1,Q.PDEV(I)	;SEE IF INTERLOCKED
	MOVEI	T2,0
	PUSHJ	P,CHKUS		;(USED BY KJOB)
	  JRST	UPMASL		;YES--IGNORE IT
	LDB	T1,[POINT 9,Q.LEN(I),8] ;NUMBER OF WORD IN HDR
	CAIG	T1,Q.USER	;MUST GO TO USER NAME
	JRST	FNYFIL		;IT DOES NOT
	LDB	T1,[POINT 9,Q.LEN(I),17] ;LENGTH OF EACH FILE
	CAIGE	T1,Q.FMOD	;MUST GO TO Q.FMOD WORD
	JRST	FNYFIL		;THEY DON'T
	HRRZ	T1,Q.LEN(I)	;GET NUMBER OF FILES
	JUMPE	T1,FNYFIL	;FUNNY FILE
	SKIPN	Q.DEV(I)	;SKIP IF THIS GOES TO A DEVICE
	JRST	FNYFIL		;IT GOES NOPLACE
;HERE WHEN A NEW REQUEST HAS BEEN FOUND--FIND HOLE IN MASTER QUEUE
;AND FILL IT WITH THIS REQUEST

UPMASF:	PUSHJ	P,GTMAST	;GET NEXT ENTRY IN MASTER QUEUE
	  JFCL			;IGNORE EOF
	PUSHJ	P,SEEUSE	;TEST ENTRY FOR INTERLOCK DEAD
	SKIPE	M.ENAM(J)	;SEE IF IN USE
	JRST	UPMASF		;YES--LOOP BACK FOR NEXT
	IFL	SEQUNC,<
	SKIPE	Q.SEQ(I)	;SEE IF SEQUENCE SPECIFIED
	JRST	UPMSNS		;YES--PROCEED BELOW>
	IFN	SEQUNC,<
	AOS	T1,MASSEQ(S)	;GET NEXT SEQUENCE NUMBER
	MOVEM	T1,Q.SEQ(I)	;STORE IN REQUEST
UPMSNS:>
	MOVE	T1,NOW(S)	;AND SET
	MOVEM	T1,Q.CREA(I)	;CREATION TIME
	PUSHJ	P,TOMAS		;TRANSFER REQUEST TO MASTER QUEUE
;HERE TO RENAME FILE TO XXNNNN.QUF TO GET IT OUT OF THE
;WAY OF FUTURE UPDATING OPERATIONS

	MOVE	T1,THISNM(S)	;PICKUP FILE NAME
	TLO	F,L.FLOK	;FLAG FOR SHORT LOOKUP
	MOVSI	T2,'QUE'	;REMEMBER EXTENSION
	PUSHJ	P,LOOK		;LOOKUP FILE AGAIN
	  JRST	UPMFAL		;GIVE UP IF NOT STILL THERE
	MSTIME	T1,		;GET THE MILLISECOND CLOCK
	IDIVI	T1,^D100	;CONVERT TO TENTHS
UPMRNL:	MOVE	T2,[POINT 6,RB.NAM(S),11]  ;SET BYTE POINTER
	AOS	T3,T1		;ADVANCE, GET NEXT GUESS
UPMRN1:	IDIVI	T3,^D10		;GET NEXT DIGIT
	ADDI	T4,'0'		;CONVERT TO SIXBIT
	IDPB	T4,T2		;PLACE IN BLOCK
	TLNE	T3,(77B5)	;SEE IF DONE YET
	JRST	UPMRN1		;NO--LOOP FOR NEXT DIGIT
	MOVSI	T2,'QUF'	;CHANGE EXTENSION
;[67]UPMRN1+6
	HLLM	T2,RB.EXT(S)	;[67]IN BLOCK
	MOVE	T2,QUEDIR(S)	;GET DIRECTORY
	MOVEM	T2,RB.PPX(S)	;TO BE CLEAN IN LEVEL C
	IFN	DEBUG,<	SKIPN	RB.NAM(S)  ;SEE IF DELETE!!
			JRST	E.UPRN	;YES--BOMB>
	RENAME	IO,RB.NAM(S)	;TRY THE RENAME
	  SKIPA	T2,RB.EXT(S)	;FAILED--FIND OUT WHY

	JRST	UPMRNG		;WORKED--FINISH UP WORK
	TRNE	T2,777773	;ERROR CODE 4 (NAME EXISTS)
	  JRST	UPMRRF		;NO, NEED MORE CHECKS
	TRNN	T1,77		;OK--ALLOW 64*SAFETY FACTOR
	PUSHJ	P,LOOPR		;GUARD AGAINST INF.LOOP
	JRST	UPMRNL		;LOOP BACK FOR ANOTHER TRY

UPMRNG:	MOVE	T1,RB.NAM(S)	;GET NAME
	TLZ	T1,777700	;CLEAR JUNK
	IORM	T1,M.ENAM(J)	;ADD TO MASTER QUEUE
	JRST	UPMASL		;LOOP BACK FOR NEXT REQUEST

UPMRRF:	HRRZS	T2		;ISOLATE ERROR CODE
	CAIE	T2,3		;FILE BEING MODIFIED
	  JRST	E.MRF		;NO, DIE
	JRST	UPMF.1		;SKIP THIS ENTRY THIS TIME AROUND

;HERE IF LOOKUP FAILS SECOND TIME

UPMFAL:	LWARN	<updating queue>
UPMF.1:	PUSHJ	P,CLRMAS	;CLEAR MASTER QUEUE WE JUST BUILT
	MOVN	T1,[M.ELEN,,M.ELEN]
	ADDM	T1,MASIOW(S)	;BACK UP QUEUE SO WE WILL FIND THIS AGAIN
	JRST	UPMASL		;AND GO BACK AROUND LOOP


;HERE AT END TO FINISH SCANNING MASTER QUEUE FOR DEAD BODIES

UPMASX:	PUSHJ	P,GTMAST	;GET NEXT ENTRY
	  PJRST	RTMAST		;DONE--RETURN INTERLOCK AND RETURN
	PUSHJ	P,SEEUSE	;SEE IF IN USE BY DEAD USER
	JRST	UPMASX		;AND LOOP BACK FOR MORE

;HERE IF STRANGE REQUEST WAS FOUND

FNYFIL:	WARN	<Bad queue request found>
	SETZB	T1,T2		;PREPARE TO DELETE
	RENAME	IO,T1		;DELETE
	  JFCL			;WE TRIED
	JRST	UPMASL		;LOOK AT NEXT .QUE FILE
;RTMAST -- RETURN MASTER QUEUE INTERLOCK
;REWRITE CURRENT WINDOW IF CHANGED AND READ--WRITE FIRST WINDOW
;CALL:	PUSHJ	P,RTMAST
;RETURNS
;USES T1, T2, T3, T4, IO

RTMAST:	IFN	DEBUG,<	TLNN	F,L.MAST  ;SEE IF INTERLOCKED
			JRST	E.MASR	;NO--BOMB>
	SETZM	M.HOLD(S)	;CLEAR INTERLOCK IN CASE THIS IS FIRST WINDOW
	MOVE	T1,MASSEQ(S)	;GET SEQUENCE NUMBER
	MOVEM	T1,M.SEQ(S)	;RETURN TO MASTER QUEUE
	TLZN	F,L.CHNG	;SEE IF THIS WINDOW CHANGED
	JRST	RTMASY		;NO--JUST UPDATE HEADER
	PUSHJ	P,WRMAST	;YES--UPDATE THIS WINDOW
	MOVE	T1,MASSTI(S)	;GET BLOCK POINTER
	CAIN	T1,1		;SEE IF AT BEGINNING
	PJRST	CLSRET		;YES--ALL DONE

RTMASY:	SETZM	MASIOW(S)	;RESET TO START
	TLO	F,L.FMRD	;FLAG FOR ONE BLOCK READ
	MOVE	T1,MASSTI(S)	;PICK UP CURRENT POSITION
	CAIE	T1,1		;IF AT START, SAVE THE READ
	PUSHJ	P,RDMAST	;READ HEADER
	  JFCL			;IGNORE EOF
	SETZM	M.HOLD(S)	;CLEAR INTERLOCK
	MOVE	T1,MASSEQ(S)	;GET SEQUENCE NUMBER
	MOVEM	T1,M.SEQ(S)	;RETURN TO MASTER QUEUE
RTMASZ:	PUSHJ	P,GTMSNM	;RESET ENTER BLOCK
	ENTER	IO,T1		;UPDATE FILE
	  JRST	.+2		;IF CANNOT ENTER--LOOP
	PJRST	WRMSHD		;WRITE OUT HEADER AND RETURN
	MOVEI	T1,-3(T2)	;GET ERROR CODE
	JUMPN	T1,E.RMI	;ERROR IF WORSE THAN CONFLICT
	PUSHJ	P,SLEEPR	;FILE BUSY--TRY LATER
	JRST	RTMASZ		;LOOP BACK
;UPMASI -- INTERLOCK MASTER QUEUE
;INTERLOCK BY JOB BECAUSE MAY REQUIRE INTERLOCK WHEN NO DEVICE SPECIFIED
;(E.G. FOR MODIFY)
;CALL:	PUSHJ	P,UPMASI
;RETURN CPOPJ IF FAILED TO INTERLOCK
;SKIP RETURN IF INTERLOCKED
;WILL CREATE MASTER QUEUE IF NEEDED
;USES T1, T2, T3, T4, IO

UPMASI:	IFN	DEBUG,<	TLNE	F,L.MAST  ;SEE IF INTERLOCKED
			JRST	E.MASI	;YES--BOMB>
	SETZM	MASIOW(S)	;YES--CLEAR FLAG SO READ STARTS AT BEGINNING
	PUSHJ	P,JLOKMA	;LOOKUP MASTER, PREPARE FOR INTERLOCK
	  JUMPGE	T2,.+2		;SKIP IF LOOKUP ERROR, NOT IF EOF
	JRST	UPMSI1		;OK SO FAR
	TRNE	T2,-1		;SKIP IF NO MASTER QUEUE EXISTS
	PJRST	W.MLF		;SOMETHING IS WRONG WITH THE MASTER QUEUE
	TLOA	F,L.NEWQ	;FLAG THAT WE ARE CREATING
UPMSI1:	TLZ	F,L.NEWQ	;CLEAR POSSIBLE FLAG
	PUSHJ	P,GTMSNM	;SET ENTER BLOCK FOR INTERLOCK
	ENTER	IO,T1		;CREATE OR UPDATE FILE
	  JRST	UPMASR		;MAY NOT HAVE PRIVILEGES, MAY BE BUSY
	TLNN	F,L.LEVD	;SEE IF LEVEL C
	TLNN	F,L.NEWQ	;SEE IF LEVEL C CREATING
	JRST	UPMASJ		;NO--PROCEED BELOW
	PUSHJ	P,UPMSQC	;FINISH LEVEL C CREATE
	PUSHJ	P,LOOPR		;PROTECT AGAINST INF LOOP
	JRST	UPMASI		;LOOP BACK TO TRY AGAIN

UPMASJ:	MOVEI	T3,1		;RESET TO BLOCK 1
	TLZN	F,L.NEWQ	;JUST CREATED THE MASTER
	PUSHJ	P,NOWRED	;NO, READ FIRST BLOCK NOW
	  JFCL			;USES CPOPJ1 RETURN
	HLRZ	T1,M.HOLD(S)	;GET JOB THAT PRESUMABLY OWNS MASTER QUEUE
	CAMN	T1,THSJOB(S)	;COMPARE WITH OUR JOB TO SEE IF AFTER CRASH
	JRST	UPMASH		;YES, WE CAN HAVE IT
	MOVE	T1,M.HOLD(S)	;SEE IF INTERLOCKED
	MOVE	T2,M.HOLD+1(S)
	PUSHJ	P,CHKUS		;CHECK INTERLOCK IN USE
	  JRST	UPMAR1		;YES--TRY AGAIN LATER

;HERE WHEN WE ARE ALLOWED TO INTERLOCK MASTER QUEUE

UPMASH:	PUSHJ	P,JBLOCK	;SET UP INTERLOCK BY JOB
	MOVEM	T1,M.HOLD(S)	;STORE XWD JOB, PPN FOLDED
	MOVEM	T2,M.HOLD+1(S)	;AND RUN TIME OF JOB
	MOVE	T1,M.SEQ(S)	;GET SEQUENCE
	MOVEM	T1,MASSEQ(S)	;SAVE FOR EASY ACCESS
	AOS	(P)		;ADVANCE RETURN
	IFN	DEBUG,<	TLO	F,L.MAST  ;TURN ON INTERLOCK>
				;FALL INTO WRITE MASTER HEADER AND RETURN
;WRMSHD -- WRITE HEADER (BLOCK 1) OF MASTER QUEUE
;CALL:	PUSHJ	P,WRMSHD
;USES T1, T2

WRMSHD:	USETO	IO,1		;POSITION FILE
	IFN	DEBUG,<	MOVEI	T1,1	;NOTE THE REPOSITIONING
			MOVEM	T1,MASSTI(S)  ;FOR LATER>
	HRLZI	T1,-200		;SET IOWD
	PJRST	WRMASE		;AND CONTINUE IN WRMAST ROUTINE

;HERE WHEN CANT GET INTERLOCK--WAIT AND TRY AGAIN IF BUSY

UPMASR:	HRRZS	T2		;T2=ERROR CODE
	CAIE	T2,3		;SKIP IF MASTER QUEUE BUSY
	PJRST	CLSRET		;NO, MUST NOT HAVE PRIVILEGES
UPMAR1:	CLOSE	IO,34		;RESET LOOKUP OR ENTER
	MOVE	T2,LOPCNT(S)	;GET LOOP COUNT
	SOJLE	T2,CPOPJ	;TYPE GOOD MESSAGE INSTEAD OF BOUNCING THIS
	PUSHJ	P,SLEEPR	;BUSY--WAIT A WHILE, BUT NOT TOO MANY TIMES
	JRST	UPMASI		;AND TRY AGAIN

;UPMSQC -- FINISH LEVEL C CREATE WITH OUTPUTS AND RENAME FOR PROTECTION
;CALL:	PUSHJ	P,UPMSQC


UPMSQC:	MOVEI	T1,1		;SET TO START
	MOVEM	T1,MASSTI(S)	; AT BEGINNING OF FILE
	PUSHJ	P,WRMASO	;OUTPUT FILE OF ZEROS
	PUSHJ	P,GTMSNM	;YES--SETUP ENTER BLOCK
	RENAME	IO,T1		;SET IN PROTECTION CODE
	  JFCL			;IGNORE ERROR (DEFAULT IS OK)
	POPJ	P,

;JBLOCK -- SET UP INTERLOCK BY JOB
;CALL:	PUSHJ	P,JBLOCK
;RETURN	T1, T2=TWO WORD INTERLOCK BY JOB
;USES T1, T2, T3, T4

JBLOCK:	HRLZ	T1,THSJOB(S)	;JOB NUMBER IN LEFT HALF
	MOVE	T2,T1
	MOVE	T3,T1
	HRRI	T2,G.TTIM
	GETTAB	T2,		;GET RUN TIME IN T2
	  SETZ	T2,
	SETZ	T4,		;NO CUSP NAME
	PUSHJ	P,CPRGPP	;COMPUTE PPN FOLDED
	HRR	T1,T4		;COMPLETE FIRST WORD
	POPJ	P,		;AND EXIT
;REDREQ -- READ REQUEST INTO PARAMETER AREA
;SETS UP POINTER TO REST OF REQUEST IF OVERFLOW
;CALL:	PUSHJ	P,REDREQ
;RETURNS CPOPJ IF FAILED
;SKIP RETURN IF OK
;USES T1, T2, T3, T4, IO

REDREQ:	PUSHJ	P,LOOKR		;LOOKUP FILE
	  POPJ	P,		;GIVE FAILURE RETURN
	IN	IO,T3		;READ IT
	  JRST	REDROK		;PROCEED IF NO ERRORS
	STATO	IO,74B23	;SEE IF AN ERROR
	  JRST	REDROK		;NO--MUST JUST HAVE BEEN EOF
	IOERR	<Request read>

REDROK:	MOVE	T1,M.EPDV(J)	;UPDATE PROCESSING DEVICE
	MOVEM	T1,Q.PDEV(A)	;  BECAUSE SCHED DOESN'T
	LDB	T1,[POINT 9,Q.LEN(A),8]  ;GET FIXED HEADER LENGTH
	LDB	T2,[POINT 9,Q.LEN(A),17]  ;GET FILE LENGTH
	HRRZ	T3,AL		;GET SIZE OF PARAMETER AREA
	SUB	T3,T1		;GET SIZE OF SPACE FOR FILES
	IDIV	T3,T2		;DIVIDE BY SIZE OF ONE FILE
	HRRZ	T4,Q.LEN(A)	;GET NUMBER OF FILES IN REQUEST
	CAML	T3,T4		;SEE IF WE READ THEM ALL
	JRST	CPOPJ1		;SUCCESSFUL RETURN

	SOJL	T3,E.NRP	;NO--SEE IF ROOM FOR POINTER (BOMB IF NOT)
	IMUL	T3,T2		;GET SIZE OF FILES WHICH FIT
	ADD	T1,T3		;GET SIZE OF REQUEST WHICH FIT
	ADDI	T1,1(A)		;ADD PARAMETER AREA OFFSET
;HERE WITH T1 POINTING TO OVERFLOW POINTER

	SKIPN	T3,RB.STR(S)	;SEE IF LOOKUP TOLD WHICH STR
	MOVE	T3,OPNBLK+1(S)	;NO--GIVE NAME WE USED ON LOOKUP
	MOVEM	T3,Q.FSTR(T1)	;STORE IN AREA
	MOVE	T3,QUEDIR(S)	;GET DIRECTORY BEING USED
	MOVEM	T3,Q.FDIR(T1)	;STORE AWAY FOR CALLER
	SETZM	Q.FDIR+1(T1)	;CLEAR REST OF AREA
	HRLZI	T3,Q.FDIR+1(T1)	; ..
	HRRI	T3,Q.FDIR+2(T1)	; ..
	BLT	T3,Q.FLEN-1(T1)	; ..
	MOVE	T3,M.ENAM(J)	;GET FILE NAME
	TLZ	T3,777700	;CLEAR JUNK
	IOR	T3,QUENM(S)	;ADD PREFIX
	MOVEM	T3,Q.FNAM(T1)	;STORE AWAY
	MOVSI	T3,'QUF'	;GET EXTENSION
	MOVEM	T3,Q.FEXT(T1)	;STORE
	MOVE	T3,T1		;GET OFFSET
	SUBI	T3,1(A)		;GET SIZE ACTUALLY READ
	IDIVI	T3,200		;CONVERT TO BLOCKS/WORDS
	HRLI	T4,1(T3)	;COMBINE
	MOVEM	T4,Q.FBIT(T1)	;STORE FOR USER
	MOVSI	T3,(1B0)	;SET FLAG
	MOVEM	T3,Q.FMOD(T1)	;FOR USER
	JRST	CPOPJ1		;SUCCESSFUL RETURN
;TOPRM -- MOVE MASTER QUEUE ENTRY TO PARAMETER AREA
;TOPRMP -- PARTIAL MOVE FOR SCHEDULING, ETC.
;CALL:	MOVEI	J,LOCATION IN MASTER QUEUE
;	PUSHJ	P,TOPRM
;RETURN T1 .EQ. 0 IF ENTRY EMPTY
;RETURN T1.NE.0 IF COPIED OK
;USES T1, T2

TOPRM:	PUSHJ	P,CLRPRM	;CLEAR AREA
	SKIPN	T1,M.ENAM(J)	;GET NAME--SEE IF IN USE
	POPJ	P,		;NO--RETURN
	LSH	T1,-^D24	;YES--POSITION REMOTE CODE
	IOR	T1,QUENM(S)	;GET QUEUE NAME
	PUT	DEV		;STORE FOR CALLER
	MOVEI	T1,QO.CRE	;DUMMY ENTRY TYPE
	PUT	OPR		;FOR USER
	MOVSI	T1,(BYTE (9)QUEBLL,0)  ;FUDGE LENGTHS
	PUT	LEN		;FOR USER

TOPRMP:	MOVE	T1,M.EPPN(J)	;GET USER'S NUMBER
	PUT	PPN		;STORE
	MOVE	T1,M.ESEQ(J)	;GET SEQUENCE
	PUT	SEQ		; ..
	MOVE	T1,M.EPRI(J)	;GET PRIORITY WORD
	PUT	PRI		; ..
	MOVE	T1,M.EPDV(J)	;GET PROCESSING DEVICE
	PUT	PDEV		; ..
	MOVE	T1,M.EJOB(J)	;GET JOB NAME
	PUT	JOB
	HRLZI	T1,M.ECRE(J)	;MOVE TIMES
	HRRI	T1,Q.CREA(A)	; ..
	BLT	T1,Q.DEAD(A)	; ..
	HRLZI	T1,M.EXXX(J)	;MOVE EXTRA AREA
	HRRI	T1,Q.I(A)	; ..
	BLT	T1,Q.I+3(A)	; ..
	POPJ	P,		;RETURN



;CLRPRM -- CLEAR THE PARAMETER AREA
;CALL:	PUSHJ	P,CLRPRM
;USES T1,T2

CLRPRM:	SETZM	(A)		;CLEAR FIRST WORD
	HRLZI	T1,(A)		;BUILD BLT POINTER
	HRRI	T1,1(A)		; ..
	HRRZ	T2,A		;COMPUTE ENDING ADDRESS
	ADD	T2,AL		; ..
	BLT	T1,-1(T2)	;CLEAR AREA
	POPJ	P,		;RETURN
;CLRMAS -- CLEAR THE MASTER QUEUE AREA
;CALL:	PUSHJ	P,CLRMAS
;USES T1

CLRMAS:	SETZM	(J)		;CLEAR AREA
	HRLZI	T1,(J)		; ..
	HRRI	T1,1(J)		; ..
	BLT	T1,M.ELEN-1(J)	; ..
	POPJ	P,		;RETURN



;TOMAS -- COPY ENTRY INTO MASTER QUEUE
;CALL:	MOVEI	I,SOURCE IN EXPANDED FORMAT
;	MOVEI	J,ENTRY IN MASTER QUEUE
;	PUSHJ	P,TOMAS
;USES T1, T2

TOMAS:	TLO	F,L.CHNG	;FLAG THAT WINDOW MODIFIED
	HRLZ	T1,Q.DEV(I)	;GET REMOTE CODE
	LSH	T1,6		;POSITION TO BITS 0-11
	MOVEM	T1,M.ENAM(J)	;STORE
	MOVE	T1,Q.PPN(I)	;GET USER'S PPN
	PUSHJ	P,VALPPN	;VALIDATE IT
	MOVEM	T1,M.EPPN(J)	;STORE IN QUEUE

	MOVE	T1,Q.SEQ(I)	;GET SEQUENCE
	MOVEM	T1,M.ESEQ(J)	; ..
	MOVE	T1,Q.PRI(I)	;GET FULL PRIORITY WORD
	MOVEM	T1,M.EPRI(J)	;PUT IN QUEUE
	TLNN	F,L.CHK		;DO NOT RELEASE IF CHKPNT
	SETZM	M.EPDV(J)	;CLEAR PROCESSING DEVICE
	MOVE	T1,Q.JOB(I)	;NAME OF REQUEST
	MOVEM	T1,M.EJOB(J)	;SAVE IN CASE MODIFY COMES BY
	HRLZI	T1,Q.CREA(I)	;MOVE TIMES OVER
	HRRI	T1,M.ECRE(J)	; ..
	BLT	T1,M.EDED(J)	; ..
	HRLZI	T1,Q.I(I)	;MOVE XXX AREA OVER
	HRRI	T1,M.EXXX(J)	; ..
	BLT	T1,M.EXXX+3(J)	; ..
	POPJ	P,		;RETURN
;LOOKR -- GET FILE NAME AND LOOKUP .QUF FILE
;CALL:	(MOVE	T1,REMEMBERED NAME IF LOOKR1)
;	PUSHJ	P,LOOKR/LOOKR1
;RETURN CPOPJ IF FAILED WITH ERROR IN T1 (ONLY 0, 2, OR 6)
;SKIP RETURNS IF SUCCESSFUL WITH T3=IOWD TO PARAMS, T4=0
;USES T1, T2, IO

LOOKR:	MOVE	T1,M.ENAM(J)	;GET NUMBER OF FILE
LOOKR1:	TLZ	T1,777700	;CLEAR JUNK
	IOR	T1,QUENM(S)	;INCLUDE PREFIX
	MOVSI	T2,'QUF'	;GET EXTENSION
				;FALL INTO LOOK

;LOOK -- LOOKUP QUEUE FILE AND PREPARE IOWD
;CALL:	SET L.FLOK TO 1 FOR SHORT LOOKUP
;	MOVE	T1,FILE NAME
;	MOVE	T2,EXTENSION
;	PUSHJ	P,LOOK
;RETURN CPOPJ IF FAILED WITH ERROR IN T1 (ONLY 0, 2, 6)
;SKIP RETURN IF SUCCESSFUL WITH T3=IOWD TO PARAMS, T4=0
;USES T1

LOOK:	MOVE	T3,QUEDIR(S)	;GET DIRECTORY
	MOVEM	T1,RB.NAM(S)	;STORE FILE NAME IN LOOKUP BLOCK
	MOVEM	T2,RB.EXT(S)	;  INTO LOOKUP BLOCK
	MOVEM	T3,RB.PPX(S)	;SET LEVEL C DIRECTORY
	MOVEM	T3,RB.PPN(S)	;SET DIRECTORY
	MOVEI	T1,LENRB-1	;SET LENGTH
	MOVEM	T1,RB.LEN(S)	;  INTO LOOKUP BLOCK
	SETZM	RB.AUT(S)	;CLEAR AUTHOR FOR LEVEL-C
	MOVEI	T1,RB.LEN(S)	;POINT TO EXTENDED BLOCK
	TLZN	F,L.FLOK	;SEE IF FORCED SHORT FORM
	TLNN	F,L.LEVD	;NO--SEE IF LEVEL-C
	MOVEI	T1,RB.NAM(S)	;YES--POINT TO SHORT FORM
	LOOKUP	IO,(T1)		;LOOKUP FILE
	  JRST	LOOKFL		;ABORT IF FAILURE
	LDB	T3,[POINT <USRSIZ+^D18>,A,35]	;COMPUTE [50]
	MOVN	T3,T3		;IOWD TO PARAMETER AREA
	HRRI	T3,-2(A)	; ..
	AOBJN	T3,.+1		; ..
	AOBJN	T3,.+1		; ..
	MOVEI	T4,0		;SET END OF DUMP LIST
	JRST	CPOPJ1		;SKIP RETURN


;HERE WHEN LOOKUP FAILS--SEE IF OK TO RETURN ERROR

LOOKFL:	HRRZ	T1,RB.EXT(S)	;PICK UP ERROR CODE
	JUMPE	T1,CPOPJ	;OK IF 0 (NOT FOUND)
	CAIE	T1,2		;OK IF 2 (PROTECTION)
	CAIN	T1,6		;OK IF 6 (I/O FAILURE)
	POPJ	P,		;RETURN
	JRST	E.RLF		;BOMB ALL OTHERS
;VALPPN -- VALIDATE USER'S PPN
;IF AUTHOR IS UNKNOWN OR [1,2], ACCEPT ENTRY, ELSE CHANGE TO AUTHOR
;CALL:	MOVE	T1,USER'S PPN
;	PUSHJ	P,VALPPN
;RETURN WITH T1 UPDATED
;USES T2

VALPPN:	JUMPE	T1,VALPPA	;IF USER DID NOT SAY, CHANGE TO AUTHOR
	SKIPE	T2,RB.AUT(S)	;SEE IF AUTHOR EXISTS
	CAMN	T2,FSFPPN(S)	;YES--SEE IF HE HAD FULL FILE ACCESS
	POPJ	P,		;YES--RETURN UNCHANGED
	TRNN	T2,777775	;HOW ABOUT PROGRAMMER 2
	  POPJ	P,		;IS OK AS IS
VALPPA:	MOVE	T1,RB.AUT(S)	;CHANGE TO AUTHOR
	POPJ	P,		;RETURN



;SUFD -- SEARCH UFD FOR THIS TYPE OF FILE
;CALL:	(UIOWD PRESET TO 0 INITIALLY)
;	PUSHJ	P,SUFD
;	  NO MORE FILES
;	NEXT FILE NAME IN T1 AND "QUE" IN T2 (UIOWD ADVANCED)
;USES T1, T2, T3, T4, IO

SUFD:
SUFDL:	MOVE	T2,UIOWD(S)	;GET/CHECK UFD POINTER
	JUMPL	T2,SUFDL1	;IF IN PROGRESS, PROCEED
	PUSHJ	P,RDUFD		;NO--READ NEXT BLOCK
	  POPJ	P,		;RETURN IF USED UP
SUFDL1:	AOBJN	T2,.+1		;ADVANCE TO NEXT FILE
	MOVE	T1,(T2)		;GET FILE NAME
	AOBJN	T2,.+1		;ADVANCE TO EXTENSION
	MOVEM	T2,UIOWD(S)	;SAVE UFD POINTER
	HLLZ	T2,(T2)		;GET FILE EXTENSION
	CAME	T2,[SIXBIT /QUE/]  ;SEE IF A SYSTEM QUEUE FILE
	JRST	SUFDL		;NO--LOOP
	XOR	T1,QUENM(S)	;YES--SEE IF OUR TYPE
	TLNE	T1,777700	;TEST FIRST TWO LETTERS OF NAME
	JRST	SUFDL		;NO--LOOP
	XOR	T1,QUENM(S)	;YES--RESTORE NAME

CPOPJ1:	AOS	(P)		;ADVANCE PC
CPOPJ:	POPJ	P,		;AND RETURN
;RDUFD -- READ UFD ONE BLOCK AT A TIME
;CALL:	MOVE	T2,0 ON FIRST CALL, NOT 0 ON SUBSEQUENT
;	PUSHJ	P,RDUFD
;RETURNS CPOPJ AT END OF FILE
;SKIP RETURNS IF BLOCK READ WITH T2=IOWD TO BLOCK
;USES T1, T2, T3, T4, IO

RDUFD:	SKIPN	T2		;SEE IF FIRST CALL
	SETZM	UUSETI(S)	;YES--CLEAR BLOCK COUNTER
	PUSHJ	P,GTQDNM	;GET QUEUE DIRECTORY NAME BLOCK
	LOOKUP	IO,T1		;LOOK UP UFD
	  JRST	E.ULF		;HOPELESS IF FAILS
	AOS	T1,UUSETI(S)	;ADVANCE BLOCK COUNTER
	USETI	IO,(T1)		;POSITION FILE
	HRLZI	T2,-200		;SET UP
	HRRI	T2,UFDBLK-1(S)	;  IO WORD
	MOVEI	T3,0		;AND END OF LIST
	IN	IO,T2		;READ BLOCK
	  JRST	RDUFDX		;IF NO ERROR, PROCEED
	STATZ	IO,74B23	;SEE IF JUST END OF FILE
	  JRST	RDUFDE		;NO--GO GIVE ERROR MESSAGE
RDUFDZ:	CLOSE	IO,34		;YES--CLOSE WITHOUT ACCESS UPDATE
	POPJ	P,		;AND GIVE ALL DONE RETURN

RDUFDE:	IOERR	<UFD read>
	STATZ	IO,1B22		;SEE IF EOF UP
	JRST	RDUFDZ		;YES--GO TO EOF RETURN

RDUFDX:	CLOSE	IO,34		;CLOSE WITHOUT ACCESS UPDATE
	JRST	CPOPJ1		;GIVE FOUND RETURN
;GTMAST -- ADVANCE TO NEXT ENTRY IN MASTER QUEUE
;CALL:	PUSHJ	P,GTMAST
;RETURN CPOPJ AT EOF
;SKIP RETURN BEFORE EOF
;RETURN WITH I/O DONE AND J POINTING TO NEXT AREA
;RETURN WITH T1 AS XWD BLOCK OF WINDOW,INDEX IN WINDOW
;USES: T2, T3, T4, IO

GTMAST:	SKIPGE	J,MASIOW(S)	;PICK UP POINTER TO NEXT ENTRY
	JRST	GTMASB		;STILL SOME, PROCEED
	PUSHJ	P,WRDMAS	;IF OUT OF WINDOW ADVANCE TO NEXT
	  SOS	(P)		;EOF--ENSURE NON-SKIP
	MOVE	J,MASIOW(S)	;GET NEW OR OLD POINTER
GTMASB:	MOVE	T1,[M.ELEN,,M.ELEN]  ;SET ADVANCEMENT SIZE
	ADDM	T1,MASIOW(S)	;ADVANCE POINTER
	MOVEI	T1,(J)		;DETERMINE WORD IN WINDOW
	SUBI	T1,MASBLK(S)	;  RELATIVE TO START OF WINDOW
	HRL	T1,MASSTI(S)	;GET WINDOW BLOCK NUMBER
	JRST	CPOPJ1		;RETURN


;WRDMAS -- ADVANCE WINDOW ON MASTER QUEUE, WRITING IF NEEDED
;CALL:	TLO	F,L.CHNG	IF WRITE DESIRED
;	PUSHJ	P,WRDMAS
;USES T1, T2, T3, T4, IO

WRDMAS:	TLZE	F,L.CHNG	;SEE IF WRITE NEEDED
	PUSHJ	P,WRMAST	;YES--WRITE IT OUT
	PJRST	RDMAST		;PROCEED TO READ NEXT WINDOW
;WRMAST -- WRITE CURRENT WINDOW TO MASTER QUEUE
;WRMASO -- DITTO EXCEPT FILE ALREADY ENTERRED
;CALL:	(TLO	F,L.NEWQ  TO SUPPRESS CLOSE AT END)
;	PUSHJ	P,WRMAST/WRMASO
;USES T1, T2, T3, T4, IO

WRMAST:	PUSHJ	P,GTMSNM	;SETUP LOOKUP BLOCK
	LOOKUP	IO,T1		;LOOKUP FILE
	  JRST	E.MLF		;ERROR IF NOT THERE
WRMASL:	PUSHJ	P,GTMSNM	;GET MASTER NAME BLOCK
	ENTER	IO,T1		;UPDATE FILE
	  JRST	.+2		;ERROR--SEE WHY
	JRST	WRMASO		;OK--PROCEED
	MOVEI	T2,-3(T2)	;GET ERROR CODE
	JUMPN	T2,E.MEF	;IF NOT CONFLICT ERROR--DIE
	PUSHJ	P,SLEEPR	;IF CONFLICT, WAIT A SEC
	JRST	WRMASL		;AND LOOP BACK

WRMASO:	MOVE	T1,MASSTI(S)	;GET BLOCK POINTER
	USETO	IO,(T1)		;POSITION FILE
	HRLZI	T1,-LN.MAS	;SET IOWD

;HERE ALSO FROM WRMSHD ROUTINE

WRMASE:	HRRI	T1,MASBLK-1(S)	;  TO CORE COPY OF WINDOW
	MOVEI	T2,0		;  ..
	IFN	DEBUG,<	TLNN	F,L.MAST  ;SEE IF INTERLOCKED
			JRST	E.MASW	;NO--BOMB>
	OUT	IO,T1		;WRITE WINDOW
	  JRST	WRMASC		;PROCEED IF OK
	IOERR	<Master queue write>
WRMASC:	TLZN	F,L.NEWQ	;SUPPRESS CLOSE IF NECESSARY
	CLOSE	IO,34		;SUPPRESS ACCESS UPDATE
	IFN	DEBUG,<	MOVE	T1,MASSTI(S)  ;SEE IF 
			CAIE	T1,1	;  FIRST BLOCK
			POPJ	P,	;NO--RETURN
			TLZ	F,L.MAST  ;CLEAR INTERLOCK
			SKIPE	M.HOLD(S)  ;SEE IF SET
			TLO	F,L.MAST  ;FLAG INTERLOCKED>
	POPJ	P,		;RETURN
;RDMAST -- READ FIRST OR NEXT WINDOW OF THE MASTER QUEUE
;CALL:	PRESET MASIOW TO 0 TO START AT BEGINNING
;	SET L.FMRD TO 1 FOR 1 BLOCK READ
;	PUSHJ	P,RDMAST
;RETURN CPOPJ IF END WITH BLOCK 0
;SKIP RETURN IF NOT END WITH WINDOW IN BLOCK AND CHANNEL LOOKUP

JLOKMA:	TLOA	F,L.UMSI	;UPMASI CALLING, JUST LOOKUP THE MASTER
RDMAST:	TLZ	F,L.UMSI	;CLEAR THE FLAG
	IFN	DEBUG,<	TLNE	F,L.CHNG	;FLAG AS UNCHANGED
			JRST	E.CLS		;BOMB IF WE LOST A CHANGE>
	SETZM	MASBLK(S)	;CLEAR WINDOW BLOCK
	HRLZI	T1,MASBLK(S)	; ..
	HRRI	T1,MASBLK+1(S)	; ..
	BLT	T1,MASBLK-1+LN.MAS(S)  ; ..
	MOVEI	T1,LN.MAS/200-1  ;GET READY TO SET TO START IF NEEDED
	SKIPN	MASIOW(S)	;SEE IF TIME TO RESTART
	MOVNM	T1,MASSTI(S)	;YES--PRESET BLOCK COUNTER
	MOVEI	T2,LN.MAS/200	;ADVANCE BLOCK
	ADDM	T2,MASSTI(S)	;  POINTER
	HRLZI	T2,-LN.MAS	;PREPARE IOWD
	TLZE	F,L.FMRD	;SEE IF SHORT READ
	HRLZI	T2,-200		;YES--JUST READ ONE BLOCK
	HRRI	T2,MASBLK-1(S)	;  ..
	ADD	T2,[M.WAST,,M.NTRY+1]  ;  TO START OF AREA
	MOVEM	T2,MASIOW(S)	;  ..
	PUSHJ	P,GTMSNM	;SETUP FOR LOOKUP
	LOOKUP	IO,T1		;LOOKUP FILE
	  JRST	[HRRZS T2	;NOT THERE, ISOLATE ERROR CODE
		POPJ P,]	;AND GIVE ERROR RETURN
	HLRE	T1,T4		;GET LENGTH OF FILE
	PUSHJ	P,GFILEN	;  INTO T1
	MOVNI	T2,1		;SET T2=-1 FOR EOF RETURN
	MOVE	T3,MASSTI(S)
	CAMLE	T3,T1		;SEE IF OFF THE END
	JRST	CLSRET		;YES--GIVE EOF RETURN
	TLNE	F,L.UMSI	;UPMASI CALLING
	  JRST	CPOPJ1		;YES, EXIT NOW
	CAIE	T3,1		;SAVE A UUO IF NOT NEEDED
NOWRED:	USETI	IO,(T3)		;TELL MONITOR
	MOVE	T2,MASIOW(S)
	SUB	T2,[M.WAST,,M.NTRY+1]
	MOVEI	T3,0		;  ..
	IN	IO,T2		;READ WINDOW INTO CORE
	  JRST	CPOPJ1		;GIVE OK RETURN IF NO ERROR
	STATZ	IO,74B23	;ERROR--SEE IF JUST EOF
	  JRST	RDMASE		;NO--GO DO ERROR PROCESS
	JRST	CPOPJ1		;GIVE OK RETURN
CLSRET:	CLOSE	IO,34		;YES--CLOSE NO ACCESS UPDATE
	POPJ	P,		;GIVE EOF RETURN
RDMASE:	IOERR	<Master queue read>
	JRST	CPOPJ1		;GIVE OK RETURN
;GTMSNM -- GET MASTER QUEUE NAME LOOKUP BLOCK
;CALL:	PUSHJ	P,GTMSNM
;RETURN WITH T1-T4 SETUP FOR LOOKUP OR ENTER

GTMSNM:	MOVE	T1,MASNAM(S)	;SET FILE NAME
	MOVSI	T2,'QUF'	;SET EXTENSION
	MOVSI	T3,(<REQPRT>B8)	;SET PROTECTION
	MOVE	T4,MASDIR(S)	;GET DIRECTORY
	POPJ	P,		;RETURN



;SEEUSE -- SEE IF MASTER QUEUE REQUEST IS IN USE OR IS
;HELD BY A DEAD USER.  IF THE LATER, CLEAR THE INTERLOCK
;CALL:	PUSHJ	P,SEEUSE
;USES T1, T2, T3, T4

SEEUSE:	SKIPE	T1,M.EPDV(J)	;SEE IF INTERLOCKED
	PUSHJ	P,CHKUSM	;SEE IF IN USE
	  POPJ	P,		;YES--JUST RETURN
	SETZM	M.EPDV(J)	;CLEAR THE INTERLOCK
	TLO	F,L.CHNG	;FLAG THAT REQUEST CHANGED
	HLRZ	T1,QUENM(S)	;GET QUEUE NAME
	CAIN	T1,'IN '	;SEE IF INPUT QUEUE
	SKIPL	M.IDEP(J)	;YES--SEE IF NON-RESTARTABLE
	POPJ	P,		;NO--OK TO RESTART
	MOVSI	T1,(1B3)	;NON-RESTARTABLE, SO SET FLAG
	MOVEM	T1,M.IDEP(J)	;IN QUEUE ENTRY FOR BATCH
	SETZM	M.EAFT(J)	;CAUSE IT TO RUN NEXT
	POPJ	P,		;AND RETURN
;CHKUSE -- CHECK IF ENTRY IS IN USE (ENTRY IN Q.PDEV)
;CHKUSM -- (DITTO) (ENTRY IN M.EPDV)
;CHKUS -- (DITTO) (ENTRY IN T1, T2)
;FORM ONE:	T1=DEVICE, T2=0 OR XWD JOB,PPN+CUSP FOLDED
;FORM TWO:	T1=XWD JOB,PPN FOLDED, T2=0 OR RUN TIME AT INTERLOCK
;CALL:	PUSHJ	P,CHKUSE
;	RETURN IF IN USE
;	SKIP RETURN IF NOT
;USES T1, T2, T3, T4

CHKUSE:	MOVE	T1,Q.PDEV(A)	;GET DEVICE LISTED IN QUEUE REQUEST
	MOVEI	T2,0
	JRST	CHKUS
CHKUSM:	MOVE	T1,M.EPDV(J)	;GET FROM MASTER QUEUE
	MOVE	T2,M.EPDV+1(J)
CHKUS:	JUMPE	T1,CPOPJ1	;IF NONE, THEN NOT IN USE

	CAMN	T1,PRODV(S)	;SEE IF SAME AS THIS GUY IN A 
				;  PREVIOUS INCARNATION
	JRST	CPOPJ1		;YES--REPORT AS NOT IN USE
	TLNN	T1,(77B5)	;SEE IF DEVICE
	JRST	CHKJOB		;NO--MUST BE JOB
	MOVE	T3,T1		;NO--SEE IF DEVICE IS IN USE
	DEVCHR	T1,1B19		;TRY NON-LOGICAL UUO
	CAMN	T3,T1		;SEE IF IT WORKED
	DEVCHR	T1,		;NO--TRY LOGICAL VARIETY
	JUMPE	T1,CPOPJ1	;NO SUCH DEVICE--ASSUME OK
	DEVTYP	T3,1B19		;DO A DEVTYP UUO TO SEE IF THIS IS
	  POPJ	P,		; A SPOOLED LPT. IF IT IS DO NOT
	TLNE	T3,(1B13)	; TEST DEVCHR BITS SINCE THEY WILL
	JRST	.+3		; REFLECT THE SPOOLED DEVICE.
	TRNN	T1,D.INIT	;SEE IF INITED
	JRST	CPOPJ1		;NO--MUST BE UNUSED
	JUMPE	T2,CPOPJ	;JUMP IF NO JOB SPECIFIED
	ANDI	T3,777000
	LSH	T3,^D9		;T3=JOB NUMBER IN LH
	XOR	T2,T3
	TLNE	T2,-1		;SKIP IF INITED BY THIS JOB
	JRST	CPOPJ1		;NO, REQUEST IS NOT IN USE
	PUSHJ	P,CPRGPN	;COMPUTE FOLDED SUM OF PROGRAM NAME AND PPN
	XOR	T2,T4		;COMPARE SPECIFIED AND COMPUTED FOLDED SUM
	TRNE	T2,-1		;SKIP IF MATCH
	JRST	CPOPJ1		;NO, SOME OTHER JOB
	POPJ	P,		;SIGH--IN USE
;HERE WHEN INTERLOCK IS JOB TYPE

CHKJOB:	HLRZ	T3,T1		;GET JOB NUMBER
	MOVN	T3,T3		;SETUP FOR JOBSTS
	JOBSTS	T3,		;SEE WHAT MONITOR THINKS
	  JRST	CHKJGT		;OLD MONITOR--GO USE GETTAB
	JUMPGE	T3,CPOPJ1	;RETURN IF JOB NOT IN USE
	JB.JNA==JB.JNA		;(IS BIT 0)
	JRST	CHKJPP		;YES--GO CHECK IF SAME

CHKJGT:	HLLZ	T3,T1		;GET JOB NUMBER
	G.JSTS==G.JSTS		;(IS 0)
	GETTAB	T3,		;GET MONITOR STATUS
	  JRST	CPOPJ1		;NOT IN USE IF NOT THERE
	TLNN	T3,(ST.JNA)	;SEE IF JOB IN USE
	JRST	CPOPJ1		;NO--THERE ENTRY IS NOT

CHKJPP:	HLLZ	T3,T1		;JOB NUMBER
	SETZ	T4,
	PUSHJ	P,CPRGPP	;COMPUTE FOLDED SUM OF PROGRAM NAME AND PPN
	XOR	T1,T4		;SEE IF IT MATCHES
	TRNE	T1,-1		;TEST FIELD
	JRST	CPOPJ1		;NOT SAME USER
	JUMPE	T2,CPOPJ	;JUMP IF NO RUN TIME SPECIFIED
	HRRI	T1,G.TTIM
	GETTAB	T1,		;GET RUN TIME
	  JRST	CPOPJ1		;CANT
	CAMGE	T1,T2		;SKIP IF CURRENT TIME GE TIME AT INTERLOCK
	JRST	CPOPJ1		;NO, MUST HAVE RESTARTED
	POPJ	P,		;STILL IN USE

;CPRGPN/CPRGPP -- COMPUTE FOLDED SUM OF PROGRAM NAME AND PPN
;ARGS	LH T3=JOB NUMBER
;	T4=PROGRAM NAME OR 0 IF ENTERED AT CPRGPP
;VALUES	T4=XWD 0, FOLDED SUM
;USES T3, T4

CPRGPN:	MOVE	T4,T3		;T4=JOB NUMBER IN LH
	HRRI	T4,G.JPRG
	GETTAB	T4,		;GET NAME OF PROGRAM RUNNING
	  SETZ	T4,		;CANT HELP IT
CPRGPP:	HRRI	T3,G.JPPN
	GETTAB	T3,		;GET PPN OF JOB
	  SETZ	T3,		;CANT
	ADD	T3,T4		;COMPUTE SUM
	HLRZ	T4,T3		;LH OF SUM
	ADDI	T4,(T3)		;ADDED TO RH OF SUM
	TLNE	T4,-1		;SKIP IF NO OVERFLOW
	MOVEI	T4,1(T4)	;YES--INCLUDE IT
	POPJ	P,
;MAKQUE -- VERIFY THAT SYSTEM QUEUE AREA IS GOOD, ATTEMPT TO FIX IF BAD
;CALL:	MOVE	T1,STRUCTURE
;	MOVE	T2,DIRECTORY (UFD)
;	PUSHJ	P,MAKQUE
;RETURNS AFTER ATTEMPTED FIXUP
;USES T3, T4

MAKQUE:	PUSH	P,T1		;SAVE STRUCTURE
	PUSH	P,T2		;SAVE DIRECTORY
	MOVEM	T2,QUEDIR(S)	;SAVE AWAY FOR NAME BLOCK MAKER
	MOVE	T2,T1		;SETUP FOR OPEN
	MOVE	T1,[400000,,17]  ;DUMP MODE--PHYSICAL DEVICE
	MOVEI	T3,0		;NO BUFFERS
	OPEN	IO,T1		;OPEN CHANNEL
	  JRST	MAKERR		;GIVE UP IF FAILED

MAKLOP:	PUSHJ	P,GTQDNM	;GET QUEUE DIRECTORY NAME BLOCK
	LOOKUP	IO,T1		;SEE IF OK
	  JRST	MAKUFD		;IF FAIL, GO MAKE IT
	TLNE	F,L.LEVD	;SEE WHICH FILE SYSTEM
	JRST	MAKLD		;LEVEL D--GO HANDLE

	TLNN	T3,(333B8)	;LEVEL C--SEE IF INFITELY WRITEABLE
	JRST	MAKRET		;YES--RETURN
	JRST	MAKRNM		;AND GO RENAME

MAKLD:	TLC	T3,(777B8)	;LEVEL D--SEE IF INFINITELY WRITEABLE
	TLCN	T3,(777B8)	; ..
	JRST	MAKRET		;YES--RETURN

MAKRNM:	PUSHJ	P,GTQDNM	;GET QUEUE DIRECTORY NAME BLOCK
	RENAME	IO,T1		;RENAME TO BE REASONABLE
	  JRST	MAKERR		;NICE TRY
	JRST	MAKRET		;AND RETURN TO CALLER
;HERE WHEN LOOKUP FAILS ON QUEUEING UFD

MAKUFD:	TRNE	T2,-1		;SEE WHAT TYPE OF FAILURE
	JRST	MAKERR		;GIVE UP IF NOT MISSING
	PUSHJ	P,GTQDNM	;GET QUEUE DIRECTORY NAME BLOCK
	TLNE	F,L.LEVD	;SEE WHAT FILE SYSTEM
	JRST	MAKLDU		;LEVEL D--PROCEED BELOW

	ENTER	IO,T1		;CREATE FILE
	  JRST	MAKERR		;GIVE UP IF LOST
	OUTPUT	IO,[IOWD 1,[0]
			0]	;SUPERSTITIOUS OUTPUT
	CLOSE	IO,		;CLOSE
	PUSHJ	P,GTQDNM	;GET QUEUE DIRECTORY NAME BLOCK
	RENAME	IO,T1		;CHANGE PROTECTION
	  JRST	MAKERR		;IGNORE ERROR
	JRST	MAKRET		;RETURN

MAKLDU:	SETZM	RB.LEN(S)	;CLEAR
	HRLZI	T2,RB.LEN(S)	;  ENTIRE
	HRRI	T2,RB.LEN+1(S)	;  LOOKUP
	BLT	T2,RB.LEN+LENRB-1(S)  ;  AREA
	MOVEI	T2,LENRB-1	;SET LENGTH
	MOVEM	T2,RB.LEN(S)	;  INTO AREA
	MOVEM	T4,RB.PPN(S)	;SET MFD
	MOVEM	T1,RB.NAM(S)	;SET FILE NAME
	MOVSI	T2,'UFD'	;RESTORE EXTENSION
	MOVEM	T2,RB.EXT(S)	;SET EXTENSION
	MOVEM	T3,RB.PRT(S)	;  INTO AREA
	MOVEI	T3,1		;ALLOCATE ONE BLOCK
	MOVEM	T3,RB.ALC(S)	;  INTO AREA
	MOVEI	T3,7B20		;SET STATUS OF UNKILLABLE, ETC.
	MOVEM	T3,RB.STS(S)	;  INTO AREA
	HRLOI	T3,377777	;SET INFINITE QUOTA
	MOVEM	T3,RB.QTF(S)	;  FOR LOGGED IN
	MOVEM	T3,RB.QTO(S)	;  AND LOGGED OUT
	ENTER	IO,RB.LEN(S)	;TRY TO MAKE IT HAPPEN
	  JRST	MAKERR		;NICE TRY
	USETO	IO,2		;THIS HELPS KEEP UFD CLEAN
	CLOSE	IO,4		;CLOSE KEEPING ALLOCATED AREA
	JRST	MAKRET		;RETURN
;HERE TO RESTORE T1, T2 AND RETURN TO CALLER

MAKERR:	WARN	<ERROR CREATING QUEUE DIRECTORY>
	JRST	MAKRTT		;AND GO RELEASE CHANNEL

MAKRET:	CLOSE	IO,34		;CLOSE WITHOU ACCESS UPDATE
	STATO	IO,74B23	;SEE IF ANY ERRORS
	JRST	MAKRTT		;NO--FINISH UP
	IOERR	<CREATING QUEUE DIRECTORY>
MAKRTT:	RELEASE	IO,		;RELEASE CHANNEL
	POP	P,T2		;RESTORE DIRECTORY
	POP	P,T1		;RESTORE STRUCTURE
	POPJ	P,		;RETURN



;GTQDNM -- SETUP QUEUE DIRECTORY NAME BLOCK
;CALL:	PUSHJ	P,GTQDNM
;RETURNS T1-4 SETUP FOR ENTER

GTQDNM:	MOVE	T1,QUEDIR(S)	;GET UFD NAME
	MOVSI	T2,'UFD'	;AND EXTENSION
	MOVSI	T3,(777B8)	;GET LEVEL D INF.WRITE PROT.
	TLNN	F,L.LEVD	;SEE IF LEVEL C
	MOVSI	T3,(444B8)	;YES--GET SAME
	MOVE	T4,MFDPPN(S)	;GET DIRECTORY
	POPJ	P,		;RETURN



;GFILEN -- COMPUTE FILE LENGTH
;CALL:	MOVE	T1,LOOKUP LENGTH
;RETURN T1 = LENGTH IN BLOCKS (ROUNDED UP)

GFILEN:	JUMPGE	T1,CPOPJ	;RETURN IF ALREADY IN BLOCKS
	MOVNS	T1		;ELSE MAK POSITIVE
	ADDI	T1,177		;ROUND UP
	LSH	T1,-7		;CONVERT TO BLOCKS
	POPJ	P,		;RETURN
;CLO.IO AND CLO.CC REOPEN CHAN IF LEVEL C
;CALL:	PUSHJ	P,CLO.XX
;	CLOSE	XX,
;	HERE IF LEVEL C
;
CLO.IO:	TLNE	F,L.LEVD	;LEVEL D?
	POPJ	P,		;YES--DONT NEED THIS
	OPEN	IO,OPNBLK(S)	;NO--NEED AN OPEN
	  JRST	[FAIL	<Level C OPEN failed on IO>
]
	JRST	CPOPJ1		;SKIP CLOSE

CLO.CC:	TLNE	F,L.LEVD	;LEVEL D?
	POPJ	P,		;YES--DON'T NEED THIS
	OPEN	CC,OPNBLK(S)	;NO--NEED AN OPEN
	  JRST	[FAIL	<Level C OPEN failed on CC>
]
	JRST	CPOPJ1		;SKIP CLOSE
;UPDTIM -- HANDLE TIMES IN + FORMAT
;CALL:	MOVE	T1,TIME
;	PUSHJ	P,UPDTIM
;RETURNS T1=STANDARD FORMAT TIME
;USES NO ACS

UPDTIM:	JUMPGE	T1,CPOPJ	;RETURN IF ALREADY OK
	TLZ	T1,(1B0)	;CLEAR + FLAG
	ADD	T1,NOW(S)	;ADD TO CURRENT TIME
	TLNE	T1,(1B0)	;SEE IF OVERFLOW
	HRLOI	T1,377777	;YES--SET TO MAX
	POPJ	P,		;RETURN


;ASKDAE -- PUT IN DAEMON REQUEST
;CALL:	T1=NUMBER OF AFTER REQUESTS
;RETURNS NUMBER OF AFTER REQUEST OR ZERO IF DAEMON WON
;USES T2,T3,T4,T5(IDIVI)

ASKDAE:	MOVE	T2,[G.MNVR]	;GET MONITOR VERSION NUMBER
	GETTAB	T2,		; ..
	  POPJ	P,		;OOPS
	MOVEI	T2,(T2)		;IGNORE CUSTOMER HALF
	CAIG	T2,50301	;NEWER THAN 5.03A?
	POPJ	P,		;NO--DO NOT TRY
	MOVEI	T2,T3		;POINT TO T3
	MOVEI	T3,2		;CLOCK FUNCTION
	MOVE	T4,MINAFT(S)	;GET AFTER LIMIT
	IDIVI	T4,3		;CONVERT TO SECONDS
	DAEMON	T2,		;CALL DAEMON
	  POPJ	P,		;WIN SOME --  LOOSE SOME
	SETZ	T1,		;CLEAR T1
	POPJ	P,		;RETURN
;GETNOW -- COMPUTE CURRENT TIME IN SPECIAL FORMAT
;CALL:	PUSHJ	P,GETNOW
;RETURNS WITH RESULT IN T1
;USES T1, T2, T3, T4, T5

				;GET SYSTEM DATE/TIME IN STANDARD FORMAT
	RADIX	10		;ASSEMBLE UNDER RADIX 10 !!!!!!!!!!
GETNOW:	DATE	T2,		;AND DO AS PER ROUTINE IN SCAN.MAC

	IDIVI	T2,12*31	;T2=YEARS-1964
	CAILE	T2,2217-1964	;SEE IF BEYOND 2117
	JRST	GETNW2		;YES-- RETURN -1

	IDIVI	T3,31		;T3=MONTHS-JAN, T4=DAYS-1

	ADD	T4,MONTAB(T3)	;T4=DAYS-(JAN 1)
	MOVEI	T5,0		;LEAP YEAR ADDITIVE IF JAN ,  FEB

	CAIL	T3,2		;CHECK MONTH
	MOVEI	T5,1		;ADDITIVE IF MARCH - DECEMBER
	MOVE	T1,T2		;SAVE YEARS FOR REUSE

	ADDI	T2,3
	IDIVI	T2,4		;HANDLE REGULAR LEAP YEARS
	CAIE	T3,3		;SEE IF THIS IS A LEAP YEAR
	MOVEI	T5,0		;NO, WIPE OUT ADDITIVE
	ADDI	T4,<1964-1859>*365+<1964-1859>/4+<31-18>+31(T2)
				;T4= DAYS BEFORE JAN 1 , 1964 + SINCE JAN 1 
				;PLUS ALLOWANCE FOR ALL LEAP YEARS SINCE '64

	MOVE	T2,T1		;RESTORE YEARS SINCE 1964
	IMULI	T2,365		;DAYS SINCE 1964

	ADD	T4,T2		;T4= DAYS EXCEPT FOR 100 YEAR FUDGE
	HRREI	T2,64-100-1(T1)	;T2=YEARS SINCE 2001

	JUMPLE	T2,GETNW1		;ALL DONE IF NOT SPACE ODYSSEY
				;"2001"

	IDIVI	T2,100		;GET CENTURIES SINCE 2001
	SUB	T4,T2		;ALLOW FOR LOST LEAP YEARS
	CAIE	T3,99		;SEE IF THIS IS A LOST LEAP YEAR
GETNW1:	ADD	T4,T5		;ALLOW FOR LEAP YEAR THIS YEAR
	CAILE	T4,^O377777	;SEE IF TOO BIG
GETNW2:	SETOI	T4,		;YES, SET TO -1

	MSTIME	T1,		;GET MILLISEC TIME
	MOVEI	T2,0		;CLEAR OTHER HALF
	ASHC	T1,-17		;POSITION
	DIV	T1,[24*60*60*1000]		;CONVERT TO 1/2**18 DAYS
	HRLI	T1,(T4)		;INCLUDE DATE
	POPJ	P,		;RETURN

MONTAB:	EXP	0,31,59,90,120,151,181,212,243,273,304,334
	RADIX	8
;REMOTE -- CONVERT SIXBIT DEVICE CODE TO REMOTE CODE
;CALL:	MOVE	T1,SIXBIT CODE
;	PUSHJ	P,REMOTE
;RETURNS T1 = REMOTE CODE
;USES T2, T3, T4

REMOTE:	TLNE	T1,(77B5)	;DO NOTHING IF IT'S DSK
	TRNN	T1,-1		;SEE IF ANY REMOTE SPEC.
	POPJ	P,		;NO--RETURN DIRECTLY
	LDB	T2,[POINT 6,T1,23]
	CAIE	T2,'S'		;SEE IF STATION
	JRST	REMDVN		;NO--MUST BE SPECIFIC UNIT
	LDB	T2,[POINT 3,T1,29]
	TRNE	T1,77		;SEE IF ONE DIGIT
	LSH	T2,3		;NO--POSITION FOR SECOND UNIT
	TRZ	T1,777770	;CLEAR JUNK
	ADD	T1,T2		;INCLUDE REST OF STATION
	POPJ	P,		;RETURN

;HERE IF SPECIFIC UNIT SPECIFIED

REMDVN:	MOVE	T2,[POINT 6,T1,17]
	MOVEI	T3,0		;CLEAR RESULT
REMDVL:	ILDB	T4,T2		;GET NEXT CHAR
	JUMPE	T4,REMDVX	;JUMP IF DONE
	LSH	T3,3		;POSITION RESULT
	ADDI	T3,-'0'(T4)	;INCLUDE DIGIT
	TLNE	T2,(77B5)	;SEE IF AT END
	JRST	REMDVL		;NO--LOOP BACK
REMDVX:	HRRI	T1,1000(T3)	;MOVE TO RESULT
	POPJ	P,		;RETURN
;GET -- GET ONE WORD FROM USER'S PARAMETER AREA
;CALL:	GET FOO
;	RETURN WITH Q.FOO IN T1 (0 IF OUT OF BOUNDS)
;USES T2

GET.:	MOVEI	T1,0		;CLEAR IN CASE OUT OF BOUNDS
	CAML	T2,AL		;TEST AGAINST LIMIT
	POPJ	P,		;FAIL--RETURN
	ADD	T2,A		;OK--SETUP ADDRESS
	MOVE	T1,(T2)		;GET FROM AREA
	POPJ	P,		;RETURN


;PUT -- PUT ONE WORD INTO USER'S PARAMETER AREA
;CALL:	MOVE	T1,VALUE
;	PUT FOO
;	RETURN WITH T1 INTACT
;USES T2

PUT.:	CAML	T2,AL		;TEST AGAINST LIMIT
	POPJ	P,		;FAIL--RETURN
	ADD	T2,A		;OK--SETUP ADDRESS
	MOVEM	T1,(T2)		;DO THE STORE
	POPJ	P,		;RETURN



;GCORE -- ALLOCATE MORE CORE (FROM MONITOR IF NEEDED)
;CALL:	SAVE .JBFF FOR LATER (START OF AREA)
;	GCORE	N     OR	MOVEI	T1,N
;				PUSHJ	P,GCORE.
;	RETURN WITH CORE EXPANDED
;USES T1

GCORE.:	ADDB	T1,.JBFF	;UPDATE .JBFF
	CAMG	T1,.JBREL	;SEE IF NEED MORE
	POPJ	P,		;NO--RETURN
	CORE	T1,		;GET FROM THE MONITOR
	  JRST	E.NEC		;ERROR
	POPJ	P,		;RETURN
;SLEEPR -- SLEEP 1 SEC AND TRY AGAIN UP TO SAFETY FACTOR TIMES
;LOOPR -- LOOP UP TO SAFETY FACTOR TIMES
;WHEN SAFETY FACTOR EXPIRES, GIVE UP BUT CONTINUE TRIES FACTOR TIMES
;AGAIN BEFORE STOPPING
;CALL:	PUSHJ	P,SLEEPR/LOOPR
;USES T2

SLEEPR:	MOVEI	T2,1		;SET SLEEP INTERVAL (SECS.)
	SLEEP	T2,		;SLEEP A WHILE
LOOPR:	SOSLE	LOPCNT(S)	;DECREMENT COUNT
	POPJ	P,		;STILL OK--RETURN

	MOVEI	M,[ASCIZ /
? Loop too long in queue manager--CONTINUE to try again
/]
	PUSHJ	P,STROUT	;TYPE STRING
	MONRET			;NON-DESTRUCTIVE RETURN TO MONITOR
	MOVEI	T2,LN.LOP	;RESET SAFETY FACTOR
	MOVEM	T2,LOPCNT(S)	;  FOR ANOTHER ROUND OF TRIES
	POPJ	P,		;AND RETURN
	SUBTTL	ERROR PROCESSING

;MANY RANDOM ERROR MESSAGES (BUT NOT ALL)

W.MMQI:	WARN	<Master queue interlocked>
W.MRBS:	MOVEI	M,[ASCIZ /
% Request interlocked /]
	JRST	W.MNS1
W.MNSE:	MOVEI	M,[ASCIZ /
% Cant find request /]
W.MNS1:	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,QUENM(S)	;PROCESSING DEVICE
	PUSHJ	P,TSIX
	MOVEI	M,":"
	PUSHJ	P,CHROUT
	MOVE	T1,Q.JOB(A)	;NAME OF ENTRY
	PUSHJ	P,TSIX
	MOVE	T1,Q.PPN(A)	;PPN
	PUSHJ	P,TPPN
	MOVEI	M,[ASCIZ / in queue manager
/]
	PJRST	STROUT		;TYPE STRING
E.PTS:	FAIL	<PDL too short>
E.NQS:	FAIL	<No queue specified>
E.UOF:	FAIL	<UFD open failure>
E.ULF:	FAIL	<UFD lookup failure>
E.NEC:	FAIL	<Not enough core>
E.PATS:	FAIL	<Parameter area too small>
E.RLF:	FAIL	<Request lookup failure>
W.REF:	WARN	<Request enter failure>
	POP	P,T3
	JRST	REQREL
W.WQR:	IFN DEBUG,<
	MOVEI	M,[ASCIZ .
% PRODV = .]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,PRODV(S)	;PROCESSING DEVICE
	PUSHJ	P,TOCT		;OUTPUT IT
	MOVEI	M,[ASCIZ /, M.EPDV = /]
	PUSHJ	P,STROUT	;OUTPUT THE STRING
	MOVE	T1,M.EPDV(J)	;INTERLOCK WORD
	PUSHJ	P,TOCT		;OUTPUT THAT
	MOVEI	M,[ASCIZ /, MEM = /]
	PUSHJ	P,STROUT	;TYPE STRING
	GET	MEM
	PUSHJ	P,TOCT
>	;END CONDITIONAL ON DEBUG
	WARN	<Wrong queue request>
	POPJ	P,
W.DF:	WARN	<Delete failure>
	JRST	REQREL
E.QEN:	FAIL	<Enter failure>
E.QLK:	FAIL	<Creation lookup failure>
W.MLF:	TLZ	F,L.NEWQ	;CLEAR CREATING MASTER QUEUE BIT
	MOVEI	M,[ASCIZ /
% /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVEI	T1,(T2)		;T1=ERROR CODE
	IDIVI	T1,10
	MOVEI	M,"0"(T1)	;M=HIGHER DIGIT IN ASCII
	CAIE	M,"0"		;DONT TYPE LEADING 0
	PUSHJ	P,CHROUT	;TYPE THE CHAR
	MOVEI	M,"0"(T2)	;M=LOWER DIGIT IN ASCII
	PUSHJ	P,CHROUT	;TYPE THE CHAR
	WARN	<Master queue lookup failure>
	POPJ	P,

E.MLF:	FAIL	<Master queue lookup failure>
E.MEF:	FAIL	<Master queue enter failure>
E.MRF:	FAIL	<Master queue rename failure>
E.RMI:	FAIL	<Enter failure when releasing master queue interlock>
E.NIU:	FAIL	<Processing device not INITed properly by caller--detected>
E.NDS:	FAIL	<No processing device specified by caller--detected>
E.NRP:	FAIL	<Expand parameter area--no room for pointer>
W.MPRV:	WARN	<Running under unprivileged PPN>
	MOVNI	T1,1		;PRESUME NO SUCH ENTRY
	TLO	F,L.KLMD	;AND FOUND SOME - THIS WILL END SEARCH
	POPJ	P,

	IFN	DEBUG,<E.PDL:	FAIL	<PDL phase error>
			E.MAST:	FAIL	<Master queue interlocked at end>
			E.MASR:	FAIL	<Master queue not interlocked at return>
			E.MASI:	FAIL	<Master queue interlocked at get>
			E.MASW:	FAIL	<Master queue not interlocked at write>
			E.MASL:	FAIL	<Master queue interlocked in loop>
			E.CLS:	FAIL	<Change lost>
			E.UPRN:	FAIL	<Updating rename is delete>>

;ERRORS IN CREATE OPERATION

E.LOHS:	FAIL	<Header is too short in queue request -- found>
E.LOES:	FAIL	<File specifications too short in queue request - found>
E.NOFS:	FAIL	<No files in request - found>
E.DEVS:	FAIL	<No device specified - found>

;FAIL -- COMMUNICATION OR SYSTEM FAILURE
;TYPE OUT MESSAGE PREFIXED BY ? AND SUFFIXED BY "IN QUEUE MANAGER"
;CALL:	FAIL	MESSAGE
;	DOES NOT RETURN
;DESTROYS AL

FAIL.:	MOVEI	M,[ASCIZ /
? /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVEI	M,(AL)		;OUTPUT MESSAGE
	PUSHJ	P,STROUT	;TYPE MESSAGE
FAIL1.:	MOVEI	M,[ASCIZ / in queue manager
/]
	PUSHJ	P,STROUT	;TYPE STRING
	HLRZ	AL,A		;RESTORE AC CLOBBERED BY CALL
FAIL1:	MONRET			;RETURN TO MONITOR
	MOVEI	M,[ASCIZ /? Can't CONTINUE--try REENTER
/]
	PUSHJ	P,STROUT	;TYPE STRING
	JRST	FAIL1		;IN CASE OF CONTINUE
;LWARN -- HANDLE LOOKUP WARNING FAILURES
;CALL:	MOVEI	T1,ERROR NUMBER
;	LWARN <MESSAGE>
;USES T1

LWARN.:	MOVEI	M,[ASCIZ /
% Lookup failure /]
	PUSHJ	P,STROUT	;TYPE STRING
LWRN1.:	PUSH	P,T2		;SAVE T2
	PUSHJ	P,TOCT		;PRINT T1 IN OCTAL
	POP	P,T2		;RESTORE T2

IFN DEBUG,<
	MOVEI	M,[ASCIZ / FILE /] ;IDENTIFY FILE NAME
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,OPNBLK+1(S)	;DEVICE NAME
	PUSHJ	P,TSIX		;TYPE IT
	MOVEI	M,":"		;COLON AFTER DEVICE
	PUSHJ	P,CHROUT	;TYPE COLON
	MOVE	T1,RB.NAM(S)	;FILE NAME
	PUSHJ	P,TSIX		;TYPE IT
	MOVEI	M,"."		;PERIOD AFTER FILE NAME
	PUSHJ	P,CHROUT	;TYPE PERIOD
	HLLZ	T1,RB.EXT(S)	;EXTENSION
	PUSHJ	P,TSIX		;TYPE IT
	MOVE	T1,QUEDIR(S)	;PPN
	PUSHJ	P,TPPN		;TYPE IT
>	;END CONDITIONAL ON DEBUG

	MOVEI	M,[ASCIZ / REQUEST /] ;IDENTIFY REQUEST
	PUSHJ	P,STROUT	;TYPE STRING
	MOVE	T1,M.EJOB(J)	;NAME OF REQUEST
	PUSHJ	P,TSIX		;TYPE IT
	MOVE	T1,M.EPPN(J)	;USER'S PPN
	PUSHJ	P,TPPN		;TYPE IT
	MOVEI	M," "		;SEPARATOR
	PUSHJ	P,STROUT	;TYPE SEPARATOR
	PJRST	WARN1.		;AND CONTINUE BELOW
;WARN -- ISSUE WARNING MESSAGE
;CALL:	WARN	<MESSAGE>
;USES NO ACS

WARN.:	MOVEI	M,[ASCIZ /
% /]
	PUSHJ	P,STROUT	;TYPE STRING
WARN1.:	EXCH	T1,(P)		;GET MESSAGE POINTER
	MOVEI	M,(T1)		;ADDR OF MESSAGE
	PUSHJ	P,STROUT	;TYPE MESSAGE
	MOVEI	M,[ASCIZ / in queue manager
/]
	PUSHJ	P,STROUT	;TYPE STRING
	PUSH	P,T2		;SAVE EXTRA AC
WARN2.:	AOS	T1		;ADVANCE POINTER TO RETURN
	MOVE	T2,-1(T1)	;GET WORD
	TRNE	T2,376		;SEE IF AT END OF MESSAGE
	JRST	WARN2.		;NO--LOOP BACK FOR NEXT WORD
	POP	P,T2		;YES--RESTORE T2
	EXCH	T1,(P)		;RESTORE T1 AND UPDATE RETURN
	POPJ	P,		;RETURN

;IOERR -- HANDLE TRANSMISSION, ETC. ERRORS DURING I/O
;CALL:	IOERR	<MESSAGE>
;USES T1

IOERR.:	PUSH	P,T2		;PRESERVE T2
	MOVEI	M,[ASCIZ /
% /]
	PUSHJ	P,STROUT	;TYPE STRING
	MOVEI	M,(T1)		;OUTPUT MESSAGE
	PUSHJ	P,STROUT	;TYPE MESSAGE
	MOVEI	M,[ASCIZ \ I/O error \]
	PUSHJ	P,STROUT	;TYPE STRING
	GETSTS	IO,T2		;GET CHANNEL STATUS
	HRRZ	T1,T2		;COPY FOR MESSAGE
	TRZ	T2,74B23	;CLEAR ERROR BITS
	SETSTS	IO,(T2)		;TELL MONITOR
	PUSHJ	P,TOCT		;OUTPUT ERROR STATUS
	MOVEI	M,[ASCIZ / in queue manager
/]
	PUSHJ	P,STROUT	;TYPE STRING
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN TO CALLER
;TPATH0--PRINT FULL PATH NAME FROM LOOKUP BLOCK
;TPATH -- TYPE THE FULL PATH NAME FROM QUEUE ENTRY
;CALL:	T1=POINTER TO PATH OR PPN
;USES T1, T2, T3

TPATH0:	TLNE	T1,-1		;IS THIS A PPN?
	PJRST	TPPN		;YES--PRINT AS A PPN
	ADDI	T1,2		;NO--BUMP POINTER PAST JUNK

TPATH:	TLNE	T1,-1		;IS THIS A PPN?
	PJRST	TPPN		;YES--GO PROCESS THE PPN
	MOVEI	M,"["		;SET UP A BRACKET
	PUSHJ	P,CHROUT	;SEND IT OUT
	MOVE	T3,T1		;SAVE POINTER
	HLRZ	T1,(T3)		;PICK UP PROJECT
	PUSHJ	P,TOCT		;PRINT THAT
	MOVEI	M,","		;LOAD A COMMA
	PUSHJ	P,CHROUT	;SEND IT OUT
	HRRZ	T1,(T3)		;COPY PROGRAMMER NUMBER
	PUSHJ	P,TOCT		;PRINT THE PROGRAMMER NUMBER
	ADDI	T3,1		;POINT TO FIRST SFD
	HRLI	T3,-5		;SET A POINTER UP
TPLOOP:	MOVE	T1,(T3)		;PICK UP SFD
	JUMPE	T1,TRSQB	;TYPE A RIGHT SQUAER BRACKET ON END
	PUSHJ	P,TSIX		;ELSE PRINT SFD
	MOVEI	M,","		;FOLLOWED BY A
	PUSHJ	P,CHROUT	;  COMMA
	AOBJN	T3,TPLOOP	;LOOP FOR MORE SFDS
TRSQB:	MOVEI	M,"]"		;PRINT THE BRACKET
	PJRST	CHROUT		;EXIT VIA THE TYPER
;;TSIX -- TYPE SIXBIT WORD
;CALL:	MOVE	T1,WORD
;	PUSHJ	P,TSIX
;USES T1, T2

TSIX:	MOVE	T2,[POINT 6,T1]
TSIX1:	TLNN	T2,(77B5)	;SKIP IF MORE BYTES
	POPJ	P,		;NO, ALL DONE
	ILDB	M,T2		;GET NEXT CHAR
	JUMPE	M,CPOPJ		;END AT FIRST 0
	ADDI	M," "-' '	;CONVERT TO ASCII
	PUSHJ	P,CHROUT	;TYPE CHAR
	JRST	TSIX1		;AND LOOP


;TPPN -- TYPE PPN IN BRACKETS
;CALL:	MOVE	T1,PPN
;	PUSHJ	P,TPPN
;USES T1, T2, T3

TPPN:	HRLM	T1,(P)		;SAVE RIGHT HALF
	HLRZS	T1		;T1=LEFT HALF
	MOVEI	M,"["
	PUSHJ	P,CHROUT	;TYPE OPEN BRACKET
	PUSHJ	P,TOCT		;TYPE LEFT HALF
	MOVEI	M,","		;SEPARATED BY A COMMA
	PUSHJ	P,CHROUT	;TYPE COMMA
	HLRZ	T1,(P)		;RESTORE RIGHT HALF
	PUSHJ	P,TOCT		;TYPE RIGHT HALF
	MOVEI	M,"]"
	PJRST	CHROUT		;TERMINATED BY CLOSE BRACKET

;TOCT -- TYPE OCTAL NUMBER
;CALL:	MOVE	T1,NUMBER
;	PUSHJ	P,TOCT
;USES T1, T2

TOCT:	JUMPGE	T1,TOCT1	;JUMP IF POSITIVE
	SETZ	T2,
	ROTC	T1,3		;MOVE HIGH ORDER CHAR TO T2
	MOVEI	M,"0"(T2)	;MAKE FIRST CHAR ASCII
	PUSHJ	P,CHROUT	;TYPE IT
	LSH	T1,-3		;T1=REST (MUST BE POSITIVE)
TOCT1:	IDIVI	T1,10		;GET NEXT DIGIT
	HRLM	T2,(P)		;STORE IT
	SKIPE	T1		;SEE IF DONE YET
	PUSHJ	P,TOCT1		;NO--LOOP
	HLRZ	T1,(P)		;RECOVER DIGIT
	MOVEI	M,"0"(T1)	;CONVERT TO ASCII FOR OCTAL
	PJRST	CHROUT		;TYPE CHAR
;STROUT -- TYPE A STRING
;CALL:	MOVEI	M,ADDR OF ASCIZ STRING
;	PUSHJ	P,STROUT
;SAVES ALL AC'S EXCEPT M

STROUT:	PUSH	P,T1
	PUSH	P,16
	HRRZ	T1,TYPCHR(S)	;ADDR OF ROUTINE TO TYPE A CHAR IF SPECIFIED
	JUMPE	T1,STROU2	;NO, OUT OUTSTR
	HRLI	M,(POINT 7,)	;MAKE M A BYTE POINTER
STROU1:	ILDB	16,M		;NEXT CHAR IN STRING
	JUMPE	16,STROU3	;EXIT IF END OF STRING
	PUSHJ	P,(T1)		;CALL ROUTINE SPECIFIED
	JRST	STROU1		;LOOP FOR ALL FILES
STROU2:	OUTSTR	(M)		;TYPE STRING
STROU3:	POP	P,16		;RESTORE AC'S
	JRST	TPOPJ		;RESTORE T1 AND EXIT

;CHROUT -- TYPE A CHAR
;CALL:	MOVEI	M,CHAR
;	PUSHJ	P,CHROUT
;SAVES ALL AC'S EXCEPT M

CHROUT:	PUSH	P,16		;SAVE AC
	MOVE	16,M		;16 IS CHARACTER AC FOR ROUTINE
	HRRZ	M,TYPCHR(S)	;ADDR OF ROUTINE IF SPECIFIED
	SKIPE	M		;SKIP IF NON SPECIFIED
	PUSHJ	P,(M)		;CALL ROUTINE SPECIFIED TO TYPE CHAR
	SKIPN	M		;SKIP IF ROUTINE SPECIFIED
	OUTCHR	16		;NO, TYPE HERE
	POP	P,16		;ESTORE 16
	POPJ	P,
	SUBTTL	STORAGE

	XLIST	;LITERALS
	LIT
	LIST

;PARAMETER AREA OFFSETS

	RELOC	QMANGR	;TO AVOID WASTE SPACE
	PHASE	0
Q.ZER:!			;START OF QUEUE PARAMETER AREA
Q.MEM:!	 BLOCK	1	;HOLD XWD WINDOW BLOCK,WINDOW WORD INDEX
Q.OPR:!	 BLOCK	1	;OPERATION CODE
    QO.CRE==1		;CREATION OPERATION
    QO.LST==4		;LIST OPERATION
    QO.MOD==5		;MODIFY OPERATION
    QO.KIL==6		;KILL OPERATION
    QO.DEL==10		;DELETE OPERATION
    QO.REQ==11		;REQUEUE OPERATION
    QO.FLS==12		;FAST LIST OPERATION
Q.LEN:!	 BLOCK	1	;LENGTHS IN AREA
Q.DEV:!	 BLOCK	1	;DESTINATION DEVICE
Q.PPN:!	 BLOCK	1	;PPN ORIGINATING REQUEST
Q.JOB:!	 BLOCK	1	;JOB NAME
Q.SEQ:!	 BLOCK	1	;JOB SEQUENCE NUMBER
Q.PRI:!	 BLOCK	1	;EXTERNAL PRIORITY
Q.PDEV:! BLOCK	1	;PROCESSING DEVICE
Q.TIME:! BLOCK	1	;PROCESSING TIME OF DAY
Q.CREA:! BLOCK	1	;CREATION TIME
Q.AFTR:! BLOCK	1	;AFTER PARAMETER
Q.DEAD:! BLOCK	1	;DEADLINE TIMES
Q.CNO:!	 BLOCK	1	;CHARGE NUMBER
Q.USER:! BLOCK	2	;USER'S NAME

Q.I:!			;START OF INPUT QUEUE AREA
Q.IDEP:! BLOCK	1	;DEPENDENCY WORD
Q.ILIM:! BLOCK	3	;JOB LIMITS
Q.IL:!			;END OF AREA NEEDED TO READ FOR MASTER QUEUE
Q.IDDI:! BLOCK	6	;JOB'S DIRECTORY
Q.II:!			;START OF INPUT FILES AREA

	PHASE	Q.I
Q.O:!			;START OF OUTPUT QUEUE AREA
Q.OFRM:! BLOCK	1	;FORMS REQUEST
Q.OSIZ:! BLOCK	1	;LIMIT WORD
Q.OL:!			;END OF AREA NEEDED TO READ FOR MASTER QUEUE
Q.ONOT:! BLOCK	2	;ANNOTATION
Q.FF:!
	PHASE	0
Q.F:!			;DUPLICATED AREA FOR EACH REQUESTED FILE
Q.FSTR:! BLOCK	1	;FILE STRUCTURE
Q.FDIR:! BLOCK	6	;ORIGINAL DIRECTORY
Q.FNAM:! BLOCK	1	;ORIGINAL NAME
Q.FEXT:! BLOCK	1	;ORIGINAL EXTENSION
Q.FRNM:! BLOCK	1	;RENAMED FILE NAME (0 IF NOT)
Q.FBIT:! BLOCK	1	;BIT 0=PRESERVED BY QUEUE, REST=STARTING BIT
Q.FMOD:! BLOCK	1	;FILE SWITCHES
X.LOG==1B1	;FILE IS LOG FILE
X.NEW==1B2	;OK IF FILE DOESNT EXIST YET
Q.FRPT:!BLOCK	2		;/REPORT

Q.FLEN==.-Q.F
	DEPHASE
	PHASE	0
Q.FDRM:! BLOCK	6	;DIRECTORY MASK FOR MODIFY
Q.FNMM:! BLOCK	1	;FILE NAME MASK FOR MODIFY
Q.FEXM:! BLOCK	1	;EXTENSION MASK FOR MODIFY
Q.FMDM:! BLOCK	1	;MODIFIER MASK FOR MODIFY
Q.FMLN==.-Q.F	;LENGTH OF MODIFY BLOCK

	DEPHASE
	RELOC	QMANGR	;TO AVOID WASTE SPACE
	PHASE	0
S.ZER:!		;START OF SCRATCH AREA (RELOCATED BY S)

;LOOKUP  BLOCK

RB.LEN:! BLOCK	1	;LENGTH OF  BLOCK
RB.PPN:! BLOCK	1	;DIRECTORY
RB.NAM:! BLOCK	1	;FILE NAME
RB.EXT:! BLOCK	1	;FILE EXTENSION
RB.PRT:! BLOCK	1	;PROTECTION
RB.PPX:! BLOCK	1	;LEVEL-C DIRECTORY
	 BLOCK	3	;JUNK
RB.ALC:! BLOCK	1	;ALLOCATION SIZE IN BLOCKS
	 BLOCK	4	;JUNK
RB.STR:! BLOCK	1	;STRUCTURE OF FILE
RB.STS:! BLOCK	1	;FILE STATUS WORD
	 BLOCK	2	;JUNK
RB.QTF:! BLOCK	1	;LOGGED IN QUOTA
RB.QTO:! BLOCK	1	;LOGGED OUT QUOTA
	 BLOCK	2	;JUNK
RB.AUT:! BLOCK	1	;AUTHOR
LENRB==.-RB.LEN


;MISC. SCRATCH LOCATIONS

UIOWD:!	 BLOCK	1	;IOWD TO UFD BLOCK FOR WILDCARD LOOKUP
UUSETI:! BLOCK	1	;USETI (BLOCK) COUNTER FOR WILDCARD LOOKUP
SCHDLR:! BLOCK	1	;ADDRESS OF SCHEDULER
PRODV:!	 BLOCK	1	;NAME OF PROCESSING DEVICE
THISNM:! BLOCK	1	;NAME OF THIS FILE
BESTPR:! BLOCK	1	;BEST PRIORITY FOUND SO FAR
BESTNM:! BLOCK	1	;NAME OF BEST REQUEST SO FAR
MASIOW:! BLOCK	1	;IOWD+1 FOR MASTER QUEUE WINDOW
MASSTI:! BLOCK	1	;BLOCK COUNTER FOR MASTER QUEUE WINDOW
QUENM:!	 BLOCK	1	;REQUESTED QUEUE TYPE
FSFPPN:! BLOCK	1	;PPN FOR FULL FILE ACCESS
MFDPPN:! BLOCK	1	;MASTER FILE DIRECTORY
QUEDIR:! BLOCK	1	;DIRECTORY FOR QUEUES
OPNBLK:! BLOCK	3	;OPEN BLOCK FOR WILDCARDS
FILNAM:! BLOCK	1	;FILE NAME FOR QUEUE REQUEST
MASNAM:! BLOCK	1	;MASTER QUEUE NAME
MASDIR:! BLOCK	1	;MASTER QUEUER DIRECTORY
LOPCNT:! BLOCK	1	;LOOP COUNTER FOR SAFETY
QUECNT:! BLOCK	1	;COUNTER TO QUEUE NAME FOR MASTER QUEUES IN ALL:/LIST
NOW:!	 BLOCK	1	;CURRENT TIME IN STANDARD FORMAT
MASSEQ:! BLOCK	1	;MASTER SEQUENCE NUMBER
MINAFT:!	BLOCK	1	;MIN WAIT ON DAEMON UUO.
AFTNUM:! BLOCK	1	;NUMBER OF REQUESTS REJECTED FOR AFTER OR DEPEN
REMSTA:! BLOCK	1	;STATION NUMBER TO MATCH IN QUEUE
REMDEV:! BLOCK	1	;DEVICE NUMBER TO MATCH IN QUEUE
STNPRT:! BLOCK	1	;STANDARD FILE PROTECTION
IFN DEBUG,<SCHLPF:! BLOCK 1 ;FLAG FOR REASON CANT SCHEDULE REQUEST>
THSJOB:! BLOCK	1	;THIS JOB NUMBER
TYPCHR:! BLOCK	1	;ADDR OF ROUTINES FOR TYPING CHARS
PATH:!	 BLOCK	12	;PATH FOR LOOKUP, ENTER, RENAME
SAVPRV:!		;PLACE TO SAVE PROTECTION WORD
SAVMOD:! BLOCK	1	;PLACE TO SAVE MODE AROUND INITS
SAVDAT:! BLOCK	1		;SAVE OTHER STUFF FOR DATE-75
LEN.H:!	BLOCK	1		;LENGTH OF HEADER
LEN.E:!	BLOCK	1		;LENGTH OF EACH ENTRY
UFDBLK:! BLOCK	200	;BLOCK FOR READING UFD FOR WILDCARD


MASBLK:! BLOCK	LN.MAS	;WINDOW INTO THE MASTER QUEUE


QUEBLL==Q.IL-1		;DETERMINE SIZE OF READ FOR MASTER QUEUE
IFG Q.OL-Q.IL,<QUEBLL==Q.OL-1>
QUEBLK:! BLOCK	QUEBLL	;AREA TO READ QUE FOR MASTER QUEUE


S.LEN==.-S.ZER


	LOC	MASBLK	;DEFINE WINDOW CONTENTS
M.HOLD:! BLOCK	2	;DEVICE WHICH IS MODIFYING QUEUE
M.SEQ:!  BLOCK	1	;SYSTEM SEQUENCE NUMBER (USED ON INPUT QUEUE ONLY)
M.NTRY==.-MASBLK	;START OF AN ENTRY

	PHASE	0	;BLOCK FOR EACH ENTRY IN MASTER QUEUE
M.ENAM:! BLOCK	1	;0-11=REMOTE DESTINATION, 12-35=FILE NAME OF .QUF
M.EPPN:! BLOCK	1	;USER'S NUMBER
M.ESEQ:! BLOCK	1	;SEQUENCE OF THIS JOB
M.EPRI:! BLOCK	1	;PRIORITY WORD
M.EPDV:! BLOCK	2	;PROCESSING DEVICE
M.EJOB:! BLOCK	1	;REQUEST NAME (SAVED FOR MODIFY AND KILL)
M.ECRE:! BLOCK	1	;CREATION TIME
M.EAFT:! BLOCK	1	;AFTER TIME
M.EDED:! BLOCK	1	;DEADLINE TIME
M.EXXX:! BLOCK	4	;MISC. PER QUEUE TYPE
M.ELEN:!		;LENGTH OF AN ENTRY
M.NTRS==<LN.MAS-M.NTRY>/M.ELEN	;NUMBER OF ENTRIES IN WINDOW
M.WAST==LN.MAS-<M.NTRS*M.ELEN>	;NUMBER OF WORDS NOT IN ENTRIES IN WINDOW

	PHASE	M.EXXX	;INPUT QUEUE
M.IDEP:! BLOCK	1	;DEPENDENCY WORD
M.ILIM:! BLOCK	3	;JOB LIMITS

	PHASE	M.EXXX	;OUTPUT QUEUE
M.OFRM:! BLOCK	1	;SPECIAL FORMS
M.OSIZ:! BLOCK	1	;OUTPUT SIZE AND LIMIT
M.ONOT:! BLOCK	2	;ANNOTATION
	END		;NO STARTING ADDRESS