Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99m-bb - filuuo.x19
There are no other files named filuuo.x19 in the archive.
TITLE FILUUO LEVEL D DISK SERVICE ROUTINE  V1162
SUBTTL DESIGNED BY T.HASTINGS,T.WACHS,C.WHITE CODED BY T.WACHS/TW  22 JUL 86
	SEARCH	F,S
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.



;

XP VFILUUO,1162
ENTRY	FILUUO
FILUUO::

;ASSEMBLY PARAMETER FOR FNDFIL INTERLOCK

	ENTRY	FILSER
FILSER::
	SUBTTL	DEFINITIONS

;BITS IN THE ACCESS TABLE STATUS WORD
ACPCRE==:40
ACPSUP==:20
ACPUPD==:10
ACPREN==:200
ACRSUP==:2
ACPNIU==:400000
ACMCNT==:377400
ACPSMU==:4


IOSMON==400000	;THIS FILE IS CURRENTLY DOING MONITOR IO
IOSAU==200000	;THIS FILE HAS THE ALTER-UFD RESOURCE
IOSUPR==100000	;SUPER USETI/USETO DONE ON THIS CHAN
IOSDA==40000	;THIS FIL HAS DISK ALLOCATION QUEUE
IOSRIB==20000	;RIB IS IN MONITOR BUFFER
IOSRDC==:10000	;THIS USER CHANNEL HAS READ COUNT UP FOR FILE
IOSWLK==4000	;FILE (WHOLE STR) IS SOFTWARE WRITE-=LOCKED
		; EITHER FOR ALL JOBS OR FOR THIS JOB ONLY
IOSPBF==2000	;PARTIAL BUFFER DONE
IOSFIR==1000	;COMPUTE AND STORE OR CHECK THE CHECKSUM
IOSHMS==IOBEG	;HUNG-DEVICE MESSAGE ALREADY TYPED
IOSRST==IOFST	;RESET (RELEASE) WAS DONE ON A SPOOLED DEVICE

;THE FOLLOWING S BITS ARE DEFINED IN COMMON.MOD
;BECAUSE THEY WANT TO BE IN THE SAME POSITION IN S AS IN RIB STATUS WORD
;IOSHRE=100	;HARD READ ERROR ENCOUNTERED
;IOSHWE=200	;HARD WRITE ERROR ENCOUNTERED
;IOSSCE=400	;SOFTWARE CHECKSUM ERROR ENCOUNTERED OR HARD POSITIONING ERROR

;IOSERR=IOSHRE+IOSHWE+IOSSCE
;IOSMER=-IOSERR

;BITS IN RH OF S
UDSX==:200	;SUPER USETO IS TO WRITE FORMATS ON THE DISK

;BITS IN LH(M) USED IN LOOKUP/ENTER/RENAME

UUOMSK==777000	;MASK FOR ALL POSSIBLE UUO BITS
UUOLUK==400000	;LOOKUP IN PROGRESS
UUOSFD==:200000	;SFD FOUND ON SOME STR IN SEARCH LIST
UUOREN==:100000	;RENAME IN PROGRESS
UUOUFD==:40000	;AT LEAST 1 UFD FOUND IN SEARCH LIST (FNDFIL)
UUOUPD==20000	;ENTER IS AN UPDATE
UUO2SF==:UUOUPD	;ON IF JUST SCANNING AT'S FOR AN SFD (2ND PASS)
UUOSF2==:UUOSFD+UUO2SF
UULKRN==:UUOLUK+UUOREN
UUODIR==:10000	;UUO IS FOR A DIRECTORY
UALASK==4000	;ALLOCATION REQUESTED ON ENTER
UPARAL==2000	;BIT ON IF PARTIAL ALLOCATION OR ENTER
UTRTWC==2000	;TRIED LOOKUP ON MORE THAN 1 SPECIFICATION
EXTUUO==1000	;BIT ON IN LH(UUO) IF EXTENDED UUO
DEFINE	NOSCHEDULE <>
DEFINE SCHEDULE <>
IFE	FTCBDB,<
DEFINE	CBDBUG(A,B)<>
>

IFN	FTCBDB,<
DEFINE	CBDBUG(A,B)<
IFIDN	<A>,<Y><
	EXCH	T1,CBUSER##
	CAME	T1,.CPJOB##
	HALT	.
	EXCH	T1,CBUSER##
>
IFIDN	<B>,<Y><
PUSHJ	P,CKBAS##
>
AOSA	.+1
0
>
>
IFN FTCBDB,<
	PRINTX	%FTCBDB SHOULD = 0
>

REPEAT 0,<
THE FOLLOWING IS THE ORDER IN WHICH RESOURCES SHOULD BE OBTAINED:

FIRST GET:	THEN GET:
MON BUF		CB, DA, OR AU
CB		DA
AU		CB
>
SUBTTL	INTERFACE SUBROUTINES WITH THE REST OF THE MONITOR

;DISPATCH TABLE
	POPJ	P,		;(-4) DEVOP UUO
	JRST	DBFSIZ		;(-3) GET BUFFER SIZE
	JRST	DSKINI##	;(-2) INITIALIZE
	JRST	CPOPJ1##	;(-1) HUNG, LET DSKSEC HANDLE IT
DSKDSP::JRST	DSKREL		;(0) RELEASE
	JRST	CLOSOU		;(1) OUTPUT CLOSE
	JRST	OUTPT		;(2) OUTPUT
	JRST	INPT		;(3) INPUT
	JRST	UENTR		;(4) ENTER
	JRST	ULOOK		;(5) LOOKUP
	JRST	DMPOUT		;(6) DUMP-MODE OUTPUT
	JRST	DMPIN		;(7) DUMP-MODE INPUT
	JRST	USETO0##	;(10) USETO
	JRST	USETI0##	;(11) USETI
	POPJ	P,		;(12) UGETF
	JRST	RENAM		;(13) RENAME
	JRST	CLOSIN		;(14) INPUT CLOSE
	POPJ	P,		;(15) UTPCLR
	POPJ	P,		;(16) MTAPE

;SUBROUTINE TO DETERMINE IF A JOB HAS A SHARABLE DISK RESOURCE
;ENTER	J=JOB NUMBER
;EXIT CPOPJ IF NO, CPOPJ1 IF YES
;RESPECTS ALL AC'S
FLSDR::	HLL	J,JBTSTS##(J)	;JOB STATUS BITS
	TLZ	J,-1-JXPN	;CLEAR ALL BUT JXPN
	TLZE	J,JXPN		;RESTORE JOB NUMBER, SKIP IF JXPN CLEAR
	POPJ	P,		;JOB IS EXPANDING, LIE ABOUT RESOURCES
IFN FTMP,<
	CAME	J,MCUSER##	;OWN MC? CAN'T SWAP OWNER
>
	CAMN	J,CBUSER##	;JOB HAVE CB
	PJRST	CPOPJ1##	;YES
	PJRST	TSTAD##		;NO, GO TEST AU,DA
;SUBROUTINE TO CLEAN UP THE ACCESS TABLES FOR A JOB AFTER AN ERROR.
; DECREMENTS THE READ-COUNT IF READING, CLEARS THE STATUS BYTE IF WRITING
; AND INCREMENTS THE QUOTA IF CREATE OR SUPERSEDE
SWPCLN::HLRZ	F,SWPDDB##+DEVSER ;START AT FIRST DSK
SWPCL1:	MOVE	T1,DEVMOD(F)	;IS THIS A DISK?
IFN FTSPL,<SKIPL DEVSPL(F)>	;OR SPOOLED DDB?
	TLNE	T1,DVDSK
	TDZA	T2,T2		;YES
	JRST	SWPCL9		;NO
	LDB	T1,PJOBN##	;IS IT OURS?
	CAME	T1,J
	JRST	SWPCL9		;NO
	HRRZ	T1,DEVACC##(F)	;LOC OF A.T.
	JUMPE	T1,SWPCL9	;THROUGH IF NONE
	MOVE	S,DEVIOS(F)	;DECREMENT READ-COUNT IF IT'S UP
	TLZE	S,IOSRDC
	MOVNI	T2,ACPCNT##
	ADDB	T2,ACCCNT##(T1)	;UPDATE COUNT, GET STATUS
	MOVEM	S,DEVIOS(F)
	TRNN	T2,ACPUPD+ACPREN+ACPCRE+ACPSUP ;IS THE FILE BEING WRITTEN?
	JRST	SWPCL4		;NO
	TRNN	T2,ACPUPD+ACPREN ;YES, BEING RENAMED OR UPDATED?
	JRST	SWPCL2		;NO
	TRNN	T2,ACMCNT	;YES, IS THE READ-COUNT NOW 0?
	JRST	SWPCL3		;YES, CLEAN UP THE A.T.
	MOVEI	T3,DEPWRT##
	TRNN	T2,ACPREN	;IS THE FILE BEING RENAMED?
	TDNN	T3,DEVWRT##(F)	;NO, IS THIS DDB AN UPDATER?
	JRST	SWPCL5		;NO, LEAVE A.T. ALONE
	LDB	T3,ACYWCT##	;HE IS AN UPDATER
	SUBI	T3,1		;DECR COUNT OF UPDATERS
	DPB	T3,ACYWCT##	;DONT CLEAR ACPUPD IF OTHER UPDATERS
	JUMPN	T3,SWPCL4

	JRST	SWPCL3		;CLEAN UP A.T.
SWPCL2:	MOVE	T2,ACCALC##(T1)	;NUMBER OF BLOCKS ALLOCATED TO THE FILE
	HRRZ	T3,DEVUFB##(F)	;LOC OF UFB
	SKIPE	T3
	ADDM	T2,UFBTAL##(T3)	;UPDATE THE USER'S QUOTA BY THE SIZE OF THE FILE
SWPCL3:	MOVEI	T2,ACPUPD+ACPREN+ACPSUP+ACPCRE
	ANDCAB	T2,ACCSTS##(T1)	;CLEAN OUT THE STATUS OF THE A.T.
SWPCL4:	PUSH	P,F		;SAVE F
	SETZ	F,		;INDICATE DONT USE CB (ON CLOCK LEVEL)
	TRNN	T2,ACMCNT	;READ-COUNT NOW 0?
	PUSHJ	P,ATRMOV##	;GET RID OF A.T.
	POP	P,F
SWPCL5:	HLLZS	DEVACC##(F)
SWPCL9:	PUSHJ	P,NXDDB##	;FIND NEXT DDB
	  CAMN	J,.USJOB	;DON'T DO FUNNY SPACE IF NOT ADDRESSABLE
	JUMPN	F,SWPCL1	;DO THIS ONE TOO
	POPJ	P,		;ALL DONE
;SUBROUTINE TO GET WORD POINTED TO BM FROM USER'S AREA
;RETURNS WORD IN T3, PRESERVES T1 AND T2
GTWDT3:	PUSH	P,T1		;SAVE T1
	PUSHJ	P,GTWST2##	;GET THE WORD INTO T1
	MOVE	T3,T1		;RETURN IT IN T3
	JRST	TPOPJ##		;RESTORE T1 AND RETURN

;ROUTINE FOR TESTING FOR SPECIAL DEVICE NAMES
;ENTER T1=DEVICE NAME
;EXIT CPOPJ IF NOT A SPECIAL DEVICE, WITH T1=NAME
;EXIT CPOPJ1 IF YES, T1=NAME, T2=INDEX IN TABLE (=0 FOR SYS, 1 FOR SXS)
; T3=0 IF JUST 'DEV', T3 =1 IF 'DEVX', AND DSKX EXISTS
; T4=INDEX INTO LOGICAL NAME TABLE IF A LOGICAL NAME
;CALL SDVTS1 TO IGNORE LOGICAL NAMES
;CALL SDVTSP TO IGNORE LOGICAL NAMES IF PT.PHO IS ON IN P1
SDVTSP:	TLNN	P1,PT.PHO##	;IGNORE LOGICAL NAMES?
SDVTST::PUSHJ	P,LNMTST	;IS DEVICE A LOGICAL NAME?
	  JRST	SDVTS1		;NO, SEE IF IT IS IN TABLE
	MOVEI	T2,LIBNDX##	;YES, PRETEND IT IS LIB
	SETZ	T3,		;NOT DEVX
	JRST	CPOPJ1##
SDVTS1::SETZB	T2,T3		;T2=INDEX T3=0 IF STRAIGHT MATCH
	TRNE	T1,-1		;ERSATZ DEVS ARE 3 CHARS
	JRST	SDVTS4		; SO A LONGER NAME DOESN'T MATCH
SDVTS2:	HLLZ	T4,SDVTBL##(T2)	;NAME
	CAMN	T1,T4		;MATCH?
	JRST	SDVTS3		;EXTRA WORK IF LIB
	CAIGE	T2,SDVLEN##	;END OF TABLE?
	AOJA	T2,SDVTS2	;NO, TRY NEXT
SDVTS4:	TRNN	T1,7777		;NO REAL MATCH
	TRNN	T1,770000	;IS IT DEVX?
	POPJ	P,		;NO - NO MATCH
	PUSH	P,T1		;YES, SAVE NAME
	HRLI	T1,'DSK'	;MAKE IT DSKX
	HRROI	T2,770000	;SET T2=MASK FOR DSKX
	PUSHJ	P,UNSRCH##	;LOOK FOR UNIT
	  PJRST	TPOPJ##		;NOT FOUND
	HLLZ	T1,(P)		;DSKX EXISTS
	PUSHJ	P,SDVTS1	;IS DEV A SPECIAL DEVICE?
	  PJRST	TPOPJ##		;NO, NON-SKIP
	CAIN	T2,LIBNDX##
	JRST	TPOPJ##		;"LIBX" DOESN'T EXIST
	MOVEI	T3,1		;YES, SET T3 NON-0
	PJRST	TPOPJ1##	;FOUND - SKIP RETURN
SDVTS3:	CAIE	T2,LIBNDX##	;GOOD RETURN IF NOT LIB:
	PJRST	CPOPJ1##
				;DROP THROUGH TO NEXT PAGE IF LIB
;HERE ON DEVICE "LIB", BUT NO LOGICAL DEVICE BY THAT NAME

;SUBROUTINE TO FIND THE LIB (SPEC WHICH IS SEARCHED ON LOOKUP FAILURE)
;EXIT NON-SKIP IF NONE
;SKIP-RETURN IF FOUND, T4=INDEX
;PRESERVES T1-T3
FNDLB:	SETZ	T4,		;START AT 1ST LOGICAL NAME
	SKIPE	.USLNM		;ARE THERE LOG NAMES?
FNDLB1:	SKIPN	@.USLNM		;YES, AT END?
	POPJ	P,		;NO LIB
	SKIPL	@.USLNM		;IS THIS A LIB?
	AOJA	T4,FNDLB1	;NO, TRY NEXT
	JRST	CPOPJ1##	;YES

;SUBROUTINE TO FIND A LOGICAL NAME
;ENTER T1=NAME
;EXIT T1=NAME, T3=BITS, T4=INDEX INTO TABLE
;ENTER AT LNMTSN IF F IS NOT POINTING AT A DDB
LNMTST::MOVE	T4,DEVPHO##(F)
	TLNE	T4,DEPPHO##	;PHYSICAL ONLY?
	JUMPN	F,CPOPJ##	;YES, NO MATCH
LNMTSN::IFN FTXMON,<PUSHJ P,SSEC0##>	;ENTER SECTION ZERO
	SETZ	T4,		;START AT BEGINNING
	CAMN	T1,[-1]		;WOULD WE MATCH OLD-STYLE LIB KLUDGERY?
	POPJ	P,		;YES, HACK, NO MATCH FOR ARGUMENT OF -1
	SKIPE	.USLNM		;ANY AT ALL?
LNMTS1:	SKIPN	T3,@.USLNM	;YES, DONE?
	POPJ	P,		;NO MATCH
	CAMN	T1,(T3)		;IS THIS THE ONE WE WANT?
	JRST	CPOPJ1##	;MATCH
	AOJA	T4,LNMTS1	;TRY NEXT

;SUBROUTINE  TO CHECK FOR DEVICE "NUL"
;RETURNS CPOPJ IF NUL:, ELSE CPOPJ1
NULTST::MOVS	T1,DEVNAM(F)	;NAME USER INITED
	CAIE	T1,'NUL'	;NUL:?
	AOS	(P)		;NO
	POPJ	P,		;RETURN POPJ OR POPJ1
;SUBROUTINE TO GET THE PPN ASSOCIATED WITH SYS:
;RETURNS NON-SKIP IF "SYS" IS A LOGICAL NAME OR A PATH(O)LOGICAL NAME
;SKIP-RETURNS WITH PPN IN T3 OTHERWISE
;RESPECTS ALL ACS EXCEPT T3
SYSNM::	PUSHJ	P,SAVT##	;SAVE ACS
	MOVE	T1,.JDAT+SGAMOD##
	TLNE	T1,PHONLY	;PHYSICAL ONLY SYS?
	JRST	SYSNM1		;YES, GET SYSPPN
	SKIPE	DEVLOG(F)	;IF F POINTS AT A DDB WITH A LOGICAL NAME
	POPJ	P,		;THE NAME MUST BE "SYS"
	MOVSI	T1,'SYS'	;SEE IF WE HAVE A PATH(O)LOGICAL NAME
	PUSHJ	P,LNMTST	;NO. LOGICAL NAME?
SYSNM1:	  SKIPA	T3,.CPJOB##	;NO, GIVE SYS IS NOT A LOGICAL NAME RETURN
	POPJ	P,		;HAS SUCH A NAME
	MOVE	T3,JBTSFD##(T3)
	TLNE	T3,JBPXSY##	;NEW ENABLED?
	SKIPA	T3,XSYPPN##	;YES
	MOVE	T3,SYSPPN##	;NO
	MOVEM	T3,-3(P)	;WHERE SAVT WILL RESTORE T3 FROM
	JRST	CPOPJ1##
;SUBROUTINE TO TEST IF THE DEVICE WHOSE NAME IS IN T1 IS A DISK
;ENTER WITH J = JOB NUMBER
;RH(P1) CONTAINING DD%PHO IF PHYSICAL ONLY
;EXIT CPOPJ IF A DISK, WITH F=PROTOTYPE DDB
;EXIT CPOPJ1 IF NOT A DISK, OR A SINGLE-ACCESS DISK NOT FOR THIS JOB
;LIGHTS SYSDEV IN LH(F) IF THE NAME IS SOME FLAVOR OF SYS (EG "SYSB")
;CALLED BY DEVPHY
TSTDSK::JUMPE	T1,CPOPJ1##	;"0" IS NOT A DISK
	PUSHJ	P,SAVT##	;SAVE T2-T4
	MOVEI	F,DSKDDB##	;SET F FOR PROTOTYPE DDB
	PUSHJ	P,ALIASD##	;IS NAME AN ALIAS FOR "DSK"?
	  POPJ	P,		;YES. NON-SKIP RETURN
	TRNN	P1,DD%PHO##	;PHYSICAL ONLY?
	PUSHJ	P,LNMTST	;NO, LOOK FOR A LOGICAL NAME
	  CAIA			;NOT FOUND OR PHYSICAL ONLY
	POPJ	P,		;FOUND A LOGICAL NAME
	PUSHJ	P,SDVTS1	;IS IT A SPECIAL DEV?
	  JRST	TSTDS1		;NO
	CAIG	T2,SYSNDX##	;YES, IS IT SYS?
	TLO	F,SYSDEV	;YES, LIGHT SYSDEV
	POPJ	P,		;AND RETURN
TSTDS1:	CAMN	T1,['NUL   ']	;'NUL'
	POPJ	P,		; IS A DISK
	TLNN	T1,-1		;XWD 0,,"A"?
	PJRST	CPOPJ1##	;YES,NOT A DSK
IFN FTPSTR,<
	PUSHJ	P,SAVE2##	;S.L. ROUTINES CLOBBER P1 AND P2
>
	PUSH	P,U		;SAVE U FOR REST OF MON
	PUSHJ	P,SRSTR##	;USER SUPPLYING STR NAME?
	  SKIPA			;NOT AN STR NAME
	JRST	TSTDS2		;YES, AN STR
	PUSHJ	P,MSKUNI##	;SET T2=MASK FOR NAME
	MOVEI	T4,SRUNI##	;ASSUME NO SECONDARY PORT SEARCH
IFN FTDUAL,<
	TRNE	P1,DD%ALT##	;ALSO SEARCHING FOR ALTERNATE PORTS
	MOVEI	T4,SRUNA##	;YES, GET THAT ROUTINE
>
	PUSHJ	P,(T4)		;IS USER SUPPLYING A UNIT NAME?
	  JRST	UPOPJ1##	;NOT A DISK - SKIP RETURN
	  JFCL			;PHYSICAL DSK NAME
	HRRZ	T3,UNISTR##(U)	;YES, SET T3 TO STR DB LOC
	JUMPN	T3,TSTDS2	;IF UNIT NOT IN A STR
	MOVE	T1,.PDOBI##(W)
	TLNE	T1,(JP.OPP)	;DOES JOB HAVE OPR PRIVS?
	JRST	TSTDS6		;YES, OK
	JRST	TSTDS4		;NO, ONLY IF PRIV'D
TSTDS2:
IFN FTPSTR,<
	MOVE	T4,STRPVS##(T3)	;F.S. IS PRIVATE BIT
	TRNN	T4,STPPVS##	;IS THIS A PRIVATE F.S.?
	JRST	TSTDS3		;NO, ALL IS WELL
	PUSHJ	P,SLPTR##	;FIND THIS JOBS S.L.
	  JRST	TSTDS4		;NONE OR EMPTY, LEGAL ONLY IF PRIV'ED
	HRRZ	T1,STRFSN##(T3)	;F.S. NMBER
	PUSHJ	P,SLFND##	;IS THIS F.S. IN THE USER'S S.L.
	  JRST	TSTDS4		;NO, ILLEGAL UNLESS PRIV'ED
TSTDS3:>
	SKIPLE	T4,STRJOB##(T3)	;STR SINGLE-ACCESS?
	CAIN	J,(T4)		;YES. FOR THIS JOB?

	JRST	TSTDS6		;YES, OK
TSTDS4:	MOVE	T1,JBTPPN##(J)	;NO. JOB MUST BE PRIVILEGED TO DO IT
;HERE IF TRYING TO GET A UNIT NOT IN AN STR, OR SINGLE ACCESS STR NOT FOR THIS JOB
;ALLOW IT IS JOB IS PRIVILEGED, OTHERWISE ERROR RETURN
	JUMPGE	M,TSTDS5	;IF A COMMAND,
	SKIPL	DEVJOB(F)	;M NEGATIVE IF FILOP.
	CAMN	T1,FFAPPN##	; ONLY [1,2] IS LEGAL
TSTDS5:	PUSHJ	P,PRVJO##	;PRIV'D JOB?
	  JRST	TSTDS7
TSTDS6:
IFE FTMDA,<
	MOVE	T2,UNIUST##(U)	;NO NEW ACCESSES FOR UNIT?
	TLNE	T2,UNPNNA##
> ;END IFE FTMDA
IFN FTMDA,<
	PUSHJ	P,CHKLOK##	;LOCKED?
> ;END IFN FTMDA
	JRST	UPOPJ1##	;YES, SAY IT ISNT A DSK

	JRST	UPOPJ##		;YES. OK RETURN
TSTDS7:	CAMN	T1,UMDPPN##	;IF USER MODE DIAG
	JUMPE	T3,UPOPJ##	;OK IF RIGHT PPN
	JRST	UPOPJ1##	;NOPE, LOSE
;ROUTINE TO WRITE THE SATS OF ALL UNITS WHICH HAVE CHANGED
;ENTER WITH RIB IN MONITOR BUFFER
;ENTER/EXIT WITH U=UNIT THAT HAS DA (IF ANY)
;ALWAYS EXITS WITH DA ON SAME UNIT AS WHEN ENTERED (IF ANY)

RIBSAT::TLNE	S,IOSDA		;HAVE DA?
	JRST	RIBSAD		;YES
	PUSHJ	P,UPDA##	;NO, GET IT
	PJRST	RIBSAW		;WRITE CHANGED SATS, RETURNS DA

RIBSAD:	PUSH	P,U		;SAVE UNIT THAT HAS DA
	PUSHJ	P,RIBSAW	;WRITE CHANGED SATS
	POP	P,U		;GET ORIGINAL UNIT BACK
	PUSHJ	P,STORU##	;STORE IT IN DEVUNI
	PJRST	UPDA##		;GET DA BACK ON THAT UNIT

;ROUTINE TO WRITE SATS - MUST BE CALLED WITH DA, RETURNS WITHOUT DA

RIBSAW:	PUSHJ	P,SAVE1##	;SAVE P1
	SKIPGE	DEVRIB##(F)	;IF IN AN EXTENDED RIB,
	PUSHJ	P,WTUSAT	; NO UNIT-CHANGE TO EXTENDED RIB
	PUSHJ	P,DWNDA##	;GIVE UP DA
	PUSHJ	P,SPTRW##	;GET AOBJN WORD FOR POINTERS
	MOVE	P1,T1		;INTO P1
RIBSA2:	SKIPN	T2,(P1)		;GET A POINTER
	POPJ	P,		;DONE
	TLNE	T2,-1		;UNIT CHANGE?
	JRST	RIBSA3		;NO, TRY NEXT
	TRZ	T2,RIPNUB##	;YES, GET UNIT NUMBER
	PUSHJ	P,NEWUNI##	;SET U TO THIS UNIT
	  JRST	RIBSA3		;NO GOOD - DON'T TOUCH SATS
	PUSHJ	P,UPDA##
	PUSHJ	P,WTUSAT	;WRITE SAT FOR UNIT IF IT CHANGED
	PUSHJ	P,DWNDA##	;GIVE UP DA
RIBSA3:	AOBJN	P1,RIBSA2	;AND TRY NEXT POINTER
	POPJ	P,		;DON'T - RETURN

;SUBROUTINE TO WRITE SATS FOR A UNIT
WTUSAT::PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,SAVR##	;AND R
	SE1ENT			;ENTER SECTION 1
	LDB	P1,UNYSIC##	;NUMBER OF SAB BLOCKS FOR UNIT
	SKIPN	R,UNISAB##(U)	;LOC OF 1ST SAB
	POPJ	P,		;UNIT HAS NO SAB (OFF-LINE, DOWN, OR STR YANKED)
WTUSA1:	SKIPGE	SABFIR##(R)	;HAS SAT BEEN MODIFIED?
	PUSHJ	P,SATWRT##	;YES. WRITE IT
	SKIPN	UNISAB##(U)	;UNIT STILL HAVE SAB?
	POPJ	P,		;NO, STR YANKED WHILE BLOCKED IN UUOPWQ
	MOVE	R,SABRNG##(R)	;STEP TO NEXT SAB IN RING
	SOJG	P1,WTUSA1	;GO IF IT HASNT BEEN CHECKED
	POPJ	P,		;RETURN
;SINCE SAT TABLES ARE ALWAYS WRITTEN BEFORE UFD'S, THERE IS NO NEED
;FOR SPECIAL CODE TO WRITE SAT'S ON A 147 RESTART,   SO.......
;MAKE DSKSTP BE A POPJ
;FAKE WAIT1 FOR USE DURING RESTART
ONCWAT::MOVSI	T1,ONCTIM##	;SET UP A HUNG TIMER
ONCWA1:	MOVE	S,DEVIOS(F)
	TRNN	S,IOACT		;DONE?
	JRST	CPOPJ##		;YES
	SOJG	T1,ONCWA1
	MOVE	U,DEVUNI##(F)	;TIMED OUT
	HRRZ	J,UNIKON##(U)
	PUSHJ	P,@KONSTP##(J)	;STOP THE DEVICE
	  JFCL
	SETZM	UNISTS##(U)	;SET UNIT IDLE
	MOVSI	T1,KOPBSY##	;SET KONTROLLER IDLE
	ANDCAM	T1,KONBSY##(J)
	SETOM	@KONCHN##(J)	;SET CHANNEL IDLE
	TRC	S,IOACT+IODERR	;CLEAR IOACT, LIGHT DEVICE ERROR
	PJRST	STOIOS##	; AND RETURN

;HERE ON A LOGOUT, WHEN THERE ARE NO OTHER JOBS LOGGED IN UNDER THIS PPB
;CALLED BY LOGOUT , WITH AC=PPN  (DSKLGO UUO)
DSKLGO::MOVEI	F,0		;NO REAL DDB
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	HLRZ	T2,SYSPPB##	;%NO. SET TO SEARCH PPB'S
	PUSHJ	P,LSTSCN##	;%FIND PPB FOR THIS JOB
	  JUMPLE T2,GVCBJ##	;%NOT THERE - EXIT IF NO CORE BLOCK SET UP
	MOVEI	T1,PPPNLG##	;%FOUND - SET NLG
	ANDCAM	T1,PPBNLG##(T2)	;% IN PPB BLOCK
	PJRST	TSTPP2		;%AND GO DELETE PPB,UFBS FOR THIS PRJ,PRG
;SUBROUTINE TO BUILD A DISK DEVICE DATA BLOCK
;ENTER WITH T1=DEVICE NAME, F=LOC OF DDB (OR PROTOTYPE DDB)
;IF A SPOOLING DEVICE, P1 CONTAINS DEVMOD, ELSE P1=0
;CALLED BY ASSPRG
;HERE FROM ONCE-ONLY CODE
;RETURNS CPOPJ IF NO MORE DDB SPACE, CPOPJ1 NORMALLY
;PRESERVES T2-T4
SETDDO::PUSH	P,DSKDDB##	;SAVE NAME
	JRST	SETDD3		;GO CREATE THE DDB
;THIS IS THE NORMAL ENTRY POINT
SETDDB::PUSHJ	P,SAVT##	;SAVE T2-T4
	HRRZ	T3,F		;ADDR. OF THE DDB
	CAIE	T3,DSKDDB##	;IS IT THE PROTOTYPE?
	MOVE	T1,DEVNAM(F)	;NO. GET THE PHYSICAL DEVICE NAME
	PUSH	P,T1		;SAVE NAME
	MOVE	T1,DEVMOD(F)
	TRNE	T1,ASSPRG	;DDB BEEN INITED?
	JRST	SETDD1		;YES. HAVE TO COPY PROTOTYPE
	CAIE	T3,DSKDDB##	;IS IT PROTOTYPE?
	JRST	SETDD2		;NO. USE IT

;HERE WHEN WE MUST MAKE A COPY OF THE PROTOTYPE DDB
SETDD1:	MOVEI	T2,DDBLEN##	;NO OF 4-WORD BLOCKS NEEDED
	MOVEI	T1,GTFWDU##	;ASSUME NOT A GET/RUN
	MOVE	T3,J		;COPY/JOB CONTEXT HANDLE
	ANDI	T3,JOBMSK##	;ISOLATE JOB NUMBER
	MOVE 	T3,JBTSTS##(T3)	;GET JOB STATUS WORD
	TRNE	T3,JS.ASA
	MOVEI	T1,GFWDUD##	;ALWAYS WIN FOR GET/RUN
	PUSHJ	P,(T1)		;GET THE CORE
	  JRST	TPOPJ##		;CANT GET IT - RETURN
	SKIPA	T2,F		;PRESERVE OLD DDB (SETDDB)
SETDD3:	SETZ	T2,		;CLEAR OLD DDB (SETDDO)
	HRR	F,T1		;LOC OF THE CORE
	HRLI	T1,DSKDDB##	;FROM THE PROTOTYPE
	BLT	T1,DEVRB1##-1(F) ;BLT THE NEEDED INFORMATION
IFN FTSPL,<
	JUMPE	T2,SETDD6	;HAVE AN OLD DDB
	HRRZ	T1,DEVSPM##(T2)	;DOES THE OLD DDB HAVE A
	JUMPE	T1,SETDD6	; SPOOLED PARAMETER BLOCK?
	PUSH	P,T1		;YES, REMEMBER ADDRESS
	MOVEI	T2,SPBMAX##	;SIZE OF AN SPB
	PUSHJ	P,GTFWDC##	;GET CORE
	  JRST	TTPOPJ##	;RAN OUT OF PER-PROCESS FUNNY SPACE
	HRRZM	T1,DEVSPM##(F)	;STORE NEW SPB ADDRESS IN NEW DDB
	MOVEI	T2,SPBMAX##(T1)	;COMPUTE END ADDRESS OF BLOCK
	POP	P,T3		;GET OLD SPB ADDRESS
	HRLI	T1,(T3)		;SET UP BLT POINTER
	BLT	T1,-1(T2)	;COPY SPB
SETDD6:
> ;END IFN FTSPL
	HRRZ	T2,F		;GET NEW DDB ADDRESS
	CAML	T2,SYSSIZ##	;IN SWAPPING AREA?
	JRST	SETDD4		;YES, DO IT DIFFERENTLY
	SKIPE	.UONCE##	;TWICE?
	JRST	TPOPJ1##	;YES, GO AWAY
	DDBSRL
	MOVE	T1,SWPDDB##+DEVSER
	HLLM	T1,DEVSER(F)
	HRLM	F,SWPDDB##+DEVSER ;LINK PROTOTYPE TO THIS DDB
	DDBSRU
	JRST	SETDD5
SETDD4:	MOVE	T2,.USLST
	HLLM	T2,DEVSER(F)
	HRLM	F,.USLST
				;FALL INTO SETDD5
SETDD5:
IFN FTSPL,<
	SKIPE	P1		;IF THIS IS A SPOOLING DDB
	MOVEM	P1,DEVMOD(F)	;SAVE DEVMOD OF REAL DEVICE
>
	MOVEI	T1,ASSCON+ASSPRG ;MAKE SURE ASSIGN BITS ARE OFF
	ANDCAM	T1,DEVMOD(F)	;(1 WILL BE TURNED ON BY ASSPRG)
	MOVE	T1,(P)		;GET NAME
	PUSHJ	P,MSKUNI##	;SET UP A MASK
	PUSHJ	P,UNSRCH##	;FIND THE UNIT (OR STR)
	  SETZ	T3,		;NONE (SHOULDN'T HAPPEN)
	HRRM	T3,DEVUNI##(F)	;SAVE IN DEVUNI (SO DDB
				; WILL BE FOUND ON A REMOVE)
SETDD2:	POP	P,DEVNAM(F)	;SET NAME INTO DDB
IFN FTMP,<
	MOVSI	T2,1000		;MP & QUEUED PROTOCOL 1
	HLLM	T2,DEVCPU##(F)	;STORE FOR UUOCON
>
	PUSHJ	P,NULTST	;IF NUL:
	  SKIPA	T2,[XWD -1-TTYATC,177777] ;ALL DV'S, ALL MODES
	JRST	CPOPJ1##
	IORM	T2,DEVMOD(F)

	JRST	CPOPJ1##
IFN FTSPL,<
; ROUTINE TO CREATE A SPOOLED PARAMETER BLOCK
; CALL:	PUSHJ	P,SETSPB
;	  <ERROR>		;NO FREE CORE
;	<SKIP>			;T1 AND DEVSPM SETUP
;
SETSPB::SKIPE	T1,DEVSPM##(F)	;IS THERE A SPOOL PARAM BLOCK?
	JRST	CPOPJ1##	;YES--ALL DONE
	MOVEI	T2,SPBMAX##	;HOW MUCH CORE WE NEED
	PUSHJ	P,GTFWDC##	;GET THAT CORE
	  POPJ	P,		;NO FREE CORE
	MOVEM	T1,DEVSPM##(F)	;REMEMBER WHERE IT IS
	HRLZ	T2,T1		;SET ADR,,0
	HRRI	T2,1(T1)	;ADR,,ADR+1
	SETZM	0(T1)		;CLEAR FIRST WORD
	BLT	T2,SPBMAX##-1(T1) ;CLEAR THE REST
	JRST	CPOPJ1##	;RETURN
> ;END IFN FTSPL
;SUBROUTINE TO COMPUTE THE SIZE OF THE BUFFER
DBFSIZ:	TLNN	M,.OPLBF	;LARGE BUFFERS?
	 JRST	DBFSZ1		;NO - GO RESET THE VALUE IN CASE IT CHANGED
	SKIPN	T1,.PDLBS##(W)	;YES, HAVE DEFAULTS?
	MOVEI	T1,LBFSIZ##+1	;NO, USE SYSTEM DEFAULT
	TLNE	T1,-1		;SET BY UUO?
	HLRZS	T1		;YES, USE THAT SIZE
	POPJ	P,		;RETURN TELLING UUOCON THE BUFFER SIZE

;HERE TO SET THE BUFFER SIZE FROM THE PROTOTYPE DISK DDB
DBFSZ1:	PUSH	P,F		;SAVE F FOR A MOMEMT
	MOVEI	F,DSKDDB##	;POINT AT PROTOTYPE DISK DDB
	PUSHJ	P,REGSIZ##	;GET THE DEFAULT BUFFER SIZE
	JRST	FPOPJ##		;RESTORE F AND RETURN
;SUBROUTINE TO CLEAR A DISK DEVICE DATA BLOCK
;ENTER WITH F=LOC OF DDB
;CALLED BY RELEASE CODE
CLRDDB::HRRZ	T1,F
	CAML	T1,SYSSIZ##
	SKIPA	T1,[.USLST-DEVSER]
	MOVEI	T1,SWPDDB##	;START AT PROTOTYPE
	DDBSRL
CLRDD1:	MOVE	T2,T1
	HLRZ	T1,DEVSER(T2)	;GET SUCCESSOR TO THIS DDB
	SKIPN	T1		;END?
	STOPCD	CLRDD2,DEBUG,DNF,	;++ DDB NOT FOUND
	CAIE	T1,(F)		;NO. IS LINK THE ONE WE WANT?
	JRST	CLRDD1		;NO. TRY NEXT

;HERE WITH T2=LOC OF DDB WHOSE LINK IS THE ONE WE WANT
	MOVE	T3,DEVSER(F)	;LINK OF DDB WE ARE REMOVING
	HLLM	T3,DEVSER(T2)	;SAVE IN LINK OF PREDECESSOR
CLRDD2:	DDBSRU
	SKIPE	DINITF##	;IN ONCE-ONLY CODE?
	POPJ	P,		;YES, DON'T GIVE UP CORE
	HRRZ	T2,DEVSPM##(F)	;A SPOOLING PARAMETER BLOCK?
	JUMPE	T2,CLRDD3	;NO, JUST GO ON
	MOVEI	T1,SPBMAX##	;GET SIZE OF BLOCK
	PUSHJ	P,GVFWDS##	;AND GIVE IT BACK
CLRDD3:	MOVEI	T1,DDBLEN##	;NO OF 4-WORD BLOCKS TO RETURN
	HRRZ	T2,F		;LOC OF DDB TO CLEAR
	CAMGE	T2,SYSSIZ##
	PJRST	GIVWDS##	;RETURN THE CORE AND RETURN TO CALLER
	PUSHJ	P,DMPFZR##	;ZERO F IN DUMP AC'S AND SAVED CONTEXT
	PJRST	GVFWDS##



;SUBROUTINE TO SET UP A DDB
;EXITS WITH F=LOC OF DDB
;EXIT CPOPJ IF NO FREE CORE, CPOPJ1 IF OK
FAKDDB::MOVEI	T2,DDBLEN##	;GET CORE FOR A DDB
	PUSHJ	P,GETWDS##
	  POPJ	P,		;NONE AVAILABLE - RETURN CPOPJ
FAKDDX::PUSHJ	P,SAVE1##
	SETZB	S,P1		;SO SETDDB WON'T CHANGE DEVMOD, CLEAR RANDOM BITS IN S
	PUSHJ	P,SETDDO	;GOT IT - MAKE A DDB FROM THE SPACE
	  STOPCD .,JOB,SER,	;++SETDDO ERROR RETURN
	MOVE	J,.CPJOB##	;SET UP J
	DPB	J,PJCHN##	;STORE IN DDB
	PJRST	CPOPJ1##	;AND TAKE SKIP-RETURN
;SUBROUTINE TO RETURN THE ACTUAL STR NAME FOR A DDB
;ENTER WITH F=LOC OF DDB
;EXIT CPOPJ IF NOT A DISK OR NO UNIT ASSOCIATED WITH DDB (LOOKUP NOT DONE)
;EXIT CPOPJ1 IF A DISK, WITH T1=NAME OF STR

NAMSTR::MOVE	T1,DEVMOD(F)	;IS DEVICE A DISK?
	TLNN	T1,DVDSK
	POPJ	P,		;NO, NON-SKIP RETURN
	HRRZ	T1,DEVFUN##(F)	;YES, GET SOME UNIT IN STR
	JUMPE	T1,CPOPJ##	;NONE - NO LOOKUP HAS BEEN DONE
	MOVE	T1,UNISTR##(T1)	;GOT ONE. GET STR DATA BLOCK LOC
	MOVE	T1,STRNAM##(T1)	;NAME OF STR
	PJRST	CPOPJ1##	;SKIP-RETURN
SUBTTL	COMCON - COMMAND DECODER INTERFACE ROUTINES

;SUBROUTINE TO PERFORM "DISK" COMMAND - PRINT DISK ACCESSES
;CALL:	MOVE	J,JOB NO.
;	PUSHJ	P,DSKCOM	;CALLED FROM COMCON - COMMAND DECODER
;	ALWAYS RETURN
;PRINTS INCREMENTAL READS AND WRITES, TOTAL READS AND WRITES
;TOTAL BLOCKS ALLOCATED, AND KILO-DISK-MIN FOR ALL STRS COMBINED


DSKCOM::PUSHJ	P,SAVJW##	;PRESERVE J (W GETS A RIDE)
	PUSHJ	P,GETJOB##	;GET DECIMAL JOB NO. ARG IF ANY
	  JRST	DSKCM1		;NO ARG, ASSUME USER'S OWN JOB(AC [=J)
	MOVE	J,T2		;NO, SETUP JOB NUMBER
	JRST	DSKCM2		;PRINT DATA FOR SPECIFIED JOB

;HERE WHEN USER DID NOT SPECIFY A JOB NUMBER - SO DO HIS WITH INCREMENTAL
DSKCM1:	PUSHJ	P,INLMES##	;NO, PRINT MESSAGE
	ASCIZ	/Rd,Wt=/
	PUSHJ	P,DSKINC	;PRINT INCREMENTAL DISK READS
	PUSHJ	P,INLMES##	;COMMA
	ASCIZ	/,/
	PUSHJ	P,PRTWDW	;PRINT NO OF INCREMENTAL DISK WRITES
	PUSHJ	P,CRLF##	;PRINT CRLF
;STILL IN FTDSTT
;HERE TO PRINT DATA FOR ANOTHER JOB(IE DO NOT PRINT INCREMENTAL)
DSKCM2:	PUSHJ	P,INLMES##	;PRINT HEADING
	ASCIZ	/Rd,Wt=/
	LDB	T1,JBYRCT##	;TOTAL NO. OF READS FOR JOB SINCE LOG-IN
	PUSHJ	P,RADX10##	;PRINT DECIMAL
	PUSHJ	P,INLMES##	;PRINT COMMA
	ASCIZ	/,/
	LDB	T1,JBYWCT##	;TOTAL NO. OF WRITES FOR JOB SINCE LOGIN
	PUSHJ	P,RADX10##	;PRINT DECIMAL
REPEAT 0,<			;ALLOCATION NOT CODED YET
	PUSHJ	P,INLMES##	;PRINT HEADER
	ASCIZ	/
Al=/
	LDB	T1,JBYTDB	;NO. OF BLOCKS ON ALL STRS FOR JOB
	PUSHJ	P,RADX10##	;PRINT
	PUSHJ	P,INLMES##	;PRINT HEADER
	ASCIZ	/
Kilo-dsk-min=/
	MOVE	T1,JBTTDB(J)	;TOTAL DISK BLOK SEC SO FAR
				;***NEED TO RECOMPUTE*** ON COMMAND
	IDIVI	T1,^D60*^D1000/^D128	;CONVERT TO J-MIN
	PUSHJ	P,RADX10##	;PRINT DECIMAL
>	;END REPEAT 0
	PJRST	CRLF##		;PRINT CRLF AND RETURN

;ROUTINE TO PRINT DISK BLOCK # FOR CONTROL-T
DSKCTT::MOVE	S,DEVIOS(F)	;GET I/O STATUS
	JUMPL	S,DSCTT2	;JUMP IF IOSMON=1
	TLNE	S,IOSUPR	;SUPER MODE?
	JRST	DSCTT1		;YES -- PRINT BLOCK #
	MOVE	T1,DEVREL##(F)
	CAIG	T1,0		;EARLY BLOCK?
	JRST	DSCTT2		;YES -- ASSUME MONITOR I/O
DSCTT1:	MOVEI	T1,[ASCIZ " block "]
	PUSHJ	P,CONMES##	;PRINT TITLE
	TLNN	S,IOSUPR	;SUPER I/O
	SKIPA	T1,DEVREL##(F)	;NO--GET RELATIVE BLOCK
	MOVE	T1,DEVBLK##(F)	;YES--GET ABSOLUTE BLOCK #
	PJRST	RADX10##	;PRINT THE NUMBER
DSCTT2:	MOVEI	T1,[ASCIZ " (Monitor I/O)"]
	PJRST	CONMES##


;SUBROUTINE TO PRINT NO OF DISK WRITES (RESULT OF WATCH COMMAND)
;CALL:	MOVE J,JOB NO [J=J]
;	PUSHJ P,PRTWDW
PRTWDW::ADDI	J,JBDIRD##	;INCREASE JOB NO BY DIFF IN READ/WRITE TABLE ORIGINS
	PUSHJ	P,DSKINC	;PRINT INCREMENTAL DISK WRITES
	MOVEI	J,MJBDRD##(J)	;DECREASE JOB NO BY DIFF IN TABLE ORIGINS
	POPJ	P,


;SUBROUTINE TO PRINT INCREMENTAL NO. OF BLOCKS READ OR WRITTEN
;CALL:	MOVE	J,JOB NO.(J=J)
;	PUSHJ	P,DSKINC
;	ALWAYS RETURN


PRTWDR::			;PRINT INCREMENTAL NO OF BLOCKS READ
DSKINC:	LDB	T1,JBYRCT##	;TOTAL NO OF READS(OR WRITES) FOR JOB
	LDB	T2,JBYIRD##	;INCREMENTAL SETTING(LOW ORDER N BITS
				; OR TOTAL NO.)
	DPB	T1,JBYIRD##	;UPDATE INCREMENTAL SETTING WITH CURRENT TOTAL
	SUB	T1,T2		;DIFFERENCE CUR TOTAL-LAST TOTAL
	ANDI	T1,JBRIRD##	;MASK OUT ALL BITS OUTSIDE INCREMENTAL FIELD
	PJRST	RADX10##	;PRINT DECIMAL AND RETURN
;COMMAND TO PRINT FILE STRUCTURES IN SYSTEM, AND UNITS NOT IN STRUCTURES
; (RESOURCES COMMAND)
DSKRES::PUSHJ	P,SAVE1##	;SAVE P1
	HLRZ	P1,SYSSTR##	;FIRST STR DATA BLOCK ADDRESS

DSKR1:	SKIPE	T2,STRNAM##(P1)	;FILE STRUCTURE NAME
	PUSHJ	P,NAMCOM	;TYPE NAME AND COMMA
	HLRZ	P1,STRSYS##(P1)	;NEXT STR LOC
	JUMPN	P1,DSKR1	;TYPE NAME IF THERE IS ONE


	HLRZ	P1,SYSUNI##	;ADDR OF 1ST UNIT IN SYSTEM
DSKR2:	MOVE	T2,UNINAM##(P1)	;PHYSICAL UNIT NAME
	EXCH	P1,U		;SETUP U FOR UNYUST
	LDB	T1,UNYUST##	;GET UNIT STATUS
	EXCH	P1,U		;RESTORE U FOR NAMCOM
	CAIN	T1,UNVDWN##	;DOWN OR DOESN'T EXIST?
	JRST	DSKR4		;YES, DON'T PRINT
	SKIPN	UNILOG##(P1)	;NO SKIP IF UNIT IS NOT IN A FILE STRUCTURE
	PUSHJ	P,NAMCOM	;YES, TYPE ITS NAME
DSKR4:	HLRZ	P1,UNISYS##(P1)	;STEP TO NEXT UNIT IN SYSTEM
	JUMPN	P1,DSKR2	;TEST IT IF NOT THE END
	POPJ	P,		;THROUGH - RETURN


;SUBROUTINE TO TYPE NAME AND COMMA    T2=SIXBIT NAME
NAMCOM:	PUSHJ	P,PRNAME##	;PRINT NAME
	JSP	T1,CONMES##	;THEN COMMA AND RETURN
	ASCIZ	/,/
;ROUTINE TO TURN OFF OPR MESSAGES FOR AN OFF-LINE DISK
;ENTER T1=(PHYSICAL) NAME
;NON SKIP-RETURN IF NOT A DISK OR NOT IN OPR WAIT
;SKIP-RETURN IF OK
DSKQUI::CAMN	T1,[SIXBIT /RIB/]
	JRST	DSKQU2
	CAMN	T1,[SIXBIT /DSKERR/]
	JRST	DSKQU3
	PUSH	P,U		;SAVE U
	PUSHJ	P,MSKUNI##	;GENERATE MASK FOR UNIT
	PUSHJ	P,SRUNI##	;FIND UNIT
	  PJRST	UPOPJ##		;NO MATCH
	  PJRST	UPOPJ##		;LOGICAL NAME MATCH - NOT GOOD ENOUGH
	MOVE	T1,UNISTS##(U)	;STATUS OF UNIT
	CAIE	T1,OCOD##	;IS IT OPR WAIT?
	PJRST	UPOPJ##		;NO, NON-SKIP RETURN
	MOVEI	T1,O2COD##	;YES
	PUSHJ	P,BTHSTS##	;STORE IT
	PJRST	UPOPJ1##	;SKIP RETURN

;HERE TO SET RIB-ERROR THRESHOLD
DSKQU2:	PUSHJ	P,DECIN1##	;GET THRESHOLD
	  POPJ	P,
	  POPJ	P,
	MOVEM	T2,RIBECT##	;SAVE
	PJRST	CPOPJ1##	; AND GOOD-RETURN


;HERE TO SET DSK ERROR THRESHOLD
DSKQU3:	PUSHJ	P,DECIN1##	;GET THRESHOLD
	  POPJ	P,
	  POPJ	P,
	MOVEM	T2,HERLIM##	;SAVE
	PJRST	CPOPJ1##	;AND GOOD RETURN
;SUBROUTINE TO CLEAN UP CORE ON A KJOB COMMAND
;CALLED AT CLOCK LEVEL IF NO CORE, UUO LEVEL IF CORE WHEN JOB IS KILLED
;CALL	MOVE J,JOB NUMBER
;	PUSHJ P,DSKKJB
DSKKJB::
	PUSHJ	P,SFDPPN	;FIND DEFAULTS FOR JOB
	JUMPE	T1,DSKKJ1	;NONE IF T1=0
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVE	P1,T4		;SAVE DEFLT PPN
	HLRZ	P2,T1		;SAVE DEFLT LOC (SFD OR PPB)
	SKIPE	T1,T2		;IS THERE A DEFAULT SFD?
	PUSHJ	P,DECALL	;YES, DECR. ALL USE-COUNTS FOR IT
	CAMN	P1,JBTPPN##(J)	;IS IT JOB'S PPN?
	JRST	DSKKJ1		;YES
	PUSHJ	P,FAKDDB	;NO, SET UP A FAKE DDB FROM FREE CORE
	  JRST	DSKKJ2
	MOVE	T1,P1		;GOR ONE, T1=DEFAULT PPN
	PUSHJ	P,PTHCHG	;DELETE CORE BLOCKS, REWRITE NEW QUOTA INFO
	PUSHJ	P,CLRDDB	;GIVE UP THE DDB
	MOVE	J,.CPJOB##	;RESET J
DSKKJ1:	HLRZ	P2,JBTSFD##(J)	;PPB OF LIB
	TRZ	P2,CORXTR##	;ZAP THE EXTRA BITS
	JUMPE	P2,DSKKJ2	;FORGET IT IF NO LIB
	PUSHJ	P,FAKDDB	;THERE IS - GET A DDB
	  JRST	DSKKJ2		;CANT GET ONE, CONTINUE
	MOVE	T1,PPBNAM##(P2)	;GET PPN OF LIB
	PUSHJ	P,PTHCHG	;FINISH UP IF NO OTHER JOBS USING
	PUSHJ	P,CLRDDB	; THE PPN NOW
DSKKJ2:	SKIPN	.USLNM		;ANY LOGICAL NAMES?
	JRST	DSKKJ5		;NO
	SETZ	T4,		;YES, START AT FIRST
DSKKJ3:	SKIPN	@.USLNM		;PICK UP NEXT LOGICAL NAME
	JRST	DSKKJ4		;DONE
	PUSHJ	P,PTKUDF	;UNDEFINE IT, RETURN FUNNY SPACE
	  JFCL
	AOJA	T4,DSKKJ3	;AND TRY NEXT
DSKKJ4:	MOVEI	T1,LNMMAX##+MAXLVL##+1 ;GIVE UP THE LOGICAL NAME TABLE SPACE
	HRRZ	T2,.USLNM
	PUSHJ	P,GVFWDS##
	SETZM	.USLNM
				;FALL INTO DSKKJ5
DSKKJ5:	MOVE	J,.CPJOB##	;RESET J
	SETZM	JBTSFD##(J)	;CLEAR DEFAULT DIRECTORY
	HLRZ	T2,.USSWI
	JUMPE	T2,DSKKJ6
	HRRZ	T1,SWILEN##(T2)	;FUNNY SPACE WHERE SWITCH.INI IS SAVED
	PUSHJ	P,GVFWDS##	;RETURN IT
	HRRZS	.USSWI
DSKKJ6:	MOVE	T1,JBTPPN##(J)	;GET PPN
	PUSHJ	P,ONLYTS	;IS THERE ANY JOB USING THIS PPN?
	  CAIA			;YES
	PUSHJ	P,DSKLGO	;NO, DELETE DISK 4-WORD CONTROL BLOCKS
	SCHEDULE		;TURN SCHEDULING BACK ON
	SKIPN	.USSBF		;WILL RETURN IT ELSEWHERE IF .UPSBF NON-0
	SKIPN	T1,.USMBF	;HAVE MON BUFF?
	POPJ	P,		;NO, THATS ALL
	SETZM	.USMBF

;SUBROUTINE TO RETURN MONITOR BUFFER
;ENTER WITH T1=LOC OF MON BUF-1
GVMNBF:	MOVEI	T2,1(T1)	;START ADR OF MON BUF
	MOVEI	T1,BLKSIZ##
	PUSHJ	P,GVFWDS##	;RETURN THE MONITOR BUFFER
	POPJ	P,		;AND EXIT
;SUBROUTINE TO FIX UP DATA BASE WHEN SET DATA/TIME COMMAND
;CALLED WITH T1 INCREMENTAL TIME TO FUDGE
;MUST PRESERVE T1!

FILSDT::
IFN FTMDA,<
	HLRZ	T2,SYSUNI##	;GET FIRST UNIT IN UDB CHAIN
SDT.1:	SKIPE	UNILTM##(T2)	;LOCK TIME SET?
	 ADDM	T1,UNILTM##(T2)	;YES--FIX IT UP
IFN FTDUAL,<
	SKIPE	T3,UNI2ND##(T2)	;DUAL PORTED?
	 SKIPN	UNILTM##(T3)	;YES--LOCK TIME SET?
	  CAIA			;NO
	   ADDM	T1,UNILTM##(T3)	;YES--FIX IT UP TOO
>;END IFN FTDUAL
	HLRZ	T2,UNISYS##(T2)	;GET NEXT UDB
	JUMPN	T2,SDT.1	;LOOP IF MORE
>;END FTMDA
	POPJ	P,		;AND RETURN
	SUBTTL	QUESER - INTERFACE ROUTINES

IFN FTEQDQ,<

;FILIRC	-- INCREMENT READER COUNT OF FILE
;CALL:
;	MOVE	T1,ACCESS-TABLE-ADDRESS
;	PUSHJ	P,FILIRC
;	RETURN HERE ALWAYS

FILIRC::PUSH	P,T2		;SAVE T2
	MOVEI	T2,ACPCNT##	;GET 1 FIELD FOR A.T. READ COUNT
	ADDM	T2,ACCCNT##(T1)	;INCREMENT READ COUNT SO FILE STAYS
	JRST	T2POPJ##	;RETURN

;FILDRC	-- DECREMENT READER COUNT OF FILE
;CALL:
;	MOVE	T1,ACCESS-TABLE-ADDRESS
;	PUSHJ	P,FILDRC
;	RETURN HERE ALWAYS

FILDRC::PUSH	P,T2		;SAVE T2
	MOVNI	T2,ACPCNT##	;-1 IN COUNT FIELD
	ADDM	T2,ACCCNT##(T1)	;DECREMENT READER COUNT IN A.T.
	JRST	T2POPJ##	;RETURN

;FILNDR	-- SET 'NO DELETE ON RESET' STATUS BIT
;CALL:
;	MOVE	T1,ACCESS-TABLE-ADDRESS
;	PUSHJ	P,FILNDR
;	RETURN HERE ALWAYS

FILNDR::PUSH	P,T2		;SAVE T2
	MOVEI	T2,ACPNDR##	;GET NO DELETE ON RESET BIT
	IORM	T2,ACCSTS##(T1)	;PUT IN STATUS WORD
	JRST	T2POPJ##	;RETURN

;FILGFC	-- CHECK TO SEE IF FILE IS A GHOST FILE
;CALL:
;	MOVE	T1,ACCESS-TABLE-ADDRESS
;	PUSHJ	P,FILGFC
;	  <IF FILE IS A GHOST FILE>
;	<IF FILE IS NOT A GHOST FILE>

FILGFC::PUSH	P,T2		;SAVE T2
	MOVE	T2,ACCSTS##(T1)	;GET A.T. STATUS
	TRNE	T2,ACPDEL##!ACPSUP!ACPCRE ;GHOST FILE? (BEING CREATED
				; OR SUPERSEDED)
	JRST	T2POPJ##	;YES, RETURN
	JRST	T2POJ1##	;NOT A GHOST FILE, SKIP RETURN

>;END IFN FTEQDQ
SUBTTL	DISK. UUO - MISC DISK FUNCTIONS

;CALLI AC,DISK.
;LH(AC)=FUNCTION RH(AC)=ADR

DSKUUO::HLRZ	T2,T1		;FUNCTION
	CAILE	T2,DUULEN	;LEGAL?
	PJRST	RTM1##		;NO, ERROR RETURN
	HRR	M,T1		;ADDRESS
	SKIPL	T2,DUUTBL(T2)	;PRIV'D?
	JRST	(T2)		;NO, DISPATCH
	PUSHJ	P,PRVJ##	;YES, CAN THIS JOB DO THE FUNCTION?
	  JRST	(T2)		;YES, DISPATCH
	PJRST	RTM2##		;NO, RETURN AC=-2

DUUTBL:	EXP	PRIUUO		;SET DISK PRIORITY
	XWD	400000,SETCPT##	;(1) SET 10/11 COMPATABILITY MODE
	XWD	400000,CLRCPT##	;(2) CLEAR 10/11 COMPATABILITY MODE
	XWD	400000,UNLOAD##	;(3) UNLOAD A DRIVE (RP04)
	XWD	400000,SOONDN##	;(4) TAKE CHAN/KONTROLLER OFF LINE SOON
	XWD	400000,NOWDWN##	;(5) TAKE CHAN/KONTROLLER OFF LINE NOW
	XWD	400000,NOWUP##	;(6) PUT CHAN/KONTROLLER BACK ON LINE
	XWD	0,CMPRSS	;(7) SET TO CALL UFD COMPRESSOR
	XWD	400000,REMSWP##	;(10) REMOVE A SWAPPING UNIT
	XWD	400000,ADDSWP##	;(11) ADD A SWAPPING UNIT
	XWD	400000,SDLADD	;(12) ADD STRUCTURE TO SYSTEM DUMP LIST
	XWD	400000,SDLREM	;(13) REMOVE STRUCTURE FROM SYSTEM DUMP LIST
	XWD	0,LENGTH	;(14) TELL LENGTH OF FILE
IFN FTMDA,<
	XWD	400000,CLRMDA##	;(15) CLEAR A DISK UNIT FROM MDA
>
IFE FTMDA,<
	XWD	400000,CPOPJ1## ;(15) FEATURE TEST OFF
>
	XWD	0,GGUFBT##	;(16) GET UFBTAL FOR STR:[P,PN]
DUULEN==.-DUUTBL-1
;ERROR CODES RETURNED BY DISK. UUO FUNCTIONS 12 AND 13

DUDND%==1		;NO SUCH STRUCTURE
DUDNC%==2		;NO CRASH SPACE ON STRUCTURE
DUDAD%==3		;STRUCTURE ALREADY IN SYSTEM DUMP LIST
DUDDF%==4		;SYSTEM DUMP LIST FULL
DUDNS%==1		;STRUCTURE NOT IN SYSTEM DUMP LIST


ERCODE	DSUNSS,DUDND%
ERCODE	DSUNKC,DUDNC%
ERCODE	DSUADL,DUDAD%
ERCODE	DSUDLF,DUDDF%
ERCODE	DSUNDL,DUDNS%
; DISK. UUO FUNCTION 12 - ADD A STRUCTURE TO THE SDL

SDLADD:	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,GETWDU##	;GET THE SIXBIT STR NAME
	PUSHJ	P,SRSTR##	;FIND STR DATA BLOCK
	  JRST	DSUNSS		;NO SUCH STRUCTURE
	MOVE	P1,T3		;COPY TO A SAFE PLACE
	HRRZ	T1,STRK4C##(P1)	;GET K FOR CRASH
	JUMPE	T1,DSUNKC	;NO CRASH SPACE
	SKIPL	STRSDL##(P1)	;ALREADY IN THE SDL?
	  JRST	DSUADL		;YES--ERROR
	PUSHJ	P,SDLFRE	;FIND THE FIRST FREE ENTRY
	  JRST	DSUDLF		;ERROR IF SDL IS FULL
	MOVEM	T2,STRSDL##(P1)	;STORE POSITION IN THE STR DB
	PUSHJ	P,SDLBLD##	;REBUILD THE PRESERVED SDL
	  JFCL			;BOOTSTRAP NOT AVAILBLE
	PUSHJ	P,FRCCPY##	;COPY ANY UNPROCESSED DUMP ON THIS STR
	JRST	CPOPJ1##	;RETURN


; DISK. UUO FUNCTION 13 - REMOVE A STRUCTURE FROM THE SDL

SDLREM:	PUSHJ	P,GETWDU##	;GET SIXBIT STRUCTURE NAME
	PUSHJ	P,SDLCHK	;SEE IF IT'S IN THE SDL
	  JRST	DSUNDL		;IT'S NOT
	SETOM	STRSDL##(T3)	;REMOVE FROM THE SDL
	PUSHJ	P,SDLBLD##	;REBUILD THE PRESERVED SDL
	  JRST	DSUNDL		;NO BOOTSTRAP
	JRST	CPOPJ1##	;RETURN


; CHECK FOR A STR IN THE SDL
SDLCHK:	PUSHJ	P,SRSTR##	;FIND THE STR WITH THIS NAME
	  POPJ	P,		;NOT IN SDL IF DOESN'T EXIST
	SKIPL	STRSDL##(T3)	;IF STR IS IN SDL,
	AOS	(P)		;THEN SKIP
	POPJ	P,		;RETURN


; FIND THE FIRST FREE POSITION IN THE SDL
SDLFRE:	SETZ	T1,		;INIT MASK
	MOVEI	T2,DIFSTR##	;GET PRDECESSOR OF SYSSTR
SDLFR1:	HLRZ	T2,STRSYS##(T2)	;GET NEXT STR IN SYSTEM
	JUMPE	T2,SDLFR2	;DONE SEARCHING IF NO MORE
	SKIPGE	T3,STRSDL##(T2)	;GET STR'S POSITION IN THE SDL
	JRST	SDLFR1		;NOT IN THE SDL
	ANDI	T3,77		;PARANOIA
	IOR	T1,BITTBL##(T3)	;INCLUDE THIS BIT
	JRST	SDLFR1		;LOOP OVER ALL STR DB'S
SDLFR2:	SETCA	T1,		;FLIP BITS
	JFFO	T1,CPOPJ1##	;RETURN FIRST FREE POSITION
	POPJ	P,		;NON-SKIP IF FULL
IFE FTDPRI,<
PRIUUO==CPOPJ##
>
IFE FTDUFC,<
CMPRSS==CPOPJ##
>
IFN FTDUFC,<
CMPRSS:	PUSHJ	P,SAVE1##
	PUSHJ	P,GETWDU##	;GET CHAN
	MOVE	P1,T1		;WHERE WE EXPECT CHAN
	PUSHJ	P,VALUUO##	;SET UP F
	  POPJ	P,		;NO OPEN DISK ON THAT CHAN
	HRRZ	T1,DEVUFB##(F)
	JUMPE	T1,CPOPJ1##	;FORGET IT IF NO OPEN FILE
	MOVSI	T2,UFPZRB##	;LIGHT A BIT TO CALL
	IORM	T2,UFBZRB##(T1)	;COMPRESSOR AT NOTOLD
	JRST	CPOPJ1##	;AND RETURN
>

;FUNCTION TO RETURN LENGTH OF A FILE
LENGTH:	PUSHJ	P,GETWDU##	;CHAN
	PUSHJ	P,SAVE1##
	MOVE	P1,T1
	PUSHJ	P,VALUUO##	;SET UP F
	  PJRST	ECOD2##		;NOT A DISK
	HRRZ	T1,DEVACC##(F)
	JUMPE	T1,ECOD1##	;NO OPEN FILE
	MOVE	T1,ACCWRT##(T1)	;SIZE OF FILE
	AOS	(P)
	PJRST	STOTAC##	;TELL USER AND RETURN
IFN FTDPRI,<
PRIUUO:	HRR	M,T1		;LOC OF ARGUMENT
	PUSHJ	P,GETWDU##	;GET IT
	HRRE	T2,T1		;PRIORITY HE'S TRYING TO SET
	PUSHJ	P,PRCHK		;LEGAL?
	  PJRST	ECOD1##		;NO, NON-SKIP
	PUSHJ	P,SAVE1##
	MOVSI	T3,DVDSK
	HLRE	T1,T1		;YES, GET CHAN NUMBER
	TRO	T2,DEPUUO	;LIGHT THE SET-BY-UUO BIT
	JUMPL	T1,PRIUU1	;IS IT A REAL CHAN?
	MOVE	P1,T1		;YES, LEGAL?
	PUSHJ	P,SETUF##	;YES, IS A FILE OPEN ON THE CHAN?
	  PJRST	ECOD2##		;NO, NON-SKIP RETURN
	PUSHJ	P,PRIDEP	;YES, SAVE NEW PRIORITY IN DDB
	PJRST	CPOPJ1##	;AND RETURN

;HERE IF CHAN IS NEGATIVE
PRIUU1:	AOJE	T1,PRIUU3	;GO IF LH(ADR)=-1
	AOJN	T1,ECOD3##	;ERROR IF LH NOT=-2
PRIUU2:	DPB	T2,JBYPRI##	;-2, SET JOB'S DISK PRIORITY
	PJRST	CPOPJ1##	;AND GOOD RETURN

;HERE IF SETTING PRIORITY FOR ALL OPEN CHANS
PRIUU3:	SETZ	P1,		;NO OF OPEN CHANS
PRIUU4:	PUSHJ	P,NXTCH##	;THIS CHAN OPEN?
	  JRST	CPOPJ1##
	MOVE	F,T1
	PUSHJ	P,PRIDEP	;YES, SET PRIORITY IN DDB
	JRST	PRIUU4		;LOOP FOR ALL CHANS
PRICOM::PUSHJ	P,PRCHK		;HERE ON COMMAND.  LEGAL?
	  POPJ	P,		;NO
	JRST	PRIUU2		;YES, SET JOB'S PRIORITY AND EXIT

;SUBROUTINE TO DETERMINE IF SETTING DISK PRIORITY IS LEGAL
;ENTER T2=DESIRED PRIORITY
;EXIT CPOPJ IF NO, CPOPJ1 IF YES
;PRESERVES T1
PRCHK:	LDB	T3,JBZPRI##	;MAX PRIORITY JOB CAN SET
	CAMLE	T2,T3		;TRYING TO SET HIGHER?
	POPJ	P,		;YES, ERROR RETURN
	JUMPGE	T2,CPOPJ1##	;NO, OK IF POSITIVE
	MOVMS	T2		;NEGATIVE.  GET +N
	CAILE	T2,3		;TO LOW?
	MOVEI	T2,3		;YES, SET MAX NEGATIVE VALUE
	TRO	T2,MINDPR	;SET THE NEGATIVE-BIT
	PJRST	CPOPJ1##	;AND TAKE GOOD RETURN

;SUBROUTINE TO SET DISK PRIORITY
PRIDEP:	TDNE	T3,DEVMOD(F)	;IS IT A DISK?
	DPB	T2,DEXPRI##	;YES, SET PRIORITY
	POPJ	P,
>	;END FTDPRI CONDITIONAL
SUBTTL	INPUT/OUTPUT UUO'S

;BUFFERRED MODE INPUT

INPT:	PUSHJ	P,NULTST	;IF NULL DEVICE,
	  JRST	SETION		; RETURN EOF
IFN FTSPL,<
	PUSHJ	P,SPTSTI	;SEE IF 1ST SPOOLED INPUT
	  PJRST	SETION		;YES, AND NO FILE - SET IOEND
>
	TLNE	S,IOSUPR	;SUPER USETI DONE?
	JRST	INPSW9		;YES

	TLNN	F,LOOKB		;LOOKUP BEEN DONE?
	PJRST	SETIMP		;NO, LIGHT IOIMPM AND RETURN
INPSW9:	TLZ	S,IO		;NO. INDICATE INPUT
	MOVEM	S,DEVIOS(F)	;SAVE S
	PUSHJ	P,SAVE2##	;SAVE SOME ACS
	PUSHJ	P,UUOSET##	;SET DDB PNTRS FOR THIS BLOCK
	  JRST	INPT1		;EOF. LIGHT A BIT
	MOVE	T1,DEVFIL(F)
	HLRZ	T2,DEVEXT(F)
	CAMN	T1,[SIXBIT /SWITCH/]
	CAIE	T2,'INI'	;READING SWITCH.INI?
	PJRST	UUOPWQ##	;NO. GO QUEUE REQUEST
	MOVE	T4,.CPJOB##	;YES, READING THIS JOB'S SWITCH.INI?
	MOVE	T4,JBTPPN##(T4)
	SKIPN	DEVSFD##(F)
	CAME	T4,DEVPPN(F)
	JRST	UUOPWQ##	;NO, GO DO NORMAL STUFF
;HERE WHEN USER IS READING SWITCH.INI. WORRY ABOUT IN-CORE COPY
	PUSHJ	P,SAVE3##
	HLRZ	P1,.USSWI	;LOC OF FUNNY-SPACE SWITCH.INI
	HRRZ	P2,DEVACC##(F)	;AT FOR ONE WE JUST LOOKED UP
	MOVE	T2,P2
	LDB	T1,ACYLBS##	;SIZE OF LOOKED-UP COPY
	MOVE	P3,ACCWRT##(P2)
	SUBI	P3,1
	LSH	P3,BLKLSH##	;SIZE IN WORDS OF SWITCH.INI
	ADD	P3,T1
	HRL	P3,ACCUN1##(P2)	;UNIT OF LOOKED-UP COPY
	JUMPE	P1,INPSW1	;GO IF NO FUNNY-SPACE COPY
	MOVE	T1,ACCPRV##(P2)	;PRIVS/CREATION DATE,TIME
	CAME	T1,SWIPRV##(P1)	;MATCH?
	JRST	INPSW1		;NO, READ NEW ONE INTO FUNNY SPACE
	MOVE	T1,ACCPT1##(P2)	;1ST PNTR OF FUNNY-SPACE COPY
	CAMN	T1,SWIPT1##(P1)	;ARE THEY THE SAME?
	CAME	P3,SWIUN1##(P1)
INPSW1:	SKIPA	T1,DEVREL##(F)	;NO, SET TO COPY TO FUNNY SPACE
	JRST	INPSW7		;YES, GIVE FUNNY COPY TO USER
	SOJN	T1,UUOPWQ##	;JUST READ FILE IF NOT 1ST BLOCK (TOO LARGE)
	JUMPE	P1,INPSW3	;GO IF DON'T ALREADY HAVE ONE
	PUSHJ	P,GETNMB	;ALREADY HAVE ONE IN FUNNY SPACE
	HLRZ	T1,NMBACC##(T1)
INPSW2:	CAIE	T1,(P2)		;LOOK FOR AN A.T.
	SKIPE	ACCDOR##(T1)	;IF NOT OURS AND NOT DORMANT
	SKIPA	T2,P1
	JRST	UUOPWQ##	; WE CAN'T GET RID OF THIS COPY
	HLRZ	T1,ACCNMB##(T1)
	TRNN	T1,DIFNAL##	;LOOK FOR ANOTHER A.T.
	JRST	INPSW2
	HRRZ	T1,SWILEN##(P1)	;YES, RETURN IT
	PUSHJ	P,GVFWDS##
	HRRZS	.USSWI		;CLEAR POINTER TO IT
				;FALL INTO INPSW3
INPSW3:	MOVE	T2,ACCWRT##(P2)	;SIZE OF CURRENT SWITCH.INI
	CAILE	T2,3		;TOO LARGE TO FIT?
	PJRST	UUOPWQ##	;YES, JUST PLAIN READ INTO USER SPACE
	LSH	T2,BLKLSH##	;FITS FINE. COMPUTE NO OF WORDS WE NEED
	ADDI	T2,SWIDAT##
	MOVE	P1,T2		;SAVE LENGTH
	PUSHJ	P,GTFWDC##	;GET SPACE FOR IT
	  PJRST	UUOPWQ##	;OH WELL, JUST READ INTO USER SPACE
	EXCH	P1,T1		;SAVE LOC, GET LENGTH
	HRLM	P1,.USSWI	;SAVE LOC IN UPMP
	MOVEM	P3,SWIUN1##(P1)	;SAVE UN1,,NO OF WORDS
	MOVEM	T1,SWILEN##(P1)	;SAVE NUMBER OF FUNNY-SPACE WORDS WE HAVE
	MOVE	T1,ACCPT1##(P2)
	MOVEM	T1,SWIPT1##(P1)	;SAVE RETIREVAL POINTER
	MOVE	T1,ACCPRV##(P2)	;SAVE CREATION DATE,TIME
	MOVEM	T1,SWIPRV##(P1)
	PUSHJ	P,GTMNBF##	;NOW READ SWITCH.INI INTO FUNNY SPACE
INPSW4:	MOVE	T2,DEVBLK##(F)	;READ A BLOCK
	PUSHJ	P,MONRDU##	;READ NOT FROM DISK CACHE
	JUMPN	T3,INPSW5	;LOSE IF IO ERROR
	MOVE	T2,DEVREL##(F)	;RELATIVE BLOCK OF FILE
	LSH	T2,BLKLSH##	;COMPUTE WHERE IT GOES IN FUNNY SPACE
	CAMLE	T2,SWILEN##(P1)	;IF ABOVE TOP
	JRST	INPSW5		; SOME OTHER JOB IS MAKEING IT LARGER
	ADDI	T2,SWIDAT##-BLKSIZ##(P1)
	HRLI	T2,1(T1)
	MOVE	T1,T2		;SAVE IT IN USER'S SPACE
	BLT	T2,BLKSIZ##-1(T1)
	AOS	DEVREL##(F)	;POINT TO NEXT BLOCK OF FILE
	AOS	DEVBLK##(F)
	SOS	DEVLFT##(F)
	PUSHJ	P,UUOSET##	;SET TO READ NEXT BLOCK
	  JRST	INPSW6		;EOF
	MOVE	T1,.USMBF	;NEXT BLOCK IS THERE - GO READ IT
	JRST	INPSW4
;HERE ON IO ERROR READING SWITCH.INI
INPSW5:	PUSHJ	P,INPSW8	;RESET DDB TO POINT AT 1ST BLOCK
	HRRZ	T2,P1
	HRRZ	T1,SWILEN##(P1)
	PUSHJ	P,GVFWDS##	;RETURN THE FUNNY SPACE
	HRRZS	.USSWI
	PJRST	UUOPWQ##	; AND READ INTO USER'S AREA

;HERE WHEN ALL OF SWITCH.INI IS IN CORE
INPSW6:	TRNE	S,IOIMPM+IOBKTL+IODTER+IODERR  ;ANY ERRORS?
	JRST	INPSW5		;YES
	PUSHJ	P,INPSW8	;RESET DDB TO POINT AT 1ST BLOCK OF FILE

;HERE TO READ FIRST (OR NEXT) BLOCK OF SWITCH.INI
INPSW7:	SKIPN	T3,DEVREL##(F)
	PJRST	UUOPWQ##	;READING RIB (DIRECT) IF 0
	SUBI	T3,1		;CONVERT BLOCK NUMBER
	LSH	T3,BLKLSH##	;TO WORD COUNT
	HRRZ	T4,SWIUN1##(P1)	;TOTAL LENGTH OF FILE
	SUB	T4,T3		;NUMBER OF WORDS LEFT TO READ
	HRRZ	T2,DEVIAD(F)	;GET THE USER'S BUFFER ADDRESS
	EXCTXU	<HLRZ T1,(T2)>	;GET THE BUFFER SIZE
	ADDI	T2,2		;POINT TO THE BUFFER DATA
	SUBI	T1,1		;GET RID OF OVERHEAD
	CAMLE	T4,T1		;READING LAST BLOCK?
	MOVE	T4,T1		;NO.  READ A WHOLE BUFFER
	EXCTXU	<MOVEM T4,-1(T2)> ;STORE AS WORDCOUNT OF FILE
	ADDI	T4,BLKSIZ##-1	;ROUND UP TO THE
	ANDI	T4,MBLKSZ##	; NUMBER OF BLOCKS THIS IS
	ADDI	T3,SWIDAT##(P1)	;POINT TO THE SOURCE OF THE DATA
	HRL	T2,T3		;SET UP BLT POINTER
	HRRZ	T1,T2		;COPY THE BUFFER POINTER
	ADDI	T1,-1(T4)	;COMPUTE LAST WORD TO WRITE
	EXCTXU	<BLT T2,(T1)>	;COPY CURRENT BLOCK TO USER SPACE
	LSH	T4,-BLKLSH##	;CONVERT WORD COUNT TO BLOCK COUNT
	ADDM	T4,DEVBLK##(F)	;POINT DDB AT NEXT BLOCK
	ADDM	T4,DEVREL##(F)
	MOVNS	T4		;NEGATE BLOCK COUNT
	ADDM	T4,DEVLFT##(F)
	PUSHJ	P,ADVBFF##	;TELL UUOCON THE BUFFER IS FULL
	  JFCL
	JRST	CPOPJ1##	;AND GO AWAY HAPPY

;SUBROUTINE TO RESET TO READ 1ST BLOCK OF SWITCH.INI
INPSW8::HRRZ	T3,DEVACC##(F)	;POINT TO ACCESS TABLE
	PUSHJ	P,AT2DDB##	;RESET TO FIRST BLOCK
	  JFCL			;ALLOW IT TO PROPAGATE
	PJRST	CPZPTR##	;AND COPY
;HERE ON EOF (KEEP GOING IF CONTINUED DIRECTORY)
INPTU:	PUSHJ	P,UUOSET##
INPT1:	  TLOA	S,IOEND		;LIGHT EOF BIT
	PJRST	UUOPWQ##
;IF THE FILE BEING READ IS A DIRECTORY, NO EOF TILL ALL STR'S LOOKED AT
	MOVE	T1,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,ACCDIR##(T1)
	TRNE	T1,ACPDIR##	;A DIRECTORY?
	PUSHJ	P,SETSRC##	;YES. GET SEARCH LIST
	  PJRST	STOIOS##	;NO. REAL EOF
	PUSH	P,T1		;SAVE SL PTR
	SETZ	P1,		;COUNT NUMBER OF STRS IN SL
	MOVE	P2,T1
UFDSR5:	PUSHJ	P,SLITA##
	 SKIPA	P2,(P)		;RESET SL PTR
	AOJA	P1,UFDSR5
	SOJE	P1,UFDSR3	;ONLY ONE STR, LEAVE THINGS ALONE
;HERE WITH P1 NON-0
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
	LDB	T1,ACYFSN##	;CURRENT STR NUMBER
	PUSHJ	P,SLFNA##	;FIND IT IN SEARCH LIST
	  JRST	UFDSR3		;DONE IF NOT THERE

;P2 NOW HAS PREDECREMENTED PTR TO NEXT STR (FOR CALL TO FNDFIL BELOW)
	PUSHJ	P,SFDUP		;BUMP PPBCNT AND NMBCNT
	HRRZ	T1,DEVSFD##(F)	;BUMP ALL ACC'S
	SKIPE	T1
	PUSHJ	P,INCALL
	PUSHJ	P,CLOSIN	;CLOSE CURRENT A.T.
UFDSR6:	TLZ	M,UUOMSK	;SET UUO TO LOOK LIKE A LOOKUP
	TLO	M,UUOLUK
	MOVEI	T2,0		;FORCE RECOMPUTING
	DPB	T2,DEYFNC##
	MOVE	T2,P2		;SEARCH LIST INTO T2
	PUSHJ	P,FNDFLA##	;LOOK FOR UFD ON NEXT STR'S IN SYSTEM
	  JRST	UFDSR4		;NO DIRECTORY ON NEXT STRS
;STILL IN FTSTR CONDITIONAL
	PUSHJ	P,DECMST	;DECR ALL BUT THE RIGHT ACC
	POP	P,P2		;RETURN POSSIBLE TEMP SL. (SETSRC CALL)
	PUSHJ	P,SLGVT##
	TLO	F,LOOKB		;FOUND ONE. SET F AS IF LOOKUP HAPPENED
	HRRZ	T3,DEVACC##(F)	;LOC OF A.T.
	PUSHJ	P,AT2DDB##	;COPY DATA FROM A.T. TO DDB
	  JRST	STOIOS##	;A.T. DATA IS VERY WRONG
	JUMPE	P1,STOIOS##	;JUST RE-OPENED 1ST STR, GIVE EOF RETURN
	TLZ	S,IOEND		;IT ISN'T REALLY AN EOF YET
	PJRST	INPTU		;DO 1ST INPUT ON NEW DIRECTORY FILE
;HERE WHEN SL IS EXHAUSTED
UFDSR4:	MOVE	P2,(P)		;RESET SL PTR TO BEGINING
	TRZE	P1,-1		;1ST TIME HERE?
	JRST	UFDSR6		;YES, RE-OPEN 1ST STR (SO REWIND WORKS)
	PUSHJ	P,JDAADR##	;2ND TIME (STR YANKED)
	HLLM	F,(T1)		;CLEAR LOOKB IN USRJDA
	SETZM	DEVUNI##(F)	;FILE IS LEFT CLOSED SO USETI UUO
				;WOULD BE INTERPRETED AS SUPER USETI.
				;ZERO DEVUNI TO MAKE USETI FAIL.
	PUSHJ	P,DECSFD	;DECR ALL ACC'S
	PUSHJ	P,SFDDEC	;DECR PPBCNT AND NMBCNT
	PUSHJ	P,TSTPPB	;DELETE CORE BLOCKS FOR THE PPN
				;AND FALL INTO UFDSR3

UFDSR3:	POP	P,P2		;RETURN TEMP SL. (IF ANY)
	PUSHJ	P,SLGVT##
	PJRST	STOIOS##	;AND RETURN NO MORE UFDS
;BUFFERRED MODE OUTPUT

OUTPT:	PUSHJ	P,NULTST	;IF NUL:,
	  JRST	OUTPT1		; EAT OUTPUT
IFN FTSPL,<
	PUSHJ	P,SPTSTO	;SEE IF 1ST SPOOLED OUTPUT
	  PJRST	SETIMP		;YES, AND ERROR ON ENTER - SET IOIMP
>
	TLNE	F,ENTRB		;ENTER BEEN DONE?
	TLNE	S,IOSWLK+IOSUPR	;YES. STR WRITE-LOCKED?
	JRST	SETIMP		;YES. SET IOIMPM
	SKIPG	DEVREL##(F)	;TRYING TO WRITE A RIB (USETI 0 OR -N/OUTPUT)
	JRST	SETBTL		;YES. LIGHT IOBKTL AND RETURN
	PUSHJ	P,TSTSFD	;MAKE SURE NOT DOING OUTPUT TO AN SFD OR UFD
	  JRST	SETIMP		; (CAN'T ENTER *.SFD IF FTSFD=0)
	HRRZ	U,DEVUNI##(F)
	PUSHJ	P,WTRBIC##	;REWRITE RIB IF CHANGED, USER WANTS IT
				; (FROM A PREVIOUS OUTPUT)
	TLO	S,IO		;NO. INDICATE OUTPUT
	MOVEM	S,DEVIOS(F)	;SAVE S
	PUSHJ	P,UUOSET##	;SET DDB PNTRS FOR THIS OPERATION
	  JRST	SETBTL		;QUOTA EXHAUSTED
	PUSHJ	P,CHKLBK	;CHECK FOR LAST BLOCK OF APPEND-ONLY
	  JRST	SETBTL		;NOT ALLOWED
	  PJRST	UUOPWQ##	;OK, GO QUEUE REQUEST
	POPJ	P,		;ALREADY DONE
OUTPT1:	PUSHJ	P,ADVBFE##	;NULL DEVICE-EAT THE BUFFER
	  JFCL
	POPJ	P,		;AND RETURN

;DUMP MODE INPUT

DMPIN:	PUSHJ	P,NULTST	;IF NUL:,
	  JRST	SETION		; RETURN EOF
IFN FTSPL,<
	PUSHJ	P,SPTSTI	;SEE IF 1ST INPUT IN SPOOL MODE
	  PJRST	SETION		;YES, AND NO FILE - SET IOEND
>
	TLNE	S,IOSUPR	;SUPER USETI DONE?
	JRST	DMPIN1		;YES. DON'T CHECK POINTERS

	TLNN	F,LOOKB		;LOOUP BEEN DONE?
	PJRST	SETIMP		;NO. LIGHT IOIMPM AND RETURN
DMPIN1:	TLZ	S,IO		;NO. INDICATE INPUT
	JRST	DUMPST		;AND CONTINUE

;SUBROUTINE TO MAKE SURE AN OUTPUT UUO ISNT BEING DONE TO AN SFD OR UFD
TSTSFD:	HLRZ	T1,DEVEXT(F)
	CAIE	T1,(SIXBIT .SFD.)	;AN SFD?
	CAIN	T1,(SIXBIT /UFD/)	;OR UFD?
	SOS	(P)		;YES, YOU LOSE
	PJRST	CPOPJ1##
;DUMP MODE OUTPUT

DMPOUT:	PUSHJ	P,NULTST	;IF NUL,
	  POPJ	P,		; DONT WRITE ANYTHING
IFN FTSPL,<
	PUSHJ	P,SPTSTO	;SEE IF 1ST OUTPUT IN SPOOL MODE
	  PJRST	SETIMP		;YES, AND ERROR ON ENTER - SET IOIMPM
>
	TLNE	S,IOSUPR	;SUPER USETO DONE?
	JRST	[SKIPE	U,DEVUNI##(F)	;IF UNIT ISNT IN AN STR
		 SKIPE	UNILOG##(U)	; THEN WRITE HEADERS IS LEGAL
		 TRZN	S,UDSX		;IF IN AN STR,
		 JRST	DMPOU1
		 JRST	SETIMP]		;WRITE HEADERS IS A NO-NO

	TLNE	F,ENTRB		;ENTER BEEN DONE?
	TLNE	S,IOSWLK	;YES. STR WRITE LOCKED?
	JRST	SETIMP		;YES. SET IOIMPM
	SKIPG	DEVREL##(F)	;NO. TRYING TO WRITE A RIB (USETI 0 OR -N/OUTPUT)
	JRST	SETBTL		;YES. LIGHT IOBKTL AND RETURN
	PUSHJ	P,TSTSFD	;MAKE SURE NOT OUTPUTTING TO AN SFD
	  JRST	SETIMP		;YES WE ARE, ILLEGAL
DMPOU1:	TLO	S,IO		;NO. INDICATE OUTPUT

DUMPST:	PUSHJ	P,SAVE1##

DUMPGO:	MOVEM	S,DEVIOS(F)	;SAVE S
	PUSH	P,S		;FILSER ALWAYS RETURNS TO UUO
				;LEVEL FOR EACH IOWD. HENCE WE DO
				;NOT SAVE THE LIMITS OR FLAG, AND WE
	PUSHJ	P,COMCHK##	;RECOMPUTE THE LIMITS. COMCHK RETURNS
				;HERE WITH S=0 IF OK,-1 IF ERROR
				;P AND P1 CONTAIN THE LIMITS, BUT WE
	JUMPE	S,DUMPG1	;THROW THEM AWAY. JUMP IF NO ERROR
	POP	P,S		;THERE WAS AN ERROR
	TRZ	S,UDSX		;MAKE SURE FORMAT-SWITCH IS OFF
	MOVEM	S,DEVIOS(F)

	JRST	ADRERR##	;RESTORE S AND GO REPORT IT
;HERE WHEN THE IO LIST HAS BEEN CHECKED, M POINTS TO LIST
DUMPG1:	POP	P,S		;RESTORE S WHEN NO ERROR
	MOVE	P1,T1		;SAVE UNRELOCATED IOWD
	JUMPN	T1,DUMPG3	;IF IOWD GO ON TO DO IT
	SETZM	DEVDMP##(F)	;THROUGH - ZERO DEVDMP
	TRZ	S,UDSX		;MAKE SURE WRITE-FORMAT OFF

	PUSHJ	P,WTRBIC##	;REWRITE RIB IF CHANGED, USER WANTS IT
	PJRST	STOIOS##	;AND RETURN TO USER


;HERE TO DO A RETRY AT UUO LEVEL
DUMPG9:	HLRZ	T1,DEVUVA##(F)	;REBUILD THE IOWD
	SUBI	T1,(P1)
	HRLS	T1
	ADD	T1,P1
DUMPG3:	HLLZM	T1,DEVDMP##(F)	;STORE -NO OF WORDS LEFT, CORE ADR=0
				;RH GETS SET BELOW AT DUMPG5
	PUSHJ	P,UUOSET##	;SET DDB POINTERS FOR THIS OPERATION
	  JRST	DUMPG8		;EOF OR QUOTA EXHAUSTED
	HLRE	T2,P1		;-NO OF WORDS LEFT TO GO IN THIS IOWD
	HLRE	T1,DEVDMP##(F)	;-NO OF WDS TOTAL IN THIS IOWD
	SUBM	T2,T1		;-NO OF WDS DONE SO FAR IN THIS IOWD
	MOVNS	T1		;+NO OF WDS DONE SO FAR IN THIS IOWD
	HRLS	T1		;SET TO UPDATE ORIGINAL IOWD
	ADD	T1,P1		;INCREMENT BOTH HALVES BY TOTAL SO FAR

	HRRM	T1,DEVDMP##(F)	;STORE ABS ADR FOR DATA TRANSFER
				; (RH ALREADY SET -IGNORE OVERFLOW FROM LH)
	HRLM	T1,DEVUVA##(F)	;SAVE FOR COMPUTING THE CHECKSUM
	PUSHJ	P,CHKLBK	;CHECK FOR LAST BLOCK OF APPEND ONLY
	  JRST	SETBTL
	PUSHJ	P,UUOPWQ##	;OK - GO QUEUE REQUEST
	PUSHJ	P,PWAIT1##	;WAIT FOR IO TO FINISH
	TLZE	S,IOSTBL	;TROUBLE?
	JRST	DUMPG9		;YES, RETRY AT UUO LEVEL
	MOVE	T1,DEVDMP##(F)	;THIS COMMAND DONE?
	TLNE	T1,-1
	JRST	DUMPG3		;NO. CONTINUE WITH THIS IOWD
	MOVEM	P1,DEVDMP##(F)	;PUT ORIGINAL IOWD BACK
	TLC	S,IO!IOSUPR	;SUPER OUTPUT
	TLCN	S,IO!IOSUPR	;?
	  PUSHJ	P,CSDELI##	;YES--DELETE THIS IOWD FROM CACHE

	HRRZ	T1,DEVACC##(F)	;GET LOC OF A.T.
	JUMPE	T1,DUMPG7	;GO ON IF NO A.T.
	MOVE	T1,ACCWRT##(T1)	;NO OF BLOCKS WRITTEN
	CAMGE	T1,DEVREL##(F)	;IS THIS THE LAST BLOCK OF THE FILE?
	TLNN	S,IO		;YES, WRITING?
DUMPG7:	AOJA	M,DUMPGO	;NO. GO GET NEXT IOWD AND CHECK IT
	HLRE	T1,P1		;YES. GET WORDCOUNT OF IOWD
	MOVNS	T1		;+N
	TRNE	T1,BLKSIZ##-1	;AN EVEN MULTIPLE OF BLKSIZ WORDS?
	TRZA	T1,BLKSIZ##	;NO. MAKE SURE COUNT LT 200
	MOVEI	T1,BLKSIZ##	;YES. MAKE SURE ONLY BLKSIZ IS ON
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
	DPB	T1,ACYLBS##	;SAVE WORDCOUNT OF LAST BLOCK
	AOJA	M,DUMPGO	; GO GET NEXT IOWD AND CHECK IT
;HERE ON AN ERROR RETURN FROM UUOSET
DUMPG8:	TLNE	S,IO		;INPUT?
	JRST	SETBTL		;NO, QUOTA EXHAUSTED, DISK FULL
SETION:	TDO	S,[XWD IOEND,IODEND]	;YES. EOF
	PJRST	STOIOS##	;SAVE S AND RETURN TO CALLER




;HERE ON AN OUTPUT REQUEST TO RELATIVE BLOCK 0 OF THE FILE
;(OCCURS AFTER USETI/USETO 0)
SETBTL:	TROA	S,IOBKTL	;LIGHT IOBKTL
;HERE ON AN OUTPUT REQUEST TO A WRITE-LOCKED STR
SETIMP::TRO	S,IOIMPM	;LIGHT WRITE-LOCK ERROR BIT
	PJRST	STOIOS##	;SAVE S AND RETURN TO CALLER
;ROUTINE TO CHECK IF WRITING LAST BLOCK OF APPEND ONLY FILE.
;DO NOT ALLOW THE USER TO ALTER THE PORTION OF THE BLOCK
;WHICH WAS PREVIOUSLY WRITTEN.
;READ THE LAST BLOCK INTO A MONITOR BUFFER, AND COPY
;THE FIRST PORTION INTO THE USER'S BUFFER. THUS IF THE
;USER IS ATTEMPTING TO ALTER THE FIRST PORTION, HIS DATA WILL
;BE OVERWRITTEN WITH THE CORRECT VALUES.
;RETURN CPOPJ IF TRANSFER IS NOT TO BE ALLOWED.
;I.E. NEW BUFFER IS SMALLER THAN OLD.
;RETURN CPOPJ1 IF IT'S OK TO LET HIM DO THE TRANSFER
;RETURN CPOPJ2 IF TRANSFER IS ALREADY DONE (CAN ONLY HAPPEN IN BUFFERED).
CHKLBK:	TLNE	S,IO		;WRITING?
	TLNE	S,IOSUPR	;AND NOT SUPER?
	JRST	CPOPJ1		;NO, OK
	LDB	T1,DEYFNC##	;PROTECTION OF FILE
	HRRZ	T2,DEVACC##(F)	;ADDR OF ACC
	MOVE	T3,ACCWRT##(T2)	;NUMBER OF BLOCKS WRITTEN
	CAMN	T3,DEVREL##(F)	;LAST BLOCK?
	CAIE	T1,FNCAPP##	;AND APPEND-ONLY?
	JRST	CPOPJ1##	;NO, OK
	PUSHJ	P,SAVE2##	;SAVE P1,P2
	LDB	P1,ACYLBS##	;SIZE OF LAST BLOCK
	JUMPE	P1,CPOPJ1##	;IF EMPTY LET HIM DO IT
IFE FTAPLB,<
	POPJ	P,		;DON'T LET HIM
>
IFN FTAPLB,<
	CAIL	P1,BLKSIZ##	;LAST BLOCK HAVE ROOM?
	POPJ	P,		;NO, DON'T LET HIM
	LDB	T1,PIOMOD##	;MODE OF FILE
	CAIL	T1,SD		;DUMP MODE OR BUFFERED?
	JRST	CHKLB1		;DUMP
	HRRZ	P2,DEVOAD(F)	;BUFFERED, GET ADDR OF BUFFER
	EXCTUX	<MOVE T1,1(P2)>	;GET SIZE
	ADDI	P2,2
	JRST	CHKLB4

;HERE IF DUMP MODE
CHKLB1:	HLRE	T1,DEVDMP##(F)	;GET SIZE OF USER BUFFER
	MOVNS	T1
	HLRZ	P2,DEVUVA##(F)	;GET ADDR OF USER BUFFER
	ADDI	P2,1
;STILL IN FTAPLB CONDITIONAL
;HERE WITH:
;T1=SIZE OF USER BUFFER
;P1=SIZE OF LAST BLOCK
;P2=ADDR OF USER BUFFER
CHKLB4:	CAMGE	T1,P1		;NEW SIZE MUST BE BIGGER THAN OLD
	POPJ	P,
	PUSHJ	P,GTMNBF##	;GET A MON-BUF
	MOVE	T2,DEVBLK##(F)	;NUMBER OF LAST BLOCK
	PUSHJ	P,MONRDU##	;READ IT
	PJUMPN	T3,CPOPJ##	;RETURN IF ERRORS DETECTED IN MONRED
	HRLZI	T1,1(T1)	;FROM
	HRR	T1,P2		;TO
	ADDI	P2,-1(P1)	;STOP AT
	EXCTXU	<BLT T1,(P2)>	;COPY FIRST PORTION OF BLOCK
	LDB	T1,PIOMOD##	;MODE OF FILE
	CAIL	T1,SD		;DUMP MODE OR BUFFERED?
	JRST	CPOPJ1		;DUMP
	PUSHJ	P,UUOPWQ##	;BUFFERED, START THE TRANSFER
	PUSHJ	P,WSYNC##	;WAIT FOR COMPLETION (EVEN IF NON-BLOCKING)
				; WE DON'T WANT TO GIVE CONTROL BACK TO
				; THE USER UNTIL THE TRANSFER IS COMPLETE.
				; ELSE A MALICIOUS USER MIGHT ALTER THE BUFFER.
	AOS	-3(P)		;EXIT CPOPJ2 FROM SAVE2
	JRST	CPOPJ1##
>	;END CONDITIONAL ON FTAPLB
IFN FTSPL,<

;TEST FOR 1ST SPOOL-MODE INPUT. IF IT IS, DO THE LOOKUP
SPTSTI:	SKIPL	DEVSPL(F)	;IS THIS A SPOOLING DDB?
	JRST	CPOPJ1##	;NO, RETURN
	MOVE	T1,DEVMOD(F)	;YES, GET DEVMOD
	TLNN	T1,DVIN		;CAN DEVICE DO INPUT?
	JRST	ILLINP##	;NO, ERROR
	SKIPE	DEVPPN(F)	;YES.  ALREADY SET UP FILE?
	PJRST	CPOPJ1##	;YES, RETURN
	LDB	J,PJOBN##	;NO. GET THE JOB NUMBER
	HLRZ	T2,JBTSPL##(J)	;INPUT FILE-NAME
	SKIPN	T2		;IF NOT SET UP
	MOVEI	T2,'QAA'	; START AT QAA.CDR
	MOVSM	T2,DEVFIL(F)	;SAVE NAME IN DECFIL
	MOVEI	T2,'CDR'	;EXTENSION
	MOVSM	T2,DEVEXT(F)	;INTO DEVEXT
	PUSHJ	P,SFDPPN	;GET DEFAULT PPN
	MOVEM	T4,DEVPPN(F)	;INTO DDB
	TLZ	M,UUOMSK	;SET UP UUO
	PUSHJ	P,SLPTJ##	;SET T1= SL. PTR.
	  POPJ	P,		;NO S.L.

	PUSHJ	P,ULOOK3	;DO THE LOOKUP
	  PJRST	SETBTL		;NOT FOUND- IMMEDIATE RETURN
	HLRZ	T1,DEVFIL(F)	;FOUND. GET THE FILE NAME
	AOS	T1		;AND INCREMENT BY 1
SPTST2:	LDB	T2,[POINT 6,T1,35]	; SO IF NO NEW SET IS DONE,
	CAIG	T2,'Z'		; THE NEXT FILE WILL BE READ
	JRST	SPTST3
	SUBI	T1,'Z'-'A'+1	;RESET TO 'A'
	ROT	T1,-6		;GET THE NEXT CHAR
	TRNE	T1,-1		;IS THERE ONE?
	AOJA	T1,SPTST2	;YES, INCREMENT IT
	ROT	T1,6		;DONE - SET UP IN RH AGAIN
SPTST3:	TLNE	T1,-1		;COMPLETELY IN RH?
	JRST	.-2		;NO, GET NEXT CHAR
	LDB	J,PJOBN##	;JOB NUMBER
	HRLM	T1,JBTSPL##(J)	;SAVE NEXT FILE-NAME IN JBTSPL
	TLO	F,LOOKB		;INDICATE LOOKUP DONE
	PUSHJ	P,JDAADR##
	HLLM	F,(T1)		;SAVE BITS IN USRJDA
	PJRST	CPOPJ1##	;AND TAKE GOOD RETURN
;STILL IN FTSPL CONDITIONAL
;TEST FOR 1ST SPOOL-MODE OUTPUT
SPTSTO:	MOVE	T1,DEVMOD(F)	;DEVMOD OF REAL DEVICE
	TLNN	T1,DVOUT	;CAN IT DO OUTPUT?
	JRST	SPTST9		;NO, GIVE ERROR
	SKIPGE	DEVSPL(F)	;SPOOLING DDB?
	SKIPE	DEVPPN(F)	;YES, ALREADY SET UP?
	PJRST	CPOPJ1##	;YES, RETURN
	TLNE	S,IOSRST	;DOING A RESET UUO?
	PJRST	CPOPJ1##	;YES, DON'T ENTER ANYTHING
SPTSTR:	PUSHJ	P,SAVE2##	;NO. SAVE P1,P2
	MOVEI	T2,1		;GET 1 4-WORD BLOCK
	PUSHJ	P,GET4WD##
	  POPJ	P,		;NONE AT ALL- CANT FAKE THE ENTER
	MOVE	P1,T1		;GOT ONE - SAVE ITS LOC IN P1
	HRLI	T1,.JDAT+140	;SINCE GETWRD WANTS M TO POINT TO A USER'S AREA,
	BLT	T1,3(P1)	; SAVE USER'S 140-143,
				; USE THESE LOCS FOR THE FAKED ENTER
	MOVE	T1,DATE##	;GET DATE
	MOVEM	T1,SPLGEN##	;SAVE IT
SPTSO1:	AOS	T1,SPLGEN##	;INCR AND LOAD
	IDIV	T1,[44*44*44*44*44] ;DIVIDE BY 36^5
	MOVE	T1,[POINT 6,.JDAT+140] ;POINT TO FILENAME
	SETZM	.JDAT+140
	MOVEI	T3,'Q'		;LOAD FIRST LETTER
	IDPB	T3,T1		;STORE IT
	PUSHJ	P,SPTSO2	;MAKE A NAME
	MOVEI	T1,'SPL'	;RELEASE 4 EXTENSION
	SKIPN	%SIOPR##	;IS ORION RUNNING
	HLRZ	T1,DEVNAM(F)	;NO, GET INIT'ED DEVICE
	CAIE	T1,'LL '	;LOWER
	CAIN	T1,'LU '	;UPPER
	MOVEI	T1,'LPT'	;SOME FLAVOR OF LPT
	HRLZM	T1,.JDAT+141	;STORE
	SKIPE	T1,%SIQSR##
	MOVE	T1,SPLPPN##	;GET PPN
	MOVEM	T1,.JDAT+143	;SAVE IT
	JRST	SPTSO3


SPTSO2:	IDIVI	T2,^D36		;DIVIDE BY 36
	PUSH	P,T3		;SAVE RESIDUE
	SKIPE	T2		;SKIP IF DONE
	PUSHJ	P,SPTSO2	;ELSE RECURSE
	POP	P,T2		;GET A CHAR
	ADDI	T2,'0'		;MAKE IT SIXBIT
	CAILE	T2,'9'		;IF NOT A DIGIT
	ADDI	T2,'A'-'9'-1	;MAKE IT ALPHA
	IDPB	T2,T1		;DEPOSIT
	POPJ	P,		;UNWIND
SPTSO3:
IFN FTMPB,<
	JUMPN	T1,SPTS5A	;DON'T CHANGE NAME IF QUASAR RUNNING
	MOVE	T1,DEVNAM(F)	;GET DEVICE USER INITED
	HLRZ	T3,T1		;GET LEFT HALF
	CAIE	T3,'LL '	;IS IT LL?
	CAIN	T3,'LU '	;OR LU?
	MOVSI	T1,'LPT'	;MAKE IT LPT
	HLLZM	T1,.JDAT+141	;AND STORE IT
IFN FTNET,<
	TRNE	T1,-1		;IS THERE A RIGHT HALF?
	JRST	SPTST4		;YES
	LDB	T2,PJOBN##	;NO, JOB NUMBER
	MOVE	T1,JBTLOC##(T2)	;WHERE THE JOB IS
	PUSHJ	P,CVTSBT##	;CONVERT TO SIXBIT
	LSH	T1,-^D24	;INTO RH(T1)
	TRO	T1,'S  '	;'S' FOR STATION
	CAIN	T3,'LL '	;IS IT LL?
	TRC	T1,370000	;YES MAKE 'S' INTO 'L'
	CAIN	T3,'LU '	;IS IT LU?
	TRC	T1,060000	;YES MAKE 'S' INTO 'U'
>	;END IFN FTNET
SPTST4:	HRRM	T1,.JDAT+140	;SAVE RH OF FILE NAME IN ENTER BLOCK
	MOVEI	T1,^D640	;THERE ARE 36**2 LEGAL NAMES STARTING WITH "Q",
	HRRM	T1,.JDAT+141	; SO SET A LIMIT OF HALF THAT
	AOS	T1,SPLGEN##	;START WHERE LEFT OFF LAST
	IDIVI	T1,^D46655	; ENSURE .LT. 36^3
	IDIVI	T2,^D36		; CONVERT TO NUMBER
	ADDI	T3,20		;TO "SIXBIT
	CAILE	T3,31
	ADDI	T3,7		; LETTER
	LSHC	T3,-6		;SAVE THE CHAR
	IDIVI	T2,^D36		;SECOND CHAR
	ADDI	T3,20
	CAILE	T3,31
	ADDI	T3,7
	LSHC	T3,6		;2 CHARS IN T3
	TRO	T3,'Q  '	;+ 'Q'
	ADDI	T2,20
	MOVE	T1,.JDAT+141	;COUNT OF TRIES
	TRNE	T1,-1		;TRIED (AND LOST) ENOUGH?
	SOSA	.JDAT+141	;NO
	DPB	T2,[POINT 6,T3,23]	;YES, 1ST CHAR = RANDOM
	HRLM	T3,.JDAT+140	;SAVE NAME
	SETZM	.JDAT+143	;ZERO PPN
SPTS5A:
>	;END IFN FTMPB
	PUSH	P,M		;SAVE M
	HRRI	M,140		;POINT M TO THE FAKED ENTER-BLOCK
	MOVE	T2,SPLPRT##	;PROTECTION FOR SPOOLED FILES
	MOVEM	T2,.JDAT+142
	MOVEI	P2,UENT4
	SKIPL	DEVSPL(F)
	HRROI	P2,RECLSD
IFN FTKL10&FTMP,<
	PUSH	P,DEVNBF(F)	;WE'LL CHANGE THIS NUMBER DOING THE ENTER
>
	PUSHJ	P,(P2)		;FAKE AN ENTER
	  JRST	SPTST6		;DID NOT WIN
	SKIPL	P2
	TLO	F,ENTRB		;OK - TURN ON ENTRB
IFE FTKL10&FTMP,<
	AOSA	T1,-1(P)	;SET FOR SKIP-RETURN
>
IFN FTKL10&FTMP,<
	AOSA	T1,-2(P)
>
SPTST6:	TLZ	F,ENTRB		;MAKE SURE ENTRB OFF ON FAILURE
IFN FTKL10&FTMP,<
	POP	P,DEVNBF(F)
>
	POP	P,M		;RESTORE UUO
	PUSH	P,T1		;GET CHAN NUM
	PUSHJ	P,JDAADR##
	HLLM	F,(T1)		;SAVE BITS IN USRJDA
	POP	P,T1
	TLZ	T1,-1
	CAIE	T1,FBMERR	;FILE BEING MODIFIED?
	CAIN	T1,AEFERR	;OR SUPERSEDE ERROR?
	JRST	SPTSO1		;YES, TRY AGAIN
	HRLZ	T2,P1		;LOC OF 4-WORD BLOCK
	HRRI	T2,.JDAT+140	;SET TO RESTORE USER'S 0-3
	BLT	T2,.JDAT+143	;BACK AS GOOD AS NEW
	MOVEI	T1,1		;DONE - GIVE UP CORE BLOCK
	HRRZ	T2,P1
	PJRST	GIV4WD##	;RETURN BLOCK AND EXIT
SPTST9:	TLNE	S,IOSRST	;FORGET IT IF RELEASE (PROBABLY A COMMAND)
	POPJ	P,		;COMMAND - ALLOW IT TO FINISH
	PJRST	ILLOUT##	;UUO - ERROR MESSAGE


>
;END FTSPL CONDITIONAL
SUBTTL	CLOSE
;WHEN RENAME CALLS CLOSE, IT MAY ALREADY HAVE THE MONITOR BUFFER, AND THE RIB
;MAY BE IN IT. IF SO, DEPRIB IS ON IN S

;INPUT CLOSE
CLOSIN:	TLZE	F,LOOKB		;LOOKUP IN FORCE?
	TLZN	S,IOSRDC	;YES, READ COUNT UP FOR CHAN?
	PJRST	STOIOS##	;NO. RETURN
CLOSRN:	PUSHJ	P,SAVE2##	;SAVE P1,P2
	PUSHJ	P,SETU##	;WAS F/S YANKED?
	  POPJ	P,		;YES, RETURN
	HLRZ	U,DEVUNI##(F)	;SET U TO UNIT OF RIB

	PUSHJ	P,TSTRDR	;IS ANYONE ELSE READING FILE?
	JUMPE	T1,STOIOS##	;RETURN IF NO AT
	MOVE	P2,T1		;SET RH(P2)=LOC OF NMB
CLOSR1:	HLRZ	P2,ACCNMB##(P2)
	SKIPN	P2
	STOPCD	UACLX,JOB,ALW,	;++ACCESS TABLE LINKED WRONG.
				;IT'S PROBABLY ON THE FREE LIST.
				;PROBABLE CAUSE: USE COUNT IS
				;WRONG.
	TRZN	P2,DIFNAL##
	JRST	CLOSR1		;LOOP
	MOVSI	T4,DEPRAD##	;DONT DECR PPB COUNT
	TDNN	T4,DEVRAD##(F)	; IF RENAME ACROSS DIRS

	HRL	P2,ACCPPB##(T1)	;AND LH(P2)=LOC OF PPB
	ANDCAM	T4,DEVRAD##(F)	;NO LONGER RENAMING ACCROSS DINS

	TRNE	T2,ACMCNM##	;NOT IF READ COUNT=1
	JRST	CLSIN2		;YES. RESET ACCESS DATE AND EXIT
	MOVEI	T4,ACPSBC##
	ANDCAM	T4,ACCSBC##(T1)
	TRNN	T2,ACPREN	;FILE BEING RENAMED (BY SOME OTHER JOB)?
				; CANT BE FOR THIS JOB SINCE ACPREN IS A VERY
				; TRANSIENT BIT - RENAME CALLS CLOSE WHICH CLEARS IT
	TRNN	T2,ACPDEL##	;NO, FILE MARKED FOR DELETION?
	JRST	CLSIN2		;NO
;HERE, CALLED FROM CLRSTS, IF THERE WAS A RENAMER, WHEN HE FINISHES
;NEEDED SINCE DELETE CODE CANT ACTUALLY DO ANYTHING EVEN IF READ-COUNT =0
;WHEN THERE IS A RENAME IN PROGRESS BY SOME OTHER JOB
CLOSR2:	PUSHJ	P,CLSNAM	;SET T1=LOC OF NMB,  RESET DEVFIL, DEVEXT
	MOVE	P1,T1		;P1=LOC OF NMB (FOR DELNAM)
	MOVE	T2,ACCSTS##(T2)	;STATUS OF FILE
	TRNE	T2,ACPNIU	;HAS FILE BEEN REMOVED FROM UFD?
	JRST	CLSIN1		;GO DELETE BLOCKS OF FILE
	PUSHJ	P,UPAU##	;GET AU (ALTER UFD) RESOURCE
	TLZ	S,IOSRIB	;RIB IS NOT IN MON BUF ANY MOR
	PUSHJ	P,DELNAM	;FIND FILE NAME AND DELETE IT FROM UFD
	  JRST	FREACC		;FILE NAME NOT FOUND IN UFD
CLSIN1:	TLO	F,RENMB		;SO RIBCHK WON'T CHECK RIBDIR
	PUSHJ	P,REDRIB##	;GO READ THE RIB INTO CORE
	  JRST	FREAC1		;RIB ERROR, DON'T COUNT ON THE DATA
	TLZ	F,RENMB
	PUSHJ	P,SPTRW##	;SET UP AN AOBJN WORD FOR POINTERS
	MOVE	P1,T1		;AOBJN WORD INTO P1
	PUSHJ	P,DELRIB	;GO DELETE THE BLOCKS OF THE FILE
	  STOPCD .+1,DEBUG,DNS,	;++DELRIB NON-SKIP RETURN
	PUSHJ	P,LOGTST	;RECOMPUTE RIBUSD IF PPN NOT LOGGED IN
	PUSHJ	P,SFDDEC	;DECR PPBCNT, NMBCNT
	PUSHJ	P,DECUSA	;DECREMENT USE-COUNTS OF THE FATHER SFD AT'S
	JRST	FREAC1		;FINISH UP
;HERE WHEN THE FILE NAME WAS NOT FOUND IN THE UFD.
FREACC:	PUSHJ	P,DWNAU##	;GIVE UP AU RESOURCE

FREAC1:	TLZ	F,RENMB		;TURN OFF RENMB SO CLOSE OUTPUT WONT DO ANYTHING
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	HRRZ	T1,DEVACC##(F)	;%LOC OF A.T.
	CBDBUG	(Y,Y);
	SETZM	DEVFIL(F)	;FOR SET WATCH FILE

	HLRZ	T2,NMBRNG##(P2)	;%IS THE FILE AN SFD?
	TRNN	T2,NMPUPT##	;%DOES THE SFD HAVE CHILDREN?
	JUMPN	T2,CLSIN8	;%YES, RETURN ACC, LEAVE NMB
	JRST	CLSIN7		;%RETURN NMB IF POSSIBLE
;HERE WHEN FILE IS NOT MARKED FOR DELETION
CLSIN2:	TRNE	M,CLSOUT	;SUPPRESSING OUTPUT CLOSE?
	JRST	CLSIN3		;YES, CHECK (POSSIBLY UPDATE) ACCESS DATE
	TLNE	F,ENTRB+RENMB	;NO, ENTER OR RENAME DONE?(IF SO CLSOUT WILL BE CALLED)
	JRST	CLSXIT		;YES. DECREMENT COUNT AND EXIT
CLSIN3:	JUMPE	T1,TSTPPB	;DEVACC=0 IF F/S WAS JERKED OUT
	TLNN	S,IOSERR##	;UPDATE BAT BLOCK IF ERROR
	TRNN	M,CLSACC	;NO. SUPPRESS UPDATING ACCESS DATE?
	TRNE	T2,ACPREN+ACPUPD;OR RENAME OR UPDATE HAPPENING (BY A DIFFERENT JOB)?
	JRST	CLSIN5		;YES, DON'T WRITE RIB
	TLNN	S,IOSWLK	;FILE WRITE LOCKED?
	TLNN	F,INPB		;NO. ANY INPUTS DONE?
	JRST	CLSIN5		;NO. DON'T CHANGE ACCESS DATE
	TLNE	S,IOSERR##	;ANY ERRORS ENCOUNTERED?
	TDZA	T4,T4		;YES. FORCE WRITING OF RIB
	LDB	T4,[POINT 15,ACCADT##(T1),17]	;ACCESS DATE
	CAMN	T4,THSDAT##	;NO. AC. DATE=TODAY?
	JRST	CLSIN5		;YES. JUST SET A.T. DORMANT
	MOVE	T4,THSDAT##	;NO. SET ACCESS DATE=TODAY
	DPB	T4,[POINT 15,ACCADT##(T1),17]	;IN ACC
	PUSHJ	P,CLSNAM	;UPDATE DEVFIL, DEVEXT
	PUSHJ	P,BUFRIB##	;GET MON BUF, READ RIB INTO IT
	  JRST	CLSIN5		;RIB ERR - DON'T REWRITE IT
	TRNE	M,CLSACC
	JRST	CLSIN4
	MOVE	T1,.USMBF	;LOC OF BUF (-1)
	MOVE	T2,THSDAT##	;GET TODAYS DATE
	DPB	T2,[POINT 15,RIBEXT##+1(T1),35]
	PUSHJ	P,STORU##
CLSIN4:
	PUSHJ	P,TSTBAD	;SET RIBELB IF ERROR

	MOVE	T2,RIBSLF##+1(T1)	;BLOCK NO. OF RIB
	PUSHJ	P,MONWRT##	;REWRITE THE RIB WITH NEW AC. DATE
	PUSHJ	P,ERRFIN	;WRITE BAT BLOCK IF THERE WAS AN ERROR

CLSIN5:	TLNE	F,ENTRB+RENMB	;ENTER OR RENAME DONE?
	JRST	CLSXIT		;YES, EXIT (UPDATE SUPPRESSING OUTPUT CLOSE)
	PUSHJ	P,CLSNAM	;UPDATE DDB IN CASE SOMEBODY RENAMED THE FILE
IFN FTFDAE,<
	MOVSI	T1,DEPFDA##	;CALL FILE DAEMON ON CLOSE BIT
	TDNN	T1,DEVFDA##(F)	;SHOULD THE FILE DAEMON BE CALLED?
	JRST	CLSIN6		;NO
	ANDCAM	T1,DEVFDA##(F)	;YES, CLEAR THE BIT
	MOVEI	T1,.FDCLI	;INDICATE INPUT CLOSE
	PUSHJ	P,SNDFMG##	;TELL THE FILE DAEMON THAT
	  JFCL			;DON'T CARE
CLSIN6:>
	PUSHJ	P,SFDDEC	;DECR NMBCNT,PPBCNT FOR SFD
	PUSHJ	P,DECUSA	;DECREMENT USE-COUNTS OF THE FATHER SFD AT'S
	PUSHJ	P,DECRDR	;NO, DECREMENT COUNT
	  SETZ	T1,		;%READ COUNT NOT 0
	PUSHJ	P,UACLX		;%RESET A.T. LOC AND UFB LOC IN DDB
	JUMPE	T1,CLSI13	;%EXIT IF READ-COUNT NON-0
	TRNE	T2,ACPREN	;%RENAME IN PROGRESS (BY ANOTHER JOB)?
	JRST	CLSI13		;%YES, LEAVE THE A.T. ALONE
	TRNN	M,CLSDAT	;%CNT=0. WANT A.T. TO GO AWAY?
	TLNN	F,INPB		;%NO, ANY INPUTS BEEN DONE?
	TRNE	M,CLSNMB	;%YES. USER WANT CORE BLOCKS TO STAY AROUND ANYWAY?
	JRST	CLSI14		;%YES, JUST MAKE A.T. DORMANT
	HLRZ	T2,NMBRNG##(P2)	;%IS THE FILE AN SFD?
	JUMPE	T2,CLSIN7	;%GO IF NOT SFD
	MOVE	T4,NMBCNT##(P2)	;%IS SOMEBODY INSIDE FNDFIL?
	CAIG	T4,1
	TRNN	T2,NMPUPT##	;%DOES THE SFD HAVE CHILDREN?
	JRST	CLSI14		;%YES, JUST MAKE ACC DORMANT
CLSIN7:	MOVE	T4,NMBCNT##(P2)
	SOJLE	T4,CLSIN9	;%LEAVE NMB IF ANOTHER READING
CLSIN8:	PUSHJ	P,ATNLNK##	;%ANOTHER USER OF NMB EXISTS
	JRST	CLSI10		;% RETURN AT, LEAVE NMB
CLSIN9:	HRL	P1,ACCPPB##(T1)	;%DELETE ALL CORE BLOCKS FOR FILE(IF POSSIBLE)
	PUSHJ	P,ATNLNK##	;%UNLINK A.T. FROM NMB RING
	TRZE	T2,DIFNAL##	;%PREDECESSOR A NAME BLOCK?
	TRZN	T3,DIFNAL##	;%YES. SUCCESSOR AN NMB?
CLSI10:	TDZA	P1,P1		;%NO. THERE ARE OTHER A.T.S IN RING
	HRR	P1,T2		;%YES, SAVE LOC OF NMB
	PUSH	P,F		;%SAVE F
	SKIPE	P1		;%IF WE'RE GOING TO REMOVE THE NMB,
	SETZ	F,		;%ZERO F SO ATSDRA WONT GIVE UP CB
	PUSHJ	P,ATSFR0##	;%PUT THIS A.T. ON FREE CORE LIST
	POP	P,F		;%RESTORE DDB LOC
	HLLZS	DEVACC##(F)	;%MAKE SURE THE A.T. ISN'T REUSED
	JUMPE	P1,CLSI15	;%EXIT IF NMB STILL IN USE
;HERE IF NMB NOW HAS NO A.T.S IN ITS RING
	HLRZ	T2,P1		;%LOC OF PPB FOR FILE
	PUSHJ	P,SET1NM	;%SET T2 TO 1ST NMB IN LIST
	JUMPE	T2,CLSI13	;%GO IF NONE (SYSTEM ERROR?)
CLSI11:	CAIN	T2,(P1)		;%THIS THE RIGHT NMB?
	JRST	CLSI12		;%YES. HAVE PRED IN T3
	MOVE	T3,T2		;%NO. NEW PREDECESSOR
	HLRZ	T2,NMBPPB##(T2)	;%STEP TO NEXT NMB IN RING
	TRNN	T2,NMPUPT##	;%UPWARD PNTR (NOT SAME LIST) IF ON
	JUMPN	T2,CLSI11	;%GO TEST IT
	JRST	CLSI13		;%CANT FIND THE PREDECESSOR (SYSTEM ERROR?)
;HERE WITH T3=LOC OF PREDECESSOR NMB TO THE ONE WE WANT TO DELETE
CLSI12:	MOVE	T1,NMBPPB##(P1)	;%NMB'S LINK
	HLLM	T1,NMBPPB##(T3)	;%SAVE IN LINK OF PRED
	MOVE	T1,SYSCOR##	;%PREVIOUS 1ST FREE CORE BLOCK
	HRLM	P1,SYSCOR##	;%THIS NMB IS NEW 1ST FREE
	HLLM	T1,CORLNK##(P1)	;%LINK PREVIOUS 1ST FREE TO THIS ONE
	HLLZS	P2		;NO NMB USE-COUNT TO DECR
CLSI13:	PUSHJ	P,GVCBJ1##	;%GIVE UP CB AND SKIP
CLSI14:	PUSHJ	P,ATSDRA##	;%MAKE A.T. DORMANT
CLSI15:	SETZM	DEVUNI##(F)	;THIS FILE NO LONGER OPEN (SO ENTER WILL TEST UNIT)
	PUSHJ	P,CLRLIB
	PJRST	TSTPPB		;TEST IF PPB LOGGED IN, AND EXIT
;HERE TO DECREMENT READ-COUNT, EXIT
CLSXIT:	PUSHJ	P,DECRDR	;%COUNT DOWN BY 1
	  JFCL			;%READ COUNT  NON-0
	CBDBUG	(Y,Y);
	PUSHJ	P,GVCBJ##
;TURN OFF DEPLIB
CLRLIB:	MOVSI	T1,DEPLIB##	;CLEAR FILE-FROM-LIB
	ANDCAM	T1,DEVLIB##(F)	;SO UPDATE WILL WIN
;FALL INTO DECUC

;SUBROUTINE TO DECREMENT USE-COUNTS
;ENTER P2=PPB,,NMB
;PRESERVES ALL ACS EXCEPT P2, WHICH IT CHANGES
DECUC:	TRNN	P2,-1		;IF FROM CLRSTS, COUNTS ALREADY DECR'D
	JRST	DECUC1
	SOSL	NMBCNT##(P2)	;DECREMENT NMB COUNT
	JRST	DECUC1
	;STOPCD	.+1,DEBUG,NUN,	;++NMB USE-COUNT NEGATIVE
	SETZM	NMBCNT##(P2)	;RESET COUNT
	PUSH	P,T1		;SAVE SOME DEBUGGING INFO
	AOS	NUNCNT		;COUNT OF "NUN STOPCDS"
	MOVE	T1,PPBNAM##(P2)
	MOVEM	T1,NUNSFD
	HLRZ	T1,NMBACC##(P2)
	TRZE	T1,DIFNAL##
	JRST	.+3
	MOVE	T1,ACCPPB##(T1)
	MOVE	T1,PPBNAM##(T1)
	MOVEM	T1,NUNPPN
	POP	P,T1
DECUC1:	HLRZS	P2
	JUMPE	P2,CPOPJ##	;NO PPB TO DECR IF 0
	SOSL	PPBCNT##(P2)	;DECREMENT PPB COUNT
	POPJ	P,
	;STOPCD	.+1,DEBUG,PUN,	;++PPB USE-COUNT NEGATIVE
	SETZM	PPBCNT##(P2)
	AOS	PUNCNT		;COUNT OF "PUN STOPCDS"
	PUSH	P,PPBNAM##(P2)
	POP	P,PUNPPN
	POPJ	P,		;EXIT
	$LOW
PUNCNT:	0
PUNPPN:	0
NUNCNT:	0
NUNPPN:	0
NUNSFD:	0
	$HIGH
;SUBROUTINE TO SET UP P2 FOR DECUC
;RETURNS T1=L(AT), P2 CHANGED
DECSU:	PUSHJ	P,GETNMB	;GET LOC OF NMB,AT
	EXCH	T1,T2		;T1=LOC OF AT
	MOVE	P2,T2		;P2=NMB
	HRL	P2,ACCPPB##(T1)	;P2=PPB,,NMB
	POPJ	P,		;RETURN

;SUBROUTINE TO DECREMENT NMB,PPB COUNTS IF FILE IS IN AN SFD
;PRESERVES T1,T2
SFDEC:
SFDDEC:	SKIPA	T4,[-1]		;SET TO COUNT DOWN
SFDUP:	MOVEI	T4,1		;SET TO COUNT UP
	HRRZ	T3,DEVSFD##(F)	;LOC OF SFD
	JUMPE	T3,CPOPJ##	;RETURN IF NONE
	ADDM	T4,NMBCNT##(T3)	;CHANGE NMBCNT
	HLRZ	T3,NMBACC##(T3)
	TRNE	T3,DIFNAL##	;POINT AT A.T.
	POPJ	P,		;NO A.T., RETURN
	MOVE	T3,ACCPPB##(T3)	;POINT AT PPB
	ADDM	T4,PPBCNT##(T3)	;COUNT PPBCNT UP OR DOWN
	POPJ	P,		;AND RETURN
;SUBROUTINE TO FIND THE ACCESS-TABLE FOR A FILE, GET THE STATUS
; IN T2
;ALWAYS RETURNS CPOPJ WITH T2=STATUS=READ COUNT
TSTRDR:	TDZA	T2,T2		;DECREMENT COUNT BY 0
				;AND FALL INTO DECRDR

;SUBROUTINE TO DECREMENT THE NUMBER OF READERS OF A FILE
;EXIT CPOPJ IF THERE ARE OTHER READERS, CPOPJ1 IF THE READ COUNT HAS GONE TO 0
;EXITS WITH THE COUNT (=STATUS) WORD IN T2, WITH CB RESOURCE, AND T1=A.T. LOC (OR 0).
DECRDR::MOVNI	T2,ACPCNT##	;SET TO DECREASE READ COUNT
	HRRZ	T1,DEVACC##(F)	;LOC OF A.T.
	JUMPE	T1,CPOPJ##	;SYSTEM ERROR (?) IF 0
	SKIPE	T2		;IF CHANGING THE READ-COUNT,
	PUSHJ	P,GETCB##	; GET CB RESOURCE
	ADDB	T2,ACCCNT##(T1)	;%1 LESS JOB IS READING FILE
	MOVEM	S,DEVIOS(F)	;%SAVE S (IOSRDC NOW OFF)
				; SO REDOING CLOSE WON'T DECREMENT
				; AGAIN (EG ON ADR ERR ON CLOSE)
	TRNE	T2,ACMCNT+ACPREN+ACPUPD	;%ANYONE USING FILE AT ALL?
	POPJ	P,		;%YES, NON-SKIP
	PJRST	CPOPJ1##	;%NO, SKIP-RETURN


;SUBROUTINE TO GET THE LOC OF THE NMB FROM THE DDB
;RETURNS T1=LOC OF NMB, T2=LOC OF A.T.
;ENTER AT GTNM1 WITH LOC OF A.T. IN T1; T,T2,T3 RESPECTED
GETNMB::HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
	SKIPN	T1,T2		;IS THERE ONE?
	JRST	GTNM2
GTNM1::	HLRZ	T1,ACCNMB##(T1)	;STEP TO NEXT IN RING
	TRZN	T1,DIFNAL##	;IS IT AN NMB?
	JRST	.-2		;NO. TRY NEXT
	POPJ	P,		;YES. RETURN


GTNM2:	SKIPN	DEVUNI##(F)
	POPJ	P,
	STOPCD	CPOPJ##,STOP,NNF, ;++NMB NOT FOUND
;SUBROUTINE TO SET UP DEVFIL AND DEVEXT FROM NMB
; CALLED BY CLOSE INPUT (SINCE ANOTHER JOB MIGHT HAVE RENAMED THE FILE
; THIS JOB WAS USING, SWITCHING THE A.T. TO A NEW NMB)
;RETURNS T1=LOC OF NMB   T2=LOC OF A.T.
CLSNM::	PUSHJ	P,GETNMB	;SET T1=NMB, T2=A.T.
	MOVE	T3,NMBNAM##(T1)	;NAME
	MOVEM	T3,DEVFIL(F)	;INTO DDB
	HRLZ	T4,NMBEXT##(T1)	;GET EXTENSION
	HLLM	T4,DEVEXT(F)	;INTO DDB
	POPJ	P,		;RETURN

;ROUTINE TO FIX DEVFIL, DEVEXT, DEVPPN, DEVSFD, AND DEVUFB
CLSNAM::PUSHJ	P,CLSNM		;FIX DEVFIL AND DEVEXT
	PUSHJ	P,SAVT##	;RETURN AC'S LIKE THIS
CLSNM1:	HLRZ	T1,NMBPPB##(T1)	;FIND NMB OF PARENT SFD
	TRZN	T1,DIFNAL##
	JUMPN	T1,CLSNM1
	MOVEM	T1,DEVSFD##(F)	;STORE NEW SFD
	MOVE	T3,ACCPPB##(T2)	;ADDR OF NEW PPB
	MOVE	T4,PPBNAM##(T3)	;NEW PPN
	CAMN	T4,DEVPPN(F)	;HAS IT CHANGED?
	POPJ	P,		;NO
	MOVEM	T4,DEVPPN(F)	;YES, SAVE NEW PPN
	LDB	T1,ACYFSN##	;GET FILE STR
	HLRZ	T2,PPBUFB##(T3)	;ADDR OF 1ST UFB
	PUSHJ	P,BYTSCA##	;FIND THE RIGHT UFB
	  HRRM	T2,DEVUFB##(F)	;SHOULD NEVER SKIP, SAVE IT
	POPJ	P,

;ROUTINE TO COMPUTE THE CURRENT LEVEL OF SFD NESTING
;T1 RETURNS LEVEL (E.G. UFD=0)
CNTLVL:	HRRZ	T2,DEVSFD##(F)	;CURRENT SFD
CNTLV0:	SETZ	T1,		;INITIALIZE COUNT
CNTLV1:	JUMPE	T2,CPOPJ	;QUIT IF TOP LEVEL
CNTLV2:	HLRZ	T2,NMBPPB##(T2)	;FIND PARENT SFD
	TRZN	T2,DIFNAL##
	JUMPN	T2,CNTLV2
	AOJA	T1,CNTLV1	;BUMP COUNT AND DO NEXT LEVEL
;SUBROUTINE TO SET THE ADR OF THE 1ST NMB IN THE LIST
;ENTER WITH T2=LOC OF PPB
;EXIT T3=LOC OF PREDECESSOR, T2= 1ST NMB IN LIST
;IF AN SFD, RETURNS T4= LOC OF FATHER SFD NMB
SET1NM::
	HRRZ	T4,DEVSFD##(F)
	JUMPE	T4,SETIN1	;IN AN SFD?
	HLRZ	T2,NMBRNG##(T4)	;YES, GET 1ST NMB IN LIST
	MOVEI	T3,DIFNMC##(T4)	;AND PREDECESSOR
	POPJ	P,
SETIN1:	MOVEI	T3,DIFPNL##(T2)	;PRESET PRED
	HLRZ	T2,PPBNMB##(T2)	;1ST NMB IN PPB-LIST
	POPJ	P,		;AND RETURN


;SUBROUTINE TO DELETE A FILE NAME FROM A UFD
;ENTER WITH NAME TO BE DELETED IN DEVNAM,DEVEXT; UFD SPECIFIED BY DEVUFB
;AND P1=LOC OF NMB
;JOB MUST HAVE AU RESOURCE BEFORE CALLING DELNAM
;EXIT CPOPJ IF NAME NOT FOUND (STILL WITH AU RESOURCE)
;EXIT CPOPJ1 IF FOUND, WITH CFP IN T1, AND AU RES GIVEN UP
; THE UFD WILL HAVE BEEN REWRITTEN WITHOUT THE FILE NAME ON  GOOD RETURN
; AND THE NMB WILL BE ADJUSTED (NMBYES=0 FOR THE STR)
DELNAM:	HLRZ	U,DEVUNI##(F)	;SET U TO UNIT OF RIB
	PUSHJ	P,UFDSRC##	;SEARCH UFD
	  POPJ	P,		;TAKE NOT-FOUND RETURN
	PUSH	P,T1		;FOUND MATCH - SAVE CFP
	HRLI	T1,2(T3)	;BLT REST OF NAMES IN UFD DOWN
	HRRI	T1,(T3)		; BY 2 (OVERWRITE THIS NAME)
	HLRE	T4,T3		;DISTANCE FROM NAME TO END OF BLOCK
	MOVNS	T4
	ADD	T3,T4		;ADDR ONE PAST END OF BUF
	CAIE	T4,2		;DON'T DO BLT IF LAST ENTRY
	BLT	T1,-3(T3)	;SLIDE EVERYTHING DOWN
	SETZM	-2(T3)		;ZERO LAST SLOT IN UFD BLOCK
	SETZM	-1(T3)
	PUSHJ	P,WRTDIR	;GO WRITE THE UPDATED UFD
	PUSHJ	P,DWNAU##	;GIVE UP AU RESOURCE
	JUMPE	P1,TPOPJ1##	;DON'T CHANGE NMB IF P1=0
	PUSHJ	P,GETCB##	;CHANGE NMB - GET CB RESOURCE
	HRRZ	T2,DEVUFB##(F)	;%LOC OF UFB
	LDB	T1,UFYFSN##	;%GET FSN

	PUSHJ	P,FSNPS2##	;%SET A BIT FOR NMBYES
	ORM	T2,NMBKNO##(P1)	;%YES WE KNOW ABOUT FILE
	ANDCAM	T2,NMBYES##(P1)	;%NO IT IS NOT IN THIS STR
	POP	P,T1		;%RESTORE CFP TO T1
	PJRST	GVCBJ1##	;%GIVE UP CB AND SKIP RETURN
;SUBROUTINE TO TO SEE IF A BAD BLOCK (OR REGION) WAS ENCOUNTERED
;IF SO, SET RIBELB,RIBEUN,RIBNBB,RIBSTS. DO NOT WRITE RIB,AS THIS IS DONE BY CALLING ROUTINE
;EXIT WITH T1=C(.UPMBF)
TSTBAD:	MOVE	T1,.USMBF	;POINT AT RIB
	HLRZ	T3,S		;LH STATUS BITS
	ANDI	T3,IOSERR##	;MASK OUT ALL BUT ERROR BITS
	JUMPE	T3,CPOPJ##	;RETURN IF NONE
	MOVEI	T2,RIPABC##	;SET TO TEST FOR ALWAYS BAD CHECKSUM
	TDNN	T2,RIBSTS##+1(T1)	;ALWAYS BAD CHECKSUM?
	ORM	T3,RIBSTS##+1(T1)	;NO, SAVE ERROR BITS IN RH(RIBSTS)
	SKIPN	T2,DEVELB##(F)	;SHOULD A REGION BE MARKED IN BAT.SYS?
	POPJ	P,		;NO. RETURN

;HERE WITH T2=1ST BLOCK OF A REGION TO MARK IN BAT.SYS
	MOVEM	T2,RIBELB##+1(T1) ;SAVE 1ST BLOCK NO IN RIB
	LDB	T3,DEYEUN##	;UNIT (WITHIN STR) OF ERROR
	MOVSM	T3,RIBEUN##+1(T1) ;SAVE IN LH OF RIBEUN
	PUSHJ	P,SAVE2##	;SAVE P1
	PUSH	P,U		;SAVE U
	MOVE	T2,T3		;UNIT NUMBER WITHIN F/S
	PUSHJ	P,NEWUNI##	;SET U TO RIGHT UNIT
	  MOVE	U,(P)		;BAD NUMBER - ASSUME ORIGINAL U IS RIGHT
	MOVEI	P1,1		;P1 WILL COUNT # OF BLOCKS IN BAD REGION
IFN FTCIDSK,<
	SETZ	P2,		;ASSUME WE WON'T NEED A BUFFER
	LDB	T2,UNYKTP##	;GET KONTROLLER TYPE
	CAIE	T2,TYPRA##	;CI DISK?
	JRST	TSTBD1		;NO
	MOVEI	T2,BLKSIZ##	;SIZE OF A BLOCK
	PUSHJ	P,GFWDCD##	;GET A BUFFER TO SCAN THE BAD BLOCK/REGION
	  STOPCD TSTBD5,DEBUG,CGB, ;++CAN'T GET BUFFER TO READ BAD BLOCK
	SOS	P2,T1		;GET ADDRESS -1
	TLOA	T1,MBLKSZ##	;IOWD TO READ 1 BLOCK, AND STORE DATA
>; END IFN FTCIDSK
TSTBD1:	MOVSI	T1,MBLKSZ##	;IOWD TO READ 1 BLOCK, BUT NOT STORE DATA
	LDB	T2,DEYELB##	;BAD BLOCK NUMBER
	PUSH	P,DEVISN##(F)	;SAVE USER'S SECTION #
	SETZM	DEVISN##(F)	;MAKE SURE MAPIO IGNORES SECTION #
TSTBD2:	ADDI	T2,1		;STEP TO NEXT BLOCK IN REGION
	CAIGE	P1,BAFNUM##	;ALREADY READ AS MANY BLOCKS AS WILL FIT IN 1 PNTR?
	CAMLE	T2,UNIBPU##(U)	;NO, PAST TOP OF UNIT?
	JRST	TSTBD3		;YES, ALL FINISHED READING BAD BLOCKS
	PUSHJ	P,MONRDU##	;NO, READ IT
	TRNE	T3,IODTER+IODERR ;IS IT BAD?
	AOJA	P1,TSTBD2	;YES. COUNT AND TRY NEXT BLOCK
TSTBD3:
IFN FTCIDSK,<
	JUMPE	P2,TSTBD4	;JUMP IF NO BUFFER TO RETURN
	MOVEI	T2,1(P2)	;GET ADDRESS OF BUFFER
	MOVEI	T1,BLKSIZ##	;SIZE OF A BLOCK
	PUSHJ	P,GVFWDS##	;RETURN THE SPACE
>; END IFN FTCIDSK
TSTBD4:	MOVE	T1,.USMBF	;LOC OF MON BUF (AND RIB)
	HRRM	P1,RIBNBB##+1(T1) ;SAVE COUNT IN RIB
	POP	P,DEVISN##(F)	;RESTORE SECTION #
TSTBD5:	POP	P,U		;RESTORE ORIGINAL U
	PJRST	STORU##		;SAVE IN DDB AND RETURN
;SUBROUTINE TO FINISH UP IF AN ERROR OCCURRED
;UPDATE BATBLK, LH(RIBSTS) IN THE UFD RIB
ERRFIN:	TLNN	S,IOSERR##	;ANY ERROR?
	POPJ	P,		;NO. RETURN
	PUSHJ	P,SAVE2##	;YES. SAVE P1,P2
	MOVE	T1,.USMBF	;LOC OF RIB
	MOVE	P1,RIBELB##+1(T1) ;REGION TO WRITE IN BAT.SYS?
	TLZ	P1,BATMSK##	;JUST BLOCK NO.
	JUMPE	P1,ERFIN5	;NOT IF 0
	HLRZ	T2,RIBEUN##+1(T1)	;YES. BAD UNIT IN STR
	HRRZ	T3,UNISTR##(U)	;LOC OF STR DATA BLOCK
	JUMPE	T3,ERFIN0	;DON'T GO TO NEWUNI IF NOT IN A F/S
				;(FROM RELEASE AFTER SUPER USETI/O)
	PUSHJ	P,NEWUNI##	;SET U TO DATA BLOCK
	  JRST	ERFN4A		;BAD UNIT NUMBER - IGNORE BAT BLOCK
ERFIN0:	PUSHJ	P,SUPDA##	;GET DA RESOURCE IF DONT ALREADY HAVE IT (SIM UPDATE)
	MOVE	T1,.USMBF	;LOC OF RIB
	HRRZ	P2,RIBNBB##+1(T1) ;LENGTH OF BAD REGION
	ADD	P2,P1		;TOP BLOCK(+1) OF BAD REGION
	PUSHJ	P,REDBAT##	;READ AND VERIGY BAT BLOCKS
	  JRST	SDWNDA##	;BOTH BLOCKS BAD, DON'T UPDATE
	MOVEI	T2,1(T1)	;1ST REAL WORD OF BAT
	ADD	T2,BAFFIR##(T2)	;COMPUTE AOBJN WORD FOR BAT REGIONS
ERFIN1:	MOVE	T3,BAFELB##(T2)	;1ST BLOCK OF A BAD REGION
	TLZ	T3,BATMSK##
	JUMPE	T3,ERFIN3	;IF 0 DONE, THIS IS A NEW REGION
	MOVEI	T4,BAPNTP##	;OLD STYLE?
	TDNN	T4,BAFAPN##(T2)
	HRRZS	T3		;YES, ONLY 18 BITS OF BLOCK NUMBER
	LDB	T4,BAYNBB##	;NO OF BLOCKS IN REGION-1
	ADD	T4,T3		; TOP BLOCK OF BAD REGION
	ADDI	T4,1		; TOP BLOCK +1
	CAML	P2,T3		;DOES NEW REGION OVERLAP THIS REGION?
	CAMLE	P1,T4
	JRST	SCNBAD		;NO. LOOK AT NEXT REGION IN BAT
	CAMLE	P1,T3		;YES. NEW 1ST BLOCK LT OLD 1ST BLOCK?
	MOVE	P1,T3		;NO. SET P1=LOWEST BLOCK
	CAMGE	P2,T4		;NEW TOP BLOCK GT OLD TOP BLOCK?
	MOVE	P2,T4		;SET P2=HIGHEST BLOCK
	LDB	T3,BAYAPN##	;SERIAL NO OF APR WHICH 1ST SAW BAD REGION
	CAME	T3,SERIAL##	;WAS IT THIS APR?
	JRST	ERFIN2		;NO.
	LDB	T3,BAYKNM##	;YES. KONTROLLER NO. WHICH 1ST SAW REGION
	LDB	T4,UNYKNM##	;THIS KONTROLLER NUMBER
	CAMN	T3,T4		;SAME?
	JRST	STOPUB		; YES. STORE NEW LIMITS OF REGION

;HERE IF A DIFFERENT APR OR KONTROLLER SAW THIS REGION BEFORE
ERFIN2:	MOVSI	T3,BAPOTH##	;SET A FLAG FOR MULTIPLE KONTROLLERS
	ORB	T3,BAFOTH##(T2)	; IN THIS BAT REGION
	JRST	WRTBAT		;ABD WRITE BAT (DON'T MARK THIS UNIT IN BAFPUB)

SCNBAD:	AOBJN	T2,.+1		;2 WORDS PER BAT ENTRY
	AOBJN	T2,ERFIN1	;GO TEST NEXT BAT ENTRY
	JRST	ERFIN4		;NO ROOM TO ENTER REGION - CANT DO ANYTHING WITH BAT

;HERE TO STORE A BAT ENTRY THE 1ST TIME
ERFIN3:	MOVE	T3,SERIAL##	;SERIAL NO OF APR
	TRO	T3,BAPNTP##	;NEW-STYLE ENTRY
	MOVEM	T3,BAFAPN##(T2)
	LDB	T3,UNYKNM##	;KONTROLLER NUMBER
	DPB	T3,BAYKNM##	;SAVE IT
	AOS	BAFCNT##+1(T1)	;INCREMENT COUNT OF BAT ENTRIES

;HERE TO MARK THE UNIT WHICH SAW THE ERROR
STOPUB:	MOVSI	T3,BARPUB##	;BIT FOR UNIT 0
	LDB	T4,UNYPUN##	;THIS UNIT NUMBER
	ANDI	T4,7		;MODULUS 8
	LSH	T3,(T4)		;POSITION BIT FOR THIS UNIT
	ORB	T3,BAFPUB##(T2)	;MARK IN TALLY OF UNITS WHICH SAW BAD REGION
;HERE WITH P1,P2=NEW LIMITS FOR THE BAD REGION WHOSE INDEX IS IN T2
WRTBAT:	SUBI	P2,1(P1)	;LENGTH OF BAD REGION+1
	DPB	P2,BAYNBB##	;SAVE IN BAT ENTRY(NO. BAD BLKS-1)
	MOVEM	P1,BAFELB##(T2)	;SAVE 1ST BLOCK OF REGION
	HLLZ	P1,DEVELB##(F)	;GET ERROR CODE
	TLZ	P1,MBTMSK##
	TRNE	T3,BAPNTP##
	IORM	P1,BAFELB##(T2)	;SAVE THEM IN BAT
	HRRZ	T2,UNIHOM##(U)	;LOC OF 1ST HOME BLOCK
	ADDI	T2,LBOBAT##	;LOC OF 1ST BAT BLOCK
	PUSHJ	P,MONWRS##	;WRITE IT
	HLRZ	T2,UNIHOM##(U)	;LOC OF 2ND HOME BLOCK
	ADDI	T2,LBOBAT##	;LOC OF 2ND BAT BLOCK
	PUSHJ	P,MONWRS##	;WRITE IT
	MOVEI	T3,1(T1)	;POINT TO BAT
	LDB	T4,BAYNBR##	;NO OF SLOTS THE MAPPER FOUND
	ADD	T4,BAFCNT##(T3)	;+ NO THE MONITOR FOUND
	HLRE	T3,BAFFIR##(T3)
	ASH	T3,-1		;2 WORDS PER ENTRY
	ADD	T3,T4		;-TOTAL NUMBER
	MOVNS	T3		;=-(NO OF SLOTS LEFT IN BAT)
	DPB	T3,UNYBCT##
ERFIN4:	PUSHJ	P,SDWNDA##	;GIVE UP DA RESOURCE IF NOT SIM. UPDATE
	JRST	ERFIN5

;HERE IF A BAD RIBEUN IN RIB
ERFN4A:	HRRZ	U,DEVUNI##(F)	;RESET U

;HERE AFTER BAT BLOCK IS WRITTEN
ERFIN5:	HRRZ	P1,DEVUFB##(F)	;LOC OF UFB
	JUMPE	P1,CPOPJ##	;NO UFB IF SUPER IO
	PUSHJ	P,UPAU##	;GET AU RESOURCE
	MOVE	T1,UFBUN1##(P1)	;UNIT OF UFD
	LDB	T2,UN1PTR##	;NUMBER (IN STR) OF UNIT
	PUSHJ	P,NEWUNI##	;SET U TO UNIT DB
	  STOPCD DWNAU##,DEBUG,IUN,	;++INVALID UNIT NUMBER
	SKIPE	T2,UFBPT1##(P1)	;1ST RETRIEVAL POINTER OF UFD
	PUSHJ	P,CNVPTR##	;GET ADDRESS
	JFCL			;BAD UNIT-CHANGE PNTR!!!
	  PJRST DWNAU##		;UFB WAS DELETED - GIVE UP AU AND RETURN
	MOVE	T1,.USMBF	;IOWD FOR MON BUFFER
	MOVE	T2,DEVBLK##(F)	;BLOCK NUMBER OF UFD
	PUSHJ	P,MONRED##	;READ UFD RIB
	PJUMPN	T3,DWNAU##	;ERROR ON READ-GIVE UP AU AND RETURN
	HLLZ	T3,S
	TLZ	T3,IOSMER##	;ERROR BITS
	IORB	T3,RIBSTS##+1(T1)	;MARK IN LH(RIBSTS)
	TRNN	T3,RIPNDL##	;DON'T WRITE UNCLEARABLE BITS
	PUSHJ	P,MONWRT##	;WRITE UFD RIB
	PJRST	DWNAU##		;GIVE UP AU AND RETURN
;CLOSE OUTPUT

CHNDIR==1		;BIT ON IN M IF CHANGE DIRECTORY ON A CLOSE

CLOSOU:
IFN FTSPL,<
	PUSHJ	P,SPTSTO	;TEST FOR SPOOL-MODE FIRST OUTPUT
	  JRST	SETIMP		;IT WAS, AND ERROR ON ENTER - SET IOIMP
>
	TLNN	F,ENTRB+RENMB	;ENTER OR RENAME DONE?
	POPJ	P,		;NO. RETURN
	HRRZ	T1,DEVACC##(F)	;LOC OF ACCESS TABLE
	JUMPE	T1,CPOPJ##	;RETURN IF NONE
	PUSHJ	P,SAVE4##	;SAVE SOME ACS
	TLZN	S,IOSWLK	;STR WRITE-LOCKED?
	JRST	CLSOU1		;NO
	HRRZ	U,DEVFUN##(F)	;SET U IN CASE WRITE-LOCKED, NOT LOGGED-IN
	JRST	CLRSTS		;AND FINISH UP (WITHOUT WRITING ON THE DISK)
CLSOU1:	TLNN	S,IOSRST	;RESET OF A SPOOLED OUTPUT DEV?
	TLNN	F,ENTRB		;NO, RENAME ONLY?
	JRST	NOOUTP		;YES, DON'T FIDDLE WITH BUFFERS
	TLO	F,OCLOSB	;TURN ON OCLOSB (SPTSTO MIGHT HAVE ZEROED IT)
	LDB	T2,PIOMOD##	;MODE OF FILE
	CAIGE	T2,SD		;BUFFERRED MODE?
	TLNE	F,RESETB	;YES. FROM RESET UUO?
	JRST	NOOUTP		;YES. DON'T WORRY ABOUT LAST BUFFER
	HLRZ	T2,DEVBUF(F)	;OUTPUT LAST BUFFER LOC OF HEADER
	JUMPE	T2,NOOUTP
	EXCTUX	<SKIPG T3,@T2>	;VIRGIN RING?
	JRST	NOOUTP		;YES. NOTHING TO OUTPUT
	AOS	T2		;NO. POINT TO POINTER WORD
	EXCTUX	<HRRZ T4,@T2>	;LAST WORD FILLED
	SKIPE	T4		;IGNORE IT IF 0
	SUBI	T4,1(T3)	;-1ST WORD=LENGTH OF LAST BUFFER
	TRNN	S,IOWC		;USER COMPUTING OWN WORD COUNT?
	JRST	CLSOU2		;NO, SKIP ON
	HLL	T3,T2		;SET TO RELOCATE BUFFER POINTER
	AOS	T1,T3		;GET ADDR OF USER WORD COUNT IN T1,T3
	PUSHJ	P,UADRCK##	;MAKE SURE LEGAL, NO RETURN IF NOT
	EXCTUX	<HRRZ T4,@T3>	;GET USER WORD COUNT
CLSOU2:	JUMPE	T4,NOOUTP	;DON'T OUTPUT IF LENGTH .LE. 0
	TLZA	S,IOSRIB	;RIB IS NO LONGER IN MON BUF
				;(OUTPUT MAY READ RIB BACK)
CLSOU3:	IORM	T1,DEVADV(F)	;MAKE SURE UUOCON DOESN'T ADVANCE BUFFERS
	PUSHJ	P,OUT##		;WRITE THE LAST BUFFER
	PUSHJ	P,PWAIT1##	;WAIT FOR IT
	MOVEI	T1,DEPOND
	TLNE	S,IOSTBL	;CLOSE HAVE A PARTIAL BUFFER LEFT?
	JRST	CLSOU3		;YES, TRY ONCE MORE TO GET LAST BUFFER OUT
	ANDCAM	T1,DEVADV(F)	;CAN ADVANCE BUFFERS ONCE AGAIN
	TLO	F,OUTPB		;REMEMBER AN OUTPUT WAS DONE
	MOVSI	T1,DEPFFA	;FILOP. UPDATE RIB BIT
	MOVEI	T2,UP.MLB	;THE MERGE LAST BLOCK BIT
	TDNE	T1,DEVJOB(F)	;ARE WE INSIDE FOP.UR?
	IORM	T2,.USBTS	;YES - REMEMBER WE DID OUTPUT
;HERE WHEN THE FILE IS COMPLETELY WRITTEN
NOOUTP:	SKIPL	DEVSPL(F)	;SPOOLING DDB?
	JRST	NOOUT0		;NO, CONTINUE ON
	TLNE	F,OUTPB		;ANY OUTPUTS DONE?
	TRZA	M,CLSRST	;YES, NEVER DO RESET
	TRO	M,CLSRST	;NO, DON'T CREATE NULL FILE
NOOUT0:	TRNE	M,CLSRST	;CLOSE-RESET?
	TLO	F,RESETB	;YUP!
	PUSHJ	P,SETU##	;SET UP U FROM DDB
	  POPJ	P,		;A.T. WAS FIXED IF STR WAS YANKED
	TLNN	F,OCLOSB	;OUTPUT FILE BEEN CLOSED?
	TLNN	F,ENTRB		;NO. HAS AN ENTER BEEN DONE?
	SKIPA	T2,DEVACC##(F)	;NO. JUST GET LOC OF A.T.
	PUSHJ	P,CLSNAM	;YES. RESET DEVFIL, DEVEXT
				;(ELSE ENTER, RENAME WITH NO CLOSE LOSES)
	MOVE	T2,ACCSTS##(T2)	;STATUS OF FILE
	TRNE	T2,ACPUPD+ACPPAL##	;UPDATING OR PRE-ALLOCATED?
	TLZ	F,RESETB	;YES. MAKE SURE FILE ISNT DELETED
	MOVE	T1,DEVACC##(F)	;IF THIS IS A SIMULTANEOUS UPDATE FILE
	MOVE	T1,ACCSMU##(T1)	; GET THE DA RESOURCE AS A GUARD AGAINST
	TRNE	T1,ACPSMU	; RACE CONDITIONS INVOLVING RIBS
	PUSHJ	P,UPDA##	; GET DA BEFORE READING THE RIB


	TLOE	S,IOSRIB	;PRIME RIB IN CORE?
	JRST	NOOUT1		;YES, NO REASON TO READ
	PUSHJ	P,RIBCUR##	;NO. READ THE RIB
	JUMPE	T3,NOOUT1	;GO IF NO RIB ERROR
	TLNE	S,IOSDA		;RIB ERROR - HAVE DA?
	PUSHJ	P,DWNDA##	;YES (SIM UPDATE). RETURN IT
	JRST	NOOUT2		;AND CONTINUE

NOOUT1:	PUSHJ	P,SPTRW##	;SET AN AOBJN WORD FOR THE RETRIEVAL PNTRS
	MOVE	P1,T1		;SAVE POINTER IN P1
	PUSHJ	P,DD2MN##	;COPY LAST DDB POINTERS TO MON BUF
	  JFCL			;MAY OVERFLOW FROM  LAST 0'S IN DDB
	SKIPGE	DEVRIB##(F)	;EXTENDED RIB?
	PUSHJ	P,WRTRIB##	;YES WRITE IT NOW
				;PRIME RIB WILL GET WRITTEN LATER

	TLZN	F,RESETB	;RESET BEING PERFORMED?
	JRST	CLSOU4		;NO. CONTINUE
	SKIPL	DEVRIB##(F)	;IN EXTENDED RIB?
	JRST	NOUT1A		;NO
	PUSHJ	P,REDRIB##	;READ PRIME RIB
	  JRST	CLRSTS		;ERROR READING RIB
NOUT1A:

	PUSHJ	P,DECSU		;SET P2 TO DECR
	PUSHJ	P,ATRMOV##	;GET RID OF A.T.
	PUSHJ	P,DECUC		;DECREMENT USE-COUNTS
	PUSHJ	P,DECUSA	;DECREMENT USE-COUNT OF SFD A.T.
	PUSHJ	P,SFDDEC	;DECREMENT NMB/PPB COUNT OF SFD
	SETZM	DEVSFD##(F)	;WIPE THE POINTER
	HLLZS	DEVACC##(F)	;YES. SET DEVACC=0
	HLRZ	U,DEVUNI##(F)	;SET U TO UNIT OF (1ST) RIB
	JRST	CLSDL1		;AND DELETE THE FILE

;HERE ON A RIB ERROR TRYING TO CLOSE THE FILE
;DON'T DESTROY OLD VERSION IF SUPERSEDE, ENTER FILE IN UFD ANYWAY
;IF CREATE (DAMAGE ASSESMENT MAY MAKE SOME SENSE OUT OF IT LATER)
NOOUT2:	HRRZ	T1,DEVACC##(F)	;LOC OF A.T.
	JUMPE	T1,CLRSTS	;GO IF UNIT WAS YANKED
	HRLZ	T2,ACCSTS##(T1)	;STATUS
	HLRZ	U,DEVUNI##(F)	;MAKE SURE U IS OK (MAY NOT BE IF UFD CFP ERR)
	MOVE	P3,U		;SET UP P3 FOR SETCFP
	TLNE	T2,ACPUPD	;UPDATE?
	DPB	T2,ACZFSN##	;YES, DON'T USE THIS A.T. AGAIN
	TLNN	F,RESETB	;CLOSE ACTING LIKE RESET?
	TLNN	T2,ACPCRE	;CREATE?
	JRST	CLRSTS		;NO, DON'T TOUCH OLD FILE
	JRST	CLSR11		;YES, ENTER NAME IN UFD
;HERE WITH THE RIB IN CORE, AND ALL PNTRS IN THE RIB
CLSOU4:
	MOVE	T1,DEVACC##(F)	;IF THIS IS AN UPDATE FILE
	MOVE	T2,ACCSTS##(T1)
	TRNN	T2,ACPUPD
	JRST	CLSSIM
	LDB	T2,ACYWCT##	;IF SIM-UPD FILE
	SOJLE	T2,CLSSIM
	TLZ	M,400000	;INDICATE NOT A DIRECTORY TO CLSRI5
	SKIPL	DEVRIB##(F)	;NOT LAST WRITER - IN PRIME RIB?
	JRST	CLSRI5		;YES, JUST UPDATE DATES
	PUSHJ	P,REDRIB##	;READ PRIME RIB
	  JRST	NOOUT2		;RIB ERR
	JRST	CLSRI5		;AND GO UPDATE DATE/TIME
CLSSIM:	PUSHJ	P,DOWNIF##	;LADT WRITER - GIVE UP DA
	MOVE	T1,P1		;AOBJN WORD FOR POINTERS
CLSLUP:	HRRZ	T4,DEVACC##(F)	;LOC OF ACC
	MOVE	T3,ACCWRT##(T4)	;HIGHEST WRITTEN BLOCK OF FILE
	MOVE	T4,.USMBF	;IOWD FOR MONITOR BUFFER
	MOVE	T2,RIBFLR##+1(T4) ;GET FIRST BLOCK NUMBER IN RIB
	SKIPL	DEVRIB##(F)	;EXTENDED RIB?
	SETZ	T2,		;NO, ZERO STARTING BLOCK IN CASE OLD FILE
	PUSHJ	P,SCNPTR##	;GET THE POINTER FOR THIS BLOCK
	  JRST	CLSOU6		;NOT IN THIS RIB, LOOK IN NEXT
	MOVE	P1,T1		;AOBJN WORD STARTING AT LAST POINTER USED
	AOS	DEVBLK##(F)	;POINT TO 1ST BLOCK AFTER LAST WRITTEN
	AOS	DEVREL##(F)	;POINT TO LAST RELATIVE BLOCK DESIRED
	AOBJN	T1,.+2		;IF IN LAST POINTER,
	AOSA	T1,DEVLFT##(F)	; DEVLFT HAS BEEN ADJUSTED

	HRRZ	T1,DEVLFT##(F)	;NUMBER OF BLOCKS LEFT IN THIS PNTR
	SOJN	T1,CLSRIB	;GO IF THERE IS A BLOCK IN PNTR FOR  LAST RIB
CLSOU5:	AOBJP	P1,CLSOU8	;STEP TO NEXT POINTER SLOT
	SKIPE	T2,(P1)		;IS THERE ONE?
	JRST	CLSO12		;YES. USE IT
	SUB	P1,[XWD 1,1]	;NO. BACK UP P1 TO LAST PNTR
;HERE WHEN WE HAVE TO ALLOCATE 1 MORE CLUSTER TO WRITE THE LAST RIB OF THE FILE
	HRRM	P1,DEVRET##(F)	;SET DEVRET TO POINT TO LAST PNTR
	MOVEI	T2,1		;WE WANT TO ALLOCATE 1 BLOCK
	PUSHJ	P,CHKADD##	;CAN WE ADD TO CURRENT POINTER?
	JUMPE	T2,CLSOU9	;IF T2=0 CANT ADD
	MOVE	T1,DEVBLK##(F)	;1ST BLOCK AFTER HIGHEST WRITTEN BLOCK
	PUSHJ	P,TAKBLK##	;TRY TO GET 1 CLUSTER STARTING THERE
	  JRST	CLSOU9		;CANT GET IT THERE - TRY ANYWHERE
	PUSHJ	P,DOWNIF##	;TAKBLK KEEPS DA IF SIM. UPD.

	PUSHJ	P,ADDPTR##	;GOT IT. ADD TO CURRENT POINTER
	JRST	CLSRIB		;AND CONTINUE


;HERE TO LOOK FOR THE LAST WRITTEN BLOCK IN THE NEXT RIB
CLSOU6:
	SKIPLE	DEVRIB##(F)	;PRIME RIB IN CORE?
	PUSHJ	P,WRTRIB##	;YES, WRITE IT (MIGHT HAVE CHANGED)
	PUSHJ	P,PTRNXT##	;GET THE NEXT RIB INTO CORE
	JRST	CLSOU7		;EITHER ERROR OR NONE
	PUSHJ	P,SPTRW##	;PUT AOBJN WORD TO POINTERS IN T1
	JRST	CLSLUP		;GO SCAN THIS RIB
CLSOU7:	JUMPN	T3,NOOUT2	;IF T3 NON-ZERO, ERROR
	STOPCD	NOOUT2,DEBUG,NER,	;++NO EXTENDED RIB
;HERE WHEN POINTERS RAN OUT, WE KNOW THERE IS ONE MORE BLOCK IN THE LAST POINTER
CLSOU8:	SUB	P1,[XWD 1,1]	;BACK UP TO LAST POINTER
	AOJA	T1,CLSRIB	;FORCE DEVLFT TO BE 1
;HERE WHEN WE HAVE TO CREATE A NEW POINTER TO ALLOCATE THE LAST BLOCK
CLSOU9:	AOBJP	P1,CLSFUL	;STEP TO NEXT POINTER SLOT
	HRRM	U,DEVUNI##(F)
CLSO10:	PUSHJ	P,SUPDA##
	HRRM	P1,DEVRET##(F)	;SAVE LOC OF NEW POINTER (IN MON BUF)
	SKIPLE	UNITAL##(U)	;UNIT HAVE ANY SPACE LEFT?
	JRST	CLSO11		;YES
	PUSHJ	P,DWNDA##
	PUSHJ	P,NEXTUN##	;NO. STEP TO NEXT UNIT
	  JRST	CLSFUL		;NO UNIT IN STR HAS SPACE!
	AOBJN	P1,CLSO10	;FOUND. STEP TO NEXT PNTR LOC IF ROOM IN RIB
	SETZM	@DEVRET##(F)	;NO ROOM IN RIB - ZERO UNIT-CHANGE
	HRRZ	U,DEVUNI##(F)	;RESET U TO LAST UNIT IN RIB
				;AND FALL INTO CLSFUL


;HERE WHEN THERE IS NO SPACE IN STR, OR ALL POINTER SLOTS ARE TAKEN
CLSFUL:	TRO	S,IOBKTL	;LIGHT ERROR BIT
	HRRZ	T2,DEVACC##(F)	;LOC OF ACC
	SOSGE	ACCWRT##(T2)	;DECREASE AMOUNT WRITTEN BY 1
	JRST	CLSFL2		;NOTHING WRITTEN
	SOS	DEVREL##(F)	;POINT TO LAST RELATIVE BLOCK DESIRED
	SOS	DEVBLK##(F)	;POINT TO LAST DATA BLOCK
	HRRI	M,CLSDLL	;INDICATE DON'T DELETE ANYTHING ON CLOSE
	HRRZ	U,DEVUNI##(F)	;SET U TO UNIT WITH LAST DATA
	MOVEI	T1,BLKSIZ##	;REINITIALIZE COUNT
	DPB	T1,ACYLBS##
	JRST	CLSRI1		;GO WRITE LAST RIB OVER LAST DATA BLOCK

;HERE WHEN NO ROOM IN STR, AND ACCWRT = 0
;DELETE THE FILE (WHICH IS JUST THE 1ST RIB)
CLSFL2:	SUB	P1,[XWD 1,1]	;SET P1 = AOBJN WORD
	PUSHJ	P,DELRIB	;GIVE BACK THE BLOCK
	  STOPCD .+1,DEBUG,DER,	;++DELRIB ERROR RETURN
	PJRST	CLRSTS		;FINISH UP (DON'T WRITE UFD)

;HERE WHEN A UNIT HAS BEEN FOUND WITH SPACE ON IT
CLSO11:	MOVEI	T2,1		;WE WANT 1 BLOCK
	SETZ	T1,		;ANYWHERE ON THE UNIT
	PUSHJ	P,TAKBLK##	;GET A CLUSTER
	  STOPCD .,STOP,UFI,	;++UNIT FREE-COUNT INCONSISTENT
	MOVEM	T2,(P1)		;SAVE THE PNTR IN THE MON BUF
	HRRZ	T1,DEVACC##(F)	;LOC OF A.T.
	MOVEI	T3,ACP1PT##	;TURN OFF 1PT BIT IN A.T.
	ANDCAM	T3,ACC1PT##(T1)
CLSO12:	PUSHJ	P,CNVPTR##	;CONVERT POINTER TO COUNT, ADDRESS
	  JRST	NOOUT2		;BAD UNIT-CHANGE PNTR
	  JRST	CLSOU5		;UNIT CHANGE - TRY NEXT POINTER
;HERE WITH DEVBLK,DEVREL,DEVLFT SET TO REDUNDANT LAST RIB BLOCK
CLSRIB:	HRRM	T1,DEVLFT##(F)	;SAVE COUNT OF BLOCKS LEFT IN PNTR
CLSRI1:
	MOVE	T1,DEVRIB##(F)	;GET DEVRIB INTO T1 IN CASE NOT GO TO UPDGIV

	TRNE	M,CLSDLL	;DELETE UNWRITTEN BLOCKS FROM FILE?
	JRST	CLSRI2		;NO
	PUSH	P,DEVRIB##(F)	;SAVE POINTER TO CURRENT RIB

	MOVE	P2,DEVBLK##(F)	;YES. SAVE BLOCK OF RIB
	MOVE	P3,DEVREL##(F)	;SAVE DEVREL IN CASE UPDGIV CHANGES IT
	PUSHJ	P,UPDGIV	;GIVE UP THE UNWRITTEN BLOCKS OF THE FILE
	  STOPCD .+1,DEBUG,SBT,	;++SHOULDN'T BE TRUNCATING
	MOVEM	P3,DEVREL##(F)	;RESTORE TO DDB
	MOVEM	P2,DEVBLK##(F)	;RESTORE BLOCK NO. OF LAST RIB
	POP	P,T1		;RESTORE PREVIOUS CURRENT RIB TO T1

CLSRI2:
	SKIPL	DEVRIB##(F)	;SKIP IF NOT IN PRIME RIB
	JRST	CLSRI4		;PRIME RIB, GO WRITE REDUNDANT
	CAME	T1,DEVRIB##(F)	;ARE WE STILL IN THE SAME EXTENDED RIB?
	JRST	CLSRI3		;NO, GET PRIME
	PUSHJ	P,WRTRIB##	;WRITE OUT THE CURRENT RIB
CLSRI3:	PUSHJ	P,REDRIB##	;GET THE PRIME RIB INTO CORE
	  JRST	NOOUT2		;ERROR READING RIB

CLSRI4:	TLZ	M,400000
	HLRZ	T1,DEVEXT(F)	;EXTENSION OF FILE
	CAIN	T1,(SIXBIT .SFD.)	;AN SFD?
	TLOA	M,400000	;YES, LIGHT SIGN BIT, DON'T CHANGE UFB
	CAIE	T1,(SIXBIT .UFD.)	;A UFD?
	JRST	CLSRI5		;NO
	TLO	M,400000	;INDICATE FILE IS A DIRECTORY
	PUSHJ	P,FNDUFB	;YES. FIND UFB FOR FILE
	  JRST	CLSRI5		;NOT THERE - CONTINUE
	PUSHJ	P,SPTRW##	;%FOUND - SET AOBJN WORD FOR PNTRS
	MOVE	T3,(T1)		;%UNIT OF UFD
	DPB	T3,COYUN1##	;%SAVE UNIT IN UFB
	MOVE	T1,1(T1)	;%FIRST REAL POINTER
	MOVEM	T1,UFBPT1##(T2)	;%SAVE IN UFB
	PUSHJ	P,GVCBJ##	;%RETURN CB RESOURCE
CLSRI5:	MOVE	T1,.USMBF	;IOWD FOR MON BUF
	HRRZ	P1,DEVACC##(F)	;LOC OF A.T.
	JUMPE	P1,CLRSTS	;GO IF UNIT YANKED
	SKIPE	T4,ACCWRT##(P1)	;NO. OF BLOCKS WRITTEN
	SUBI	T4,1		;-1
	LSH	T4,BLKLSH##	;*128
	MOVE	T3,P1
	LDB	P2,ACZLBS##	;SIZE OF LAST BLOCK
	JUMPGE	M,CLSRI6	;IF THE FILE IS A DIRECTORY
	SKIPE	ACCWRT##(P1)	; WHICH IS NOT EMPTY,
	MOVEI	P2,BLKSIZ##	; MAKE SURE THE LAST BLOCK IS "FULL"
	DPB	P2,ACZLBS##	;SAVE NEW SIZE IN ACC
CLSRI6:	ADD	T4,P2		;TOTAL NUMBER OF WORDS IN FILE
	MOVEM	T4,RIBSIZ##+1(T1)	;SAVE IN RIB
	MOVEI	T2,RIPPAL##
	MOVE	T3,DEVPAL##(F)	;PRE-ALLOCATING?
	TRZE	T3,DEPPAL##
	TLNE	F,OUTPB		;YES, OUTPUT DONE?
	JRST	CLSRI7		;NOT PRE-ALLOCATING OR WRITTEN
	IORM	T2,RIBSTS##+1(T1)	;PRE-ALLOCATED, LIGHT BIT
	JRST	CLSRI8
CLSRI7:	MOVEM	T3,DEVPAL##(F)	;ENSURE DEPPAL=0
	ANDCAM	T2,RIBSTS##+1(T1)	; AND THE BIT IS OFF
CLSRI8:	MOVE	T2,ACCSTS##(P1)	;STATUS OF FILE
	TLNN	F,RENMB		;FILE BEING RENAMED?
	TRNE	T2,ACPUPD	;UPDATE?
	TLNN	F,OUTPB+INPB	;YES, ANY OUTPUTS OR INPUTS DONE?
	JRST	CLSRI9		;NO
	MOVE	T3,TIME##	;YES, ACCESS DATE
	IDIV	T3,TICMIN##	;T3=TIME RIGHT ADJUSTED
	HRRZ	T4,THSDAT##	;DATE
	DPB	T4,[POINT 15,ACCADT##(P1),17]	;SAVE NEW ACCESS DATE
	DPB	T4,[POINT 15,RIBEXT##+1(T1),35]	; IN RIB AND A.T.
	TLNN	F,OUTPB		;OUTPUTS DONE?
	JRST	CLSR10		;NO, DON'T UPDATE CREATION DATE
	LDB	T2,[POINT 3,T4,23]	;HI PART OF CREATION DATE
	DPB	T3,[POINT 11,T4,23];POSITION TIME IN WORD
	MOVSI	T3,777740	;SET TO MASK OUT TIME,DATE
	AND	T3,RIBPRV##+1(T1)	;GET MODE, PROTECTION
	ORM	T3,T4		;PLUS NEW DATE, TIME
	MOVEM	T4,RIBPRV##+1(T1)	;SAVE NEW DATE, TIME WORD IN RIB
	MOVEM	T4,ACCPRV##(P1)	; AND IN ACC
	DPB	T2,[POINT 3,RIBEXT##+1(T1),20]	;SAVE HI CRE-DATE IN RIB
	DPB	T2,[POINT 3,ACCADT##(P1),2]	; AND IN A.T.
	MOVE	T3,DATE##	;MOVE NEW DATE TIME IN
	HRRZ	T4,RIBFIR##+1(T1)	;NO OF VALUES IN RIB
	CAIL	T4,RIBTIM##+1	;DON'T WIPE OUT 1ST PNTR IF OLD FILE
	MOVEM	T3,RIBTIM##+1(T1)
CLSRI9:	LDB	T2,UNYKNM##	;KONTROL NUMBER
	LSH	T2,17
	IOR	T2,.C0ASN##	;APR NUMBER
	HRRZ	T3,RIBUNI##+1(T1)
	CAIE	T3,(T2)		;SAME AS BEFORE?
	SETZM	RIBUNI##+1(T1)	;NO, NO UNITS YET WROTE
	HRRM	T2,RIBUNI##+1(T1)
	HLRZ	U,DEVUNI##(F)	;UNIT WITH RIB
	PUSHJ	P,ORINUN	;LIGHT BIT
	HRRZ	U,DEVUNI##(F)	;CURRENT UNIT
	PUSHJ	P,ORINUN	;LIGHT BIT
CLSR10:	MOVE	T3,ACCALC##(P1)	;AMOUNT OF SPACE ALLOCATED
	MOVEM	T3,RIBALC##+1(T1)	;SAVE IN RIB
	PUSHJ	P,SPTRW##	;GET AOBJN WORD FOR POINTERS
	MOVE	T2,1(T1)	;GET FIRST POINTER IN PRIME RIB
	MOVEM	T2,ACCPT1##(P1)	;MOVE TO ACC
	PUSHJ	P,TSTBAD	;SET RIBELB, ETC IF ERROR

	HLRZ	P3,DEVUNI##(F)	;SAVE FIRST UNIT IN P3 FOR LATER CALL TO SETCFP
ALLPT1:
	TLNE	S,IOSDA		;IF HAVE DA MUST BE SIM UPDATE
	JRST	ALLPT5		;SO JUST REWRITE PRIME RIB (WITH NEW DATES)

	MOVE	T2,RIBFLR##+1(T1)	;GET FIRST BLOCK NUMBER IN RIB
	SKIPL	DEVRIB##(F)	;SKIP IF EXTENDED RIB
	SETZ	T2,		;NOT EXTENDED, FIRST BLOCK =0
	SKIPN	T3,DEVREL##(F)	;DEVREL=0 MEANS INACTIVE RIB
	JRST	ALLPT2		;GO WRITE REDUNDANT RIB NEXT TO REAL
	PUSHJ	P,SCNPT0##	;SCAN THE RIB FOR THE BLOCK IN T3
	  JRST	ALLPT3		;NOT FOUND, MUST BE A FULL RIB
	SETZM	DEVREL##(F)	;FLAG THAT NEXT RIB(IF ANY) IS INACTIVE
	JRST	ALLPT4		;GO WRITE REDUNDANT

;HERE WHEN WORKING IN AN INACTIVE RIB (BLOCKS ALLOCATED BUT NOT USED)
ALLPT2:	MOVE	T3,T2		;GET NUMBER OF FIRST BLOCK IN RIB TO T3
	AOJ	T3,		;POINT TO NEXT BLOCK
	PUSHJ	P,SCNPT0##	;SCAN THE RIB FOR THIS BLOCK
	  STOPCD .,JOB,BMR,	;++BLOCK MISSING FROM RIB
	SETZM	DEVREL##(F)	;RESET THE INACTIVE RIB FLAG TO 0
	JRST	ALLPT4		;GO WRITE THE RIB
	;STILL IN FTDMRB CONDITONAL
;HERE TO WRITE THE REDUNDANT RIB IN THE LAST BLOCK OF THE RIB
ALLPT3:	PUSH	P,DEVREL##(F)	;SAVE FLAG FOR INACTIVE RIBS
	PUSHJ	P,GTLPT		;GET LAST RIB POINTER
	PUSHJ	P,CNVPTR##	;DECODE THE POINTER
	  JFCL			;BAD UNIT-CHANGE
	  STOPCD .,JOB,LPU,	;++LAST POINTER UNIT-CHANGE
	SOS	T2,T1		;LENGTH OF POINTER -1 TO T2
	ADDM	T2,DEVBLK##(F)	;BLOCK NUMBER FOR WRITE TO DDB
	POP	P,DEVREL##(F)	;RESTORE BLOCK FOR LAST ACTIVE REDUNDANT WRITE
;HERE TO WRITE RIB IN CORE REDUNDANTLY IN BLOCK NUMBER CONTAINED IN DEVBLK
ALLPT4:	MOVE	T1,.USMBF	;GET IOWD FOR MONITOR BUFFER
	MOVE	T2,DEVBLK##(F)	;GET BLOCK NUMBER FOR REDUNDANT WRITE
	MOVEM	T2,RIBSLF##+1(T1) ;PUT IN RIB
	MOVEI	T3,CODRIB##	;777777 TO RH(T3)
	MOVEM	T3,RIBCOD##+1(T1)	;MAKE SURE CODE IS IN RIB
	TLNE	F,RENMB		;DOING A RENAME?
	PUSHJ	P,NAMNW		;YES, PUT NEW NAME,EXT AND PPN IN RIB
	PUSHJ	P,MONWRU##	;WRITE REDUNDANT RIB (KEEP OUT OF DISK CACHE)
ALLPT5:	PUSHJ	P,WRTRIB##	;WRITE REAL RIB
	JUMPE	T3,ALLPT6	;GO IF WRITTEN OK
	MOVE	T1,DEVACC##(F)
	HRLZ	T2,ACCSTS##(T1)	;IF AN UPDATE FILE
	TLNE	T2,ACPUPD
	DPB	T2,ACZFSN##	;MAKE SURE A.T. ISN'T FOUND LATER
ALLPT6:	PUSHJ	P,RIBSAT	;WRITE SATS WHICH HAVE CHANGED
	MOVE	T1,.USMBF	;IOWD TO MONITOR BUFFER
	PUSH	P,RIBXRA##+1(T1) ;GET POINTER TO NEXT RIB (IF ANY)
	SKIPGE	DEVRIB##(F)	;PRIME RIB?
	JRST	ALLPT7		;NO, DON'T DO ANYTHING ABOUT BAT BLOCKS
	SKIPE	RIBFLR##+1(T1)	;SKIP IF EXTENDABLE RIB
	SETZM	(P)		;NOT EXTENDABLE, RIBFLR IS GARBAGE
	PUSH	P,U
	PUSHJ	P,ERRFIN	;YES, WRITE BAT BLOCK IF ERRORS
	POP	P,U

ALLPT7:	POP	P,DEVRIB##(F)	;GET POINTER FROM PREVIOUS RIB
	SKIPN	DEVRIB##(F)	;ANY MORE RIBS?
	JRST	ALLPT8		;NO, THROUGH
	PUSHJ	P,RIBCUR##	;READ THE NEXT RIB
	JUMPN	T3,NOOUT2	;IF T3 NON-ZREO, RIB ERROR
	JRST	ALLPT1		;TAKE CARE OF THE EXTENDED RIB

;HERE WHEN WE ARE FINISHED CLEANING UP SATS AND RIBS
ALLPT8:
	TLNN	S,IOSDA		;SIM UPDATE?
	JRST	CLSR11		;NO, CHANGE DIRECTORY
	PUSHJ	P,DWNDA##	;YES, GIVE UP DA SINCE RIB NOW WRITTEN
	JRST	CLRSTS		;AND FINISH THE CLOSE


;ROUTINE TO STORE THE CFP
;T1 PASSES THE CFP
;T2 PASSES ADDR OF NMB
SAVCFP:	HRRM	T1,NMBCFP##(T2)	;SAVE THE CFP
	HRRZ	T1,DEVACC##(F)	;SAVE FSN CFP IS FOR
	LDB	T1,ACZFSN##
	DPB	T1,NMYFSN##
	MOVE	T3,T2		;ADDR OF NMB
	PUSHJ	P,FSNPS2##	;POSITION A BIT
	ORM	T2,NMBYES##(T3)	;FILE EXISTS ON THIS STR
	POPJ	P,

;NOW CHANGE THE DIRECTORY
CLSR11:	PUSHJ	P,UPAU##	;GET AU RESOURCE
	HRRZ	P1,DEVACC##(F)	;LOC OF ACC
	MOVE	T1,ACCSTS##(P1)	;STATUS OF FILE
	TRNE	T1,ACPCRE	;CREATING?
	JRST	NOTOLD		;YES
	HRRZ	T3,ACCPPB##(P1)	;NO. LOC OF PPB
	MOVE	T4,PPBNAM##(T3)	;NEW PRJ,PRG NUMBER
	CAME	T4,DEVPPN(F)	;SAME AS OLD?
	JRST	NOTOL1		;NO. CREATE FILE IN NEW DIR.

	TLNN	F,RENMB		;IF A RENAME WAS DONE,
	JRST	CLSR12
	MOVE	T3,DEVSFD##(F)	;DEFAULT SFD
	HLRZ	T4,T3		;ORIGINAL SFD
	CAIE	T4,(T3)		;SAME AS "NEW" SFD?
	JRST	NOTOL1		;NO, CREATE THE NAME IN NEW SFD
	HLRZ	T4,DEVEXT(F)	;RENAMED A UFD
	CAIE	T4,'UFD'	;NO NEED TO RE-WRITE MFD
CLSR12:	TRNE	T1,ACPNIU+ACPUPD	;YES, FILE BEEN REMOVED FROM DIRECTORY OR JUST UPDATE?
	JRST	CLRST2		;YES, DON'T HAVE TO CHANGE DIRECTORY
	TRNN	T1,ACPREN	;IF FILE NOT BEING RENAMED,
	TRNN	T1,ACPPAL##	;IF PRE-ALLOCATED
	CAIA
	JRST	CLRST2		; LEAVE THE UFD ALONE
	PUSHJ	P,UFDSRC##	;NO. FIND FILE NAME IN DIRECTORY
	  JRST	NOTOLD		;CANT FIND IT - CREATE NEW NAME
	EXCH	P1,T1		;P1 HAS CFP, T1 HAS LOC OF ACC
	PUSHJ	P,GTNM1		;FIND NMB
;HERE WITH T1=LOC OF NMB FOR THE FILE
	MOVE	T2,NMBNAM##(T1)	;(NEW) FILE NAME
	MOVEM	T2,UFDNAM##(T3)	;SAVE IN DIRECTORY
	HRLZ	T4,NMBEXT##(T1)	;(NEW) EXTENSION
	HLLM	T4,UFDEXT##(T3)	;SAVE IN DIRECTORY
	HRLM	T3,P1		;SAVE LOC OF DIRECTORY SLOT
	PUSH	P,T1		;SAVE LOC OF NMB
	PUSHJ	P,SETCFP##	;COMPUTE CFP FROM A.T. AND U
	HLRZ	T3,P1		;LOC OF DIRECTORY SLOT
	HRRM	T1,UFDCFP##(T3)	;SAVE CFP IN UF
	MOVE	T2,(P)		;LOC OF NMB
	HRRZ	T3,DEVACC##(F)	;SAVE ACPSUP
	HRL	P1,ACCSTS##(T3)
	PUSHJ	P,NEWCFP	;SAVE CFP IN NMB
	  JFCL
	PUSHJ	P,WRTDIR	;GO WRITE THE UPDATED DIRECTORY BLOCK
	;PUSHJ	P,DWNAU##	;DON'T GIVE UP AU UNTIL WE'RE
				; DONE WITH DELRIB. ELSE SOMEBODY
				; ELSE CAN SNEAK IN A DELETE WHILE
				; WE'RE BLOCKED IN RIBCUR
	TLNE	P1,ACPSUP	;SUPERSEDER?
	JRST	ALLPT9		;YES. REMOVE OLD FILE
	POP	P,T1		;NO. REMOVE JUNK FROM PD LIST
	JRST	CLRSTS		;AND FINISH UP
ALLPT9:	HRRZ	T1,P1		;CFP FOR THE OLD FILE
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
ALLP10:	CBDBUG	(N,Y);

	LDB	P1,ACYFSN##	;STR NUMBER

	PUSHJ	P,CFP2BK##	;CONVERT TO BLOCK ADR
	  JRST	ALLP11		;CFP BAD - LEAVE OLD FILE ALONE
	SETZM	DEVRIB##(F)	;ZERO OUT DEVRIB FOR DPB'S
	LDB	T3,UNYLUN##	;GET LUGICAL UNIT NUMBER FOR UFD RIB
	DPB	T3,DEYRBU##	;DEPOSIT IN RIB POINTER
	LDB	T3,UNYBPC##	;GET NUMBER OF BLOCKS PER CLUSTER
	IDIV	T2,T3		;CONVERT BLOCK NUMBER TO CLUSTER NUMBER
	DPB	T2,DEYRBA##	;TO DDB
	PUSHJ	P,RIBCUR##	;GET THE RIB POINTER AT BY DEVRIB INTO CORE
	JUMPN	T3,ALLP11	;JUMP IF RIB ERROR, LEAVE OLD FILE ALONE
	PUSHJ	P,SPTRW##	;SET AN AOBJN WORD FOR PNTRS
	EXCH	P1,T1		;P1=AOBJN WORD, T1=FSN
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	POP	P,T2		;%LOC OF NMB
	TRO	T2,DIFNAL##	;%ADJUST FOR ACCNMB
DELTST:	PUSHJ	P,BYTSC1##	;%SEARCH FOR AN A.T.
	  SKIPA	T3,ACCSTS##(T2)	;%FOUND ONE. GET STATUS
	JRST	CLSDL3		;%NO A.T. TO DELETE
	TRNE	T3,ACPCRE+ACPUPD+ACPSUP+ACPREN	;%FILE JUST READING?
	JRST	DELTST		;%NO. IGNORE IT
	MOVE	T4,DEVACC##(F)	;%IF A LOOKUP GOT THROUGH FNDFIL
	MOVE	T4,ACCPT1##(T4)	;% AND READ THE NEW RIB AFTER
	CAME	T4,ACCPT1##(T2)	;% OUR CALL TO WRTUFD HE IS READING
	JRST	DELTS1		;% THE NEW FILE, WHICH WE SHOULDN'T DELETE
	HRRZ	T2,DEVACC##(F)	;%DELETE OUR A.T. AND THE OLD FILE
	JRST	CLSDEL		;% LEAVING THE OTHER A.T. ALONE
;HERE WITH T2=LOC OF AN A.T. WHICH MUST BE DELETED
DELTS1:	LDB	T4,ACZCNT##	;%FILE DORMANT?
	JUMPE	T4,CLSDEL	;%YES, DELETE A.T., FILE
	TRNN	T3,ACPDEL##	;%ALREADY MARKED FOR DELETION ?
	JRST	DELTS2		;%NO, MARK IT
	MOVE	T3,1(P1)	;% IF THE A.T. WE FOUND
	CAME	T3,ACCPT1##(T2)	;% IS NOT FOR THIS FILE
	JRST	DELTST		;% THEN THE FILE CAN BE DELETED NOW
DELTS2:	MOVEI	T1,ACPDEL##+ACPNIU ;MARK FILE TO BE DELETED ON CLOSE
	ORM	T1,ACCDEL##(T2)	;SO FILE WILL DISAPPEAR WHEN READ COUNT EXHAUSTED
	PUSHJ	P,GVCBJ##	;%RELEASE CB RESOURCE
	JRST	CLRSTS		;AND FINISH UP

;HERE WHEN THERE IS NO A.T. TO REMOVE
CLSDL3:	PUSHJ	P,GVCBJ1##	;%GIVE UP CB AND SKIP

;HERE WITH T2=LOC OF A.T. WHEN THERE IS AN A.T. TO REMOVE
CLSDEL:	PUSHJ	P,ATRMVX##	;REMOVE THE A.T. FROM SYSTEM

;HERE TO DELETE A FILE, WITH RIB IN MON BUF
CLSDL1:	MOVEI	P4,DEPALC##
	IORM	P4,DEVALC##(F)	;ACCALC SHOULD NOT BE CHANGED
	HRRZ	T1,DEVACC##(F)	;CLEAR SUPERSEDING BIT, SO
	JUMPE	T1,CLSDL2
	MOVEI	T2,ACPSUP	; SNUKIN CODE WILL WORK IF WE
	ANDCAM	T2,ACCSTS##(T1)	; GET RESCHEDULED AND A LOOKUP IS IN PROGRESS
	MOVEI	T2,ACPCNT##	;IF WE GET RESCHEDULED AND A LOOKUP/CLOSE HAPPENS
	ADDM	T2,ACCCNT##(T1)	; THE A.T. WILL BECOME DORMANT, SO BUMP READ-COUNT
CLSDL2:	PUSHJ	P,DELRIB	;DELETE THE FILE
	  STOPCD .+1,DEBUG,DCR,	;++DELRIB CPOPJ RETURN
	ANDCAM	P4,DEVALC##(F)	;CHANGE ACCALC AGAIN
	MOVNI	P4,ACPCNT##	;DECR READ-COUNT WHEN
	JRST	CLRSTX		; WE ARE THROUGH (CLRST0)
ALLP11:	POP	P,T1		;ERR READING RIB - REMOVE JUNK FROM PD LIST
	JRST	CLRSTS		;AND FINISH UP
;HERE TO CREATE A NEW NAME IN A DIRECTORY BLOCK
NOTOLD:
	TRZA	M,-1		;NO OLD DIR
NOTOL1:	HRRI	M,CHNDIR	;INDICATE DELETE NAME FOM OLD DIR

	HRRZ	T1,DEVACC##(F)	;IF ACPNIU IS LIT, WE MUST BE DOING
	MOVE	T1,ACCSTS##(T1)	; A RENAME ACCROSS DIRS AND SOMEBODY
	TRNE	T1,ACPNIU	; SNUCK IN WITH A LOOKUP AND RENAME TO 0.
	JRST	FNDFRY		; SO DON'T PUT IT IN THE DIR
	PUSHJ	P,DIRSET##	;GET RETRIEVAL PNTRS TO READ THE DIR
	  TROA	S,IOIMPM	;NOT THERE - LIGHT AN ERROR BIT
	JRST	NOTOL3		;THERE IS A REAL PNTR
	PUSHJ	P,DWNAU##	;GIVE UP AU RESOURCE
	PUSHJ	P,SPTRW##	;SET AN AOBJN WORD FOR WHOLE RIB PNTRS
	EXCH	P1,T1		;P1=AOBJN WORD, T1=LOC OF A.T.
	MOVE	T2,T1		;A.T. LOC INTO T2
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	JRST	CLSDEL		;%DELETE THE FILE WHICH WAS JUST WRITTEN
NOTOL3:	PUSHJ	P,SETFS0##	;SET UP TO READ DIRECTORY
	  JRST	BADUFD		;ERROR READING DIRECTORY - CANT ENTER NAME
IFN FTDUFC,<			;IF KEEP FILES IN ORDER IN UFO
	PUSHJ	P,UFORSS##	;GET UFB OR SFD A.T. LOC
	TRZE	T3,NMPSFU##	;AN SFD?
	SKIPA	P2,ACCWRT##(T3)	;YES, GET SIZE FROM ACCWRT
	LDB	P2,UFYWRT##	;NO OF DATA BLOCKS IN DIRECTORY
;IN THE FOLLOWING CODE, P4 IS A FLAG THAT TELLS YOU WHETHER OR NOT TO COMPRESS:
;P4=NEGATIVE, NEVER COMPRESS
;P4=ZERO, SOMETIMES COMPRESS (ONLY COMPRESS IF YOU REALLY HAVE TO)
;P4=POSITIVE, ALWAYS COMPRESS
	HLRZ	P4,UFBZRB##(T3)	;"ALWAYS" COMPRESS IF BLOCK OF ZEROES
	ANDI	P4,UFPZRB##
	CAIGE	P2,2		;NEVER COMPRESS UNLESS AT LEAST TWO BLOCKS
	SETO	P4,
	JUMPE	P2,UFDNXT	;DON'T TRY TO READ ZERO LENGTH DIR
	JUMPLE	P4,NOTO3B	;ONLY CALL CMPOK IF GOING TO COMPRESS
	PUSHJ	P,CMPOK		;OK TO COMPRESS?
	  TLOA	P4,-1		;NO
	JRST	UFDNXT		;YES, DO IT NOW
NOTO3B:	MOVE	T2,DEVDMP##(F)	;ADR OF RIB
	ADD	T2,P2		;(PROBABLE) DIRECTORY BLOCK
	HRRZ	T4,DEVLFT##(F)	;NO OF BLOCKS IN FIRST POINTER
	CAIG	P2,(T4)		;IS BLOCK TO WRITE IN 1ST PNTR?
	JRST	NOTOL6		;YES
	PUSHJ	P,UFDCRD	;NO, READ DIRECTORY RIB
	  JRST	BADUFD		;ERROR READING RIB
	SETZ	T2,		;START AT 1ST PNTR
	MOVE	T3,P2		;BLOCK WE'RE LOOKING FOR
	PUSHJ	P,SCNPT0##	;GO FIND PNTR TO BLOCK
	  STOPCD .,JOB,BNR,	;++BLOCK NOT RIB
	MOVEM	T2,DEVFLR##(F)	;SAVE LOWEST BLOCK IN DDB
	PUSHJ	P,PTRBLT##	;COPY PNTRS INTO DDB
	MOVE	T2,DEVBLK##(F)	;DIRECTORY BLOCK TO WRITE
	JRST	NOTOL6		;GO MAKE SURE IT'S NOT FULL
;STILL IN FTDUFC CONDITIONAL
;HERE AFTER COMPRESSING THE DIRECTORY
NOTOL5:	POP	P,T1		;REMOVE JUNK FROM PD LIST
	MOVE	P2,DEVREL##(F)	;RESET LENGTH OF DIRECTORY

;HERE WITH T2= BLOCK FOR DIRECTORY
NOTOL6:	MOVEM	T2,DEVBLK##(F)	;SAVE DATA BLOCK NO.
	MOVE	T1,.USMBF	;IOWD FOR DATA
	PUSHJ	P,MONRED##	;READ THE DIRECTORY BLOCK
	JUMPN	T3,UFDNXT	;LEAVE DATA BLOCK ALONE IF ERROR READING
>	;END CONDITIONAL ON FTDUFC

IFE FTDUFC,<

	TDZA	P2,P2
SCNFRE:	TLZ	S,IOSFIR	;NOT 1ST BLOCK IN PTR
	PUSHJ	P,DIRRED##	;READ NEXT UFD BLOCK
	  JRST	UFDNXT		;NO SPACE - ALLOCATE ANOTHER BLOCK
	JUMPN	T3,UFDNXT	;LEAVE DATA BLOCK ALONE IF ERROR READING
	HRRZ	T1,.USMBF	;LOC OF MON BUF (-1)
>
	SKIPN	BLKSIZ##-1(T1)	;IS IT FULL?
	AOJA	T1,FNDFRE	;NO - GO FIND FIRST EMPTY SLOT
IFE FTDUFC,<
	AOJA	P2,SCNFRE	;NO, READ NEXT BLOCK
>
;HERE TO INITIALIZE THE NEXT BLOCK FOR THE DIRECTORY
UFDNXT:	JSP	T4,SAVUN##	;PUSH U, SET DEVUNI TO RIB UNIT
	PUSHJ	P,UFDCRD	;READ THE UFD RIB
	  JRST	BADUF0		;ERROR READING RIB - CANT ENTER FILE

;HERE WITH THE UFD RIB IN THE MONITOR BUFFER
	PUSHJ	P,UFORSS##	;GET LOC OF UFB OR SFD AT
	EXCH	P2,T2		;LOC INTO P2, T2 HAS HIGHEST DATA BLOCK
	SETZ	P1,		;ASSUME ONLY 1 POINTER
IFN FTDUFC,<
	JUMPG	P4,UFDNX3	;COMPRESS IF A WHOLE BLOCK OF ZEROES
>
	HRRZ	T1,.USMBF	;LOC OF MON BUF (-1)
	ADDI	T2,2		;ACCOUNT FOR 2 RIB BLOCKS
	CAMGE	T2,RIBALC##+1(T1) ;HAVE WE WRITTEN IN ALL ALLOCATED BLOCKS?
	JRST	UFDNX2		;NO. ZERO OUT NEXT BLOCK AND WRITE IN IT
IFN FTDUFC,<
;HERE IF "SOMETIMES" OR "NEVER"
	JUMPL	P4,UFDNX4	;GO IF "NEVER" COMPRESS
	MOVE	T2,P2		;HAVEN'T CALLED CMPOK YET
	PUSHJ	P,CMPOK		;OK TO COMPRESS?
	  JRST	UFDNX4		;NO
UFDNX3:	PUSHJ	P,UFDCMP	;YES. SQUEEZE ZEROS OUT OF UFD
	  JRST	NOTOL5		;DELETED SOME UFD SLOTS - TRY AGAIN
;HERE WHEN ONE MORE CLUSTER MUST BE ALLOCATED TO THE UFD
	JSP	T4,RIBUN##	;GET RIB UNIT BACK
	PUSHJ	P,UFDCRD	;READ THE RIB AGAIN
	  JRST	BADUF0		;ERROR
UFDNX4:
>
	HRRZ	T1,.USMBF	;GET HIGHEST BLOCK WRITTEN
	MOVE	T3,RIBALC##+1(T1)
	SUBI	T3,2		;ACCOUNT FOR BOTH RIBS
	SETZ	T2,		;RIB STARTS AT BLOCK ZERO
	PUSHJ	P,SCNPT0##	;FIND HIGHEST BLOCK WRITTEN
	  STOPCD .,JOB,NLB	;++NO LAST BLOCK
	MOVE	P1,T1		;SAVE AOBJN PNTR TO LAST RTP
	HRRM	T1,DEVRET##(F)	;SAVE LOC OF LAST POINTER IN DEVRET
	MOVEI	T2,DEPALC##
	IORM	T2,DEVALC##(F)	;DON'T CHANGE ACCALC
	MOVEI	T2,1		;WANT 1 MORE BLOCK
	PUSHJ	P,CHKADD##	;CAN WE ADD TO CURRENT PNTR?
	JUMPE	T2,UFDAL2	;NOT IF T2=0
	MOVE	T1,DEVBLK##(F)	;YES. BLOCK WE WANT
	ADDI	T1,2		;1 PAST FORMER END (ALLOW FOR 2ND RIB)
	PUSHJ	P,TAKBLK##	;TRY TO GET 1 MORE CLUSTER
	  JRST	UFDAL2		;CANT ADD TO END
	PUSHJ	P,ADDPTR##	;GOT IT. UPDATE POINTER
	MOVE	T2,P2		;UFB LOC
	TRZ	T2,NMPSFU##	;T2 = L(A.T.) IF AN SFD
	PUSHJ	P,SPTRW##	;SET AOBJN WORD FOR POINTERS
	MOVE	T3,1(T1)	;GET 1ST REAL POINTER (MAY HAVE UPDATED IT)
	MOVEM	T3,CORPT1##(T2)	;SAVE IN UFB BLOCK
	SETZ	P1,		;INDICATE STILL ONLY 1 PNTR
	MOVE	T1,DEVPPN(F)	;PRJ,PRG
	TRNN	P2,NMPSFU##	;IS IT A UFD
	CAME	T1,MFDPPN##	;YES, IS IT [1,1]?
	JRST	UFDAL9		;NO
	LDB	T1,UFYFSN##	;YES, GET STR INDEX
	MOVE	T1,TABSTR##(T1)	;STR DB LOC
	MOVEM	T3,STRPT1##(T1)	;UPDATE VERSION IN SDB
	JRST	UFDAL9		;AND CONTINUE
;HERE WHEN WE HAVE TO GET A NEW POINTER FOR THE EXTRA BLOCK IN THE UFD
UFDAL2:	AOBJP	P1,UFDFUL	;POINT TO FIRST FREE SLOT
UFDAL3:	MOVEI	T2,1		;WANT 1 BLOCK
	SETZ	T1,		;ANYWHERE ON THE UNIT
	PUSHJ	P,TAKBLK##	;TRY FOR A BLOCK
	  SKIPA			;CANT GET 1 ON THIS UNIT
	JRST	UFDAL8		;GOT A BLOCK
	HRRM	P1,DEVRET##(F)	;SAVE THE POINTER SLOT IN THE DDB
	PUSHJ	P,NEXTUN##	;STEP TO NEXT UNIT WITH SPACE
	  JRST	UFDAL5		;NO UNIT HAS UNITAL GT 0
	MOVSS	(P)		;SAVE UNIT TO WRITE DATA BLOCK ON
	HRRM	U,(P)		;SAVE UNIT TO WRITE 2ND RIB ON
	AOBJN	P1,UFDAL3	;GOT ONE. STEP TO NEXT POINTER SLOT

;HERE WHEN THERE ARE NO POINTER SLOTS IN THE UFD RIB
UFDFUL:	TRO	S,IOBKTL	;LIGHT AN ERROR BIT
	POP	P,T1		;REMOVE GARBAGE FROM PD LIST
	JRST	BADUFD		;AND FINISH UP (DON'T WRITE UFD)


;HERE WHEN NO UNIT HAS UNITAL GT 0.(THERE STILL MAY BE SPACE SINCE UNITAL
; DOES NOT SHOW ALL THE FREE BLOCKS IN THE UNIT)
UFDAL5:	HRRZ	U,UNISTR##(U)	;LOC OF STR DB
	HLRZ	U,STRUNI##(U)	;SET U TO 1ST UNIT IN STR
UFDAL6:	SETZ	T1,		;WANT A BLOCK ANYWHERE
	MOVEI	T2,1		;ONLY 1 BLOCK
	PUSHJ	P,TAKBLK##	;TRY TO GET ONE
	  SKIPA			;THIS UNIT REALLY FULL
	JRST	UFDAL7		;FOUND A FREE BLOCK
	HLRZ	U,UNISTR##(U)	;STEP TO NEXT UNIT IN STR
	JUMPN	U,UFDAL6	;TEST IT IF NOT END
	LDB	J,PJOBN##	;JOB NUMBER
	PUSH	P,P1		;SAVE P1
	PUSHJ	P,HNGSTP##	;TYPE MESSAGE TO USER (STR FULL)
	POP	P,P1		;RESTORE P1
	MOVE	U,(P)		; AND U
	JRST	UFDAL3		;GO TRY FOR A BLOCK AGAIN

;HERE WHEN WE GOT A BLOCK ON SOME UNIT IN STR
UFDAL7:	LDB	T1,UNYLUN##	;UNIT NUMBER
	TRO	T1,RIPNUB##	;INSURE NON-0
	MOVEM	T1,(P1)		;SAVE UNIT-CHANGE PNTR IN RIB
	AOBJP	P1,UFDFUL	;STEP TO NEXT PNTR SLOT
	MOVSS	(P)		;SAVE UNIT FOR DATA BLOCK
	HRRM	U,(P)		;SAVE NEW CURRENT UNIT (FOR 2ND RIB)
;HERE WITH T2=NEW POINTER, P1=LOC IN MONITOR BUFFER
UFDAL8:	MOVEM	T2,(P1)		;SAVE POINTER IN MON BUF
	PUSHJ	P,CNVPTR##	;CONVERT TO ADR, COUNT
	  JFCL			;BAD UNIT-CHANGE
	  STOPCD .,JOB,NAP,	;++NOT ADDRESS POINTER
	MOVE	T2,P2		;L(UFB OR SFD A.T.)
	TRZ	T2,NMPSFU##	;L(A.T.) IF AN  SFD
	MOVEI	P1,UFP1PT##	;PNTR SAVED IN UFB CANT BE THE ONLY PNTR,
	ANDCAM	P1,COR1PT##(T2)	; SO INSURE 1PT IS OFF
	MOVE	T1,DEVPPN(F)	;PRJ,PRG
	TRNN	P2,NMPSFU##	;IS IT A UFD
	CAME	T1,MFDPPN##	;YES, IS IT [1,1]?
	JRST	UFDAL9		;NO
	LDB	T1,UFYFSN##	;YES, GET STR INDEX
	MOVE	T1,TABSTR##(T1)	;STR DB LOC
	ANDCAM	P1,STRUN1##(T1)	;INDICATE MORE THAN 1 PTR IN MFD
UFDAL9:	PUSHJ	P,WTUSAT	;WRITE CHANGED SAT
	LDB	T3,UNYBPC##	;DONT COUNT BLOCKS ADDED TO UFD
	TRNN	P2,NMPSFU##
	ADDM	T3,UFBTAL##(P2)	; AS PART OF THIS JOBS QUOTA
	MOVEI	T1,DEPALC##
	ANDCAM	T1,DEVALC##(F)
	MOVE	T1,.USMBF
	ADDM	T3,RIBALC##+1(T1);UPDATE NO OF BLOCKS ALLOCATED
UFDNX2:	TRNE	P2,NMPSFU##	;AN SFD?
	AOSA	T3,DIFAWU##(P2)	;YES, GET ACCWRT
	AOS	T3,UFBWRT##(P2)	;UPDATE NO OF DIRECTORY BLOCKS WRITTEN
	ANDI	T3,UFWMSK##	;JUST NO OF BLOCKS IN UFD
	MOVE	T4,T3		;NEW NUMBER OF BLOCKS
	LSH	T4,BLKLSH##	;NUMBER OF WORDS
	MOVEM	T4,RIBSIZ##+1(T1)	;STORE NEW SIZE OF UFD IN RIB
	ADDI	T3,1		;+1=LOC OF 2ND UFD RIB
	SETZ	T2,		;START AT BEGINNING
	PUSHJ	P,SPTRW##	;SINCE SCNPTR WONT FIND LAST BLOCK
	SUB	T1,[1,,0]	; FAKE IT OUT IN CASE RIB IS FULL
	PUSHJ	P,SCNPTR##	;FIND POINTER FOR THE BLOCK
				; (STORE LOC OF 2ND RIB IN DEVBLK)
	  STOPCD .,JOB,SPM,	;++SECOND POINTER MISSING
	TRNE	P2,NMPSFU##	;AN SFD?
	JRST	UFDALB		;YES, DON'T LOOK FOR A UFD A.T.
	PUSHJ	P,UFDACC	;FIND THE A.T. FOR THE UFD
	    SKIPA T3,P2		;%FOUND - UPDATE ACCWRT
	JRST	UFDALA		;%NOT THERE
	LDB	T1,UFYWRT##	;NO OF BLOCKS IN UFD
	MOVEM	T1,ACCWRT##(T2)	;STORE IN A.T.
	ANDCAM	P1,ACC1PT##(T2)	;%TURN OFF 1PT IF CAME THROUGH UFDAL8
UFDALA:	PUSHJ	P,GVCBJ##	;%
UFDALB:	PUSHJ	P,UFORSS##	;GET LOC OF THE DIRECTORY BLOCK
	TRZN	T2,NMPSFU##	;AN SFD?
	JRST	UFDALX		;NO
	MOVEI	T3,BLKSIZ##	;SET NO OF WORDS WRITTEN
	DPB	T3,ACYLBS##	;=A FULL BLOCK
UFDALX:	MOVE	T1,.USMBF	;IOWD FOR MON BUF
	MOVE	T2,DEVDMP##(F)	;ADR OF UFD RIB
	JSP	T4,RIBUN##	;SET U TO UNIT OF 1ST RIB
	PUSHJ	P,MONWRT##	;WRITE THE UPDATED RIB
	MOVE	T2,DEVBLK##(F)	;LOC OF 2ND UFD RIB
	MOVEM	T2,RIBSLF##+1(T1)
	POP	P,U		;UNIT FOR NEW UFD BLOCK
	PUSHJ	P,STORU##	;SAVE IN DDB
	PUSHJ	P,MONWRU##	;WRITE 2ND RIB (KEEP OUT OF DISK CACHE)
	TLNN	U,-1		;IS THERE A DIFFERENT UNIT FOR THE DATA?
	JRST	UFDALC		;NO
	HLRZS	U		;YES, SET U TO DATA BLOCK UNIT
	PUSHJ	P,STORU##	;AND SAVE IN DDB
UFDALC:	HRRZ	T3,DEVUFB##(F)	;LOC OF UFB
	TRNE	P2,NMPSFU##	;AN SFD?
	SKIPA	T3,DIFAWU##(P2)	;YES, GET ACCWRT
	LDB	T3,UFYWRT##	;NO OF BLOCKS IN UFD
	SETZ	T2,		;INDICATE START AT 1ST BLOCK IN FILE
	PUSHJ	P,SCNPT0##	;FIND PTR FOR LAST DATA BLOCK IN UFD
	  STOPCD .,JOB,UDM,	;++UFD DATA MISSING
	PUSHJ	P,PTRBLT##	;COPY POINTERS FROM RIB TO DDB (NEED FOR WRTUFD)
	HRRZ	T1,.USMBF	;LOC OF MON BUF (-1)
	MOVSI	T2,1(T1)	;SET TO ZERO ENTIRE BUFFER
	HRRI	T2,2(T1)
	SETZM	1(T1)
	BLT	T2,BLKSIZ##(T1)	;ENTIRE BLOCK IS 0
	AOSA	T1		;T1=LOC OF 1ST WORD IN BUF
FNDFRZ:	ADDI	T1,2		;STEP TO NEXT NAME LOC

;HERE WITH T1=START OF MON BUF,EMPTY SLOT SOMEWHERE IN BLOCK
FNDFRE:	SKIPE	(T1)		;EMPTY UFD SLOT?
	JRST	FNDFRZ		;NO. TRY NEXT
	PUSH	P,T1		;SAVE ADDR OF UFD SLOT
	PUSHJ	P,GETNMB	;FIND THE NMB
	PUSH	P,T1		;SAVE ADDR OF NMB
	PUSHJ	P,SETCFP##	;BUILD A CFP
	POP	P,T2		;ADDR OF NMB
	POP	P,T4		;ADDR OF UFD SLOT
	MOVE	T3,NMBNAM##(T2)	;GET FILENAME FROM NMB
	MOVEM	T3,UFDNAM##(T4)	;STORE IN UFD
	HRL	T1,NMBEXT##(T2)	;ADD EXT TO CFP
	MOVEM	T1,UFDEXT##(T4)	;STORE IN UFD
	PUSHJ	P,NEWCFP	;SAVE CFP IN NMB
	  JFCL
	PUSHJ	P,WRTDIR	;WRITE THE NEW DIRECTORY BLOCK
FNDFRY:	PUSHJ	P,GETNMB	;FIND THE NMB AND ACC
	LDB	T3,ACYFSN##	;GET FSN
	PUSH	P,T3		;SAVE FSN
	HLRZ	P1,T1		;SAVE NMB IN A SAFE PLACE
	HRRZ	P3,ACCPPB##(T2)	;GET ADDR OF NEW PPB
	HRRZ	P2,DEVUFB##(F)	;SAVE LOC OF UFB
	SETZ	P4,		;INDICATE NO EXTRA PPB
	TRNN	M,CHNDIR	;CHANGING DIRECTORIES?
	JRST	FNDFR1		;NO
				;YES, FALL INTO NEXT PAGE
;HERE WHEN CHANGING DIRECTORIES - DELETE THE FILE FROM THE OLD DIR
	PUSHJ	P,DECUSA	;DECREMENT USE-COUNT OF NEW SFD
	HRRZ	T1,DEVSFD##(F)	;IF RENAME INTO A UFD
	JUMPE	T1,[SKIPE DEVSFD##(F) ; FROM AN SFD
		    AOS PPBCNT##(P3)  ; PPBCNT IS TOO LOW, SO BUMP IT
		    JRST .+2]
	SOS	NMBCNT##(T1)	;RENAME INTO SFD - ADJUST COUNT
	SKIPE	DEVSFD##(F)	;IF RENAME INTO/OUT OF AN SFD
	TLO	P3,-1		; SET A FLAG FOR FNDFR1
	HLRZS	DEVSFD##(F)	;RESTORE SFD LOC OF OLD DIRECTORY
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	HLRZ	T2,SYSPPB##	;%START OF PPB BLOCKS
	MOVE	T1,DEVPPN(F)	;%OLD PRJ,PRG
	PUSHJ	P,LSTSCN##	;%FIND THE OLD PPB BLOCK
	  JRST	FNDFRA		;%PPB WAS DELETED (SYSTEM ERROR)
	MOVE	P4,T2		;SAVE LOC OF PPB
	MOVE	T1,(P)		;%FSN

	HLRZ	T2,PPBUFB##(T2)	;%START OF UFB BLOCKS FOR FILE
	PUSHJ	P,BYTSCA##	;%FIND THE UFB
	  JRST	FNDFR0		;%FOUND UFB
;STILL IN FTDRDR CONDITIONAL
;HERE IF THE PPB AND/OR THE UFB WAS DELETED (BY TSTPPB)
FNDFRA:	PUSHJ	P,GVCBJ##	;%RELEASE CB RESOURCE
	TLZ	M,UUOMSK	;WIPE BITS OUT OF LH(UUO)
	TLO	M,UUOLUK	;MAKE BELIEVE THIS IS A LOOKUP
	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST
	  STOPCD FNDFR1,DEBUG,SLM,	;++SEARCH LIST MISSING
	MOVE	T2,T1		;SEARCH LIST INTO T2
	PUSHJ	P,FNDFIL##	;SET UP UFB BLOCK
	  JFCL			;FNDFIL GETS A RIB ERROR ON LOOKUP(WRONG RIBPPN)
	JRST	FNDFRB		;AND CONTINUE
FNDFR0:	PUSHJ	P,GVCBJ##
	PUSHJ	P,DWNAU##	;GIVE UP AU FOR OLD UFB
	MOVEM	T2,DEVUFB##(F)	;SAVE OLD UFB LOC IN DDB
	PUSHJ	P,UPAU##	;GET AU FOR NEW UFB
	PUSHJ	P,LOGTS2	;REWRITE UFD RIB WITH NEW QUOTA
	PUSHJ	P,UPAU##	;GET AU RESOURCE AGAIN

FNDFRB:	SETZ	P1,		;INDICATE NMB SHOULD BE LEFT ALONE
	PUSHJ	P,DELNAM	;DELETE THE NAME FROM THE UFD
FNDFR1:	  PUSHJ	P,DWNAU##	;NOT THERE - RELEASE AU
	HRRM	P2,DEVUFB##(F)	;RESTORE NEW UFB LOC
	CAIN	P4,(P3)		;IF RENAME IN SAME PPN
	TLZ	P3,-1		; COUNTS ARE RIGHT
	TLNE	P3,-1		;IF RENAME TO/FROM SFD ACCROSS PPNS
	SOS	PPBCNT##(P3)	; THEN PPB COUNT IS TOO HIGH
	MOVE	P3,PPBNAM##(P3)	;GET NEW PPN
	MOVEM	P3,DEVPPN(F)	;SAVE IN DDB (NEEDED BY LOGTST
				;IF RENAMING INTO NEW DIR)
	SKIPE	P4		;DECR OLD PPB USE-COUNT
	SOS	PPBCNT##(P4)	; SO TSTPPB CAN DO ITS THING
	HLRZ	T1,DEVEXT(F)	;EXTENSION OF FILE
	CAIE	T1,(SIXBIT .UFD.)	;UFD?
	JRST	FNDFR3		;NO
	MOVE	T1,DEVFIL(F)	;YES. PRJ,PRG
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	HLRZ	T2,SYSPPB##	;%T1=START OF PPB'S
	PUSHJ	P,LSTSCN##	;%FIND PPB FOR FILE
	  JRST	FNDFR2		;%NOT THERE
	MOVE	T1,(P)		;%FOUND. T1=FSN

	MOVE	T4,T2		;%SAVE PPB LOC
	PUSHJ	P,FSNPS2##	;%POSITION A BIT FOR FSN
	ORM	T2,PPBKNO##(T4)	;%INDICATE THAT THERE IS A UFD
	ORM	T2,PPBYES##(T4)	;% FOR THIS STR
FNDFR2:	PUSHJ	P,GVCBJ##	;%GIVE UP CB
FNDFR3:	POP	P,T1		;REMOVE FSN FROM PD LIST
	LDB	T1,DEYFSN##	;FSN OF FILE BEING SUPERSEDED
	JUMPE	T1,CLRSTS	;NONE IF 0

;HERE IF A FILE IN 1 STR IS SUPERSEDING A FILE IN ANOTHER STR
;(NO ROOM TO WRITE NEW FILE IN ORIGINAL STR)
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
	LDB	T3,ACYFSN##	;FSN THEN NEW FILE EXISTS OR
	CAMN	T3,T1		;IF THE SAME,
	JRST	CLRSTS		; THE SUPERCEEDED FILE GOT DELETED
	HRRZ	T2,ACCPPB##(T2)	;LOC OF PPB
	HLRZ	T2,PPBUFB##(T2)	;1ST UFB LOC
	PUSHJ	P,BYTSCA##	;FIND UFB FOR FORMER FILE
	  SKIPA
	JRST	CLRSTS		;NOT THERE
	HRRM	T2,DEVUFB##(F)	;SAVE LOC OF UFB FOR UFDSRC
	PUSHJ	P,UPAU##	;GET AU
	LDB	T1,UFYFSN##	;FSN
	MOVE	U,TABSTR##(T1)	;STR DATA BLOCK LOC
	HLRZ	U,STRUNI##(U)	;SET U TO ANY UNIT IN STR
	HRLM	U,DEVUNI##(F)	;SAVE IN DDB (FOR DELNAM)
	HLRZS	P1		;LOC OF NMB
	PUSHJ	P,DELNAM	;REMOVE NAME FROM UFD
	  JRST	CLRST2		;NOT THERE - SOMEONE ALREADY DELETED IT
	PUSH	P,P1		;SAVE LOC OF NMB
	HRRZ	T2,DEVUFB##(F)	;LOC OF UFB
	JRST	ALLP10		;GO DELETE OLD FILE

;HERE WHEN WE CANT ENTER THE FILE IN THE UFD
BADUF0:	POP	P,U		;REMOVE U FROM PDLIST
BADUFD:	TLNE	S,IOSAU		;HAVE AU RESOURCE?
	PUSHJ	P,DWNAU##	;NOT ANY MORE
	PUSHJ	P,REDRIB##	;READ THE PRIME-RIB AGAIN
	  JRST	CLRSTS		;NOW THAT'S GONE BAD?
	PUSHJ	P,SPTRW##	;GET PNTR TO RET PNTRS
	MOVE	P1,T1		;INTO P1 FOR DELRIB
	PUSHJ	P,DELRIB	;
	  STOPCD	.+1,DEBUG,DDS,	;++ DELRIB DIDNT SKIP
	JRST	CLRSTS
CLRST2:	PUSHJ	P,DWNAU##	;GIVE UP AU RESOURCE
;HERE WHEN THE UFD IS WRITTEN
CLRSTS:	SETZ	P4,		;PREPARE FOR ADDM P4,ACCCNT
CLRSTX:	TLNE	S,IOSAU		;STILL HAVE AU?
	PUSHJ	P,DWNAU##	;YES, GIVE IT UP
	MOVE	T1,DEVUFB##(F)
	MOVSI	T2,UFPCHG##	;SOME FILE HAS BEEN WRITTEN OR RENAMED
	IORM	T2,UFBCHG##(T1)
	TLNE	M,UUOREN	;IF RENAME
	PUSHJ	P,CLSNM		; GET DDB RIGHT FOR WATCH FILE


	PUSHJ	P,GETCB##	;DID FILOP TELL US TO SLIP?
	PUSHJ	P,NWCFP0
	  JRST	CLRSTB		;NO
;HERE IF FILOP IS SLIPPING THE FILE INTO UPDATE MODE.
;MOST OF THE WORK WAS ALREADY DONE BY NEWCFP, WE MERELY
;NEED TO CLEAN UP (I.E. DO THE STUFF THAT COULDN'T
;BE DONE WHILE THE DIRECTORY POINTERS WERE IN CORE)
	HRRZ	T3,DEVACC##(F)	;ADDR OF ACC
	ADDM	P4,ACCCNT##(T3)	;DECR IF CLSDEL DID INCR
	PUSHJ	P,AT2DDB##	;SET UP POINTERS FROM ACC
	  JFCL
	TLZ	F,ICLOSB+OCLOSB	;UNDO CLOSE
	TLO	F,ENTRB+LOOKB
	HRRZ	T3,DEVCPY##(F)	;ALREADY GOT COPY?
	JUMPN	T3,CLRSTY
	PUSHJ	P,GETCPY	;NO, COPY THE POINTERS
	CAIA
CLRSTY:	PUSHJ	P,CPYPTR	;YES, UPDATE THE COPY
	HRRZ	T2,DEVACC##(F)
	MOVE	W,ACCWRT##(T2)	;SIZE OF FILE
	ADDI	W,1		;EOF
	PUSHJ	P,USETO0##	;UPDATE POINTERS
	JRST	STOIOS##	;DONE
;ROUTINE TO STORE THE CFP AND SLIP THE FILE INTO UPDATE MODE.
;IF, INDEED, THE FILE MUST BE SLIPPED INTO UPDATE MODE, THIS MUST
;BE DONE BEFORE THE DIRECTORY IS WRITTEN (ELSE SOME OTHER JOB CAN
;START A LOOKUP AND BUILD A DUPLICATE ACC).
;WE MUST CLEAR ACPCRE+ACPSUP SO THAT HE WILL SEE OUR OWN ACC
;AND USE IT. ORDINARILY A DUPLICATE ACC WOULD NOT BE
;A PROBLEM, WE'D DETECT HIS ACC AND DELETE OUR COPY.
;BUT DURING A FILOP SLIP, WE CANNOT DELETE OUR ACC AND
;THEREFORE CANNOT ALLOW HIM TO BUILD A DUPLICATE.
;T1 PASSES THE CFP
;T2 PASSES ADDR OF NMB
;CPOPJ IF NO SLIP, CPOPJ1 IF SLIP
NEWCFP:	PUSHJ	P,GETCB##	;GET THE CB
	PUSHJ	P,SAVCFP	;%STORE CFP IN NMB
;HERE IF NMB DOESN'T NEED TO BE UPDATED
NWCFP0:	MOVE	T3,DEVJOB(F)	;%DID FILOP TELL US TO SLIP?
	TLNE	T3,DEPFFA
	PUSHJ	P,TSTSFD
	  PJRST	GVCBJ##		;%NO
	JUMPL	M,GVCBJ##	;%NO
	HRRZ	T2,DEVACC##(F)
	JUMPE	T2,GVCBJ##	;%NO
	LDB	T1,ACYSTS##	;%ALREADY IN UPDATE MODE?
	CAIN	T1,ACRUPD##
	JRST	NWCFP1		;%YES
	MOVEI	T1,ACRUPD##	;%NO, SET UPDATE NOW
	DPB	T1,ACYSTS##
	MOVEI	T1,1		;%FIRST WRITTER
	DPB	T1,ACZWCT##
	MOVEI	T1,ACPSMU
	TLNE	T3,DEPSIM	;%SIMULTANEOUS UPDATE?
	IORM	T1,ACCSTS##(T2)	;%YES, LIGHT BIT IN ACC

NWCFP1:	TLOE	S,IOSRDC	;%INPUT CLOSE DONE?
	PJRST	GVCBJ1##	;%NO
	MOVEI	T1,ACPCNT##	;%YES, UNDO INPUT CLOSE
	ADDM	T1,ACCCNT##(T2)
	PUSHJ	P,INCUC
	MOVEM	S,DEVIOS(F)
	PJRST	GVCBJ1##
;HERE WITH P4=0 OR -ACPCNT (CLSDL1)
CLRSTB:	CBDBUG	(N,Y);
IFN FTSPL,<
	SKIPN	DEVSPN##(F)
	SKIPGE	DEVSPL(F)	;SPOOLED FILE?
	PUSHJ	P,[PUSHJ P,CLSNAM ;YES, TELL QUASAR
		   JRST QSRSPL##]
	SETZM	DEVSPN##(F)
>
IFN FTFDAE,<
	MOVSI	T1,DEPFDA##	;CALL THE FILE DAEMON ON CLOSE BIT
	TDNN	T1,DEVFDA##(F)	;SHOULD THE FILE DAEMON BE CALLED?
	JRST	CLRST0		;NO
	ANDCAM	T1,DEVFDA##(F)	;YES, CLEAR THE BIT
	MOVEI	T1,.FDCLO	;INDICATE OUTPUT CLOSE
	PUSHJ	P,SNDFMG##	;TELL THE FILE DAEMON
	  JFCL			;DON'T CARE
	PUSHJ	P,GTMNBF##
CLRST0:>
	PUSHJ	P,DDBZR		;CLEAR OUT PNTRS IN CASE OF NEW ENTER
	MOVEI	T1,DEPWRT##	;CLEAR THE DDB - IS - WRITING BIT
	ANDCAM	T1,DEVWRT##(F)
	TLZ	F,ENTRB+RENMB+OUTPB	;ZERO RENAME, OUTPUT AND ENTER BITS
	HRRZ	T1,DEVACC##(F)	;LOCATION OF ACCESS TABLE
	JUMPE	T1,[SETZM DEVUNI##(F)
		    PUSHJ P,LOGTSP	;DO UFD ACCOUNTING
		    SETO T1,
		    JRST CLRSTC]
	MOVE	T2,ACCSTS##(T1)	;FILE STATUS
	TRNE	T2,ACPUPD	;UPDATE MODE ?
	TLNE	F,ICLOSB	;YES, IMPUT SIDE STILL OPEN ?
	SETZM	DEVUNI##(F)	;NO, CLEAR DEVUNI
	PUSHJ	P,LOGTST	;TURN ON RIPLOG IN UFD IF PPB NOT LOGGED IN
	PUSHJ	P,DDBZR		;LOGTST MIGHT SET PNTRS UP AGAIN
	PUSHJ	P,GETCB##
	PUSHJ	P,GETNMB	;GET THE NMB
	PUSHJ	P,GVCBJ##	;RETURN CB
	MOVE	T3,ACCSTS##(T2)	;DON"T CALL FIXPTH IF RENAME
	TRNN	T3,ACPREN	;IT WAS ALREADY DONE BY FNDFIL
	PUSHJ	P,FIXPTH	;BUMP COUNT IF IN SOMEBODY'S PATH
	EXCH	T1,T2		;T1=LOC OF AT, T2=NMB
	MOVE	P2,T2		;SET P2 TO DECREMENT COUNTS
	HRL	P2,ACCPPB##(T1)
	LDB	J,PJOBN##	;JOB NUMBER
	TLNE	F,LOOKB		;CLOSIN WILL GET IT IF INPUT SIDE OPEN
	JRST	CLRS0A
	PUSHJ	P,SFDDEC	;DEC PPBCNT,NMBCNT FOR SFD
	PUSHJ	P,DECUSA	;DECREMENT USE-COUNTS FOR SFD
CLRS0A:	HRRZ	T1,DEVACC##(F)	;RESET T1 TO LOC OF A.T.
	PUSHJ	P,GETCB##	;%GET CB RESOURCE
	MOVE	T3,ACCSTS##(T1)	;%FILE STATUS
	TRNE	T3,ACPUPD	;%UPDATE?
	TLNE	F,ICLOSB	;%YES, INPUT SIDE CLOSED?
	PUSHJ	P,UACLR		;%YES, TAKE A.T. OUT OF DDB, CLEAR DEVUFB
	MOVSI	T2,DEPSIM	;%CLEAR SIM. UPDATE BIT FROM DDB
	ANDCAM	T2,DEVJOB(F)	;%
	LDB	T4,ACYWCT##	;%DECREMENT NUMBER OF WRITERS
	TRNE	T3,ACPUPD	;% IF AN UPDATE FILE
	SUBI	T4,1		;%(UP EVEN IF NOT SIM-UPD)
	DPB	T4,ACYWCT##
	MOVEI	T2,ACPCRE!ACPREN!ACPSUP+ACPPAL##
	SKIPN	T4		;%SIM UPDATE?
	TRO	T2,ACPUPD!ACPSMU	;%DONT CLEAR ACPUPD IF STILL UPDATERS

	ADDM	P4,ACCCNT##(T1)	;DECR READ-COUNT IF IT WAS COUNTED UP
				; AT CLSDL1 TO PREVENT A.T. GOING DORMANT
	ANDCAB	T2,ACCSTS##(T1)	;%CLEAR THE STATE CODE
	PUSHJ	P,DECUC		;%DECR USE-COUNTS OF NMB, PPB
	MOVEI	T3,ACPPAL##
	MOVE	T4,DEVPAL##(F)	;%IF PRE-ALLOCATED,
	TRZE	T4,DEPPAL##
	IORM	T3,ACCPAL##(T1)	;% LIGHT BIT IN A/T/
	MOVEM	T4,DEVPAL##(F)	;% AND CLEAR THE DDB BIT
CLRSTC:	HRRZ	T4,DEVCPY##(F)	;% IS THERE AN IN-CORE COPY?
	JUMPE	T4,CLRSTG
	MOVEI	T3,SYSPTR##-PTRSYS## ;% YES, START AT BEGINNING
	PUSH	P,T1
	DDBSRL			;% INTERLOCK IT
CLRSTD:	HLRZ	T1,PTRSYS##(T3)	;% STEP TO NEXT
	CAIN	T1,(T4)		;% IS IT THE ONE WE WANT?
	JRST	CLRSTE		;% YES
	SKIPE	T3,T1		;% NO, STEP TO NEXT
	JRST	CLRSTD
	JRST	CLRSTF		;% NONE. (SYSTEM ERROR)
CLRSTE:	MOVE	T1,PTRSYS##(T4)	;% GET LINK OF THIS ONE
	HLLM	T1,PTRSYS##(T3)	;% STORE IN PREVIOUS LINK
CLRSTF:	DDBSRU			;% NO NEED FOR INTERLOCK NOW
	HLLZS	DEVCPY##(F)	;% NO IN-CORE COPY NOW
	MOVE	T2,T4		;% ADDRESS
	MOVEI	T1,PTRCOR##
	PUSHJ	P,GIV4WD##	;% GIVE UP THE SPACE
	POP	P,T1		;% RESTORE T1
	MOVE	T2,ACCSTS##(T1)	;% AND T2
CLRSTG:	JUMPL	T1,CLRST1	;GO IF NO ACCESS TABLE
	TRNE	T2,ACMCNT!ACPUPD ;%ANYONE READING FILE?
	JRST	CLRST4		;%YES, RETURN
	TRNE	T2,ACPDEL##	;%FILE MARKED FOR DELETION (RACE CONDITION-
				; CAUSED BY THIS JOB BEING HELD UP IN OUTPUT CLOSE
				; AND ANOTHER JOB ZOOMING THROUGH DELETE)
	JRST	CLRST3		;%YES, GO DELETE FILE NOW
	SKIPE	T2,ACCDOR##(T1)	;%NO,  A.T. DORMANT?
	STOPCD	GVCBJ##,DEBUG,FAD,	;%++FILE ALREADY DORMANT
	PUSHJ	P,SPARKS	;%DID ANOTHER A.T. SNEAK IN?
	  PUSHJ	P,ATSDRA##	;%NO, MAKE OUR A.T. DORMANT
CLRST1:	PJRST	TSTPPB		;TEST IF PPB LOGGED IN, EXIT

;HERE ON A WIERD TIMING PROBLEM
CLRST3:	HRRM	T1,DEVACC##(F)	;CAUSE CLOSR2 CALLS GETNMB
	PUSHJ	P,GVCBJ##
	PUSHJ	P,STORU##
	HRLM	U,DEVUNI##(F)	;SAVE U IN DDB
	SETZ	P2,		;DONT DECR USE-COUNTS AGAIN
	JRST	CLOSR2		;GO BACK TO INPUT CLOSE AND DELETE FILE

;HERE IF OTHER READERS OF THE FILE
CLRST4:	PUSHJ	P,GVCBJ##
	HRRZ	T3,DEVACC##(F)	;AT
	JUMPE	T3,CPOPJ##	;IF 0 THEN WE'RE NOT UPDATING
				;UPDATER - RESET DDB POINTERS
	PUSHJ	P,AT2DDB##	; (ELSE NEXT INPUT WILL READ UFD)
	  JFCL			;AT IS MESSED UP - HE'LL FINE OUT SOON
	POPJ	P,

;THIS ROUTINE TESTS FOR AN OBSCURE RACE.
;IF WE JUST CREATED A NEW VERSION OF THE FILE,
;THEN IT IS POSSIBLE THAT A LOOKUP SNUCK IN
;AFTER WE WROTE THE UFD. THE JOB DOING THE LOOKUP
;IGNORED OUR A.T. BECAUSE IT WAS MARKED AS EITHER
;ACPCRE OR ACPSUP. HE NOW HAS AN A.T. FOR THE
;NEW VERSION OF THE FILE. HIS A.T. IS
;NOW AN EXACT DUPLICATE OF OUR OWN. WE CANNOT ALLOW
;DUPLICATE A.T.'S SO WE MUST DESTROY ONE OF THE TWO.
;WE CHOOSE TO DESTROY OUR OWN A.T. AS IT IS KNOWN
;TO BE DORMANT.

;CALL WITH T1=A.T.
;CALL WITH CB
;NORMALLY EXITS CPOPJ (STILL HAVING CB)
;EXITS CPOPJ1 IF THERE WAS A DUPLICATE A.T. (IT HAS
;BEEN DESTROYED AND CB WAS GIVEN AWAY).
SPARKS:	PUSH	P,T1		;%SAVE ADDR OF OUR A.T.
	PUSHJ	P,GTNM1		;%GET ADDR OF NMB
	MOVEI	T2,DIFNAL##(T1)	;%ADDR OF NMBACC
	MOVE	T1,(P)		;%GET FSN OF OUR A.T.
	LDB	T1,ACZFSN##
SPARK1:	PUSHJ	P,BYTSC1##	;%FIND ANOTHER A.T.
	  SKIPA	T3,ACCPT1##(T2)	;%GET ITS RTP
	JRST	TPOPJ##		;%NO MORE A.T.'S
	MOVE	T4,(P)		;%ADDR OF OUR A.T.
	CAME	T2,T4		;%SKIP OVER OUR OWN
	CAME	T3,ACCPT1##(T4)	;%SAME RTP?
	JRST	SPARK1		;%NO, KEEP LOOKING
	POP	P,T2		;%YES, GET BACK OUR A.T.
	PUSHJ	P,ATRMVX##	;%DESTROY OUR A.T.
	JRST	CPOPJ1##
;SUBROUTINE TO TEST IF USER IS LOGGED IN (ON A CLOSE)
;IF NOT, RECOMPUTE RIBUSD AND REWRITE THE RIB
;ENTER AT LOGTS1 IF KNOWN NOT TO BE LOGGED IN
;ENTER AT LOGTS2 IF ALREADY HAVE AU RESOURCE
;ENTER AT LOGTSP IF A.T. NOT AVAILABLE
LOGTSP:	MOVE	T1,DEVPPN(F)	;GET THE FILE'S PPN
	HLRZ	T2,SYSPPB##	;GET LOC OF 1ST PPB
	PUSHJ	P,LSTSCN##	;SEARCH FOR THE PPB
	  POPJ	P,		;NONE.  JUST RETURN
	MOVE	T1,T2		;COPY THE PPB
	JRST	LOGTS3		;PICK UP WITH PPB BELOW
LOGTST:	MOVE	T1,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,ACCPPB##(T1)	;LOC OF PPB
LOGTS3:	MOVE	T1,PPBNLG##(T1)	;LOGGED-IN WORD
	TLNE	S,IOSWLK	;DON'T WRITE IF STR IS WRITE-LOCKED
	POPJ	P,		;YES. RETURN
	PUSHJ	P,SAVE2##	;S.L. STUFF WIPES P2
	TRNN	T1,PPPNLG##	;IS USER LOGGED IN ?
	JRST	LOGTS1		;NO, WRITE RIB
	SKIPN	T1,DEVUFB##(F)	;YES. GET UFB
	JRST	LOGTS1
	MOVE	T1,UFBLOG##(T1)
	TLNE	T1,UFPLOG##	;IS RIPLOG ON IN UFD?
	POPJ	P,		;YES, RETURN
LOGTS1:	PUSHJ	P,UPAU##	;NO. GET AU RESOURCE
	CAIA
LOGTS2:	PUSHJ	P,SAVE1##
	HRRZ	P1,DEVUFB##(F)	;LOC OF UFB
	JUMPE	P1,DWNAU##
	SKIPN	T2,UFBPT1##(P1)	;RETRIEVAL PNTR FOR UFD
	PJRST	DWNAU##		;UFD WAS DELETED - RETURN
	MOVE	T1,UFBUN1##(P1)	;UNIT WORD
	PUSHJ	P,SETFS0##	;SET UP U, BLOCK IN T2
	  PJRST	DWNAU##		;ERROR READING RIB - RETURN
	PUSHJ	P,UFDRED##	;READ THE UFD RIB
	  PJRST	DWNAU##		;ERROR READING RIB - RETURN
	MOVEI	T3,RIPNDL##	;GET NO DELETE BIT
	TDNE	T3,RIBSTS##+1(T1) ;IS IT SET FOR THIS UFD?
	PJRST	DWNAU##		;YES, DON'T UPDATE
	MOVE	T3,UFBCHG##(P1)	;HAS ANY FILE BEEN CHANGED?
	TLZN	T3,UFPCHG##
	TDZA	T2,T2		;NO, DON'T SET BIT IN RIB
	MOVSI	T2,RIPCHG##	;YES, SET BIT IN RIB
	MOVEM	T3,UFBCHG##(P1)	;CLEAR BIT IN UFB
	TDNE	T2,RIBSTS##+1(T1) ;BIT ALREADY SET IN RIB?
	SETZ	T2,		;YES, DON'T REWRITE RIB
	IORM	T2,RIBSTS##+1(T1) ;LIGHT RIBSTS BIT IF CHANGE
	MOVE	T3,RIBQTF##+1(T1) ;COMPUTE NUMBER OF BLOCKS USED
	SUB	T3,UFBTAL##(P1)
	CAME	T3,RIBUSD##+1(T1) ;SAME AS BEFORE?
	SETO	T2,		;NO, MUST REWRITE RIB
	MOVEM	T3,RIBUSD##+1(T1) ;STORE NEW VALUE IN RIB
	JUMPE	T2,DWNAU##	;DON'T REWRITE IF DIDN'T ALTER RIB
	MOVE	T2,RIBSLF##+1(T1) ;BLOCK NUMBER OF RIB
	PUSHJ	P,MONWRT##	;REWRITE 1ST RIB OF UFD
	PJRST	DWNAU##		;RETURN AU RESOURCE AND EXIT
;SUBROUTINE CALLED ON OUTPUT CLOSE OF A FILE
;CLEARS DEVACC, DEVUFB UNLESS FLOW WILL GET GO CLRST3
;ENTER WITH T3=ACCSTS. CALL UACLX TO CLEAR DEVACC, DEVUFB
;PRESERVES ALL ACS
UACLR:	TRNN	T3,ACMCNT	;%ANY READERS?
	TRNN	T3,ACPDEL##	;%YES, MARKED FOR DELETION
	CAIA			;%READERS OR NOT TO DELETE - OK
	POPJ	P,		;%GOING TO DELETE NOW - DON'T CLEAR DDB
				;% (CALL INPUT CLOSE TO DELETE FILE NOW)
UACLX:	HLLZS	DEVACC##(F)	;%CLEAR DEVACC, DEVUFB
	SETZM	DEVUFB##(F)	;%
	POPJ	P,		;%

;SUBROUTINE TO READ THE UFD RIB DURING CLOSE
;ENTER WITH U SET UP, EXIT CPOPJ IF ERROR READING RIB
;EXIT CPOPJ1 NORMALLY, WITH RIB IN MONITOR BUFFER
UFDCRD:	PUSH	P,DEVPPN(F)	;SAVE OLD PRJ-PRG
	MOVE	T1,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,ACCPPB##(T1)	;LOC OF (NEW) PPB
	MOVE	T1,PPBNAM##(T1)	;(NEW)PRJ-PRG
	MOVEM	T1,DEVPPN(F)	;SAVE IN DEVPPN SO UFDRED WONT GIVE AN ERROR
				;RETURN IF RENAMING INTO ANOTHER DIRECTORY
	MOVE	T2,DEVDMP##(F)	;BLOCK NUMBER OF RIB
	PUSHJ	P,UFDRED##	;GO READ THE RIB
	  JRST	TPOPJ##		;BAD UFD RIB, ERROR RETURN
	POP	P,DEVPPN(F)	;RESTORE OLD PRJ-PRG
	JRST	CPOPJ1##	;AND RETURN

;SUBROUTINE TO FIND THE LAST UNIT-CHANGE POINTER IN THE RIB
;ENTER WITH RIB IN MON BUF
;EXIT U=RH(DEVUNI)=LAST UNIT POINTED TO BY RIB
LSTUNI:	PUSHJ	P,SPTRW##	;SET AOBJN WORD FOR POINTERS
LSTUN2:	SKIPN	T3,(T1)		;GET A POINTER
	JRST	LSTUN3		;THROUGH
	TLNN	T3,-1		;UNIT CHANGE?
	MOVE	T2,T3		;YES, SAVE IN T2
	AOBJN	T1,LSTUN2	;TEST NEXT POINTER
LSTUN3:	PUSHJ	P,CNVPTR##	;CONVERT POINTER TO UNIT
	  CAIA			;BAD UNIT-CHANGE PNTR
	  POPJ	P,		;AND RETURN
	STOPCD	CPOPJ##,DEBUG,NUP,	;++NO UNIT CHANGE POINTER

;SUBROUTINE TO LIGHT UNIT-BIT IN RIBUNI
;ENTER T1=C(.UPMBF), U=UNIT
;LIGHTS RIGHT BIT IN LH(RIBUNI) FOR THIS UNIT
;EXIT T1=C(.UPMBF)
ORINUN:	MOVSI	T2,1		;BIT FOR DRIVE 0
	LDB	T3,UNYPUN##	;DRIVE NUMBER
	LSH	T2,(T3)		;POSITION BIT
	IORM	T2,RIBUNI##+1(T1)	;STORE IN RIB
	POPJ	P,		;AND RETURN

;SUBROUTINE TO GET LAST RIB POINTER
;ENTER WITH RIB IN MONITOR BUFFER
;EXIT WITH T2 = LAST POINTER
;PRESERVES T3
GTLPT::	PUSHJ	P,SPTRW##	;GET AOBJN WORD FOR PNTRS
	HLRE	T2,T1		;NUMBER OF PNTRS
	SUB	T1,T2		;POINT AT END +1
	MOVE	T2,-1(T1)	;GET LAST POINTER
	POPJ	P,		;AND RETURN
;SUBROUTINE TO UPDATE RIBNAM,RIBEXT, RIBPPN IN THE CASE OF A CLOSE FOR RENAME
;T1=IOWD FOR MONITOR BUFFER, T1,T2 RESPECTED.
NAMNW:	PUSH	P,T2		;SAVE T2
	HRRZ	T4,DEVACC##(F)	;GET ADDRESS OF A.T.
	HLRZ	T4,ACCNMB##(T4)	;STEP TO NEXT IN RING
	TRZN	T4,DIFNAL##	;NAME BLOCK?
	JRST	.-2		;NO, LOOK AT NEXT
	MOVE	T2,NMBNAM##(T4)	;GET NEW NAME
	MOVEM	T2,RIBNAM##+1(T1) ;TO RIB
	MOVE	T2,NMBEXT##(T4)	;NEW EXTENSION
	HRLM	T2,RIBEXT##+1(T1) ;TO RIB
	HRRZ	T2,DEVACC##(F)	;GET A.T. AGAIN
	HRRZ	T4,ACCPPB##(T2)	;LOCATION OF PPB
	MOVE	T3,PPBNAM##(T4)	;NEW PPN
	MOVEM	T3,RIBPPN##+1(T1)	;TO RIB
	PUSH	P,T1
	LDB	T1,ACYFSN##	;STR NUMBER
	HLRZ	T2,PPBUFB##(T4)	;START OF UFB CHAIN
	PUSHJ	P,BYTSCN##	;FIND UFB (ANOTHER JOB MIGHT
	  CAIA			; HAVE RENAMED ACCROSS DIRECTORIES)
	STOPCD	.+1,DEBUG,UNF,	;++ UFB NOT FOUND
	HRRM	T2,DEVUFB##(F)	;SAVE (NEW) DEVUFB
	POP	P,T1
	PUSHJ	P,SETUFR	;SET UP RIBUFD
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN
IFN FTDUFC,<			;IF KEEPING FILES IN ORDER
;SUBROUTINE TO COMPRESS THE UFD INTO AS FEW BLOCKS AS POSSIBLE
;ENTER WITH 1 MONITOR BUFFER, UFD RIB IN IT

; SETS DEVREL TO NEW SIZE OF THE FILE
;EXIT CPOPJ IF NO MORE BLOCKS HAVE TO BE ALLOCATED, T2=BLOCK TO WRITE
;EXIT CPOPJ1 IF MORE BLOCKS MUST BE ALLOCATED
UFDCMP:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSHJ	P,CPYFST##	;COPY 1ST VALUES FROM UFD RIB TO DDB
	  POPJ	P,		;RIB FOULED UP BADLY - RETURN
	SOS	T1,DEVBLK##(F)	;POINT DEVBLK TO RIB
	MOVEM	T1,DEVDMP##(F)	;SAVE RIB BLOCK NO IN DDB
	SETZB	P4,DEVREL##(F)	;DEVREL WILL BE BUMPED IN DIRRED
	MOVE	P3,F		;SAVE LOC OF DDB
	PUSHJ	P,FAKDDB	;GET AN EXTRA DDB
	  JRST	UFDCMD		;NO ROOM
	EXCH	P3,F		;RESTORE F, SAVE NEW DDB LOC
	MOVE	S,DEVIOS(F)	;RESTORE S
	MOVEM	U,DEVUNI##(P3)	;SAVE U IN CASE NO HOLES
	MOVE	T1,.USMBF	;LOC OF MON-BUF
	MOVE	T2,RIBSTS##+1(T1) ;GET RIB STATUS BITS
	TROE	T2,RIPCMP##	;LIGHT UFD-BEING-COMPRESSED BIT
	TRO	T2,RIPCBS##	;PLUS RIPCBS IF RIPCMP WAS ALREADY ON
	MOVEM	T2,RIBSTS##+1(T1) ;REPLACE STATUS BITS
	MOVE	T2,RIBSLF##+1(T1); (UFD CAN GET ZAPPED IF SYSTEM CRASHES
	PUSHJ	P,MONWRT##	; WHILE A UFD IS BEING COMPRESSED)
	MOVE	P1,.USMBF	;SAVE ADDR OF MON BUF
	SETZM	.USMBF		;SET TO GET ANOTHER BUFFER
	PUSHJ	P,GTMNBF##	;GET SECOND MON-BUF
	MOVE	P2,.USMBF	;LOC OF MON BUF INTO P2
;STILL IN FTDUFC CONDITIONAL
;HERE WITH P1,P2 = LOC OF MON BUFS, P3=L(EXTRA DDB)
UFDCM4:	PUSHJ	P,DIRRED##	;READ A UFD BLOCK
	  JRST	[HRRM P2,DEVDMP(P3)	;NO HOLES AT ALL
		 MOVEM P1,.USMBF	;FIX THINGS UP
		 JRST UFDCMB]		;AND EXIT
	TRNE	S,IOIMPM!IODERR!IODTER!IOBKTL	;ANY READ ERRORS?
	JRST	[HRRM P2,DEVDMP(P3)	;YES, FIX THINGS UP
		 MOVEM P1,.USMBF	;AND DON'T COMPRESS
		 JRST UFDCMC]
	SKIPE	BLKSIZ##-2(P2)	;IS BLOCK FULL?
	AOJA	P4,UFDCM4	;YES - READ NEXT BLOCK

;HERE WHEN A UFD BLOCK WITH AT LEAST 1 HOLE HAS BEEN FOUND
	MOVEI	T1,DEVMOD(P3)	;LOC OF EXTRA DDB
	HRLI	T1,DEVMOD(F)	;SET TO BLT CURRENT STATE OF DDB
	BLT	T1,DEVRBN##(P3)	;EXTRA DDB POINTS TO 1ST UFD BLOCK TO WRITE
	HRRZ	T1,P3		;NOW ADJUST DEVRET IN COPIED UFD
	SUBI	T1,(F)		;RELATIVE DISTANCE
	ADDM	T1,DEVRET##(P3)	;NEW DEVRET POINTS TO RIGHT PNTR
	SOS	DEVBLK##(P3)	;RESET LOCS IN THE DDB WHICH WE WILL WRITE FROM
	SOS	DEVREL##(P3)	; (DIRRED INCREMENTS BEFORE I/O)
	AOS	DEVLFT##(P3)
	MOVEM	P1,.USMBF	;BUFFER TO READ INTO
	MOVE	P4,P2		;PNTR TO MON BUF WITH UFD DATA
	AOSA	P4		;GO FIND 1ST EMPTY SLOT
	ADD	P4,[XWD 2,2]
	SKIPE	(P4)		;THIS SLOT FREE?
	JRST	.-2		;NO, TRY NEXT
	MOVEM	S,DEVIOS(P3)	;SAVE S (IOSFIR) IN WRITING-DDB
	PUSH	P,DEVPPN(F)	;IF DIRRED HAS TO READ THE UFD RIB
	MOVE	T1,DEVACC##(F)	; AND WE WERE CALLED VIA
	MOVE	T1,ACCPPB##(T1)	; RENAME ACROSS DIRECTORIES
	MOVE	T1,PPBNAM##(T1)	; UFDRED WILL CHECK DEVPPN
	MOVEM	T1,DEVPPN(F)	;SO MAKE IT RIGHT



UFDCM5:	PUSHJ	P,DIRRED##	;READ INTO P1-BUFFER
	  JRST	UFDCM9		;EOF - FINISH UP
	MOVE	P1,.USMBF	;POINTER TO THIS UFD BLOCK DATA
UFDCM6:	SKIPN	T1,1(P1)	;PICK UP UFD ENTRY
	JRST	UFDCM5		;DONE - READ NEXT UFD BLOCK
	MOVEM	T1,(P4)		;SAVE IN OUTPUT-BUFFER
	MOVE	T1,2(P1)	;GET EXTENSION, CFP
	MOVEM	T1,1(P4)	;SAVE IN OUT-BUF
	AOBJN	P4,.+1		;COUNT OUTPUT WORDS
	AOBJP	P4,UFDCM8	;GO IF OUT-BUFFER IS FULL
UFDCM7:	AOBJN	P1,.+1		;COUNT INPUT WORDS
	AOBJN	P1,UFDCM6	;GO IF MORE IN THIS BLOCK
	JRST	UFDCM5		;BLOCK THROUGH - READ NEXT
;STILL IN FTDUFC CONDITIONAL
;HERE WITH P2-BUFFER FULL, WRITE IT
UFDCM8:	EXCH	P2,.USMBF	;WRITE THE P2-BUFFER
	PUSHJ	P,DIRWRT	;WRITE THE UFD BLOCK
	EXCH	P2,.USMBF
	MOVE	P4,P2		;POINTER TO THE BUFFER
	AOJA	P4,UFDCM7	;GO FILL IT AGAIN

;HERE WHEN THE UFD HAS BEEN COMPLETELY READ
UFDCM9:
	POP	P,DEVPPN(F)

	HLRE	P1,P4		;SAVE NO OF WDS IN LAST BUFFER
	SETZM	(P4)		;ZERO THE REST OF THE UFD BLOCK
	AOBJN	P4,.-1
	HLLOM	DEVLFT##(P3)	;MAKE SURE DIRWRT DOESNT CHANGE DDB DATA
				; (LAST BLOCK OF A GROUP)
	EXCH	P2,.USMBF	;WRITE P2-BUFFER
	PUSHJ	P,DIRWRT	;WRITE THE LAST UFD DATA BLOCK
	EXCH	P2,.USMBF
	HRRM	P2,DEVDMP##(P3)	;SAVE LOC OF EXTRA MON BUF
	MOVE	P4,DEVREL##(P3)	;NEW SIZE OF UFD
	CAMN	P4,DEVREL##(F)	;SAME AS ORIGINAL SIZE?
	CAMG	P1,[EXP -2*6]	;YES. AT LEAST 6 FREE SLOTS?
	SETZ	P1,		;YES. SET P1=0(DON'T ALLOCATE)
	PUSHJ	P,UFORSS##	;GET L(UFB OF SFD A.T.)
	TRZ	T3,NMPSFU##	;CLEAR NOISE BIT
	MOVSI	T4,UFPZRB##	;COMPRESSED SUCCESSFULLY
	ANDCAM	T4,UFBZRB##(T3)	;BLOCK OF ZEROES IS GONE
	MOVE	P2,DEVPPN(F)	;IN CASE IT IS H OR SFD
	TRZE	T2,NMPSFU##	;SFD?
	JRST	[PUSHJ P,GETCB## ;YES, JUST UPDATE ACCWRT
		 JRST UFDCMA]
	MOVE	T3,T2		;NO, GET LOC IN T3
	DPB	P4,UFYWRT##	;SAVE NEW NO OF BLOCKS WRITTEN
	MOVE	P2,DEVACC##(F)	;GET (NEW) PPB NAME
	MOVE	P2,ACCPPB##(P2)	; AND SAVE IN DEVPPN FOR UFDACC
	MOVE	P2,PPBNAM##(P2)
	EXCH	P2,DEVPPN(F)
	PUSHJ	P,UFDACC	;FIND THE UFD NMB IN [1,1]
UFDCMA:	  MOVEM	P4,ACCWRT##(T2)	;%SAVE UPDATED SIZE IN NMB
	MOVEM	P2,DEVPPN(F)	;RESTORE OLD PPN
	PUSHJ	P,GVCBJ##	;%GIVE UP CB RESOURCE
UFDCMB:	JSP	T4,RIBUN##	;SET U TO UNIT OF UFD RIB
	PUSHJ	P,UFDCRD	;READ THE RIB
	  JRST	UFDCMC		;CAN'T READ IT
	LSH	P4,BLKLSH##	;COMPUTE NO WDS IN UFD
	MOVEM	P4,RIBSIZ##+1(T1) ;SAVE IN RIB
	MOVE	T3,RIBSTS##+1(T1) ;GET STATUS BITS
	TRZN	T3,RIPCBS##	;TURN OFF RIBCBS
	TRZ	T3,RIPCMP##	;BUT NOT RIPCMP IF IT WAS ON GNTRY
	MOVEM	T3,RIBSTS##+1(T1) ;REPLACE BITS
	PUSHJ	P,MONWRT##	;AND GO REWRITE THE RIB
;STILL IN FTDUFC CONDITIONAL
UFDCMC:	EXCH	P3,F		;SET F=L(EXTRA DDB)
	HRRZ	T1,DEVDMP##(F)	;LOC OF EXTRA MON BUF
	PUSHJ	P,GVMNBF	;RETURN 2ND MONITOR BUFFER
	HRRZ	U,DEVUNI##(F)	;SAVE UNIT OF LAST UFD BLOCK
	MOVE	P2,DEVBLK##(F)	;AND NO OF THE BLOCK
	PUSHJ	P,CLRDDB	;RETURN THE EXTRA DDB
	MOVE	F,P3		;RESTORE F
	JUMPN	P1,CPOPJ1##	;GO IF HAVE TO ALLOCATE MORE BLOCKS
	MOVE	T2,P2		;DON'T ALLOCATE - BLOCK TO WRITE
	PJRST	STORU##		;SAVE UNIT TO WRITE THE BLOCK AND NON-SKIP

;HERE IF NO ROOM FOR ANOTHER DDB
UFDCMD:	MOVE	F,P3
	PJRST	CPOPJ1##

;SUBROUTINE TO WRITE A UFD BLOCK
;WRITES THE MONITOR BUFFER WHOSE ADDR IS IN THE EXTRA DDB (POINTED TO BY P3)
DIRWRT:	EXCH	P3,F		;SAVE F, SET UP OTHER DDB
	HRRZ	U,DEVUNI##(F)	;UNIT OF UFD DATA
	SETZM	DEVNAM(F)	;DEVNAM=0 - WRITE UFD BLOCK
	PUSHJ	P,DIRRED##	;GO WRITE THE BLOCK
	HRRZ	T1,DEVLFT##(F)	;NO OF BLOCKS LEFT IN POINTER
	SOJGE	T1,DIRWR1	;GO IF THERE IS ANOTHER BLOCK

;HERE IF THE PNTR IS EXHAUSTED
;CALL DIRRED ONCE MORE TO SET UP NEXT PNTR
;(MAY HAVE TO READ THE RIB INTO MON BUF)
	SETOM	DEVNAM(F)	;SO DIRRED WON'T WRITE
	PUSHJ	P,DIRRED##	;GO SET UP NEXT PNTR
	  JFCL			;DIRRED RETURNS CPOPJ1
	SOS	DEVBLK##(F)	;RESET THE DDB LOCS WHICH DIRRED CHANGED
	SOS	DEVREL##(F)	; (THESE LOCS ARE BUMPED BEFORE WRITING)
	AOS	DEVLFT##(F)
DIRWR1:	EXCH	P3,F		;RESTORE F
	HRRZ	U,DEVUNI##(F)	; AND U
	POPJ	P,		;AND EXIT
;STILL IN FTDUFC CONDITIONAL
;ROUTINE TO TEST IF IT'S OK TO COMPRESS
;DON'T COMPRESS IF SOMEBODY IS READING THE DIRECTORY AS A FILE.
;IT'LL SCREW UP HIS WILDCARD ROUTINE.
;T2 PASSES UFB OR SFD ACC
;CPOPJ IF NOT OK TO COMPRESS
;CPOPJ1 IF OK
;RULES:
;1. DON'T CALL CMPOK EXCEPT AS A LAST DITCH BEFORE
;YOU COMPRESS. (CMPOK IS SLOW).
;2. IF CMPOK SAYS DON'T COMPRESS, THEN TRY EVERYTHING
;POSSIBLE BEFORE ALLOCATING MORE DIRECTORY BLOCKS.
CMPOK:	TRZN	T2,NMPSFU##	;SFD OR UFD?
	JRST	CMPOK1		;UFD
	PUSHJ	P,GETCB##	;SFD, GET INTERLOCK
	LDB	T1,ACZCNT##	;%GET USE COUNT
	SOJE	T1,GVCBJ1##	;%COMPRESS IF WE'RE THE ONLY GUY
CMPOK2:	HLRZ	T2,ACCNMB##(T2)	;%FIND NMB
	TRZN	T2,DIFNAL##
	JRST	CMPOK2
	MOVE	T3,NMBCNT##(T2)	;%COUNT UP ONLY BECAUSE SET PATH?
	SOJE	T3,GVCBJ1##	;%SET PATH DOESN'T BUMP NMBCNT
;NMBCNT IS PROBABLY WRONG AGAIN, DOUBLE CHECK.
	MOVE	T3,HIGHJB##	;%HIGHEST JOB IN USE
CMPOK3:	HRRZ	T4,JBTSFD##(T3)	;%DOES JOB HAVE PATH SET HERE?
	TRZ	T4,CORXTR##
	CAMN	T2,T4
	SOJE	T1,GVCBJ1##	;%YES, COMPRESS IF ALL ACCOUNTED FOR
	SOJG	T3,CMPOK3	;%NO, TEST NEXT JOB
	PJRST	GVCBJ##		;%SOMEBODY LEFT, DON'T COMPRESS
CMPOK1:	PUSHJ	P,UFDACC	;FIND THE UFD'S ACC
	  SKIPA	T1,ACCCNT##(T2)	;%PICK UP THE USE COUNT
	PJRST	GVCBJ1##	;%NO ACC, NO READER, COMPRESS
	TRNN	T1,ACMCNT	;%IS THERE A READER?
	AOS	(P)		;%NO, COMPRESS
	PJRST	GVCBJ##
>;END CONDITIONAL ON FTDUFC
;RELEASE UUO
DSKREL:	PUSHJ	P,WAIT1##	;WAIT FOR I/O TO STOP
	PUSHJ	P,NULTST	;IF NULL
	  POPJ	P,		; DONT DO ANYTHING
	MOVE	J,.CPJOB##	;SET J FOR RETRES
IFN FTFDAE,<
	PUSHJ	P,CHKFCU	;CHECK IF AT COUNT UP FOR FILDAE
>
	PUSHJ	P,RETRES##	;RETURN ANY RESOURCES DDB HAS
				;IN CASE OF ERROR RE-ENTRY)
	SKIPGE	DEVSPL(F)	;SPOOLING DEVICE?
	TLOE	S,IOSRST	;YES, DO A CLOSE INSTEAD OF A RELEASE
				; (BUT IF ERROR, NEXT RELEASE WILL RESET)
	TLO	F,RESETB	;INDICATE RESET IN PROGRESS
	PUSHJ	P,GTMNBF##	;COULD HAVE GIVEN IT UP ON A KJOB
	PUSHJ	P,CLOSIN	;CLOSE INPUT (IF NOT ALREADY DONE)
	TLO	F,ICLOSB
	PUSHJ	P,CLOSOU	;CLOSE OUTPUT (DITTO)
	TLO	F,OCLOSB
	TLZE	S,IOSUPR	;SUPER USETI/O?

	TLNN	S,IOSERR##	;YES, ANY ERRORS?
	JRST	DSKRL1		;NO
;HERE TO WRITE BAT BLOCK FOR ERRORS DETECTED DURING INPUT/OUTPUT WITH SUPER USETI/O
;MUST DO AT RELEASE SINCE NO FILE IS OPEN SO CLOSE WONT WRITE THEM
	MOVEM	S,DEVIOS(F)	;SAVE S, IOSUPR OFF
	PUSHJ	P,SETU##	;YES, WRITE BAT BLOCK SINCE CLOSE DID NOT
	  JRST	DSKRL1		;IF F/S JERKED, OR OUTPUT CLOSE DONE
	MOVSI	T1,UNPHWP##	;DON'T TRY TO UPDATE BAT BLOCK
	TDNE	T1,UNIDES##(U)	;IF THE UNIT IS HARDWARE WRITE PROT.
	JRST	DSKRL1		;IT IS SO FORGET IT
	PUSHJ	P,TSTBAD	;FIND EXTENT OF BAD REGION
	MOVE	T1,.USMBF	;LOC OF MON BUF
	HRRZ	T2,RIBNBB##+1(T1) ;NO OF BAD BLOCKS
	MOVE	T1,DEVELB##(F)	;FIRST BAD BLOCK
	TLZ	T1,BATMSK##	;ONLY BLOCK NUMBER
	JUMPE	T1,DSKRL0
	HRRZ	T3,UNISTR##(U)	;DONT ALLOCATE IF NOT IN A STR
	JUMPE	T3,DSKRL0
	PUSHJ	P,TAKBLK##	;ALLOCATE THEM IF POSSIBLE
	  JFCL			; (SO WONT BE GIVEN UP AGAIN)
DSKRL0:	PUSHJ	P,ERRFIN	;WRITE BAT BLOCKS
	TLZ	S,IOSERR##	;NO BAD BLOCKS NOW

DSKRL1:	TLZ	F,RESETB	;RESET BIT
	SETZM	DEVFIL(F)	;INDICATE FILE RELEASED
	SETZM	DEVUFB##(F)	;ZERO DEVUFB SO UFDLK WILL WORK RIGHT
	SETZM	DEVREL##(F)	;ZERO DEVREL SO SUPER USETI WILL WORK RIGHT
	SETZM	DEVPPN(F)	;ZERO DEVPPN SO SPTSTO/I WILL WORK RIGHT
	SETZM	DEVSFD##(F)	;ZERO DEVSFD SO NO SFD TO START
	SETZM	DEVELB##(F)	;ZERO DEVELB SO NEXT ERROR WILL GET IN BAT BLOCK

	HLLZS	DEVCPY##(F)	;SUPERSTITION
	TLZ	S,IOSWLK!IOSUPR!IOSRST!IOSMON	;ZERO SOME BITS
	MOVSI	T1,DEPLIB##	;CLEAR DEPLIB IN DDB
	ANDCAM	T1,DEVLIB##(F)
	MOVEI	T1,DEPPAL##	;CLEAR PRE-ALLOCATING FILE
	ANDCAM	T1,DEVPAL##(F)
	PJRST	STOIOS##	;SAVE IN DDB AND RETURN

;ROUTINE TO WRITE A DIRECTORY BLOCK
WRTDIR:	MOVE	T1,.USMBF	;IOWD FOR MONITOR BUFFER
	MOVE	T2,DEVBLK##(F)	;BLOCK NUMBER
	;PJRST	WRTUFD		;GO WRITE THE UPDATED UFD

;SUBROUTINE TO WRITE A UFD BLOCK
;ENTER WITH AC'S, DATA SET AS FOR MONWRT
WRTUFD:	TLZ	S,IOSFIR	;MAKE SURE IOSFIR IS OFF
	PJRST	MONWRT##	;WRITE UFD
IFN FTFDAE,<
;SUBROUTINE TO CHECK IF AT COUNT IS UP
;IF SO, DECREMENT COUNT
CHKFCU:	MOVSI	T1,DEPFCU##
	TDNN	T1,DEVFCU##(F)	;COUNT UP?
	POPJ	P,		;NO
	ANDCAM	T1,DEVFCU##(F)	;YES, BUT NO LONGER
	PUSHJ	P,DECRDR	;DECR COUNT
	  JUMPN	T1,GVCBJ##	;%EXIT IF OTHER READERS
	JUMPE	T1,CPOPJ##	;%DON'T HAVE CB IF NO AT
	SKIPN	ACCDOR##(T1)	;%ALREADY DORMANT?
	JRST	ATSDRA##	;%NO, MAKE DORMANT
	PJRST	GVCBJ##		;%AND RETURN
>
;SUBROUTINE TO FIND THE ACCESS TABLE FOR A UFD
;ASSUMES PRJ,PRG IS IN DEVPPN  -  UFD JUST READ UNDER [1,1]
;RETURNS CPOPJ IF FOUND, WITH T2=LOC OF A.T.;  CPOPJ1 IF NOT FOUND
;ALWAYS RETURNS WITH THE CB RESOURCE
UFDACC:	MOVE	T1,MFDPPN##	;PPN FOR UFD'S
	PUSHJ	P,GETCB##	;GET CB RESOURCE
	HLRZ	T2,SYSPPB##	;%START OF UFD BLOCKS
	PUSHJ	P,LSTSCN##	;%SEARCH FOR THIS MFD PPB
	  JRST	CPOPJ1##	;%NOT THERE
	HLRZ	T2,PPBNMB##(T2)	;%START OF NMBS UNDER MFD
	MOVE	T1,DEVACC##(F)	;%GET PPN FROM A.T.
	MOVE	T1,ACCPPB##(T1)	;% (DEVPPN "WRONG" IF RENAMING
	MOVE	T1,PPBNAM##(T1)	;%ACROSS DIRECTORIES)
	SETO	T3,		;%INDICATE DON'T CREATE NMB IF NOT FOUND
UFDAC1:	PUSHJ	P,LSTSRA##	;%SEARCH FOR IT
	  JRST	CPOPJ1##	;%NOT THERE
	HRRZ	T3,NMBEXT##(T2)	;%EXTENSION
	CAIN	T3,(SIXBIT .UFD.) ;%IS IT "UFD"?
	JRST	UFDAC2		;%YES. OK
	HLRZ	T2,NMBPPB##(T2)	;%NO. IGNORE THE ENTRY
	TRNE	T2,NMPUPT##	;%IS IT A REAL NMBPPB POINTER?
	PJRST	CPOPJ1##	;%NO, RETURN (UPWARD PNTR TO FATHER SFD)
	JRST	UFDAC1		;%YES, SCAN FOR ANOTHER JBTPPN NAME BLOCK
UFDAC2:	HLRZ	T2,NMBACC##(T2)	;%FOUND NMB FOR THIS UFD. LOC OF 1ST A.T.
	MOVE	T1,DEVACC##(F)	;%A.T. FOR THIS FILE
	LDB	T1,ACZFSN##	;%FSN OF FILE (=FSN OF UFD)

	PJRST	BYTSCA##	;%SEARCH FOR A.T. FOR UFD
;SUBROUTINE TO TEST IF THE PPB BLOCK IS IN USE
;IF SO,RETURN     IF NOT, TEST THE UFB BLOCKS
;IF A UFB IS FOUND WHICH IS NOT CURRENTLY BEING USED BY A FILE, RETURN TO FREE CORE
;IF ALL UFB'S ARE RETURNED, RETURN THE PPB TO FREE CORE
;CALLED BY CLOSE
TSTPPB::CBDBUG	(N,Y);
	LDB	J,PJOBN##	;JOB NUMBER
	MOVE	T1,JBTSTS##(J)	;STATUS WORD
	TLNE	T1,JACCT	;JACCT ON (PROBABLY LOGIN)?
	TLNE	T1,JLOG		;YES, JOB LOGGED IN?
	CAIA			;YES, CAN'T BE LOGIN
	POPJ	P,		;NO. LEAVE CORE BLOCKS ALONE
TSTPP1:	PUSHJ	P,GETCB##	;GET CB RESOURCE
	MOVE	T1,DEVPPN(F)	;%PPN OF FILE
TSTPPX::HLRZ	T2,SYSPPB##	;%NO, GET LOC OF 1ST PPB
	PUSHJ	P,LSTSCN##	;%SEARCH FOR PPB BLOCK
	  PJRST	GVCBJ##		;%
TSTPP2:	MOVE	T1,PPBNLG##(T2)	;%LOGGED-IN WORD
	SKIPN	PPBCNT##(T2)	;%ANY DDBS USING PPB?
	TRNE	T1,PPPNLG##	;%IS PPN LOGGED IN?
	PJRST	GVCBJ##		;%YES. GIVE UP CB AND RETURN
	PUSH	P,T2		;%NO. SAVE LOC OF PPB
	CAMN	T3,[-1]		;%FIRST PPB?
	MOVEI	T3,SYSPPB##	;%YES, SET PREDECESSOR
	HRLM	T3,(P)		;%SAVE LOC OF PREDECESSOR
	MOVEI	T3,DIFPBC##(T2)	;%PPB=PRED OF 1ST UFB
	HLRZ	T4,PPBUFB##(T2)	;%LOC OF 1ST UFB IN PPB
	JUMPE	T4,TSTPP4	;%NONE IF 0
TSTPP3:	HLL	T4,CORLNK##(T4)	;%SAVE LINK TO NEXT UFB
	PUSHJ	P,RET4WD	;%NO, DELETE THIS UFB
	HLRZS	T4		;%NEXT UFB INTO T4
	JUMPN	T4,TSTPP3	;%TEST IT IF IT EXISTS
TSTPP4:	POP	P,T1		;%LOC OF PPB
	HLRZ	T2,PPBNMB##(T1)	;%LOC OF 1ST NMB UNDER PPB
	PUSHJ	P,SAVE2##	;%SAVE P1,P2
	PUSH	P,T1		;%SAVE LOC OF PPB 1ST ON PD LIST
	SKIPA	P1,T2		;%P1=LOC OF 1ST NMB
TSTPP5:	HLRZS	P1		;%NEXT NMB
	TRZE	P1,NMPUPT##	;%IS IT A PNTR TO A FATHER SFD?
	JRST	TSTPP7		;%YES, GO CHECK FATHER
TSTPP6:	JUMPE	P1,TSTPP9	;%NO NMBS  - DELETE PPB
	HLRZ	T3,NMBRNG##(P1)	;%NMB FOR AN SFD?
	JUMPE	T3,TSTPP7	;%NO, CONTINUE
	MOVE	P1,T3		;%YES, DOES IT POINT TO ANOTHER NMB LIST?
	TRZN	P1,NMPUPT##	;%
	JRST	TSTPP6		;%YES, TURN DOWN THAT CHAIN
;HERE WHEN THE NMB IS REMOVABLE
TSTPP7:	HLRZ	T1,NMBACC##(P1)	;%LOC OF 1ST A.T. ON NMB RING
	TRNE	T1,DIFNAL##	;%1-ITEM RING?
	JRST	TSTPP8		;%YES. ALL A.T.'S GIVEN UP
	PUSH	P,F		;%NO, SAVE F
	MOVEI	F,0		;%INDICATE DONT MESS WITH CB RESOURCE
	PUSHJ	P,ATRMOV##	;%REMOVE THE ACCESS TABLE
	POP	P,F		;%RESTORE F
	JUMPE	F,TSTPP7	;%CANT BE OUR AT IF DEVACC =0
	HRRZ	T2,DEVACC##(F)	;%OUT A.T.
	CAIN	T2,(T1)		;%DID WE REMOVE THE AT FOR THIS DDB?
	HLLZS	DEVACC##(F)	;YES, CLEAR DEVACC
	JRST	TSTPP7		;%AND GO TEST NEXT AT IN THE RING
TSTPP8:	HLL	T1,SYSCOR##	;%CURRENT 1ST FREE CORE BLOCK
	HRLM	P1,SYSCOR##	;%THIS NMB IS NEW 1ST FREE
	HLL	P1,NMBPPB##(P1)	;%LH(P1)=LOC OF NEXT NMB
	HLLM	T1,CORLNK##(P1)	;%LINK PREVIOUS 1ST FREE TO THIS
IFN FTCBDB,<
	MOVE	T4,(P)		;FAKE OUT DATA-BASE CHECKER
	HLLM	P1,PPBNMB##(T4)	; BY SETTING PPBNMB TO 1ST REMAINING NMB
>
	JRST	TSTPP5		;%AND GO DELET NEXT NMB RING


TSTPP9:	POP	P,T4		;%LOC OF PPB
	SKIPE	PPBLOK##(T4)	;%ANY INTERLOCKS SET?
	PJRST	TSTP10		;%YES, LEAVE PPB ALONE
	HLRZ	T3,T4		;%PRED OF PPB
	CAIN	T3,SYSPPB##	;%PRED=SYSPPB?
	SUBI	T3,CORLNK##	;%YES. ADJUST PREDECESSOR
	PUSHJ	P,RET4WD	;%RETURN PPB TO FREE CORE
	HRRZ	T2,SYSPPB##	;%PPB THE CORE GRABBER WILL LOOK AT NEXT
	CAIN	T2,(T4)		;%DID WE JUST DELETE IT?
	HLLZS	SYSPPB##	;%YES, START AT 1ST PPB NEXT TIME
	CBDBUG	(Y,Y);
	PJRST	GVCBJ##		;%GIVE UP CB RESOURCE AND RETURN

;HERE IF INTERLOCKS SET IN PPB
TSTP10:	SETZM	PPBNMB##(T4)	;%DON'T LEAVE FUNNY LINKS
	SETZM	PPBUFB##(T4)	;% HANGING AROUND IN DATABASE
	PJRST	GVCBJ##


;SUBROUTINE TO RETURN A 4-WORD BLOCK TO FREE CORE.
;THIS ROUTINE LINKS THE PREDECESSOR BLOCK AROUND THE BLOCK BEING RETURNED
;ENTER WITH T4=LOC OF BLOCK TO RETURN,  T3=LOC OF PREDECESSOR
;ENTER AT RETXWD IF DONT CARE ABOUT PREDECESSOR LINK
RETXWD:	MOVE	T3,T4		;%MAKE SURE DONT CLOBBER ANYTHING WITH T3
RET4WD::MOVE	T1,CORLNK##(T4)	;%LINK TO NEXT BLOCK
	HLLM	T1,CORLNK##(T3)	;%SAVE AS LINK IN PREDECESSOR
	MOVE	T1,SYSCOR##	;%1ST FREE CORE BLOCK
	HRLM	T4,SYSCOR##	;%SAVE THIS AS 1ST BLOCK
	HLLM	T1,CORLNK##(T4)	;%LINK PREVIOUS 1ST TO THIS ONE
	POPJ	P,		;%AND RETURN
SUBTTL	LOOKUP

ULOOK:	PUSHJ	P,NULTST	;ON DEVICE NUL,
	  PJRST	CPOPJ1##	; LOOKUP WINS
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;SPOOL-MODE?
	PJRST	CPOPJ1##	;YES, OK RETURN
>
	TLNE	F,ENTRB		;ENTER IN FORCE?
	JRST	LUKER1		;YES. ERROR RETURN
	SETZM	DEVSFD##(F)
	TLZ	F,INPB		;MIGHT BE ON FROM SUPER I/O
	SETZM	DEVLNM##(F)	;NOT A LOGICAL NAME TO START WITH
	PUSHJ	P,SAVE4##	;SAVE ACS (SETLER RETURNS STUFF IN P3,P4)
	PUSHJ	P,SETLER	;NO, SET UP UUO FOR LOOKUP
	  JRST	ILNMER		;ILLEGAL NAME - ERROR RETURN
	MOVSI	T2,DEPLIB##	;MAKE SURE DEPLIB IS OFF
	ANDCAM	T2,DEVLIB##(F)	; SO UPDATE WILL WIN
	SKIPE	DEVLNM##(F)	;IF A LOGICAL NAME
	TLZ	F,SYSDEV	;NOT FROM SYS (YET)
	MOVSI	T2,DEPFFS##!DEPFFL## ;CLEAR FOUND BY SCANNING, FOUND IN LIB
	ANDCAM	T2,DEVPTB##(F)	; BITS FROM THE DDB
	HLLZS	T1,DEVCFS##(F)	;CLEAR USER-SUPPLIED CFP
	TLNE	T1,DEPCFS##	;IS USER SUPPLYING CFPS?
	PUSHJ	P,PRVJB##	;YES. PRIV'D JOB?
	  JRST	ULOOK1		;NO CFPS
	HRRI	M,UUXELB-UUXNAM(M) ;GET USER-SUPPLIED CFP
	PUSHJ	P,GETWDU##
	HRRM	T1,DEVCFS##(F)	;SAVE IN THE DDB FOR FILFND
	HRRI	M,UUXNAM-UUXELB(M) ;RESET M TO NAME
ULOOK1:	PUSH	P,[-1,,0]	;INITIALIZE ERROR - SAVE
	TLOA	M,UUOLUK
ULOOK2:	TLO	M,UTRTWC
	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST IN T1
	JRST	[SKIPN DEVLNM##(F)
		 JRST ULOO20
		 MOVEI T1,SLEERR
		 JRST ULOOK4]
ULOOK3:	TLO	M,UUOLUK	;INSURE FNDFIL KNOWS
	MOVE	T2,T1		;SEARCH LIST INTO T2

	TLZ	S,IOSWLK	;MAKE SURE IOSWLK OFF (IN CASE OF RENAME)
	PUSHJ	P,FNDFIL##	;SEARCH FOR FILE NAME
	  SKIPA			;ERROR
	JRST	FOUND		;FILE FOUND

;HERE ON AN ERROR RETURN FROM FNDFIL
	SETZM	DEVUNI##(F)	;ZERO DEVUNI SO THAT UNILUP WILL WORK RIGHT IF AN
				; ENTER IS DONE (IT POINTS TO UFD-UNIT NOW)
	SETZM	DEVUFB##(F)	;ZERO DEVUFB SO TSTPPB WILL WORK RIGHT
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;SPOOL MODE?
	POPJ	P,		;YES, IMMEDIATE RETURN
>
	CAIE	T1,TRNERR
	CAIN	T1,PRTERR
	SETZM	(P)
ULOOK4:	HRRM	T1,(P)
	PUSHJ	P,TSTPPB	;DELETE USELESS CORE BLOCKS
	SKIPL	(P)
	JRST	ULOO15

	HRRZ	T1,DEVSFD##(F)	;SCAN - GET LOC OF SFD
	JUMPE	T1,ULOOK7	;DONE IF 0 (JUST SEARCHED UFD)
	PUSHJ	P,SFDDEC
	LDB	T2,DEYSCN##	;SCANNING SWITCH
	JUMPE	T2,ULOOK6	;DON'T SCAN IF 0
	MOVSI	T2,DEPFFS##	;SET FILE-FOUND-BY-SCANNING BIT IN DDB
	IORM	T2,DEVPTB##(F)	;(WILL CLEAR IF NOT FOUND)
	PUSHJ	P,DECALL	;DECR. USE-COUNTS OF THIS SFD
ULOOK5:	HLRZ	T1,NMBPPB##(T1)	;SCAN FOR POINTER TO FATHER SFD
	TRZN	T1,NMPUPT##
	JUMPN	T1,ULOOK5
	HRRM	T1,DEVSFD##(F)	;FOUND - SAVE AS CURRENT SFD
	SKIPE	T1		;UFD ITSELF?
	PUSHJ	P,INCALL	;NO, INCR. USE-COUNTS OF A.T.'S
	PUSHJ	P,SFDUP
	JRST	ULOOK2		;AND RETRY THE LOOKUP IN THIS DIRECTORY
ULOOK6:	HRRZ	T1,DEVSFD##(F)	;IF AN SFD IS DEFAULT PATH
	JUMPE	T1,ULOOK7	; AND SCAN IS OFF
	PUSHJ	P,DECALL	;DECR SFD USE-COUNTS
ULOOK7:	SETZM	DEVSFD##(F)	;SO LIB WILL BE SEARCHED
	MOVSI	T2,DEPFFS##	;DIDN'T FIND IT BY SCANNING
	ANDCAM	T2,DEVPTB##(F)
	SKIPL	(P)		;ARE WE REMEMBERING AN ERROR?
	JRST	ULOO15		;YES, DON'T TRY LOGICAL NAMES
	SKIPN	DEVLNM##(F)	;NO, LOOKING AT LOGICAL NAME?
	JRST	ULOOK8		;NO, SEE IF /SYS
	PUSHJ	P,NXTSPC	;YES, GET NEXT PART OF SPECIFICATION
	  JRST	ULOOK2		;TRY LOOKUP ON THIS PPN/SFD
	SETZM	DEVLNM##(F)	;AT END OF SPEC - NOT IN TTHIS LOG NAME
	JRST	ULOO10		;SEE IF /SYS WANTED
ULOOK8:	MOVSI	T2,'SYS'
	CAMN	T2,DEVNAM(F)	;IF LOOKUP SYS:FILE TRIED NEW:
	JRST	ULOO12		; THEN TRY SYS: WITHOUT DEPLIB
	SUB	T2,DEVLOG(F)	;T2 = 0 IF LOGICAL SYS
	MOVSI	T1,DEPPP0##
	TDZE	T1,DEVPP0##(F)	;WAS E+3=0 ON LOOKUP?
	JUMPN	T2,ULOO20	;NO, NO LIB/SYS IF NOT LOGICAL SYS
	HLR	T2,T1		;T2=0 IF LOGICAL SYS, NOT DSK=SYS
	MOVE	T1,DEVLLE##(F)	;HOW WE HANDLE LIB
	TLNE	T1,DEPDSL##	;DON'T SEARCH IT (OR SYS?)
	JRST	ULOO20		;YES, LOOKUP FAILS
	TLNE	T1,DEPAUL##	;ALLOW UPDATE/RENAME IN LIB?
	TDZA	T1,T1		;YES, DON'T LIGHT DEPLIB
	MOVSI	T1,DEPLIB##	;INDICATE FROM LIB/SYS
	ORM	T1,DEVLIB##(F)	;IN CASE THIS LOOKUP WINS
				; (IN CASE OF UPDATE)
	TLNE	F,SYSDEV	;SYSTEM?
	JRST	ULOO12		;YES
	JUMPE	T2,ULOO10	;SEARCH SYS IF LOGICAL SYS
	SKIPN	T1,.PDOSL##(W)	;IS THERE AN OLD-STYLE LIB?
	JRST	ULOOK9
	CAMN	T1,DEVPPN(F)	;YES. ALREADY SEARCHED IT?
	JRST	ULOO10		;YES, TRY SYS
	MOVEM	T1,DEVPPN(F)	;NO, SEARCH IT NOW
	JRST	ULOOK2
ULOOK9:	MOVE	T1,DEVNAM(F)	;SEARCH LIB IF OPEN WAS
	PUSHJ	P,ALIASD##	; DONE ON "DSK"
	  PUSHJ	P,FNDLB		;IS THERE A LIB?
	  JRST	ULOO10		;NO, TEST IF /SYS
	MOVSI	T1,DEPFFL##	;LIGHT FILE-FOUND-IN-LIB
	IORM	T1,DEVPTB##(F)	; SINCE ITS EITHER IN LIB/SYS OR LOOKUP FAILS
	MOVE	T1,@.USLNM	;YES, POINT AT LIB SPEC
	ADDI	T1,LNMDEV##-LNRDEV##
	HRRZM	T1,DEVLNM##(F)	;SAVE IT IN THE DDB
	PUSHJ	P,NXTSP3	;POINT AT START OF THE SPEC
	  JRST	ULOOK2		;GO LOOKUP FILE IN THIS PPB
;HERE IF DSK AND LIB ARE DONE, TRY SYS:
ULOO10:	HLRZ	T1,JBTSFD##(J)	;LIB, SYS BITS
	TRNN	T1,JBPSYS##	;USER WANT TO LOOKUP SYS:?
	JRST	ULOO14		;NO, FILE NOT FOUND
	MOVE	T2,XSYPPN##	;YES, GET NEW: PPN
	TRNE	T1,JBPXSY##	;WANT NEW:?
	CAMN	T2,DEVPPN(F)	;YES, HAVE WE TRIED IT ALREADY?
	MOVE	T2,SYSPPN##	;YES, TRY REAL SYS
	TLO	F,SYSDEV	; AND SAY ITS REAL
ULOO11:	MOVEM	T2,DEVPPN(F)	;SAVE SYS OR NEW PPN
	MOVE	T1,DEVNAM(F)	;ARGUMENT FOR ALIASD
	PUSHJ	P,ALIASD##	;IS THIS "DSK"?
	  SKIPA			;YES, USE SYSTEM 'SL
	PUSHJ	P,SETSRC##	;NO, GET SEARCH LIST FROM DEVICE NAME
	  MOVE	T1,SYSSRC##
	MOVSI	T2,DEPFFL##	;LIGHT FOUND-IN-LIB
	IORM	T2,DEVPTB##(F)	; SINCE ITS EITHER IN SYS OR LOOKUP FAILS
	MOVE	T2,T1		;FNDFIL WANTS T2=SEARCH LIST
	PUSHJ	P,FNDFIL##	;LOOKUP THE FILE
ULOO12:	  SKIPA	T2,SYSPPN##	;DIDN'T FIND IT
	JRST	FOUND		;FOUND - FINISH UP
	TLNE	F,SYSDEV	;IF SYS (NEW)
	JUMPE	T1,ULOO13	;DON'T REMEMBER FNF ERROR
	SKIPGE	(P)		;ERROR CODE STORED? (NOT IF FNF ON SYS:)
	TLNE	T1,-1		;NO, ERROR RETURN FROM FNDFIL?
	CAIA			;NO
	MOVEM	T1,(P)		;YES, STORE ERROR NOW
ULOO13:	CAME	T2,DEVPPN(F)	;TRIED SYS?
	JRST	ULOO11		;NO, TRY IT NOW
ULOO14:	TLNE	M,UTRTWC
	SETZM	(P)
ULOO15:	PUSH	P,M		;SAVE M
	PUSHJ	P,GETWDU##	;GET E+3
	TLNN	T1,-1		;PATH POINTER ?
	HRRI	M,2(T1)		;YES, POINT AT PPN WRD
	HRRZ	T1,-1(P)	;GET THE ERROR CODE
	CAIE	T1,TRNERR	;RIB ERROR
	CAIN	T1,PRTERR	; OR PROTECTION FAILURE?
	SKIPA	T1,DEVPPN(F)	;YES, STORE THE PPN IN THE LOOKUP BLOCK
	SETZ	T1,		;NO, ZERO PPN WORD ON LOOKUP FAILURE
	PUSHJ	P,PUTWDU##
	SETZM	DEVPPN(F)	;SO PATH. WILL WIN
	JUMPE	T1,ULOO19	;DON'T STORE PATH IF NO PPN
	CAMN	M,(P)		;ARE WE FILLING IN A PATH BLOCK?
	JRST	ULOO19		;NO.  ALL DONE THEN.
	PUSH	P,[0]		;YES, PUT A MARKER ON THE STACK
	HRRZ	T2,DEVSFD##(F)	;GET THE FIRST SFD NMB POINTER
	JUMPE	T2,ULOO18	;JUMP IF NO SFD
ULOO16:	PUSH	P,NMBNAM##(T2)	;SAVE THE SFD NAME
ULOO17:	HLRZ	T2,NMBPPB##(T2)	;GET THE NEXT NMB LINK
	TRZN	T2,NMPUPT##	;POINTER TO THE NEXT HIGHER LEVEL?
	JUMPN	T2,ULOO17	;NO, TRY NEXT
	JUMPN	T2,ULOO16	;YES, REMEMBER THIS ONE
ULOO18:	POP	P,T1		;RESTORE AN SFD NAME
	PUSHJ	P,PUTWD1##	;STORE THE SFD NAME IN THE PATH BLOCK
	JUMPN	T1,ULOO18	;DO ALL OF THEM.
ULOO19:	POP	P,M
ULOO20:	POP	P,T1		;RESTORE ERROR CODE
	PJRST	LKENR4		;AND GO TELL USER
;HERE WHEN FILE NAME IS FOUND ON LOOKUP
;HERE WITH M AT PPN
FOUND:	MOVE	J,.CPJOB##	;JOB
	MOVE	T1,JBTSTS##(J)
	MOVE	T2,DEVFIL(F)	;FILE NAME WE LOOKED UP
	TRNE	T1,JS.ASA	;MONITOR DO THE LOOKUP (SAVGET)?
	MOVEM	T2,.JDAT+SGANAM## ;YES. MAKE SURE WE KNOW THE REAL FILE
	MOVE	T1,DEVPPN(F)	;PPN WE FOUND FILE IN
	CAME	T1,SYSPPN##	;IS IT SYS
	CAMN	T1,NEWPPN##	; OR NEW?
	SKIPA	T2,DEVACC##(F)	;YES, GET A.T.
	JRST	FOUND0		;NO
	LDB	T1,ACYFSN##	;GET FSN WE FOUND FILE ON
	PUSH	P,P2
	MOVE	P2,SYSSRC##
	PUSHJ	P,SLFND##	;IS FSN IN SYS SEARCH LISTT?
	  CAIA			;NO
	TLO	F,SYSDEV	;YES, TELL THE WORLD WE FOUND IT ON SYS
	POP	P,P2
FOUND0:
IFN FTDUFC,<
	PUSHJ	P,CMPSLP	;WAIT TILL UFD COMPRESSOR IS DONE
>
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T. ENTRY
	MOVE	T3,T2		;INTO T3 ALSO
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;SPOOL-MODE?
	JRST	FOUND3		;YES, DON'T STORE IN USER AREA
>
	POP	P,(P)		;REMOVE "ERROR CODE" FROM LIST
	TLNE	M,EXTUUO	;EXTENDED UUO?
	JRST	FOUND2		;YES
	PUSHJ	P,WRDCNT	;SAVE LENGTH IN E+3
	HRRI	M,-<UUNPPN-UUNATT>(M)	;POINT TO ATTRIBUTES WORD
	MOVE	T1,ACCPRV##(T3)	;DATE AND TIME WORD
	PUSHJ	P,PUTWDU##
	HRRI	M,-<UUNATT-UUNEXT>(M)	;POINT M TO ACCESS DATE WORD
	PUSHJ	P,GTWST2##	;GET ACCESS DATE WORD
	HLR	T1,ACCADT##(T3)	;ACCESS DATE
	PUSHJ	P,PUTWDU##	;STORE IT IN THE USER'S AREA
	HRRI	M,UUNPPN-UUNEXT(M) ;BACK TO PPN
	JRST	FOUND3		;FINISH UP (RIB DOESN'T HAVE TO BE READ)
;SUBROUTINE TO COMPUTE THE CONTENTS OF E+3 FOR LOOKUP/UPDATE ENTER
;EXITS T1=E+3 WORD (ALSO STORED IN USERS AREA)
; T2, T3=LOC OF A.T.
WRDCNT:	HRRZ	T2,DEVACC##(F)	;AT LOC INTO T2
	MOVE	T3,T2		;AND T3
	SKIPE	T1,ACCWRT##(T2)	;GET HIGHEST WRITTEN BLOCK
	SUBI	T1,1		;LAST BLOCK WILL BE COUNTED SEPERATELY
	CAIL	T1,2000		;GT 2^17 WORDS?
	AOJA	T1,FOUND1	;YES, STORE +BLOCK COUNT
	LSH	T1,BLKLSH##	;NO, CONVERT TO WORDS
	LDB	T4,ACZLBS##	;GET NO. OF WORDS IN LAST BLOCK
	ADD	T1,T4		;ADD INTO TOTAL NUMBER OF WORDS
	MOVNS	T1		;STORE -N IN LH
FOUND1:	HRLZS	T1
	PJRST	PUTWDU##	;STORE LENGTH IN E+3 AND RETURN

;HERE WHEN FILE IS FOUND FOR AN EXTENDED LOOKUP
FOUND2:	HRRI	M,-UUXPPN(M)
	PUSHJ	P,GTWST2##	;NUMBER OF ARGUMENTS
	MOVE	P1,T1
	TRZ	P1,RB.BIT	;CLEAR FLAG BITS
	HRRI	M,UUXPPN(M)	;POINT TO PPN WORD
	PUSH	P,M
	PUSHJ	P,GETWDU##	;GET PPN/SFD LIST WORD
	TLNN	T1,-1		;IS IT AN SFD POINTER?
	HRRI	M,2(T1)		;YES. POINT M TO REAL PPN WORD
	MOVE	T1,DEVPPN(F)	;GET PPN (MIGHT BE LIB,SYS,NEW)
	PUSHJ	P,PUTWDU##	;TELL USER REAL PPN
	POP	P,M
	CAIGE	P1,4		;STORE VALUES?
	JRST	FOUND3		;NO. FINISH UP
	HRRI	M,UUXPRV-UUXPPN(M)	;YES. POINT TO PRIVS WORD
	MOVE	T1,ACCPRV##(T3)	;PRIVILEGES WORD
	PUSHJ	P,PUTWDU##	;SAVE IN USERS AREA
	HRRI	M,-<UUXPRV-UUXEXT>(M)	;POINT TO ACCESS DATE WORD
	PUSHJ	P,GTWST2##	;GET ACCESS DATE WORD
	HLR	T1,ACCADT##(T3)	;ACCESS DATE
	PUSHJ	P,PUTWDU##	;STORE IT IN THE USER'S AREA
	HRRI	M,UUXSIZ-UUXEXT(M)	;POINT TO LENGTH WORD
	SKIPE	T1,ACCWRT##(T2)	;LENGTH
	SUBI	T1,1		;LAST BLOCK WILL BE COUNTED SEPERATELY
	LSH	T1,BLKLSH##	;CONVERT TO WORDS
	LDB	T4,ACZLBS##	;NUMBER OF WORDS IN LAST BLOCK
	ADD	T1,T4		;=TOTAL NUMBER OF WORDS IN FILE
	CAILE	P1,UUXPRV	;WANT LENGTH IN DIRECTORY BLOCK?
	PUSHJ	P,PUTWDU##	;YES. SAVE IT
	HRRI	M,UUXPPN-UUXSIZ(M) ;BACK TO PPN
	CAILE	P1,UUXSIZ	;NEED MORE VALUES?
	JRST	FOUND4		;YES. GO READ RIB
;HERE TO FINISH UP A LOOKUP IF THE RIB DOESN'T HAVE TO BE READ
;HERE WITH M AT PPN
FOUND3:	TLZ	S,IO		;INDICATE READING
	PUSHJ	P,AT2DDB##	;SET DEVREL, ETC FROM A.T. DATA
	  JRST	LKRIB		;ACCESS TABLE DATA IS BADLY FOULED UP!
	JRST	LKXIT		;GIVE UP MON BUF AND GOOD RETURN


;HERE WHEN USER WANTS MORE VALUES THAN ARE STORED IN ACCESS TABLE
;READ RIB (IF IT ISN'T ALREADY IN CORE)
FOUND4:	PUSH	P,M		;SAVE ADDR OF PPN
	HRRI	M,RIBVER##-RIBPPN##(M)
	TLNE	S,IOSRIB	;JOB HAVE RIB IN MONITOR BUFFER?
	JRST	FOUND5		;YES
	MOVE	T1,ACCUN1##(T3)	;UN1 WORD
	LDB	T2,UN1PTR##	;UNIT NUMBER
	PUSHJ	P,NEWUNI##	;SET U,DEVUNI
	  JRST	FOUND7		;BAD UNIT - MAKE DO WITH DATA FROM A.T.
	HRLM	U,DEVUNI##(F)	;SAVE AS RIB UNIT NO.
	PUSHJ	P,BUFRIB##	;GET MON BUF, READ RIB INTO IT
	  JRST	FOUND7		;RIB ERR - GIVE DATA FROM A.T.

;HERE WITH FILE RIB IN CORE
FOUND5:	HRRZ	T2,.USMBF	;LOC OF MONITOR BUF
	HRRZ	T1,RIBFIR##+1(T2);NO OF VALUES IN RIB
	HRRZ	P2,P1		;NUMBER OF ARGS USER WANTS
	CAIL	P2,UUXACT	;WANT ACCOUNT STRING?
	CAIGE	T1,UUXACT	;YES, IS THERE ONE IN THE RIB?
	JRST	FND5A		;NO
	SUBI	P2,UUXACT	;YES, NO. OF ACCOUNT STRING WORDS HE WANTS
	CAILE	P2,MAXACS##	;WANT MORE THAN THERE POSSIBLY ARE?
	MOVEI	P2,MAXACS##	;YES, GIVE HIM THE MAX
	MOVNS	P2		;P2 NEGATIVE NUMBER OF ARGS TO STORE
	MOVE	T3,RIBACT##+1(T2);AOBJN WORD FOR ACCT STRING
	ADDI	T3,1(T2)	;RELOCATE IT
	MOVEI	P1,UUXACT-1	;ONLY STORE UP TO ACCT STRING IN 1ST LOOP
FND5A:	CAILE	P1,-1(T1)	;USER WANT TOO MANY?
	MOVEI	P1,-1(T1)	;YES, SETTLE FOR EVERYTHING
	MOVE	T1,UNILOG##(U)	;(ALIAS) NAME OF UNIT
	MOVEM	T1,RIBDEV##+1(T2);STORE IN RIB IN CASE USER WANTS IT
	PUSHJ	P,FIXUSD	;FIX RIBUSD
	ADDI	T2,RIBVER##+1	;SET TO LOC OF RIBVER
	MOVNI	P1,-UUXSIZ(P1)	;WE ALREADY STORED UUXSIZ VALUES,
	HRLI	T2,(P1)		; SO SET AOBJN WORD FOR VALUES -UUXSIZ
FOUND6:	MOVE	T1,(T2)		;GET A NUMBER FROM RIB
	PUSHJ	P,PUTWDU##	;SAVE IN DIRECTORY BLOCK FOR USER
	HRRI	M,1(M)		;POINT TO NEXT WORD
	AOBJN	T2,FOUND6	;AND CONTINUE IF MORE WANTED
	JUMPGE	P2,FND6C	;GO IF NO ACCOUNT STUFF TO STORE
FND6A:	SKIPA	T1,(T3)		;GET AN ACCOUNT-STRING WORD
FND6B:	SETZ	T1,		;NO MORE IN RIB, RETURN A 0
	PUSHJ	P,PUTWDU##	;TELL THE USER
	HRRI	M,1(M)
	AOJGE	P2,FND6C	;GO IF ALL STORED
	AOBJN	T3,FND6A	;GET ANOTHER VALUE IF MORE IN RIB
	JRST	FND6B		;NO MORE IN RIB, STORE A 0
FND6C:	POP	P,M		;RESTORE ADDR OF PPN
	PUSHJ	P,CPYFST##	;COPY POINTERS TO DDB, SET DEVBLK,ETC
	  JRST	LKRIB		;RIB IS BADLY FOULED UP
;HERE WHEN LOOKUP ALL THROUGH
LKXIT:	PUSHJ	P,DECMST	;DECREMENT ALL SFD AT'S EXCEPT THE RIGHT ONE
	SETZM	DEVFLR##(F)	;1ST POINTER INDDB IS FOR BLOCK 0
	HRRZ	U,DEVUNI##(F)	;LOC OF UNIT DATA BLOCK
	HRRM	U,DEVFUN##(F)	;=UNIT OF 1ST POINTER IN DDB
	SETZM	DEVRIB##(F)	;CLEAR POINTER TO CURRENT RIB
	LDB	T2,UNYLUN##	;GET CURRENT LOGICAL UNIT NUMBER
	DPB	T2,DEYRBU##	;STORE IN DEVRIB
	MOVE	T3,UNISTR##(U)	;GET SDB ADDRESS FOR CURRENT RIB
	MOVE	T2,DEVACC##(F)	;GET ADDRESS OF A.T.
	MOVE	T2,ACCPT1##(T2)	;GET FIRST RETRIEVAL POINTER
	LDB	T2,STYCLP##(T3)	;PICK OUT CLUSTER ADDRESS
	DPB	T2,DEYRBA##	;STORE IN DEVRIB
	TLZ	S,IOSRIB	;RIB IS NO LONGER IN MON BUFFER
	MOVEM	S,DEVIOS(F)
	PJRST	CPOPJ1##	;AND TAKE GOOD RETURN

;HERE WHEN CANNOT READ RIB - GIVE USER DATA FROM A.T.
FOUND7:	HRRZ	T3,DEVACC##(F)	;LOC OF A.T.
	POP	P,M		;RESTORE ADDR OF PPN
	JRST	FOUND3		;GO GET A.T. STUFF


;HERE IF THE DATA IN THE RIB IS BADLY FOULED UP, BUT RIBCHK PASSED IT
;DON'T ATTEMPT TO DECREMENT THE USE COUNT ON THE FILE ITSELF,
;THE ACC IS PROBABLY CLOBBERED.
;OK TO DECREMENT THE SFD
LKRIB:	MOVEI	T1,TRNERR	;ERROR CODE
	PJRST	LKENR4		;GO GIVE AN ERROR RETURN
SUBTTL	ENTER

UENTR:	PUSHJ	P,NULTST	;ON DEVICE NUL,
	  PJRST	CPOPJ1##	; ENTER WINS
IFN FTSPL,<
	SKIPL	DEVSPL(F)	;SPOOLING DEVICE?
	JRST	UENT3		;NO
	PUSH	P,M		;SAVE M
	PUSHJ	P,GETWDU##	;YES, GET NAME OR ADDRESS USER IS ENTERING
	MOVE	T2,T1		;SAVE INCASE IYB
	TLNE	T1,-1		;FILENAME OR ADDRESS
	  JRST	UENT2		;FILENAME
	HRRI	M,UUXNUM(M)	;POINT M TO LENGTH IN ENTER BLOCK
	PUSHJ	P,GETWDU##	;GET LENGTH OF ENTER BLOCK
	HRRI	M,<UUXNAM-UUXNUM>(M) ;ASSUME FILENAME FOR SPOOLED NAME
	CAIGE	T1,<UUXFUT-UUXNUM> ;IS THE BLOCK LONG ENOUGH TO
				; INCLUDE A SPOOLED NAME?
	  JRST	UENT1		;NO, USER FILENAME
	HRRI	M,<UUXFUT-UUXNAM>(M) ;POINT M TO SPOOLED NAME IN
				; THE ENTER BLOCK
	PUSHJ	P,GETWDU##	;GET THE SPOOLED NAME
	JUMPN	T1,UENT2	;IF ZERO NAME USER FILENAME
	HRRI	M,<UUXNAM-UUXFUT>(M) ;ZERO SPOOLED NAME, SO USER FILENAME
UENT1:	PUSHJ	P,GETWDU##	;GET FILENAME FOR SPOOL NAME
UENT2:	MOVEM	T1,DEVSPN##(F)	;SAVE TEMPORARILY IN DDB
	SETZM	DEVPPN(F)
	POP	P,M		;RESTORE M
	MOVSI	T1,(UP.IYB)	;IN-YOUR-BEHALF BIT
	TLNN	T2,-1		;EXTENDED ENTER?
	TDNN	T1,.USBTS	;IS THAT WHAT WE'RE DOING?
	PJRST	CPOPJ1##	;NO--JUST RETURN
	ANDI	T2,<-1-RB.BIT>	;KEEP ONLY THE WORD COUNT
	CAIGE	T2,UUXACT	;ACCT STRING SPECIFIED?
	JRST	CPOPJ1##	;NOPE
	MOVEI	T3,ACTSTL##	;GET ACCT STRING LENGTH AS DEFINED IN COMMON
	JUMPE	T3,CPOPJ1##	;RETURN IF ZERO
	SUBI	T2,UUXACT	;COMPUTE LENGTH OF
	CAILE	T2,(T3)		; SPECIFIED STRING
	MOVEI	T2,(T3)		;  IN THE ENTER BLOCK
	MOVNS	T2		;NEGATE
	HRLZS	T2		;MAKE IT -LEN,,0
	PUSH	P,T2		;AND SAVE COUNT
	PUSHJ	P,SETSPB	;SET UP SPB
	  JRST	CPOPJ1##	;NO FREE CORE
	HRRI	M,UUXACT-1(M)	;POINT TO ACCT STRING IN ENTER BLOCK
	POP	P,T2		;GET -LEN,,0
	HRRI	T2,SPBACT##(T1)	;POINT TO ACCT STRING IN SPB
UENT3A:	PUSHJ	P,GETWD1##	;GET A WORD
	MOVEM	T1,(T2)		;PUT A WORD
	AOBJN	T2,UENT3A	;LOOP
	JRST	CPOPJ1##	;AND RETURN
UENT3:
>	;END CONDITIONAL ON FTSPL
	TLNE	F,LOOKB		;LOOKUP IN FORCE?
	JRST	UPDATE		;YES. UPDATE
;HERE FOR AN ENTER WHICH IS A CREATE OR SUPERSEDE
UENT4:	SETZM	DEVSFD##(F)
	PUSHJ	P,SAVE4##	;SAVE ACS (SETLER RETURNS STUFF IN P3,P4)
	MOVE	J,.CPJOB##
	PUSH	P,JBTSFD##(J)	;SAVE JBTSFD
	MOVSI	T1,JBPXSY##
	ANDCAM	T1,JBTSFD##(J)	;MAKE SURE NEW: ISN'T WRITTEN
	MOVSI	T1,DEPLIB##
	ANDCAM	T1,DEVLIB##(F)	;IN CASE OF LOOKUP FAILURE FIRST
	SETZM	DEVLNM##(F)	;START WITH NO LOGICAL NAME
	PUSHJ	P,SETLER	;NO. SET UUO FOR ENTER
	  JRST	ILNMEN		;BAD NAME - ERROR
	MOVE	J,.CPJOB##
	POP	P,JBTSFD##(J)
	TLNN	M,UUODIR	;TRYING TO ENTER A DIRECTORY?
	JRST	UENT5		;NO
	PUSHJ	P,CNTLVL	;YES, GET SFD LEVEL
	CAMGE	T1,SFDLVL##	;ALREADY AT LIMIT?
	JRST	UENT5		;BELOW LIMIT
	MOVEI	T1,LVLERR	;ABOVE, GIVE HIM ERROR
	JRST	LKENR4
UENT5:
;HERE IF NOT TRYING TO ENTER A DIRECTORY
UENT6:	SKIPN	T1,DEVLNM##(F)	;LOGICAL NAME SPEC?
	JRST	UENT11		;NO
	TLO	M,UUOLUK	;NO, SEE IF FILE EXISTS HERE
UENT7:	JUMPGE	P4,UENT8	;/OVERRIDE?
	MOVE	T1,DEVLNM##(F)	;YES. GET SPEC
	HRLZ	T2,P4		;IS NAME.EXT FROM LOOKUP/ENTER BLOCK
	CAMN	P3,LNRNAM##(T1)	; THE SAME AS THE PATHOLOGICAL NAME SPEC?
	CAME	T2,LNREXT##(T1)
	JRST	UENT9		;NO, STEP TO NEXT SPEC
UENT8:	PUSHJ	P,SETSRC##
	  JRST	UENT9		;UNIT NOT THERE
	MOVE	T2,T1
	PUSHJ	P,FNDFIL##	;DOES FILE EXIST HERE?
	  JRST	UENT99		;NO
	PUSH	P,P2		;YES, SET UP P2 FOR DECUC
	PUSHJ	P,DECSU
	PUSHJ	P,DECRDR	;DECREMENT ACC
	  PUSHJ	P,GVCBJ1##	;%OTHER READERS, GIVE UP CB
	PUSHJ	P,TSTAMD##	;%LAST READER, FILE MARKED FOR DELETION?
	  CAIA			;YES
	PUSHJ	P,ATSDRA##	;%NO, MAKE ACC DORMANT
	PUSHJ	P,DECUC		;DECREMENT PPB+NMB
	POP	P,P2		;RESTORE P2
	JRST	UENT10		;USE THIS STR
UENT99:	CAIN	T1,PRTERR	;PROTECTION FAILURE?
	JRST	UENT10		;YES, THIS STR WILL FAIL
UENT9:	PUSHJ	P,SFDDEC	;CLEAR ANY SFD STUFF WE SET UP
	PUSHJ	P,DECSFD
	SETZM	DEVSFD##(F)
	PUSHJ	P,NXTSPC	;STEP TO NEXT SPEC
	  JRST	UENT7		;SEE IF FILE EXISTS THERE
	MOVE	T1,DEVNAM(F)	;NO FILE TO SUPERSEDE - GO BACK TO START
	PUSHJ	P,SDVTST
	  PUSHJ	P,LNMSTP	;WHAT? IT USED TO BE A LOG NAME
	MOVE	T1,@.USLNM	;GO TO 1ST PART OF SPEC
	ADDI	T1,LNMDEV##-LNRDEV##
	HRRZM	T1,DEVLNM##(F)
	PUSHJ	P,NXTSP3
	  CAIA
	PUSHJ	P,LNMSTP	;WHAT? IT USED TO BE THERE

;HERE WITTH DDB SET UP TO THE PPN/SFD WE WANT TO CREATE/SUPERSEDE IN
UENT10:	TLZ	M,UUOLUK	;NOT A LOOKUP ANY MORE
UENT11:	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST
	  SKIPA	T1,DEVLNM##(F)	;LOG NAME?
	JRST	UENT12
	JUMPE	T1,CPOPJ##	;NO, LOSE
	PUSHJ	P,NXTSPC	;YES, GET NEXT PART
	  JRST	UENT11		;SEE IF DEVICE EXISTS
	POPJ	P,
UENT12:	MOVE	T2,T1		;SEARCH LIST INTO T2
	TLZ	S,IOSWLK	;MAKE SURE IOSWLK IS OFF
	MOVEM	S,DEVIOS(F)	; (COULD BE ON FROM PREVIOUS LOOKUP)
	PUSHJ	P,FNDFIL##	;SEARCH FOR MATCH, SET A.T.
	  JRST	LKENR4		;ERROR
	HLRZ	T1,DEVEXT(F)	;GET EXTENSION
	MOVE	T2,DEVPPN(F)	; AND PPN
	CAIN	T1,'UFD'	;TRYING TO CREATE A UFD ?
	CAMN	T2,MFDPPN##	;YES. IN THE MFD ?
	SKIPA	T2,DEVACC##(F)	;YES, GET LOC OF A.T.
	JRST	NTFOUN		;NO, ERROR
	HRRZ	P1,ACCSTS##(T2)
	TRNE	P1,ACPSUP	;SUPERSEDING
	TRNN	P1,ACPPAL##	; A PRE-ALLOCATED FILE?
	CAIA			;NO
	JRST	SETE19		;YES, FINISH UP
	TLNE	S,IOSWLK	;FILE (STR) WRITE LOCKED?
	JRST	ENER12		;YES. ERROR
	HRRZ	P2,U		;REMEMBER UNIT WE OWN DA FOR
	PUSHJ	P,DDBZR		;ZERO THE DDB POINTERS
	MOVSI	T4,MRIBLN##+1	;SET UP DEVRSU(COUNT 1 FOR 1ST UNIT)
	HLLM	T4,DEVRSU##(F)
	SETZM	ACCALC##(T2)	;INSURE THAT THE ALLOCATION WORD IS 0
	LDB	T4,ACYFSN##	;T4 = FSN
	MOVE	P1,TABSTR##(T4)	;LOC OF STR DATA BLOCK INTO P1
	SETO	T2,		;SET MASK=-1 (COMPARE WHOLE NAME)
	MOVE	T1,DEVNAM(F)	;NAME USER INITED
	PUSHJ	P,UNSER0##	;LOOK FOR MATCHING UNINAM
	  JRST	UNILUP		;NO MATCH - PICK BEST UNIT
	SKIPLE	UNITAL##(T3)	;HE WANTS PARTICULAR UNIT - ANY ROOM?
	JRST	USEUNI		;YES. USE REQUESTED UNIT
;HERE WHEN A PARTICULAR UNIT WAS NOT SPECIFIED - FIND THE MOST EMPTY
; UNIT IN THE STR WITH NO OPEN FILES TO START THE FILE ON
UNILUP:	SETZB	T1,T4		;T4 WILL  CONTAIN BEST UNITAL
UNILP0:	HLR	T3,STRUNI##(P1)	;FIRST UNIT IN STR
	PUSH	P,P1		;SAVE P1
UNILP1:	CAML	T4,UNITAL##(T3)	;IS THIS THE BEST UNIT SO FAR?
	JRST	UNILP5		;NO. TRY NEXT
	MOVSI	T2,DEPNLB##
	TDNN	T2,DEVNLB##(F)	;DID USER ASK FOR ANY UNIT?
	TLNE	T3,-1		;YES. AVOIDING UNITS WITH OPEN FILES?
	JRST	UNILP4		;NO, USE THIS UNIT
	SKIPL	T2,USRHCU##	;YES. NO OF CHANS USER HAS OPEN
	SETZ	P1,
UNILP2:	PUSHJ	P,NXTCH##
	  JRST	UNILP4
	MOVSI	T2,DVDSK
	TDNE	T2,DEVMOD(T1)
	CAIN	T1,(F)
	JRST	UNILP2
	HLRZ	T2,DEVEXT(T1)	;YES. FILE'S EXTENSION
	PUSHJ	P,EXTCK		;IS IT A DIR?
	JRST	UNILP2		;YES. PUTTING DATA FILE ON SAME UNIT IS OK
	HLRZ	T2,DEVUNI##(T1)	;UNIT OF THE FILE
	CAIN	T2,(T3)		;IS IT THIS UNIT?
	JRST	UNILP5		;YES. DON'T WANT TO WRITE THE FILE ON THIS UNIT
	JRST	UNILP2		;TEST NEXT USER CHAN
UNILP4:	MOVE	T4,UNITAL##(T3)	;THIS IS THE BEST SO FAR. SAVE ITS TALLY
	HRRZ	U,T3		;SAVE LOC OF UNIT DATA BLOCK
UNILP5:	HLR	T3,UNISTR##(T3)	;STEP TO NEXT UNIT IN STR
	MOVE	S,DEVIOS(F)
	TRNE	T3,-1		;IS THERE ONE?
	JRST	UNILP1		;YES. TEST IT
	POP	P,P1		;RESTORE P1
	JUMPN	T4,USEUN1	;FOUND A UNIT WITH FREE BLOCKS IF T4 NON 0
	TLON	T3,-1		;INDICATE ANY UNIT WILL DO
	JRST	UNILP0		;GO FIND ANY UNIT WITH FREE BLOCKS
	JRST	UENT6		;NONE FREE, TRY AGAIN
USEUNI:	MOVE	U,T3		;SET U TO USER SPECIFIED UNIT
;HERE WHEN U IS SET UP (IT MAY BE CHANGED BY NON-0 E+11)
USEUN1:	PUSHJ	P,STOAU##	;SAVE LOC OF UNIT DB IN DDB
	PUSHJ	P,UPDA##	;AND GET IT FOR NEW UNIT
	SKIPLE	UNITAL##(U)	;ANY SPACE ON UNIT?
	JRST	USEU1A		;YES, PUSH ON
	PUSHJ	P,DWNDA##	;NO, SOME OTHER JOB SNUCK IN AND GRABBED IT
	MOVE	T1,UNISTR##(U)
	SKIPLE	STRTAL##(T1)	;IS THERE SPACE ANYWHERE ON STR?
	JRST	UNILUP		;YES, GO FIND ANOTHER UNIT TO WRITE ON
	JRST	UENT6		;NO, CALL FILFND AGAIN
USEU1A:	MOVEI	T3,DEVRB2##(F)	;SET DEVRET TO DEVRB2 (1ST REAL PNTR)
	HRRM	T3,DEVRET##(F)
	HRRZ	J,UNIKON##(U)	;LOC OF KONTROLLER DB
	HRRZ	P2,DEVACC##(F)	;SET P2 AND P3 POINTING
	HRRI	M,-1(M)
	TLNN	M,EXTUUO	;EXTENDED ENTER?
	JRST	CREAL4		;NO. POINT TO PRIVS WORD
	PUSHJ	P,GETWDU##	;GET NUMBER OF ARGUMENTS(VALUES)
	TRZ	T1,RB.BIT	;CLEAR NO-SUPERSEDE BIT
	HRRZ	P1,T1
	CAILE	P1,RIBENT##	;ASKING FOR TOO MANY?
	MOVEI	P1,RIBENT##	;YES. TAKE SMALLER AMOUNT
	HRRI	M,UUXALC(M)	;POINT TO (ALLOCATION WORD)
	CAIL	P1,UUXALC
	PUSHJ	P,GETWDU##
	CAIL	P1,UUXALC	;MAY HE BE SPECIFYING ALLOCATION?
	SKIPG	T2,T1		;YES. PICK UP AMOUNT
	CAIA			;NO, ESTIMATED LENGTH GIVEN?
	JRST	USEUN2		;YES, USE IT
	HRRI	M,-1(M)
	CAIL	P1,UUXEST
	PUSHJ	P,GETWDU##
	HRRI	M,1(M)
	CAIL	P1,UUXEST
	SKIPG	T2,T1		;GET ESTIMATED ALLOCATION
	HLRZ	T2,UNIGRP##(U)	;NO ESTIMATED, USE UNIGRP
	CAIA
USEUN2:	TLO	M,UALASK	;INDICATE ASKING FOR A SPECIFIC AMOUNT

	HRRZ	T4,DEVUFB##(F)	;LOC OF UFB
	CAMG	T2,UFBTAL##(T4)	;ASKING FOR MORE THAN QUOTA ALLOWS?
	JRST	CREAL1		;NO. OK
	SKIPG	T2,UFBTAL##(T4)	;YES. ANY LEFT AT ALL?
	HLRZ	T2,UNIGRP##(U)	;NO - TAKE UNIGRP BLOCKS
				;(WE DON'T CHECK QUOTAS ON SUPERSEDE IN A F/S)
	TLNE	M,UALASK
	TLO	M,UPARAL	;YES. REMEMBER FOR PARTIAL ALLOC. ERROR
;HERE WITH T2=SPACE WE WOULD LIKE TO GET
CREAL1:	HRRI	M,1(M)		;POINT TO START ADDRESS WORD
	PUSH	P,T2		;SAVE T2
	HRRZ	P3,U		;SAVE THIS UNIT
	PUSHJ	P,ALSTRT	;SET T1 FOR POSSIBLE START-ADR. SPECIFICATION
	  JRST	ENERR3		;CANT START AT SPECIFIED BLOCK (ADR. TOO HIGH)
	CAIN	P3,(U)		;DID WE STAY ON THE SAME UNIT ?
	JRST	CREAL2		;YES
	EXCH	U,P3		;NO, RETURN DA FOR FIRST UNIT
	PUSHJ	P,DWNDA##
	MOVE	U,P3		;POINT AT NEW UNIT
	PUSHJ	P,UPDA##	;GET THE DA FOR THAT ONE
CREAL2:
;HERE WITH T1=START ADR (OR 0), T2=NUMBER OF BLOCKS REQUESTED
	PUSHJ	P,ENTALC	;ALLOCATE SPACE
	  JRST	ENERR4		;CANT START AT SPECIFED BLOCK
	MOVE	T1,ACCALC##(P2)	;AMOUNT OF SPACE ALLOCATED
	CAIL	P1,UUXALC	;IF USER WANTS TO KNOW,
	PUSHJ	P,PUTWDU##	; TELL HIM AMOUNT ALLOCATED
	JRST	CREAL5		;ALLOCATION COMPLETE - CONTINUE
;HERE FOR ALLOCATION ON A 4-WORD ENTER
CREAL4:	HLRZ	T2,UNIGRP##(U)	;NUMBER OF BLOCKS TO GET
	SETZ	T1,		;GET THEM ANYWHERE
	PUSHJ	P,ADJALC	;GET SOME SPACE
	  JRST	ENERR2		;NO ROOM -ERROR
	MOVEM	T2,DEVRB2##(F)	;SAVE THE POINTER
	MOVEM	T1,ACCALC##(P2)	;SAVE NUMBER OF BLOCKS ALLOCATED
	MOVEI	P1,UUXPRV	;SET P1 SO PRIVS WORD WILL BE STORED
	AOSA	DEVRET##(F)	;SET DEVRET TO DEVRB2+1

;HERE WHEN ALL ALOCATION IS DONE
CREAL5:	POP	P,T2		;REMOVE GARBAGE FROM PD LIST
	HRLM	U,DEVUNI##(F)	;SAVE  UNIT OF RIB
	PUSHJ	P,DECMST	;DECR ALL A.T. USE COUNTS
				; EXCEPT THE ONE FOR THIS STR
	LDB	T4,UNYLUN##	;LOGICAL UNIT NUMBER
	TRO	T4,RIPNUB##	;MAKE SURE NON-0
	MOVEM	T4,DEVRB1##(F)	;SAVE IN THE DDB
	SETZ	T1,		;WILL SET UP T1
	DPB	T4,UN1PTR##	;SAVE UN1 IN T1
	MOVE	T2,DEVRB2##(F)	;1ST REAL POINTER
	SKIPN	DEVRB2##+1(F)	;ONLY POINTER?
	TRO	T1,ACP1PT##	;YES. LIGHT 1PT BIT
	SETZM	ACCWRT##(P2)	;INDICATE 0 BLOCKS WRITTEN
	HRRM	T1,ACCUN1##(P2)	;SAVE UN1 WORD IN A.T.
	MOVEM	T2,ACCPT1##(P2)	;SAVE 1ST PNTR IN A.T.
	MOVEI	T2,ACPNCK##	; FILE A DIRECTORY, PLUS ALWAYS BAD CHECKSUM
				;(SINCE OTHERWISE EARLIER MONITORS WILL COMPLAIN)
	TLNE	M,UUODIR	;IS IT A DIRECTORY?
	ORM	T2,ACCDIR##(P2)	;YES. SET BITS IN ACC
	TLNE	M,EXTUUO	;EXTENDED ENTER?
	HRRI	M,-<UUXALC-UUXPRV>(M)	;YES. POINT TO PROTECTION WORD
	CAIGE	P1,UUXPRV	;USER SPECIFYING DATE?
	TDZA	T1,T1		;NO, USE NOW
	PUSHJ	P,GETWDU##	;YES, GET TIME,DATE,PROTECTION WORD
	HRLM	T1,P2
	TRNE	T1,-1		;TIME DATE GIVEN?
	JRST	SETEN1		;YES
	MOVE	T2,TIME##	;NO. TIME, DATE =NOW
	IDIV	T2,TICMIN##
	HRR	T1,THSDAT##	;TODAY'S DATE
	DPB	T2,[POINT 11,T1,23]	;STORE TIME IN T2
SETEN1:	MOVSI	T3,777000	;SET TO GET PROTECTION OF OLD FILE (IF ANY)
	AND	T3,ACCPRV##(P2)	;IF NON-0, THIS FILE IS SUPERSEDING
	JUMPN	T3,SETEN4	;DEFAULT PROT=OLD FILE'S PROT IF SUPERSEDE
	MOVE	T3,UFDPRT##	;STANDARD DIRECTORY PROTECTION
	TLNE	M,UUODIR	;A DIRECTORY ?
	JRST	SETEN4		;YES
	LDB	J,PJOBN##	;J WAS WIPED IF I/O WAS DONE
	PUSHJ	P,FNDPDS##	;DEFAULT PROTECTION WAS SPECIFIED BIT
IFN FTFDAE,<
	MOVSI	T2,(PD.FSP)	;FILE DAEMON SPECIFIED PROT BIT
	TDNN	T2,.PDDFL##(W)	;DID THE FILE DAEMON SPECIFY PROT?
	JRST	SETEN2		;NO
	ANDCAM	T2,.PDDFL##(W)	;YES, CLEAR THE BIT
	MOVEI	T3,777000	;GET PROTECTION
	AND	T3,.PDDFL##(W)
	MOVSS	T3		;POSITION TO CORRECT FIELD
	TLZ	T1,777000	;IGNORE WHAT ENTER SAID
	JRST	SETEN4		;SET PROTECTION FIELD
SETEN2:>
	TLNN	F,SYSDEV	;IS DEVICE = SYS?
	JRST	SETEN3		;NO
	HLRZ	T3,DEVEXT(F)	;YES, PROT = <155>
	CAIN	T3,'SYS'	; EXCEPT FOR .SYS FILES
	SKIPA	T3,SYSPRY##	; WHICH ARE <157>
	MOVE	T3,SYSPRT##
	JRST	SETEN4
SETEN3:	MOVSI	T2,(PD.DPS)	;DEFAULT PROTECTION SET BIT
	MOVSI	T3,777000	;MASK TO EXTRACT DEFAULT PROTECTION FROM THE PDB
	TDNN	T2,.PDDFL##(W)	;HAS A DEFAULT PROTECTION BEEN SPECIFIED
	SKIPA	T3,STNPRT##	;NO, USE SYSTEM DEFAULT
	AND	T3,.PDDFL##(W)	;YES, GET USER SPECIFIED DEFAULT

SETEN4:	TLNN	T1,777000	;PROTECTION  ALREADY GIVEN?
	OR	T1,T3		;NO, SET STANDARD PROTECTION
	DPB	S,[POINT 4,T1,12] ;MODE
	PUSH	P,T1		;PROT, MODE, LO CRE-DATE
	HRRI	M,-<UUXPRV-UUXEXT>(M)
	PUSHJ	P,GETWDU##	;ACCESS DATE, HI CRE-DATE
IFN FTSPL,<
	SKIPGE	DEVSPL(F)
	HRRI	T1,0		;RH(E+1) IS A COUNT IF SPOOLED
>
	LDB	T2,[POINT 15,T1,35]
	SKIPE	T2		;IF NO ACCESS DATE GIVEN
	CAMLE	T2,THSDAT##	;OR IF GREATER THAN TODAY
	MOVE	T2,THSDAT##	;USE TODAY'S DATE
	DPB	T2,[POINT 15,T1,35] ;SAVE IN USERS AREA
	LDB	T4,[POINT 3,T1,20] ;HIGH PART OF CREATION DATE
	LDB	T3,[POINT 12,P2,17] ;USER-SUPPLIED LOW PART OF CREATION DATE
	DPB	T4,[POINT 3,T3,23]
	SKIPE	T3
	CAMLE	T3,THSDAT##
	MOVE	T3,THSDAT##	;NO CREATION DATE, OR DATE TOO HIGH
	SUB	T2,T3		;ACC DATE - CREATION DATE
	SKIPGE	T2		;IF ACC DATE TOO LOW,
	SUB	T1,T2		; CHANGE IT TO = CREATION DATE
	DPB	T3,[POINT 12,(P),35] ;SAVE LOW CREATION DATE
	LSH	T3,-14
	DPB	T3,[POINT 3,T1,20] ;SAVE HIGH CREATION DATE
	PUSHJ	P,PUTWDU##
	EXCH	T1,(P)
	HRRI	M,UUXPRV-UUXEXT(M)
	CAIL	P1,4		;SAVE PRIVS, LOW CRE-DATE IN USERS AREA
	PUSHJ	P,PUTWDU##	; IF HE ASKED FOR IT
	SETZ	T2,
	XOR	T1,ACCPRV##(P2)	;GET BITS WHICH ARE BEING CHANGED
	TLNE	T1,777000	;CHANGING PROTECTION?
	DPB	T2,DEYFNC##	;YES, FORCE RECOMPUTE OF PRIV'S
	XORB	T1,ACCPRV##(P2)	;STORE NEW VALUE IN ACC
	PUSHJ	P,GTMNBF##	;GET THE MONITOR BUFFER
	MOVE	T2,T1
	HRLI	T1,1(T2)	;SET TO ZERO THE ENTIRE BUFFER
	HRRI	T1,2(T2)
	SETZM	1(T2)
	BLT	T1,200(T2)	;ZERO IT
	MOVE	T3,UNILOG##(U)	;NAME OF FIRST UNIT FOR FILE
	MOVEM	T3,RIBDEV##+1(T2)	;SAVE IN RIB
	TLNN	M,EXTUUO	;EXTENDED UUO?
	AOJA	T2,SETEN5	;NO
	HRRI	M,-<UUXPRV-UUXEXT>(M)	;POINT TO ACCESS DATE WORD
	MOVEM	M,(P)		;WIPE OUT DATE, SAVE M ON LIST
	MOVE	T1,DEVPPN(F)	;PPN
	MOVEM	T1,RIBPPN##+1(T2)	;SAVE IN RIB
	HRRI	M,-<UUXEXT-UUXNAM>(M)	;POINT TO NAM WORD
	HRLI	T2,-UUXEXT+1	;SET TO SAVE FIRST FEW VALUES
	PUSHJ	P,GTWST2##	;GET A VALUE
	MOVEM	T1,RIBNAM##+1(T2)	;SAVE IN RIB
	HRRI	M,1(M)		;POINT TO NEXT VALUE
	AOBJN	T2,.-3		;GO GET IT
	PUSHJ	P,SETVAN	;STORE USER-ARGS IN RIB
	POP	P,M
	JRST	SETEN6		;AND CONTINUE
;HERE TO SET UP RIB BLOCK FROM A 4-WORD ENTER
SETEN5:	PUSHJ	P,GTWST2##	;DATE, PROT WORD
	MOVEM	T1,RIBATT##(T2)	;SAVE IN RIB
	POP	P,T1		;GET EXT, DATE
	MOVEM	T1,RIBEXT##(T2)	;SAVE IN RIB
	HRRI	M,-<UUNATT-UUNNAM>(M)	;POINT TO E
	PUSHJ	P,GTWST2##	;GET NAME
	MOVEM	T1,RIBNAM##(T2)	;INTO RIB
	HRRI	M,UUNPPN-UUNNAM(M)	;POINT TO PPN WORD
	MOVE	T1,DEVPPN(F)	;PRJ,PRG NUMBER
	MOVEM	T1,RIBPPN##(T2)	;INTO RIB
IFN FTSPL,<
	MOVE	T1,DEVSPN##(F)
	SKIPGE	DEVSPL(F)
	MOVEM	T1,RIBSPL##(T2)	;SAVE (POSSIBLE) NAME ENTERED ON A SPOOL-ENTER
>
	MOVE	T1,.JDAT+.JBVER## ;GET BERSION NUMBER
	SKIPGE	USRHCU##	;IN SAVE COMMAND?
	MOVEM	T1,RIBVER##(T2)	;YES--SAVE VERSION IN RIB



;HERE WHEN THE RIB BLOCK IS SET UP. INSERT CONSTANT VALUES, WRITE IT
SETEN6:	PUSHJ	P,RIBAD##	;COMPUTE ADR. OF RIB
	MOVE	T1,.USMBF	;LOC OF RIB(-1)
	MOVEM	T2,RIBSLF##+1(T1) ;SAVE ADR AS LAST WORD OF RIB
	SETZM	RIBSIZ##+1(T1)	;NUMBER OF WORDS WRITTEN=0
	MOVE	T2,DEVFIL(F)	;SINCE WE MIGHT DEFAULT NAME, EXT
	MOVEM	T2,RIBNAM##+1(T1) ; SET THEM UP FROM THE DDB, WHICH IS RIGHT
	MOVE	T2,DEVEXT(F)
	HLLM	T2,RIBEXT##+1(T1)
	SKIPE	RIBAUT##+1(T1)	;IF NO PRJ,PRG GIVEN
	JRST	SETEN8
	LDB	T3,PJOBN##	;JOB NUMBER
	MOVE	T3,JBTPPN##(T3)	;AUTHORS PRJ,PRG NUMBER
	MOVE	T4,DEVPPN(F)	;DIRECTORY OF FILE
	CAMN	T3,FFAPPN##	;IF AUTHOR IS [1,2]
	CAMN	T4,SPLPPN##	; UNLESS WRITING IN [3,3]
	JRST	SETEN7
	SKIPN	T3,DEVUPP##(F)	;USE IN-YOUR-BEHALF IF THERE
	MOVE	T3,T4		;MAKE AUTHOR = DIRECTORY OWNER
SETEN7:	MOVEM	T3,RIBAUT##+1(T1) ;STORE USERS PRJ,PRG
SETEN8:	MOVEI	T3,CODRIB##	;CODE WORD SHOWING THIS BLOCK IS A RIB
	MOVEM	T3,RIBCOD##+1(T1) ;SAVE IN RIB BLOCK
	MOVE	T2,[XWD MRIBLN##,RIBENT##+1]	;SET UP RIBFIR
	MOVEM	T2,RIBFIR##+1(T1)
	MOVE	T4,ACCALC##(P2)	;AMOUNT OF SPACE ALLOCATED
	MOVEM	T4,RIBALC##+1(T1) ;SAVE IN RIB
	MOVE	T4,ACCPRV##(P2)	;PRIVS, DATE
	MOVEM	T4,RIBPRV##+1(T1) ;SAVE IN RIB
	SETZM	RIBFLR##+1(T1)	;BLOCK 0 STARTS PRIME RIB
	MOVE	T4,RIBEXT##+1(T1) ;ACCESS DATE
	HRLM	T4,ACCADT##(P2)	;SAVE IN ACCESS TABLE
	MOVSI	T4,RIPLOG##	;INDICATE JOB NOT LOGGED OUT
	TLNE	M,UUODIR	;IF A DIRECTORY
	CAIL	P1,UUXSTS	; AND NOT SPECIFYING A STATUS
	SETZ	T4,		;NOT A DIR, OR STATUS GIVEN
	TLNE	M,UUODIR	;DIRECTORY FILE?
	TRO	T4,RIPNCK##	;YES. SET A BIT IN RIBSTS - RIPDIR+RIPABC
				; (RIPABC ELSE EARLIER MONITORS WILL COMPLAIN)
	ORM	T4,RIBSTS##+1(T1)
	MOVSI	T3,DEVRB1##(F)	;SET UP TO BLT POINTERS FROM DDB
	HRRI	T3,RIBENT##+2(T1)	; INTO RIB
	BLT	T3,RIBWN1##+1(T1) ;(THERE MAY BE PTRLEN POINTERS)
	HRRI	M,UUXALC-UUXEXT(M)	;POINT TO ESTIMATED LENGTH
	PUSHJ	P,CHKPAR	;STORE PAOERR IF NEEDED
	MOVE	P3,P1		;SAVE ARGUMENT COUNT
	HRRI	M,-<UUXALC-UUXEST>(M)
	CAIL	P1,UUXEST
	PUSHJ	P,GTWDT3
	CAIL	P1,UUXEST	;SPECIFYING ESTIMATED LENGTH?
	SKIPG	T3
	JRST	SETE14		;NO
	SUB	T3,RIBALC##+1(T1) ;YES. ALREADY HAVE THAT MUCH?
	JUMPLE	T3,SETE14	;YES IF NEGATIVE
	HRRZ	P1,DEVRET##(F)	;NO. GET MORE
	SUBI	P1,DEVRB1##(F)	;COMPUTE NUMBER OF POINTERS
	HRLS	P1
	PUSHJ	P,SPTRW##	;SET T1 TO AN AOBJN WORD FOR POINTERS
	ADD	P1,T1		;SET P1=AOBJN WORD FOR NEW POINTERS
	TLZ	F,OCLOSB	;SO TAKBLK WONT GIVE BLOCKS IF UNITAL LT 0
	MOVE	T2,T3		;NUMBER OF BLOCKS TO GET
	PUSHJ	P,CHKQTA##	;CHECK QUOTA
	SKIPG	P2,T2		;P2=AMOUNT WE CAN GET
	JRST	SETE13		;CANT GET ANY MORE - FORGET IT
;STILL IN FTDALC CONDITIONAL
SETEN9:	PUSHJ	P,SCDCHK##	;SEE IF SCHED WANTS TO RUN ANOTHER JOB
	PUSHJ	P,TAKCHK##	;GET AS LARGE A GROUP AS THERE IS
	  JRST	SETE11		;ON A NEW UNIT
SETE10:	MOVEM	T2,(P1)		;SAME UNIT - SAVE POINTER
	SUB	P2,T1		;SUBTRACT NUMBER OF BLOCKS OBTAINED
	JUMPLE	P2,SETE12	;DONE IF NO MORE TO GET
	MOVE	T2,P2		;NEW AMOUNT TO GET
	AOBJN	P1,SETEN9	;GO TRY AGAIN
	JRST	SETE12		;NO MORE POINTER SLOTS IN RIB - DONE
SETE11:	JUMPE	T3,SETE12	;STR FULL IF T3=0
	MOVEM	T3,(P1)		;SAVE UNIT-CHANGE IN RIB
	AOBJN	P1,SETE10	;STORE REAL POINTER IN RIB
	MOVEM	T2,-1(P1)	;NO ROOM - DELETE UNIT CHANGE, SET UP TO
	SUBI	P1,1		; GIVE BACK THE BLOCKS JUST OBTAINED
	PUSHJ	P,DELRIB	; SINCE ONLY 1 PNTR SLOT LEFT
	  STOPCD .+1,DEBUG,DNR,	;++DELRIB NON-SKIP RETURN
SETE12:	MOVE	P2,DEVACC##(F)
	TRZ	S,IOBKTL	;MAKE SURE IOBKTL OFF
	MOVE	T1,.USMBF	;LOC OF MONITOR BUFFER
	MOVEI	T3,ACP1PT##	;CLEAR THE 1PT BIT
	ANDCAM	T3,ACC1PT##(P2)	; IN THE A.T.
	MOVE	T3,ACCALC##(P2)	;NO OF BLOCKS ALLOCATED
	MOVEM	T3,RIBALC##+1(T1) ;SAVE IN RIB
	HRRI	M,UUXALC-UUXEST(M) ;POINT TO ALLOCATION WORD
	MOVE	T1,T3
	CAIL	P3,UUXALC	;IF .RBCNT .LE. .RBALC, DON'T RETURN .RBALC
	PUSHJ	P,PUTWDU##	;TELL USER THE FINAL RESULT
SETE13:	HRROI	P1,DEVRBN##(F)	;PREPARE TO SET DEVRET=DEVRBN
	HRRI	M,-<UUXALC-UUXEST>(M)	;POINT BACK AT EST LENGTH

SETE14:	PUSHJ	P,SETUFR	;SET RIBUFD IN RIB
	MOVE	T2,DATE##	;INTERNAL CREACTION TIME, DATE
	MOVEM	T2,RIBTIM##+1(T1); INTO RIB
	MOVE	T2,[XWD MACTSL##,RIBACS##]
	MOVEM	T2,RIBACT##+1(T1)	;STORE AOBJN POINTER TO ACCOUNT STRING
	JUMPGE	T2,SETE18	;GO IF 0-LENGTH ACCT STRING
	ADDI	T2,1(T1)	;AOBJN WORD FOR ACCT-STRING IN RIB
	PUSH	P,DEVUPP##(F)
	SETZM	DEVUPP##(F)	;ALLOW PRIVS HERE
	CAIL	P3,UUXACT	;IF NO STRING SPECIFIED,
	PUSHJ	P,PRVJB##	; OR IF NOT A PRIV'D JOB
	  JRST	SETE16		;GET STRING FROM PDB
	HRRI	M,UUXACT-UUXEST-1(M) ;POINT TO STRING DATA IN ENTER BLOCK
	SUBI	P3,UUXACT	;NO. OF ARGS TO GET
SETE15:	HRRI	M,1(M)		;ADVANCE TO NEXT ARGUMENT
	PUSHJ	P,GTWST2##	;GET AN ARGUMENT
	JUMPE	T1,SETE16	;DONE (OR USE PDB) IF 0
	MOVEM	T1,(T2)		;SAVE IN RIB
	AOBJP	T2,SETE17	;DONE IF RIB FULL
	SOJE	P3,SETE17	;DONE IF NO MORE VALUES
	JRST	SETE15		;GO GET ANOTHER ARG FRO USER
SETE16:	HLRZ	T3,DEVEXT(F)	;IF A UFD
	TLC	T2,MACTSL##	;OR WE ALREADY STORED AT LEAST 1 FROM BLOCK
	TLNN	T2,-1		; AND THEN TERMINATED ON A 0
	CAIN	T3,'UFD'
	JRST	SETE17		;THEN WE'RE DONE
	HRLI	T2,.PDACS##(W)	;DEFAULT CASE - BLT ACCT. STRING
	MOVE	T3,T2		; FROM PDB TO RIB
	BLT	T2,ACTSTL##-1(T3)
SETE17:	MOVE	T1,.USMBF	;RESTORE T1
	POP	P,DEVUPP##(F)
SETE18:	MOVE	T2,RIBSLF##+1(T1) ;RESTORE RIB ADDRESS
	HLRZ	U,DEVUNI##(F)	;RESET U TO UNIT OF RIB
	PUSHJ	P,MONWRT##	;WRITE THE RIB
SETE19:	HRRZ	T3,DEVACC##(F)	;LOC OF THE A.T.
	JUMPE	T3,CPOPJ##	;LOSE IF UNIT REMOVED
	TLO	S,IO		;INDICATE WRITING
	PUSHJ	P,AT2DDB##	;SET UP DEVBLK,DEVREL, ETC FROM A.T. DATA
	  STOPCD .,JOB,UPC,	;++UNIT-CHANGE POINTER CLOBBERED
	MOVEI	T2,1		;INDICATE AT RELATIVE POINTER 1
	DPB	T2,DEYRLC##	;(0 IS THE UNIT N0, NOT NOW N DDB)
	SKIPGE	P1		;POINTERS IN RIB WHICH AREN'T IN DDB?
	HRRM	P1,DEVRET##(F)	;YES, SET DEVRET=DEVRBN SO RIB WILL
				; BE READ BEFORE ALLOCATION IS DONE
ENTXIT:	TLZ	F,OCLOSB	;TURN OFF OCLOSB IN CASE OF PARTIAL ALLOCATION
	PUSHJ	P,JDAADR##
	TLNN	M,UPARAL	;PARTIAL ALLOCATION ONLY?
	JRST	ENTXI1		;NO
	HRRI	M,-<UUXALC-UUXEXT>(M)	;ADJUST
	TLOA	F,ENTRB		;YES. SET FOR NON-SKIP RETURN
ENTXI1:	AOSA	(P)		;NO. SKIP(GOOD) RETURN
	HLLM	F,(T1)		;UUOCON DOESN'T STORE F ON AN ENTER ERROR RETURN
CLRSRB:	TLZ	S,IOSRIB	;RIB IS NO LONGER IN MON BUFFER
	JRST 	STRIOS##	;SAVE S AND RETURN TO USER
;HERE WHEN THE ENTER IS AN UPDATE (LOOKUP ALREADY DONE)
UPDATE:	PUSHJ	P,SAVE3##
	PUSHJ	P,CLSNAM	;IN CASE OF RENAME
	HRRZ	U,DEVUNI##(F)	;SET UP U
	TLZ	M,UUOMSK	;ZERO MEANINGFUL BITS IN UUO
	TLO	M,UUOUPD	;INDICATE UPDATE
	PUSHJ	P,SETLE1	;CHECK FOR EXTENDED UUO, OK NAME
	  JRST	UILNMR		;ZERO NAME - ERROR
	PUSHJ	P,GETWDU##	;GET NAME
	HRRZ	P1,DEVLNM##(F)	;GET THE LOGICAL NAME POINTER IF ANY
	CAMN	T1,DEVFIL(F)	;SAME AS LOOKED-UP NAME?
	JRST	UPDAT0		;YES, GO ON.
	JUMPE	P1,UILNMR	;FILNAME MISMATCH IF NO LOGICAL NAME POINTER
	SKIPE	T1,LNRNAM##(P1)	;SO FAR SO GOOD.  ANY FILENAME?
	CAME	T1,DEVFIL(F)	;YES. SAME AS LOOKED UP NAME?
	JRST	UILNMR		;NO. ERROR
UPDAT0:	HRRI	M,UUNEXT-UUNNAM(M)	;YES. POINT TO EXTENSION
	PUSHJ	P,GETWDU##	;SUPPLIED EXTENSION
	MOVE	P3,T1
	TRZ	T1,-1
	HLLZ	T2,DEVEXT(F)	;LOOKED-UP EXT
	HRRI	M,-1(M)		;BUMP FOR BELOW
	MOVE	T3,DEVLIB##(F)	;IF THE FILE WASN'T IN UFD, BUT IN LIB
	TLNN	T3,DEPLIB##	; MAKE UPDATE ILLEGAL
	CAMN	T1,T2		;MATCH?
	JRST	UPDA0A		;YES, SKIP THIS
	JUMPE	P1,UILNMR	;ERROR IF NO LOGICAL NAME TO LOOK AT
	HLL	P3,LNREXT##(P1)	;GET THE LOGICAL'S EXTENSION
	HLLZ	T1,P3		;COPY IT
	CAME	T1,T2		;MATCH?
	JRST	UILNMR		;NO. ERROR
UPDA0A:	HRRI	M,UUNPPN-UUNEXT+1(M)	;POINT TO PRJ,PRG
	TLNE	M,EXTUUO	;EXTENDED UUO?
	HRRI	M,-<2+UUXEXT-UUXPPN>(M)	;YES,
	HRRZ	T2,DEVACC##(F)	;LOC OF A.T.
	HRRZ	T2,ACCPPB##(T2)	;LOC OF PPB
	MOVE	T2,PPBNAM##(T2)	;PRJ,PRG OF LOOKED-UP FILE
	PUSHJ	P,GTWST2##	;PPN GIVEN?
	JUMPE	T1,UPDAT2	;NO PPN IF T1=0
	TLNE	T1,-1		;POINTER TO A PATH?
	JRST	UPDAT1		;NO
	PUSH	P,M		;YES, SAVE M
	HRRI	M,2(T1)		;POINT TO PPN WORD IN PATH
	PUSHJ	P,GTWST2##	;GET PPN
	POP	P,M
	JUMPE	T1,UPDAT2	;SAME PPN IF 0
UPDAT1:	CAMN	T1,T2		;PPN'S MATCH?
	JRST	UPDAT2		;YES, EVERYTHING'S COOL
	JUMPE	P1,UPDERY	;WE'RE IN TROUBLE IF NO LOGICAL NAME HERE
	SKIPE	T1,LNRPPN##(P1)	;IS THERE A PPN IN THIS LOGICAL?
	CAME	T1,T2		;YES, PPN'S MATCH?
	JRST	UPDERY		;NO, ISU ERROR
;HERE WHEN THE NAME, EXTENSION AND PRJ,PRG AGREE WITH THE LOOKED-UP FILE
UPDAT2:	PUSHJ	P,GETCB##	;GET CB RESOURCE
	PUSHJ	P,TSTSFD	;%DON'T ALLOW UPDATE OF DIRECTORY
	  JRST	UPDER9
	MOVEI	T1,FNCAPP##	;%CHECK TO SEE IF APPEND IS LEGAL
	PUSHJ	P,CHKPRV##
	  JRST	UPDER9
	HRRZ	T1,DEVACC##(F)	;%OK, LOC OF A.T.
	MOVE	T2,ACCNDL##(T1)	;%IS THIS A MAGIC FILE?
	TRNE	T2,ACPNDL##
	JRST	UPDER9		;%YES, IT CAN'T BE UPDATED
	MOVE	T1,ACCSTS##(T1)	;%STATUS
	TRNE	T1,ACPDEL##	;%MARKED FOR DELETION?  (IF SO, ANOTHER JOB
	JRST	UPDER5		;%DID A SUPERSEDE BEFORE THIS ENTER)
	PUSHJ	P,TSTWRT	;%TEST IF WRITING IS ALLOWED
	  JRST	UPDER7		;%NO, GIVE FILE-BEING-MODIFIED ERROR
	MOVEI	T1,FNCCAT##	;%CAN USER CHANGE ATTRIBUTES?
	SETZ	P2,
	PUSHJ	P,CHKPRV##
	  SETO	P2,
IFN FTFDAE,<
	PUSHJ	P,TSTWRT	;%FILE STILL WRITABLE?
	  JRST	UPDER7		;%NO, FILDAE MUST HAVE BLESSED 2 AT ONCE
>
	MOVEI	T2,ACPUPD	;%INDICATE THIS FILE BEING UPDATED
	MOVE	T3,DEVACC##(F)	;%
	HLL	T3,DEVJOB(F)	;%SIM UPDATE BIT
	TLNE	T3,DEPSIM	;%DDB ENABLED FOR SIM UPDATE?
	TRO	T2,ACPSMU	;%YES, FILE IS SIM UPDATE
	MOVSI	T1,ACPWCT##	;%INCREMENT WRITE COUNT
	ADDM	T1,ACCWCT##(T3)	; %EVEN FOR NON- SIM UPDATE FILES

	ORM	T2,ACCSTS##(T3)	;%
	PUSHJ	P,INCUC		;%INCR NMB, PPB USE-COUNTS
	PUSHJ	P,GVCBJ##	;%GIVE UP CB RES
	PUSHJ	P,WAIT1##
	TLNE	S,IOSWLK	;IS FILE (STR) WRITE LOCKED?
	JRST	CPOPJ1##	;YES. TAKE GOOD RETURN (DON'T CHANGE RIB)
	PUSHJ	P,DDBZR		;ZERO POINTERS IN CASE OF EXTENDED RIB
	TLNN	M,EXTUUO	;NO. EXTENDED ENTER?
	JRST	UPDER1		;NO
	HRRI	M,-UUXPPN(M)	;YES. POINT TO E
	HLRZ	U,DEVUNI##(F)	;SET U TO UNIT OF RIB
	PUSHJ	P,GETWDU##	;NUMBER OF ARGS/VALUES
	TRZ	T1,RB.BIT	;IGNORE NOISE BITS
	MOVE	P1,T1
	HRRI	M,UUXALC(M)	;POINT TO ALLOCATION WORD
	CAIL	P1,UUXALC
	PUSHJ	P,GETWDU##	;GET IT
	CAIL	P1,UUXALC	;SPECIFYING ALLOCATION?
	SKIPGE	T2,T1
	JRST	UPDER2		;NO. TAKE GOOD RETURN
	JUMPN	T1,UPDAT3	;SPECIFIED .RBALC IN ARGUMENT BLOCK?
	HRRI	M,-1(M)		;NO, POINT TO .RBEST
	PUSHJ	P,GETWDU##
	HRRI	M,1(M)		;PUT M BACK TO WHAT IT WAS
	SKIPN	T2,T1		;SPECIFIED .RBEST?
	JRST	UPDER2		;NO, TAKE GOOD RETURN
	MOVE	T3,DEVACC##(F)
	SUB	T2,ACCALC##(T3)	;HOW BIG IS THE FILE NOW?
	JUMPLE	T2,UPDER2	;IT'S ALREADY BIGGER THAN .RBEST, RETURN
	TLO	M,UALASK	;INDICATE ALLOCATION
	PUSHJ	P,UPDALC	;ADD MORE BLOCKS AT END OF FILE
	 JRST	UPDER2		;QUOTA EXCEEDED, RETURN ANYWAY
	  JRST	UPDER2		;BLOCK NOT FREE, RETURN ANYWAY
	TLZ	M,UPARAL	;DO NOT GIVE PARTIAL ALLOCATION FAILURE
	JRST	UPDAT4		;GO WRITE SATS
UPDAT3:	MOVE	T3,DEVACC##(F)
	SUB	T2,ACCALC##(T3)	;N-J
	JUMPLE	T2,DELGRP	;TRUNCATING IF NEGATIVE
				;CANT GET HERE FOR SIMULTANEOUS UPDATE,
				;SINCE LOOKUP STORES REAL ACCALC IN ENTER BLOCK
	TLO	M,UALASK	;INDICATE SPECIFYING ALLOCATION
	PUSHJ	P,UPDALC	;ADD MORE BLOCKS TO FILE
	 JRST	ENERR7		;QUOTA EXCEEDED
	  JRST	ENERR1		;COULDN'T START WHERE REQUESTED (E+11)
UPDAT4:	PUSHJ	P,WTUSAT
	TLOE	S,IOSRIB	;ALREADY HAVE RIB IN CORE?
	JRST	UPDER3		;YES
	PUSHJ	P,PTRGET##	;NO, READ RIB INTO CORE
	PUSHJ	P,UPDSET	;ADJUST DEYRLC FOR CURRENT POSITION
	JRST	UPDER3		;AND CONTINUE
;SUBROUTINE TO SEE IF WRITING A FILE IS ALLOWED
;ENTER WITH DEVACC SET UP
;EXIT CPOPJ IF FILE ALREADY BEING WRITTEN
;EXIT CPOPJ1 IF OK TO WRITE
TSTWRT:	PUSHJ	P,GETNMB	;%GET LOC OF NMB
	MOVE	T3,ACCSTS##(T2)	;STATUS OF DDB'S A.T.
	TRNE	T3,ACPDEL##	;MARKED FOR DELETION?
	POPJ	P,		;YES CANT RENAME OR UPDATE
	LDB	T2,ACYFSN##	;%STR NO IN T2

	EXCH	T1,T2		;%T=FSN, T2=LOC OF NMB
	TRO	T2,DIFNAL##	;%ADD OFFSET FOR NMBACC
TSTWR1:	PUSHJ	P,BYTSC1##	;%FIND AN A.T. FOR THIS STR
	  SKIPA	T3,ACCSTS##(T2)	;%FOUND - GET STATUS
	JRST	CPOPJ1##	;%NO MORE - UPDATE IS LEGAL
	TRNN	T3,ACPUPD!ACPSUP!ACPREN	;%FILE BEING WRITTEN?
	JRST	TSTWR1		;%NO, LOOK FOR MORE A.T.'S
	TRNN	T3,ACPSUP!ACPREN ;%BEING SUPERSEDED OR RENAMED?
	TRNN	T3,ACPSMU	;%NO, OPEN FOR SIM UPDATE?
	POPJ	P,		;%ERROR IF NOT UPDATE ON SIM UPDATE FILE
	MOVE	T3,DEVJOB(F)	;%SIM UPDATE FILE,
	TLNE	T3,DEPSIM	;%DDB IN SIM UPDATE MODE?
	TLNN	M,UUOUPD	;%AND AN UPDATE UUO?
	POPJ	P,		;%NOT SIM UPDATER OR RENAME UUO
	JRST	CPOPJ1##	;%SIM UPDATE FILE AND DDB - OK



;HERE ON 4-WORD UPDATE   SET UP SIZE IN E+3
UPDER1:	PUSHJ	P,WRDCNT	;STORE WRDCNT IN E+3
	PUSHJ	P,SIMRIB	;GET DA, IF SIM UPDATE, THEN READ RIB
	  JRST	ENERR6		;RIB ERROR

	PUSHJ	P,UPDAUT	;UPDATE RIBAUT
	  JRST	UPDFN1		;RIBAUT DIDN'T CHANGE - LEAVE RIB ALONE
	PJRST	UPDFIN		;REWRITE RIB AND TAKE GOOD RETURN
;SUBROUTINE TO UPDATE RIBAUT
;ENTER WITH RIB IN MONITOR BUFFER
;EXIT CPOPJ IF RIBAUT DIDN'T CHANGE
;EXIT CPOPJ1 IF IT DID, RIBAUT UPDATED
UPDAUT:	LDB	T1,PJOBN##	;JOB NUMBER
	MOVE	T1,JBTPPN##(T1)	;IF [1,2] IS UPDATING IN [3,3],
	MOVE	T2,DEVPPN(F)
	CAMN	T1,FFAPPN##
	CAME	T2,SPLPPN##
	SKIPA	T2,.USMBF
	POPJ	P,		;DON'T CHANGE RIBAUT
	CAMN	T1,RIBAUT##+1(T2)	;RIBAUT CHANGING?
	POPJ	P,		;NO
	MOVEM	T1,RIBAUT##+1(T2)	;YES, STORE NEW VALUE
	PJRST	CPOPJ1##	;AND SKIP-RETURN

;SUBROUTINE TO INCREMENT NMB, PPN USE-COUNTS
;PRESERVES T2
INCUC:	MOVE	T1,DEVACC##(F)
	MOVE	T3,ACCPPB##(T1)	;%LOC OF PPB
	AOS	PPBCNT##(T3)	;%BUMP COUNT
	HLRZ	T1,ACCNMB##(T1)
	TRZN	T1,DIFNAL##	;%FIND NMB
	JRST	.-2
	AOS	NMBCNT##(T1)	;%BUMP ITS COUNT
	POPJ	P,		;%AND RETURN
;HERE WHEN ALL ALLOCATION IS DONE. SET VALUES INTO USER AREA
UPDER2:
	PUSHJ	P,SIMRIB	;GET DA IF SIM UPDATE, READRIB
	  JRST	UPDFN2		;RIB ERROR

UPDER3:	PUSHJ	P,UPDAUT	;UPDATE RIBAUT
	  JFCL
	SKIPGE	P2		;IF USER HASN'T GOT PRIVS TO CHANGE ATTS.
	TLO	M,400000	; SET A FLAG
	PUSHJ	P,SETVAL	;YES, STORE USER-SUPPLIED VALUES INTO THE RIB
	TLZ	M,400000
	MOVE	T1,.USMBF
	CAIE	P1,3		;DID USER SPECIFY 3-WORD BLOCK?
	 JRST	UPDER4		;NO, USE HIS CREATION DATE
	TRNN	P3,700000	;DID HE SPECIFY BITS?
	 IOR	P3,RIBEXT##+1(T1) ;NO, GET THEM FROM THE RIB.
UPDER4:	TRNN	P3,77777	;USER SUPPLIED HI CREATION DATE
	IOR	P3,THSDAT##	;SUPPLY ACCESS DATE IF 0
	HRRM	P3,RIBEXT##+1(T1) ;SAVE IN RIB
	HRRZ	T2,DEVACC##(F)	;GET THE ACCESS TABLE POINTER
	MOVE	T3,RIBPRV##+1(T1)	;GET THE PRIVS WORD
	MOVEM	T3,ACCPRV##(T2)	;STORE IN THE AT
	HRRZ	T3,RIBEXT##+1(T1)	;GET THE ACCESS DATE, HI CREATION DATE
	HRLM	T3,ACCADT##(T2)	;STORE IN THE AT

;HERE WHEN ALL NON-POINTER INFO IS STORED IN RIB
UPDFIN:	PUSHJ	P,SPTRW##	;SET UP AN AOBJN WORD FOR THE PTRS IN THE MON BUF
	PUSHJ	P,PTRWRT##	;COPY POINTERS INTO MON BUF AND WRITE
UPDFN1:
	TLNE	S,IOSDA		;SIM UPDATE?
	PUSHJ	P,DWNDA##	;YES, GIVE UP DA NOW THAT RIB IS WRITTEN

	SOS	T1,DEVREL##(F)	;SAVE DEVREL
	TLNE	T1,-1		; FOR POSSIBLE USETO -1
	SETZ	T1,		;OPPS! LARGER THAN 2**18
	HRLM	T1,DEVLRL##(F)
	PUSH	P,DEVRSU##(F)
	PUSHJ	P,CPYFST##	;SET UP FIRST DDB NUMBERS (DEVBLK, ETC)
	  JFCL			;SHOULD NEVER HAPPEN
	POP	P,DEVRSU##(F)
	PUSHJ	P,GETCPY
UPDFN2:
	PJRST	ENTXIT		;AND EXIT THE UUO
;SUBROUTINE TO GET IN-CORE COPY SPACE AND LINK IT IN
GETCPY:	MOVEI	T2,PTRCOR##
	PUSHJ	P,GET4WD##	;GET SOME SPACE FOR POINTERS
	  POPJ	P,		;NONE AVAILABLE, FORGET IT
	HRRM	T1,DEVCPY##(F)	;SAVE THE SPACE
	HRRZ	T3,DEVACC##(F)	;POINT COPY TO ACCESS TABLE
	HRRM	T3,PTRAT##(T1)	; FOR IDENTIFICATION
	DDBSRL			;INTERLOCK THIS STUFF
	MOVE	T2,SYSPTR##	;INSERT THIS COPY AT FRONT OF LIST
	HRLM	T1,SYSPTR##
	HLLM	T2,PTRSYS##(T1)	;POINT THIS ONE AT FORMER FIRST
	DDBSRU			;UNLOCK
	PJRST	CPYPTR##	;STUFF POINTERS INTO SPACE WE GOT, RETURN

;HERE TO RETURN SOME BLOCKS ON AN UPDATE ENTER
DELGRP:	JUMPE	T2,UPDER2	;NO ALLOCATION IF T2=0  - FINISH UP
	MOVE	T2,ACCCNT##(T3)	;NUMBER OF READERS
	TRNE	T2,ACMCNM##	;IF MORE THAN 1 READER,
	JRST	UPDER6		; CANT TRUNCATE FILE (SECURITY RISK -
				; THE BLOCKS MAY BE REUSED FOR ANOTHER FILE)
	PUSHJ	P,PTRGET##	;READ RIB INTO MON BUFFER
	PUSHJ	P,GTWDT3	;GET LAST GOOD BLOCK
	MOVEI	T2,0		;RIB STARTS AT BLOCK 0
DELLUP:	PUSHJ	P,SCNPTR##	;FIND THE RIGHT POINTER
	  JRST	DELGP1		;;NOT HERE, LOOK AT OTHER RIBS
	PUSH	P,DEVRIB##(F)	;SAVE POINTER TO CURRENT RIB
	PUSHJ	P,UPDGV9	;GIVE UP SOME BLOCKS
	  JRST	UPDER8		;PRIVS WONT ALLOW IT - ERROR RETURN
	POP	P,T1		;RESTORE PREVIOUS DEVRIB
	CAME	T1,DEVRIB##(F)	;SKIP IF UPDGIV DID NOT MOVE INTO ANOTHER RIB
	JRST	DELG0A		;IF ANOTHER RIB, PREVIOUS CURRENT RIB ALREADY WRITTEN

;DEALLOCATION IS COMPLETE - FINISH UP
	MOVE	T1,.USMBF	;LOC OF MON BUF (-1)
	PUSHJ	P,WRTRIB##	;GO WRITE NEW RIB
	SKIPL	DEVRIB##(F)	;PRIME RIB IN CORE?
	JRST	DELG0B		;YES, PROCEED
DELG0A:	PUSHJ	P,REDRIB##	;READ THE PRIME RIB INTO CORE
	  JRST	UPDFN2		;ERROR READING RIB

DELG0B:	PUSHJ	P,WTUSAT	;WRITE CHANGED SAT
	JRST	UPDER3		;AND FINISH UP


;HERE TO LOOK AT OTHER RIBS
DELGP1:
	PUSHJ	P,PTRNXT##	;GET NEXT RIB, IF ANY

	  STOPCD .,JOB,NNR,	;++NO NEXT RIB
	PUSHJ	P,GETALC##	;GET REAL ACCALC (BASED ON THE EXTENDED RIB)
	PUSHJ	P,GTWDT3	;GET LAST GOOD BLOCK
	SUB	T1,T3		;BLKS IN FILE - HIS ARGUMENT
	JUMPLE	T1,UPDER2	;NOT REALLY TRUNCATING IF NON-POS
	MOVE	T2,.USMBF	;IOWD FOR MONITOR BUFFER
	MOVE	T2,RIBFLR##+1(T2) ;FIRST BLOCK NUMBER IN CURRENT RIB
	PUSHJ	P,SPTRW##	;SET UP AOBJN WORD TO POINTERS IN T1
	JRST	DELLUP		;SCAN THIS RIB
SUBTTL	LOOKUP/ENTER SETUP (INCLUDING SFD PATHS)
;SUBROUTINE TO SET UP FOR LOOKUP, ENTER
;RETURNS WITH EXTUUO ON IN LH(M) IF EXTENDED UUO, AND M POINTING TO PRJ,PRG NO.
;RETURNS P3= ORIGINAL LOOKUP NAME, P4=ORIGINAL EXT (LH=-1 IF /OVERRIDE)
;SETS UP DEVPPN ON RETURN
;ON ERROR RETURN, IF UUOREN IS ON, THE ERROR CODE IS IN T1
;	M WILL POINT TO THE FILE NAME WORD
SETLER:	TLZ	M,UUOMSK	;ZERO BITS IN LH(UUO)
	TLZ	S,IOSPBF+IOSERR## ;MAKE SURE PERMANENT ERR BITS ARE OFF
	SETZM	DEVFIL(F)	;FOR SET WATCH FILE

IFN FTFDAE,<
	PUSHJ	P,CHKFCU	;CHECK IF AT COUNT IS UP FROM FILDAE
>
SETLE1:	PUSHJ	P,GETWDU##
	SETZ	T2,		;SET TO ZERO PROTECTION BYTE
	DPB	T2,DEYFNC##	;IN CASE OF LOOKUP WITH NO PRECEDING CLOSE
	DPB	T2,DEYFSN##	;IN CASE OF ENTER WITH NO PRECEDING CLOSE
	MOVSI	T2,DEPDSL##+DEPAUL##+DEPNLB## ;CLEAR BITS LEFT FROM PREVIOUS UUO
	ANDCAM	T2,DEVLLE##(F)
	MOVEI	T2,DEPECS	;CLEAR NO-SUPERSEDE BIT IN DDB
	SKIPL	DEVJOB(F)
	ANDCAM	T2,DEVSPL(F)
IFN FTKL10&FTMP,<
	SETZM	DEVNBF(F)	;CLEAR COUNTERS OF BUFFERS SWEPT FOR
	SETZM	DEVSBF(F)
>
	TLNN	T1,-1		;NAME?
	JUMPN	T1,SETL11	;NO, MUST BE EXTENDED UUO
SETLE2:	TLNE	M,UUOUPD	;UPDATE?
	JRST	CPOPJ1##	;YES. GOOD RETURN
	MOVE	P3,T1		;ORIGINAL NAME FROM LOOKUP BLOCK
	PUSHJ	P,GETWD1##	;GET EXTENSION
	HLRZ	P4,T1		;SAVE IN P4
	LDB	J,PJOBN##

	SETZM	DEVPPN(F)	;START WITH DEVPPN=0
	SETZM	DEVSFD##(F)	;MAKE SURE START AT UFD
	PUSH	P,M		;SAVE M
	HRRI	M,UUNPPN-UUNEXT(M) ;POINT TO PPN WORD
	TLNE	M,EXTUUO
	HRRI	M,-<3+UUXNAM-UUXPPN>(M)
	MOVE	T1,DEVNAM(F)
	PUSHJ	P,SDVTST	;IS THIS AN ERSATZ DEVICE?
	  JRST	SETLE3		;NO, CARRY ON
	CAIE	T2,LIBNDX##	;YES, IS IT A LOGICAL NAME?
	JRST	SETLE3		;NO
	MOVE	T1,@.USLNM	;YES, POINT AT THE START
	ADDI	T1,LNMDEV##-LNRDEV##
	HRRZM	T1,DEVLNM##(F)	;SAVE IN DDB
	TLNE	T1,LNPOVR##	;OVERRIDE?
	TLO	P4,-1		;YES, SET P4 NEGATIVE
	PUSHJ	P,NXTSP3	;GO GET FIRST SPEC IN LOG NAME
	  CAIA
	JRST	SETLE9		;NOT THERE, ERROR RETURN
	PUSHJ	P,GETWDU##	;GET PPN
	CAME	T1,MFDPPN##	;IS PPN [1,1]?
	JRST	SETL99		;NO
	MOVEM	T1,DEVPPN(F)	;YES, OVERIDE THE IMPLIED PPN
	PUSHJ	P,SFDDEC	;AND WIPE THE SFD (IF ANY)
	PUSHJ	P,DECSFD
	SETZM	DEVSFD##(F)
SETL99: MOVE	T1,DEVPPN(F)
	PUSHJ	P,PUTWDU##	;TELL USER THE PPN
	JRST	SETLE5
SETLE3:	JUMPE	P3,MPOPJ##	;IF NO LOG NAME, LOOKUP 0 IS ILLEGAL
	PUSHJ	P,GTWDT3	;IS IT IS XWD 0,ADR?
	SKIPLE	T2,T3
	TLNE	T2,-1
	JRST	SETLE4		;NO, PATH NOT GIVEN
	HRR	M,T2		;YES, POINT M TO PATH LIST
	SETOM	DEVFIL(F)	;MAKE SURE A 1ST SFD NAME OF 0 DOESN'T SCAN FOR A UFD
	PUSHJ	P,SETPT2	;FIND THE SFD HE WANTS
	  JRST	SETLE9		;NO SEARCH LIST OR NO SFD
	MOVE	J,.CPJOB##	;PARANOIA
SETLE4:	MOVEM	P3,DEVFIL(F)	;SAVE NAME IN DDB
	HRLM	P4,DEVEXT(F)	;SAVE EXT IN DDB
SETLE5:	POP	P,M		;RESTORE M
	HRRZ	T1,P4		;GET EXT ALONE
	CAIN	T1,(SIXBIT .SFD.) ;IS THE FILE AN SFD?
	TLO	M,UUODIR	;YES, SET UUODIR IN M
	HRRI	M,UUNPPN-UUNEXT-1(M)	;POINT TO PRJ, PRG WORD
	TLNE	M,EXTUUO	;EXTENDED UUO HAS PRJ,PRG
	HRRI	M,-<2+UUXEXT-UUXPPN>(M)	; IN WORD 1
	SKIPLE	DEVPPN(F)	;PRJ,PRG ALREADY SET UP?
	AOJA	M,CPOPJ1##	;YES, PATH WAS SPECIFIED. RETURN
	PUSHJ	P,PPNPP0	;GET PPN
	CAMN	T2,MFDPPN##	;LOOKING FOR [1,1]?
	MOVE	T1,T2		;YES, DONT USE IMPLIED PPN
	MOVEM	T1,DEVPPN(F)	;SAVE PPN IN DDB
	PUSHJ	P,PUTWDU##	;TELL USER THE PPN
	TLNE	F,SYSDEV	;IS THIS SYS:?
	JRST	CPOPJ1##	;YES, GOOD RETURN
	SKIPN	T3		;USE DEFAULT DIR?
	CAME	T1,T4		;YES, WRITING IN DEFAULT PPN?
	JRST	CPOPJ1##	;NO, USE UFD
	PUSHJ	P,SFDPPN
	HRRM	T2,DEVSFD##(F)	;YES, SAVE NEW PATH
	DPB	T3,DEYSCN##	;SAVE SCAN SWITCH
	SKIPN	T1,T2		;IS THE DEFAULT AN SFD?
	PJRST	CPOPJ1##	;NO, GOOD RETURN
	PUSHJ	P,SFDUP
	PUSHJ	P,INCALL	;YES, INCREMENT A.T.'S(INSURANCE FROM CORE-GRABBER)
	PUSHJ	P,SAVE3##
	MOVE	P3,NMBYES##(T1)	;P1=YES BITS
	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST
	  POPJ	P,		;NULL SL. WILL BE CAUGHT ELSEWHERE
	MOVE	P1,T1
	MOVE	P2,T1		;P2=SL.PTR.
SETLE6:	PUSHJ	P,SLITA##	;NEXT STR IN SEARCH LIST
	  JRST	SETLE7		;END OF LIST, SFD WASN'T FOUND
	PUSHJ	P,FSNPS2##	;POSITION BIT FOR YES WORD
	TDNE	T2,P3		;DOES SFD EXIST IN THIS STR?
	JRST	[		;YES-GIVE UP TEMP.SL.(IF ANY) AND RETURN
		MOVE	P2,P1
		AOS	(P)
		PJRST	SLGVT##
		]
	JRST	SETLE6		;NO, TRY NEXT STR

;HERE WHEN THE SFD DOESN'T EXIST IN THE SEARCH LIST
SETLE7:	MOVE	P2,P1		;GIVE UP POSSIBLE TEMP SL.
	PUSHJ	P,SLGVT##
	HRRI	M,-<UUNPPN-UUNEXT+1>(M)
	TLNE	M,EXTUUO
	HRRI	M,2+UUXEXT-UUXPPN(M)	;POINT M TO EXT, ERROR CODE WORD
	MOVE	T1,DEVSFD##(F)	;DECR. USE-COUNTS
	PUSHJ	P,DECALL
	PUSHJ	P,SFDDEC
	TLO	M,UUOREN	;FLAG TO USE ERROR IN T1
	ADDI	M,UUNEXT	;ACCOUNT FOR LATER SUBI
	JRST	SETL10		;AND GIVE SFD-NOT-FOUND ERROR RETURN
;HERE ON ERROR RETURN FROM SETPT3
;IF THIS CODE IS EXECUTED FROM THE RENAME CODE, THE ERROR
;MUST BE PLACED INTO THE USER'S AREA BY THIS ROUTINE.
;OTHERWISE, ONLY LIGHT UUOREN AND SET THE ERROR CODE INTO T1.
;THE CODE AT ILNMER WILL SET THE ERROR INTO THE USER'S AREA
SETLE8:	POP	P,M
	TLOA	M,UUOREN
SETLE9:	POP	P,M		;RESTORE LOC OF NAME
	TLON	M,UUOREN	;TURN ON UUOREN
	JRST	SETL10		;IF ENTER, ONLY SET ERROR
	PUSHJ	P,GETWD1##	;RENAME, GET EXTENSTION WORD
	HRRI	T1,SNFERR	;SFD-NOT-FOUND
	PUSHJ	P,PUTWDU##	;SAVE IN LOOKUP/ENTER BLOCK
SETL10:	MOVEI	T1,SNFERR	;GET SFD-NOT-FOUND
	HLRZS	DEVSFD##(F)	;MAKE SURE DEVSFD=0
	SUBI	M,UUNEXT	;POINT BACK AT NAME
	POPJ	P,		;AND TAKE ERROR RETURN

;HERE ON EXTENDED UUO
SETL11:	TLO	M,EXTUUO	;INDICATE EXTENDED UUO
	TRZE	T1,RB.NSE	;NO-SUPERSEDE ENTER?
	IORM	T2,DEVSPL(F)	;YES, LIGHT BIT IN DDB
	SETZB	U,T2		;INDICATE NON SINGLE-ACCESS
				;SET BITS FOR LIB SEARCH/UPDATE
	TRZE	T1,RB.DSL
	TLO	T2,DEPDSL##
	TRZE	T1,RB.AUL
	TLO	T2,DEPAUL##
	TRZE	T1,RB.NLB
	TLO	T2,DEPNLB##
	IORM	T2,DEVLLE##(F)	;AND STORE IN DDB
	MOVE	T2,T1
	CAIL	T1,UUXSTS	;IS THIS A DIRECTORY FILE ENTER?
	PUSHJ	P,PRVJB##	;YES, IS THIS A PRIVILEGED JOB?
	  JRST	SETL12		;NO, CANT ENTER A UFD
	HRRI	M,UUXSTS(M)	;POSSIBLY.
	PUSHJ	P,GTWST2##
	TRNE	T1,RIPDIR##	;DIR BIT ON FOR ENTER?
	TLO	M,UUODIR	;YES. ENTERING A UFD
	HRRI	M,-UUXSTS(M)	;RESET ADR. OF UUO
SETL12:	HRRI	M,UUXNAM(M)	;UUOCHK ADR CHECKS IF VM
	PUSHJ	P,GTWST2##
	CAIGE	T2,UUXEXT	;MUST HAVE AT LEAST 3 ARGUMENTS
	POPJ	P,		;NOT ENOUGH ARGUMENTS
	JRST	SETLE2		;ARG BLOCK OK, KEEP ON
;SUBROUTINE TO STEP TO NEXT PART OF LOGICAL NAME SPEC
;EXIT CPOPJ1 IF NONE OR AT END
;EXIT CPOPJ IF FOUND, WITH DEVLNM, DEVSFD SET UP
;ENTER AT NXTSP3 IF USE CURRENT DEVLNM = T1 TO START
NXTSPC:	LDB	J,PJOBN##
	HRRZS	P1,DEVLNM##(F)	;LNM SPEC OF DDB
	JUMPE	P1,CPOPJ1##	;SKIP RETURN IF NONE
	MOVS	T1,LNRDEV##(P1)	;CURRENT LOGICAL NAME
	MOVE	T2,DEVPPN(F)	;AND PPN
	CAIN	T1,'SYS'	;IF IT IS SYS
	CAME	T2,NEWPPN##	;AND WE'RE CURRENTLY LOOKING AT NEW
	JRST	NXTSP2
	HLRZ	T1,JBTSFD##(J)	;IF USER HAS NEW ENABLED
	TRNN	T1,JBPXSY##
	JRST	NXTSP2
	MOVE	T1,SYSPPN##	;THEN DO SYS NOW
	JRST	NXTS12
NXTSP0: HLLZS	DEVSFD##(F)	;SETPTH MAY HAVE LEFT JUNK
	MOVE	J,.CPJOB##
NXTSP2:	PUSHJ	P,NXTILN	;GET NEXT PART OF SPEC
	  JRST	CPOPJ1##	;NOT A LOGICAL NAME
NXTSP3:	HRRZ	P1,DEVLNM##(F)	;ADDR OF CURRENT SPEC
	SKIPN	LNRNAM##(P1)	;ZERO FILENAME?
	JUMPE	P3,NXTSP2	;BOTH ZERO, TRY NEXT SPEC
	MOVE	T1,LNRDEV##(P1)	;GET NAME
	PUSHJ	P,SDVTS1	;ERSATZ DEVICE?
	  JRST	NXTSP9		;NO, USE PPN AS GIVEN
	JUMPN	T2,NXTSP8	;YES. SYS?
	MOVE	J,.CPJOB##
	HLRZ	T1,JBTSFD##(J)	;YES. IS NEW ENABLED?
	TRNE	T1,JBPXSY##
	MOVEI	T2,NEWNDX##	;YES. USE NEW PPN
NXTSP8:	SKIPG	T1,@SDVPPN##(T2) ;IMPLIED PPN FOR ERSATZ DEV?
	JRST	NXTSP9		;NO
NXTS12:	SKIPN	LNRPPN##(P1)	;YES, IS PATH SPECIFIED?
	JRST	NXTS11		;NO, USE ERSATZ PPN
	JRST	NXTS13		;USE ERSATZ PPN AND PATHOLOGICAL SFDS
NXTSP9:	SKIPN	T1,LNRPPN##(P1)	;GET PPN, IS IT DEFAULT?
	JRST	NXTSP4		;YES, SET UP FOR IT
NXTS13:	SKIPN	LNRSFD##(P1)	;NO, IS THERE AN SFD?
	JRST	NXTS11		;NO, UFD
NXTSP4:	PUSHJ	P,SETPT1	;YES, SET UP FOR THE SFD
	  JRST	NXTSP0		;CAN'T FIND IT, STEP TO NEXT PART OF SPEC
	SKIPA	J,.CPJOB##
NXTS11:	PUSHJ	P,PPNXWD	;SAVE PPN IN DDB
	SKIPE	T1,LNRNAM##(P1)	;PATHOLOGICAL NAME HAVE A FILE NAME?
	JUMPL	P4,NXTSP6	;YES, USE IT IF /OVERRIDE
	SKIPE	P3		;NOT /OVERRIDE, LOOKUP NAME GIVEN?
	MOVE	T1,P3		;YES, USE NAME FROM LOOKUP BLOCK
NXTSP6:	MOVEM	T1,DEVFIL(F)	;SAVE NAME IN DDB
	SKIPE	T1,LNREXT##(P1)	;PATHOLOGICAL NAME HAVE AN EXTENSION?
	JUMPL	P4,NXTSP7	;YES. USE IT OF /OVERRIDE
	TRNE	P4,-1		;NOT /OVERRIDE. EXT IN LOOKUP BLOCK?
	HRL	T1,P4		;YES, USE IT
NXTSP7:	HLLM	T1,DEVEXT(F)	;SAVE EXT IN DDB
	POPJ	P,

;ROUTINE TO STORE PPN
;T1 PASSES PPN (-1 IN EITHER HALF MEANS LOGGED IN PPN)
PPNXWD:	MOVE	J,.CPJOB##
	TLC	T1,-1		;NO, WANT LOGGED IN PROJ NUMBER?
	TLCN	T1,-1
	HLL	T1,JBTPPN##(J)	;YES
	TRC	T1,-1		;WANT LOGGED IN PROG NUMBER?
	TRCN	T1,-1
	HRR	T1,JBTPPN##(J)	;YES
	MOVEM	T1,DEVPPN(F)	;SAVE PPN IN DDB
	POPJ	P,


;SUBROUTINE TO FIND NEXT DEV, PPN, SFD SET IN LOG NAME SPEC
;NON-SKIP RETURN IF END, OR NOT A LOGICAL NAME
;SKIP-RETURN IF LOG NAME, WITH T1=RH(DEVLNM)=NEXT DEVICE IN SPEC
NXTILN:	HRRZ	T1,DEVLNM##(F)	;LOGICAL NAME SPEC
	JUMPE	T1,CPOPJ##	;NOT THERE
	ADDI	T1,LNRPPN##	;POINT AT PPN SPEC (OR END)
	SKIPE	(T1)		;FIND THE END OF THIS PART
	AOJA	T1,.-1
	SKIPN	1(T1)		;AT END OF ENTIRE SPEC?
	POPJ	P,		;YES, NO NEXT PART
	ADDI	T1,1		;NO, POINT DDB AT NEXT PART OF SPEC
	MOVEM	T1,DEVLNM##(F)
	JRST	CPOPJ1##	;AND GOOD RETURN
;SUBROUTINE TO GET NEXT SFD IN SPEC
;NON-SKIP RETURN IF NOT USING A LOGICAL NAME
;SKIP RETURN IF LOGICAL NAME, T1=NEXT SFD (CAN BE 0)
NXTSLN:	SKIPN	T1,DEVLNM##(F)	;IN LOG NAME?
	POPJ	P,		;NO
	MOVE	T2,LNRPPN##(T1)	;YES. GET PPN
	TLNN	T1,-1		;1ST TIME HERE?
	SKIPE	T2		;DEFAULT PATH?
	JRST	NXTSL6		;NOT DEFAULT PATH OR ALREADY SET UP
	HRRZ	T2,.USLNM	;POINT AT TEMP SPACE
	ADDI	T2,LNMMAX##+MAXLVL##-2 ;AT TOP
	SETZM	1(T2)		;TERMINATE THE SPEC
	HRRZ	T1,JBTSFD##(J)
	TRZ	T1,JBPSCN##
	JUMPE	T1,NXTSL5	;GET PPN FROM JBTPPB IF NO JBTSFD
	TRZE	T1,JBPUFB##	;DEFAULT PATH AN SFD?
	JRST	NXTSL4		;UFB - GET IT, DONT STORE SFDS
	HLRZ	T4,NMBACC##(T1)	;SFD - POINT TO ITS AT
	MOVE	T4,ACCPPB##(T4)	;PRESERVE POINTER TO PPB
	JRST	NXTSL2		;GO STORE THIS SFD NAME IN TEMP SPACE
NXTSL1:	HLRZ	T1,NMBPPB##(T1)	;LINK
	TRZN	T1,NMPUPT##	;POINT AT FATHER SFD?
	JUMPN	T1,NXTSL1	;NO, GO TO NEXT
	JUMPE	T1,NXTSL3
NXTSL2:	MOVE	T3,NMBNAM##(T1)
	MOVEM	T3,(T2)
	SOJA	T2,NXTSL1
NXTSL3:	MOVE	T1,T4		;GET PPB POINTER BACK
NXTSL4:	SKIPA	T1,PPBNAM##(T1)	;GET PPN
NXTSL5:	MOVE	T1,JBTPPN##(J)
	MOVEM	T1,DEVPPN(F)
	MOVSI	T1,(T2)		;POINT JUST BEFORE 1ST SFD SPEC
NXTSL6:	TLNN	T1,-1		;ALREADY POINTING AT AN SFD?
	JRST	NXTSL7		;NO, POINT AT 1ST SFD
	HLRZS	T1		;YES, POINT AT THIS SFD
	AOSA	T1		;STEP TO NEXT PART
NXTSL7:	ADDI	T1,LNRSFD##
	HRLM	T1,DEVLNM##(F)	;SAVE IN DDB
	MOVE	T1,(T1)		;GET SFD NAME (OR 0 IF UFD)
	JRST	CPOPJ1##	;AND SKIP-RETTURN

;HERE IF WE COULDN'T SET UP LIB AGAIN AFTER ENTER COULDN'T FIND  THE FILE
LNMSTP:	STOPCD	.+1,DEBUG,LND, ;++LOGICAL NAME NOT FOUND
	POP	P,(P)
	JRST	LKENER
;ROUTINE TO GET THE PPN
;ENTER M POINTING TO USERS ARG (-1)
;ENTER AT CURPPX IF NO USER ARG
;EXIT T1=PPN, T2=SPECIFIED PPN IF SPECIAL DEV, OTHERWISE LH(T2)=0
; EXIT T4=JOBS DEFAULT PPN
;CURPPN RETURNS NON-SKIP IF USE DEFAULT PPN(E+3=0)
; IT RETURNS CPOPJ1 IF E+3 POSITIVE
;CURPPX ALWAYS RETURNS NON-SKIP
CURPPX::HRRZ	T2,F
	CAIN	T2,DSKDDB##	;GET DEVNAM IF NOT PROTOTYPE
	SKIPL	T1		;T1 A CHAN NUMBER?
	MOVE	T1,DEVNAM(F)	;YES, GET NAME
	PUSH	P,T1		;SAVE ON PD LIST
	PUSHJ	P,SFDPPN	;GET DEFAULT PPN
	SETZ	T3,
	JRST	CURPPY		;AND CONTINUE
CURPPN:	PUSHJ	P,SFDPPN	;GET DEFAULT
	PUSHJ	P,GETWD1##	;GET USERS ARG
	MOVEI	T3,1
	PUSH	P,DEVNAM(F)	;SAVE NAME
	JUMPG	T1,[AOS -1(P)	;IF NOT SPECIFIED
		SETZ	T3,
		JRST	CURPP1]
CURPPY:	MOVE	T1,T4		;T1=DEFAULT PPN
CURPP1:	EXCH	T1,(P)		;SAVE PPN, GET NAME
	PUSH	P,T4
	PUSH	P,T3
	PUSHJ	P,SDVTST	;SPECIAL DEV?
	  MOVEI	T2,ZPPNDX##	;NO, POINT T2 AT @0
	CAILE	T2,SYSNDX##	;IF NOT SYS
	TLZ	F,SYSDEV	; CLEAR BIT IN F
	POP	P,T3
	CAIE	T2,LIBNDX##	;LOGICAL NAME?
	JRST	CURPP2		;NO
	MOVE	T1,@.USLNM	;YES, GET PPN FROM SPECIFICATION
	MOVE	T1,LNMPPN##(T1)
	MOVEM	T1,-1(P)	;SAVE AS DEFAULT PPN
CURPP2:	POP	P,T4
	SKIPG	T1,@SDVPPN##(T2)	;YES, IS THERE AN IMPLIED PPN?
	JRST	TPOPJ##		;NO, RETURN
	ADDM	T3,-1(P)	;YES, SKIP RETURN IF CALL TO CURPPN
	JUMPN	T2,T2POPJ##	;LOOKING FOR SYS?
	MOVE	T2,JBTSFD##(J)	;YES, WANT NEW?
	TLNE	T2,JBPXSY##
	MOVE	T1,XSYPPN##	;YES
	PJRST	T2POPJ##	;THROW AWAY OLD PPN AND RETURN

;ROUTINE TO GET CURRENT PPN, SET DEPPP0
;CALL, EXIT SAME AS CURPPN
;ALWAYS RETURNS CPOPJ
PPNPP0:	PUSHJ	P,CURPPN	;GET PPN
	  TDZA	T3,T3		;PPN=0
	MOVEI	T3,1		;PPN NON-0
	TLNE	F,SYSDEV	;SYS?
	MOVEI	T3,0		;YES, SET SO NEW: SEARCHES SYS
	DPB	T3,DEYPP0##	;REMEMBER STATE OF PPN WORD
	POPJ	P,		;RETURN
PTHUUO::PUSHJ	P,SAVE4##	;SAVE P1
	HRR	M,T1		;LOC OF ARG LIST
	HLRZ	P4,T1		;N-3 INTO P4
	SKIPE	P4		;MAKE 0 ARGS DEFAULT TO 3
	SUBI	P4,3		;NO. OF ARGS-3
	JUMPL	P4,ECOD11##	;1 OR 2 ARGS ILLEGAL
	PUSHJ	P,GETWDU##	;GET VALUE
PTHUU1:	HLRE	P2,T1		;GET JOB NUMBER
	SKIPLE	P2		;IF .LE. 0
	CAILE	P2,JOBMAX##	;  OR TOO HIGH
	MOVE	P2,.CPJOB##	;USE CURRENT JOB
	TLNN	T1,770000
	HRRES	T1		;GET ARGUMENT
	MOVN	T2,T1
	SKIPLE	T2
	CAILE	T2,MXPATH
	JRST	PTHU13
	JRST	@PTHDSP-1(T2)

PTHDSP:	PTHU20			; -1  READ DEFAULT PATH
	PTHUU3			; -2 SET DEFAULT PATH
	PTHUU2			; -3 SET LIB, SYS, NEW
	PTHU12			; -4 READ LIB, SYS, NEW
	PTHSLN			; -5 SET LOGICAL NAME
	PTHRLN			; -6 READ LOGICAL NAME
MXPATH==.-PTHDSP

PTHUU2:	SETOB	P1,P4		;SET SOME FLAGS
	PUSHJ	P,GETWD1##	;GET ARGUMENT
	TRNN	T1,PT.DTL##	;DONT CHANGE LIST?
	SOJA	M,PTHUU3	;NO, DO REGULAR STUFF
	ANDI	T1,CORXTR##	;YES, CLEAR OUT FUNNY BITS
	MOVE	T2,JBTSFD##(J)	;GET CURRENT DEFAULT
	TLZ	T2,CORXTR##
	TLO	T2,(T1)		;SET NEW LIB/SYS BITS
	MOVEM	T2,JBTSFD##(J)	;SAVE AS CURRENT DEFAULT
	JRST	CPOPJ1##	;AND GOOD RETURN

PTHUU3:	PUSHJ	P,FAKDDB	;SET UP A DDB FROM FREE CORE
	  POPJ	P,		;NO FREE CORE LEFT - CANT SET THE PATH
	MOVEM	P4,DEVNAM(F)	;STORE N-3 IN NAME
	PUSHJ	P,SETPT2	;SET UP THE DEFAULT PATH
	  PJRST	PTHUU6		;SOME SFD WASN'T THERE
	JUMPL	P4,PTHUU7	;SET LIB, SYS IF -3
	MOVE	T2,DEVSFD##(F)
	TRNN	T2,JBPUFB##	; IF POINTING AT UFD
	PUSHJ	P,SFDDEC
	PUSHJ	P,SFDPPJ	;GET OLD DEFAULT
	HLRZ	P2,T1		;SAVE LOC OF SFD NMB OR PPB
	LDB	T1,DEYSCN##	;GET VALUE OF SCAN-SWITCH
	OR	T1,DEVSFD##(F)	;PLUS L(SFD NMB)
	HRRM	T1,JBTSFD##(J)	;SET AS NEW DEFAULT
	MOVE	P1,T4		;SAVE OLD PPN
	SKIPE	T1,T2		;IS THERE AN OLD SFD?
	PUSHJ	P,DECALL	;YES, DECREMENT ITS USE-COUNTS
	CAMN	P1,DEVPPN(F)	;OLD PPN=NEW PPN?
	JRST	PTHUU5		;YES, FINISH UP
	MOVE	T1,P1		;NO, GET OLD PPN
	CAME	T1,JBTPPN##(J)	;SAME AS JOB'S PPN?
	PUSHJ	P,PTHCHX	;NO, CLEAN UP OLD DEFAULT
	MOVE	T1,DEVPPN(F)	;NEW DEFAULT PPN
	CAMN	T1,JBTPPN##(J)	;IS IT JOB'S PPN?
	JRST	PTHUU5		;YES
	PUSHJ	P,SFDPPN	;NO, GET L(PPB)
	HLRS	T1
PTHUU4:	MOVEI	T2,PPPNLG##	;PRETEND NEW DEFAULT PPN IS LOGGED IN
	ORM	T2,PPBNLG##(T1)
PTHUU5:	PUSHJ	P,TSTPPB	;DELETE PPB IF UNUSED
	PUSHJ	P,CLRDDB	;RETURN THE DDB
	PJRST	CPOPJ1##	;AND TAKE GOOD RETURN

;HERE ON ERROR RETURN FROM SETPT3
PTHUU6:	PUSHJ	P,TSTPPB	;DELETE PPB IF NOW UNUSED
	PUSHJ	P,CLRDDB	;RETURN THE DDB TO FREE CORE
	LDB	T1,PUUOAC##	;GET CALLI AC
	HRR	M,T1		;INTO ADDRESS OF M
	PJRST	RTM1##		;RETURN -1 AS INDICATION OF FAILURE
;HERE TO SET UP A LIB
PTHUU7:	PUSHJ	P,GETWDU##	;GET ARGUMENT
	JUMPN	T1,PTHUU8	;CLEARING LIB?
	SETZM	.PDOSL##(W)
	PUSHJ	P,FNDLB		;YES, FIND OLD LIB
	  JRST	PTHUU9		;NOT THERE
	MOVSI	T1,LN.LIB##	;CLEAR LIB SPEC
	ANDCAM	T1,@.USLNM
	JRST	PTHUU9		;AND CONTINUE
PTHUU8:	SETO	P4,		;DEFINE A LOGICAL NAME
	PUSHJ	P,PTHSL		; SO WE DONT HAVE TO SPECIAL CASE THE OLD STUFF
	  PJRST	CLRDDB		;CANT DEFINE IT - ERROR RETURN
PTHUU9:	PUSHJ	P,FNDPDS##
	HRRZ	T2,DEVSFD##(F)	;LIB, SYS, AND NNEW
	PUSHJ	P,GTWST2##
	SKIPN	T1		;CLEARING LIB?
	ANDI	T2,CORXTR##	;YES, IGNORE WHAT SETPTH SAID
	MOVEM	T1,.PDOSL##(W)	;SAVE OLD-STYLE LIB
	MOVE	J,.CPJOB##
	HLRZ	P2,JBTSFD##(J)	;OLD LIB
	HRLM	T2,JBTSFD##(J)	;SAVE NEW LIB, SYS BITS
	TRZ	P2,CORXTR##	;ZAP THE EXTRA BITS
	JUMPE	P2,PTHU10	;GO IF NO OLD LIB
	TRZ	T2,CORXTR##
	CAMN	T2,P2		;
	JRST	PTHU10		; OR IF OLD LIB = NEW

;HERE IF THERE IS AN OLD LIB
	MOVE	T1,PPBNAM##(P2)	;GET PPN
	PUSHJ	P,PTHCHX	;FINISH UP IF NOW NO USER OF THE PPN
PTHU10:	SETO	T1,
	HLRZ	T2,JBTSFD##(J)	;IS THERE A NEW LIB?
	TRNN	T2,-1-CORXTR##
	PUSHJ	P,PTXUDF	;NO, UNDEFINE THE OLD ONE
	  JRST	PTHU11		;NO OLD LIB
	PUSHJ	P,PTHSL2	;RETURN THE SPACE FOR IT
	  JFCL
PTHU11:	HRRZ	T1,DEVSFD##(F)	;NEW PPB INTO T1
	TRZ	T1,CORXTR##	;CLEAR /SYS/NEW
	JRST	PTHUU4		;GO SET IT LOGGED-IN
;HERE TO READ LIB, SYS
PTHU12:	HLRZ	T1,JBTSFD##(P2)	;LIB, SYS,NEW
	ANDI	T1,CORXTR##	;JUST SYS, NEW
	PUSHJ	P,PUTWD1##	;TELL USER
	MOVE	T1,P2		;JOB# IN T1
	MOVE	T2,JBTSTS##(T1)	;IS JOB NUMBER ASSIGNED?
	TLNN	T2,JNA##
	PJRST	ECOD7##		;NO, GIVE ERROR CODE PTNSJ%
	PUSHJ	P,FPDBT1##	;GET POINTER TO JOB'S PDB
	  PJRST	NPJSTP##	;NO PDB FOR JOB, GIVE STOPCD AND ERROR RETURN
	MOVE	T1,.PDOSL##(T1)	;OLD STYLE LIB
	PUSHJ	P,PUTWD1##	;TELL USER
	PJRST	CPOPJ1##	;AND TAKE SKIP-RETURN

;HERE WHEN TRYING TO READ THE PATH
PTHU13:	PUSHJ	P,DVCNSG##	;GET DDB
	  PJRST	ECOD0##		;NONE - RETURN 0 TO USER
	SETOM	P3		;SET ALL FLAGS.
	TDO	P1,[-1-<PT.PHO##,,0>] ;MAINTAIN STATE OF PT.PHO (PHONLY)
	MOVE	T2,DEVMOD(F)
	TLNN	T2,DVDSK	;DSK?
	PJRST	RTZER##		;NO, RETURN 0
	HRRZ	T2,F		;ADR OF DDB (SYSDEV MIGHT BE ON)
	CAIE	T2,DSKDDB##	;PROTOTYPE DDB?
	MOVE	T1,DEVNAM(F)	;NO, GET NAME
	PUSHJ	P,ALIASD##	;IS IT DSK?
	TLZ	P1,PT.GEN##	;YES, CLEAR A BIT
	PUSHJ	P,SDVTSP	;SPECIAL DEVICE?
	  JRST	PTHU14
	MOVE	P3,T2		;SAVE INDEX
	HRL	P3,T3		;LH P3=0 IF DEV, 1 IF DEVX
	HRR	P1,T4		;SAVE LOGICAL NAME INDEX
	CAIN	T2,LIBNDX##	;LOGICAL NAME?
	PUSHJ	P,SDVTS1	;YES, ALSO AN ERSATZ DEVICE?
	  JRST	PTHU15		;NO
	TLZA	P1,PT.ESZ##	;YES, MAKE P1 POSITIVE
PTHU14:	MOVSI	T1,'DSK'
PTHU15:	HRRZ	T2,DEVACC##(F)	;LOC OF AT
	JUMPE	T2,PTHU16	;NO OPEN FILE, NAME='DSK'
	LDB	T2,ACYFSN##	;AN OPEN FILE, GET STR NUMBER

	MOVE	T1,@TABSTR##(T2) ; TELL USER STR NAME
				;FALL INTO PTHU16
PTHU16:	CAIE	P3,LIBNDX##
	JRST	PTHU17
	MOVE	T4,P1
	MOVE	T4,@.USLNM
	MOVE	T1,LNMDEV##(T4)
PTHU17:	PUSHJ	P,PUTWDU##	;STORE IT FOR USER
	LDB	T3,DEYSCN##	;SCAN-SWITCH
	HRRZ	T2,DEVACC##(F)	;IF NO A.T.
	JUMPE	T2,PTHU18	; FILE HAS BEEN CLOSED
	HRRZ	T2,DEVSFD##(F)	;LOC OF SFD NMB
	SKIPE	T4,DEVPPN(F)	;PPN SET UP?
	JRST	PTHU21
	JRST	PTHU19
PTHU18:	CAIE	P3,LIBNDX##
	JRST	PTHU19
	HRRO	T2,T4		;LOG NAME-REMEMBER LOC
	SKIPA	T4,LNMPPN##(T4)
PTHU19:	PUSHJ	P,SFDPPN	;NO, TELL HIM DEFAULT PPN
	TRZ	T3,JBPUFB##	;SO SCAN BITS WILL BE CORRECT
	TLNE	F,SYSDEV
	MOVE	T4,SYSPPN##
	JRST	PTHU21		;CONTINUE

;HERE TO READ DEFAULT PATH
PTHU20:	SETO	P3,
	SETZ	P1,		;INSURE PT.JSL GETS SET
	MOVEI	F,DSKDDB##	;FAKE UP F
	MOVE	J,P2		;JOB NUMBER
	PUSHJ	P,SFDPPN	;GET DEFAULT
	TRZ	T3,JBPUFB##	;MASK OUT DEFAULT=UFB BIT
PTHU21:	MOVEI	T1,1(T3)	;INTERNAL SCAN-SWITCH +1
	HLRZ	T3,JBTSFD##(J)	;LIB, SYS, NEW
	TRZE	T3,777774	;CLEAR EVERYTHING BUT SYS,NEW
	TRO	T1,PT.LIB##	;LIB NON-0 , LIGHT A BIT
	LSH	T3,2		;POSITION SYS,NEW BITS
	TRO	T1,(T3)		;LIGHT THEM IN T1
	JUMPL	P3,PTHU22	;IF A SPECIAL DEVICE,
	TLNN	P1,PT.ESZ##	;BOTH LOGICAL NAME AND ERSATZ DEVICE?
	TRO	T1,PT.EDA##	;YES, LITE A BIT
	HRRZ	T3,SDVTBL##(P3)	; GET SEARCH-LIST TYPE
	TLZN	P3,-1		;WAS IT DEVX?
	IOR	T1,T3		;NO, RETURN TYPE TO USER

	SKIPE	@SDVPPN##(P3)	;IF THERE IS AN IMPLIED PPN
	TRO	T1,PT.IPP##	;LIGHT A BIT
PTHU22:	TLNN	P1,PT.GEN##	;GENERIC DSK?
	TRO	T1,PT.JSL##	;YES, LIGHT JOB SEARCH LIST
	PUSH	P,T4		;PROTECT T4 IN CASE OF ABSURD USAGE
	CAIN	P3,LIBNDX##	;IF A LOGICAL NAME
	TRO	T1,PT.DLN##	; HE CAN GET MORE INFO WITH PATH
	MOVE	T4,DEVPTB##(F)
	TLNE	T4,DEPFFS##	;FOUND BY SCANNING?
	TRO	T1,PT.FFS##
	TLNE	T4,DEPFFL##	;FOUND IN LIB?
	TRO	T1,PT.FFL##
	PUSHJ	P,PUTWD1##	;TELL THE USER
	POP	P,T4
	CAIN	P3,LIBNDX##	;LIB OR LOGICAL NAME?
	JRST	PTHU25		;YES, PPN ALREADY SET UP
	JUMPL	P3,PTHU25	;IF  A SPECIAL DEVICE,
	JUMPN	P3,PTHU23	; IF SYS
	HLRZ	T1,JBTSFD##(J)	; IS NEW ON FOR USER ?
	TRNE	T1,JBPXSY##
	MOVEI	P3,NEWNDX##	; YES, RETURN NEWPPN
PTHU23:	JUMPGE	P2,PTHU24	;IF ASKING FOR NAME.EXT,
	MOVE	T1,DEVFIL(F)	; TELL HIM
	PUSHJ	P,PUTWD1##
	HLLZ	T1,DEVEXT(F)
	PUSHJ	P,PUTWD1##
PTHU24:	HRRZ	T1,DEVACC##(F)	;LOOKUP DONE?
	JUMPN	T1,PTHU25	;YES, GO TELL THE TRUTH
	SKIPLE	T1,@SDVPPN(P3)	;IS THERE AN IMPLIED PPN?
	TDZA	T2,T2		;YES, FLAG NOT TO USE SFDS FROM DEFAULT PATH
PTHU25:	MOVE	T1,T4		;DEFAULT PPN
	PUSHJ	P,PUTWD1##	;SAVE FOR USER
	JUMPLE	P4,CPOPJ1##	;RETURN IF THAT'S ALL HE WANTS
	JUMPL	T2,PTHU29	;GO IF PATH.[SIXBIT /LOGNAM/]
	PUSH	P,[0]		;SAVE TERMINATOR
	JUMPE	T2,PTHU28	;DONE IF HAVE A 0 NAME
PTHU26:	PUSH	P,NMBNAM##(T2)	;GET THE NEXT NAME
PTHU27:	HLRZ	T2,NMBPPB##(T2)	;SCAN FOR FATHER SFD
	TRZN	T2,NMPUPT##
	JUMPN	T2,PTHU27
	JUMPN	T2,PTHU26	;SAVE ITS NAME AND CONTINUE
PTHU28:	POP	P,T1		;READ A NAME FROM LIST
	SOSL	P4
	PUSHJ	P,PUTWD1##	;STORE IT IN USERS AREA
	JUMPN	T1,PTHU28	;GET NEXT
	PJRST	CPOPJ1##	;DONE - GOOD RETURN
;HERE ON A LOGICAL NAME. GIVE PATH OF 1ST COMPONENT
PTHU29:	MOVE	T1,LNMSFD##(T2)	;GET SFD
	PUSHJ	P,PUTWD1##	;TELL USER
	JUMPE	T1,CPOPJ1##	;TERMINATE ON END OF SFD'S
	SOJLE	P4,CPOPJ1##	;TERMMINATE ON FILLING BLOCK
	AOJA	T2,PTHU29	;TELL HIM NEXT SFD
;HERE TO SET A LOGICAL NAME
PTHSLN:	CAILE	P4,1		;LEGAL NUMBER OF ARGS?
	CAILE	P4,LNMMXL##-1
	JRST	ECOD1##		;NO, ERROR 1
	ADDI	M,2		;YES, POINT AT LOGICAL NAME
	PUSHJ	P,GETWDU##	;GET IT
	JUMPE	T1,ECOD5##	;MUST NOT BE BLANK
	PUSHJ	P,DEVLG##	;IS THERE A LOGICAL NAME ALREADY DEFINED?
	  CAMN	T1,[SIXBIT /DSK/] ;NO, TRYING TO DEFINE LOG NAME "DSK"?
	JRST	ECOD5##		;YOU LOSE
	SUBI	M,1		;POINT M BACK AT BITS
	MOVEI	F,DSKDDB##	;FAKE UP F FOR LNMTST

;CALLED FROM PATH FUNCTION -3 (SET LIB)
;WIPES OUT P ACS
PTHSL:	SKIPE	T1,.USLNM	;LOGICAL NAME TABLE EXIST?
	JRST	PTHSL1		;YES
	MOVEI	T2,LNMMAX##+MAXLVL##+1 ;NO, GET SPACE FOR TABLE, TEMP SPACE
	PUSHJ	P,GTFWDC##
	  JRST	ECOD4##		;NO FUNNY SPACE AVAILABLE
	HRLI	T1,T4
	MOVEM	T1,.USLNM	;SAVE ADDR (INDEXED BY T4) IN UPMP
	SETZM	(T1)
	MOVS	T2,T1		;MAKE SURE THE TABLE IS EMPTY
	HRRI	T2,1(T1)
	BLT	T2,LNMMAX##(T1)
PTHSL1:	JUMPL	P4,PTHSL4	;GO IF CALLED FROM PATH FNCN -3
	PUSHJ	P,GETWDU##	;GET BITS
	TLNN	T1,LN.UDF##	;UNDEFINE A LOGICAL NAME?
	JRST	PTHSL4		;NO

;HERE TO DELETE A LOGICAL NAME
	PUSHJ	P,PTHUDF	;UNDEFINE THE NAME
	  JRST	ECOD3##		;NO SUCH NAME
PTHSL2:	MOVEI	T1,@.USLNM	;POINT AT THIS LOGICAL NAME
	SKIPN	T3,1(T1)	;IS IT THE LAST NAME IN TABLE?
	JRST	PTHSL3		;YES
	MOVEI	T2,1(T1)	;NO, FIND LAST
	SKIPE	1(T2)
	AOJA	T2,.-1
	MOVE	T3,(T2)		;GET LAST LOGICAL NAME
	SETZM	(T2)		;CLEAR THE SPACE
PTHSL3:	EXCH	T3,(T1)		;SAVE PREVIOUS LAST NAME (OR 0) IN THIS SPACE
	SETZ	T4,		;SEE IF FIRST LOGICAL NAME TABLE SLOT ZERO
	SKIPE	@.USLNM		;(WE UNDEFINED LAST LOGICAL NAME SPEC)
	JRST	PTHSL5		;NO
	PUSH	P,T3		;SAVE LIBEDNESS FLAG
	MOVEI	T1,LNMMAX##+MAXLVL##+1 ;GIVE UP THE LOGICAL NAME TABLE SPACE
	HRRZ	T2,.USLNM
	PUSHJ	P,GVFWDS##
	SETZM	.USLNM		;FORGET ABOUT IT
	POP	P,T3		;RESTORE LIBEDNESS FLAG
PTHSL5:	JUMPGE	T3,PTHS12	;EXIT IF IT WASN'T LIB WE UNDEF'D
	PUSHJ	P,GETCB##	;WE GOT RID OF LIB - RETURN CORE BLOCKS
	PJRST	PTHS11		; IF THIS IS LAST USER OF THAT PPN
;HERE TO DEFINE A LOGICAL NAME
PTHSL4:	MOVE	P1,T1		;PRESERVE BITS
	PUSHJ	P,PTHUDF	;UNDEFINE PREVIOUS SPEC FOR THIS NAME
	  TDZA	T4,T4		;NO PREVIOUS SPEC. START AT BEGINNING
	JRST	PTHSL6		;THERE WAS ONE, USE ITS TABLE SLOT
	SKIPE	@.USLNM		;FIND FIRST FREE TABLE SLOT
	AOJA	T4,.-1
	CAILE	T4,LNMMAX##-1	;REACHED END OF TABLE?
	JRST	ECOD2##		;YES, TOO MANY NAMES TO DEFINE A NEW ONE

;HERE WITH T4=INDEX TO NEW NAME
PTHSL6:	SKIPGE	T2,P4		;CALLED BY PATH. FNCN -3?
	MOVEI	T2,4		;YES, 4 WDS ("DSK", 0 NAME, 0 EXT, PPN)
	ADDI	T2,3		;ACCOUNT FOR OVERHEAD WORDS
	DPB	T2,LNYLEN##	;SAVE LENGTH OF THIS ENTRY
	MOVEI	P2,@.USLNM	;POINT AT TABLE ENTRY
	MOVE	P3,T1		;SAVE NAME
	PUSHJ	P,GTFWDC##	;GET FUNNY SPACE FOR THE SPECIFICATTION
	  JRST	[SETZM (P2)	;NOT ENOUGH FUNNY SPACE
		 JRST ECOD4##]
	HRRM	T1,(P2)		;SAVE ADDR OF SPEC IN TABLE
	MOVEM	P3,LNMPLN##(T1)	;SAVE LOGICAL NAME
	MOVEI	P3,LNMDEV##(T1)	;POINT AT DEV (DSK, UNIT, STR,...)
	JUMPL	P4,[MOVSI T1,'DSK' ;IF CALLED BY PATH. -3
		    MOVEM T1,(P3) ; NAME IS "DSK"
		    SETZM 1(P3)	;NO NAME
		    SETZM 2(P3)	;NO EXT
		    ADDI P3,2	;POINT AT PPN
		    MOVE T1,DEVPPN(F) ; PPN IS GOTTEN FROM DDB
		    AOJA P3,PTHSL9] ;SAVE PPN AND FINISH UP
				;FALL INTO PTHSL7 IN NOT PATH. -3
PTHSL7:	MOVEI	R,LNRPPN##	;ALWAYS READ 1ST FEW ARGUMENTS
	AOSA	M		;SKIP NODE
PTHSL8:	JUMPE	T1,PTHSL7	;DO NEXT PART IF DONE WITH THIS
	PUSHJ	P,GETWD1##	;GET AN ARGUMENT
PTHSL9:	MOVEM	T1,(P3)		;REAL ARG - SAVE IT
	SOSL	R		;IN 1ST PART (NODE, DEV, NAME, EXT)?
	MOVEI	T1,1		;YES. MAKE SURE WE DONT TERMINATE
	SOSLE	P4		;MORE TO GO?
	AOJA	P3,PTHSL8	;YES, GET NEXT PART OF SPEC
	SETZM	1(P3)		;INDICATE WE ARE AT END
	SETZM	2(P3)
	MOVSI	T1,LNPOVR##
	ANDCAM	T1,(P2)		;CLEAR BITS IN SPEC
	TLNN	P1,LN.OVR##	;/OVERRIDE?
	TLZ	T1,LNPOVR##	;NO
	IORM	T1,(P2)		;SAVE BITS IN SPEC WORD
	MOVSI	T1,LN.LIB##
	HLL	P2,(P2)		;GET OLD LIB SPEC
	ANDCAM	T1,(P2)		;CLEAR LIBEDNESS
	TLNN	P1,LN.LIB##	;WAS IT FORMERLY A LIB?
	JUMPGE	P4,PTHS10	;NO (IF NOT PATH. -3)
	PUSHJ	P,FNDLB		;FIND OLD LIB
	  CAIA			;NO OLD LIB
	ANDCAM	T1,@.USLNM	;CLEAR LIBEDNESS FROM OLD LIB
	IORM	T1,(P2)		;SET LIBEDNESS IN NEW LIB
	JUMPL	P4,PTHS12	;DONE IF PATH. -3
	PUSHJ	P,FNDPDS##
	SETZM	.PDOSL##(W)	;NO OLD-SYLE LIB
	CAIA
				;FALL INTO NEXT PAGE
				;DROPS INTO HERE FROM PREVIOUS PAGE
PTHS10:	JUMPGE	P2,PTHS12	;WAS THERE AN OLD LIB?
	PUSHJ	P,GETCB##	;YES
	HLRZ	T2,SYSPPB##	;%START AT 1ST PPB IN SYSTEM
	HRRZ	T3,(P2)		;%GET NEW LIB PPN
	MOVE	T1,LNMPPN##(T3)
	PUSHJ	P,LSTSRC##	;%FIND NEW LIB PPB (CREATE IF NONEXISTENT)
	  JUMPE	T2,[PUSHJ P,GVCBJ## ;%EXIT IF NO CORE BLOCKS
		   SOS (P)
		   JRST PTHS12]
	MOVEI	T3,PPPNLG##
	SKIPGE	P2		;%IS THERE A NEW LIB?
PTHS11:	TDZA	T2,T2		;%NO
	IORM	T3,PPBNLG##(T2)	;%YES, PRETEND (1ST) PPN IS LOGGED IN
	HLRZ	P2,JBTSFD##(J)	;%GET OLD SYS/NEW BITS
	TRZ	P2,-1-CORXTR##
	TRO	T2,(P2)		;%INSERT NEW LIB PPN ADDR
	HLRZ	P2,JBTSFD##(J)	;%SAVE OLD LIB
	HRLM	T2,JBTSFD##(J)	;%STORE NEW LIB
	PUSHJ	P,GVCBJ##	;%RETURN CB RESOURCE
	CAIN	P2,(T2)		;OLD LIB+NEW LIB?
	JRST	PTHS12		;YES, DONE
	TRZ	P2,CORXTR##	;NO SAVE ADDR OF OLD PPB
	PUSHJ	P,FAKDDB	;LOGTST WILL REWRITE OLD UFD RIB
	  JRST	PTHS12		;NO SPACE FOR FAKE DDB, GOOD EXIT
	MOVE	T1,PPBNAM##(P2)	;GET OLD LIB PPN
	PUSHJ	P,PTHCHX	;REWRITE UFD RIB IF NOW NOT LOGGED IN
	PUSHJ	P,CLRDDB	;GIVE UP THE FAKE DDB
PTHS12:	JRST	CPOPJ1##	;AND TAKE GOOD RETURN


;HERE ON PATH. -6 (READ LOGICAL NAMES)
PTHRLN:	CAILE	P4,0		;NUMBER OF ARGUMENTS LEGAL?
	CAILE	P4,LNMMXL##-1
	JRST	ECOD1##		;NO
	MOVEI	F,DSKDDB##	;LNMTST LOOKS AT DDB
	PUSHJ	P,GETWD1##	;YES, GET ARGUMENT
	MOVE	P1,T1		;SAVE BITS
	PUSHJ	P,GETWD1##	;GET NEXT WORD (WHERE TO START)
	SKIPE	T4,T1		;WANT FIRST NAME?
	AOJA	P1,PTHRL3	;NO
	SKIPE	T1,.USLNM	;YES, ANY NAMES AT ALL?
	AOJA	P1,PTHRL5	;YES, GET 1ST
PTHRL1:	AOS	(P)		;NO, RETURN 0 (END)
	PJRST	PUTWDU##
;HERE WHEN USER SPECIFIES WHERE TO START
PTHRL3:	PUSHJ	P,LNMTST	;FIND THIS LOGICAL NAME
	  JRST	ECOD6##		;NONE SUCH NAME - ERROR
	TLNN	P1,LN.RIT##	;RETURN INFO ABOUT THIS NAME?
PTHRL4:	ADDI	T4,1		;NO, POINT TO NEXT NAME
PTHRL5:	SKIPN	T1,@.USLNM	;GET SPEC FOR THIS NAME
	JRST	PTHRL1		;DONE - RETURN 0
	MOVE	T2,LNMPLN##(T1)	;IF -1 IT IS OLD-STYLE LIB
	AOJE	T2,PTHRL4	; SO DON'T TELL ABOUT IT
	TDZ	T1,[-1-LN.LIB##-LNPOVR##,,-1] ;SAVE LIBEDNESS
	TLZE	T1,LNPOVR##	;/OVERRIDE?
	TLO	T1,LN.OVR##	;YES
	SUBI	M,1		;POINT AT BITS
	PUSHJ	P,PUTWDU##	;TELL CALLER IF THIS IS LIB
	MOVE	P1,@.USLNM	;POINT AT SPEC
	MOVE	T1,(P1)		;GET PATHOLOGICAL NAME
	PUSHJ	P,PUTWD1##	;TELL USER
	ADDI	P1,1		;POINT AT DEV
PTHRL6:	MOVEI	P3,LNRPPN##+1	;ALWAYS STORE FIRST ARGS
	SOS	P1		;ACCOUNT FOR LATER ADDI
	TDZA	T1,T1		;STORE A ZERO FOR NODE
PTHRL7:	MOVE	T1,(P1)		;GET NEXT WORD OF SPEC
	PUSHJ	P,PUTWD1##	;TELL USER
	SOJLE	P4,CPOPJ1##	;DONE IF NO MORE SPACE IN CALLERS BLOCK
	ADDI	P1,1		;POINT AT NEXT PART OF SPEC
	SOJGE	P3,PTHRL7
	JUMPN	T1,PTHRL7	;GET NEXT SFD IF DIDN'T END
	SKIPE	(P1)		;END OF THIS PART. FINAL PART?
	JRST	PTHRL6		;NO, STORE NEXT PART
	SETZB	T1,P4		;YES, MAKE SURE WE EXIT
	PUSHJ	P,PUTWD1##	;STORE THE 2ND 0
	JRST	PTHRL7		;AND STORE THE FINAL ZERO

;SUBROUTINE TO UNDEFINE A LOGICAL NAME
;ENTER WITH M POINTING AT THE NAME -1
;RETURNS CPOPJ IF NO MATCH, CPOPJ1 IF MATCH WITH T1=NAME
;RETURNS T4=INDEX IN LOG NAME TABLE IF A MATCH
PTHUDF:	SKIPL	T1,P4		;CALLED BY PATH. -3 ?
	PUSHJ	P,GETWD1##	;NO, GET NAME
PTXUDF:	PUSHJ	P,LNMTST	;FIND ITS SLOT
	  POPJ	P,		;NO SUCH NAME
PTKUDF:	PUSH	P,T1
	PUSH	P,T4
	LDB	T1,LNYLEN##	;NO OF WORDS FOR THIS SPEC
	HRRZ	T2,@.USLNM	;ADDR OF SPEC
	PUSHJ	P,GVFWDS##	;RETURN THE SPACE
	POP	P,T4
	JRST	TPOPJ1##	;AND RETURN
;SUBROUTINE TO SET UP THE PATH
;ENTER WITH M POINTING TO THE 1ST WD IN THE PATH SPEC, J= JOB NUMBER
;ENTER WITH DEVSFD=0
;IF DEVNAM IS POSITIVE, IT IS ASSUMED TO BE A COUNT OF SFD LEVELS (PTHUUO)
;IF DEVNAM=-1 IT IS ASSUMED THAT THE CALL IS TO SET A LIBRARY
;EXIT CPOPJ IF NO SEARCH LIST OR A NAME IN THE PATH ISN'T FOUND
;EXIT CPOPJ1 NORMALLY, WITH DEVSFD SET UP, USE CNTS UP IN SFD AT'S
;0 FOR PPN MEANS DEFAULT (NOT NECCESSARILY JOB'S PPN)
;ENTER WITH T1=LOC OF "FORBIDDEN" NMB-ERROR IF THIS
; NMB IS ON THE PATH (USED BY RENAME TO PREVENT A DIRECTORY INCONSISTENCY)
;ENTER AT SETPT2 IF ANY SFD IS LEGAL
;ENTER AT SETPT1 IF GETTING SFDS FROM LOGICAL NAME SPEC (WITH T1=PPN)
SETPT1:	PUSHJ	P,SAVE4##
	SETZB	P1,P2		;NO SCAN, NO FORBIDDEN NMB
	DPB	P1,DEYSCN##	;CLEAR SCAN SWITCH
	PUSHJ	P,PPNXWD	;SAVE PPN IN DDB
	SETOM	DEVFIL(F)	;DON'T CALL FNDFIL IF 1ST SFD IS ZERO
	PJRST	SETPT7		;AND KEEP ON TRUCKIN
SETPT2:
SETPT3:	PUSHJ	P,SAVE4##
	MOVE	P2,T1		;SAVE FORBIDDEN NMB LOC
	HRRZ	T1,M
	PUSHJ	P,SETP16	;ADDRESS CHECK ARGUMENTS (MIGHT GET EUE
	MOVE	T3,M		;GET SET TO ADDRESS-CHECK THE ARGUMENTS
	MOVE	T2,SFDLVL##	;GET MAX. NUMBER OF SFD'S
	HRRI	M,1(M)		;GO TO WORD BEFORE FIRST SFD
SETPT4:	MOVEI	T1,1(M)		;GET ADDRESS OF NEXT SFD
	PUSHJ	P,SETP16	;ADDRESS-CHECK IT
	PUSHJ	P,GETWD1##	;GET SFD SPEC ITSELF
	SKIPE	T1		;HIT ZERO?
	SOJGE	T2,SETPT4	;NO, GO UNTIL SFD LVL IS REACHED
	MOVE	M,T3		;RESTORE M
	PUSHJ	P,GETWD1##
	ANDI	T1,3
	MOVE	P1,T1		;SCANNING SWITCH
	AOSN	DEVNAM(F)	;DEVNAM=-1?
	TROA	P1,400000	;YES, P1 WILL BE NEGATIVE
	SOSA	DEVNAM(F)	;NO, RESET DEVNAM
	JRST	SETPT6		;WANT ALL OF WORD IF LIB
	JUMPN	P1,SETPT5	;IF NO CHANGE,
	MOVE	P1,JBTSFD##(J)	;GET OLD VALUE
	ANDI	P1,JBPSCN##
	JRST	SETPT6
SETPT5:	CAIE	T1,2		;IF HE IS SPECIFYING IT
	TDZA	P1,P1		;2 MEANS NO SCAN,
	MOVEI	P1,JBPSCN##	;OTHERWISE SCAN
SETPT6:	HRLZS	P1		;SAVE IN LH(P1)
	DPB	P1,DEYSCN##	;SCAN SWITCH=0 FOR NOW
	HLLZS	DEVSFD##(F)	;START AT UFD
	PUSHJ	P,PPNPP0	;GET PPN
	MOVEM	T1,DEVPPN(F)	;SAVE AS PPN
	SKIPN	DEVNAM(F)	;IF NOT SETTING LIB,
	JRST	SETPT7
	PUSHJ	P,PUTWRD##	;TELL USER
	  JRST	ADRERR##	;CANT STORE IN PROTECTED JOB DATA AREA
SETPT7:	TLO	M,UUOLUK	;INDICATE LOOKUP
	MOVSI	T1,(SIXBIT .SFD.)
	MOVEM	T1,DEVEXT(F)	;PREPARE TO LOOKUP SFD'S
	PUSH	P,DEVUNI##(F)	;SAVE DEVUNI (FNDFIL WILL CHANGE IT)
	SKIPN	T1,DEVNAM(F)	;UFD IF DEVNAM ALREADY IS ZERO
	AOSA	DEVNAM(F)	;SET DEVNAM NON-ZERO
SETPT8:	JRST	[PUSHJ P,NXTSLN	;GET NEXT SFD IN LOGICAL NAME
		   PUSHJ P,GETWD1## ;NOT LOG NAME, GET USERS ARG
		 JRST .+1]
	SKIPE	DEVFIL(F)	;IF NOT 1ST TIME,
	JUMPE	T1,SETP12	; 0 TERMONATES THE LIST
	MOVEM	T1,DEVFIL(F)	;SAVE SFD NAME (0 MEANS UFD)

	MOVSI	P3,DEPPRV##	;DON'T CHECK PRIVS
	IORM	P3,DEVPRV##(F)	; IN LOWER SFDS
	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST
	  JRST	SETP14		;NONE - ERROR
	MOVE	T2,T1
				;SO CHK PRV WONT BE CALLED
	MOVE	P4,S		;SAVE IOSRDC
	PUSHJ	P,FNDFIL##	;LOOKUP NAME.SFD
	  JRST	SETP14		;NOT FOUND
	TLNN	P4,IOSRDC
	TLZ	S,IOSRDC	;IOSRDC IS FOR FILE, NOT SFD
	MOVEM	S,DEVIOS(F)	; SO CLEAR IT
	ANDCAM	P3,DEVPRV##(F)
	PUSHJ	P,SFDDEC	;DECR NMB USE-COUNT
	SKIPN	DEVFIL(F)	;LOOKING FOR UFD?
	JRST	SETP10		;YES
				;NO, FALL INTO NEXT PAGE
;HERE WHEN NAME.SFD WAS FOUND BY FNDFIL
	PUSHJ	P,DECSFD	;DECREMENT USE-COUNTS OF OLD SFD
	PUSHJ	P,GETNMB	;FIND NMB FOR NEW SFD
	CAMN	T1,P2		;THE FORBIDDEN NMB?
	JRST	SETP13		;YES, ERROR
	HRRM	T1,DEVSFD##(F)	;SAVE AS CURRENT SFD
	PUSHJ	P,INCSFD	;INCREMENT ITS USE-COUNTS
	SKIPL	T1,DEVNAM(F)	;IF DEVNAM IS A POSITIVE NUMBER
	TLNE	T1,-1
	JRST	SETPT9
	SOSG	DEVNAM(F)	;DECR BY 1
	AOJA	P1,SETP12	;DONE ALL HE ASKED FOR - RETURN
SETPT9:	MOVEI	T1,1(P1)	;COUNT LEVEL UP
	CAIGE	T1,MAXLVL##	;TOO HIGH?
	AOJA	P1,SETPT8	;NO, TRY NEXT NAME IN USERS LIST
	AOJA	P1,SETP12	;YES, DONE

;HERE ON GOOD RETURN FROM FNDFIL WITH DEVFIL=0 (LOOKING FOR UFD)
SETP10:	HRRZ	T1,DEVACC##(F)	;SAVE DEVACC (LOC OF UFB)
	TLZE	P1,400000	;SETTING LIB?
	TSOA	T1,P1		;YES, COPY SYS AND NEW BITS
	TRO	T1,JBPUFB##	;NOT LIB, INDICATE UFD
	HRRM	T1,DEVSFD##(F)	;SAVE IN DDB
SETP12:	HLRZS	P1		;SCAN SWITCH
	DPB	P1,DEYSCN##	;SAVE IN DDB
	POP	P,DEVUNI##(F)	;RESTORE DEVUNI
	HRRZ	U,DEVUNI##(F)	; AND U
	HLLZS	T2,DEVACC##(F)	;WANT TO RECOMPUTE PROTECTION
	DPB	T2,DEYFNC##	; SO SET THE BYTE=0
	PJRST	CPOPJ1##	;AND TAKE GOOD RETURN

;HERE ON ERROR RETURN FROM SETSRC OR FNDFIL
SETP13:	HRRZ	T1,DEVACC##(F)	;DECREMENT FAILING SFD'S
	PUSHJ	P,DECONE	; USE COUNT
	JRST	SETP15
SETP14:	PUSHJ	P,DECSFD	;DECR USE COUNT
	PUSHJ	P,SFDDEC
SETP15:	HLLZS	DEVACC##(F)	;ZERO DEVACC
	ANDCAM	P3,DEVPRV##(F)
	POP	P,DEVUNI##(F)
	POPJ	P,		;AND ERROR RETURN
SETP16:	TRNE	T1,-20
	PUSHJ	P,UADRCK##
	POPJ	P,
;LOGICAL END OF SLSTR, PUT IN FILUUO WITH REST OF PATH STUFF
;FIXES UP ACCESS TABLES, ACCESS TABLE COUNTS WHEN AN STR IS ADDED TO S.L.
; AND THE DEFAULT PATH IS IN AN SFD
;WIPES OUT P1-P4, RETURNS CPOPJ1
;ENTER, EXIT WITH CB
ADJPT::	PUSHJ	P,SFDPPN	;% GET DEFAULT PATH
	JUMPE	T2,CPOPJ1##	;%NOTHING TO DO IF IT ISN'T AN SFD
	SETZB	P1,P3		;%
	PUSHJ	P,FAKDDB	;%GET A DDB TO WORK WITH
	  JRST	ADJPT6		;%NO FREE CORE, HOPE FOR THE BEST
ADJPT1:	PUSHJ	P,SFDPPJ	;%GET DEFAULT SFD
	JUMPN	P1,ADJPT2	;%IF FIRST TIME,
	HRLI	M,UUOLUK	;%INDICATE LOOKUP
	EXCH	P3,F		;%ZERO F CAUSE WE ALREADY HAVE CB
	PUSHJ	P,DECALL	;%DECREMENT USE-COUNTS IN CURRENT SFD A.T'S
	MOVE	F,P3		;%RESTORE F
	MOVEM	T4,DEVPPN(F)	;%SAVE PPN
	MOVSI	T2,'SFD'	;%SAVE EXTENSION
	MOVEM	T2,DEVEXT(F)
ADJPT2:	CAIN	P1,(T1)		;%ARE WE AT DEFAULT PATH?
	JRST	ADJPT5		;%YES, FINISH UP
	MOVE	T2,T1		;%NO, SAVE CURRENT SFD
ADJPT3:	HLRZ	T1,NMBPPB##(T1)	;%SEARCH FOR ITS FATHER SFD (OR UFD)
	TRZN	T1,NMPUPT##
	JUMPN	T1,ADJPT3
	CAIN	T1,(P1)		;%ARE WE THERE?
	JRST	ADJPT4		;%YES
	MOVE	T2,T1		;%NO, SAVE THIS AS CURRENT
	JUMPN	T1,ADJPT3	;%AND FIND ITS FATHER
	JRST	ADJPT7		;%SYSTEM ERROR
ADJPT4:	HRRM	T1,DEVSFD##(F)	;%SAVE FATHER SFD
	MOVE	T1,(T2)		;%GET NAME OF CURRENT SFD
	MOVEM	T1,DEVFIL(F)	;%SAVE IT FOR FNDFIL
	MOVE	T2,ALLSRC##
	MOVE	P2,JBTSFD##(J)
	HLLZS	JBTSFD##(J)	;%DON'T WANT FILFND TO MESS WITH SFDS
	PUSHJ	P,FNDFLA##	;%GO LOOKUP THIS SFD
	  JRST	ADJPT8		;COULDN'T?
	MOVE	J,.CPJOB##
	MOVEM	P2,JBTSFD##(J)	;RESTORE DEFAULT SFD
	PUSHJ	P,GETNMB	;GET NMB, AT FOR THIS SFD
	HRRM	T1,DEVSFD##(F)	;SAVE SFD NMB LOC
	HRRZ	P1,T1		;SAVE WHERE WE ARE NOW
	PUSHJ	P,SFDEC		;DECREMENT PPB,NMB CNTS WHICH FILFND INCR'D
	PUSHJ	P,GETCB##
	MOVNI	T1,ACPCNT##	;%DECREMENT USE-COUNT
	ADDM	T1,ACCCNT##(T2)	;%IN CURRENT AT
	JRST	ADJPT1		;%AND GO LOOKUP NEXT SFD (IF NOT UP TO DEFAULT)
;HERE WHEN "REAL" SFD HAS BEEN LOOKED UP
ADJPT5:	HRRZ	T1,DEVSFD##(F)	;%CURRENT SFD (=DEFAULT)
	SETZ	F,		;%CAUSE WE HAVE CB
	PUSHJ	P,INCALL	;%BUMP USE-COUNTS IN ALL AT'S
	MOVE	F,P3
	PUSHJ	P,CLRDDB	;%RETURN THE DDB
ADJPT6:	SETZ	F,
	JRST	CPOPJ1##	;%AND GOOD RETURN

;HERE WHEN FILE.SFD CANT BE FOUND
ADJPT8:	PUSHJ	P,GETCB##	;GETCB BACK
ADJPT7:	MOVE	J,.CPJOB##
	HLLZS	JBTSFD##(J)	;%CLEAR DEFAULT SFD
	PJRST	ADJPT6		;%AND FINISH UP
;ROUTINE TO FIX THE ACC USE COUNT
;BUMPS THE COUNT ONCE FOR EACH JOB THAT HAS HIS PATH SET TO THE SFD
;T1 PASSES ADDR OF NMB
;T2 PASSES ADDR OF ACC
;PRESERVES ALL AC'S
FIXPTH::PUSHJ	P,SAVE3##	;PRESERVES AC'S
	HLRZ	P1,NMBRNG##(T1)	;ONLY IF SFD
	JUMPE	P1,CPOPJ##
	MOVE	P1,HIGHJB##	;SET UP LOOP
	MOVEI	P3,ACPCNT##
FXPTH1:	HRRZ	P2,JBTSFD##(P1)	;IS HIS PATH HERE?
	TRZ	P2,CORXTR##
	CAMN	P2,T1
	ADDM	P3,ACCCNT##(T2)	;YES, BUMP COUNT
	SOJG	P1,FXPTH1	;TEST EACH JOB
	POPJ	P,
;SUBROUTINE TO INCREMENT/DECREMENT THE USE-COUNT OF AN SFD A.T.
;ENTER WITH T1=LOC OF THE A.T.
;ENTER WITH F=0 IF HAVE CB
;EXIT T1=LOC OF THE A.T.
INCONE:	SKIPA	T2,[EXP ACPUSE##];SET TO INCR. COUNT
DECONE::MOVNI	T2,ACPUSE##	;SET TO DECR COUNT
	PUSHJ	P,GETCBX##
	ADDM	T2,ACCUSE##(T1)	;%UPDATETHE USE COUNT
	JUMPGE	T2,INCON2	;%
	MOVE	T2,ACCUSE##(T1)	;%IF DECREMENTING,
	TRNN	T2,ACMUCT##+ACPREN+ACPCRE	;%IF NOW UNUSED,
	SKIPE	ACCDOR##(T1)	;%
	PJRST	GVCBJX##	;%
	PJRST	ATSDRA##	;%MAKE THE A.T. DORMANT
INCON2:	SKIPN	T2,ACCDOR##(T1)	;%IF INCREMENTING,
	PJRST	GVCBJX##	;%
	EXCH	T1,T2		;%
	PUSHJ	P,UNLINK##	;%MAKE UNDORMANT IF IT WAS DORMANT
	MOVE	T1,T2		;%
	PJRST	GVCBJX##	;%


;SUBROUTINE TO INCREMENT/DECREMENT THE A.T. OF THE FATHER SFD FOR A FILE
INCUSA:	SKIPA	T1,INCLOC
DECUSA:	MOVEI	T1,DECONE
	PUSH	P,T1		;WHERE TO GO
	PUSHJ	P,UFORSS##	;FIND UFB OR SFD A.T.
	TRZN	T2,NMPSFU##	;SFD?
	PJRST	TPOPJ##		;NO, RETURN
	MOVE	T1,T2		;YES, A.T. LOC INTO T1
INCLOC:	POPJ	P,INCONE	;GO INCR OR DECR THE USE-COUNT
;SUBROUTINE TO INCREMENT ALL A.T.'S FOR AN SFD
;ENTER WITH T1=LOC OF SFD NMB
;EXIT WITH T1=LOC OF SFD NMB
;ENTER WITH F=0 IF HAVE CB
INCALL:	SKIPA	T2,INCLOC
DECALL::MOVEI	T2,DECONE
	PUSH	P,F
	PUSHJ	P,GETCBX##	;GET CB IF DONT HAVE IT ALREADY
	SETZ	F,		;INDICATE NOW HAVE CB
	PUSH	P,T2		;WHERE TO GO
	HLRZ	T1,NMBACC##(T1)	;1ST A.T. LOC
DECAL1:	TRZE	T1,DIFNAL##	;BACK TO THE NMB?
	JRST	DECAL2		;YES, FINISH UP
	HRL	T1,ACCSTS##(T1)	;STILL BEING CREATED?
	TLNN	T1,ACPCRE
	PUSHJ	P,@(P)		;NO, GO INCR OR DECR
	HLRZ	T1,ACCNMB##(T1)	;STEP TO NEXT A.T.
	JRST	DECAL1		;AND DO IT
DECAL2:	POP	P,(P)		;REMOVE GARBAGE FROM PD LIST
	POP	P,F		;RESTORE F (MAY STILL BE 0)
	PJRST	GVCBJX##	;RETURN CB IF GOT IT ABOVE
;SUBROUTINE TO DECREMENT ALL A.T.'S FOR THE FATHER SFD EXCEPT
; THE ONE FOR THE STR ON WHICH THE FILE ACTUALLY IS
;(NEEDED SINCE SETLER INCREMENTS ALL A.T.'S, BUT AFTER THE LOOKUP/ENTER
; PICKS AN STR, ONLY THAT A.T. SHOULD HAVE ITS COUNT UP)
DECMST:	PUSHJ	P,UFORSF##	;FIND SFD A.T. OR UFB
	  JRST	DECMS1
	TRZN	T2,NMPSFU##	;SFD?
	POPJ	P,		;NO
	MOVE	T1,T2		;YES, GET ITS LOC IN T1
	PUSHJ	P,INCONE	;INCR ITS USE-COUNT (DECSFD WILL DECR ALL AT'S)

				;AND FALL INTO DECSFD

;SUBROUTINE TO DECREMENT ALL A.T.'S FOR THE FATHER SFD
DECSFD:	HRRZ	T1,DEVSFD##(F)	;LOC OF SFD NMB
	JUMPE	T1,CPOPJ##
	PJRST	DECALL		;DECR ALL A.T. COUNTS


;SUBROUTINE TO INCREMENT ALL SFD'S FOR THE FATHER SFD EXCEPT C(DEVACC)
;NEEDED SINCE FNDFIL INCREMENTS THE USE-COUNT OF THE 1ST SFD A.T. IN THE RING
; WHEN A LOOKUP IS DONE ON THE SFD
INCSFD:	HRRZ	T1,DEVSFD##(F)	;L(NMB)
	PUSHJ	P,INCALL	;INC ALL USE-COUNTS
	HRRZ	T1,DEVACC##(F)	;THEN DECR THE RIGHT ONE
	PJRST	DECONE

;HERE IF NO SFD AT WAS FOUND
DECMS1:	HLLZ	T2,DEVSFD##(F)	;RENAMING ACCROSS SFD's?
	JUMPN	T2,CPOPJ##	;YES, THIS IS OK
	PJRST	BNTSTP##	;NO, CRASH
;ROUTINE TO EXTRACT INFORMATION ABOUT THE DEFAULT SFD AND PPN
;ENTER AT SFDPPJ IF J IS NOT SET UP (GET FROM DDB)
;ENTER AT SFDPPN IF J=JOB NUMBER
;ENTER AT SFDPP1 WITH T1=LOC OF SFD
;EXIT CPOPJ WITH T4=PPN
;T3=JBPUFB & JBPSCN BITS
;T2=0 IF NO DEFAULT OR DEFAULT IS A BARE UFD, ELSE = L(SFD NMB)
;T1=JBTSFD, WITH EXTRANEOUS BITS =0
;LH(T1)= L(PPB) IF A DEFAULT IS GIVEN (RH(T1) NOT 0)
SFDPPJ:	LDB	J,PJOBN##	;JOB NUMBER
SFDPPN:	HRRZ	T1,JBTSFD##(J)	;LOC OF DEFAULT SFD
SFDPP1:	SETZB	T2,T3
	JUMPE	T1,SFDPP2	;RETURN PPN IF NO DEFAULT
	LDB	T3,SFYSCU##	;JBPUFB & JBPSCN
	TRZ	T1,CORXTR##	;ZERO EXTRANEOUS BITS
	HRLS	T1		;LH(T1)=L(PPB) IF JBPUFB=1
	TRNE	T3,JBPUFB##	;IS IT A UFB?
	SKIPA	T4,PPBNAM##(T1)	;YES, T4=PPN
	SKIPA	T2,T1		;NO, T2=L(SFD NMB)
	POPJ	P,		;RETURN IF A UFB
	HLRZ	T4,NMBACC##(T1)	;L(1ST A.T. IN RING)
	TRNE	T4,DIFNAL##	;IS THERE AN A.T.?
	JRST	SFDPP2		;NO. SYSTEM ERROR?
	MOVE	T4,ACCPPB##(T4)	;YES, GET L(PPB)
	HRL	T1,T4		;SAVE IN LH(T1)
	SKIPA	T4,PPBNAM##(T4)	;SET T4=PPN
SFDPP2:	MOVE	T4,JBTPPN##(J)	;PPN=JOB'S PPN
	POPJ	P,
;SUBROUTINE TO SEE IF THIS IS THE ONLY USER OF A PPN
;CALL WITH T1=PPN, J=JOB NUMBER
;EXITS POPJ IF THERE IS ANOTHER JOB WITH THIS PPN, OR SOME JOB
; HAS A DEFAULT PATH IN THIS PPN
;EXITS CPOPJ1 IF NO OTHER JOB IS USING PPN
;EXITS UNDER THE NOSCHED MACRO, WITH T1=PPN
ONLYTS:	CAME	T1,SYSPPN##	;IF CUSP
	CAMN	T1,MFDPPN##	; OR MFD
	POPJ	P,		;PRETEND STILL LOGGED IN
	CAMN	T1,SPLPPN##	;IF QUEUE AREA
	POPJ	P,		; PRETEND STILL LOGGED IN
	PUSHJ	P,SAVE1##
	PUSH	P,J		;SAVE J
	NOSCHEDULE
	MOVE	P1,T1		;SAVE PPN
	MOVE	J,HIGHJB##
ONLYT1:	CAMN	J,(P)		;DON'T TEST THE JOB FOR WHICH WE'RE LOOKING
	JRST	ONLYT3
	HLRZ	T1,JBTSFD##(J)	;LOC OF LIB
	TRZ	T1,CORXTR##	;ZAP THE EXTRA BITS
	SKIPE	T1		;0 IF NO LIB
	MOVE	T1,PPBNAM##(T1)	;PPN
	CAMN	T1,P1		;IS IT THE RIGHT ONE?
	JRST	ONLYT2		;YES, NON-SKIP RETURN
	PUSHJ	P,SFDPPN	;GET DEFAULT PPN
	CAME	P1,T4		;IS IT THIS PPN?
	CAMN	P1,JBTPPN##(J)	;IS IT JOB'S PPN?
ONLYT2:	SOSA	-1(P)		;YES, SET FOR NON-SKIP RETURN
ONLYT3:	SOJG	J,ONLYT1	;NO, TEST NEXT JOB
	POP	P,J		;RESTORE J
	MOVE	T1,JBTPPN##(J)	; AND PPN
	PJRST	CPOPJ1##	;TAKE SKIP OR NON-SKIP RETURN
;SUBROUTINE TO CLEAN UP WHEN CHANGING DEFAULT SFD'S FROM ONE PPN TO ANOTHER
;ENTER WITH T1= OLD PPN, P2=LOC(PPB) - AS RETURNED BY SFDPPN
;ENTER AT PTHCHX IF THIS JOB SHOULD BE LOOKED AT
;(E.G. CHANGING LIB, BUT DEFAULT PATH FOR THAT PPN EXISTS)
PTHCHX:	SETZ	J,
PTHCHG:	PUSHJ	P,ONLYTS	;ANY OTHER JOB WITH THIS PPN?
	  JRST	[LDB J,PJOBN##	;YES, RETURN
		 POPJ P,]
	PUSHJ	P,GTMNBF##	;NO, GET A MON-BUF
	MOVE	T1,PPBNAM##(P2)	;PPN
	MOVEM	T1,DEVPPN(F)	;SAVE IN DDB
	AOS	PPBCNT##(P2)	;PROTECT AGAINST OTHER CLOSERS
	MOVEI	T1,PPPNLG##	;INDICATE PPN NOT LOGGED-IN
	ANDCAM	T1,PPBNLG##(P2)
	HLRZ	T1,PPBUFB##(P2)	;LOC OF 1ST UFB
	JUMPE	T1,PTHCH2
PTHCH1:	HRRM	T1,DEVUFB##(F)	;SAVE IN DEVUFB
	LDB	T1,ACZFSN##	;STR NUMBER
	MOVE	T1,TABSTR##(T1)

	HLRZ	U,STRUNI##(T1)	;SET U TO 1ST UNIT IN STR
	PUSHJ	P,STOAU##	;SAVE IN DDB
	PUSHJ	P,LOGTS1	;GO REWRITE UFD WITH NEW QUOTAS
	MOVE	T1,DEVUFB##(F)	;STEP TO NEXT UFB
	HLRZ	T1,UFBPPB##(T1)
	JUMPN	T1,PTHCH1	;REWRITE IT
PTHCH2:	SCHEDULE
	SOS	PPBCNT##(P2)
	PUSHJ	P,TSTPP1	;DELETE THE 4-WORD CORE BLOCKS FOR THE PPB
	LDB	J,PJOBN##	;RESTORE JOB NO
	POPJ	P,		;AND EXIT
SUBTTL	RENAME

RENAM:	PUSHJ	P,NULTST	;ON DEVICE NUL
	  PJRST	CPOPJ1##	;RENAME WINS
	MOVE	T1,DEVLIB##(F)	;IF FILE NOT IN UFD, BUT IN LIB
	TLNE	F,LOOKB		; MAKE RENAME ILLEGAL
	TLNN	T1,DEPLIB##	; (ERROR 0 IF LOOKUP FAILED)
	SKIPN	DEVFIL(F)	;IS THERE AN OPEN FILE?
	JRST	RENER4		;NO. ERROR RETURN
	TLNE	S,IOSWLK	;STR WRITE LOCKED?
	JRST	RENER3		;YES. ERROR RETURN
RECLSD:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	TLZ	M,UUOMSK	;ZERO INDICATOR BITS IN M
	MOVE	P2,M		;SAVE ORIGINAL ADDRESS
	PUSHJ	P,GTWST2##	;GET 1ST WORD
	JUMPE	T1,RENAM1	;RENAMING TO ZERO
	TLNE	T1,-1		;EXTENDED UUO?
	JRST	RENAM1		;NO
	MOVE	P3,T1		;YES, SAVE NUMBER OF ARGS
	TLO	P2,EXTUUO	;SET EXTENDED BIT
	HRRI	M,UUXNAM(M)	;POINT TO FILENAME
	PUSHJ	P,GTWST2##	;GET IT
RENAM1:	TLNE	F,LOOKB+ENTRB	;DOES HE HAVE A FILE OPEN?
	JRST	RENAM2		;YES
	HRRZS	T3,DEVSFD##(F)	;NO, WAS PREVIOUS FILE IN AN SFD?
	JUMPE	T3,RENAM2	;NOT SFD, LET HIM DO IT
	PUSHJ	P,SFDPPN	;WE CAN'T BE SURE THAT THE NMB  DEVSFD
	HRRZM	T2,DEVSFD##(F)	; POINTS TO IS STILL THERE, SO FORGET
	MOVEM	T4,DEVPPN(F)	; DEVSFD AND USE DEFAULT PATH INSTEAD
	PUSHJ	P,SFDUP		;BUMP PPBCNT AND NMBCNT
RENAM2:				;FALL INTO NEXT PAGE
	TLNN	F,ENTRB		;AN ENTER BEEN DONE?
	JRST	RENAM3		;NO

;HERE ON A RENAME WITH AN OPEN OUTPUT FILE - HAVE TO CLOSE IT
;SINCE WE WILL NEED THE DDB POINTER SPACE TO READ THE UFD
	HRRI	M,0		;THESE BITS MEAN THINGS TO CLOSE
	TLNE	F,LOOKB		;CREATE OR UPDATE?
	SETO	T1,		;UPDATE, CLSRST WON'T MAKE IT GO AWAY
	SKIPN	T1		;DELETE A CREATE?
	TROA	M,CLSRST	;YES, TELL CLOSE NOT TO ENTER IN UFD
	PUSHJ	P,SFDUP		;NO, BUMP THE COUNTS SO THAT THE BLOCK
				; DEVSFD POINTS TO WON'T GO AWAY WHILE THE
				; FILE IS CLOSED.
	PUSH	P,DEVUPP##(F)	;SAVE "IN YOUR BEHALF" PPN
	PUSHJ	P,CLOSE1##	;CLOSE THE FILE
	POP	P,DEVUPP##(F)	;RESTORE PPN THAT CLOSE1 BLEW AWAY
	TRNE	M,CLSRST	;DELETE A CREATE?
	JRST	CPOPJ1##	;YES, ALL DONE
RENAM3:	MOVE	M,P2		;RESTORE ORIGINAL ADDRESS
	PUSHJ	P,WAIT1##
	PUSHJ	P,DDBZR		;OUTPUT CLOSE WANTS TO CALL DD2MN
	TLO	M,UUOLUK	;INDICATE LOOKUP FOR FNDFIL
	HLRZ	U,DEVUNI##(F)	;SET U IN CASE DON'T GO TO FNDFIL
	JUMPE	U,RENM3A	;U MAY BE ZERO IF RENAME AFTER CLOSE (MAYBE LEGAL)
	PUSHJ	P,CHEKU##	;CHECK IF STR YANKED
	  JRST	RENER5		;PRETEND FILE NOT FOUND
RENM3A:	HRRZ	P2,DEVACC##(F)	;LOC OF ACCES BLOCK
	JUMPN	P2,RENAM5	;DON'T HAVE TO LOOKUP IF THERE
	PUSHJ	P,SETSRC##	;SET UP SEARCH LIST
	  POPJ	P,		;NULL LIST - SHOULD NEVER HAPPEN
	MOVE	T2,T1		;SEARCH LIST INTO T2

	PUSHJ	P,FNDFIL##	;SET UP AN ACCESS BLOCK FOR IT
	  JRST	RENER5
	PUSHJ	P,INCUSA	;INCREMENT USE-COUNT OF FATHER SFD
	PUSH	P,DEVUFB##(F)	;SAVE DEVUFB IN CASE OF FAILURE

	PUSHJ	P,RENAM4	;AND GO DO REST OF RENAME
	  PJRST	REFAIL		;ERROR - FIX UP ACCESS TABLE
				;(UUOCON WONT DO A CLOSE SINCE THE RENAME FAILED)
	PJRST	TPOPJ1##	;GOOD RETURN
;HERE ON RENAME FAILURE
REFAIL:	TLZ	S,IOSRIB	;INVALIDATE RIB IN MONITOR BUFFER (SECURITY)
	POP	P,DEVUFB##(F)	;RESTORE DEVUFB
	HRRZ	T1,DEVACC##(F)
	JUMPE	T1,CLOSIN
	PUSHJ	P,CLSNAM
	PJRST	CLOSIN		;FIX ACCESS TABLE AND EXIT


RENAM4:	TLO	F,LOOKB		;SET SO CLOSE INPUT WILL HAPPEN
	TLZ	F,OCLOSB+ICLOSB
	SKIPA	P2,DEVACC##(F)	;LOC OF A.T. INTO P2

RENAM5:	PUSHJ	P,CLSNAM	;GET REAL NAME OF FILE (IN CASE OF UNSUCCESSFUL
				; RENAME DEVFIL, DEVEXT ARE WRONG)
	HRRZ	T2,ACCNDL##(P2)	;NO-DELETE WORD
	TRNE	T2,ACPNDL##	;IS THIS A MAGIC FILE?
	MOVSI	T2,-1		;YES, NOT EVEN [1,2] CAN DELETE IT
	TLNE	M,EXTUUO	;EXTENDED UUO?
	HRRI	M,UUXNAM(M)	;YES, POINT TO FILENAME
	PUSHJ	P,GTWST2##	;GET FILENAME
	JUMPN	T1,RENA11	;GO IF NOT DELETE
;HERE WHEN RENAMING A FILE TO 0 (DELETING)
	JUMPL	T2,RENE16	;NDL FILE IF T2 NEG
	PUSHJ	P,ZDYFNC	;ZERO DEYFNC
	MOVEI	T1,FNCDEL##	;CAN USER DELETE FILE?
	PUSHJ	P,CHKPRV##
	  JRST	RENE16		;NO. ERROR RETURN
	MOVE	T2,ACCDIR##(P2)	;IS FILE A DIRECTORY?
	TRNN	T2,ACPDIR##
	JRST	DIRDL4		;NO
	MOVE	T2,ACCSTS##(P2)	;YES, GET USE-COUNT
	TRNE	T2,ACMUCM##	;IS COUNT=1 (FOR THIS READER)?
	JRST	DIRDL2		;NO, CANT DELETE
	MOVE	T2,ACCPT1##(P2)	;YES, GET RETRIEVAL INFO
	MOVE	T1,ACCUN1##(P2)
	PUSHJ	P,SETFS0##	;SET UP TO READ THE DIRECTORY
	  JRST	DIRDL2
	PUSH	P,DEVSFD##(F)	;SAVE L(SFD)
	PUSHJ	P,GETNMB	;GET L(NMB)
	HRRM	T1,DEVSFD##(F)	;SAVE AS DEVSFD
DIRDL1:	PUSHJ	P,DIRRED##	;READ A DIRECTORY BLOCK
	  JRST	DIRDL3		;EOF - IT'S EMPTY
	SKIPN	1(T1)		;GOT A BLOCK - EMPTY?
	JRST	DIRDL1		;YES, READ NEXT
	POP	P,DEVSFD##(F)	;RESTORE DEVSFD
DIRDL2:	MOVEI	T1,DNEERR	;DIR-NOT-EMPTY
	AOJA	M,PUTERR	;RETURN THE ERROR
DIRDL3:	POP	P,DEVSFD##(F)	;RESTORE DEVSFD
DIRDL4:	PUSHJ	P,UPAU##	;GET AU
	PUSHJ	P,GETCB##
IFN FTEQDQ,<
	HRRZ	T1,P2		;GET ACCESS TABLE ADDRESS
	MOVEI	T2,ACPNDR##	;NO DELETE ON RESET REQUESTED?
	TDNN	T2,ACCSTS##(T1)
	JRST	NONDR		;NO, FILE CAN BE DELETED
	PUSHJ	P,ENQNDR##	;DOES QUESER STILL NEED THIS FILE?
	  JRST	RENE19		;YES,IT CAN'T BE DELETED
	ANDCAM	T2,ACCSTS##(T1)	;CLEAR BIT NOW
NONDR:>
	MOVE	T1,ACCSTS##(P2)	;%STATUS OF FILE
	TRNE	T1,ACPUPD	;%FILE BEING UPDATED BY ANOTHER JOB?
	JRST	RENE17		;%YES, ERROR RETURN
	TROE	T1,ACPDEL##+ACPNIU	;%NO, FILE ALREADY MARKED FOR DELETION?
	JRST	RENAM9		;%YES, JUST CLOSE FILE
	MOVEM	T1,ACCSTS##(P2)	;%NO, SET FOR DELETE AFTER LAST READER CLOSES
	PUSHJ	P,GETNMB	;%GET LOC OF NMB
	MOVE	P1,T1		;%NMB LOC INTO P1
	LDB	T1,ACYFSN##	;%FSN

	PUSHJ	P,FSNPS2##	;%SET A BIT FOR THIS STR
	ANDCAM	T2,NMBYES##(P1)	;%INDICATE FILE ISNT IN THIS STR
	HLLZS	NMBCFP##(P1)	;%MAKE SURE A BAD CFP ISN'T LEFT AROUND
	HLRZ	T3,DEVEXT(F)	;GET EXTENSION
	CAIE	T3,'UFD'	;IS THIS A UFD?
	JRST	RENAM7		;%NO
	MOVE	P3,T2		;%YES. SAVE FSN BIT
	PUSHJ	P,GVCBJ##	;%GIVE UP CB RESOURCE
	PUSHJ	P,FNDUFB	;FIND UFB FOR THIS FILE
	  JRST	RENAM8		;NOT THERE
	SETZM	UFBPT1##(T2)	;%ZERO POINTER TO UFD
	ANDCAM	P3,PPBYES##(T1)	;%INDICATE UFD NO LONGER THERE
	SETZM	UFBWRT##(T2)	;% IN CASE UFD GETS RECREATED

RENAM7:	PUSHJ	P,GVCBJ##	;%GIVE UP CB
RENAM8:	PUSH	P,DEVUNI##(F)	;SAVE DEVUNI (DELNAM WILL CHANGE IT)
	PUSHJ	P,DELNAM	;REMOVE FILE NAME FROM UFD
	  PUSHJ	P,DWNAU##	;ANOTHER JOB MUST HAVE DELETED THE NAME
	POP	P,U		;RESTORE DEVUNI(FOR INPUT-CLOSE)
	PUSHJ	P,STOAU##
	TLZ	F,RENMB+ENTRB	;SO CLOSE INPUT WONT THINK CLOSE OUTPUT WILL HAPPEN
	TLZE	S,IOSRDC	;IS FILE READING?
	JRST	RENA10		;YES - LOOKUP, RENAME OR ENTER,CLOSE,RENAME DONE
	MOVEI	T1,ACPCNT##	;NO. ENTER, RENAME DONE - FAKE UP A.T.
	ADDM	T1,ACCCNT##(P2)	;SO CLOSIN WILL DELETE THE FILE
	JRST	RENA10
RENAM9:	PUSHJ	P,GVCBJ##	;%GIVE UP CB
	PUSHJ	P,DWNAU##	;GIVE UP AU
RENA10:	PUSHJ	P,CLOSRN	;GO FINISH UP FILE
	TLZ	F,LOOKB		;ZERO LOOKB SO A FOLLOWING ENTER WILL SUCCEED
	PUSHJ	P,JDAADR##	;GET CHAN NUM
	HLLM	F,(T1)		;UUOCON WONT SAVE LH(F)
	JRST	CPOPJ1##	;AND TAKE GOOD RETURN
;HERE TO RENAME A FILE TO SOMETHING (NOT DELETE)
RENA11:	JUMPL	T2,RENE16	;NDL FILE IF T2 NEG
	PUSHJ	P,TSTWRT	;CAN THIS FILE BE RENAMED?
	  JRST	RENE18		;NO, ALREADY BEING WRITTEN - FBMERR
	PUSH	P,M		;SAVE LOC OF NAME
	HRRI	M,UUXPRV-UUXNAM(M)	;POINT TO PROT WORD
	TRZ	P3,RB.BIT	;CLEAR NOISE BITS
	TLNN	M,EXTUUO	;EXTENDED UUO?
	MOVEI	P3,UUXPRV	;NO, THEN PRIV WORD IS ALWAYS THERE
	CAIGE	P3,UUXPRV	;IS PRIV WORD THERE?
	TDZA	T1,T1		;NO, DON'T CHANGE PRIVS
	PUSHJ	P,GETWDU##	;GET IT
	SKIPE	T1		;TRYING TO CHANGE IT?
	XOR	T1,ACCPRV##(P2)	;MAYBE, XOR WITH ORIGINAL PROT
	HLRZ	P1,DEVEXT(F)	;FNCCAT IS NEVER LEGAL FOR UFD
	CAIN	P1,'UFD'	;IS THIS THE UFD?
	TLO	T1,777000	;YES, TRY FNCCPR (IT'S SOMETIMES LEGAL)
	LDB	P1,[POINT 9,T1,8];GET 0 OR NEW PROT
	SKIPN	T1,P1		;IF 0 HE ISNT CHANGING PROT
	TROA	T1,FNCCAT##	; SO TEST TO SEE IF HE CAN CHANGE ATTS
	MOVEI	T1,FNCCPR##	;CHANGING PROT, SEE IF HE CAN
	PUSHJ	P,CHKPRV##	;LEGAL?
	  TLOA	P1,400000	;NO, P1 NEGATIVE
	SETZ	P1,		;YES, P1 0
	SKIPE	P1		;IF P1 IS NOT 0
	TLO	P1,200000	;CANT CHANGE PROTECTION, TRYING TO
	MOVE	M,(P)		;RESTORE LOC OF NAME
	HRRI	M,-1(M)		;POINT M TO PPN
	TLNN	M,EXTUUO	;EXTENDED-FORMAT ARG BLK?
	HRRI	M,UUNPPN-UUNNAM+1(M)	;NO, ADVANCE TO E+3
	HRLS	DEVSFD##(F)	;SAVE OLD DIRECTORY IN LH(DEVSFD)
	HRRZS	-1(P)		;SET LH (PD WRD) = 0 IF NO PATH GIVEN
	PUSHJ	P,GETWDU##	;GET PPN
	SKIPLE	P4,T1
	TLNE	P4,-1		;POINTER TO A PATH?
	JRST	RENA12		;NO
	HRRI	M,2(P4)		;YES. POINT TO PPN
	HRROS	-1(P)		;INDICATE A PATH IS GIVEN
	PUSHJ	P,GETWDU##	;GET PPN
	SKIPE	P4,T1		;SAVE PPN IN P4
RENA12:	SKIPG	P4		;IF NO PPN GIVEN,
	MOVE	P4,DEVPPN(F)	;USE SAME PPN AS LOOKED-UP FILE
	MOVE	T1,DEVNAM(F)	;DEVICE NAME
	PUSHJ	P,SDVTST	;ERSATZ?
	  JRST	RENA13		;NO
	SKIPLE	@SDVPPN##(T2)	;YES, IS THERE AN IMPLIED PPN?
	MOVE	P4,@SDVPPN##(T2) ;YES, USET IT IN SPITE OF WHAT E+3 SAYS
RENA13:	MOVE	T1,P4		;TELL USER THE PPN
	PUSHJ	P,PUTWDU##
	POP	P,M		;RESTORE LOC OF NAME
	MOVE	T4,M		;SAVE LOC OF NAME
	PUSHJ	P,GETWDU##
	CAMN	P4,DEVPPN(F)	;IF NOT CHANGING PPN
	TLNN	P1,200000	;IF TRYING TO CHANGE PROT AND CANT
	CAIA
	JRST	RENE15		;LOSE WITH PROT ERR
	CAMN	P4,DEVPPN(F)

	CAME	T1,DEVFIL(F)	;RENAMING TO SAME NAME?
	JRST	RENA14		;NO
	PUSHJ	P,GETWD1##	;GET EXTENSION
	TRZ	T1,-1
	HLLZ	T2,DEVEXT(F)	;OLD EXTENSION
	XOR	T1,T2
	SKIPL	(P)		;PATH SPECIFIED?
	JUMPE	T1,RENA22	;NO, JUMP IF EXTENSIONS MATCH
;HERE WHEN CHANGING NAME, EXTENSION, OR DIRECTORY
RENA14:	SKIPE	T1		;IF T1=0 THEN NAME,EXT AND PPN'S MATCH
	HRRZS	(P)		;WANT PDWORD  NEGATIVE ONLY IF ALL MATCH
	HRRI	M,1(T4)		;POINT TO EXTENSION
	PUSHJ	P,GETWDU##	;GET NEW EXTENSION
	HLRZ	T2,T1
	XOR	T1,DEVEXT(F)	;SAME AS OLD?
	TLNN	T1,-1
	JRST	RENA15		;YES, CONTINUE
	PUSHJ	P,EXTCK		;NO, RENAMING TO "UFD" OR "SFD"?
	  JRST	RENE14
	HLRZ	T2,DEVEXT(F)	;NO, RENAMING FROM "UFD" OR "SFD"?
	PUSHJ	P,EXTCK
	  JRST	RENE14
RENA15:	HRRI	M,-1(T4)	;POINT M TO UUXPPN
	TLNN	M,EXTUUO	;EXTENDED UUO?
	HRRI	M,1+UUNPPN-UUNNAM(M)	;NO. POINT TO PPN WORD
	CAMN	P4,DEVPPN(F)	;NEW PPN=OLD PPN?
	JRST	RENA16		;YES
	PUSHJ	P,GETNMB	;GET L(NMB)
	HLRZ	T1,NMBRNG##(T1)	;IS FILE IN AN SFD?
	JUMPN	T1,RENER7	;YES, CANT CHANGE PPN (ELSE ALL FILES IN SFD
				; WOULD HAVE TO CHANGE ALSO)
	MOVEI	T1,FNCDEL##	;CHANGING DIRECTORIES
	PUSHJ	P,CHKPRV##	;CAN JOB DELETE FROM OLD DIRECTORY?
	  JRST	RENER7		;DELETE FROM OLD DIR IS ILLEGAL
	MOVEM	P4,DEVPPN(F)	;SAVE NEW PPN IN DDB
	SETZB	T1,P4		;OK. WIPE OUT OLD HIGHEST FUNCTION
	DPB	T1,DEYFNC##	;(WANT TO RECOMPUTE IT FOR NEW DIRECTORY)
	MOVSI	T1,DEPRAD##	;RENAMING ACROSS DIRECTORIES
	IORM	T1,DEVRAD##(F)
;HERE WHEN RENAME HAS BEEN CHECKED (IF CHANGING DIRECTORIES)
RENA16:	HRL	P2,M		;SAVE LOC OF PPN
	HRRI	M,1(M)		;POINT TO NAME WORD AT E+2
	TLNN	M,EXTUUO	;EXTENDED FORMAT ARG BLK?
	HRRI	M,-<UUNPPN-UUNNAM+1>(M)	;NO, NAME AT E+0
	PUSH	P,M		;SAVE M
	HLR	M,P2		;POINT TO PPN
	PUSHJ	P,GTWST2##	;POINTING TO A PATH?
	SKIPLE	T1
	TLNE	T1,-1
	JRST	RENA19		;NO
	HRR	M,T1		;YES, PATH LOC INTO M
	HRRZ	P3,DEVACC##(F)	;SAVE DEVACC
	PUSHJ	P,GETNMB	;SET T1="FORBIDDEN" NMB LOC
				; (ELSE AN SFD COULD "SWALLOW" ITSELF)
	PUSH	P,DEVUFB##(F)	;SAVE DEVUFB (TO TELL IF RENAMING ACROSS DIRECTORIES)
	PUSH	P,DEVLNM##(F)	;SAVE THEE LOGICAL NAME POINTER
	PUSH	P,DEVNAM(F)	;SAVE THE DEVICE NAME
	HRRZ	T1,DEVLNM##(F)	;GET THE LOGICAL NAME POINTER IF ANY
	JUMPE	T1,REN16A	;SKIP THIS IF NO LOGICAL NAME
	SETZM	DEVLNM##(F)	;PRETEND THERE ISN'T ONE
	SKIPN	T1,LNRDEV##(T1)	;GET THE DEVICE NAME WE'RE USING
	MOVSI	T1,'DSK'	;NONE.  DEFAULT
	MOVEM	T1,DEVNAM(F)	;STORE THE REAL DEVICE NAME
REN16A:	PUSHJ	P,SETPT3	;SET UP NEW PATH
	  TLO	P3,-1		;ERROR
	POP	P,DEVNAM(F)	;RESTORE THE DEVICE NAME
	POP	P,DEVLNM##(F)	;RESTORE THE LOGICAL NAME POINTER
	POP	P,DEVUFB##(F)
	HRRM	P3,DEVACC##(F)	;RESTORE DEVACC
	JUMPL	P3,SETLE8	;GO IF AN ERROR
	HRRZ	T1,DEVSFD##(F)	;NEW SFD
	HLRZ	T2,DEVSFD##(F)	;OLD SFD
	CAME	T1,T2		;NEW SFD=OLD SFD?
	JRST	RENA17		;NO, THIS REALLY DOES CHANGE SOMETHING
	PUSHJ	P,DECSFD	;YES, SETPT3 COUNTED SFD USE-COUNT UP, SO
	PUSHJ	P,SFDDEC	; DECR IT
	SKIPL	-1(P)
	JRST	RENA20		;GO IF NAME, EXT, OR PPN ARE BEING CHANGED
	POP	P,(P)		;THIS ISN'T CHANGING NAME EXT OR DIRECTORY
	HLR	M,P2		;RESTORE AC'S AND DDB
	PUSHJ	P,CLSNM
	JRST	RENA23		;AND CONTINUE

;HERE ON A RENAME CHANGING SFD'S
RENA17:	PUSHJ	P,GTUFR		;SFD EXIST ON THIS STR?
	  SKIPA	T1,SETL10	;NO
	JRST	RENA18		;YES
	POP	P,M		;RESTORE M = LOC OF NAME
	AOJA	M,RENER9
RENA18:	PUSHJ	P,DECMST	;ADJUST USE-COUNTS
	JRST	RENA20
;HERE IF NO PATH IS GIVEN
RENA19:	JUMPN	P4,RENA20	;IF CHANGING PPN'S
	HLLZS	DEVSFD##(F)	; RENAME INTO THE UFD
RENA20:	POP	P,M		;RESTORE M
	PUSHJ	P,GETWDU##	;GET NAME
	MOVEM	T1,DEVFIL(F)	;SAVE IN DDB (FOR FNDFIL)
	PUSHJ	P,GETWD1##	;GET EXTENSION
	HLLM	T1,DEVEXT(F)	;SAVE IN DDB
	HLRZS	T1		;RENAMING AN SFD?
	CAIE	T1,'SFD'
	JRST	RENA99		;NO
	HLRZ	T2,DEVSFD##(F)	;YES, COUNT OLD LEVEL
	PUSHJ	P,CNTLV0
	PUSH	P,T1		;SAVE OLD LEVEL
	PUSHJ	P,CNTLVL	;COUNT NEW LEVEL
	POP	P,T2
	CAMLE	T1,T2		;CAN'T GO DEEPER
	JRST	RENER8
RENA99:	MOVE	P3,DEVUFB##(F)	;LOC OF UFB
	MOVE	P4,DEVUNI##(F)	;ADDR. OF UNIT DATA BLOCK
	PUSHJ	P,SETSRC##	;GET SEARCH LIST
	  PUSHJ	P,SLXBPT##	;STOPCD BPT IF NONE
	MOVE	T2,T1		;SL INTO T2

	TLC	M,UUOLUK+UUOREN	;ZERO UUOLUK, LIGHT UUOREN
	PUSHJ	P,FNDFIL##	;CHECK THAT NEW FILE NAME DOESN'T EXIST
	  JRST	RENA21		;NEW FILE NAME ALREADY EXISTS
	TLNE	M,UUOREN	;CHANGING DIRECTORIES?

	MOVEM	P3,DEVUFB##(F)	;NO, RESTORE LOC OF UFB
	MOVEM	P4,DEVUNI##(F)	;RESTORE LOC OF UNIT DATA BLOCK
	HLR	M,P2		;RESTORE LOC OF PPN
	MOVE	T2,UFBTAL##(P3)
	MOVE	T1,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,ACCALC##(T1)	;SIZE OF FILE
	CAME	P3,DEVUFB##(F)	;NEW UFD=OLD UFD?
	ADDM	T1,UFBTAL##(P3)	;NO. CHANGING DIRECTORIES
				;INCREASE AMOUNT OF ROOM LEFT IN OLD DIR
	JUMPL	T2,RENA24	;WAS QUOTA POSITIVE?
	SKIPGE	UFBTAL##(P3)	;YES, DID QUOTA BECOME HUGELY NEGATIVE?
	HRLOS	UFBTAL##(P3)	;YES (OVERFLOW). MAKE IT POSITIVE AGAIN

	JRST	RENA24		;AND CONTINUE
RENA21:	HRRM	P3,DEVUFB##(F)
	MOVEM	P4,DEVUNI##(F)	;IN CASE ANOTHER RENAME IS DONE
	MOVE	P2,DEVACC##(F)	;GET THE ACCESS TABLE
	MOVE	T2,ACCPPB##(P2)	;GET THE PPB
	MOVE	T2,PPBNAM##(T2)	;GET THE PPN
	MOVEM	T2,DEVPPN(F)	;YES, RESTORE OLD ONE
	JRST	RENER9		;GIVE USER THE ERROR CODE


;SUBROUTINE TO CHECK EXTENSIONS
;ENTER T2=EXTENSION
;RETURN CPOPJ IF "SFD" OR "UFD"
;RETURN CPOPJ1 OTHERWISE
;T4 PRESERVED
EXTCK:	CAIE	T2,(SIXBIT /UFD/)
	CAIN	T2,(SIXBIT /SFD/)
	POPJ	P,
	PJRST	CPOPJ1##
;HERE ON A RENAME WHEN THE NAME, EXTENSION AND DIRECTORY ARE NOT BEING CHANGED
RENA22:	HRRI	M,-1(T4)	;POINT TO UUXPPN
	TLNN	M,EXTUUO	;EXTENDED UUO?
	HRRI	M,1+UUNPPN-UUNNAM(M)	;NO. POINT TO PPN WORD
RENA23:	PUSHJ	P,GETCB##	;GET CB RESOURCE
	MOVE	T1,ACCSTS##(P2)	;% STATUS OF FILE
	TLC	M,UUOLUK+UUOREN	;%ZERO UUOLUK, LIGHT UUOREN
	TRNE	T1,ACPCRE+ACPSUP+ACPUPD	;%FILE BEING WRITTEN?
	TLNE	F,ENTRB		;%YES, BY THIS JOB?
	TROE	T1,ACPREN	;%RENAME IN PROGRESS?
	JRST	RENER2		;%YES, ERROR
	MOVEM	T1,ACCSTS##(P2)	;%NO. INDICATE RENAME IN PROGRESS
	PUSHJ	P,GVCBJ##	;%GIVE UP CB RESOURCE
	PUSH	P,P2
	PUSHJ	P,DECSU		;SET P2 TO PPB,,NMB
	AOS	NMBCNT##(P2)	;SINCE FNDFIL WONT BE CALLED
	HLRZS	P2		; WE MUST INCR COUNTS BY HAND
	AOS	PPBCNT##(P2)	; CAUSE CLOSE WILL DECR THEM
	POP	P,P2
	TLNE	S,IOSRIB	;PRIME RIB IN CORE?
	JRST	RENA25		;YES, NO NEED TO READ IT
RENA24:	PUSHJ	P,GTMNBF##	;GET A MONITOR BUFFER
	HLRZ	U,DEVUNI##(F)	;GET UNIT OF PRIME RIB
	PUSHJ	P,STORU##	;SAVE AS CURRENT UNIT
	PUSHJ	P,PRMRIB##	;SET UP TO READ PRIME RIB
	PUSHJ	P,MONRED##	;READ THE PRIME RIB
	JUMPN	T3,RENE13	;ERROR READING RIB IF T3 NON-ZERO
	MOVE	T3,RIBCOD##+1(T1)	;GET RIB CODE WORD
	CAIN	T3,CODRIB##	;IS IT A RIB?
	CAME	T2,RIBSLF##+1(T1)	;YES, RIGHT ONE?
	JRST	RENE13		;NO,ERROR
	TLO	S,IOSRIB	;INDICATE PRIME RIB IS IN CORE
	MOVEM	S,DEVIOS(F)	;SAVE IN DDB

;HERE WHEN WE HAVE THE MONITOR BUFFER, AND THE RIB IS IN IT
RENA25:	HRRZ	T1,.USMBF	;LOC OF MON BUFFER
	MOVE	T2,RIBNAM##+1(T1) ;GET OLD FILE NAME
	MOVEM	T2,DEVFIL(F)	;RESTORE IN DDB
	HLLZ	T2,RIBEXT##+1(T1)	;GET OLD EXTENSION
	HLLM	T2,DEVEXT(F)	;AND SAVE IN DDB
	MOVE	T2,RIBPPN##+1(T1)	;GET OLD PPN
	MOVEM	T2,DEVPPN(F)	;SAVE OLD PPN IN DDB
	PUSHJ	P,SETUFR	;SET UFD ADR INTO RIB
;HERE WITH THE RIB IN THE MON BUF, M POINTING TO PPN WORD
	HRRI	M,-1(M)
	TLNN	M,EXTUUO	;EXTENDED UUO?
	JRST	RENA26		;NO. POINT TO ATT WORD
	HRRI	M,-<UUXPPN-1>(M)	;POINT TO E
	PUSHJ	P,GETWDU##	;GET NO. OF ARGS
	TRZ	T1,RB.BIT	;CLEAR NOISE BITS
	HRR	P1,T1
	CAIGE	T1,RIBATT##	;SPECIFYING ATTRIBUTES?
	JRST	[JUMPG P1,RENA37	;OK IF CAN CHANGE ATT'S
		 HRRI	M,4(M)	;CAN'T - ERROR
		 JRST RENE12]
	HRRI	M,UUXPRV(M)	;MAYBE. POINT TO ATT WORD
RENA26:	HRRI	M,-1(M)		;POINT TO EXTENSION WORD
	PUSHJ	P,GETWDU##	;GET EXT. HIGH CREATION DATE
	LDB	P3,[POINT 3,T1,20]	;HIGH CREATION DATE
	MOVE	T1,.USMBF	;POINT TO MON BUF
	LDB	P4,[POINT 3,RIBEXT##+1(T1),20]	;HI CREATION DATE FROM RIB
	SUB	P4,P3		;P4=DIFFERENCE
	PUSHJ	P,GETWD1##	;GET ATTRIBUTES WORD
	MOVE	T2,T1		;
	HRRZ	T3,.USMBF	;LOC OF MON BUF (-1)
	SKIPN	P3		;IF HI CREATION DATE = 0
	JUMPE	T2,RENA30	; RIBATT = 0 MEANS NO CHANGE
	XOR	T2,RIBATT##+1(T3)	;COMPARE WITH RIB ATTR. WORD
	SKIPN	P4		;HI CREATION DATE THE SAME?
	JUMPE	T2,RENA30	;YES, ALL THE SAME IF T2=0
	TLNN	M,UUOREN	;CHANGING DIRECTORIES?
	JRST	RENA28		;YES, IT'S LEGAL

	TLNN	T2,777740	;IF PROTECTION AND MODE SAME
	TDNE	T1,[37,,-1]	;IF 0 LOW DATE
	JRST	RENA27		;NO, A CHANGE
	TLNN	M,EXTUUO	; AND NOT EXTENDED
	JUMPE	P3,RENA30	; AND HI DATE 0, WIN
RENA27:	TLNE	T2,777000	;IF CHANGING PROTECTION
	MOVEI	T1,FNCCPR##	;REMEMBER THAT
	JRST	RENA29		;WE ALREADY CHECKED FNCCAT OR FNCCPR
RENA28:	TLZ	P1,-1		;INDICATE NO PROT ERROR
RENA29:	HRRZ	T2,.USMBF	;LOC OF MON BUF
	PUSH	P,T1		;GET PRIVS FROM USER
	PUSHJ	P,GTWST2##
	LDB	T4,[POINT 4,T1,12]	;GET SPECIFIED I/O MODE
	MOVEI	T3,1		;GET A BIT TO POSITION
	LSH	T3,(T4)		;MAKE INTO MODE BIT
	LDB	T4,[POINT 4,RIBATT##+1(T2),12]	;GET VALUE FROM RIB
	TDNN	T3,DEVMOD(F)	;LEGAL MODE?
	DPB	T4,[POINT 4,T1,12]	;NO, OVERRIDE USER'S VALUE
	LDB	T4,[POINT 15,T1,35]	;CREATION DATE SUPPLIED?
	DPB	P3,[POINT 3,T4,23]
	MOVEI	T3,0
	SKIPE	T4		;IF NO CREATION DATE,
	CAMLE	T4,THSDAT##	; OR DATE TOO HIGH
	HRLOI	T3,37		;DON'T CHANGE THE CURRENT DATE
	ANDM	T3,RIBATT##+1(T2)	;CLEAR OLD PROTECTION (AND MAYBE LOW DATE)
	ANDCAM	T3,T1
	IORM	T1,RIBATT##+1(T2)	;STORE NEW VALUE(S)
	LSH	T4,-14
	SKIPN	T3		;IF CHANGING DATE,
	DPB	T4,[POINT 3,RIBEXT##+1(T2),20]	;SAVE HIGH CREATION DATE
	POP	P,T1		;RESTORE PROTECTION BYTE
	HLRZ	T3,DEVEXT(F)	;EXTENSION
	CAIN	T1,FNCCPR##	;CHANGING PROTECTION
	CAIE	T3,(SIXBIT /UFD/); OF A UFD?
	JRST	RENA30		;NO
	PUSHJ	P,FNDUFB	;YES. FIND UFB FOR FILE
	  JRST	RENA30		;NOT THERE
	PUSHJ	P,GTWST2##
	LDB	T1,[POINT 9,T1,8];%FOUND - GET PROTECTION
	MOVE	T4,T2		;%LOC OF UFB
	DPB	T1,UFYPRV##	;%SAVE NEW PROT IN UFB BLOCK
	PUSHJ	P,GVCBJ##	;%AND RETURN CB RESOURCE
RENA30:	TLZE	P1,-1		;PROT ERR? (CAN'T CHANGE ATT, NOT CHANGING PROT)
	PJSP	T1,RENE12	;YES, LOSE
	SETZ	P4,
	MOVSI	T1,DEPALW	;SPECIFYING ALLOCATION IN WORDS?
	CAIL	P1,UUXSIZ
	TDNN	T1,DEVJOB(F)
	JRST	RENA31		;NO
	PUSHJ	P,GETWD1##	;YES, GET IT
	MOVE	P4,T1		;SAVE IT
	TRNE	T1,BLKSIZ##-1	;PARTIAL BLOCK?
	ADDI	T1,BLKSIZ##	;YES, ACCOUNT FOR IT
	LSH	T1,MBKLSH##	;CONVERT TO BLOCKS
	HRRI	M,UUXALC-UUXSIZ(M) ;POINT AT "REAL" ALLOCATION WORD
	PUSHJ	P,PUTWDU##	;SAVE IN USER'S RENAME BLOCK
	JRST	RENA32		;AND CARRY ON
RENA31:	HRRI	M,UUXALC-UUXPRV(M) ;POINT TO ALLOCATION WORD
	TLNE	M,EXTUUO	;EXTENDED UUO?
	CAIGE	P1,UUXALC	;YES. CHANGING ALLOCATION?
	JRST	RENER1		;NO
	PUSHJ	P,GETWDU##	;SPECIFYING ALLOCATION?
RENA32:	SKIPLE	T2,T1
	CAMN	T2,ACCALC##(P2)	;YES. ALLOCATION SAME AS BEFORE?
	JRST	RENER1		;YES. NOT REALLY CHANGING IT
	MOVE	T3,ACCDIR##(P2)	;GET DIRECTORY WORD
	MOVEI	T1,FNCTRN##	;ASSUME TRUNCATING
	CAML	T2,ACCWRT##(P2)	;RIGHT ?
	SKIPA	T1,[FNCALL##]	;NO, ALLOCATE
	TRNN	T3,ACPDIR##	;DON'T ALLOW UFD TRUNCATION
	PUSHJ	P,CHKPRV##	;CHECK IT
	  JRST	RENE11		;CANT DO IT - ERROR
	MOVE	T1,ACCSTS##(P2)	;STATUS OF FILE
	TRNE	T1,ACMCNM##	;OTHER READERS?
	JRST	RENE10		;YES, CANT CHANGE ALLOCATION
	PUSHJ	P,GETWDU##	;OK. HIGHEST BLOCK HE WANTS
	MOVE	T2,T1
	SUB	T2,ACCALC##(P2)	;CHECK ALLOCATION OR DEALLOCATION
	JUMPL	T2,RENA33	;DEALLOCATING IF NEGATIVE
	PUSHJ	P,UPDALC	;ALLOCATING - GET MORE
	 JRST	ENERR7		;QUOTA EXCEEDED
	  JRST	RENE20		;CANT START WHERE SPECIFIED - ERROR
	PUSHJ	P,UPDSET	;UPDATE DEYRLC FOR NEW POINTERS STORED IN RIB
	PUSHJ	P,CHKPAR	;STORE ERROR WORD IF PARTIAL ALLOCATION
	JRST	RENER1		;AND CONTINUE
;STILL IN CONDITIONAL ON FTDALC
;HERE TO DEALLOCATE/TRUNCATE ON A RENAME
RENA33:	PUSHJ	P,GTWDT3	;LAST BLOCK TO KEEP
	MOVEI	T2,0		;SET T2=0 (1ST BLOCK IN RIB IS 0)
RENA34:	PUSHJ	P,SCNPT0##	;GO FIND POINTER TO LAST BLOCK DESIRED
	  JRST	RENA38		;NOT IN THIS RIB, TRY NEXT
	MOVE	P3,P1		;SAVE NUMBER OF ARGS
	PUSH	P,DEVRIB##(F)	;SAVE POINTER TO CURRENT RIB
	PUSHJ	P,UPDGV9	;GO DEALLOCATE SOME BLOCKS
	  STOPCD .+1,DEBUG,TCI,	;++TRUNCATION CHECK INCONSISTENT
	MOVE	T2,DEVACC##(F)	;ALLOCATION GIVEN IN WORDS?
	JUMPE	P4,RENA35	;NO
	TRNN	P4,BLKSIZ##-1	;YES, PARTIAL BLOCK?
	TROA	P4,BLKSIZ##	;NO, LAST BLOCK IS FULL
	TRZ	P4,BLKSIZ##	;YES, ENSURE LESS THAN 1 BLOCK
	SKIPE	ACCWRT##(T2)
	DPB	P4,ACYLBS##	;YES, SAVE SIZE OF LAST BLOCK
RENA35:
	POP	P,T1		;RESTORE PREVIOUS CURRENT RIB TO T1
	SKIPL	DEVRIB##(F)	;CURRENTLY IN PRIME RIB?
	JRST	RENA36		;YES, NO NEED TO WRITE THE RIB
	CAMN	T1,DEVRIB##(F)	;STILL LOOKING AT THE SAME RIB?
	PUSHJ	P,WRTRIB##	;YES, MAKE SURE UPDATED COPY GETS WRITTEN
	PUSHJ	P,REDRIB##	;READ THE PRIME RIB BACK INTO CORE
	  JRST	RENE13		;ERROR READING RIB
RENA36:	MOVE	P1,P3
	PUSHJ	P,CPYFST##	;COPY UPDATED POINTERS TO DDB
	  JRST	RENE13		;RIB ERROR
;HERE WHEN ALLOCATION/DEALLOCATION IS THROUGH. SET UP FOR CLOSE
RENER1:	TLO	M,UUOREN
	PUSH	P,M		;SAVE ADDR OF ALC
	PUSHJ	P,SETVAL	;STORE ARGUMENTS FROM USER IN RIB
	POP	P,M		;POINT AT ERROR CODE
	HRRI	M,<UUXEXT-UUXALC>(M);IN CASE PARTIAL ALLOCATION
;WE MUST DO "SET WATCH FILES" STUFF NOW WHILE
;DEVSFD STILL POINTS TO THE RIGHT PLACE (THE NEW SFD) AND
;WHILE THE SFD USE COUNTS ARE STILL UP
RENA37:	TLNN	M,UPARAL	;PARTIAL ALLOCATION ERROR?
	TRZ	M,-1		;NO, INDICATE NO ERROR CODE
	PUSHJ	P,WCHFIL##	;TYPE SET WATCH FILES
	 CAI	"R"
	MOVEI	T1,UP.SWF	;LIGHT BIT SO WE DON'T DO IT AGAIN
	IORM	T1,.USBTS
	MOVE	T1,.USMBF	;LOC OF MON BUF
	MOVE	T2,RIBPRV##+1(T1)	;PRIVS WORD (MAY HAVE BEEN CHANGED)
	MOVEM	T2,ACCPRV##(P2)	;SAVE IN ACC
	MOVE	T2,RIBEXT##+1(T1)	;GET ACCESS DATE HI CREATION DATE
	HRLM	T2,ACCADT##(P2)	; SAVE IN A.T. (CRE-DATE MIGHT CHANGE)
	MOVE	T1,ACCSTS##(P2)	;GET STATUS
	TRNE	T1,ACPCRE+ACPSUP	;IF FILE WAS JUST WRITTEN
	TRZA	M,-1		;SET TO DEALLOCATE ON CLOSE
	HRRI	M,CLSDLL	;OTHERWISE SET TO KEEP ALL ALLOCATED BLOCKS
	TLO	F,RENMB		;MAKE SURE RENAME BIT IS ON
	TLZ	F,OCLOSB	;AND THAT OUTPUT CLOSE HAPPENS
	MOVEM	S,DEVIOS(F)	;SAVE S BITS IN DDB
	PUSH	P,DEVBUF(F)
	SETZM	DEVBUF(F)	;MAKE SURE CLOSE1 DOESN'T FIND ADR ERR
	PUSHJ	P,CLOSE1##	;CALL CLOSE CODE IN UUOCON
	POP	P,DEVBUF(F)
	PUSHJ	P,JDAADR##	;GET CHAN NUM
	TLZ	F,ICLOSB	;CLEAR INPUT CLOSED INDICATION
	HLLM	F,(T1)		;SO SUBSEQUENT CLOSE WILL WIN
	TLNN	M,UPARAL	;PARTIAL ALLOCATION ERROR?
	AOS	(P)		;NO. SET FOR SKIP-RETURN
ZDYFNC:	SETZ	T1,
	DPB	T1,DEYFNC##	;CLEAR PROT SO WILL RECOMPUTE IT
	POPJ	P,		;RETURN TO USER

;HERE WHEN WE HAVE TO SCAN ANOTHER RIB TO FIND THE CORRECT POINTER
RENA38:	PUSHJ	P,PTRNXT##	;GET THE NEXT RIB
	  STOPCD .,JOB,NRM,	;++NEXT RIB MISSING
	MOVE	T1,.USMBF	;IOWD FOR MONITOR BUFFER
	MOVE	T2,RIBFLR##+1(T1)	;GET FIRST BLOCK NUMBER IN RIB
	PUSHJ	P,GTWDT3	;LAST BLOCK TO KEEP
	JRST	RENA34		;SCAN THIS RIB
;HERE TO RENAME A FILE INTO [3,3] ON SPPRM, FUNCTION 2
SPLREN::TLNE	F,ENTRB
	TLNE	F,OCLOSB
	TLNN	F,LOOKB
	JRST	ECOD5##		;DOCUMENT
	MOVE	T1,DEVFIL(F)
	MOVEM	T1,DEVSPN##(F)
	PJRST	SPTSTR
;SUBROUTINE TO ALLOCATE EXTRA BLOCKS FOR A FILE - ENTER UPDATE OR RENAME
;ENTER WITH T2= AMOUNT TO GET AND M POINTING TO ALLOCATION WORD
;EXIT CPOPJ IF QUOTA EXCEEDED
;EXIT CPOPJ1 IF CANT START WHERE REQUESTED
;EXIT CPOPJ2 IF GOT ANY BLOCKS (UPARAL MAY BE ON IN M)

UPDALC:	HRRZ	T4,DEVUFB##(F)	;LOC OF UFB
	CAMG	T2,UFBTAL##(T4)	;DOES HE WANT MORE THAN HE CAN GET?
	AOJA	M,UPDAL1	;NO. OK
	SKIPN	T2,UFBTAL##(T4)	;YES. DOES HE HAVE ANY SPACE AT ALL?
	POPJ	P,		;NO. CANT GET MORE

	ADDI	M,UUXPOS-UUXALC	;YES. HE CAN GET PART OF IT
	TLO	M,UPARAL	;INDICATE PARTIAL ALLOCATION

UPDAL1:	AOS	(P)		;SET FOR SKIP/DOUBLE SKIP RETURN
	PUSH	P,T2		;SAVE NUMBER OF BLOCKS TO GET
	PUSHJ	P,DDBZR		;ZERO OUT THE DDB RETRIEVAL POINTERS
	MOVEI	T1,DEVRB1##(F)	;SET UP DEVRET TO POINT TO
	HRRM	T1,DEVRET##(F)	; DEVRB1
	TLON	S,IOSRIB	;RIB ALREADY IN CORE?
	PUSHJ	P,PTRGET##	;NO, READ IT
	PUSHJ	P,LSTUNI	;SET U TO LAST UNIT OF FILE
	PUSHJ	P,ALSTRT	;SET UP T1 FOR START ADR OF BLOCKS
	  JRST	TPOPJ##		;CANT START AT SPECIFIED LOCATION
	JUMPN	T1,UPDAL4	;NO START ADR. IF 0
	MOVE	T2,(P)		;GET REQUESTED AMOUNT
	CAMG	T2,UNITAL##(U)	;DOES THIS UNIT HAVE ENOUGH FREE SPACE?
	JRST	UPDAL5		;YES. TRY TO GET IT
	MOVE	T3,UNISTR##(U)	;NO. POINT TO 1ST UNI IN STR
	HLRZ	T3,STRUNI##(T3)	;1ST UNIT
UPDAL2:	CAMG	T2,UNITAL##(T3)	;DOES THIS UNIT HAVE ENOUGH?
	JRST	UPDAL3		;YES. USE IT
	HLRZ	T3,UNISTR##(T3)	;NO. STEP TO NEXT UNIT IN STR
	JUMPN	T3,UPDAL2	;AND TRY IT
	TLO	M,UPARAL	;INDICATE REQUESTING MORE BLOCKS
	JRST	UPDAL5		;NO UNIT HAS ENOUGH. USE ORIGINAL UNIT
UPDAL3:	MOVE	U,T3		;SET UP NEW U
UPDAL4:	PUSHJ	P,STORU##	;SAVE IN DDB
	LDB	T2,UNYLUN##	;GET LOGICAL UNIT NUMBER
	TRO	T2,RIPNUB##	;INSURE NON-0
	PUSHJ	P,PTSTO##	;SAVE CHANGE-UNIT POINTER
	AOS	DEVRET##(F)	;POINT TO NEXT POINTER SLOT
UPDAL5:	PUSH	P,T1		;SAVE T1
	PUSHJ	P,UPDSET	;UPDATE DEYRLC, DEVRSU
	POP	P,T1		;RESTORE T1
	MOVE	T2,(P)		;AND T2
	MOVSI	T3,1		;ACCOUNT FOR UNIT-CHANGE
	ADDB	T3,DEVRSU##(F)
	JUMPGE	T3,[SOS -1(P)	;TOO HIGH?
		    JRST UPDAL6] ;YES, PARTIAL ALLOC ERR
	PUSHJ	P,ENTALU	;NO, ALLOCATE SPACE FOR UPDATE
	  JRST	TPOPJ##		;ERROR RETURN
UPDAL6:	POP	P,T2		;REMOVE GARBAGE FROM PDL
	PUSHJ	P,CHKPAR	;SET ERROR BIT IF PARTIAL ALLOCATION
	HRRZ	T1,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,ACCALC##(T1)	;AMOUNT OF SPACE ALLOCATED
	PUSHJ	P,PUTWDU##	;TELL USER AMOUNT ALLOCATED
	JRST	CPOPJ1##	;TAKE GOOD RETURN

;SUBROUTINE TO UPDATE DEYRLC AFTER UPDAT5 HAS ALLOCATED MORE SPACE
; (CANT BE DONE IN UPDAT5 SINCE RIB MAY NOT BE IN CORE YET)
;ENTER AT UPDSE2 IF T1 HAS ALREADY BEEN SET TO AN AOBJN POINTER
UPDSET:	PUSHJ	P,SPTRW##	;SET AOBJN WORD FOR POINTERS
UPDSE2:	MOVE	T2,T1		;INTO T2
	SKIPE	(T2)		;THIS POINTER SLOT EMPTY?
	AOBJN	T2,.-1		;NO. TRY NEXT
	HLLM	T2,DEVRSU##(F)	;YES, UPDATE DEVRSU
	SUBI	T2,(T1)		; COMPUTE NEW LENGTH
	DPB	T2,DEYRLC##	;SAVE LENGTH IN DDB
	POPJ	P,		;AND RETURN

;SUBROUTINE TO READ RIB FOR UPDATE-ENTER
;RETURNS CPOPJ WITHOUT DA IF RIB ERROR
;RETURNS CPOPJ1 IF OK, WITH RIB IN CORE AND DA IF SIM UPDATE
SIMRIB:	TLOE	S,IOSRIB	;IF WE ALREADY HAVE RIB IN CORE
	JRST	CPOPJ1##	;ALL IS OK
	MOVE	T1,DEVACC##(F)	;A.T. LOC
	MOVE	T1,ACCSMU##(T1)	;IF A SIMULTANEOUS UPDATE FILE,
	TRNE	T1,ACPSMU	; GET THE DA RESOURCE BEFORE READING RIB
	PUSHJ	P,UPDA##	; AS PROTECTION AGAINST RACE CONDITIONS
	PUSHJ	P,REDRIB##	; INVOLVED IN REWRITING RIBS
	  JRST	DOWNIF##	;ERROR READING RIB - GIVE UP
	MOVEI	T1,DEPWRT##	;INDICATE THIS IS A
	IORM	T1,DEVWRT##(F)	; WRITING DDB
	JRST	CPOPJ1##	;TAKE GOOD RETURN



;SUBROUTINE TO DEALLOCATE OR TRUNCATE BLOCKS FROM A FILE
;ENTER WITH P1=AOBJN WORD FOR POINTERS,  DEVREL,DEVBLK SET TO LAST DESIRED BLOCK
;EXIT CPOPJ IF PRIVS DON'T ALLOW TRUNCATION, FUNCTION IS TRUNCATE
;EXIT CPOPJ1 NORMALLY WITH RIB SET UP, BUT NOT WRITTEN
;HERE WITH T1=AOBJN
UPDGV9:	MOVE	P1,T1		;PUT IT IN A SAFE PLACE
	AOBJN	T1,UPDGIV	;LAST RTP IN RIB?
	AOS	DEVBLK##(F)	;YES, SCNPTR LEFT DEVLFT ONE TOO LOW
				;COMPENSATE BY BUMPING DEVBLK
;HERE WITH P1=AOBJN
UPDGIV:	HRRZ	T3,DEVACC##(F)	;LOC OF A.T.
	MOVE	T1,DEVREL##(F)	;LAST DESIRED BLOCK
	CAML	T1,ACCWRT##(T3)	;THROWING AWAY BLOCKS WITH DATA?
	JRST	UPDGV0		;NO. OK
	MOVEI	T1,FNCTRN##	;YES. SEE IF PRIVS ALLOW TRUNCATING
	PUSHJ	P,CHKPRV##	;OK?
	  POPJ	P,		;NO. ILLEGAL
	HRRZ	T3,DEVACC##(F)	;YES. GET A.T. LOC AGAIN
	MOVE	T1,DEVREL##(F)	;NEW HIGHEST BLOCK
	MOVEM	T1,ACCWRT##(T3)	;SAVE AS HIGHEST BLOCK WITH DATA
	MOVEI	T4,BLKSIZ##
	DPB	T4,ACZLBS##	;LAST BLOCK IS FULL


;HERE WHEN ACCWRT IS SET. T1=DEVREL HAS THE NUMBER OF THE LAST BLOCK TO KEEP
UPDGV0:	SOS	DEVLFT##(F)	;YES, ACCOUNT FOR THE REDUNDANT RIB BLOCK
	LDB	T4,UNYBPC##	;NUMBER OF BLOCKS PER CLUSTER
	HRRZ	T1,DEVLFT##(F)	;GET NUMBER OF BLOCKS LEFT IN CROUP
	IDIV	T1,T4		;CONVERT LAST BLOCK TO CLUSTER ADDR.
	JUMPE	T2,UPDGV1	;EXACT NUMBER OF CLUSTERS IF 0
	ADDM	T2,DEVBLK##(F)	;UPDATE LAST BLOCK ADR
	ADDM	T2,DEVREL##(F)	;UPDATE LAST LOGICAL BLOCK
	MOVNS	T2
	ADDM	T2,DEVLFT##(F)	;UPDATE AMOUNT TO THROW AWAY IN THIS CLUSTER
;HERE WHEN DEVREL AND DEVBLK POINT TO THE LAST BLOCK IN THE CLUSTER
UPDGV1:	HRRZ	T1,DEVLFT##(F)	;NO OF BLOCKS LEFT IN GROUP
	JUMPE	T1,UPDGV3	;NOTHING TO DELETE IF 0
	IDIV	T1,T4		;YES. CONVERT TO CLUSTERS
	SKIPE	T2		;SHOULD BE AN EVEN NO OF CLUSTERS
	STOPCD	.+1,DEBUG,ONC,	;++ODD NUMBERED CLUSTER
	PUSH	P,T1		;SAVE NO OF CLUSTERS TO DELETE
	MOVE	T4,UNISTR##(U)	;LOC OF STR DATA BLOCK
	MOVE	T2,(P1)		;LAST POINTER
	CAME	T2,ACCPT1##(T3)	;IS IT 1ST POINTER?
	SETZ	T3,		;NO. INDICATE BY T3=0
	LDB	T1,STYCNP##(T4)	;PREVIOUS CLUSTER COUNT
	SUB	T1,(P)		;DECREASE BY AMOUNT WE AREW DELETING
	DPB	T1,STYCNP##(T4)	;SAVE NEW CLUSTER COUNT
	POP	P,T1		;REMOVE JUNK FROM PD LIST
	MOVEM	T2,(P1)		;SAVE POINTER
	SKIPE	T3		;IS THIS 1ST POINTER?
	MOVEM	T2,ACCPT1##(T3)	;YES. UPDATE PNTR IN ACC ALSO
	HRRZ	T2,DEVLFT##(F)	;NUMBER OF BLOCKS IN CLUSTER TO DELETE
	AOS	T1,DEVBLK##(F)	;1ST ADR NOT WANTED
UPDGV2:	HLRZ	T3,DEVEXT(F)	;GET EXTENSION OF FILE
	CAIE	T3,'UFD'	;A DIRECTORY?
	CAIN	T3,'SFD'	; OF SOME FLAVOR?
	PUSHJ	P,[PUSHJ P,SAVT## ;YES, SALT AWAY THE AC'S FOR GIVBLK
		   JRST CSDELR##] ;FLUSH THE DIRECTORY DATA FROM THE CACHE
	PUSHJ	P,GIVBLK##	;DELETE SOME BLOCKS
UPDGV3:	AOBJP	P1,DELRB2	;THROUGH IF NO MORE

;SUBROUTINE TO DELETE A FILE
;ENTER WITH RIB BLOCK IN CORE, P1=AOBJN WORD FOR POINTERS
;EXIT CPOPJ1
DELRIB::SKIPN	T2,(P1)		;GET NEXT POINTER FROM RIB
	JRST	DELRB2		;THROUGH IF 0
	SETZM	(P1)		;ZERO THE POINTER (IN CASE OF TRUNCATE)
	PUSHJ	P,CNVPTR##	;CONVERT TO ADR, COUNT
	  JRST	DELRB2		;BAD UNIT-CHANGE PNTR. STOP DELETING
	  JRST	UPDGV3		;CHANGE-UNIT, TRY AGAIN
	MOVE	T2,T1		;COUNT INTO T2
	MOVE	T1,DEVBLK##(F)	;ADDRESS INTO T1
	JRST	UPDGV2		;GO DELETE THIS POINTER
;HERE WHEN ALL THE BLOCKS HAVE BEEN RELEASED IN THE CURRENT RIB
DELRB2:	MOVE	P1,.USMBF	;LOC OF MONITOR BUFFER
	PUSH	P,U		;SAVE CURRENT U
	SKIPL	DEVRIB##(F)	;CURRENT RIB EXTENDED?

	SKIPN	T1,RIBELB##+1(P1)  ;ERROR REGION?
	JRST	DELRB3		;NO. FINISH UP
	HLRZ	T2,RIBEUN##+1(P1)	;YES. GET UNIT OF ERROR
	PUSHJ	P,NEWUNI##	;SET U TO UNIT DATA BLOCK LOC
	  JRST DELRB3		;BAD UNIT NUMBER - CONTINUE RECOVERS
	MOVE	T1,RIBELB##+1(P1)  ;JUST BLOCK NUMBER(CLEAR CONI BITS IN LH)
	TLZ	T1,BATMSK##	;CLEAR ERROR BITS
	JUMPE	T1,DELRB3	;DON'T ALLOCATE IF NO BLOCK NUMBER GIVEN
	HRRZ	T2,RIBNBB##+1(P1)  ;GET NO OF BAD BLOCKS IN REGION
	SKIPN	T2		;IF RIBNBB=0
	MOVEI	T2,1		; TRY FOR 1 CLUSTER
	PUSHJ	P,TAKBLK##	;MARK THEM AS TAKEN
	  JFCL

DELRB3:	MOVE	U,(P)
	HRRZ	U,UNISTR##(U)	;GET ADR STR
	HLRZ	U,STRUNI##(U)	;GET ADR 1ST UNIT IN STR
DELRB4:	PUSHJ	P,STORU##	;SAVE IN DDB
	PUSHJ	P,WTUSAT	;GO WRITE SATS FOR THIS UNIT IF NOT CURRENT UNIT
	HLRZ	U,UNISTR##(U)	;GET NEXT IN THE STRUCTURE
	JUMPN	U,DELRB4	;REWRITE THE SAT IF ITS BEEN CHANGED
	POP	P,U		;RESTORE CURRENT U
	PUSHJ	P,STORU##	;RESET DDB
	SKIPL	DEVRIB##(F)	;SKIP IF CURRENT RIB IS EXTENDED
	SKIPN	RIBFLR##+1(P1)	;NOT EXTENDED, NON-0 RIBFLR MEANS OLD FILE
	SKIPN	T1,RIBXRA##+1(P1)  ;IS THERE ANOTHER RIB ON CHAIN?
	PJRST	CPOPJ1##	;NO, EXIT
	PUSH	P,T1		;SAVE POINTER TO NEXT RIB
	SETZM	RIBXRA##+1(P1)	;CLEAR THE POINTER BECAUSE THE OTHERS WILL GO AWAY
	PUSHJ	P,WRTRIB##	;WRITE THE CURRENT RIB
	POP	P,DEVRIB##(F)	;SET UP DEVRIB TO POINT TO NEXT RIB
	PUSHJ	P,PTRCUR##	;GET THE RIB INTO CORE
	JUMPN	T3,CPOPJ1##	;ERROR READING RIB IF T3 NON-ZERO
	MOVE	P1,T1		;GET ADDRESS OF FIRST POINTER
	JRST	DELRIB		;AND DELETE THIS RINFULL
;SUBROUTINE TO CHECK FOR START-ADDRESS SPECIFICATION.
;RETURNS CPOPJ IF THE SPECIFIED ADDRESS IS HIGHER THAN THE HIGHEST BLOCK IN STR.
;RETURNS CPOPJ1 IN NORMAL CASE, WITH T1 SET UP (POSSIBLY 0).
;RESTORES T2 FROM -1(P)  -  ASSUMES NUMBER OF BLOCKS IN IT
;IF A START ADR. IS GIVEN, U WILL BE CHANGED TO POINT TO THE RIGHT UNIT

ALSTRT:	CAIL	P1,UUXPOS
	PUSHJ	P,GETWDU##	;POSSIBLY SPECIFYING START ADR.?
	HRRI	M,-1(M)		;DEC M FOR RETURN
	CAIL	P1,UUXPOS
	SKIPN	T1		;YES. IS HE?
	JRST	ALSTR1		;NO. GET SPACE ANYWHERE
	SKIPL	T1		;NEGATIVE BLOCK NUMBER LOSES
	PUSHJ	P,ADR2UN	;CONVERT T1 TO UNIT, BLOCK WITHIN UNIT
	  POPJ	P,		;BLOCK GT HIGHEST BLOCK IN STR - NON-SKIP RETURN
	SKIPA	T2,-1(P)	;PICK UP NUMBER OF BLOCKS AGAIN
ALSTR1:	SETZ	T1,		;ZERO T1, SO TAKE BLOCKS ANYWHERE
	JRST	CPOPJ1##	;TAKE GOOD RETURN


;SUBROUTINE TO CHECK FOR PARTIAL ALLOCATION, STORE AN ERROR NUMBER IF SO
;ENTER WITH UUO POINTING TO ALC WORD, LH(UUO) HAS UPARAL IF AN ERROR
CHKPAR:	TLNN	M,UPARAL	;PARTIAL ALLOCATION?
	POPJ	P,		;NO. RETURN
	HRRI	M,-<UUXALC-UUXEXT>(M)	;YES. POINT UUO TO ERROR WORD
	PUSHJ	P,GTWST2##	;GET THE WORD
	HRRI	T1,PAOERR	;PARTIAL ALLOCATION ERROR NUMBER
	PUSHJ	P,PUTWDU##	;STORE ERR BIT IN USER AREA
	HRRI	M,UUXALC-UUXEXT(M)	;POINT TO ALC WORD AGAIN
	POPJ	P,		;AND RETURN


;SUBROUTINE TO CONVERT FROM A BLOCK NUMBER WITHIN AN STR TO A UNIT AND BLOCK WITHIN UNIT
;ENTER WITH T1=BLOCK NUMBER
;EXIT CPOPJ IF THE NUMBER IS HIGHER THAN THE HIGHEST BLOCK IN STR
;EXIT CPOPJ1 NORMALLY, U AND DEVUNI=NEW UNIT,  T1=BLOCK WITHIN UNIT
ADR2UN::MOVE	T4,UNISTR##(U)	;LOC OF STR DB
	CAMLE	T1,STRHGH##(T4)	;START BLOCK ABOVE HIGHEST IN STR?
	POPJ	P,		;YES. NON-SKIP RETURN
	MOVE	T3,STRBPU##(T4)	;NO. NUMBER OF BLOCKS/UNIT
	IDIV	T1,T3		;CONVERT START ADR TO UNIT, BLOCK NO.
	EXCH	T1,T2		;SET UNIT INTO T2
	HLRZ	U,STRUNI##(T4)	;LOC OF 1ST UNI IN STR
	PUSHJ	P,NEWUN##	;SET U, DEVUNI TO DESIRED UNIT
	  JFCL
	JRST	CPOPJ1##	;AND RETURN
;SUBROUTINE TO ALLOCATE INITIAL BLOCKS FOR A FILE
;SINCE FILES MUST START AT EVEN SUPER-CLUSTER BLOCKS,
;  THE START ADR. MUST BE MODIFIED
ADJALC::HRRZ	T4,UNISTR##(U)	;STR LOC
	HLRZ	T4,STRBSC##(T4)	;NUMBER OF BLOCKS/SUPER-CLUSTER
	JUMPE	T1,ADJAL1	;GO IF NO START-ADR. GIVEN
	MOVE	T3,T1		;DESIRED START ADR.
	IDIV	T3,T4		;CONVERT TO SUPER-CLUSTER
	JUMPE	T4,TAKBLK##	;IF NO REMAINDER IT IS A VALID ADR.
	POPJ	P,		;NOT A START ADR FOR A SUPER CLUSTER. ILLEGAL

;HERE WHEN NO START ADR. IS SPECIFIED
ADJAL1:	LDB	T3,UNYBPC##	;NO. OF BLOCKS PER CLUSTER
	SUB	T4,T3		;SUBTRACT FROM NO. IN A SUP. CLUS.
	JUMPE	T4,TAKBLK##	;ANY CLUSTER ADR. IS OK IS THEY ARE THE SAME
	ADD	T2,T4		;ADJUST AMOUNT REQUESTED BY THE DIFFERENCE
	HRRZ	T4,DEVUFB##(F)	;LOC OF UFB
	CAMLE	T2,UFBTAL##(T4)	;WANT MORE THAN QUOTA ALLOWS?
	SKIPLE	T2,UFBTAL##(T4)	;YES. TAKE LESSER AMOUNT

	PUSHJ	P,TAKBLK##	;TRY FOR THAT MANY
	  POPJ	P,		;RETURN (QUOTA 0 OR BELOW)
	PUSHJ	P,SAVE2##	;GOT SOME BLOCKS. SAVE P1,P2
	PUSHJ	P,GRPAD##	;CONVERT TO BLOCK ADR OF THE GROUP
	MOVE	P1,T1		;SAVE NUMBER OF BLOCKS IN P1
	MOVE	P2,T2		;SAVE START ADR OF THE GROUP
	HRRZ	T4,UNISTR##(U)	;LOC OF STR DB
	HLRZ	T3,STRBSC##(T4)	;NO. OF BLOCKS PER SUP. CLUS.
	IDIV	T2,T3		;CONVERT BLOCK TO SUP. CLUS ADR.
	JUMPE	T3,ADJAL2	;EVEN ADR. IF T3=0
	HLRZ	T4,STRBSC##(T4)	;NO OF BLKS/SUPER CLUSTER
	SUBM	T4,T3		;NO OF BLKS WE CAN'T USE
;HERE WITH T3= NO. OF BLOCKS AT START OF FILE WHICH WE CANT USE
	SUB	P1,T3		;ADJUST BLOCK COUNT
	MOVE	T1,P2		;1ST BLOCK TO RETURN
	MOVE	T2,T3		;NO. OF BLOCKS TO RETURN
	ADD	P2,T3		;ADJUST START ADR
	PUSHJ	P,GIVBLK##	;GIVE THEM UP

;NOW RECONSTRUCT A GROUP POINTER FROM P1,P2
ADJAL2:	JUMPE	P1,CPOPJ##	;ERROR RETURN IF ALL BLOCKS GIVEN BACK
	MOVE	T2,P2		;STARTING BLOCK NO
	LDB	P2,UNYBPC##	;BLOCKS PER CLUSTER
	IDIV	T2,P2		;COMPUTE START CLUSTER ADR
	SKIPE	T3		;MUST BE AN EVEN CLUSTER ADR
	STOPCD	.+1,DEBUG,CNE,	;++CLUSTER NOT EVEN
	MOVE	T1,P1		;NUMBER OF BLOCKS IN GROUP
	IDIV	P1,P2		;CONVERT TO CLUSTER COUNT
	SKIPE	P2		;MUST BE AN EVEN NO OF CLUSTERS
	STOPCD	.+1,DEBUG,CAO,	;++CLUSTER ADDRESS ODD
	HRRZ	T3,UNISTR##(U)	;LOC OF STR DB
	DPB	P1,STYCNP##(T3)	;SAVE GROUP SIZE IN T2
	JRST	CPOPJ1##	;AND TAKE GOOD RETURN
;SUBROUTINE TO ALLOCATE FOR ENTER UUO
;ENTER WITH T2=(P)=NUMBER OF BLOCKS TO GET
;EXIT CPOPJ IF CANT START AT SPECIFIED BLOCK
;EXIT CPOPJ1 NORMALLY (UPARAL MAY BE ON)

;ENTER AT ENTALC TO GET INITIAL BLOCKS FOR A FILE
;ENTER AT ENTALU TO GET ADDITIONAL BLOCKS FOR AN EXISTING FILE
ENTALU:	PUSHJ	P,TAKBLK##	;GET ANY BLOCKS (NOT STARTING AT A SUPER-CLUSTER
	  POPJ	P,		;CANT START WHERE SPECIFIED
 	JRST	ENTAL1		;GOT SOME - CONTINUE

ENTALC:	PUSHJ	P,ADJALC	;GET THE BLOCKS REQUESTED STATING AT A SUPERCLUSTER
	  POPJ	P,		;CANT START AT SPECIFIED BLOCK
ENTAL1:	PUSH	P,DEVRSU##(F)
ENTAL2:	PUSHJ	P,PTSTO##	;SAVE POINTER IN DDB
	MOVSI	T4,1		;UPDATE DEVRSU
	ADDB	T4,DEVRSU##(F)
	JUMPGE	T4,ENTAL3	;ALL POINTERS TAKEN IF NOT NEGATIVE
	AOS	T4,DEVRET##(F)	;STEP TO NEXT POINTER LOC
	CAILE	T4,DEVRBN##(F)	;FILLED DDB?
ENTAL3:
	TLOA	M,UPARAL	;YES. PARTIAL ALLOCATION ERROR
	TLNN	M,UALASK	;NO. DID HE SPECIFY A PARTICULAR AMOUNT?
	JRST	ENTAL4		;ALL BLOCKS ARE ALLOCATED
	MOVN	T4,T1		;-NUMBER OF BLOCKS GOTTEN
	ADDB	T4,-2(P)	;UPDATE AMOUNT REQUESTED
	JUMPLE	T4,ENTAL4	;OK IF GOT THEM ALL

;SINCE THERE IS A RESTRICTION ON THE NUMBER OF BLOCKS WHICH WILL
;FIT INTO A RETRIEVAL POINTER, LESS THAN THE AMOUNT REQUESTED MAY HAVE BEEN
;OBTAINED AND THE NEXT CONTIGUOUS BLOCKS MAY BE AVAILABLE - TEST FOR THIS
	MOVE	T3,UNISTR##(U)
	LDB	T2,STYCLP##(T3)	;ADDRESS OF 1ST CLUSTER GOTTEN
	LDB	T4,UNYBPC##	;NUMBER OF BLOCKS PER CLUSTER
	IMUL	T2,T4		;INITIAL BLOCK ADDRESS
	ADD	T1,T2		;+NUMBER OF BLOCKS GOTTEN=NEW START ADDR.
	MOVE	T2,-2(P)	;NUMBER OF BLOCKS LEFT TO GET
	PUSHJ	P,TAKBLK##	;TRY TO GET MORE
	  TLOA	M,UPARAL	;PARTIAL ALLOCATION ERROR
	JRST	ENTAL2		;SAVE THE NEW POINTER AND TRY AGAIN

;HERE WHEN DONE
ENTAL4:	POP	P,DEVRSU##(F)	;RESTORE DEVRSU
	PJRST	CPOPJ1##	;AND SKIP-RETURN
;SUBROUTINE TO STORE USER-SUPPLIED ARGUMENTS IN THE RIB BLOCK
;CALLED BY UPDATE AND RENAME
;ENTER WITH MONITOR BUF, P1=NUMBER OF ARGS,  M=ALLOCATION WORD
; BIT 0 OF M=1 IF USER CANT CHANGE ANY VALUES
;ENTER AT SETVAN FROM ENTER, WITH M=PRVS WORD (EXTENDED UUO ONLY)
SETVAL:	TLNE	M,EXTUUO	;EXTENDED UUO?
	CAIGE	P1,UUXPRV	;YES. WANT MORE THAN ALREADY ARE STORED?
	POPJ	P,		;NO. RETURN
	HRRI	M,-<UUXALC-UUXPRV>(M) ;YES. POINT M TO PRIVS WORD
	SKIPA	T3,P1		;REMEMBER TRUE NUMBER OF ARGS
SETVAN:	SETZ	T3,		;MARK THAT WE CAME FROM SETVAN
	PUSHJ	P,SAVE2##
	SETO	P2,		;P2 FOR UNPRV'D STATUS BITS
	CAILE	P1,UUXENX	;YES. ALL ARGUMENTS ARE LEGAL
	MOVEI	P1,UUXENX
	PUSHJ	P,PRVJB##	;PRIVILEGED JOB?
	  JRST	SETVAU		;NO, NOT ALL ARGUMENTS ARE LEGAL
;
;HERE WE ARE PRIV'D, T3 HAS TRUE # OF ARGS, M=PRIV WORD
;TRY TO COPY ACCOUNT STRING FROM USER TO RIB. SIMILAR TO SETE15
;
	SKIPGE	T2,[XWD MACTSL##,RIBACS##]	;GET MAX ACCT STRING LENG
	CAIGE	T3,UUXACT	;DID THE USER SPECIFY ACCT STRING?
	  JRST	SETVAC		;MAX IS 0 OR USER DIDN'T SPECIFY
	MOVE	T1,.USMBF	;POINT TO MONITOR BUFFER
	MOVEM	T2,RIBACT##+1(T1)	;STORE AOBJN POINTER TO ACCT STRING
	ADDI	T2,1(T1)	;MAKE AOBJN WORD FOR ACCT STRING IN RIB
	HRLZ	T1,T2		;MAKE A BLT POINTER
	HRRI	T1,1(T2)
	SETZM	(T2)		;ZAP THE EXISTING ACCOUNT STRING
	BLT	T1,-MACTSL-1(T2) ;NOTE THAT MACTSL IS A NEG NUMBER
	PUSH	P,M		;SAVE USER ARG POINTER
	HRRI	M,UUXACT-UUXPRV-1(M)	;POINT TO USER SUPPLIED STRING
	SUBI	T3,UUXACT
SETVAR:	PUSHJ	P,GETWD1##	;GET NEXT USER WORD
	JUMPE	T1,SETVR1	;DONE (SINCE ACCOUNT IS ASCIZ)
	MOVEM	T1,(T2)		;STORE A WORD IN RIB
	AOBJP	T2,SETVR1	;DONE IF RIB FULL
	SOJG	T3,SETVAR	;CONTINUE IF MORE ARGS
SETVR1:	POP	P,M		;RESTORE USER ARG POINTER TO UUXPRV
SETVAC:	CAIGE	P1,UUXUSD	;MIGHT UUXUSD BE IN ENTER BLOCK?
	JRST	SETVA2		;NO
	HRRI	M,UUXUSD-UUXPRV(M) ;YES. POINT TO USD ARGUMENT
	PUSHJ	P,GTWST2##	;JOB WANT USD COMPUTED?
	HRRI	M,-<UUXUSD-UUXPRV>(M)	;POINT M TO PRIV WORD AGAIN
	JUMPGE	T1,SETVA2	;NOT IF 0
	PUSHJ	P,FIXUSD	;FIX RIBUSD (IF UFD)
	MOVE	T3,@SETVA2	;NORMAL BITS
	TLO	T3,1		;RIBUSD NOT SETTABLE
	JRST	SETVA9
;HERE IF UNPRIVED
;MASKS AT SETVA1 AND SETVA2 DETERMINE
;VALUES WHICH CAN BE WRITTEN INTO EXTENDED
;RIB. BIT POS 0 IS UUXPRV.
SETVAU:	CAIGE	P1,UUXSTS	;TRYING TO SET/LLR STATUS BITS?
	JRST	SETVA1		;NO
	HRRI	M,UUXSTS-UUXPRV(M) ;YES, POINT AT STATUS WORD
	PUSHJ	P,GETWDU##	;GET ARGUMENT
	ANDI	T1,RIPRMS##	;GET UNPRIV'D BITS
	MOVE	P2,T1		;PRESERVE THEM IN P2
	HRRI	M,-<UUXSTS-UUXPRV>(M) ;RESET M
SETVA1:	MOVE	T3,[202760,,-1]	;ASSUME DATA FILE
	PUSHJ	P,TSTSFD	;SFD OR UFD?
	  TLO	T3,17		;YES, CAN'T SET DIR STUFF
	JRST	SETVA9
;HERE WITH P1=NUMBER OF ARGUMENTS USER IS SUPPLYING
SETVA2:	MOVE	T3,[XWD 202260,036200];BITS ON FOR ARGS WHICH CANT BE SUPPLIED BY USER
SETVA9:	TLNE	M,UUOREN	;RENAME?
	TLO	T3,400000	;YES, CRE-DATE, PRIVS ALREADY CORRECT IN MON-BUF
	SKIPGE	M		;IF USER CANT CHANGE VALUES
	SETO	T3,		; JUST STORE IN ENTER/RENAME BLOCK
	MOVE	T2,.USMBF
	HRRZ	T4,RIBFIR##+1(T2) ;NO OF VALUES IN FILE
	JUMPE	T4,SETV2A
	CAILE	P1,-1(T4)	;USER SUPPLYING MORE?
	MOVEI	P1,-1(T4)	;YES, DON'T LET HIM (OLD FILE)
SETV2A:	HRRZ	T2,.USMBF	;LOC OF MON BUF
	MOVE	T1,UNILOG##(U)	;GET CURRENT UNIT NAME
	MOVEM	T1,RIBDEV##+1(T2) ;STORE IN RIB
	ADDI	T2,RIBPRV##+1	;POINT TO PRIVS WORD
	MOVNI	T1,-UUXPRV+1(P1) ;T1=-NUMBER OF ARGS TO STORE
	HRLM	T1,T2		;SAVE NUMBER IN LH(T2)
SETVA3:	JUMPG	T3,SETVA4	;PROTECTED ARGUMENT?
	MOVE	T1,(T2)		;YES, GET VALUE FROM RIB
	PUSHJ	P,PUTWDU##	;STORE IN USERS AREA
	JRST	SETVA5		;CONTINUE
SETVA4:	PUSHJ	P,GTWST2##	;GET AN ARG FROM USER
	MOVEM	T1,(T2)		;SAVE IT IN RIB
SETVA5:	HRRI	M,1(M)		;STEP TO NEXT ARG
	LSH	T3,1		;SET NEXT CANT-SUPPLY BIT IN T3
	AOBJN	T2,SETVA3	;GO IF HE WANTS ANOTHER
	MOVE	T2,DEVACC##(F)
	CAIGE	P1,RIBALC##	;NEED TO GET ALLOCATION WORD?
	 JRST	SETVA7		;NO, GO ON
	SUBI	M,-RIBALC##+1(P1) ;POINT TO ,RBALC IN USER'S AREA
	MOVE	T1,ACCALC##(T2)	;GET ACTUAL ALLOCATION OF FILE
	PUSHJ	P,PUTWDU##	;STORE IT IN USER'S ARG BLOCK
SETVA7:	MOVE	T1,.USMBF	;MAKE SURE NO-DELETE BIT OFF
	MOVE	T2,ACCDIR##(T2)	;IS FILE A DIRECTORY?
	MOVEI	T4,RIPDIR##
	TRNE	T2,ACPDIR##
	IORM	T4,RIBSTS##+1(T1)  ;YES, DONT LET RIPDIR OR RIPPAL BE CLEARED
	MOVEI	T4,RIPNDP##	; OTHERWISE COULD CREATE A
	ANDCAM	T4,RIBSTS##+1(T1)  ; NON-DELETABLE FILE
	JUMPL	P2,SETVA6	;TRYING TO SET UNPRIV'D BITS?
	MOVEI	T4,RIPRMS##
	ANDCAM	T4,RIBSTS##+1(T1) ;YES, CLEAR OR SET ACCORDINGLY
	IORM	P2,RIBSTS##+1(T1)
SETVA6:	HLRZ	T1,DEVEXT(F)	;GET EXTENSION
	CAIN	T1,'UFD'	;ONLY LEGAL FOR UFD
	PUSHJ	P,FNDUFB	;FIND UFB FOR FILE
	  POPJ	P,		;NOT THERE -RETURN
	PUSHJ	P,PRVJB##	;AND ALLOWED TO ?
	  PJRST	GVCBJ##		;NO, RETURN
	MOVE	T1,.USMBF	;%FOUND IT - L(MON BUF)
	MOVSI	T3,UFPLOG##
	ANDCAM	T3,UFBLOG##(T2)	;CLEAR UFPLOG
	SKIPGE	RIBSTS##+1(T1)	;IS RIPLOG ON?
	IORM	T3,UFBLOG##(T2)	;YES. LIGHT UFPLOG
	MOVE	T3,RIBQTF##+1(T1)  ;%LOGGED-IN QUOTA
	SUB	T3,RIBUSD##+1(T1)  ;%-AMOUNT USED
	MOVEM	T3,UFBTAL##(T2)	;%=CURRENT QUOTA
	PJRST	GVCBJ##		;%GIVE UP CB AND RETURN
;SUBROUTINE TO ZERO THE RETRIEVAL POINTERS IN THE DDB
;RESPECTS T1,T2,T3
DDBZR::
	MOVSI	T4,DEPLPC##	;LAST POINTER IS NOT IN CORE
	ANDCAM	T4,DEVLPC##(F)

DDBZRO::SETZM	DEVRB1##(F)	;ZERO 1ST PNTR
	MOVSI	T4,DEVRB1##(F)
	HRRI	T4,DEVRB2##(F)	;SET TO BLT
	BLT	T4,DEVRBN##(F)
	HRRZ	T4,DEVCPY##(F)	;LOC OF IN-CORE COPY
	JUMPE	T4,CPOPJ##
	HRLI	T4,MPTRLN##	;SET TO CLEAR IT OUT
	SETZM	PTRDAT##(T4)
	AOBJN	T4,.-1		;ZERO THOSE POINTERS TOO
	POPJ	P,		;AND RETURN
;SUBROUTINE TO COMPUTE THE RIBUFD WORD
;RESPECTS T1
GTUFR::	PUSH	P,T1
	PUSHJ	P,DIRSET##
	  PJRST	TPOPJ##
	MOVE	T4,UNISTR##(U)	;LOC OF STR DATA BLOCK
	LDB	T2,STYCLP##(T4)	;GET ADDRESS
	LDB	T1,UN1PTR##	;GET UN1 ALONE
	LDB	T3,UNYBPC##	;BLOCKS PER CLUSTER
	IMUL	T2,T3		;CONVERT CLUSTER ADR TO BLOCK ADR
	MOVE	T3,STRBPU##(T4)	;HIGHEST BLOCK PER UNIT
	IMUL	T1,T3		;NO OF PRECEEDING BLOCKS IN STR
	ADD	T2,T1		;PLUS BLOCK NO RELATIVE TO UNIT
	PJRST	TPOPJ1##	;RETURN WITH T2=RIBUFD WORD

;SUBROUTINE TO SET RIBUFD WORD IN RIB
;EXIT WITH T1=L(MON BUF-1)  AND RIBUFD WORS SET TO 1ST BLOCK OF UFD
SETUFR:	PUSHJ	P,GTUFR		;COMPUTE RIBUFD WORD
	  JRST	SETUF1		;OOPS
	MOVE	T1,.USMBF	;LOC OF MON BUF
	MOVEM	T2,RIBUFD##+1(T1)	;SAVE ADR IN RIB
FBMLOC:	POPJ	P,FBMERR	;AND RETURN

SETUF1:	SKIPN	DEVSFD##(F)	;IF THERE IS AN SFD,
	SKIPN	DEVUFB##(F)	; OR THERE IS NO UFB
	STOPCD	.,JOB,NUE,	;++NO UFB ERROR
WLKLOC:	POPJ	P,NCEERR	;UFD WAS DELETED - JUST RETURN
;SUBROUTINE TO FIND THE UFB BLOCK FOR A FILE
;ENTER WITH DEVFIL(F)=PRJ,PRG (DEVFIL,DEVEXT=A,B.UFD)
;EXIT CPOPJ IF NO UFB FOR FILE, CB RESOURCE RETURNED
;EXIT CPOPJ1 IF FOUND, WITH CB RESOURCE,
;T1=LOC OF PPB  AND T2=LOC OF UFB
;ENTER AT FNDUF1 WITH T1=PRJ,PRG FOR PPB TO BE SEARCHED
;ENTER WITH DEVACC=A.T. WHICH HAS RIGHT FSN, OR FSN ITSELF IN DEVACC
FNDUFB:	MOVE	T1,DEVFIL(F)	;UFD NAME
FNDUF1::PUSHJ	P,GETCB##	;GET CB RESOURCE
	HLRZ	T2,SYSPPB##	;%START OF PPB'S
	PUSHJ	P,LSTSCN##	;%TRY TO FIND THIS PPB
	  PJRST	GVCBJ##		;%NOT THERE - RETURN
	HRRZ	T1,DEVACC##(F)	;%FOUND.  GET FSN
	CAILE	T1,.FSMAX	;%ACTUAL FSN IF DEVACC LT FSNEND
	LDB	T1,ACZFSN##	;%A.T. LOC - GET FSN FROM ACCFSN
	PUSH	P,T2		;%SAVE LOC OF PPB
	HLRZ	T2,PPBUFB##(T2)	;%START OF UFB'S
	PUSHJ	P,BYTSCA##	;%SEARCH FOR MATCHING UFB
	  JRST	TPOPJ1##	;%FOUND - TAKE GOOD RETURN
	POP	P,T1		;%REMOVE GARBAGE FROM LIST
	PJRST	GVCBJ##		;%NOT THERE RETURN

;ROUTINE TO FIX THE VALUE OF RIBUSD IN THE RIB
;(ONLY THE VALUE IN UFBTAL IS KNOWN TO BE RIGHT)
;RESPECTS ALL ACS EXCEPT T1
FIXUSD:	HLRZ	T1,DEVEXT(F)	;RIBUSD IS ONLY MEANINGFUL FOR UFD
	CAIE	T1,'UFD'
	POPJ	P,
	PUSHJ	P,SAVT##
	PUSHJ	P,FNDUFB	;FIND THE UFB
	  POPJ	P,		;NOT THERE
	MOVE	T1,.USMBF	;%GET QUOTA FROM RIB
	MOVE	T3,RIBQTF##+1(T1)
	SUB	T3,UFBTAL##(T2)	;%MINUS AMOUNT LEFT
	MOVEM	T3,RIBUSD##+1(T1);%GIVES AMOUNT USED
	PJRST	GVCBJ##		;%GIVE UP CB
IFN FTDUFC,<
;DO NOT ALLOW A LOOKUP OF A DIRECTORY THAT IS BEING COMPRESSED
;MAKE LOOKUP BLOCK UNTIL THE COMPRESSOR IS DONE
CMPSLP:	PUSHJ	P,TSTSFD	;IS FILE A DIRECTORY?
	  CAIA			;YES
	POPJ	P,		;NO, LOOKUP IS OK
	CAIE	T1,'SFD'	;UFD OR SFD?
	JRST	CMPSL1		;UFD
	PUSHJ	P,UPAU##	;SFD, WAIT FOR COMPRESSOR TO FINISH
	PJRST	DWNAU##		;DIDN'T REALLY WANT AU ANYWAY
;HERE IF UFD
CMPSL1:	PUSHJ	P,FNDUFB	;FIND UFB (DEVUFB POINTS TO [1,1])
	  POPJ	P,		;NOT FOUND, COMPRESSOR NOT IN PROGRESS
	AOS	PPBCNT##(T1)	;%MAKE SURE UFB DOESN'T GO AWAY
	PUSHJ	P,GVCBJ##	;%NOW IT'S OK TO GIVE AWAY INTERLOCK
	EXCH	T2,DEVUFB##(F)	;POINT DDB AT RIGHT UFB
	PUSHJ	P,UPAU##	;WAIT FOR COMPRESSOR TO FINISH
	PUSHJ	P,DWNAU##	;DIDN'T REALLY WANT AU ANYWAY
	MOVEM	T2,DEVUFB##(F)	;POINT BACK AT [1,1]
	SOS	PPBCNT##(T1)	;PUT USE COUNT BACK
	POPJ	P,
>;END FTDUFC
;ERROR STUFF
ILNMEN:	MOVE	J,.CPJOB##
	POP	P,JBTSFD##(J)
	JRST	ILNMER
UILNMR:	MOVEI	T1,ISUERR
	AOJA	M,PUTERR
ILNMER:	TLZN	M,UUOREN	;IS ERROR CODE ALREADY IN T1?
	MOVEI	T1,FNFERR
	AOJA	M,LKENR2
UPDER7:	SKIPA	T1,FBMLOC	;%FILE BEING MODIFIED
UPDER5:	MOVEI	T1,FCUERR	;%FILE CANNOT BE UPDATED
	JRST	UPDERZ		;%GO STORE ERROR CODE
UPDER6:	HRRI	M,UUXEXT-UUXALC(M)
	HRRZ	T1,DEVACC##(F)
	PUSHJ	P,ENER11
	MOVEI	T1,FBMERR
PUTERR:	MOVE	T3,T1
	PUSHJ	P,GETWDU##
	HRR	T1,T3
	PJRST	PUTWDU##
RENER2:	PUSHJ	P,GVCBJ##
	SKIPA	T1,FBMLOC

NTFOUN:	MOVEI	T1,FNFERR
;HERE WITH M AT PPN
LKENER:	TLZA	T1,-1		;LH=0 MEANS LEAVE NMBCNT ALONE
LKENR4:	TLO	T1,-1		;LH=NON-0 MEANS DECREMENT NMBCNT
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;SPOOL-MODE?
	POPJ	P,		;YES, IMMEDIATE RETURN
>
	HRRI	M,UUNEXT-UUNPPN(M) ;RESET M FOR ERROR CODE DEPOSIT
	TLNE	M,EXTUUO
	HRRI	M,UUXEXT-UUXPPN-<UUNEXT-UUNPPN>(M) ;BUMP M FOR EXTENDED FORMAT
	TLNN	T1,-1
LKENR2:	TLZA	T1,-1		;LH=0 MEANS LEAVE NMBCNT ALONE
LKENR9:	TLO	T1,-1		;LH=NON-0 MEANS DECREMENT NMBCNT
	PUSHJ	P,SAVE2##	;PUT ERROR CODE IN A SAFE PLACE
	MOVE	P1,T1
	PUSHJ	P,GETWDU##
	HRR	T1,P1
	PUSHJ	P,PUTWDU##
	HRRZ	T1,DEVSFD##(F)	;JOB HAVE AN SFD?
	SKIPN	P2,T1
	JRST	LKENR3		;NO
	PUSHJ	P,GETCB##	;YES, GET INTERLOCK
	HLRZ	T2,NMBACC##(P2)	;%ADDR OF 1ST A.T.
	TRNN	T2,DIFNAL##	;%REALLY AN A.T.?
	HRL	P2,ACCPPB##(T2)	;%YES, GET ADDR OF PPB
	PUSHJ	P,GVCBJ##	;GIVE UP THE INTERLOCK
	HLRZ	T2,DEVSFD##(F)	;HAVE OLD SFD?
	CAMN	T1,T2		;NEW=OLD?
	JRST	LKENR3		;YES, USE COUNT NOT OP
	TLNE	M,UUOREN
	PUSHJ	P,DECUSA
	TLNN	M,UUOREN
	PUSHJ	P,DECALL	;NO, DECREMENT USE-COUNTS
	TLNE	P1,-1		;SHOULD WE DECREMENT NMBCNT?
	PUSHJ	P,DECUC		;YES, DO IT
LKENR3:	HLRZS	DEVSFD##(F)	;MAKE SURE NO NEW DIRECTORY
	TLNN	M,UUOUPD	;IF NOT AN UPDATE (E.G. FILE NOT OPEN)
	PUSHJ	P,TSTPPB	;CLEAR OUT PPB IF NOT LOGGED-IN
	PJRST	CLRSRB		;CLEAR IOSRIB AND RETURN
ENERR2:	PUSHJ	P,DECMST
	JRST	ENERR7
ENERR3:
ENERR4:	PUSHJ	P,DECMST
	POP	P,T2
ENERR5:	JUMPE	T1,ENERR7
ENERR1:	MOVEI	T1,BNFERR
	JRST	ENERR8
ENERR6:	SKIPA	T1,[TRNERR]
ENERR7:	MOVEI	T1,NRMERR
ENERR8:	HRRI	M,-1(M)		;DECREMENT M FOR ERROR CODE
	TLNE	M,EXTUUO	;EXTENDED FORMAT?
	HRRI	M,-<UUXALC-UUXEXT-1>(M)
	PUSH	P,T1
	TLNE	S,IOSDA
	PUSHJ	P,DWNDA##
	HRRZ	T1,DEVACC##(F)
	SKIPE	T1
	TLNN	M,UUOREN	;RENAME?
	JRST	ENER10
	PUSHJ	P,DECRDR	;YES, DECR READ COUNT
	  JFCL
	DMOVEM	T1,T3
	LDB	T1,ACZFSN##
	PUSHJ	P,FSNPS##	;POSITION BIT FOR STR
	HLRZ	T3,ACCNMB##(T3)
	TRZN	T3,DIFNAL	;FIND NMB
	JRST	.-2
	ANDCAM	T2,NMBYES##(T3)	;REMOVE FAILED - CLEAR YES BIT
	PUSHJ	P,GVCBJ##	;%
	HRRZ	T1,DEVACC##(F)
	HLLZS	DEVACC##(F)	;CLEAR DEVACC
	TRNN	T4,ACMCNT	;DONT RETURN A.T. TO FREE CORE IF OTHER READERS
ENER10:	PUSHJ	P,ENER11
	POP	P,T1
	JRST	LKENR2
RENER3:	SKIPA	T1,WLKLOC	;WRITE LOCK ERROR
RENER4:				;RENAME, NO LOOKUP OR ENTER
LUKER1:	MOVEI	T1,ISUERR	;LOOKUP, ENTER ALREADY IN FORCE
TSTWD0:	PUSHJ	P,GTWDT3
	SKIPE	T2,T3
	TLNE	T2,-1
	AOSA	M
	HRRI	M,UUXEXT(M)
	JRST	PUTERR

ENER11:	MOVEI	T2,ACPUPD	;UPDATE (BY THIS JOB)?
	TDNN	T2,ACCSTS##(T1)
	PJRST	ATRMOV##	;NO, ZAP THE AT
	ANDCAM	T2,ACCSTS##(T1)
	PUSHJ	P,DECSU		;YES, RESET AT, DDB NUMBERS
	PUSHJ	P,DECUC
	MOVSI	T2,-ACPWCT##
	ADDM	T2,ACCWCT##(T1)

	POPJ	P,		; AND DON'T WIRE THE AT
ENER12:	PUSHJ	P,DECMST
	HRRZ	T1,DEVACC##(F)	;ENTER DIDN'T HAPPEN SO A.T. WONT BE REMOVED
	PUSHJ	P,ATRMOV##	;BY OUTPUT CLOSE
	MOVE	T1,WLKLOC
	JRST	LKENER
RENER5:	PUSHJ	P,SFDDEC	;DROP THE COUNT
	SETZM	DEVSFD##(F)	;WIPE THE POINTER
RENER6:	MOVEI	T1,FNFERR	;FILE NOT FOUND
	JRST	TSTWD0		;DETERMINE WHERE TO STORE THE ERROR

UPDER8:	POP	P,(P)		;FIX STACK
	PUSHJ	P,INPSW8	;USETI TO BLOCK ONE
	MOVE	T1,DEVACC##(F)	;POINT TO ACC BLOCK
	PUSHJ	P,ENERR3	;FIX USE COUNTS
	HRRI	M,UUXEXT-UUXALC(M)
	MOVEI	T1,PRTERR	;GET PROTECTION ERROR CODE
	JRST	PUTERR		;STORE ERROR CODE

UPDER9:	MOVEI	T1,PRTERR	;%PROTECTION FAILURE
UPDERZ:	PUSHJ	P,GVCBJ1##	;%GIVE UP THE INTERLOCK
UPDERY:	MOVEI	T1,ISUERR	;ILLEGAL SEQUENCE OF UUO'S
	HRRI	M,UUXEXT-UUXPPN(M) ;POINT AT EXT
	TLNN	M,EXTUUO
	HRRI	M,UUNEXT-<UUNPPN+UUXEXT-UUXPPN>(M)
	PJRST	PUTERR
RENER7:	MOVEI	T1,PRTERR	;PRIVS WON'T ALLOW UPDATE
	JRST	LKENER
RENER8:	MOVEI	T1,SLLERR
	TLO	M,UUOREN
RENER9:	MOVSI	T2,DEPRAD##
	ANDCAM	T2,DEVRAD##(F)

	JRST	LKENR9
RENE10:	MOVEI	T3,FBMERR
	SETZ	T1,

RENE11:	HRRI	M,-5(M)
RENE12:	PUSHJ	P,CLREW
	SKIPN	T1		;NON-0 FROM CHKPRV
	SKIPA	T1,T3
	MOVEI	T1,PRTERR	;RENAME, NOT DELETE. NO PRIVS
	HRRI	M,-1(M)
	JRST	LKENR2
RENE13:	PUSHJ	P,CLREW
	MOVEI	T1,TRNERR
	JRST	LKENER



RENE14:	HRRI	M,-1(M)
RENE15:	HLRZS	DEVSFD##(F)
RENE16:	MOVEI	T1,PRTERR
	AOJA	M,PUTERR
RENE17:	PUSHJ	P,GVCBJ##
	PUSHJ	P,DWNAU##
RENE18:	MOVEI	T1,FBMERR
	AOJA	M,PUTERR
IFN FTEQDQ,<
RENE19:	PUSHJ	P,GVCBJ##
	PUSHJ	P,DWNAU##
	MOVEI	T1,NDRERR
	AOJA	M,PUTERR
>
RENE20:	PUSHJ	P,CLREW		;CLEAR RENAME IN PROGRESS
	PUSHJ	P,DECSU		;ADJUST COUNTS
	PUSHJ	P,DECUC
	MOVEI	T1,BNFERR	;GET ERROR
	HRRI	M,UUXEXT-UUXPRV(M)
	JRST	LKENR2		;CONTINUE

;PRESERVES ALL ACS
;BE CAREFUL NOT TO CALL THIS
;ROUTINE UNLESS YOUR'RE THE
;JOB THAT LIT ACPREN.
CLREW:	PUSH	P,T1
	MOVEI	T1,ACPREN
	ANDCAM	T1,ACCSTS##(P2)
	MOVSI	T1,DEPRAD##
	ANDCAM	T1,DEVRAD##(F)

	JRST	TPOPJ##

FUUEND:	END