Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93K-BB_1990 - 10,7/mon/comcon.mac
There are 14 other files named comcon.mac in the archive. Click here to see a list.
TITLE COMCON - COMMAND DECODER AND SAVEGET ROUTINES - V1751
SUBTTL /PFC/RCC/DAL/JBS		02-JAN-90

	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH
	SALL
	.DIRECT	FLBLST

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988,1990.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1990>

XP VCOMCN,1751		;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

COMCON::ENTRY	COMCON	;ALWAYS LOAD COMCON IF LIBRARY SEARCH

;CALLED FROM CLOCK ROUTINE WHEN 'COMCNT' IS GREATER THAN 0
;AS SET BY TTY SERVICE ROUTINE
;ALL AC'S HAVE BEEN SAVED BY CLOCK CHANNEL
;THE COMMAND DECODER CALLS TTYCOM WHICH SCANS FOR TTY WHICH TYPED
SUBTTL	TABLE OF CONTENTS
;               TABLE OF CONTENTS FOR COMCON
;
;
;                        SECTION                                   PAGE
;    1. TABLE OF CONTENTS.........................................   1
;    2. INTRODUCTION..............................................   3
;    3. COMMAND SETUP AND DISPATCH................................   5
;    4. COMMAND RETURN AND CLEANUP................................  12
;    5. COMMAND TABLE.............................................  14
;    6. CORE 0 COMMAND............................................  20
;    7. PJOB & KJOB COMMANDS......................................  21
;    8. START GROUP (START,CSTART,REE,DDT)........................  23
;    9. DUMP & DCORE COMMANDS.....................................  25
;   10. CONTROL-C PROCESSING......................................  26
;   11. SET COMMAND AND UUO
;        11.1   DISPATCH..........................................  29
;        11.2   JBSET.............................................  30
;        11.3   PRIVILEGE TESTS...................................  31
;        11.4   CORMAX AND CORMIN.................................  35
;        11.5   DAYTIME AND SCHED.................................  40
;        11.6   OPR, LOGMIN&MAX BATMIN&MAX........................  41
;        11.7   WATCH.............................................  42
;        11.8   DATE..............................................  44
;        11.9   SPOOL.............................................  45
;        11.10  DEFER/NODEFER.....................................  47
;        11.11  CDR...............................................  48
;        11.12  DISK STUFF........................................  49
;        11.13  ROUTINE TO READ DATE..............................  51
;        11.14  ROUTINES TO PRINT WATCH INFO......................  53
;   12. CONTINUE, CCONT AND JCONT.................................  57
;   13. CORE COMMAND..............................................  60
;   14. CONTROL-T PRINTOUT........................................  65
;   15. SAVE, SSAVE AND GET - COMMAND SETUP.......................  70
;   16. COMMANDS WHICH RUN PROGRAMS...............................  72
;   17. ASSIGN, DEASSIGN AND REASSIGN COMMANDS....................  75
;   18. ATTACH AND DETACH COMMANDS................................  92
;   19. DATASET CONNECT & SYSTEM START............................  99
;   20. DAYTIME COMMAND........................................... 100
;   21. RUNTIME ROUTINE (TIME COMMAND)............................ 101
;   22. SEND COMMAND.............................................. 102
;   23. VERSION COMMAND & PRVERS SUBROUTINE....................... 107
;   24. EXAMINE AND DEPOSIT COMMAND............................... 109

;CONTINUED ON NEXT PAGE
;   25. TTY COMMAND AND SET TTY COMMAND........................... 113
;   26. FINISH AND CLOSE COMMANDS................................. 123
;   27. SUBROUTINES
;        27.1   COMMAND SETUP..................................... 126
;        27.2   GET A WORD........................................ 127
;        27.3   GET CHARACTER..................................... 129
;        27.4   TYPE OUT ROUTINES................................. 130
;   28. SAVGET
;        28.1   PARAMETERS........................................ 143
;        28.2   COMMAND SCAN...................................... 144
;        28.3   RUN AND GETSEG UUO'S.............................. 147
;        28.4   SAVE A JOB........................................ 148
;        28.5   "EXE" SAVE FILES.................................. 151
;        28.6   GET AND RUN COMMANDS.............................. 177
;        28.7   RUN UUO........................................... 179
;        28.8   GETSEG UUO........................................ 182
;        28.9   COMMON CODE....................................... 183
;        28.10  GET FILE FROM DEVICE (R,RUN,GET,GETSEG)........... 186
;        28.11  IO ROUTINES....................................... 192
;        28.12  EXPAND COMPRESSED FILES........................... 195
;        28.13  SUBROUTINES....................................... 201
	SUBTTL	INTRODUCTION

;THE COMMAND AND THEN DISPATCHES(PUSHJ) TO APPROPRIATE
;COMMAND SETUP ROUTINE WITH AC'S SET AS:
;J = JOB NUMBER
;F = ADDRESS OF DEVICE DATA BLOCK TYPING COMMAND, IF ANY
;R = ADDRESS OF JOB'S CORE AREA, = 0 IF NO CORE
;S IS SET TO 0, USED FOR ADDRESS OF SUBSEQUENT CALLS
;U = ADDRESS OF LINE DATA BLOCK OF TTY TYPING COMMAND
;W = ADDRESS OF JOB'S PDB
;P4 = JOB STATUS WORD (C(JBTSTS(J)))
;P1 = 0 (USED FOR SAVGET FLAGS)
;P2 = COMMAND NAME (2ND NAME IF SET)
;THE PUSHDOWN LIST CONTAINS:
;LH(M) = 1B0=1B1= 1 (FLAG FOR COMMAND AT COMMAND LEVEL)
;      = 1B8-17= COMMAND TABLE ENTRY
;-1 (P) = U = ADDRESS OF LDB
;THE FOLLOWING GLOBAL USAGE PREVAILS:
;T3 LAST INPUT CHARACTER
;   ALSO TYPE OUT CHARACTER
;IN GENERAL, T1 - T4 AND P2 - 4 ARE SCRATCH
;AT COMMAND RETURN, IF J = 0 AND A
;  JOB WAS REQUIRED, AN ERROR IS ASSUMED.
;  ALL OTHER ACS CAN HAVE BEEN CHANGED
;UPON RETURN FROM COMMAND SETUP ROUTINE, A CR-LF IS ADDED TO
;MESSAGE AND TTY IS STARTED ON TTY SPECIFIED BY -1(P)
;SEVERAL COMMAND FLAGS ARE CHECKED BEFORE DISPATCHING TO
;COMMAND SETUP ROUTINES TO SEE IF COMMAND IS LEGAL AT THIS TIME
;SEVERAL MORE FLAGS ARE CHECKED UPON RETURN FROM COMMAND SETUP
;ROUTINES(UNLESS AN ERROR HAS OCCURRED) FOR STANDARD
;COMMAND RESPONSE
;IF AN ERROR OCCURS, THE JOB NO.(J) SHOULD BE 0 ON RETURN
;SO THAT JOB WILL NOT BE INITIALIZED IF FIRST COMMAND.
;ERRMES ROUTINE WILL SET J TO 0

;SINCE THE COMMAND DECODER IS CALLED FROM THE CLOCK ROUTINE
;COMMAND SETUP ROUTINE MUST RUN TO COMPLETION QUICKLY
;IF A COMMAND FUNCTION CANNOT DO THIS, IT MUST JUST SET
;THE JOB TO RUNABLE STATUS AND RETURN IMMEDIATELY
;OR DELAY THE COMMAND FOR LATER EXECUTION
;THE FOLLOWING AC USAGE PREVAILS FOR TTY IN/OUT:
;
;INPUT:	U=LDB, T3=CHARACTER		CLOBBERS T1
;
;	CTEXT CLOBBERS W, RETURNS T2=NAME
;	SKIPS		  RETURNS T2=0
;	DEC/OCT IN CLOBBERS P4, RETURNS T2=NUMBER
;	PJPGNO CLOBBERS T2,P4, RETURNS P2=USER
;
;
;OUTPUT:U=LDB, T3=CHARACTER		CLOBBERS T1,S
;
;	CONMES POINTER IN T1
;	OCTPNT/PRTDI8/RADX10 NUMBER IN T1
;		(PRTDI8 CLOBBERS T2)
;	PRNAME NAME IN T2

;P1 ASSIGNMENTS:
;
;PHONLY==1B0			;PHYSICAL ONLY
;INCREMENT==777777		;STARTING ADDRESS OFFSET
	SUBTTL	COMMAND SETUP AND DISPATCH

COMMAN::SE1ENT			;ENTER SECTION 1
	PUSHJ	P,TTYCOM##	;SETUP F,U,J, AND W
				; FOR ANY TTY WHICH HAS TYPED A COMMAND
	  JRST	[AOS CMNOTF##	;NONE FOUND, COUNT THE BUG
		 SOS COMCNT##	;ADJUST COUNT
		 POPJ P,]	;RETURN
IFN FTMP,<MOVEM J,COMJOB##>	;TO AVOID JOBSTS UUO RACE
	PUSHJ	P,SVEUB##	;SAVE EBR AND UBR AND SETUP UBR FOR
				; THE JOB THE COMMAND IS BEING EXECUTED FOR
	PUSH	P,U		;SAVE TTY LINE DATA BLOCK ADDRESS
	LDB	T1,LDPCMX##	;GET FORCED COMMAND INDEX, IF ANY
	MOVEM	T1,.CPLFC##	;SAVE IT FOR COMPARISON
	MOVSI	T2,LDBCMF##	;IS COMMAND FORCED?
	TDNN	T2,LDBCOM##(U)	; ..
	JRST	COM1		;NO, TRY USER COMMANDS
	MOVE	T2,TTFCOM##(T1)	;YES. GET SIXBIT NAME OF COMMAND
	JRST	COM1S		;GO FIND IT
COM1:	PUSHJ	P,CTEXT		;SCAN COMMAND NAME, RETURN IT IN T2
COM1Z:	CAIE	T3,"C"-100	;BREAK ON CONTROL-C?
	JRST	COM10		;NO, TRY LOGICAL NAMES
	MOVE	T2,HALTXT##	;YES--TURN COMMAND INTO HALT
	MOVEI	T1,HALTXT##-COMTAB## ;CALCULATE OFFSET IMMEDIATELY
	MOVE	P3,[XWD UNQTAB##,DISP##] ;SET P3=UNIQNESS BITS, DISPATCH TABLE
	MOVE	P4,[XWD -DISPL##,COMTAB##] ;SET P4=-LENGTH,TABLE LOC
	JRST	COM1E		;GO JOIN COMMON CODE
COM10:	CAMN	P4,[XWD -DISPL2##,COMTB2##] ;IN THE MIDDLE OF A SET COMMAND?
	JRST	COM1A		;YES, DON'T SEARCH LOGICAL NAMES
	JUMPE	T2,COM1S	;BLANK COMMAND CANNOT BE REDEFINED
	JUMPE	W,COM1S		;NO USER DEFINED COMMANDS IF NO PDB
	SKIPN	.PDCMN##(W)	;ANY USER DEFINED COMMANDS TO SEARCH THROUGH?
	JRST	COM1S		;THEN USE SYSTEM TABLES
	MOVE	T3,JBTSTS##(J)	;NEED TO SEARCH PATHOLOGICAL NAMES
	TLNN	T3,SWP!SHF	;IS JOB ON DISK OR ON ITS WAY?
	JRST	COM11		;NO, PROCEED
	HRRI	M,DLYCM		;YES, SET TO SWAP JOB IN
	PUSH	P,(P)		;KEEP THE STACK RIGHT
	JRST	COMDIS		;WAIT FOR IT TO COME IN
COM11:	CAMN	T2,[SIXBIT \R\]	;USER TYPED R COMMAND?
	JRST	COM1S		;YES, THIS CAN'T BE REDEFINED
	MOVE	P4,.PDCMN##(W)	;GET AOBJN POINTER TO COMMAND NAMES
	MOVE	P3,.PDUNQ##(W)	;GET POINTER TO UNIQNESS BITS
	MOVSI	T1,1		;FLAG INDICATING THIS IS USER-COMMAND SEARCH
	PUSHJ	P,FNDABV	;SEE IF WE CAN FIND A MATCH
	  JRST	COM1S		;NO, DEFAULT TO MONITOR'S COMMANDS
;HERE WE SEARCH MONITOR TABLE TO MAKE SURE NO UNIQUENESS CONFLICTS RESULT.
	TRNE	T3,CEXACT!CUNIQ	;DID WE MATCH EXACTLY OR UNIQUELY?
	JRST	COM11C		;YES, DON'T BOTHER WITH MONITOR COMMANDS
	PUSH	P,T1		;SAVE THE FLAGS,,DISPATCH
	PUSHJ	P,FNDCOM	;GO FIND THE COMMAND IN TABLES
	  JRST	COM11A		;ERROR, TAKE USER'S COMMAND
	POP	P,(P)		;ADJUST THE STACK
	JRST	COM1B		;GO JOIN COMMON CODE
				;HERE FOR USER COMMAND
COM11A:	POP	P,T1		;RESTORE THE DISPATCH AND FLAGS
	TRNE	T3,CAMBIG	;WAS THE COMMAND AMBIGUOUS?
	JRST	COM1A0		;YES, IT STILL IS
COM11C:	HLRZ	T3,T1		;SAVE BITS
	ADD	T1,.PDUNQ##(W)	;POINT TO DISPATCH FOR THIS COMMAND
	HRRZS	T1		;CLEAR SECTION CRUD
	HRL	P3,(T1)		;AND SAVE THE DISPATCH IN LH P3
	HRRI	P3,DISP##	;FOR LATER USE
	MOVEI	T1,PLNTXT##-COMTAB## ;SET UP FOR PATHOLOGICAL RUN COMMAND
	MOVE	P4,[XWD -DISPL##,COMTAB##] ;POINT BACK TO MAIN TABLES
	MOVE	P2,PLNTXT##	;GET SIXBIT COMMAND NAME
	JRST	COM1E		;GO JOIN COMMON CODE

;HERE TO SEARCH MAIN COMMAND TABLES
;	WITH	T2/	COMMAND
COM1S:	PUSHJ	P,FNDCOM	;FIND THE COMMAND IN THE TABLES
	  JRST	COM1A0		;NOT FOUND, SEE IF ON FRCLIN
	JRST	COM1B		;GO IF NO ERROR

;ENTRY POINT FOR "SET" COMMAND
COM1A:	SETZ	T1,		;NO FLAGS FOR FULL WORD LDB POINTER
	PUSHJ	P,FNDABV	;LOOK IT UP
	  TRNA			;ERROR
	JRST	COM1B		;GO IF NO ERROR
COM1A0:	MOVE	P2,LINTAB##+FRCLIN## ;GET LDB ADDRESS OF FRCLIN
	CAME	P2,U		;UNKNOWN COMMAND TYPED ON FRCLIN?
	JRST	NOSUCH		;USER MISTYPED
	MOVEI	T1,.RNTXT##-COMTAB## ;GET OFFSET OF .RUN COMMAND
	MOVE	P2,T2		;GET SIXBIT PROG NAME
COM1E:	HRL	M,UNQTAB##(T1)	;GET PREDISPATCH BITS
	HRR	M,DISP##(T1)	;AND GET THE DISPATCH ADDRESS
	MOVE	T2,UNQTAB##(T1)	;GET THE UNIQUENESS BITS
	CAME	P2,PLNTXT##	;USER-DEFINED COMMAND?
	JRST	COM1C		;NO, JOIN COMMON CODE
	TRZE	T3,CM.SAC##	;AUTO-PUSH FLAG LIT?
	TLO	T2,SACFLG	;YES, PROPAGATE
	JRST	COM1C		;AND RE-JOIN COMMON CODE
COM1B:	CAIL	T1,COMPIL##-COMTAB## ;COMPIL-CLASS COMMAND
	CAILE	T1,LASCCL##-COMTAB##
	TRNA			;NO
	MOVEI	T1,COMPIL##-COMTAB## ;FUDGE DISPATCH OFFSET FOR COMPIL
	MOVE	P2,T1		;CALCULATE THE OFFSET
	ADDI	P2,(P4)		; INTO THE COMMAND TABLE
	MOVE	P2,(P2)		;AND GET THE SIXBIT PROG NAME OR COMMAND
	HRRZ	M,P3		;GET DISPATCH
	ADDI	M,(T1)
	HRR	M,(M)
	HLRZ	T2,P3		;NOW POINT TO UNIQUENESS TABLE
	ADDI	T2,(T1)		;POINT TO THE COMMAND ENTRY
	HRL	M,(T2)		;GET THE BITS
	MOVE	T2,(T2)		;GET THE DISPATCH BITS
COM1C:	EXCH	T2,(P)		;SAVE TABLE OFFSET ON THE STACK
	PUSH	P,T2		; BUT KEEP U ON TOP
	ADDI	P3,(T1)		;POINT P3 TO DISPATCH ENTRY
	SKIPGE	T1		;SEE IF ERROR
	MOVEI	P3,COMERD##	;YES--SET DISPATCH
	HRRZ	P4,P3		;CLEAR LEFT HALF JUNK
	HRR	M,(P4)		;GET DISPATCH TABLE ENTRY
	MOVE	P4,JBTSTS##(J)	;JOB STATUS WORD FOR THIS JOB
;THE FOLLOWING CODE IS THE LAST NOSTALGIC VESTIGE OF FT2741
	TLNE	P4,JLOG		; WHILE NOT LOGGED IN?
	JRST	NT2741		;NO--LEAVE ALONE
	JUMPGE	T1,NT2741	;JUMP IF NOT COMMAND ERROR
	CAMN	T2,[SIXBIT .YQAOS.] ;DID HE TYPE LOGIN WITH WRONG BALL?
	HRRI	M,SET987	;YES--SET TTY ELEMENT 987
	CAMN	T2,[SIXBIT .VI.] ;MAYBE THE LEFT ONE?
	HRRI	M,SET988	;YES--SET TTY ELEMENT 988
	SET987==CPOPJ1##
	SET988==CPOPJ1##

NT2741:	TRNE	P4,JS.DEP	;IS JOB BEING STOPPED ON ERROR SO DAEMON CAN LOG?
	JRST	CHKDLY		;YES, DELAY COMMAND UNTIL DAEMON IS FINISHED LOGGING
	TLNE	P4,JLOG		;IS JOB LOGGED IN?
	JRST	CHKNO		;YES, PROCEED
	TLNN	M,NOLOGIN	;NO, CAN COMMAND PROCEED WITH NO LOGIN?
	JRST	LOGPLE		;NO, TYPE "LOGIN PLEASE"
	SKIPE	[M.RCMP##]	;MAYBE. ARE WE BEING PERMISSIVE?
	TLNE	M,NORCMP	;OR IS THIS COMMAND ALLOWED ANYWAY?
	JRST	CHKNO		;YES, PROCEED
	MOVEI	T1,LDRRMT##	;REMOTE BIT
	TDNN	T1,LDBDCH##(U)	;SEE IF DONE ON A LOCAL TERMINAL
	JRST	CHKNO		;YES, IT'S LEGAL
LOGPLE:	JSP	T1,COMER	;NO, TYPE "LOGIN PLEASE"
LOGPLM::ASCIZ	/LOGIN please
/
CHKNO:	SETZB	P1,R		;CLEAR PHYSICAL I/O FLAG, AND CORE LOCATION
	JUMPN	J,CHKRUN	;JOB NUMBER ALREADY ASSIGNED?
	TLNE	M,NOJOBN	;NO, DOES THIS COMMAND NEED A JOB NUMBER?
	JRST	COMGO		;NO
	MOVEI	J,1		;YES, SCAN FOR ONE STARTING WITH 1
NUMLOP:	HLLZ	P4,JBTST2##(J)	;FOR JS.SIP
	HLR	P4,JBTSTS##(J)	;FOR OTHER BITS
	TDNN	P4,[JS.SIP+JNA+JRQ+CMWB] ;OR ONE OF THESE?
IFN FTMP,<
	PUSHJ	P,ANYRUN##	;RUNNABLE ANYWHERE?
	  JRST	NUMLO1		;YES, JOB ISN'T REALLY AVAILABLE
	MOVE	P4,JBTSTS(J)	;KEEP REST OF CODE HAPPY
>
IFE FTMP,<
	SKIPA	P4,JBTSTS(J)	;KEEP OTHER CODE HAPPY
	  JRST	NUMLO1		;JOB ISN'T AVAILABLE
>
	JRST	NEWJOB
NUMLO1:	CAIGE	J,JOBMAX##	;YES, IS THE MAX. JOB NO.?
	AOJA	J,NUMLOP	;NO, KEEP LOOKING
	SKIPG	ARFLAG##	;SYSTEM STARTING UP?
	JRST	CHKDLY		;YES--DELAY IT
IFN FTNET,<
	MOVSI	T1,LDBCMF##	;WAS THIS COMMAND FORCED?
	TDNN	T1,LDBCOM##(U)
	JRST	NEWJER		;NO, OKAY TO COMPLAIN
	SKIPGE	LDBTTW##(U)	;IF ANF THEN PROBABLY .HELLO/.NETLD
	JRST	CHKDLY		;SO DELAY IT
>
NEWJER:	JSP	T1,COMER	;YES, NONE LEFT, PRINT "JOB CAPACITY EXCEEDED"
	ASCIZ	/Job capacity exceeded
/
NEWJED:	JSP	T1,COMER	;PRINT "NO FREE DDBs"
	ASCIZ	/Job capacity exceeded (No free TTY DDBs)
/
NEWJEP:	JSP	T1,COMER	;Not enough core
	ASCIZ	/Job capacity exceeded (No core for a PDB)
/
;EVEN THOUGH THIS IS A NEW JOB NUMBER
;IT MAY HAVE CORE ASSIGNED NOW BECAUSE IT WAS DELAYED
;UNTIL IT COULD BE SWAPPED IN(LOGIN WITH CORE FULL)

NEWJOB:	SKIPE	F,TTYTAB##(J)	;ANY TTY DDB?
	PUSHJ	P,TTYKIL##	;YES--KILL IT OFF
	SETZB	F,TTYTAB##(J)	;KEEP TTYATI HAPPY
	MOVE	U,(P)		;RESTORE U
	PUSHJ	P,TTYATI##	;TRY TO ATTACH TTY TO THIS JOB NUMBER
	  JRST	NEWJED		;IF CAN'T, NO DDB'S. SAY NO FREE DDBs
	PUSHJ	P,CREPDB##	;CREATE A PDB FOR THIS JOB
	  JRST	[PUSHJ	P,TTYKIL##  ;KILL TTY DDB OBTAINED ABOVE
		 JRST	NEWJEP]	;CAN'T GET A PDB, SAY SO
	SETZM	JBTPRG##(J)
	PUSHJ	P,CLRJBT##	;GO CLEAR ALL THE JOB TABLES AND PDB
	PUSHJ	P,ASICPT##	;ASSIGN INITIAL IN CORE PROTECT
	MOVE	T2,DATE##
	MOVEM	T2,JBTJLT##(J)
IFN FTMDA,<
	MOVEM	T2,.PDSTM##(W)	;INITIAL SETTING OF LAST RESET
> ;IFN FTMDA
	SKIPE	JBTADR##(J)	;CONTACT BOUNCE ON DLYCM?
	PUSHJ	P,MKADD##	;YES, MAKE SURE JOB IS ADDRESSABLE
IFN FTMP,<
	MOVEM	J,COMJOB##	;FOR PTYSER
>
	PUSHJ	P,CTLJBU##	;GET PTY DDB IF THERE IS ONE
	JUMPL	T1,NEWJB1	;JUMP IF NOT PTY CONTROLLED
	MOVSI	T1,DVDIBP	;GET BATCH PTY BIT
	MOVSI	T2,(JB.LBT)	;GET A BATCH JOB BIT
	TDNE	T1,DEVCHR(F)	;IS IT A BATCH PTY ?
	IORM	T2,JBTLIM##(J)	;YES, THEN ITS A BATCH JOB
NEWJB1:	HRRZ	F,LDBDDB##(U)	;RESTORE TTY DDB
	MOVEI	T1,BPTBIT##	;GET INITIAL VALUE OF JS.BPT
	DPB	T1,BPTPTR	;SET IT

	MOVE	T1,TIME##	;INITIALIZE TO TIME OF DAY
	TLO	T1,M.WCH##	;OR IN INITIAL SET WATCH BITS
				; (IN CASE THIS JOB GETS AUTOMATIC LOGIN)
	MOVEM	T1,JBTWCH##(J)	;STORE FOR THIS JOB
	CAMLE	J,HIGHJB##	;HIGHEST JOB NUMBER ASSIGNED?
	MOVEM	J,HIGHJB##	;YES,SAVE IT FOR SCHEDULER SCAN OF JOBS
IFN FTNET,<
	PUSHJ	P,FNDSTA##	;WHERE IS HE?
	DPB	T1,PDVSTA##	;THAT IS WHERE HIS TTY IS NOW
	HRRZM	T1,JBTLOC##(J)	;AND LOCATE HIM THERE
>
CHKRUN:
IFN FTMP,<
	TLNE	M,NORUN		;CAN COMMAND BE EXECUTED WHILE RUNNING?
	TLNE	P4,RUN		;YES, IS IT
	JRST	CHKRU1		;YES
	PUSHJ	P,ANYRUN##	;RUN BIT COULD BE OFF BUT THE JOB
	  JRST	CHKDLY		; COULD STILL BE THE CURRENT JOB ON ANOTHER CPU
>
CHKRU1:	TLNE	P4,RUN		;RUN BIT ON IN JOB STATUS?
	TLNN	M,NORUN		;YES, DOES THIS COMMAND REQUIRE A JOB?
	JRST	CHKBAT		;NO
	JSP	T1,COMER	;YES.
RUNERR::ASCIZ	/Please type ^C first
/

CHKBAT:	MOVE	T1,JBTLIM##(J)	;GET BATCH BIT
	TLNE	T1,(JB.LBT)	;SEE IF BATCH JOB
	TLNN	M,NBATCH	;YES--SEE IF ILLEGAL COMMAND
	JRST	CHKXO		;NO--OK TO PROCEED
	JSP	T1,COMER	;YES--BOMB USER
BATMSG:	ASCIZ	/Illegal in batch job
/


CHKXO:	TRNE	P4,JS.XO!JS.RUU	;SEE IF EXECUTE ONLY JOB
	TLNN	M,NXONLY	;YES--SEE IF ILLEGAL COMMAND
	JRST	CHKACT		;NO--OK TO PROCEED
	JSP	T1,COMER	;YES--BOMB USER
ILLXOM:	ASCIZ	/Illegal when execute only
/
CHKACT:	MOVE	R,JBTADR##(J)	;XWD PROTECTION,RELOCATION
	TLNE	M,INCORE	;MUST JOB NOT BE SWAPPING OR
				; IF JOB HAS CORE ASSIGNED, MUST IT BE
				; IN PHYSICAL CORE (RATHER THAN DISK OR ON ITS WAY)
	TLNN	P4,SWP!SHF	;YES, IS JOB ON DISK OR ON ITS WAY?
	JRST	CHKCO2		;NO
	HRRI	M,DLYCM		;ASSUME JOB MUST BE IN PHY CORE
				; SO SET TO SWAP JOB IN
	JRST	COMDIS		;WAIT FOR JOB
CHKDLY:	HRRI	M,DLYCM1	;NO, JUST DELAY COMMAND UNTIL SWAP OUT OR IN IS FINISHED
	JRST	COMDIS		;AND DISPATCH TO DELAY COMMAND

CHKCO2:	TLNE	M,NOACT		;CAN COMMAND BE PERFORMED WITH ACTIVE DEVICES?
	PUSHJ	P,RUNCHK	;NO, RETURN IF JOB STOPPED AND NO ACTIVE DEVICES
	TLNE	M,NOCORE	;DOES THIS COMMAND NEED CORE?
	JRST	COMGO		;NO. GO DISPATCH
	JUMPN	R,CHKXPN	;YES, IS CORE IN MEMORY?
	JSP	T1,COMER	;NO, PRINT "NO CORE ASSIGNED"
	ASCIZ	/No core assigned
/
CHKXPN:	TLNN	M,INCORE	;DOES THIS COMMAND NEED CORE TO BE EXPANDED?
	JRST	COMGO		;NO
	HLRE	S,USRHCU##	;YES, IS CORE STILL COMPRESSED(SAVE DID NOT GO
				; TO COMPLETION)
	JUMPGE	S,COMGO		;LH=-2 DURING SAVE, WHEN CORE COMPRESSED
				;LH=-1 DURING SAVE OF HIGH SEG, OR GET OF LOW
				; OR HIGH SEG
	CAME	P2,FCOTXT##	;IS THIS A FORCED CONTINUE?
	CAMN	P2,CONTXT##	; OR CONTINUE COMMAND?
	JRST	COMGO		;YES, DON'T EXPAND (LET SAVE FINISH)
	PUSHJ	P,CLRASA	;CLEAR EXEC MODE UUO FLAG
	AOJGE	S,COMGO		;JUMP IF DON'T NEED TO EXPAND
	S0PSHJ	EXPAND		;NO, EXPAND CORE FIRST
	  JFCL			;IGNORE ADDRESS CHECK ERROR, WE TRIED
	MOVSI	T1,JERR		;SET JERR SO CONT WON'T WIN
	IORM	T1,JBTSTS##(J)	; (WOULD GET ADR CHK IF ATTEMPTED)
	JRST	CHKDLY		;DELAY COMMAND BECAUSE COMMAND DECODER ACS ARE
				; ALL GONE, NEXT TIME JOBHCU WILL BE 0


NOSUCH:	PUSH	P,(P)		;SO COMDIS DOESN'T SCREW UP THE STACK
	SKIPA	M,[NOCOM]	;GET THE ERROR ROUTINE
COMER::	HRRI	M,ERRMES	;CALL ERROR MESSAGE ROUTINE
	HRLI	M,NOINCK!CMDERR ;SET APPROOPRIATE BITS

COMGO:	TLNN	P4,CMWB		; WAS JOB IN COMM WAIT
	TLZ	M,CMWRQ		;NO, CLEAR REQUEUE BIT IN DISP. FLAGS
	MOVSI	S,CMWB		;CLEAR CMWB
	ANDCAM	S,JBTSTS##(J)
	TLNE	P4,CMWB		;IF NOT IN COMMAND WAIT,
	SKIPN	.PDCMN##(W)	;OR NO USER-DEFINED COMMANDS,
	JRST	COMDIS		;THEN DON'T NEED THIS
	MOVSI	T2,LDBCMF##	;COMMAND FORCED BIT
	TDNN	T2,LDBCOM##(U)	;SEE IF ON
	TLO	M,CMWRQ		;NO, DEMAND A REQUEUE TO FIX UP AFTER DLYCOM

COMDIS:	POP	P,T2		;GET BACK THE OFFSET FROM THE STACK
	EXCH	T2,(P)		;KEEPING U THERE
	TLNE	M,CMDERR	;COMING IN FROM AN ERROR?
	JRST	COMDS1		;YES, JUST DISPATCH
	TLNN	M,CMWRQ		;CMWRQ ON IN PREDISPATCH? (SEE COMGO)
	TLZA	T2,CMWRQ	;NO, CLEAR IT IN POST DISPATCH FLAGS
	TLO	T2,CMWRQ	;YES, SET IT IN POST DISPATCH FLAGS
	HLL	M,T2		;NO, GET THE REAL FLAGS
COMDS1:	MOVEI	S,0		;CLEAR S FOR SETTING DISPATCH ADDRESSES
	TLO	M,FLMCOM!FLMCLV	;SET COMMAND AT COMMAND LEVEL FLAGS
	MOVEM	P,.CPISF##	;SAVE PDL FOR DLYCOM & ABORTC
	S0PSHJ	<(M)>		;DISPATCH TO COMMAND IN SECTION 0
	  JFCL			;IGNORE ERROR RETURN
	SUBTTL	COMMAND RETURN AND CLEANUP

;RETURN FROM COMMAND SETUP ROUTINE

COMRET:	NTDBUG	NO,EITHER	;STOP IF NETWORK INTERLOCK NOT RELEASED
	MOVE	T1,.CPLFC##	;GET FORCED COMMAND INDEX BACK
	POP	P,U		;RESTORE TTY LDB ADDRESS
	HRRZ	F,LDBDDB##(U)	;RESTORE TTY DDB IF ANY
	PUSHJ	P,TTYCMR##	;TELL SCNSER COMMAND IS COMPLETED
	SOS	COMCNT##
	AOS	COMTOT##	;KEEP COUNT OF TOTAL COMMANDS PROCESSED
				; (DO NOT COUNT DELAYED COMMANDS UNTIL PROCESSED)
	MOVSI	T1,1		;ALSO KEEP COUNT OF COMMANDS PROCESSED
	ADDM	T1,LDBBCT##(U)	;ON A PER-TERMINAL BASIS FOR ACCOUNT PURPOSES
	TLNN	M,ERRFLG	;ERROR?
	JRST	COMRT1		;NO, PROCEED
	SETZM	J		;YES, CLEAR J
	TLZ	M,NOFLM!NOCRLF!NOPER!TTYRNU!TTYRNC!TTYRNW!NOMESS	;ERROR--CLEAR PROBLEM BITS
	TLO	M,NOINCK+CMWRQ	;YES, JOB NUMBER REQUIRED, BUT NONE IN J.
				; PRINT ERROR MESSAGE ONLY, AND
				; REQUEUE JOB IF NECESSARY.

COMRT1:	MOVSI	P4,JNA		;JOB STATUS WORD
	TLNN	M,NOINCK	;SUPPRESS JOB INIT. CHECK?
	TDOE	P4,JBTSTS##(J)	;NO, IS JOB INIT BIT ALREADY SET?
	JRST	PCRLFA		;YES.
	MOVSI	P4,JNA		;GET JNA BIT AGAIN
	IORB	P4,JBTSTS##(J)	;NO, SO SET IT THIS COMMAND
	PUSHJ	P,TTYATI##	;ATTACH TTY TO JOB
	  JFCL			;IGNORE IF CAN NOT(SHOULD NEVER HAPPEN)
PCRLFA:	MOVEI	T1,JDCON	;CLEAR JDCON SO THAT A RUNNING JOB
	TLNE	M,TTYRNU!TTYRNC!TTYRNW	;WILL NOT BE THE "JCONT INVABLE" FROM
	ANDCAM	T1,JBTSTS##(J)	;ANOTHER TTY

	TLNE	M,NOMESS	;SEE IF MESSAGE SUPPRESSED
	JRST	PCRLF0		;YES--SKIP WATCH
	TLNE	M,TTYRNU!TTYRNC!TTYRNW	;COMMAND START JOB UP (TTY IN EITHER MODE)?
	S0PSHJ	WCHBEG		;YES, PRINT [HH:MM:SS] STARTED TO WAIT FOR RESPONSE
PCRLF0:	TLNN	M,NOFLM!NOCRLF	;SUPRESS CRLF?
	PUSHJ	P,CRLF		;NO
	TLNE	M,NOPER		;SUPRESS PRINTING PERIOD?
	JRST	PCRLF2		;YES
	PUSHJ	P,PRDOTM	;NO, GIVE A "."
	PUSHJ	P,CLRPCT##	;RESET STOP COUNTER
	PUSHJ	P,STRTDL##	;ALLOW A DEFERRED LINE TO ECHO IF NEEDED
PCRLF2:	JUMPE	J,PCRLF1	;JOB DOES NOT RUN IF ERROR OR NO JOB NO. ASSIGNED
	TLNE	M,TTYRNU	;JOB TO RUN WHEN TTY FINISHED TYPING?
				; COMMAND RESPONSE (TTY TO USER MODE)?
	PUSHJ	P,TTYUSR##	;YES, CALL SCANNER AND SCHEDULER ROUTINES
	TLNE	M,TTYRNW	;COMMAND RESTART TTY RESPECTING IO WAIT?
	PUSHJ	P,TTYUSW##	;YES. CALL SCANNER ROUTINE AND SCHEDULER
	TLNE	M,TTYRNC	;NO, JOB TO RUN AND REMAIN IN MONITOR MODE?
	PUSHJ	P,SETRUN##	;YES, CALL SCHEDULER ROUTINE
PCRLF1:	TLNN	M,NOMESS	;IS THERE A MESSAGE?
	PUSHJ	P,TTYSTR##	;YES, START TTY TYPING IT OUT
	TLNE	M,ERRFLG	;WAS AN ERROR?
	PUSHJ	P,TSETBI##	;YES--CLEAR TYPE-AHEAD
	JUMPE	F,PCRLF5	;DON'T KILL NON-EXISTENT DDBS
	TLNN	M,NOJOBN	;WAS NO JOB NUMBER NEEDED?
	TLNE	M,ERRFLG	;OR DID AN ERROR OCCUR?
	CAIA
	JRST	PCRLF5
	MOVSI	T1,JNA		;GET JNA
	LDB	T2,PJOBN##	;AND JOB NUMBER
	SKIPE	T2		;HAVE A JOB?
	TDNE	T1,JBTSTS##(T2)	;AND IS JOB NUMBER ASSIGNED?
	JRST	PCRLF4		;KILL OFF TTY IF IDLE
	MOVEI	J,(T2)		;COPY JOB NUMBER
	SETZM	TTYTAB##(J)	;ZAP TTY DDB POINTER
	PUSHJ	P,TTYKIL##	;RETURN TTY DDB TO FREE POOL
	PUSHJ	P,KILPDB##	;GIVE BACK PDB CORE
	TDZA	J,J		;DON'T CONFUSE THINGS
PCRLF4:	PUSHJ	P,TTYKLQ##	;KILL OFF TTY IF IDLE
PCRLF5:	PUSHJ	P,DECHJB##	;DECREMENT HIGHJB IF APPROPRIATE
IFN FTMP,<
	SETOM	COMJOB##	;NO JOB IN COMCON NOW
>
	JUMPE	F,CPOPJ##	;IF NO JOB, QUIT
	MOVSI	T1,LDBDET##	;SHOULD LINE BE DETACHED?
	TDNN	T1,LDBCOM##(U)	;DELAYED BECAUSE OF CMW
	JRST	PCRLF3
	ANDCAM	T1,LDBCOM##(U)
	PUSHJ	P,PTYDET##	;YES, DO IT NOW
PCRLF3:	LDB	J,PJOBN##	;GET ATTACHED JOB # FROM TTY DDB
	JUMPE	J,CPOPJ##
	CAME	J,.CPJOB##	;NEVER SET JRQ FOR CURRENT JOB!
	TLNN	M,CMWRQ		;REQUEUE JOB AFTER COMMAND WAIT OR ERROR?
	POPJ	P,
	JRST	REQUE##		;YES
	SUBTTL	CORE 0 COMMAND

COR0:	JUMPE	R,CPOPJ##	;RETURN IF JOB DOES NOT HAVE CORE

IFN FTFDAE,<
	PUSHJ	P,CHKXTM	;SEE IF AN "EXIT" MESSAGE SHOULD
				; BE SENT TO THE FILE DAEMON AND IF
				; SO, SEND IT.
>
	JSP	T2,MONJOB##	;SET TO RUN MONITOR JOB(PC IN EXEC MODE)
				; RETURN HERE AT UUO LEVEL(NO ACS SET UP)
	MOVEI	T2,ESTOP##	;PUT ERROR STOP ON END OF PDL
	JSP	T1,MONSTR##	;START MONITOR JOB BY SETTING UP ACS AND
JOB1::	MOVSI	T1,JERR		;TURN OFF JERR
	ANDCAM	T1,JBTSTS##(J)	;..
	PUSHJ	P,RESET##	;RELEASE ALL IO DEVICES ASSIGNED TO THIS JOB
IFN FTFDAE,<
	PUSHJ	P,CALLF		;NEED TO CALL FILDAE FOR THIS JOB?
	  PUSHJ	P,SNDFXM	;YES, SEND FILDAE AN EXIT MESSAGE
>
JOB1A::	MOVSI	T1,JERR		;TURN OFF JERR
	ANDCAM	T1,JBTSTS##(J)	;..
	PUSHJ	P,TTYFNU##	;FIND TTY FOR THIS JOB(SETUP J WITH JOB NO.)
IFN FTMP,<
	PUSHJ	P,UPMM##	;MUST HAVE THE MM RESOURCE
	JRST	ZAPPG1		;ZAP THE PROGRAM (UUO LEVEL STYLE)
>
ZAPPGM::
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET MEMORY MANAGEMENT RESOURCE
	  JRST	.-1		;MUST WAIT IF NOT AVAILABLE
>
ZAPPG1:	PUSHJ	P,KILHGA##	;HIGH SEG FOR THIS USER, RETURN CORE
				; REMOVE HIGH SEG FROM THIS USER
				; LOGICAL ADDRESSING SPACE
				; IF NO OTHER USERS IN CORE ARE USING IT
				; RETURN DISK SPACE IF NO LONGER SHARABLE HIGH SEG
	PUSHJ	P,INTLVL##	;AT CLOCK LEVEL?
	  PUSHJ	P,DSKFLS##	;NO, UUO, CLOBBER ANY POSSIBLE DISK PAGES
	PUSHJ	P,NOCORQ##	;PUT JOB IN NO CORE Q
	PUSHJ	P,CLRTAB	;CLEAR BITS AND TABLE ENTRIES
	MOVSI	T1,(PD.LGO)	;IF A LOGOUT UUO IS IN PROGRESS,
	TDNE	T1,.PDDFL##(W)	; ..
	JRST	JOB2		; ALWAYS DELETE ALL CORE
	MOVSI	T1,JLOG		;IF NOT LOGGED IN
	SKIPN	.CPISF##	; OR COMING FROM ERRCON
	TDNN	T1,JBTSTS##(J)
	JRST	JOB2		;ALWAYS DELETE FUNNY PAGES
	LDB	T1,NFYPGS##	;ANY MONITOR FREE CORE PAGES?
	CAIN	T1,UPMPSZ##+1
	JRST	JOB2		;NO, RETURN CORE
	MOVE	T1,[.JDAT,,.JDAT+1] ;ZERO JOB DATA AREA
	SETZM	.JDAT		;JOBSA, JOBDDT, ETC.
	SETZM	USRDDT##	;AND REMEMBERED COPY
	BLT	T1,.JDAT+PG.BDY ; AND THE REST OF PAGE 0 IN CASE XO
IFE FTMP,<
	POPJ	P,		;YES, JUST RETURN
>
IFN FTMP,<
	PJRST	GIVMM##
>
JOB2:	SKIPE	T1,JBTADR##(J)	;SKIP THIS IF NO CORE
	PUSHJ	P,VMSIZE##	;VIRTUAL SIZE OF THE JOB
	LDB	T2,NFYPGS##	;NUMBER OF FUNNY PAGES
	ADDI	T1,-UPMPSZ##(T2) ;VMSIZE ADDED UPMP SIZE
	ADDM	T1,VIRTAL##	;VIRTUAL CORE RETURNED
	PUSHJ	P,ZERSWP##	;RETURNED SWAPPING SPACE
	PUSHJ	P,FNDPDS##	;MAKE SURE W POINTS TO PDB
	SETZM	.PDCMN##(W)	;CLEAR POINTER TO COMMAND NAMES
	SETZM	.PDUNQ##(W)	;CLEAR POINTER TO UNIQNESS BITS
	PUSHJ	P,UUOLVL##	;AT UUO LEVEL?
	  JRST	JOB3		;NO
	MOVE	T1,(P)		;YES, CAN'T USE STACK IN THE
	MOVE	P,.CPNPD##	; UPMP AFTER GIVING THE
	PUSH	P,T1		; UPMP BACK TO FREE CORE
JOB3:	PUSHJ	P,KCORE1##
	SETZM	.CPADR##
	SETZM	JBTIMI##(J)	;NO VIRTUAL CORE
	SETZM	JBTIMO##(J)	;...
	SETZM	JBTSWP##(J)
IFN FTMP,<
	PJRST	GIVMM##		;RETURN THE MM RESOURCE
>
IFE FTMP,<
	POPJ	P,
>
	SUBTTL	PJOB & KJOB COMMANDS

; "PJOB" PRINT JOB NUMBER OF JOB TTY IS ATTACHED TO


PJOB::	MOVE	T1,J		;JOB NO.
DECLF::	PUSHJ	P,RADX10	;PRINT T1 AS DEC. THEN CRLF
	JRST	CRLF


;THIS PRINTS OUT:
;
; JOB N USER NAME [P,PN] TTY#
;
PJOBX:: PUSHJ	P,SAVJW##	;SAVE J(W GETS A RIDE)
	PUSHJ	P,GETJOB	;GET JOB NUMBER TO DO PJOB ON
	  SKIPA			;NO JOB NUMBER SO USE CURRENT JOB
	MOVE	J,T2		;PUT REQUESTED JOB NUMBER IN AC(J)
	JUMPE	J,ATT4		;ERROR IF NO JOB ASSIGNED
	PUSHJ	P,INLMES	;GIVE FOLLOWING MESSAGE
	ASCIZ	\Job \		;
	MOVE	T1,J		;PRINT THE
	PUSHJ	P,RADX10	; JOB NUMBER
	PUSHJ	P,INLMES	;GIVE FOLLOWING MESSAGE
	ASCIZ	\   User \		;
	PUSHJ	P,FNDPDB##	;SEE IF A PDB AND POINT AC(W) TO IT
	  JRST	PJOBX2		;NO PDB, SO CAN'T PRINT USERS NAME
	MOVE	T2,.PDNM1##(W)	;GET FIRST PART OF USERS NAME
	SKIPN	.PDNM2##(W)	;PRINT IT
	  JRST	PJOBX1		;GET USERS NAME
	PUSHJ	P,PRSIXB	;IF LAST PART IS NULL WE'RE DONE
				; WITH THE NAME PRINTOUT
	MOVE	T2,.PDNM2##(W)	;DOES FIRST NAME END WITH A SPACE?
PJOBX1:	PUSHJ	P,PRNAME
PJOBX2:	PUSHJ	P,PR3SPC	;GIVE A SPACE
	MOVE	T2,JBTPPN##(J)	;GET PPN
	PUSHJ	P,PRTPPN	;PRINT PPN
	PUSHJ	P,PR3SPC
	MOVE	T2,@TTYTAB##(J)	;GET TTY NAME
	TLNN	T2,-1		;DETACHED?
	HRLI	T2,'DET'	;YES
	PUSHJ	P,PRNAME	;PRINT THE TTY NAME
	PJRST	CRLF		;END WITH A CRLF
; "KJOB" KILL ATTACHED JOB

KJOB::	SKIPE	J		;WAS JOB INITIALIZED?
	TLNN	P4,JNA		;JOB ASSIGNED?
	SKIPA			;NO
	JRST	KJOB3		;GO RUN LOGOUT
	SE1ENT			;ENTER SECTION ONE
IFN FTNET,<
	SKIPGE	LDBREM##(U)	;IF SET HOST IN PROGRESS,
	JRST	KJOB2		;JUST BE QUIET ABOUT IT
> ;END IFN FTNET
	PUSHJ	P,SKIPS1	;EAT LEADING SPACES AND TABS
	  JRST	KJOB1		;EOL
	CAIE	T3,"/"		;WE EXPECT A SWITCH AT THIS POINT
	JRST	COMERA		;CONFUSED USER
	PUSHJ	P,CTEXT		;GET A KEYWORD
	JUMPE	T2,COMERA	;CONFUSED USER
	MOVE	T1,[-1,,[SIXBIT/DISCON/]] ;TABLE POINTER
	PUSHJ	P,FNDNAM	;AND SEARCH IT
	  JRST	COMERA		;AMBIGUOUS OR UNKNOWN
KJOB1:	PUSHJ	P,TOPDSF##	;HANG UP THE DATASET
	  JFCL			;CAN'T
IFN FTNET,<
	PUSHJ	P,TOPDNT##	;DO A NETWORK DISCONNECT
	  JFCL			;CAN'T
	SKIPGE	LDBREM##(U)	;IF SET HOST,
KJOB2:	TLOA	M,NOCRLP!NOFLM	;BE SILENT
> ;END IFN FTNET
	TLO	M,ERRFLG	;EXIT COMMAND PROCESSING CLEANLY
	MOVEI	J,0		;DITTO
	POPJ	P,		;DONE

KJOB3:	TLNN	P4,JLOG		;TEST JLOG ALSO IN CASE JOB NOT LOGGED IN
	JRST	KJOB4		;IF JOB NOT LOGGED IN
	PUSHJ	P,TTYATI##	;ATTACH TTY
	  JFCL
	TLO	M,TTYRNU	;SET TTYRNU FOR COMRET
	MOVSI	P1,PHONLY	;SET PHYSICAL I/O FORCE SYSTEM KJOB
	MOVSI	T1,(JS.BPR)	;SET BYPASS PROGRAM TO RUN
	IORM	T1,JBTST2##(J)	;TO INSURE KJOB REALLY RUNS

IFN FTMP,<
	PUSHJ	P,ALLJSP##	;SET CPU SPECIFICATION TO MAKE JOB RUNNABLE
				; ON ALL CPU'S. THIS ALSO LEAVES A REASONABLE
				; SPECIFICATION FOR THE NEXT USER WHO GETS
				; THIS JOB NUMBER
> ;END IFN FTMP
	HRRZ	T1,.PDCVL##(W)	;GET PHYSICAL LIMIT
	TRZ	T1,400000	;IGNORE LIMIT/GUIDELINE
	SKIPN	T1		;IF NO LIMIT HERE,
	HRRZ	T1,.PDMVL##(W)	;GET MPPL
	SKIPN	T1		;IF NOT LIMITED,
	MOVEI	T1,LOGSIZ##	;FIX THE COMPARE BELOW
	MOVEI	T2,LOGSIZ##	;GET SIZE TO RUN LOGIN
	CAIGE	T1,(T2)		;IF NOT ENOUGH,
	HRRM	T2,.PDCVL##(W)	;MAKE IT ENOUGH
	MOVE	P2,LGINAM##	;GET 'LOGIN'
	JRST	RUNAME		;GO RUN CUSP

KJOB4:	PUSHJ	P,GETCIC	;GET MINIMAL JOB AREA ON DISK OR CORE
IFN FTNET,<
	SE1ENT
	SKIPGE	LDBREM##(U)	;IF SET HOST IN PROGRESS,
	TLO	M,NOCRLP!NOFLM	;DON'T DO TYPEOUT
> ;END IFN FTNET
	JSP	T2,MONJOB##	;SCHEDULE MONITOR JOB (PC IN EXEC MODE)
				; RETURN HERE AT UUO LEVEL WHEN SCHEDULED
JOBKL::
IFN FTXMON,<JRST @[0,,.+1]> 	;MUST RUN IN SECTION 0
	MOVEI	T2,ESTOP##	;PUT ESTOP ON END OF PDL
	JSP	T1,MONSTR##	;GO SETUP ACS AND PD LIST AT UUO LEVEL
				;RETURN HERE AT UUO LEVEL AFTER BEING SCHEDULED
	MOVSI	T1,JERR		;TURN OFF JERR
	ANDCAM	T1,JBTSTS##(J)	;..
	SETZM	.JDAT+.JBINT##	;NO OLD-STYLE TRAPPING EITHER
	PUSHJ	P,RESET##	;ZAP PSI, IPCF STUFF, ETC.  HANDLE ^C CORRECTLY
IFN FTMP,<	                ;IF SMP
 	PUSHJ	P,ONCPU0##	;MAKE SURE WE CAN'T MESS UP COMMAND PROCESSING
>; END IFN FTMP
	PUSHJ	P,CTXLGO##	;DELETE ALL IDLE CONTEXTS
IFN FTSCA,<
	PUSHJ	P,SCSLGO##	;TELL SCSUUO JOB IS GONE
>; END IFN FTSCA
	PUSHJ	P,ENQLGO##	;TELL QUESER THAT ETERNAL LOCKS GO AWAY NOW
IFN FTDECNET,<
IFE FTXMON,<DNCALL (SCULGO##)>	;TELL SCMUUO THAT JOB IS GOING AWAY
IFN FTXMON,<SNCALL (SCULGO##,MS.HGH)> ;TELL SCMUUO THAT JOB IS GOING AWAY
>; END IFN FTDECNET
	PUSHJ	P,DSKKJB##	;CLEAR UP CORE BLOCKS ON A KJOB COMMAND
				; MAY GO INTO WAIT, SO DO BEFORE GIVING UP USER CORE

	JUMPE	W,JOBKL1	;IF THIS JOB HAS A PDB,
IFN FTKL10,<
	PUSHJ	P,BRKDEC	;MAKE SURE ADDRESS BREAK COUNT IS DECREMENTED,
				; IF NEED BE.
>
	PUSHJ	P,KILJSL##	;DESTROY THE JSL (GET MOUNT COUNTS RIGHT)
JOBKL1:	PUSHJ	P,DEASTY	;DEASSIGN ALL BUT TTY
	PUSHJ	P,IPCLGO##	;TELL [SYSTEM] INFO THAT JOB IS GONE
	PUSHJ	P,JOB1		;FLUSH CORE AFTER RELEASING DEVICES
	PUSHJ	P,FNDPDS##	;TAPUUO COULD USE W
	PUSHJ	P,TTYSRC##	;FIND THE TTY FOR THIS JOB
	  SETZ	F,		;NONE?
	SKIPE	F		;IF THERE'S A TTY DDB,
	PUSHJ	P,TTYKIL##	;RETURN TTY TO VIRGIN STATE
	JRST	KSTOP##		;CLEAR JOB STATUS WORD AND STOP JOB
	SUBTTL	START GROUP (START,CSTART,REE,DDT)

; "START L" OR "START" - START AT LOC. L OR STARTING ADDRESS

START::				;SAME AS CSTART, DIFF BY COMTAB BITS
				; WHICH PUT TTY IN MONITOR OR USER MODE

; "CSTART L" OR  "CSTART" - START AT LOC. L(TTY IN COMMAND MODE)


STARTC::MOVE	P3,P4		;SAVE STATUS
	PUSHJ	P,OCTPAR	;READ A NUMBER IF PRESENT
	  JRST	SNOARG		;NO ARG SPECIFIED RETURN
	TLNN	P3,JLOG		;IS IT LOGGED IN?
	JRST	STARTE		;NO--ERROR
	TRNE	P3,JS.XO!JS.RUU	;SEE IF EXECUTE ONLY
	JRST	ILLXO		;YES -- BOMB USER
	PUSHJ	P,CHKMED##	;CHECK TO SEE IF HIGH SEG WHICH IS SHARABLE
				; IF YES, TURN ON USER MODE WRITE PROTECT
				; FOR THIS USER, AND SET MEDDLE BIT SO HE CANNOT
				; TURN UWP OFF.
	JRST	STARTN		;START IN USER MODE

STARTE:	MOVEI	T1,LOGPLM	;SETUP ERROR MESSAGE
	PJRST	ERRMES		;GO ISSUE IT

ILLXO:	MOVEI	T1,ILLXOM	;GET ERROR MESSAGE
	PJRST	ERRMES		;GO ISSUE IT
;"REENTER" - REENTER USER PROGRAM


REENTE::SKIPN	T2,JBTADR##(J)
	JRST	CHKPCM		;NO ADDRESS IF NO CORE
	HRRZ	T2,.JDAT+.JBREN##	;GET ADDRESS FROM JOBDAT
	SKIPN	T1,.USUSA	;ANY SORT OF ENTRY VECTOR?
	JRST	CHKPCM		;NO, GO CHECK FOR /USE SECTION
	JUMPE	J,STARTE	;YES, BUT MUSTN'T ALLOW THIS IF NOT A JOB
	HLL	T2,T1		;HAVE ONE, MERGE IN ITS SECTION
	TLNN	T2,370000	;IS THIS JUST A START ADDRESS?
	JRST	STARTN		;YES, ONLY WANT ITS SECTION NUMBER
	AOS	T2,T1		;NO, OFFSET TO REENTRY ADDRESS IN ENTRY VECTOR
	TLNN	T2,360000	;IS THE VECTOR LONG ENOUGH?
	TDZA	T2,T2		;NO, CLEAR THE ADDRESS
	TLZ	T2,770000	;YES, ISOLATE THE ADDRESS FROM ITS BITS
	JUMPE	T2,CHKSTR	;BOMB USER IF NO ADDRESS
	PJRST	SNOAR2		;GET ADDRESS AT UUO LEVEL AND START THE USER

; "DDT" - START EXECUTION AT DDT IN USER AREA


DDTGO::	JUMPE	R,STARTE	;ERROR IF NO CORE (NOT A JOB)

	HRRZ	T2,.JDAT+JOBDDT##	;DDT STARTING ADR. IN JOB DATA AREA
IFN FTXMON,<
	HLLZ	T1,.USUSA	;GET ENTRY VECTOR SECTION
	TLZ	T1,770000	;CLEAR OUT BITS
	SKIPE	T2		;PRESERVE ZERO
	ADD	T2,T1		;OFFSET DDT TO THAT SECTION
> ;END IFN FTXMON
	SKIPN	.USUSA		;IF THERE IS NO ENTRY VECTOR,
	JUMPN	T2,CHKPCM	;OK IF WE HAVE DDT
	JUMPN	T2,STARTN	;IGNORE /USE SECTION IF ENTRY VECTOR
	TLNN	P4,JLOG		;MAKE SURE LOGGED IN
	JRST	CHKPCM		;NOT BOMB HIM
	TRNN	P4,JS.XO!JS.RUU ;SKIP IF EXECUTE ONLY
	PJRST	GETDDT##	;MERGE IN DDT


CHKPCM:	JUMPE	J,STARTE	;ERROR IF NOT A JOB (DDT,REENTER)
	JUMPE	T2,CHKSTR	;IS A START ADR SPECIFIED? (ERROR IF 0)
IFN FTXMON,<
	MOVE	T1,.USUSN	;GET SECTION #
	LSH	T1,P2WLSH	;POSITION
	ADD	T2,T1		;MAKE FULL WORD ADDRESS
> ;END IFN FTXMON
STARTN:	MOVE	T1,USRPC##	;YES, GET JOB'S PC
	HLR	T1,JBTSTS##(J)	;AND JOB STATUS BITS
	TDNE	T1,[XWD USRMOD,JERR]	;IS JOB IN USER MODE, OR STOPPED ON AN ERROR?
	JRST	USTART##	;YES, START HIM UP NOW
	MOVE	T1,T2		;GET START ADDRESS
	PUSHJ	P,SETUTP##	;SETUP UUO TRAP
	  JRST	USTART##	;START USER
	JRST	RSTART##	;CLEAR STATUS FLAGS AND START JOB
				; IN MIDDLE OF MONITOR WHERE IT STOPPED

;HERE TO START USER WHEN NO START ADR TYPED IN
SNOARG:	SKIPN	T2,JBTADR##(J)
	JRST	CHKSTR		;NO START ADDR IF NOT IN CORE
	SKIPE	T2,.USUSA	;START ADDR SPECIFIED ON GET/RUN COMMAND?
	JRST	SNOAR1		;YES, SEE ABOUT USING IT
	HRRZ	T2,.JDAT+JOBSA##	;START ADR. SPECIFIED BY LINKING LOADER
				; FROM END STATEMENT
	JUMPE	T2,CHKSTR	;IF ZERO, FORGET IT
IFN FTXMON,<
	MOVE	T1,.USUSN	;SECTION NUMBER USER SPECIFIED
	LSH	T1,P2WLSH	;WHERE IT BELONGS
	ADD	T2,T1		;30 BIT START ADDRESS
	TLZ	T2,770000	;CLEAR POSSIBLE BITS
> ;END IFN FTXMON
	HLLZM	T2,.USUSA	;SAVE FOR NEXT TIME
				;FALL INTO CHKSTR
;HERE TO CHECK TO SEE IF STARTING ADDRESS IS NON-ZERO, AND START USER IF OK

CHKSTR:	JUMPE	J,STARTE	;ERROR IF NOT A JOB
	TLZ	T2,770000	;CLEAR SPECIFIED BY COMMAND BIT
	JUMPN	T2,USTART##	;IS IT NON-ZERO?, IF YES
				; STORE OLD PC IN JOBOPC IN JOB DATA AREA
				; THEN START WITH PC IN USER MODE
	JSP	T1,ERRMES	;NO, PRINT "NO START ADR"
MESNSA:	ASCIZ	/No start address
/

SNOAR1:	CAIN	T2,1		;IS THIS SPECIAL S0 JOBDAT
	HRRZ	T2,.JDAT+.JBSA## ;YES, FIX IT
	TRNE	T2,-1		;IS THIS A FAKE JOBDAT ENTRY?
	TLNE	T2,370000	;OR A REAL ENTRY VECTOR?
	TRNA			;YES OR YES, NEED SAVCTX
	JRST	CHKSTR		;NO, JUST A START ADDRESS, SO TRY IT
SNOAR2:	MOVE	S,T2		;YES, SAVE ACROSS SAVCTX
	JSP	T2,SAVCTX##	;GET TO UUO LEVEL
	MOVE	T2,S		;RESTORE ENTRY VECTOR ADDRESS
	PUSHJ	P,GSADDR	;GET THE RIGHT START ADDRESS
	;PJRST	STARTV

STARTV:	SETZ	F,		;FOR USRXIT (AVOID IME)
	TRNE	T2,777700	;REASONABLE ADDRESS?
	JRST	STARTU		;YES, USE IT
	PUSHJ	P,PPQCRL	;NO, START UP AN ERROR MESSAGE
	PJRST	URUNSB		;COMPLAIN OF 'NO START ADDRESS'

GSADDR::PUSH	P,M		;SAVE FOR SAVCTX RETURN
	MOVE	M,T2		;PUT WHERE FETCH ROUTINES EXPECT IT
	TLZ	M,770000	;CLEAR OUT JUNK
	JUMPE	M,GSADD0	;DON'T FETCH IF JUNK
	CAIN	T2,1		;IF S0 JOBDAT,
	SETZ	T2,		;FIX IT UP
	TDNN	T2,[BYTE (6)37(12)(18)-1] ;IF NO LENGTH AND NO IN-SECTION ADDRESS,
	HRRI	M,.JBSA##	;FIX UP THE REFERENCE ADDRESS
	PUSHJ	P,PFHMWD##	;READ A WORD FROM THE USER'S ADDRESS SPACE
	  SETZB	T1,M		;INVALID ADDRESS
	TDNN	T2,[BYTE (6)37(12)(18)-1] ;IF SPECIAL JOBDAT REFERENCE,
	HLL	T1,M		;FIX UP SECTION NOW
	SKIPL	T1		;POSSIBLE IFIW?
	TLNE	T1,^-<(SECMSK)> ;NO, IS IT A VALID ADDRESS?
	TLNN	T1,377777	;IFIW, IS IT PURE?
	SKIPA	T2,T1		;YES, USE INDIRECTED ADDRESS
	MOVE	T2,M		;NO, USE ORIGINAL ADDRESS
	SKIPGE	T2		;IS IT AN IFIW?
	HLL	T2,M		;YES, UPDATE THE SECTION NUMBER
	TRNN	T2,^-17		;TRYING TO START IN THE ACS?
GSADD0:	SETZ	T2,		;YES, DON'T ALLOW THAT
	JRST	MPOPJ##		;RETURN THE DESIRED ADDRESS TO THE CALLER
	SUBTTL	.BPT (CONTROL-D) COMMAND

;HERE WHEN THE USER TYPES A ^D TO FORCE AN "UNSOLICITED" DDT BREAKPOINT.
;
;THE EFFECT IS TO "EXECUTE" A "JSR @.JBBPT" ON BEHALF OF THE CURRENTLY
;RUNNING USER PROGRAM; THE USER WILL THEN BE IN DDT, AND CAN "$P" TO
;RESUME THE USER PROGRAM WHERE IT WAS INTERRUPTED BY THE BREAKPOINT.

CDBPT::	JUMPE	J,ATT4		;BOMB COMMAND IF NO JOB
	JUMPGE	P4,BPTER2	; OR IF THE JOB IS ^C'ED
IFN FTMP,<			;IF MORE THAN ONE PROCESSOR,
	PUSHJ	P,SPSTOP##	;MAKE SURE NOT RUNNING ANYWHERE ELSE
	  JRST	DLYCM		;OOPS, WE WERE, WAIT TILL OTHER CPU LETS GO
IFN FTKL10,<			;IF NON-WRITE-THROUGH CACHES EXIST,
	PUSHJ	P,SBCCSH##	;NOT RUNNING, BUT MIGHT BE IN OTHER CPU'S CACHE
	  CAIA			;OK WRT CACHE
	JRST	DLYCM		;STUCK IN OTHER CPU'S CACHE, WAIT
> ;END IFN FTKL10
> ;END IFN FTMP
	PUSHJ	P,SIMCHK##	;SEE IF JOB IN GOOD STATE TO BE STOPPED
	  CAIA			;CAN STOP JOB NOW
	JRST	DLYCM		;CAN'T STOP JOB (EXEC PC), WAIT
	SKIPG	T2,.JDAT+JOBBPT##  ;ADDRESS OF BREAKPOINT TRAP ENTRY
	JRST	BPTER3		;NO BREAKPOINT TRAP ADDRESS
	PUSHJ	P,FLTTC##	;CHECK VALIDITY OF ADDRESS
	  JRST	BPTER5		;ERROR: OUT OF BOUNDS
	  JRST	BPTER6		;ERROR: PAGED OUT/INACCESSIBLE
	MOVE	T1,.JDAT+JOBBPT## ;ADDRESS AGAIN
	PUSHJ	P,IADCKL##	;I/O-LEGAL ADDRESS?
	  JRST	BPTER7		;NO
	  JRST	BPTER6		;PAGED OUT
	PUSHJ	P,CDBRK##	;ALL SET, LET CLOCK1 PLAY WITH THE USER'S PC
	  JFCL			;FAILED???
IFN FTMP,<			;IF WE CALLED SPSTOP ABOVE,
	PUSHJ	P,CLRCCB##	;THEN UNDO THE CALL TO SPSTOP HERE
> ;END IFN FTMP
	TLO	M,NOPER		;NO DOT PLEASE
	POPJ	P,		;.BPT COMMAND COMPLETED
;.BPT COMMAND ERRORS

BPTER1:	JSP	T1,BPTERM
	ASCIZ	\Breakpoint trapping is illegal when execute-only\

BPTER2:	JSP	T1,BPTERM
	ASCIZ	\Program is not running\

BPTER3:	SKIPE	.JDAT+JOBDDT##
	JRST	BPTER4
	JSP	T1,BPTERM
	ASCIZ	\DDT is not loaded\

BPTER4:	JSP	T1,BPTERM
	ASCIZ	\No breakpoint trap address\

BPTER5:	JSP	T1,BPTERM
	ASCIZ	\Breakpoint trap address out of bounds\

BPTER6:	JSP	T1,BPTERM
	ASCIZ	\Breakpoint trap address paged out\

BPTER7:	JSP	T1,BPTERM
	ASCIZ  \Invalid breakpoint trap address\




;COMMON BPT COMMAND ERROR MESSAGE PROCESSOR

BPTERM:	PUSH	P,T1		;SAVE ERROR MESSAGE ADDRESS
	PUSHJ	P,CRLF		;TYPE A CRLF
	POP	P,T1		;GET ADDR BACK
	PUSHJ	P,ERRMES	;PRINT THE ERROR MESSAGE
	TLZ	M,ERRFLG	;DEFEAT ERRMES
	SE1XCT	<MOVE T1,LDBDCH##(U)> ;GET TTY CHARACTERISTICS WORD
	TLNE	T1,LDLCOM##	;AT COMMAND LEVEL?
	TLOA	M,ERRFLG	;YES
	TLO	M,NOPER		;ELSE SUPPRESS THE DOT
	POPJ	P,		;"ERROR" RETURN
; PROCESS A "SET EDDT BREAKPOINT" COMMAND
;
SETEBP::SE1XCT	<LDB T1,LDPLNO>	;GET LINE NUMBER
IFE FTMP,<CAIE T1,TCONLN##>
IFN FTMP,<
	CAILE	T1,FRCLIN##	;IS IT A CTY?
	CAILE	T1,TCONLN##	;...
>
	JRST	COMERA1		;NO
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,0		;JOB 0
	JRST	SETBP1		;ENTER COMMON CODE


; PROCESS A "SET DDT BREAKPOINT" COMMAND
;
SETBPT::PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,J		;GET OUR JOB NUMBER

SETBP1:	PUSHJ	P,CTEXT		;GET A KEYWORD
	JUMPE	T2,SETBP3	;IF NO ARGUMENT, JUST TYPE CURRENT SETTING
	MOVE	T1,[-3,,BPTTAB]	;POINT TO TABLE
	PUSHJ	P,FNDNAM	;AND SEARCH IT
	  JRST	COMERA		;AMBIGUOUS OR UNKNOWN KEYWORD
	SKIPE	T1		;USER INCLUDE "BREAKPOINT" CHATTER?
	SOJA	T1,SETBP2	;NO--JUST STORE ON/OFF VALUE
	PUSHJ	P,CTEXT		;GET "ON" OR "OFF"
	JUMPE	T2,SETBP3	;INFORM CONFUSED USER OF .BPT STATE
	MOVE	T1,[-2,,BPTTB1]	;POINT TO ON/OFF TABLE
	PUSHJ	P,FNDNAM	;SCAN IT
	  JRST	COMERA		;AMBIGUOUS OR UNKNOWN KEYWORD
SETBP2:	DPB	T1,BPTPT1	;TURN .BPT ON OR OFF
SETBP3:	MOVEI	T1,[ASCIZ |[Control-D breakpoint facility is turned |]
	PUSHJ	P,CONMES	;TYPE TEXT
	LDB	T1,BPTPT1	;GET THE BIT
	MOVEI	T1,[ASCIZ |off|
		    ASCIZ |on|](T1)
	PUSHJ	P,CONMES	;TYPE ON OR OFF
	MOVEI	T1,[ASCIZ | for exec mode debugging|] ;INCASE "SET EXEC CTRLD"
	SKIPN	P1		;JOB 0?
	PUSHJ	P,CONMES	;YES
	MOVEI	T3,"]"		;GET MESSAGE TERMINATOR
	PJRST	COMTYO		;TYPE IT AND RETURN


; PROCESS SETUUO FUNCTIONS .STEBP AND .STBPT
;
SETEBU:	MOVEI	J,0		;SET EDDT SETUUO FUNCTION
SETUBU:	ANDI	T2,1		;SET DDT SETUUO FUNCTION (FOR USERS)
	DPB	T2,BPTPTR	;TURN .BPT ON OR OFF
	MOVE	J,.CPJOB##	;RELOAD OUR JOB NUMBER
	JRST	CPOPJ1##	;AND RETURN

BPTPTR:	POINT 1,JBTSTS##(J),^L<JS.BPT>
BPTPT1:	POINT 1,JBTSTS##(P1),^L<JS.BPT>
BPTTAB:	SIXBIT	/BREAKP/
BPTTB1:	SIXBIT	/OFF/
	SIXBIT	/ON/
SNDTXS:	MOVE	P3,[POINT 7,(T4)] ;TO COPY THE STRING
	MOVEI	T3,7		;GET A BELL
	IDPB	T3,P3		;STORE IN MESSAGE
	SUBI	P1,1		;ADJUST CHAR COUNT
SNDTX1:	PUSHJ	P,COMTYI##	;NEXT CHARACTER
	IDPB	T3,P3		;STORE IT FOR THE ACTDAE
	CAIE	T3,12		;END OF LINE?
	CAIN	T3,3
	TDZA	P1,P1
	SOJG	P1,SNDTX1	;OR USED ALL THE SPACE?
	IDPB	P1,P3		;ASCIZIZE
	MOVE	T1,P4		;ACTDAE
	MOVE	T4,P2		;LENGTH,,ADDRESS
	PJRST	SNDFFC##	;SEND IT

	SUBTTL	CONTROL-C PROCESSING

; "HALT" OR "<CONTROL>C"
;SCANNER ROUTINES DUMMY UP HALT WHEN CONTROL C TYPED IN
;STOP MUST BE DELAYED IF THIS JOB IS SYSTEM TAPE USER
;AND SYSTEM TAPE IS ACTIVE. OTHERWISE, THE JOB WILL NOT BE
;STOPPED WHEN DONE USING THE SYSTEM TAPE.
;IF JOB IS IN MONITOR MODE AND NOT IN TTY WAIT THIS JOB CANNOT BE STOPPED YET
;IN THIS CASE SET A BIT IN JOB STATUS WORD (CNTRLC) WHICH WILL BE CHECKED
;WHEN JOB RETURNS TO USER MODE


STOP::	MOVE	P2,HALTXT##
STOPF::
IFN FTNET,<
	SE1XCT	<SKIPGE LDBREM##(U)> ;IF SET HOST IN PROGRESS,
	TLO	M,NOCRLP!NOFLM	;DON'T TYPE OUT
> ;END IFN FTNET
	JUMPE	J,STOPB
	TLNE	P4,JACCT	;JACCT AND WAITING
	TRNN	P4,JDCON	;..
	JRST	STOPD		;NO--PROCEED
	JUMPL	P4,STOPD	;JUMP IF RUN BIT IS SET
	TLO	M,NOCRLP	;KILL THE DOT
	POPJ	P,0		;PUNT THE COMMAND
STOPD:	MOVEI	T1,JDCON	;CLEAR JCONT.ABLE (DEV OK?) BIT
	ANDCAM	T1,JBTSTS##(J)	; SO USER CAN STOP ONCE-A-MINUTE STUFF

IFN FTMP,<
	PUSHJ	P,SPSTOP##	;TEST IF JOB ON SLAVE, IF SO SIGNAL TO STOP IT,
	  JRST	DLYCM1		;  AND DELAY COMMAND
>

	PUSHJ	P,SIMCHK##	;OK TO "STOP IN MONITOR"?
	  JRST	STOPA		;YES, STOP JOB
	MOVSI	T1,CNTRLC	;NO, FLAG THAT USER MUST BE STOPPED WHEN
	IORB	T1,JBTSTS##(J)	; RETURNING TO USER MODE IN UUO HANDLER
	TLNE	M,CMWRQ		;IS JOB IN COMMAND WAIT?
	PUSHJ	P,REQUE##	;YES. PUT HIM BACK IN RUNNABLE QUEUE
	JRST	DLYCM1		;THEN DELAY COMMAND (IE ECHO CR-LF, DOT)
				;UNTIL SWAPPED IN
STOPA:	MOVSI	T1,SWP!SHF	;IS THE JOB SWAPPED?
	TDNE	T1,JBTSTS##(J)	;IF SO, DELAY THE CONTROL C SINCE
	PJRST	DLYCM		; THE JOB DATA AREA MUST BE IN CORE
				; TO SEE IF THE JOB IS INTERCEPTING
				; CONTROL C'S
	MOVSI	T1,CNTRLC+CMWB	;DELAYED CONTROL C+ COMMAND WAIT
	ANDCAM	T1,JBTSTS##(J)	;CLEAR THEM
	SKIPL	JBTSTS##(J)	;IS RUN BIT ALREADY OFF?
	JRST	STOPAA		;IF YES, DO NOT PRINT [XXXX] AGAIN
	PUSHJ	P,STOPX		;STOP JOB
	TLNN	M,NOPER		;IF NO PERIOD, SKIP [XXX]
	PUSHJ	P,WCHEND	;PRINT [XXXX] CRLF IF USER IS WATCHING RESPONSES
	JRST	STOPAB		;GO FINISH

STOPAA:	PUSHJ	P,STOPX		;STOP JOB
STOPAB:	SKIPGE	T1,JBTSTS##(J)	;GET JOB STATUS
	JRST	STOPB		;IF NOT STOPPED, DON'T KJOB
	TLNN	T1,JLOG		;IS JOB LOGGED IN?
	PUSHJ	P,TTKJOB##

STOPB:	SKIPL	JBTSTS##(J)	;RUNNING?
	PUSHJ	P,FNDPDB##	;FIND PDB
	  POPJ	P,
	MOVEI	T1,TTFCXI##	;FORCE .INITIA
	MOVEI	T2,JS.RPC	;IF JS.RPC = 1
	SKIPE	.PDPGM##(W)	;AND PROGRAM TO RUN
	TDNN	T2,JBTST2##(J)	; ..
	POPJ	P,0
	PUSHJ	P,TTFORC##
	PJRST	DLYCM

STOPX:	MOVSI	T1,(JS.SAC)	;BIT TO TEST
	TDNE	T1,JBTST2##(J)	;DOING AN AUTO-RESTORE ON PROGRAM EXIT?
	TLO	M,NOCRLP	;YES, DON'T TYPE CRUFT
	PJUMPL	P2,STOP1C##	;IF "HALT", STOP REGARDLESS
	PJRST	STOP1##		;IF "^C^C", STOP IF POSSIBLE
;MONITOR COMMAND LEVEL RESPONSE ROUTINES
;FIVE MULTIPLE ENTRY SUBROUTINES TO PRINT SYSTEM RESPONSE DATA FOR A JOB
;CONTROL REACHES ONE OF THESE ROUTINES ON ANY OF THE FOLLOWING:
;1. USER TYPES CONTROL C
;2. PROGRAM HALTS
;3. PROGRAM CALLS EXIT, OR CALL N,EXIT
;4. DEVICE BECOMES UNREADY  DEVICE XXX OK?
;5. ERROR IN JOB MESSAGE

;PRRSP1 - PRINT CRLF CRLF
;PRRSP3 - PRINT [XXXX] CRLF IF USER WATCHING SYSTEM DATA RESPONSE
;PRRSP4 - PRINT CRLF
;PRRSP5 - PRINT PERIOD


PRRSP1::PUSHJ	P,CRLF		;PRINT CR-LF
PRRSP3::PUSHJ	P,WCHEND	;PRINT SYSTEM RESPONSE DATA IF USER IS WATCHING
PRRSP4::PUSHJ	P,CRLF		;PRINT CR-LF
PRRSP5::PUSHJ	P,FNDPDB##	;ENSURE W IS SETUP
	  PJRST	PRDOTC		;?
	MOVEI	T1,JS.RPC	;RUN PROGRAM BIT
	SKIPE	.PDPGM##(W)	;ANY TO RUN?
	TDNN	T1,JBTST2##(J)	;DOES HE WANT IT RUN
	PJRST	PRDOTC		;NO, PRINT DOT
	POPJ	P,		;YES, DONT PRINT DOT
	SUBTTL	SET COMMAND AND UUO  -- DISPATCH

;SET COMMAND/UUO

SET::	MOVE	P3,[XWD UNQTB2##,DISP2##] ;UNIQUENESS PLUS START OF SET-TABLE
	MOVE	P4,[XWD -DISPL2##,COMTB2##] ;LENGTH, NAME
	MOVE	P,.CPISF##	;RESTORE P TO VALUE AT COMGO
	XJRST	[MCSEC1+COM1]	;GO INTERPRET 2ND PART OF THE COMMAND (IN SECTION 1)

;SUBROUTINE TO SEE IF A SYSTEM-WIDE SET COMMAND IS LEGAL
;SKIP RETURN IF LEGAL, ELSE NON-SKIP

SETLGF==FUPOPJ##
SETLGK==FUPOJ1##
SETLGL::MOVE	T3,LINTAB##+FRCLIN##
	CAMN	T3,U
	JRST	CPOPJ1##
	PUSHJ	P,OPRLGL	;OPR?
	  SKIPA	T2,JBTPPN##(T1)	;NO, CHECK FURTHER
	JRST	CPOPJ1##	;YES, OK
	CAMN	T2,FFAPPN##	;1,2?
	AOS	(P)		;YES, OK
	POPJ	P,		;RETURN
OPRLGL:	PUSH	P,U		;PRESERVE LINE
	PUSH	P,F		;AND F
	MOVE	T1,J
	MOVE	T3,OPRLDB##	;SEE IF OPR
	CAMN	T3,U		;ALSO OPR
	JRST	SETLGK		;WE WIN
	MOVE	T2,JBTSTS##(J)	;GET JOB STATUS
	TLNE	T2,JLOG		;A JOB ON THE TTY?
	JRST	SETLGF		;YES. COMMAND LOSES
	SE1XCT	<LDB T2,LDPLNO##> ;GET LINE NUMBER
	PUSHJ	P,CTLJB##	;LOSE -- SEE IF PTY
	JUMPLE	T1,SETLGF	;NO --- GIVE UP
	HRRZ	U,TTYTAB##(T1)	;OK -- GET DDB
	MOVE	U,DDBLDB##(U)	;THEN GET LDB
	JUMPE	U,SETLGF	;IF CONTROL JOB DETACHED STOP SCAN AND FAIL
	MOVSI	T2,DVDIBP	;GET BATCH JOB BITS
	TDNE	T2,DEVCHR(F)
	JRST	SETLGF		;YES. COMMAND LOSES
	CAMN	T3,U		;OR HIS TTY?
	JRST	SETLGK		;YES. COMMAND WINS
	JRST	SETLGF		;LOSE
	SUBTTL	SET COMMAND AND UUO -- JBSET.

;HERE FROM UUOCON ON JBSET. UUO
;CALL:	MOVE	AC,[+N,,BLK]
;	CALLI	AC,JBSET.
;	  ERROR RETURN AC=0
;	NORMAL RETURN
;BLK:	JOB	NUMBER
;	XWD	FUNCTION,VALUE
UJBSET::PUSHJ	P,PRVJ		;ARE WE A GOOD GUY
	  JRST	JBSET1		;YES--GO DO THE SET
	JRST	RTZER##		;NO--RETURN 0

JBSET1:	PUSH	P,M		;SAVE M
	HRRI	M,(T1)		;GET ADDRESS OF BLK
	PUSHJ	P,GETWDU##	;PICK UP JOB#
	MOVE	J,T1		;PUT JOB NUMBER IN J
	PUSHJ	P,LGLPRC##	;SKIP IF LEGAL JOB NUMBER
	  JRST	JBSET2		;NO, GIVE UP
	MOVSI	T1,JNA		;SEE IF JOB EXISTS
	TDNN	T1,JBTSTS##(J)	;  AND EXISTENT
	JRST	JBSET2		;  YES--GIVE UP
	MOVE	T4,J		;SAVE NEW JOB
	PUSHJ	P,GETWD1##	;GET NEXT WORD(XWD) PUT IT IN T1
	MOVE	J,T4		;RESTORE NEW JOB
	NOSCHED
	PUSH	P,JBTPPN##(J)	;SAVE PPN
	MOVE	T2,FFAPPN##	;GET A GOOD PPN
	MOVEM	T2,JBTPPN##(J)	;FAKE OUT PRIVJ AND PRVBIT
	PUSH	P,J
	PUSH	P,W		;PRESERVE W
	PUSHJ	P,FNDPDS##	;GET THE PDB FOR THE TARGET JOB
	PUSHJ	P,SETUUO	;DO IT
	  TDZA	T1,T1		;NOTE BAD RETURN
	SETO	T1,		;GOOD RETURN
	POP	P,W		;RESTORE W
	POP	P,J
	POP	P,JBTPPN##(J)	;RESTORE PPN
	SCHEDULE
	POP	P,M
	JUMPN	T1,CPOPJ1##	;PASS THE GOOD WORD ON
	JRST	STOTAC##	;ELSE RETURN ZERO

JBSET2:	POP	P,M		;RESTORE AC
	JRST	RTZER##		;GIVE ERROR
	SUBTTL	SET COMMAND AND UUO -- PRIVILEGE TESTS

;DISPATCH HERE (FROM UUOCON) ON A SETUUO
;CALL:	MOVE AC,[XWD FUNCTION,ARGUMENT]
;	CALLI AC,SETUUO
NEDPRV==1			;BIT ON IN DISPATCH TABLE IF PRIVS NEEDED
NLOGOK==2			;BIT ON IS DISPATCH IF OK WHEN NOT LOGGED IN
SETUUO::HRRZ	T2,T1		;ARGUMENT
	HLRES	T1		;FUNCTION
	CAML	T1,[SETTBC-SETTBL] ;A LEGAL CUSTOMER FUNCTION?
	CAILE	T1,SETLEN	;A LEGAL FUNCTION?
	POPJ	P,		;NO, RETURN DOING NOTHING
	MOVE	T1,SETTBL(T1)	;YES, GET TABLE WORD
	TLNE	T1,NEDPRV	;NEED SPECIAL PRIVS TO DO IT?
	PUSHJ	P,PRVJ		;YES, JOB HAVE PRIVS?
	  PJRST (T1)		;YES, DISPATCH
	TLNE	T1,NLOGOK	;NO PRIVS, IS IT OK IF NOT LOGGED IN?
	TLNE	T3,JLOG		;YES, IS JOB LOGGED IN?
	JRST	ECOD0##		;LOGGED IN OR NO PRIVS, ERROR RETURN
	PJRST	(T1)		;DISPATCH FUNCTION
;SUBROUTINE TO SEE IF A JOB HAS PRIVILEGE:
;CALL:	MOVE T1,BIT TO BE TESTED IN PRIVILEGE WORD
;	MOVE J,JOB NUMBER
;	PUSHJ P,PRVBIT
;	  RETURN IF PRIVILEGED BY BIT, [1,2], OR JACCT
;	RETURN IF NOT PRIVILEGED
;RESPECTS T2

PRVBIT::TDNE	T1,JBTPRV##(J)	;IS REQUESTED BIT ON IN TABLE?
	POPJ	P,		;YES. OK RETURN
;	PJRST	PRVJ		;NO. CHECK FOR JACCT OR FSFPPN


;SUBROUTINE TO TEST FOR [1,2] OR JACCT PRIVILEGES.
;NEEDED IF A SETUUO FOR A SYSTEM-PARAMETER IS DONE.
;RETURNS CPOPJ IF HAVE PRIVS, CPOPJ1 IF DON'T.
;RESPECTS T2

PRVJ::	MOVE	T3,JBTSTS##(J)	;JBTSTS WORD
	SKIPGE	M		;COMMAND LEVEL?
	TLZA	T3,JACCT	;YES--CLEAR JACCT
PRVJC::	MOVE	T3,JBTSTS##(J)	;IF AT UUO LEVEL AND THE SIGN BIT OF M COULD BE ON
	MOVE	T4,JBTPPN##(J)	;JOB'S PRJ-PRG
	CAME	T4,FFAPPN##	;=1,2?
	TLNE	T3,JACCT	;NO, JACCT ON?
	POPJ	P,		;YES, OK
	PJRST	CPOPJ1##	;NO, ERROR RETURN
;TABLE FOR SETUUO.  NEGATIVE FUNCTIONS ARE CUSTOMER DEFINED.
;POSITIVE FUNCTIONS ARE RESERVED FOR DEC.

SETTBC:				;MINIMUM CUSTOMER DEFINED FUCTION
IFN FTPATT,<
	EXP	CPOPJ##		;ROOM FOR PATCHING
>; END IFN FTPATT
SETTBL:	XWD	NEDPRV,SETMX1	;(0) - SET CORMAX
	XWD	NEDPRV,SETMN1	;(1) - SET CORMIN
	XWD	NEDPRV,SETDA1	;(2) - SET DAYTIME
	XWD	NEDPRV,SETSC1	;(3) - SET SCHED
	EXP	SETSPI		;(4) - SET CDR
	EXP	SETSPB		;(5) - SET SPOOL
	EXP	SETWTU		;(6) - SET WATCH
	XWD	NEDPRV,SETDT1	;(7) - SET DATE
	XWD	NEDPRV,SETOP1	;(10) - SET OPR (INDIRECT)
	XWD	NEDPRV,SETKSY	;(11) - SET KSYS
	XWD	NEDPRV,CORELM##
	EXP	SETIM1		;(13) - SET TIME LIMIT
	EXP	SETCPU##	;(14) - SET USER CPU SPECIFICATION
	XWD	NEDPRV,SETCRN##	;(15) - SET CPU RUNABILITY
	XWD	NEDPRV,SETLMX	;(16) - SET LOGMAX
	XWD	NEDPRV,SETBMX	;(17) - SET BATMAX
	XWD	NEDPRV,SETBMN	;(20) - SET BATMIN
	EXP	DSKFUL		;(21) - SET DSKFUL- PAUSE OR ERROR
	XWD	NEDPRV,SETVM1##	;(22) - SET VMMAX (SYSTEM-WIDE)
	XWD	NEDPRV,CPOPJ1##	;(23) - HISTORICAL
	XWD	NEDPRV+NLOGOK,SETUVL##	;(24) - SET VM MAXIMA (USER)
	EXP	SETUV1##	;(25) - SET CURRENT VM MAXIMA (USER)
	EXP	SETVTM##	;(26) - SET TIME FOR VIRTUAL TIME INTERRUPTS
	EXP	SETABR		;(27)-SET ADDRESS BREAK
	EXP	SETPGM		;(30)-SET PROGRAM TO RUN
	EXP	SETDFU		;(31)-SET DEFERED SPOOLERS
IFN FTNET,<
	XWD	NEDPRV,HOST.U##	;(32)-SET HOST
>
IFE FTNET,<
	EXP	CPOPJ##		;(32)-SET HOST - NOT DEFINED
>
	EXP	SETDLU		;(33)-SET DEFAULTS
	EXP	SETPRV		;(34)-SET PRIVILEGES
	XWD	NEDPRV,SETBSN	;(35) SET BATCH STREAM NUMBER
	XWD	NEDPRV,SETWTO	;(36) SET WTO CAPABALITIES
	XWD	NEDPRV,SETCDN##	;(37) SET CPU UP/DOWN STATUS
IFN FTKL10,<
IFN FTMP,<
	XWD	NEDPRV,SETCSB##	;(40) SET/CLEAR CACHE BITS
>
IFE FTMP,<
	EXP 	CPOPJ##		;(40) SET/CLEAR CACHE BITS - NOT DEFINED
>
> ;END IFN FTKL10
IFN FTKS10,<
	EXP 	CPOPJ##		;(40) SET/CLEAR CACHE BITS - NOT DEFINED
>; END IFN FTKS10
	EXP	SETFPS##	;(41) SET/CLEAR FLOATING POINT SIMULATION
	XWD	NEDPRV+NLOGOK,SETOPP ;(42) SET OPERATOR PRIVS
	XWD	NEDPRV,SETQST	;(43) SET QUEUE STRUCTURE
	XWD	NEDPRV,CSHSIZ##	;(44) SET DISK BLOCK CACHE SIZE
	XWD	NEDPRV,SETEBU	;(45) SET EDDT BREAKPOINT ON/OFF
	EXP	SETUBU		;(46) SET DDT BREAKPOINT ON/OFF
	XWD	NEDPRV,SETDA0	;(47) SET TIME OF DAY IN SECONDS
	XWD	NEDPRV,SETMXP	;(50) SET CORMAX IN PAGES
	XWD	NEDPRV,SETMNP	;(51) SET CORMIN IN PAGES
IFN FTMP,<
	EXP	SETPCP##	;(52) SET POLICY CPU
>; END IFN FTMP
IFE FTMP,<
	EXP 	CPOPJ##		;(52) SET POLICY - UNDEFINED IF NOT FTMP
>; END IFE FTMP
	XWD	NEDPRV,SETDJB##	;(53) SET DAEMON JOB NUMBER
	EXP	SETITP##	;(54) SET INTERVAL TIMER PATCH
IFN FTPATT,<
	EXP	CPOPJ##		;ROOM FOR PATCHING
>; END IFN FTPATT
SETLEN==.-SETTBL-1


IFE FTLOCK,<
SETMN1==CPOPJ##
SETMNP==CPOPJ##
>; END IFE FTLOCK
	SUBTTL	SET COMMAND AND UUO -- CORMAX AND CORMIN

SETMXP:	AOS	T3,T2		;COMPUTE HIGHEST ADDRESS
	ANDI	T3,400000	;PRESERVE SOFT CORMAX FLAG
	TRZ	T2,400000	;KEEP ONLY NUMBER OF PAGES
	LSH	T2,P2WLSH	;CHANGE TO WORDS
	SOSA	T2		;CONTINUE
SETMX1:	SETZ	T3,		;HARD CORMAX FOR OLD FUNCTION CODE
IFN FTLOCK,<
	SKIPE	LOCK##		;JOB BEING LOCKED?
	JRST	ECOD0##		;YES - CAN'T CHANGE CORMAX
>
	JRST	SETMX2		;ENTER COMMON CODE

SETMAX::PUSHJ	P,CORLGL	;GET DECIMAL ARG IF LEGAL
IFN FTLOCK,<
	SKIPE	LOCK##		;IF A JOB IS BEING LOCKED,
	JRST	DLYCM1		;WAIT TILL LATER
>
	SETZ	T3,		;FORCE HARD CORMAX FOR COMMAND

SETMX2:	PUSH	P,T3		;SAVE HARD/SOFT CORMAX FLAG
	MOVE	T1,RMCMAX##	;REAL MAXIMUM CORMAX, INCLUDING FUNNY SPACE
	CAMG	T2,T1		;TRY TO SET IT TOO HIGH?
	JRST	SETAOK		;NO
	JUMPGE	M,SETMXE	;RETURN ERROR IF UUO
	PUSHJ	P,INLMES
	ASCIZ	/
%Exceeds physical maximum-/
	MOVE	T1,RMCMAX##	;GET REAL MAXIMUM
	LSH	T1,W2PLSH	;SET UP FOR P OR K
	PUSHJ	P,PRCORE	;TELL WHAT IT IS
	MOVE	T2,RMCMAX##	;REDUCE PHYSICAL LIMIT
SETAOK:	CAIL	T2,MINMAX##	;TOO SMALL?
	JRST	SETIOK		;NO
	JUMPGE	M,SETMXE	;RETURN ERROR IF UUO
	PUSHJ	P,INLMES
	ASCIZ	/
%Below minimum-/
	MOVEI	T1,MINMAX##	;GET MINIMUM
	LSH	T1,W2PLSH
	PUSHJ	P,PRCORE	;REPORT IT
	MOVEI	T2,MINMAX##
SETIOK:	POP	P,T3		;GET FLAG BACK
	JUMPN	T3,SETMXF	;CONTINUE IF SOFT CORMAX
	CAMGE	T2,CORMAX##	;DECREASING?
	PUSHJ	P,CHKMAX	;YES. CHECK JOB SIZES
SETMXF:	MOVEM	T2,CORMAX##	;SAVE NEW VALUE
	LSH	T2,W2PLSH	;REDUCE TO N
	HRRM	T2,CORLIM##	;SAVE IN RH(CORLIM)
	JRST	CPOPJ1##	;AND SKIP RETURN
SETMXE:	POP	P,(P)		;PHASE STACK
	JRST	ECOD0##		;RETURN ERROR CODE 0 (BAD ARGUMENT)

CHKMAX:	PUSHJ	P,SAVE3##	;SEE IF NEW CORMAX
	SETZ	P1,0		;IS TOO SMALL FOR
	PUSH	P,J		;JOBS NOW RUNNING
	MOVE	P2,T2		;SAVE DESIRED NEW VALUE
	MOVEI	J,1		;SCAN ALL JOBS
CHKMX1:	MOVE	T2,JBTSTS##(J)	;DON'T COUNT LOCKED JOBS
	TLNE	T2,NSHF!NSWP
	TDZA	T2,T2		;THIS JOB IS LOCKED
	PUSHJ	P,SEGSIZ	;GET LOW SEG SIZE
	PUSH	P,J		;SAVE JOB #
	HRRZ	T3,JBTSGN##(J)	;SEE IF USER HAS ANY HIGH SEGS
	JUMPE	T3,CHKMX2	;NO
CHKM1A:	SKIPLE	J,.HBSGN(T3)	;IS THIS HIGH SEG REAL?
	TLNE	J,NSWP!NSHF	;AND NOT LOCKED?
	JRST	CHKM1B		;LOCKED OR SPY
	MOVE	P3,T2		;SAVE CURRENT SUM
	PUSHJ	P,SEGSIZ	;GET HISEG SIZE
	ADDI	T2,(P3)		;TOTAL
CHKM1B:	HRRZ	T3,.HBLNK(T3)	;POINT TO NEXT HIGH SEG
	JUMPN	T3,CHKM1A
CHKMX2:	LSH	T2,P2WLSH	;TOTAL WORDS
	CAMLE	T2,P1		;BIGGEST SO FAR?
	MOVE	P1,T2		;YES
	POP	P,J		;GET BACK JOB #
	CAMGE	J,HIGHJB##	;ALL JOBS SCANNED?
	AOJA	J,CHKMX1	;NO
	CAMG	P1,P2		;BIGGEST JOB FIT NEW CORMAX?
	JRST	CHKMX3		;YES. OK AS IS
	MOVE	P2,P1		;NO. ADJUST REQUEST
	JUMPGE	M,CHKMX3
	PUSHJ	P,INLMES
	ASCIZ	/
%Too small for current job(s)-/
	MOVE	T1,P2		;GET SIZE OF LARGEST JOB
	LSH	T1,W2PLSH
	PUSHJ	P,PRCORE	;REPORT IT
CHKMX3:	MOVE	T2,P2
	POP	P,J		;BALANCE STACK
	JRST	ECOD0##		;RETURN ERROR


IFN FTLOCK,<
SETMNP:	LSH	T2,P2WLSH	;CONVERT TO WORDS
	TROA	T2,PG.BDY	;CONVERT TO HIGHEST LEGAL ADDRESS
SETMIN::PUSHJ	P,CORLGL	;GET DECIMAL ARG IF LEGAL
SETMN1:	CAMLE	T2,CORMAX##	;CORMIN CAN'T
	MOVE	T2,CORMAX##	;EXCEED CORMAX
	MOVEM	T2,CORMIN##	;SET NEW VALUE IN CORMIN
	JRST	CPOPJ1##	;AND SKIP RETURN
>
;SUBROUTINE TO GET CORE ARGUMENT AND CHECK FOR LEGALITY
; DOES NOT RETURN IF NOT LEGAL
CORLGL::PUSHJ	P,SETLGL	;TEST FOR LEGALITY
	  JRST	COMERP		;NOT LEGAL
	PUSHJ	P,CORARG	;GET THE CORE ARGUMENT
	  JRST	NOTENP		;NOT ENOUGH ARGUMENTS
	AOS	T2,T1		;CONVERT TO NUMBER OF WORDS
	POPJ	P,		;RETURN


;SUBROUTINE TO TEST FOR LEGALITY, RETURN NEXT TYPED ARGUMENT IF LEGAL
;DOES NOT RETURN IF NOT LEGAL
DECLGL::PUSHJ	P,SETLGL	;TEST FOR LEGALITY
	  JRST	COMERP		;NOT LEGAL
	PUSHJ	P,DECIN1	;LEGAL - GET DECIMAL NUMBER
	  PJRST NOTENP		;NOT ENOUGH ARGS
	  PJRST COMERP		;NOT A NUMBER
	POPJ	P,		;OK - RETURN
;HERE TO SET MEMORY ON OR OFF LINE
SETMEM::PUSHJ	P,SETLGL	;MUST BE PRIVILEGED
	  JRST	COMERA		;NOT PRIVLEGED, LOSE
;	PUSHJ	P,SAVE2##
	PUSHJ	P,CTEXT		;GET MODIFIER
	JUMPE	T2,NOTENF	;MUST BE ONE
	MOVE	T1,[-2,,[SIXBIT /ON/
			 SIXBIT /OFF/]]
	PUSHJ	P,FNDNAM	;LOOK FOR EITHER "ON" OR "OFF"
	  JRST	COMERA		;IF NEITHER, LOSE
	MOVE	P1,T1		;REMEMBER WHETHER HE SAID ON OR OFF
	PUSHJ	P,SKIPS1	;SKIP SPACES, TABS, ETC.
	  JFCL			;IGNORE NON-SKIP RETURN
	CAIN	T3,"-"		;ALLOW "-LINE"
	PUSHJ	P,COMTYS	;IF A MINUS SIGN WAS TYPED, SKIP IT
	MOVE	T1,[-2,,[SIXBIT /LINE/
			 SIXBIT /FROM/]]
	PUSHJ	P,TXTARG	;ALLOW NOISE WORDS
	  JRST	SETME0		;NONE WAS TYPED
	JUMPN	T1,SETME0	;SKIP ON IF "FROM" WAS TYPED
	HRROI	T1,[SIXBIT/FROM/]
	PUSHJ	P,TXTARG	;"LINE" WAS TYPED, EAT "FROM" IF ITS THERE
	  JFCL			;DON'T CARE WHETHER IT WAS ON NOT
SETME0:	PUSHJ	P,DECIN1	;READ AN ARGUMENT (DEFAULT IS DECIMAL)
	  JRST	NOTENF		;THERE MUST BE ONE
	  PUSHJ	P,[CAIE	T3,"K"	;NUMBER ENDED WITH A NON-DIGIT,
		   CAIN	T3,"P"	; WAS IT "P" OR "K"?
		   CAIA		;YES
		   JRST	COMERP	;NO, COMPLAIN
		   MOVEI T1,P2WLSH
		   CAIE	T3,"P"	;ARGUMENT SPECIFIED IN PAGES?
		   MOVEI T1,K2WLSH
		   LSH	T2,(T1)	;CONVERT TO WORDS
		   JRST	COMTYS]	;AND EAT THE "P" OR "K"
	MOVE	P2,T2		;SAVE THE LOWER BOUND
	HRROI	T1,[SIXBIT/TO/]
	PUSHJ	P,TXTARG	;ALLOW THE NOISE WORD "TO"
	  JFCL			;DON'T CARE IF IT ISN'T THERE
	PUSHJ	P,DECIN1	;READ THE SECOND ARGUMENT
	  JRST	NOTENF		;THERE MUST BE ONE
	  PUSHJ	P,[PUSHJ P,[CAIE T3,"K"
		   CAIN	T3,"P"	;ONCE AGAIN, ALLOW ARGUMENT TO BE
		   CAIA		; QUALIFIED BY "P" OR "K"
		   JRST	COMERP	;HOWEVER, NOTHING ELSE WILL DO
		   MOVEI T1,P2WLSH
		   CAIE	T3,"P"	;PAGES?
		   MOVEI T1,K2WLSH
		   LSH	T2,(T1)	;CONVERT TO WORDS
		   JRST	COMTYS]	;AND THROW AWAY THE CHARACTER
		   SOJA T2,CPOPJ##]
	CAMG	P2,T2		;FIRST ARGUMENT MUST BE .LT. THE SECOND
	CAIE	T3,12		;AND THE LINE MUST BE PROPERLY TERMINATED
	JRST	COMERA		;GRUMBLE
	MOVE	T1,P2		;RESTORE FROM ARGUMENT
	TRZ	T1,PG.BDY	;ROUND TO A PAGE BOUNDARY
	TRZ	T2,PG.BDY	; ..
	ADDI	T2,PAGSIZ	;ROUND UP
	LSHC	T1,W2PLSH	;CONVERT FROM WORDS TO PAGES
;HERE T1 = LOWEST PAGE NUMBER (K NUMBER) OPR TYPED
;     T2 = HIGHEST PAGE NUMBER (K NUMBER) + 1 OPR TYPED
;P1 = 0 IF SET MEMORY ON LINE
;P1 = 1 IF SET MEMORY OFF LINE
;DISPATCH TO ROUTINE TO SET MEMORY ON OR OFF LINE
	JUMPN	P1,SETME1
;HERE TO SET MEMORY ON LINE, T1 = FIRST PAGE TO SET ON LINE, T2 = LAST
; PAGE + 1
MEMONL::HRLZ	S,T1		;STARTING PAGE TO SET ON LINE
	HRR	S,T2		;HIGHEST PAGE TO SET ON LINE
	JSP	T2,SAVCTX##	;SAVE THE JOB'S CONTEXT AND RETURN AT UUO LEVEL
				; (THE JOB'S CONTEXT MUST BE SAVED BECAUSE
				; IF SETTING THE MEMORY ON LINE CAUSES
				; A NXM, THE JOB'S CONTEXT WILL BE DESTROYED)
	HLRZ	T1,S		;RESTORE THE STARTING PAGE TO SET ON LINE
	HRRZ	T2,S		;AND THE HIGHEST PAGE TO SET ON LINE

;JOIN HERE FOR RECON. UUO TO SET MEMORY ON LINE
MEMONU::SE1ENT			;ENTER SECTION 1, TO LOOK AT PAGTAB.
	MOVE	T3,[NXMTAB##,,OLDNXM##] ;SET UP BLT TO COPY NXMTAB
	BLT	T3,NXMTAB##+NXMTBL##-1 ;MAKE "OLD" COPY OF ERROR LOGGING
	MOVE	T3,MEMSIZ##	;CURRENT HIGHEST ADDRESS IN THE MACHINE
	MOVE	T4,NWCORE##	;HIGHEST ADDRESS THAT CAN BE SET ON LINE
				; (CANNOT MAKE PAGTAB AND MEMTAB BIGGER)
	LSHC	T3,W2PLSH	;CONVERT TO PAGES
	CAMG	T3,T4		;PICK THE BIGGER OF THE TWO AS THE
	MOVE	T3,T4		; HIGHEST ADDRESS THAT CAN BE SET ON LINE
	TRZE	T3,PG.BDY	;ROUND UP TO A 256K BOUNDARY (IF NOT
	ADDI	T3,PAGSIZ	; ALREADY ON A 256K BOUNDARY
	CAMG	T3,T2		;IF ASKING FOR MEMORY ON LINE ABOVE THE
				; HIGHEST WHICH CAN BE DONE,
	MOVE	T2,T3		; SET ON UP TO THE HIGHEST THAT CAN BE DONE
	CAML	T1,T2		;LOWEST PAGE ABOVE THE HIGHEST PAGE?
	POPJ	P,		;YES, NOTHING TO SET ON LINE
	MOVE	P1,T1		;LOWEST PAGE TO SET ON LINE
	IDIVI	P1,^D36		;COMPUTE BIT POSITION AND WORD NUMBER WITHIN NXMTAB
	MOVNI	P2,-^D35(P2)	;BIT POSITION BYTE POINTER STYLE
	HRLI	P1,(POINT 1,0,0);FORM A 1 BIT BYTE POINTER TO NXMTAB
	DPB	P2,[POINT 6,P1,5]
	ADDI	P1,NXMTAB##	;BYTE POINTER TO BIT CORRESPONDING TO FIRST PAGE TO SET ON
	SETZB	T4,P2		;INITIALIZE FIRST AND HIGHEST NON-EXISTANT PAGES SEEN
	MOVEI	P3,PAGSIZ	;TO UPDATE MAXMAX ON EACH PAGE SET ON LINE
IFN FTMP,<
	PUSHJ	P,UPMM##	;GET THE MM RESOURCE
>
MEMON6:	MOVE	T3,@[IW MS.MEM,PAGTAB(T1)] ;PAGE DESCRIPTOR BITS
	TLNE	T3,NXMBIT	;IS THIS PAGE NON-EXISTANT?
	TLNE	T3,MONTRB	;IF AN UNMAPPED MONITOR PAGE SKIP IT TOO
	JRST	MEMON8		;NO, ITS ALREADY ON LINE
	DPB	P3,P1		;INDICATE THIS PAGE EXISTS IN NXMTAB
	PUSHJ	P,MEMOZR	;ZERO OUT THE PAGE AND CHECK FOR NXM
	  JRST	MEMON8		;GOT AN NXM
	ADDM	P3,MAXMAX##	;INCREASE THE MAXIMUM VALUE FOR CORMAX
	ADDM	P3,RMCMAX##	;INCREASE REAL MAX VALUE FOR CORMAX
	SKIPN	P2		;SKIP IF NOT THE FIRST PAGE SET ON LINE
	MOVE	P2,T1		;REMEMBER THE FIRST PAGE SET ON LINE
	JUMPE	T4,MEMON7	;JUMP IF FIRST PAGE
	HRRZM	T1,@[IW MS.MEM,PAGTAB(T4)] ;LINK PAGES BEING SET ON LINE TOGETHER
MEMON7:	MOVE	T4,T1		;REMEMBER LAST PAGE
MEMON8:	IBP	P1		;BUMP BYTE POINTER TO NEXT PAGE IN NXMTAB
	CAIE	T1,-1(T2)	;LOOKED AT THE ENTIRE RANGE OF PAGES TO SET ON LINE?
	AOJA	T1,MEMON6	;NO, LOOK AT THE NEXT PAGE
IFE FTMP,<
	JUMPE	P2,CPOPJ##	;RETURN DOING NOTHING IF ALL PAGES WERE ALREADY
>				; ON LINE
IFN FTMP,<
	PJUMPE	P2,DWNMM##	;GIVE UP THE MM
>
	SETZM	@[IW MS.MEM,PAGTAB(T4)] ;INDICATE END OF THE LIST OF PAGES SET ON LINE
;HERE WHEN MEMORY HAS BEEN MARKED ON LINE AND CHECKED FOR NXM.
;ADD ALL PAGES WHICH WERE OFF LINE TO THE FREE CORE LIST.

	MOVE	T1,P2		;FIRST PAGE IN THE LIST OF PAGES SET ON LINE
	MOVE	P1,T4		;LAST PAGE FREED
	LSH	T4,P2WLSH	;HIGHEST ADDRESS SET ON LINE
	ADDI	T4,PAGSIZ	;ADDRESS OF PAGE FOLLOWING HIGHEST SET ON LINE
	CAMLE	T4,MEMSIZ##	;IS THAT GREATER THAN CURRENT MEMORY SIZE?
	MOVEM	T4,MEMSIZ##	;YES, SAVE NEW HIGHEST ADDRESS IN MEMORY + 1
	MOVE	T4,MEMSIZ##	;HIGHEST ADDRESS IN MEMORY + 1
	LSH	T4,W2PLSH	;CONVERT TO HIGHEST PAGE
	MOVE	T2,T4		;NEW HIGHEST PAGE
	TRZE	T2,PG.BDY	;ROUND UP
	ADDI	T2,PP256K##	;TO A 256K BOUNDARY
	IDIVI	T2,^D36		;BITS/WORD
	MOVNI	T2,1(T2)	;NEGATIVE LENGTH OF NXMTAB
	HRLM	T2,NXMPTR##	;UPDATE NXMPTR TO REFLECT ADDITIONAL MEMORY
	MOVEI	T4,PAGTAB-1(T4)	;BYTE POINTER TO HIGHEST PAGE IN MEMORY
	SSX	T4,MS.MEM	;GIVE IT A SECTION NUMBER
	MOVEM	T4,CORLST##	;STORE THAT FOR CHKTAL
	SSX	T1,MS.MEM	;CLEAR BACK POINTER SO
	HLLZS	PT2TAB(T1)	;GVPAGS DOESN'T GET CONFUSED
	PUSHJ	P,GVPAGS##	;ADD THE PAGES SET ON LINE TO THE FREE CORE LIST

;FINISH UP

	PUSHJ	P,CPINXF##	;FIX CORE ALLOCATION VARIABLES
	  JFCL			;CORMAX MAY HAVE CHANGED, BUT ALL JOBS WILL STILL FIT
IFN FTMP,<
	PUSHJ	P,DWNMM##	;GIVE UP THE MM
>; END IFN FTMP

	MOVEI	T1,.CSCMO	;CONFIG STATUS CODE
	PJRST	MEMELG##	;MAKE AN ERROR LOG ENTRY
;ROUTINE TO ZERO THE PAGE BEING SET ON-LINE AND CHECK FOR NXM.
;CALL WITH T1=PAGE NUMBER, P1=BYTE POINTER TO NXMTAB
;RETURNS CPOPJ IF NXM, CPOPJ1 IF PAGE OK.
;MUST BE CALLED WITH MM, RETURNS WITH MM.
;PRESERVES T1-T4.

MEMOZR:	PUSHJ	P,SAVT##	;SAVE T1-T4
	HRRZ	T3,T1		;GET PAGE NUMBER
	MOVE	T4,.CPMAP##	;GET ADDRESS OF EXEC MAP
	HRLI	T3,(<PM.DCD>B2+PM.WRT) ;ACCESSIBLE AND WRITABLE
	MOVEM	T3,.EUPMP/PAGSIZ(T4) ;SET NEW MAPPING FOR PAGE
	CLRPT	.EUPMP		;FLUSH PAGE TABLE SO NEW MAPPING IS IN EFFECT
IFN FTMP,<
	PUSHJ	P,DWNMM##	;GIVE UP THE MM IN CASE NXM HAPPENS
>; END IFN FTMP
	MOVEI	T4,1000		;TIME TO WAIT FOR NXM TO CAUSE AN INTERRUPT
	MOVEM	J,MOFLPG##	;FLAG WE ARE SETTING MEMORY OFF-LINE
	SETZM	.EUPMP		;ZERO FIRST WORD OF PAGE
	SOJG	T4,.		;WAIT LONG ENOUGH FOR NXM INTERRUPT TO HAPPEN
	LDB	T3,P1		;GET BIT FROM NXMTAB
	JUMPN	T3,MEMOZ1	;JUMP IF NXM HAPPENED
	MOVE	T3,[XWD .EUPMP,.EUPMP+1] ;SET TO CLEAR REMAINDER OF PAGE
	MOVEI	T4,1000		;TIME TO WAIT FOR NXM TO CAUSE AN INTERRUPT
	BLT	T3,.EUPMP+PG.BDY ;ZERO THE REMAINDER OF THE PAGE
	SOJG	T4,.		;WAIT LONG ENOUGH FOR NXM INTERRUPT TO HAPPEN
	LDB	T3,P1		;GET BIT FROM NXMTAB
	SKIPN	T3		;DID NXM HAPPEN?
	AOS	(P)		;NO, SET UP SKIP RETURN
MEMOZ1:	SETZM	MOFLPG##	;NO LONGER CHECKING FOR OFFLINE PAGE
IFN FTMP,<
	PUSHJ	P,UPMM##	;GET BACK THE MM
>; END IFN FTMP
	POPJ	P,		;RETURN
SETME1:	SKIPN	[M.LOK##]	;MUST HAVE THE LOCK UUO TO SET MEMORY OFF
	JRST	COMERA		;ERROR IF LOKCON NOT LOADED
	PUSHJ	P,CKMOL##	;CHECK THAT RANGE DOESN'T OVERLAP THE MONITOR
	  JRST	SETME6		;IT DOES SO WE CAN'T DO IT
	LDB	T3,[POINT 14,NWCORE##,26] ;GET TOTAL SIZE (ON OR OFF)
	CAIL	T1,(T3)		;LOWER BOUND BEYOND END?
	POPJ	P,		;YES, IT'S ALREADY OFF
	CAIL	T2,(T3)		;UPPER BOUND BEYOND END?
	MOVE	T2,T3		;YES,CHANGE UPPER BOUND
	PUSH	P,T1		;SAVE LOWER BOUND
	PUSH	P,T2		;AND UPPER BOUND
	MOVEI	P1,[ASCIZ /?Job(s) too big to continue to run/]
	PUSHJ	P,NEWCMX##	;SEE IF ALL JOBS CAN CONTINUE TO RUN
	JUMPLE	T1,[POP P,(P)	;IF .LE. 0, TRYING TO SET MONITOR MEMORY OFF LINE
		    POP P,(P)
		    JRST SETME6];GO EXPLAIN THE PROBLEM
	PUSH	P,J		;SAVE J FOR COMRET
	MOVEI	J,0		;STARTING WITH JOB 0,
SETME3:	PUSHJ	P,JBSTBG##	;MAKE SURE ALL JOBS CAN STILL RUN (I.E., NONE IS TOO BIG)
	  JRST	SETME4		;NONE ARE
	PUSHJ	P,MOLMS		;TELL THE OPR ABOUT THIS JOB
	JRST	SETME3		;AND LOOK FOR MORE THAT ARE TOO BIG
SETME4:	JUMPE	P1,SETME7	;EXIT IF SOME JOBS WERE TO BIG
	MOVEI	P1,[ASCIZ /?Attempt to set memory containing locked jobs off-line/]
	MOVEI	J,0		;STARTING WITH JOB 0,
	MOVE	T1,-2(P)	;LOWER BOUND,
SETME5:	MOVE	T2,-1(P)	;UPPER BOUND,
	PUSHJ	P,CKLJB##	;SEE IF RANGE OVERLAPS SOME LOCKED JOB
	  JRST	SETME7		;IT DOESN'T SO ALL IS WELL
	PUSHJ	P,MOLMS		;TELL THE OPR ABOUT THIS JOB
	JRST	SETME5		;AND LOOP TO SEE IF THERE ARE ANY MORE IN THE WAY
SETME6:	JSP	T1,ERRMES	;PRINT THE ERROR MESSAGE
	ASCIZ	/Attempt to set monitor memory off-line/
SETME7:	POP	P,J		;RESTORE J FOR COMRET
	POP	P,T2		;RESTORE UPPER BOUND
	POP	P,T1		;AND LOWER BOUND
	JUMPE	P1,PCRLF	;EXIT IF THERE WAS AN ERROR
	PJRST	MEMOFL##	;GO SET THE MEMORY OFF-LINE

MOLMS:	PUSH	P,T1		;SAVE T1
	SKIPE	T1,P1		;SKIP IF ERROR MESSAGE WAS ALREADY TYPED
	PUSHJ	P,CONMES	;TYPE THE ERROR MESSAGE
	MOVEI	T1,[ASCIZ/
?Problem with job(s)/]
	SKIPE	P1		;SAY PROBLEM WITH JOBS ONCE
	PUSHJ	P,CONMES	;TYPE THAT
	MOVEI	P1,0		;FLAG AN ERROR AND DON'T PRINT ERROR HEADING TWICE
	TLO	M,ERRFLG	;TELL COMRET THAT THERE WAS AN ERROR
	PUSHJ	P,PRJBNM##	;DISPLAY INFO. ABOUT THE PROBLEM JOB
	JRST	TPOPJ##		;RESTORE T1, AND RETURN
	SUBTTL	SET COMMAND AND UUO -- DAYTIME AND SCHED

SETDAY::PUSHJ	P,SETLGL
	  JRST	COMERA
	PUSHJ	P,RDTIM		;GET TIME OF DAY
	  PJRST	ERRCRL		;ISSUE CRLF/ERROR MESSAGE AND RETURN
	JRST	SETDA3		;SKIP AROUND SETUUO CHECK

SETDA0:
IFN FTMP,<	                ;IF SMP
 	PUSHJ	P,ONCPU0##	;RUN ON POLICY CPU
>; END IFN FTMP
	CAIL	T2,<^D24*^D60*^D60> ;RANGE CHECK IT
	JRST	ECOD3##		;ILLEGAL TIME (GREATER THAN 23:59:59)
	MOVE	T1,T2		;SHUFFLE TIME TO SAME AC RDTIM USES

SETDA3::MOVE	T4,T1		;SAVE RESULT
	IDIVI	T1,^D60*^D60	;T1:= HOURS
	IDIVI	T2,^D60		;T2:= MINUTES, T3:= SECONDS
	MOVEM	T1,LOCHOR##	;SAVE HOURS
	MOVEM	T2,LOCMIN##	;SAVE MINUTES
	MOVEM	T3,LOCSEC##	;SAVE SECONDS
	IMUL	T4,TICSEC##	;CONVERT TO JIFFIES
	MOVEM	T4,TIME##	;SAVE IT
	MOVEM	T4,.CPTML##	;SAVE TIME AT THE LAST CLOCK TIC
	MOVEI	T1,.C0CDB##	;POINT AT FIRST CDB
	MOVN	T2,T3		;GET -SECONDS
	ADDI	T2,^D60		;GET SECONDS 'TIL NEXT MINUTE
	MOVE	T3,TICSEC##	;TIME TO NEXT SECOND
	JRST	SETDA2		;ENTER COMMON CODE

SETDA1:
IFN FTMP,<			;IF SMP
	PUSHJ	P,ONCPU0##	;RUN ON POLICY CPU
>;END IFN FTMP
        IDIVI	T2,^D100	;HOURS INTO T2
	MOVEM	T3,LOCMIN##
	MOVEM	T2,LOCHOR##
	SETZM	LOCSEC##	;ZERO SECOND COUNTER
	IMULI	T2,^D60		;CONVERT HOURS TO MINS
	ADD	T2,T3		;+ORIGINAL MINS
	IMUL	T2,TICMIN##	;CONVERT TO JIFFIES
	MOVEM	T2,TIME##	;SAVE AS NEW TIME
	MOVEM	T2,.CPTML##
	MOVEI	T1,.C0CDB##	;POINT AT FIRST CDB
	MOVEI	T2,^D60		;TIME TO NEXT MINUTE
	MOVE	T3,TICSEC##	;TIME TO NEXT SECOND
SETDA2:	MOVEM	T2,.CPSEC##-.CPCDB##(T1) ;STORE IN THIS CDB
	MOVEM	T3,.CPHTM##-.CPCDB##(T1) ;TIME TO NEXT SECOND
	HLRZ	T1,.CPCDB##-.CPCDB##(T1) ;STEP TO NEXT
	JUMPN	T1,SETDA2	;LOOP FOR ALL
	PUSHJ	P,OMSTIM##	;RECOMPUTE OPR MESSAGE TIME
	PJRST	SETDT2		;FIXUP 'DATE' & SKIP RETURN

SETSCD::PUSHJ	P,SETLGL	;CHECK FOR LEGALITY
	  JRST	COMERA		;NOT LEGAL
	PUSHJ	P,OCTIN1	;OK - GET OCTAL NUMBER
	  PJRST NOTENF		;NOT ENOUGH ARGS
	  PJRST COMERA		;ILLEGAL NUMBER
SETSC1:	HRRZ	T1,STATES##	;GET OLD SCHEDULE
	HRRM	T2,STATES##	;SET NEW SCHEDULE
	CAIE	T1,(T2)		;OLD AND NEW THE SAME?
	PUSHJ	P,SNDSCM##	;NO, TELL QUASAR IT CHANGED
	  JFCL
	JRST	CPOPJ1##	;AND SKIP RETURN

SETIM1:	IMUL	T2,TICSEC##	;CONVERT TO JIFFIES
	MOVSI	T3,(JB.LBT)	;GET BATCH BIT
	TDNN	T3,JBTLIM##(J)	;BATCH JOB?
	JRST	SETIM2		;NO, GO STORE
	LDB	T3,JBYLTM##	;YES, LAST CHANCE
	JUMPE	T3,SETIM2	;CAN ALWAYS ADD RESTRICTIONS
	PUSHJ	P,PRVJC		;IS HE [1,2] OR JACCT?
	  JRST	SETIM2		;LET HIM THROUGH
	PJRST	RTZER##		;NO, BOMB HIM

SETRTM::PUSHJ	P,DECIN1	;GET DECIMAL NO OF SECS
	  PJRST NOTENF		;NOT ENOUGH ARGS
	  PJRST COMERA		;NOTA NUMBER
	IMUL	T2,TICSEC##	;CONVERT TO JIFFIES
	TLNE	T2,(-JB.LTM-1)	;SEE IF TOO BIG
	PJRST	COMERA		;YES. ERROR
	MOVEI	T1,BATMSG
	LDB	T3,JBYLTM##
	JUMPE	T3,SETIM2
	MOVE	T3,JBTLIM##(J)
	TLNE	T3,(JB.LBT)
	JRST	ERRMES
SETIM2:	DPB	T2,JBYLTM##
	JRST	CPOPJ1##	;AND RETURN
	SUBTTL	SET COMMAND AND UUO -- OPR, LOGMIN&MAX BATMIN##&MAX

SETOPR::PUSHJ	P,SETLGL	;SEE IF SET OPR LEGAL
	  JRST	COMERA		;NOT LEGAL
	PUSHJ	P,CTEXT1	;GET NAME OF DEVICE
	MOVE	T1,T2		;MOVE FOR STDOPR
	PUSHJ	P,STDOPR##	;SET IT
	  PJRST	COMERA		;NO GOOD
	POPJ	P,0		;GOOD

SETOP1:	HRR	M,T2		;UUO, GET ADDRESS
	PUSHJ	P,GETWDU##	;GET CONTENTS IF LEGAL

	PUSHJ	P,STDOPR##	;CHANGE DEVICE
	  JRST ECOD0##		;ERROR RETURN
	JRST	CPOPJ1##	;GOOD RETURN


;LOGIN CONTROL PARAMETERS

SETLMX:	CAIL	T2,1		;LOGMAX MUST BE .GE. 1
	CAILE	T2,M.JOB##	;  AND .LE. M.JOB
	JRST	ECOD0##
	MOVEM	T2,LOGMAX##
	JRST	CPOPJ1##

SETBMX:	CAIL	T2,0		;BATMAX MUST BE .GE. 0
	CAILE	T2,M.JOB##	;  AND .LE. M.JOB
	JRST	ECOD0##
	MOVEM	T2,BATMAX##
	JRST	CPOPJ1##

SETBMN:	CAIL	T2,0		;BATMIN MUST BE .GE. 0
	CAMLE	T2,BATMAX##	;  AND .LE. BATMAX
	JRST	ECOD0##
	MOVEM	T2,BATMIN##
	JRST	CPOPJ1##

;SET QUEUE STRUCTURE
SETQST:	HRR	M,T2		;GET ADDR OF USER'S ARG
	PUSHJ	P,GETWDU##	;GET THE ARGUMENT
	SKIPE	T1		;WEED OUT JUNK
	PUSHJ	P,SRSTR##	;MAKE SURE ITS A KNOWN STR
	  PJRST	ECOD2##		;LOSE - ILLEGAL STRUCTURE
	MOVEM	T1,QUESTR##	;SAVE FOR % LDQUS GETTAB
	JRST	CPOPJ1##	;RETURN
	SUBTTL	SET COMMAND AND UUO -- WATCH

SETWAT::PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,[IORM T2,JBTWCH##(J)]	;WE'RE CHANGING JBTWCH(J)
	PUSHJ	P,CTEXT		;GET 1ST ARG
	JUMPE	T2,WATLP1	;ERROR IF MISSING
	SKIPA	T1,[-WATLEN-NOTLEN,,WATTAB]	;SCAN BOTH TABLES 1ST TIME
WATLOP:	MOVE	T1,[-WATLEN,,WATTAB]	;POINT TO TABLE
	PUSHJ	P,FNDNAM	;LOOK FOR ABBREV.
	  JRST	WATLP1		;ERROR
	CAIL	T1,NOTTAB-WATTAB	;SEE IF IN NOTTAB
	JRST	WATCH2		;YES, MUST BE NO, ALL, NONE
	MOVNI	T1,(T1)		;-NO. OF ENTRY IN TABLE
	MOVSI	T2,JW.WCX	;FIRST BIT
	ROT	T2,(T1)		;ROTATE RIGHT TO PROPER POSITION
WATCH1:	XCT	P1		;ANDCAM OR IORM T2,JBTWCH(J)
	PUSHJ	P,CTEXT		;GET NEXT ARG
	JUMPE	T2,CPOPJ##	;0 IF FINISHED OR NONE
	JRST	WATLOP		;AND SET A BIT FOR IT
WATCH2:	SUBI	T1,WATLEN	;RELATIVE TO NOTTAB
	TRNN	T1,1		;NO OR NONE?
	HRLI	P1,(ANDCAM T2,(J))	;YES
	MOVSI	T2,WCHALL	;READY FOR ALL,NONE
	JUMPN	T1,WATCH1	;YES IT IS
	PUSHJ	P,CTEXT		;GET ARG OF NO
	JUMPN	T2,WATLOP	;SEE IF VALID


WATLP1:	JSP	T1,ERRMES	;NO, TELL USER THE LEGAL ONES
	ASCIZ	/Args are: contexts,day,run,wait,read,write,version,mta,files,all,none/
$LOW
WATTAB::<SIXBIT /CONTEXTS/>
	<SIXBIT /DAY/>
	<SIXBIT	/RUN/>
	<SIXBIT	/WAIT/>
	<SIXBIT	/READS/>
	<SIXBIT	/WRITES/>
	<SIXBIT	/VERSION/>
	<SIXBIT	/MTA/>
	<SIXBIT	/FILES/>
;ADD NEW ITEMS HERE AND IN ERROR COMMENT AND IN S.MAC
WATLEN==.-WATTAB
WTCMXL==:<WATLEN-1>B26

;THIS TABLE MUST BE IN ORDER NO, ALL, NONE
;AND MUST FOLLOW WATTAB

NOTTAB:	<SIXBIT	/NO/>
	<SIXBIT	/ALL/>
	<SIXBIT	/NONE/>
NOTLEN==.-NOTTAB
	$HIGH
	SUBTTL	SET COMMAND AND UUO -- DATE


SETDAT::PUSHJ	P,SETLGL	;TEST FOR LEGALITY
	  JRST	COMERA		;NOT PRIVILEGED
	PUSHJ	P,SAVE3##	;FRE UP SOME ACS
	MOVE	P1,LOCYER##	;SAVE THE OLD DATE
	MOVE	P2,LOCMON##
	MOVE	P3,LOCDAY##
	MOVEI	T1,LOCYER##
	PUSHJ	P,GTDATE	;ACCEPT E.G. 3-JAN-72
	JRST	[MOVEM P1,LOCYER## ;RESTORE OLD DATE
		 MOVEM P2,LOCMON##
		 MOVEM P3,LOCDAY##
		 JRST COMERR]	;BAD DATA
SETDT2:	AOS	(P)		;SKIP RETURN
	PUSH	P,DATE##	;SAVE OLDDAE
	PUSHJ	P,SUDATE##	;RECOMPUTE UNIV. DATE
	POP	P,T1		;GET OLD DATE BACK
	SUB	T1,DATE##	;SUBTRACT NEW FROM OLD
	MOVNS	T1		;MAKE IT ADDITIVE
	MOVEM	T1,DTCVAL	;SAVE DATE/TIME CHANGE VALUE
	MOVE	T2,HIGHJB##	;GET HIGHEST JOB ASSIGNED
SETDT3:	SKIPE	JBTJLT##(T2)	;ANYTHING THERE?
	ADDM	T1,JBTJLT##(T2)	;YES, ADJUST IT
	HRRZ	T3,JBTPDB##(T2)	;GET PDB ADDR
	CAIE	T3,0		;SEE IF THERE
	ADDM	T1,.PDSTM##(T3)	;YES ADJUST IT
	SOJG	T2,SETDT3	; AND LOOP
	SKIPE	RSDTTM##	;LAST CPU ROLE SWITCH?
	 ADDM	T1,RSDTTM##	;YES--UPDATE IT
IFN FTNSCHED,<
	SKIPE	SCDSTS##	;LAST SETTING OF SCHEDULER PARAMETERS?
	 ADDM	T1,SCDSTS##	;YES--UPDATE IT
>;END IFN FTNSCHED
	SKIPE	SCDSET##	;..
	 ADDM	T1,SCDSET##	;YES
	PUSHJ	P,FILSDT##	;TELL FILSER TO FIX THINGS UP
	PUSHJ	P,ENQSDT##	;AND QUESER
	PUSHJ	P,PSISDT##	;SIGNAL USERS TOO

	SETZ	T1,		;CAUSE SEB ALLOCATION TO HAPPEN
	XMOVEI	T2,DTCTBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB##	;FILL AND QUEUE UP RECORD
	  JFCL			;NO CORE
IFN FTKL10,<
	PUSHJ	P,THSDA##	;RECOMPUTE 12 BIT DATE
	PJRST	COMSDT##	;TELL ANY FRONT ENDS ABOUT D/T CHANGE
>;END IFN FTKL10
IFN FTKS10,<PJRST THSDA##>	;RECOMPUTE 12 BIT DATE AND RETURN


;DATE/TIME CHANGE TRANSFER TABLE FOR ERROR.SYS LOGGING
DTCTBL:	SEBTBL	(.ERCSC,DTCEND,<EX.QUE!EX.AVL>)
	MOVE	DTCVAL		;(R00) OFFSET TO NEW DATE/TIME
	MOVE	DATE##		;(R01) CURRENT DATE/TIME
	MOVSI	.CSCTC		;(R02) REASON CODE
DTCEND:!			;END OF TABLE

	$LOW
DTCVAL:	EXP	0		;DATE/TIME CHANGE VALUE
	$HIGH
SETDT1:
IFN FTMP,<			;IF SMP
	PUSHJ	P,ONCPU0##	;RUN ON POLICY CPU
>;END IFN FTMP
	IDIVI	T2,^D31		;DECOMPOSE 12 BIT DATE INTO LOCYER...
	AOS	T3
	MOVEM	T3,LOCDAY##
	IDIVI	T2,^D12
	AOS	T3
	MOVEM	T3,LOCMON##
	ADDI	T2,^D1964
	MOVEM	T2,LOCYER##
	JRST	SETDT2		;GO MAKE & STORE THSDAT & DATE


SETKSY::
IFN FTMP,<			;IF SMP
	PUSHJ	P,ONCPU0##	;RUN ON POLICY CPU
>; END IFN FTMP
	CAIN	T2,-1		;KSYS NOW?
	SETOM	T2		;YES
	MOVEM	T2,SYSKTM##	;STORE VALUE FOR CLOCK1
	PUSHJ	P,PSIKSY##	;TELL EVERYONE OF CHANGE
	JRST	CPOPJ1##	;RETURN
	SUBTTL	SET COMMAND AND UUO -- SPOOL

SETSPL::PUSHJ	P,SAVE2##	;SAVE P1
	MOVE	P1,[IORM T2,JBTSPL##(J)]	;WE'RE CHANGING JBTSPL
	PUSHJ	P,CTXDEV	;GET 1ST ARG
	JUMPE	T2,NOTENF	;NOT ENOUGH ARGS
	MOVE	T1,[-NOTLEN,,NOTTAB]
	PUSHJ	P,FNDNAM	;SEE IF NO. ALL, NONE
	  JRST	SETSP0		;NO, SEE IF DEVICE
	TRNN	T1,1		;IS IF NO OR NONE
	HRLI	P1,(ANDCAM T2,(J))	;YES, TURN OFF BIT
	JUMPN	T1,SETSP3	;ALL OR NONE?
	PUSHJ	P,CTXDEV	;NO, GET ARG FOR NO
	JUMPE	T2,NOTENF	;NOT ENOUGH ARGS
SETSP0:	MOVEI	F,SPLTAB##	;POINT TO SPOOL TABLE
	TRNN	T2,-1		;DID HE SPEC A PHYS DEV?
	JRST	SETSP1		;NO ALL IS OK
	JSP	T1,ERRMES	;YES, GIVE A MESSAGE
	ASCIZ	/Cannot spool a physical device
/

SETSP1:	CAMN	T2,SPLNAM##(F)	;HATCH?
	JRST	SETSP2		;YES!
	ADDI	F,SPLLEN##	;BUMP TO NEXT CARRY
	CAIGE	F,SPLTOP##	;DONE?
	JRST	SETSP1		;NO, LOOP
	JSP	T1,ERRMES	;YES, NOT FOUND
	ASCIZ	/Not a spoolable device
/
SETSP2:	HRRZ	T2,SPLBIT##(F)	;GET THE SPOOL BIT
	SKIPA			;SKIP ALTERNATE ENTRY
SETSP3:	MOVEI	T2,.SPALL	;ALL OR NONE

	TLNE	P1,20000	;P1 AN ANDCAM?
	JRST	SETSP4		;NO - ALWAYS ALLOWED TO SET SPOOLING
	MOVSI	T1,PVNSPL	;PRIV?
	TSNN	T1,STATES##	;OR SCHED BIT?
	PUSHJ	P,PRVBIT	;90 SEC.
;NOTE THIS CODE DEPENDS ON PVNSPL=ST.NSP
IFN PVNSPL-ST.NSP,<PRINTX ST.NSP DOESN'T=PVNSPL>
	JRST	SETSP4		;YES - OK
	JSP	T1,ERRMES	;NO - TYPE THE MESSAGE:
	ASCIZ	/No privs to unspool
/
SETSP4:	XCT	P1		;TURN ON/OFF SPOOL BIT(S)
	MOVE	F,LDBDDB##(U)	; AND F
	PUSHJ	P,CTXDEV	;GET NEXT DEV
	JUMPE	T2,CPOPJ##	;RETURN IF NOTHING
	JRST	SETSP0		;AND SET ITS BIT
	SUBTTL	SET COMMAND AND UUO -- DEFER/NODEFER - BATCH STREAM - WTO - OPER PRIV
;ENTER HERE ON SETUUO FOR DEFER/NODEFER
SETDFU:	JUMPE	T2,SETNDC	;ZERO MEANS NO-DEFERED
				; ELSE FALL INTO DEFER

;ENTER HERE ON SET DEFER COMMAND
SETDFC::MOVEI	T2,JB.DFR	;GET DEFER BIT
	IORM	T2,JBTSPL##(J)	;SET IT
	JRST	CPOPJ1##	;RETURN

;ENTER HERE ON SET NODEFER COMMAND
SETNDC::MOVEI	T2,JB.DFR	;GET DEFER BIT
	ANDCAM	T2,JBTSPL##(J)	;CLEAR IT
	JRST	CPOPJ1##	;RETURN

;ENTER HERE ON SETUUO FOR BATCH-STREAM-NUMBER

SETBSN:	MOVSI	T1,(JB.BSS)	;LOAD "ALREADY SET" BIT
	TDNE	T1,.PDOBI##(W)	;TEST IT
	JRST	ECOD0##		;SET ALREADY!
	DPB	T2,PDYBSN##	;STORE VALUE
	IORM	T1,.PDOBI##(W)	;SET BIT
	JRST	CPOPJ1##	;RETURN

;ENTER HERE ON SETUUO FOR WTO CAPABILITIES

SETWTO:	DPB	T2,PDYWTO##	;STORE VALUE
	JRST	CPOPJ1##	;AND RETURN


;ENTER HERE ON SET OPER PRIVILEGE
SETOPP:	DPB	T2,PDYOPP##
	JRST	CPOPJ1##
	SUBTTL	SET COMMAND AND UUO -- DEFAULTS

SETDFL::PUSHJ	P,CTEXT		;GET DEFAULT ARGUMENT MODIFIER
	JUMPE	T2,NOTENF	;MUST BE ONE
	MOVE	T1,[-DFLTTL,,DFLTTB]	;ARGUMENT FOR FNDNAM
	PUSHJ	P,FNDNAM	;SEE IF A LEGAL MODIFIER WAS SPECIFIED
	  JRST	COMERA		;BAD ARGUMENT
	TLNN	P4,JLOG
	SKIPGE	DFLCTB(T1)
	JRST	@DFLCTB(T1)	;DISPATCH TO SET THE DEFAULT
	JRST	STARTE

;HERE ON SET DEFAULT UUO
SETDLU:	HRR	M,T2		;ADDRESS OF FUNCTION CODE
	PUSHJ	P,GETWDU##	;GET THE FUNCTION CODE
	HLRZ	T2,T1		;NUMBER OF ARGUMENTS
	HRRZS	T1		;FUNCTION CODE
	CAILE	T1,DFLUTL	;IS IT A DEFINED FUNCTION CODE?
	JRST	ECOD0##		;NO, ERROR RETURN
	JRST	@DFLUTB(T1)	;DISPATCH TO SET THE DEFAULT

DEFINE NAMES<
	C	PROTECTION,DFLPRT,0
	C	BUFFERS,DFLBFN,0
	C	ACCOUNT,DFLACS,400000
	C	BIGBUF,DFLBBC,0

>
DEFINE C(A,B,D,E)<
IFNB<E>,<E:>
	<SIXBIT /A/>
>
XALL
DFLTTB::NAMES
DFLTTL==.-DFLTTB
DFLMXL==:<DFLTTL-1>B26
DEFINE C(A,B,D,E)<
	XWD	D,B
>
DFLCTB:	NAMES
DFLUTB:	EXP	DFLPRU
	EXP	DFLBFU
	EXP	DFLDAU
	EXP	DFLBBU
DFLUTL==.-DFLUTB-1
SALL
;HERE ON SET DEFAULT PROTECTION COMMAND
DFLPRT:	MOVE	T1,[-2,,[SIXBIT /ON/
		         SIXBIT /OFF/]]
	PUSHJ	P,TXTARG	;WAS "ON OR OFF" TYPED?
	  JRST	DFLPR0		;NO
	JUMPE	T1,DFLPR1	;JUMP IF ON WAS TYPED
	MOVSI	T1,(PD.DPS)	;YES, CLEAR THE BIT WHICH SAYS
	ANDCAM	T1,.PDDFL##(W)	; DEFAULT PROTECTION WAS SET
	POPJ	P,		;AND RETURN
DFLPR0:	PUSHJ	P,SKIPS1	;SKIP BLANKS, TABS, ETC.
	  JFCL			;IGNORE
	CAIN	T3,074		;WAS A BRACKET TYPED ?
	PUSHJ	P,COMTYS	;YES, FLUSH IT.
	PUSHJ	P,OCTIN1	;READ THE PROTECTION VALUE
	  JRST	NOTENF		;IT MUST BE THERE
	  JRST	COMERA		;ILLEGAL CHARACTER
	TDNE	T2,[-1,,777000]	;LEGAL PROTECTION VALUE ?
	JRST	COMERA		;NO, COMPLAIN
	DPB	T2,PDYDPT##	;STORE DEFAULT PROTECTION
	JRST	DFLPR1		;AND INDICATE A DEFAULT WAS SPECIFIED

;HERE ON SET DEFAULT PROTECTION UUO
DFLPRU:	PUSHJ	P,GETWD1##	;GET THE PROTECTION VALUE
	TDNE	T1,[-1,,777000]	;LEGAL ?
	JRST	ECOD0##		;NO, ERROR RETURN
	DPB	T1,PDYDPT##	;STORE DEFAULT PROTECTION
DFLPR1:	MOVSI	T1,(PD.DPS)	;DEFAULT PROTECTION SPECIFIED BIT
	IORM	T1,.PDDFL##(W)	;LITE THAT
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN

;HERE ON SET DEFAULT NUMBER OF BUFFERS COMMAND
DFLBFN:	PUSHJ	P,DECIN		;READ NUMBER
	  JRST	NOTENF		;NOT THERE
	  JRST	COMERA		;NOT A NUMBER
	TDNE	T2,[-1,,777000]	;IN RANGE?
	JRST	COMERA		;NO, ERROR
	SKIPA	T1,T2		;YES, STORE DEFAULT NUMBER
;HERE ON SET DEFAULT BUFFERS UUO
DFLBFU:	PUSHJ	P,GETWD1##	;GET ARGUMENT
	TDNE	T1,[-1,777000]	;IN RANGE?
	JRST	ECOD0##		;NO, ERROR
	DPB	T1,PDYBFN##	;STORE DEFAULT NUMBER OF DISK BUFFERS
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN
;HERE ON SET DEFAULT DON'T ASK ABOUT DETACHED JOBS UUO
DFLDAU:	PUSHJ	P,GETWD1##	;GET ARGUMENT
	MOVE	T2,.PDDFL##(W)	;DEFAULT WORD
	SKIPN	T1		;SET?
	TLZA	T2,(PD.DAD)	;NO, CLEAR
	TLO	T2,(PD.DAD)	;YES
	MOVEM	T2,.PDDFL##(W)	;STORE ANSWER
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN
;HERE TO SET DEFAULT ACCOUNT STRING (USED FOR JOBS LOGGED IN ON FRCLIN)
DFLACS:	PUSHJ	P,SETLGL	;MUST BE OPR
	  JRST	COMERA		;NOT, COMPLAIN
	PUSHJ	P,SAVE2##	;WORKING ACS
	HRRZ	P1,JBTPDB##+0	;NULL JOB'S PDB
	ADD	P1,[POINT 7,.PDACS##] ;WHERE TO STORE DEFAULT
	HRREI	P2,5*ACTSTL##-1	;LENGTH OF ACCOUNT STRING
	JUMPLE	P2,COMERA	;FORGET IT IF ZERO LENGTH
DFLAC1:	PUSHJ	P,COMTYI##	;NEXT CHARACTER
	CAIE	T3,12		;LINEFEED?
	CAIN	T3,3		;OR CONTROL C
	JRST	DFLAC2		;YES, THAT'S ALL FOLKS
	IDPB	T3,P1		;NO, STORE THE CHARACTER
	SOJG	P2,DFLAC1	;LOOP FOR MORE
DFLAC2:	MOVEI	T1,0		;ASCIZIZE
	IDPB	T1,P1
	POPJ	P,		;RETURN


;HERE ON SET DEFAULT BIGBUF COMMAND
DFLBBC:	PUSHJ	P,DECIN		;GET THE NUMBER OF BLOCKS PER BUFFER
	  JRST	NOTENF		;NOT THERE
	  JRST	COMERA		;NOT A NUMBER
	MOVE	T1,T2
	CAILE	T1,LIMBBF	;IN RANGE?
	JRST	COMERA		;NO, ERROR
	TLO	M,400000	;SET THAT IT GETS SET PERMANENTLY
	JRST	DFLBB2

;HERE ON SET DEFAULT BIGBUF UUO
DFLBBU:	PUSHJ	P,GETWD1##
	TLNN	T1,-1		;SET JOB-WIDE DEFAULT?
	JRST	DFLBB1		;NO, CONTINUE
	HLRZS	T1		;YES, MAKE IT AN RH QUANTITY
	TLO	M,400000	;PRETEND WE HAVE A COMMAND
DFLBB1:	CAILE	T1,LIMBBF##	;IN RANGE?
	JRST	ECOD0##		;NO, ERROR
DFLBB2:	LSH	T1,BLKLSH##	;YES, CONVERT TO NUMBER OF WORDS
	SKIPE	T1		;CLEAR IT IF ARGUMENT IS 0
	ADDI	T1,1
	SKIPL	M		;UUO?
	HRLM	T1,.PDLBS##(W)	; SAVE IN PDB
	SKIPGE	M		;COMMAND?
	HRRM	T1,.PDLBS##(W)	; SAVE IN PBD
	JRST	CPOPJ1##	;AND TAKE GOOD RETURN
SUBTTL	SET COMMAND AND UUO -- BREAK

IFN FTKS10,<
;NO ADDRESS BREAK
	XP	SETBRK,COMERA
	XP	SETABR,CPOPJ##
	XP	CLRBRK,CPOPJ##
>

IFN FTKL10,<

;HERE IF THE USER TYPED SET BREAK
SETBRK::PUSHJ	P,SAVE2##	;SAVE P1,P2
	PUSHJ	P,FNDPDS##	;FIND THE PDB FOR THIS USER
	MOVSI	P1,400000	;NO NUMBER SEEN YET
	PUSHJ	P,OCTPRG	;SEE IF FIRST ARGUMENT IS A NUMBER
	  JRST	SETBR2		;NOT A NUMBER, LOOK FOR LEGAL TEXT
SETBR1:	MOVE	P1,T2		;NUMBER TO P1
	CAIG	P1,17		;WEED OUT REFERENCES
	CAIGE	P1,1		;  TO THE ACS
	CAMLE	P1,[MXSECN,,-1]	;REPORT THIS AS AN ERROR RATHER THAN CONFUSING USER
	JRST	COMERA		;COMPLAIN
	DPB	P1,[POINT 23,.PDABS##(W),35] ;STORE BREAK ADDRESS
	PUSHJ	P,SGSEND	;SEE IF EOL
	  JRST	SETBR2		;NO, READ NEXT ARGUMENT
	SKIPN	P2,P1		;BREAK ADDRESS ZERO?
	JRST	SETB10		;YES, TREAT SET BREAK 0 WITH NO CONDITION LIKE NONE
	HLLZ	P2,.PDABS##(W)	;GET PREVIOUS CONDITIONS IF ANY
	TLZ	P2,(OC.BSU)	;CLEAR SET BY UUO
SETB1A:	TLNN	P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;WERE THERE ANY PREVIOUSLY?
	TLO	P2,(OC.BCI+OC.BCD+OC.BCW) ;NO, ASSUME ALL
	JRST	SETBR8		;ENABLE BREAK, STORE CONDITIONS, AND GO AWAY
SETBR2:	MOVE	T1,[-4,,BRKLS1]	;TABLE LENGTH,,ADDRESS OF THE TABLE
	PUSHJ	P,TXTARG	;RECOGNIZABLE TEXT ARGUMENT?
	  JRST	SETBR5		;NO, POSSIBLY IN ANOTHER CONTEXT
	MOVE	P2,T1		;INDEX INTO BRKTBL
	JUMPN	T1,SETBR3	;JUMP IF THE USER DIDN'T TYPE 'NONE'
;HERE WHEN THE USER TYPED 'NONE'
	JUMPGE	P1,COMERA	;IF A NUMBER WAS TYPED WE SHOULDN'T BE HERE
	JRST	SETB10		;GO CLEAR BREAK CONDITIONS
SETBR3:	PUSHJ	P,SGSEND	;AT END OF LINE?
	  CAIA			;NO
	JRST	NOTENF		;IF WE'RE HERE THERE HAS TO BE ONE
	JRST	.(P2)		;DISPATCH TO THE APPROPRIATE PROCESSOR
	JRST	SETBR4		;USER TYPED 'AT'
	JRST	SETBR5		;USER TYPED 'ON'
	JRST	SETBR6		;USER TYPED 'NO'
;HERE WHEN THE USER TYPED 'AT'
SETBR4:	JUMPGE	P1,COMERA	;NO PREVIOUS NUMBERS ALLOWED IF WE GET HERE
	PUSHJ	P,OCTPRG	;READ A NUMBER
	  JRST	COMERA		;IT MUST BE A NUMBER BUT ISN'T SO COMPLAIN
	JRST	SETBR1		;LOOK FOR THE NEXT TEXT ARGUMENT
;HERE WHEN THE USER TYPED 'ON'
SETBR5:	SKIPA	P1,[TDO P2,BRKTBL-1(T1)]
;HERE WHEN THE USER TYPED 'NO'
SETBR6:	MOVE	P1,[TDZ P2,BRKTBL-1(T1)]
	HLLZ	P2,.PDABS##(W)	;GET CURRENT BREAK CONDITIONS
	TLZ	P2,(OC.BSU)	;CLEAR SET BY UUO
SETBR7:	MOVE	T1,[-7,,BRKLS2]	;TABLE LENGTH,,TABLE ADDRESS
	PUSHJ	P,TXTARG	;GET A BREAK CONDITION
	  JRST	COMERA		;IT CAN'T BE ANYTHING ELSE
	JUMPE	T1,SETB11	;JUMP IF 'USERS'
	CAIN	T1,AFTERX
	JRST	SETB12
	XCT	P1		;SET OR CLEAR THE CONDITION
	PUSHJ	P,SGSEND	;LAST ARGUMENT?
	  JRST	SETBR7		;NO, CHECK NEXT ARGUMENT
	TLZ	P2,(OC.ABE+OC.FUP) ;ASSUME NO CONDITIONS
	TLNN	P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;ANY CONDITIONS DESIRED?
	JRST	SETB10		;NO, DECREMENT NUMBER OF USERS USING ADDRESS BREAK
SETBR8:	PUSHJ	P,BRKAV		;SEE IF ADDRESS BREAK IS AVAILABLE AND INCREMENT
				; THE COUNT OF USERS USING IT IF SO
	  JRST	NOBRAK		;NOT AVAILABLE, COMPLAIN
SETBR9:	TLOA	P2,(OC.ABE+OC.FUP) ;ENABLE THE USER FOR ADDRESS BREAK
SETB10:	PUSHJ	P,BRKDEC	;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
	LSH	P2,-^D23	;POSITION BITS
	DPB	P2,[POINT 13,.PDABS##(W),12] ;STORE NEW CONDITIONS
	POPJ	P,		;AND RETURN TO COMCON
;HERE WHEN THE USER TYPED 'USERS', MUST BE PRIVILEGED
SETB11:	PUSHJ	P,SETLGL	;USER SUFFICIENTLY PRIVILEGED TO MONOPOLIZE
				; ADDRESS BREAK?
	  JRST	COMERA		;NO, COMPLAIN
	PUSHJ	P,FDNJP		;FIND THE NULL JOB'S PDB
	MOVSI	T2,400000	;SET TO TURN ON OR OFF ADDRESS BREAK
	CAME	P1,[TDZ P2,BRKTBL-1(T1)] ;WAS 'USERS' WITHOUT A 'NO' TYPED?
	JRST	[ANDCAM	T2,.PDABS##(T1)	;YES, ALLOW USERS TO USE ADDRESS BREAK
		 POPJ	P,]	;RETURN
;HERE WHEN THE USER TYPED 'NO USERS'
	SKIPLE	.PDABS##(T1)	;IS ADDRESS BREAK CURRENTLY BEING USED?
	JRST	NOBRAK		;DON'T ALLOW HIM TO YANK IT OUT FROM UNDER THEM
	IORM	T2,.PDABS##(T1)	;DON'T ALLOW USERS TO USE ADDRESS BRAEK
	POPJ	P,		;RETURN TO COMCON

;HERE WHEN THE USER TYPED 'AFTER'
SETB12:	PUSHJ	P,DECIN		;GET THE NEXT ARGUMENT
	  PJRST	NOTENF		;THERE MUST BE ONE
	  JRST	COMERA		;NOTHING BUT A NUMBER IS LEGAL
	CAILE	T2,^D510	;IS IT TOO BIG?
	JRST	COMERA		;YES
	ADDI	T2,1
	DPB	T2,[POINT 9,.PDTMI##(W),17] ;SAVE THE REPEAT COUNT
	JRST	SETB1A		;STORE IT AND GO AWAY
;HERE ON A SET ADDRESS BREAK UUO
SETABR::PUSHJ	P,SAVE2##	;SAVE P1,P2
	HRR	M,T2		;ADDRESS OF USER'S ARGUMENT
	PUSHJ	P,GETWDU##	;GET THE ARGUMENT
	LDB	P1,[POINT 9,T1,17] ;GET PROCEED COUNT
	DPB	P1,[POINT 9,.PDTMI##(W),17] ;STORE IT
	LDB	P1,[POINT 5,T1,8];GET SECTION NUMBER
	DPB	P1,[POINT 14,T1,17] ;STORE THAT
	DPB	T1,[POINT 23,.PDABS##(W),35] ;STORE BREAK ADDRESS
	MOVE	P2,T1		;P2 = BREAK CONDITIONS
	TLO	P2,(OC.BSU)	;INDICATE SET BY UUO
	AOS	(P)		;PREPARE TO GIVE GOOD RETURN
	TLNN	P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM)
	JRST	[PUSHJ P,SETB10	;TURNING OFF BREAK
		 PJRST SETRL1##]
	PUSHJ	P,BRKAV		;IS ADDRESS BREAK AVAILABLE?
	  SOSA	(P)		;NO, ERROR RETURN
	JRST	[PUSHJ P,SETBR9	;YES, SETUP BREAK CONDITIONS
		 PJRST SETRL1##]
	JRST	ECOD0##		;GIVE ERROR RETURN
;HERE ON RESET TO CLEAR BREAK ADDRESS AND CONDITIONS
; IF SET BY UUO
CLRBRK::SKIPE	T1,.PDABS##(W)	;BREAK IN USE AT ALL?
	TLNN	T1,(OC.BSU)	;AND SET BY UUO?
	POPJ	P,		;NO
	PUSHJ	P,BRKDEC	;YES, DECREMENT COUNT OF USERS
	SETZM	.PDABS##(W)	;CLEAR ADDRESS AND CONDITIONS
	POPJ	P,		;AND RETURN
;THE ORDER OF AND THE NUMBER OF ENTRIES
; IN THE FOLLOWING TABLES CANNOT BE CHANGED
; WITHOUT CHANGING THE CODE IN SETBRK

BRKLS1:	SIXBIT	/NONE/
	SIXBIT	/AT/
	SIXBIT	/ON/
	SIXBIT	/NO/
BRKLS2:	SIXBIT	/USERS/
	SIXBIT	/EXECUT/
	SIXBIT	/READ/
	SIXBIT	/WRITE/
	SIXBIT	/MUUO/
	SIXBIT	/ALL/
BRKLS3:	SIXBIT	/AFTER/
AFTERX==BRKLS3-BRKLS2
;THE ENTRIES IN THIS TABLE CORRESPOND IN ORDER
; TO THE ENTRIES IN THE ABOVE TABLE
BRKTBL:	EXP	OC.BCI
	EXP	OC.BCD
	EXP	OC.BCW
	EXP	OC.BCM
	EXP	OC.BCI+OC.BCD+OC.BCW
;SUBROUTINE TO DETERMINE WHETHER ADDRESS BREAK IS AVAILABLE TO USERS
;CALLING SEQUENCE:
;	PUSHJ	P,BRKAV
;NON-SKIP RETURN IF NOT AVAILABLE BECAUSE MEMORY
; INDICATORS ARE DISABLED OR ADDRESS BREAK IS BEING
; USED BY SYSTEM PROGRAMMERS FOR MONITOR DEBUGGING
;SKIP RETURN IF ADDRESS BREAK IS AVAILABLE TO USERS, COUNT OF THE NUMBER
;OF USERS USING ADDRESS BREAK HAS BEEN UPDATED
;PRESERVES T2

BRKAV:	PUSHJ	P,FDNJP		;FIND THE NULL JOB'S PDB
IFN FTMP,<
	PUSHJ	P,CP0RC##	;SEE IF THE JOB IS RUNNABLE ON CPU0
	  TLNN	P2,(OC.BCM)	;ITS NOT, BUT IF HE IS ENABLED FOR UUOS, SOME
>
				; MUST HAPPEN ON CPU0
	SKIPGE	.PDABS##(T1)	;HAS ADDRESS BREAK BEEN DISABLED BY THE OPR?
	POPJ	P,		;YES, LOSE
	MOVE	T3,.PDABS##(W)	;GET HIS CURRENT ADDRESS BREAK SETTINGS
	TLNN	T3,(OC.ABE)	;IS HE ALREADY BREAKING?
	AOS	.PDABS##(T1)	;NO, COUNT UP THE NUMBER OF USERS USING ADDRESS BREAK
	JRST	CPOPJ1##	;AND GIVE THE HAPPY RETURN

;SUBROUTINE TO DECREMENT THE COUNT OF THE NUMBER
; OF USERS USING ADDRESS BREAK

BRKDEC:	MOVE	T1,.PDABS##(W)	;GET HIS CURRENT BREAK SETTINGS
	TLNN	T1,(OC.ABE)	;IS HE ENABLED FOR ADDRESS BREAK?
	POPJ	P,		;NO, NOTHING TO DO
	PUSHJ	P,FDNJP		;FIND THE PDB FOR THE NULL JOB
	SOS	.PDABS##(T1)	;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
	POPJ	P,		;AND RETURN

NOBRAK:	PJSP	T1,CONMES	;SORRY FOLKS!
	ASCIZ	/?Not available
/

;SUBROUTINE TO RETURN THE ADDRESS OF THE NULL JOB'S PDB IN T1
;PRESERVES T2-T4

FDNJP::	MOVEI	T1,0		;NULL JOB'S JOB NUMBER
	PUSHJ	P,FPDBT1##	;FIND THE NULL JOB'S PDB, RETURN ITS ADDRESS IN T1
	  JFCL			;IT MUST HAVE ONE
	POPJ	P,		;RETURN TO THE CALLER

>;END IFN FTKI10!FTKL10
	SUBTTL	SET COMMAND AND UUO -- PRIVILEGE WORDS

;HERE FOR UUO TO CHANGE PRIVILEGES

SETPRV:	HRRI	M,(T2)		;POINT TO FIRST ARGUMENT
	PUSH	P,J		;SAVE JOB NUMBER
	PUSHJ	P,GETWDU##	;PICK UP FUNCTION CODE
	SKIPL	T2,T1		;SEE IF NEGATIVE
	CAILE	T2,SPRVMX	;OR TOO LARGE
	JRST	[POP P,J	;BALANCE THE STACK
		 JRST ECOD0##]	;YES, ERROR RETURN
	ADDI	M,1
	PUSHJ	P,GTWST2##	;GET ARGUMENT INTO T1
	POP	P,J		;RESTORE JOB NUMBER
	JRST	@SPRVTB(T2)	;DISPATCH

SPRVTB:	EXP	SPRVWD		;(0) SET PRIVILEGE WORD
	EXP	SPRVON		;(1) SET BITS IN PRIV WORD
	EXP	SPRVOF		;(2) CLEAR BITS IN PRIV WORD
	EXP	SCAPWD		;(3) SET CAPABILITY WORD
	EXP	SCAPON		;(4) SET BITS IN CAPABILITY WORD
	EXP	SCAPOF		;(5) CLEAR BITS IN CAPABILITY WORD

	SPRVMX==.-SPRVTB-1	;HIGHEST FUNCTION

SPRVOF:	ANDCAB	T1,JBTPRV##(J)	;CLEAR REQUESTED BITS
	JRST	STOTC1##	;AND STORE RESULT

SPRVON:	IOR	T1,JBTPRV##(J)	;INCLUDE BITS HE ALREADY HAS
SPRVWD:	MOVE	T2,.PDCAP##(W)	;GET CAPABILITIES
	ANDCB	T2,JBTPRV##(J)	;GET BITS HE CAN'T GET
	TDNE	T1,T2		;TRYING TO SET BITS HE CAN'T HAVE?
	PUSHJ	P,PRVJ		;YES, BUT SEE IF PRIVILEGED
	  SKIPA			;OK TO SET BITS
	JRST	ECOD0##		;LOSE, ERROR RETURN
	MOVEM	T1,JBTPRV##(J)	;SET NEW PRIVILEGE WORD
	JRST	STOTC1##	;AND STORE FOR USER TO SEE

SCAPOF:	ANDCAB	T1,.PDCAP##(W)	;CLEAR REQUESTED BITS
	JRST	STOTC1##	;AND RETURN RESULT

SCAPON:	IOR	T1,.PDCAP##(W)	;INCLUDE BITS ALREADY OWNED
SCAPWD:	SETCM	T2,.PDCAP##(W)	;GET BITS HE CAN'T SET
	TDNE	T1,T2		;NOT SETTING ANY NEW BITS?
	PUSHJ	P,PRVJ		;OR IS PRIVILEGED USER?
	  SKIPA			;YES, OK
	JRST	ECOD0##		;NO, LOSES
	MOVEM	T1,.PDCAP##(W)	;SET NEW CAPABILITY WORD
	JRST	STOTC1##	;AND GIVE TO USER
;HERE FOR COMMANDS TO ENABLE OR DISABLE PRIVILEGES.
;ONLY THE WHOLE WORD CAN BE MODIFIED NOW.

DISABL::SETZM	JBTPRV##(J)	;CLEAR WORD
	POPJ	P,		;AND RETURN.

ENABLE::MOVE	T1,.PDCAP##(W)	;GET CAPABILITIES
	IORM	T1,JBTPRV##(J)	;ADD TO PRIVILEGE WORD
	POPJ	P,		;DONE
	SUBTTL	SET COMMAND AND UUO -- CDR

;ENTER HERE ON SET CDR UUO
SETSPI:	HRLOS	T2		;GET NAME, -1
	AOS	(P)		;AND SKIP COMMAND ENTRY AND FORCE SUCCESS RETURN
	JRST	SETCD2
;SET CDR COMMAND
SETCDR::PUSHJ	P,CTEXT1	;GET FILE NAME
	JUMPE	T2,NOTENF	;NONE SPECIFIED
	TRNE	T2,-1		;MORE THAN 3 CHARACTERS?
	JRST	COMERA		;YES. NO GOOD.
SETCD2:	HLLM	T2,JBTSPL##(J)	;SAVE NAME
	POPJ	P,		;AND RETURN



;HERE TO SET SPOOL BITS BY UUO
SETSPB:	SETCM	T3,T2		;-BITS HE WANTS ON
	ANDI	T3,.SPALL
	TDNN	T3,JBTSPL##(J)	;CLEARING SOME BITS FROM JBTSPL?
	JRST	SETSPC		;NO - OK
	MOVSI	T1,PVNSPL	;PRIV?
	TSNN	T1,STATES##	;OR SCHED BIT?
	PUSHJ	P,PRVBIT	;GO SEE
;NOTE THIS CODE DEPENDS ON PVNSPL=ST.NSP
IFN PVNSPL-ST.NSP,<PRINTX ST.NSP DOESN'T=PVNSPL>
	  JRST SETSPC		;YES. GO DO IT.
	JRST	ECOD0##		;NO. FAILURE RETURN
SETSPC:	DPB	T2,[POINT 5,JBTSPL##(J),35]	;YES, DO IT
	JRST	CPOPJ1##	;SUCCESS RETURN
DSKSIL::PUSHJ	P,SETLGL	;LEGAL?
	  JRST	COMERA		;NO
	PUSHJ	P,CTEXT1	;YES, GET DRIVE NAME
	MOVE	T1,T2		;INTO T1
	CAMN	T2,[SIXBIT 'PDP11']	;DOES HE WANT TO STOP PDP-11 MESSAGE?
	PJRST	D76SIL##	;YES--GO SHUT HIM UP
IFN FTKS10,<
	CAMN	T2,[SIXBIT 'MEMORY'] ;DOES HE WANT TO STOP MEMORY ERROR MESSAGES?
	PJRST	MEMSIL##	;YES--GO SHUT HIM UP
>; END IFN FTKS10

	PUSHJ	P,TPMSIL##	;SEE IF A TAPE KONTROLLER
	  PJRST	CPOPJ1##	;YES - EXIT
	PUSHJ	P,DSKQUI##	;STOP MESSAGES FOR THIS DRIVE
	  JRST	COMERA		; NO SUCH UNIT, OR WRONG STATUS
	PJRST	CPOPJ1##	;OK
	SUBTTL	SET COMMAND AND UUO -- DISK STUFF

;SET DSKPRI N
DSKPRI::TLZA	P4,-1		;CLEAR LH(P4)
DSKPR2:	TLO	P4,-1		;MINUS, SET LH(P4)=-1
	PUSHJ	P,SKIPS		;GET FIRST CHAR
	  JRST	NOTENF
	CAIN	T3,"-"		;-?
	JUMPE	T2,DSKPR2	;YES, SET LH(P4), TRY AGAIN
	PUSHJ	P,DECIN1	;NO, GET THE NUMBER
	  JRST	NOTENF
	  JRST	COMERA
	SKIPGE	P4		;- SEEN?
	MOVNS	T2		;YES
	PUSHJ	P,PRICOM##	;CALL FILSER TO CHECK PRIUS
	  SKIPA
	POPJ	P,

PRIERR::JSP	T1,ERRMES
	ASCIZ	/No privileges to set priority that high
/
;SET DSKFUL PAUSE (ERROR)
FULSTP::PUSHJ	P,CTEXT
	MOVE	T1,[-2,,STPNST]	;LOOK AT ARGUMENT
	PUSHJ	P,FNDNAM
	  PJRST	COMERA
STPSET:	MOVEI	T2,JS.SFL
	XCT	STPXCT(T1)	;TURN THE PAUSE-BIT ON OR OFF
	PJRST	CPOPJ1##
STPNST:	SIXBIT	/PAUSE/
	SIXBIT	/ERROR/
STPXCT:	IORM	T2,JBTSTS##(J)
	ANDCAM	T2,JBTSTS##(J)
;SET DSKFUL UUO (0=PAUSE, 1=ERROR, OTHER=READ)
DSKFUL:	CAILE	T2,1		;SETTING?
	JRST	DSKFU1		;NO
	MOVE	T1,T2		;YES, T1=FUNCTION
	JRST	STPSET		;GO SET OR CLEAR THE BIT
DSKFU1:	MOVEI	T2,JS.SFL	;READING THE BIT
	TDNE	T2,JBTSTS##(J)	;IS HE SET TO PAUSE?
	TDZA	T1,T1		;NO - 0
	MOVEI	T1,1		;YES - 1
	PJRST	STOTC1##	;STOTAC, THEN CPOPJ1
;UUO TO SET PROGRAM TO RUN
SETPGM:	PUSHJ	P,PRVJ		;PRIV'D JOB?
	  JRST	SETPG1		;YES, ALLOW IT
	MOVE	T3,JBTLIM##(J)
	TLNN	T3,(JB.LBT)	; IN A BATCH JOB?
	TLNN	T3,(JB.LSY)	;FROM SYS: ?
	JRST	ECOD0##		;NO, ERROR
SETPG1:	HRR	M,T2		;COPY ADDRESS
	PUSH	P,J
	PUSHJ	P,GETWDU##	;GET THE WORD
	MOVE	J,(P)
	MOVEI	T2,JS.RPC	;CLEAR BIT
	ANDCAM	T2,JBTST2##(J)	; ..
	SKIPGE	T1		;WANT IT SET?
	IORM	T2,JBTST2##(J)	;YES
	PUSHJ	P,GETWD1##	;GET NAME
	POP	P,J
	PUSHJ	P,FNDPDS##
	MOVEM	T1,.PDPGM##(W)
	JRST	CPOPJ1##
	SUBTTL	SET COMMAND AND UUO -- ROUTINE TO READ DATE

;GTDATE-ACCEPTS DATE IN FORM 21-JAN-72 OR
;	JAN-21-72 OR 5-JAN OR JAN-5 GIVING
;	CREATION YEAR AS DEFAULT
;	STORES YEAR (E.G. 1972), MONTH (1-12), DAY (1-31) IN 3 WORD
;	VALVE BLOCK POINTED TO BY T1.
;
;CALL	T1:=ADDRESS
;	PUSHJ	P,GTDATE
;	ERROR, RETURN
;	SUCCESS RETURN


GTDATE::PUSHJ	P,SAVE2##	;SAVE POINTER
	MOVEI	P1,2		;SET LOOP COUNT
	MOVE	P2,T1
	SETZM	1(P2)		;NO MONTH TYPED YET
DATE01:	PUSHJ	P,CTEXT		;READ NEXT ARGUMENT
	MOVE	T1,[-MLEN,,MONTHS]
	PUSHJ	P,FNDNAM	;SCAN FOR A MONTH
	  JRST GTDAY
	ADDI	T1,1		;FORM MONTH INDEX
	MOVEM	T1,1(P2)	;STORE MONTH
	SOJG	P1,DATE01	;LOOP IF DAY NEXT
	JRST	GTYEAR

GTDAY:	JUMPN	T1,CPOPJ##	;ERROR, AMBIGOUS MONTH
	SETZM	T3		;CLEAR FOR SUM
DATE02:	SETZ	T1,
	LSHC	T1,6		;GET NEXT DIGIT
	JUMPE	T1,DATE03	;DONE, IT 0
	TRC	T1,20		;FORM OCTAL REPRESENTATION
	CAILE	T1,^D9
	POPJ	P,		;NOT A DIGIT
	IMULI	T3,^D10
	ADDI	T3,(T1)		;FORM SUM
	JRST	DATE02
DATE03:	SKIPN	1(P2)		;IF NO MONTH WAS TYPED,
	MOVEM	T3,1(P2)	; STORE IT AS MONTH ALSO SO OLD FORMAT WILL WIN
	MOVEM	T3,2(P2)	;STORE DAY
	SOJG	P1,DATE01	;LOOP IF MONTH NEEDED
GTYEAR:	PUSHJ	P,DECIN		;GET YEAR (IF TYPED)
	  SKIPA	T2,MONYER	;CREATION YEAR IF MONITOR
	  POPJ	P,		;BAD TERMINATOR
	CAIGE	T2,^D100	;IF JUST 2 CHAR'S TYPED
	ADDI	T2,^D1900	;  ADD 1900
	MOVEM	T2,(P2)		;STORE YEAR
	JRST	CPOPJ1##	;SUCCESS
DEFINE	.MONTH	(A),
	<IRP A
	<SIXBIT/A/>>

MONTHS:	.MONTH<JANUAR,FEBRUA,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEM,OCTOBE,NOVEMB,DECEMB>

MLEN==.-MONTHS
MONYER:	M.YEAR##		;YEAR OF MONITOR CREATION
	SUBTTL	SET COMMAND AND UUO -- ROUTINES TO PRINT WATCH INFO

;SUBROUTINE TO PRINT TIME OF DAY USER STARTS TO WAIT FOR RESPONSE
; IF HE HAS ENABLED IT WITH "WATCH DAY"
;CALL:	MOVE J,JOB NO.
;	PUSHJ P,WCHBEG
;	ALWAYS RETURN HERE

;THIS SUBROUTINE IS ALWAYS CALLED FROM THE COMMAND DECODER
;WHEN USER IS ABOUT TO WAIT FOR A RESPONSE


WCHBEG:	MOVE	T2,JBTWCH##(J)
	MOVE	T1,TIME##	;TIME OF DAY IN JIFFIES
	TLNE	T2,JW.WWT
	DPB	T1,JBYWCH##	;STORE FOR JOB
	TLNN	T2,JW.WDY	;DOES USER WANT TO SEE THIS?
	POPJ	P,		;NO.
	PUSHJ	P,PRLBK		;YES, PRINT LEFT BRACKET
	MOVE	T1,TIME##	;TIME OF DAY IN JIFFIES
	PUSHJ	P,PRTIM		;PRINT HH:MM:SS(NO CRLF)
				;FALL INTO PRRBKC
;SUBROUTINE TO PRINT RIGHT BRACKET,CRLF

PRRBKC::PJSP	T1,CONMES
	ASCIZ	/]
/
;SUBROUTINE TO PRINT LEFT BRACKET


PRLBK::	PJSP	T1,CONMES
	ASCIZ	/[/

;SUBROUTINE TO PRINT RIGHT BRACKET


PRRBK::	PJSP	T1,CONMES	;PRINT AND RETURN
	ASCIZ	/]/
;SUBROUTINE TO PRINT SYSTEM RESPONSE STATISTICS EACH TIME
;USER FINISHES WAITING FOR SYSTEM
;PRINT INCREMENTAL RUN TIME, WAIT TIME, # DISK BLKS READ, #DISK BLKS WRITTEN
;CALL:	MOVE J,JOB NUMBER
;	PUSHJ P,WCHEND
;	ALWAYS RETURN HERE


WCHEND::MOVSI	T1,JW.WRN!JW.WWT!JW.WDR!JW.WDW	;USER WANT ANY RESPONSE DATA?
	TDNN	T1,JBTWCH##(J)	; ..
	POPJ	P,		;NO.
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,PRLBK		;YES, PRINT LEFT BRACKET
	PUSHJ	P,FNDPDS##	;FIND PDB ADDRESS. HALT IF NONE
	MOVSI	P1,-WCHLEN	;LOOP THRU ALL RESPONSE DATA ITEMS
WCHLOP:	HLLZ	T1,WCHTAB(P1)	;GET BIT ASSOCIATED WITH THIS FIELD
	HRRZ	T2,WCHTAB(P1)	;GET DISPATCH ADDRESS
	TDZE	T1,JBTWCH##(J)	;DOES USER WANT TO WATCH IT?
	PUSHJ	P,(T2)		;YES, PRINT IT OUT
	AOBJP	P1,WCH1		;FINISHED ALL FIELDS?
	PUSHJ	P,PRSPC		;NO, PRINT A SPACE
WCH1:	JUMPL	P1,WCHLOP	;LOOP IF MORE BITS TO CONSIDER
	PJRST	PRRBKC		;APPEND RIGHT BRACKET, CRLF, AND RETURN

;TABLE OF ROUTINES TO PRINT RESPONSE DATA

WCHTAB:	XWD	JW.WRN,PRTWRN	;PRINT RUN TIME
	XWD	JW.WWT,PRTWWT	;PRINT WAIT TIME

	XWD	JW.WDR,PRTWDR##	;PRINT # DISK BLOCKS READ
	XWD	JW.WDW,PRTWDW##	;PRINT # DISK BLOCKS WRITTEN

				;ADD NEW DATA HERE
WCHLEN==.-WCHTAB
;ROUTINE TO PRINT INCREMENTAL RUNTIME(NO CRLF)
;CALL:	MOVEI T1,0
;	PUSHJ P,PRTWRN


PRTWRN:	EXCH	T1,.PDRTM##(W)	;CLEAR INCREMENTAL RUN TIME
	PJRST	PRTIM		;PRINT AS HH:MM:SS, MM::SS OR SS.HH (NO CRLF)

;ROUTINE TO PRINT WAIT TIME (NO CRLF)
;CALL:	PUSHJ P,PRTWWT


PRTWWT:	LDB	T1,JBYWCH##	;TIME OF DAY USER STARTED TO WAIT
	SUB	T1,TIME##	;-CURRENT TIME OF DAY = -WAIT TIME
	SKIPLE	T1		;IS IT REALLY MINUS?
	SUB	T1,MIDNIT##	;NO. MUST HAVE BEEN WAITING ACROSS MIDNIGHT
				; SO SUBTRACT A DAY TO GET IT NEGATIVE
	MOVNS	T1		;NOW MAKE IT PLUS WAIT TIME
	PJRST	PRTIM		;TYPE OUT TIME (NO CRLF)


SETWTU:	HLRZ	T1,JBTWCH##(J)	;GET CLOCK OVERFLOW
	ANDI	T1,77		;(ENOUGH FOR 24.*60.*60.*60.)
	TRZ	T2,77		;CLEAR REQUEST JUNK
	IOR	T2,T1		;INCLUDE OVERFLOW
	HRLM	T2,JBTWCH##(J)	;SAVE WATCH BITS
	JRST	CPOPJ1##	;AND RETURN
	SUBTTL	CONTINUE, CCONT AND JCONT

; "CONTC" - CONTINUE EXECUTION(TTY REMAINS IN COMMAND MODE)

CONTC::				;SAME AS CONT

; "CONT" - CONTINUE EXECUTION FROM WHERE LEFT OFF

CONT::	JUMPE	J,STARTE	;COMPLAIN IF NO JOB
	LDB	T1,JBYDEB##	;DEFERRED ECHO BITS
	SE1XCT	<DPB T1,LDPDEB##> ;RESTORE FOR CONTINUE
	TLNN	P4,JERR		;IS JOB ERROR BIT SET?
	JRST	CONT1		;COMMAND DECODER WILL DO THE REST
	JSP	T1,ERRMES	;YES, PRINT CANT CONTINUE

	ASCIZ	/Can't continue
/
CONT1:
IFN FTMP,<
	MOVE	T1,USRPC##	;PC
	TLNE	T1,(XC.USR)	;USER MODE?
	PJRST	DPXST##		;YES, MAKE RUNNABLE ON ALL CPUS
>
	POPJ	P,		;*** NO

;JOB CONTINUE COMMAND
;FORCES A CONTINUE COMMAND FOR JOB Y

JCONT::	PUSHJ	P,GETJOB	;GET JOB TO CONTINUE
	  JRST	NOTENF		;MUST HAVE ARGUMENT
	TRNN	T3,JDCON	;JOB WAITING FOR CONT?
	JRST	JCERR2		;NO
	CAMN	T2,J		;SEE IF FOR US
	PJRST	FCONT		;YES, GO DO IT
	MOVE	T1,T2		;GET JOB # IN CORRECT AC FOR FCONRQ
	PUSHJ	P,FCONRQ	;GO REQUEST CONT BE FORCED FOR JOB
	POPJ	P,		;RETURN - SUCCESSFUL
	PJRST	SNDBSI		;NOT ENTERED - GO TYPE "BUSY"

;CALLED TO SET UP FORCED COMMAND FOR JOB CONTINUE
;JOB NUMBER IN T1
;SKIP RETURN IF COMMAND WAS NOT ENTERED BECAUSE ALREADY A
;FORCED COMMAND PENDING


FCONRQ::MOVEI	T2,TTFCXJ##	;INDEX FOR FORCED CONTINUE
;SUBROUTINE TO FORCE COMMAND
;ARGS	T1=JOB NUMBER
;	T2=INDEX OF FORCED COMMAND


COMFRC::SE1ENT			;ENTER SECTION 1
	PUSH	P,U		;SAVE THIS AC
	PUSH	P,J		;SAVE THIS JOB NUMBER
	MOVE	J,T1		;GET HIS JOB NUMBER
	PUSHJ	P,TTYSRC##	;SET UP LINE (LDB)
	  JRST	JCONDM		;SEE IF ATTACHED
	JRST	COMFR2
COMFRL::SE1ENT			;ENTER SECTION 1
	PUSH	P,U		;SAVE ACS
	PUSH	P,J
COMFR2:	JUMPE	U,JCONDM	;CAN'T FORCE TO DETACHED LINE.
	MOVSI	T1,LDBCMF##	;ANY FORCED COMMAND
	SCNOFF
	TDNE	T1,LDBCOM##(U)	;FOR THIS JOB ALREADY
	JRST	JCONDL		;YES
	DPB	T2,LDPCMX##	;STORE COMMAND INDEX
	MOVSI	T1,LDBCMR##+LDBCMF## ;BITS FOR FORCE
	PUSHJ	P,COMSTF##	;WAKE COMCON (RETURNS WITH SCAN ON)
	POP	P,J		;RESTORE JOB
	PJRST	LPOPJ##		;RETURN

;HERE IF JOB ALREADY HAS FORCED COMMAND PENDING, DELAY THIS COMMAND

JCONDL:	SCNON
JCONDM:	POP	P,J		;RESTORE JOB NUMER
	JRST	LPOPJ1##	;CAN'T ENTER - SKIP RETURN
;HERE IF JOB NOT WAITING FOR CONTINUE

JCERR2:	JSP	T1,ERRMES
	ASCIZ	/Job not waiting/


;FORCED CONTINUE COMMAND
;NO TTY OUTPUT UNLESS COMMAND IS REALLY EXECUTED - IT WILL NOT BE
; IF USER HAS TYPED A COMMAND IN THE MEAN TIME.

FCONT::	MOVE	P4,JBTSTS##(J)	;GET JOB STATUS
	TLNN	P4,JERR		;CAN WE CONTINUE
	TRNN	P4,JDCON	;IS JOB WAITING
	POPJ	P,
	TLO	M,TTYRNW	;SET FOR RESCHEDULE
	TLZ	M,NOCRLF!NOMESS ;RESET NOMESS
	PUSHJ	P,INLMES	;TELL USER HE'S CONT
	ASCIZ	/Continued by OPR/
	POPJ	P,
	SUBTTL	CORE COMMAND

; "CORE  #" - ASSIGNS #*1024 WORDS OF CORE TO JOB
; "CORE" WITH NO ARG. WILL PRINT NO OF FREE BLOCKS LEFT
;	WITHOUT AFFECTING CURRENT ASSIGNMENT OF CORE
;	JOB NOT IN MIDDLE OF SWAPPING
;	EITHER ON DISK OR CORE OR NEITHER PLACE



CORE::	PUSHJ	P,CORARG	;GET HIGHEST RELATIVE ADDRESS USER SPECIFIED
	JRST	COR5		;NO ARG. SPECIFIED, JUST TYPE FREE BLOCK LEFT
	TLNE	T1,-1		;NO ARG GREATER THAN A SECTION ALLOWED
	JRST	COR4
	JUMPL	P4,[MOVEI T1,RUNERR	;RUNNING?
		JRST ERRMES]	;YES, LOSE
	JUMPE	T1,COR1		;RELEASE DEVICES IF USER ASKING FOR 0 CORE
	TRNE	P4,JS.XO!JS.RUU	;SEE IF EXECUTE ONLY
	PJRST	ILLXO		;YES -- GO GIVE ERROR
	HRRZ	T2,JBTSGN##(J)	;CLEAR JUNK IN LH
	JUMPE	T2,COR1		;THERE REALLY ISN'T A HIGH SEG
COR3:	SKIPG	T3,.HBSGN(T2)	;IS THIS A REAL SEGMENT?
	TLOA	T3,-1		;NO, FLAG SUCH
	HLLZ	T3,JBTADR##(T3)	;GET SIZE OF SEGMENT
	HLRES	T3		;IN THE CORRECT HALF
	SUBI	T1,1(T3)	;ROUND UP AND SUBTRACT OUT
	JUMPL	T1,COR3D	;IF WENT NEGATIVE, ARG IS TOO SMALL
	HRRZ	T2,.HBLNK(T2)	;NEXT SEGMENT
	JUMPN	T2,COR3		;CHECK IT OUT
COR1:	SKIPE	T1
	SKIPN	JBTADR##(J)
	PUSHJ	P,COR15		;CALL UNLOCK, GETMIN, ET ALL
	JUMPE	T1,COR0
	SKIPE	JBTADR##(J)	;IF DIDN'T GET CORE IN CORE.
	JRST	COR2
	LDB	T2,IMGOUT##	;DID WE GET CORE ON DSK?
	JUMPE	T2,COR4		;ERROR IF NONE
	JRST	DLYCM
COR2:
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET THE MM
	  JRST	DLYCM		;NOT AVAILABLE, DELAY
>
	SKIPE	PAGIPC##	;PAGING IN PROGRESS?
IFN FTMP,<
	JRST	[PUSHJ P,GIVMM##
		 JRST  DLYCM  ]	;YES, DELAY
>
IFE FTMP,<
	JRST	DLYCM
>
	PUSHJ	P,CORE0##	;GET CORE
IFN FTMP,<
	  JRST	[PUSHJ P,GIVMM## ;NONE AVAILABLE
		 JRST COR4]
	PUSHJ	P,GIVMM##	;GIVE UP THE MM.
>
IFE FTMP,<
	  JRST	COR4		;CORE NOT AVAILABLE, GO PRINT MESSAGE
>
	LDB	T1,PJBSTS##
	CAIE	T1,NULQ##	;IN THE NO CORE Q?
	POPJ	P,		;NO
	MOVEI	T1,STOPQ##	;YES, OK RETURN, CORE ASSIGNED ON DISK OR MEMORY
	DPB	T1,PJBSTS##	;PUT JOB IN THE STOP Q SINCE IT NOW HAS CORE
	PJRST	REQUE##
COR3D:	PUSHJ	P,INLMES	;TOO SMALL AN ARG.
ASCIZ	/?Try larger arg.
/

COR4:	PUSHJ	P,TTYFND##	;RE-FIND TTY LINE
	JUMPE	U,CPOPJ##	;GIVE UP IF GOT DETACHED
	PUSHJ	P,PRQM		;TYPE ? FOR BATCH
	PUSHJ	P,COR11		;PRINT USAGE/LIMIT SUMMARY
	TLO	M,ERRFLG	;SET ERROR FLAG
	POPJ	P,

;HERE TO GIVE CURRENT CORE SIZE FOR VM USER
COR5:	PUSHJ	P,FNDPDS##	;FIND PDB FOR JOB
	SKIPN	JBTADR##(J)	;DON'T BOTHER IF NO CORE
	JRST	COR11		;JUST SHOW LIMITS
	JSP	T2,SAVCTX##	;WE COULD HAVE A LOT OF OUTPUT
	PUSHJ	P,SAVE4##	;SAVE WORKING ACS
	PUSHJ	P,INLMES	;PRINT HEADER
	ASCIZ	/Page number	Page status	Origin

/
	MOVEI	P1,1		;START WITH PAGE 1, PAGE 0 ALWAYS EXISTS
	PUSH	P,U		;GTPACC CLOBBERS U
	MOVEI	T1,0		;PAGE 0
	PUSHJ	P,GTPACC##	;GET PAGE 0 ACCESSABILITY
	POP	P,U		;RESTORE LDB
	TDZ	T1,[<(PA.CPO+PA.OUT+PA.AA+PA.VSP)>,,-1] ;CLEAR DON'T CARE
	MOVE	P2,T1		;FOR THE LOOP
	MOVEI	P3,0		;END OF REGION
	MOVEI	P4,1		;COUNT OF PAGES
COR6:	MOVE	T1,P1		;CURRENT PAGE NUMBER
	LSH	T1,P2SLSH	;JUST SECTION NUMBER
	SKIPN	T2,.UPMP+SECTAB(T1) ;SECTION EXIST?
	JRST	COR9		;NEXT SECTION
	LDB	T1,[POINT 3,T2,2] ;GET POINTER TYPE
	CAIE	T1,PM.ICD	;INDIRECT?
	JRST	COR8		;NO
	MOVEI	T1,[ASCIZ /Section /]
	PUSHJ	P,CONMES	;PRINT THAT
	MOVE	T1,P1		;PAGE NUMBER
	LSH	T1,P2SLSH	;SECTION NUMBER
	PUSH	P,T2		;PRTDI8 CLOBBERS T2
	PUSHJ	P,PRTDI8	;PRINT SECTION NUMBER
	MOVEI	T1,[ASCIZ / @section /]
	PUSHJ	P,CONMES	;INDIRECT
	POP	P,T2		;RESTORE POINTER
	HLRZ	T1,T2		;RIGHT HALF
	ANDI	T1,MXSECN	;ISOLATE SECTION NUMBER
	PUSHJ	P,PRTDI8	;PRINT INDIRECT SECTION NUMBER
	PUSHJ	P,CRLF		;CRLF
COR7:	TRO	P1,PG.BDY	;NEXT SECTION
	JRST	COR10		;CONTINUE
COR8:	MOVE	T1,P1		;PAGE NUMBER
	PUSH	P,U		;GETPAC CLOBBERS U
	PUSHJ	P,GTPACC##	;GET PAGE ACCESSIBILITY
	POP	P,U		;RESTORE LDB
	TDZ	T1,[<(PA.OUT+PA.CPO+PA.AA+PA.VSP)>,,-1]	;DON'T CARE ABOUT IN, OUT, OR TARGET
	TLNN	T1,(PA.GSP)	;A SPY PAGE?
	SKIPGE	T1		;DOES PAGE EXIST?
	CAIA			;DON'T COUNT NON-EXISTANT OR SPY PAGES IN TOTAL
	AOS	P4		;UPDATE TOTAL PAGE COUNT
	CAMN	T1,P2		;SAME AS PREVIOUS PAGE?
	JRST	COR10		;YES, LOOK AT NEXT PAGE
COR9:	PUSH	P,T1		;SAVE NEW ACCESSIBILITY BITS
	SKIPL	P2		;PREVIOUS PAGES NON-EXISTANT?
	PUSHJ	P,PRTACC	;NO, REPORT THEM
	POP	P,P2		;NEW ACCESSIBILITY BITS
	MOVE	P3,P1		;START OF RANGE
	MOVE	T1,P1		;PAGE NUMBER
	LSH	T1,P2SLSH	;CURRENT SECTION NUMBER
	SKIPE	.UPMP+SECTAB(T1);DOES IT EXIST?
	JRST	COR10		;YES, LOOK AT IT
	TLO	P2,400000	;NO, PREVIOUS PAGE NON-EXISTANT
	JRST	COR7		;NEXT SECTION
COR10:	CAIGE	P1,HLGPGS	;LOOKED AT ALL SECTIONS?
	AOJA	P1,COR6		;NO, LOOP ON
	SKIPL	P2		;PREVIOUS PAGES NON-EXISTANT?
	PUSHJ	P,[AOJA P1,PRTACC] ;NO, REPORT THEM
	MOVEI	T1,[ASCIZ /
Total of /]
	PUSHJ	P,CONMES	;SUMMARY
	MOVE	T1,P4		;TOTAL NUMBER OF "REAL" PAGES SEEN
	PUSHJ	P,RADX10	;OUTPUT THAT
	MOVEI	T1,[ASCIZ / page/]
	PUSHJ	P,CONMES	;FINISH UP
	CAIN	P4,1		;SINGULAR?
	SKIPA	T1,[[ASCIZ /

/]]
	MOVEI	T1,[ASCIZ /s
/]				;NOTE THAT THIS IS <LF><CRLF> SO FITS IN 1 WORD
	PUSHJ	P,CONMES	;OUTPUT

;CONTINUED ON NEXT PAGE
COR11:	HLRZ	T1,.PDMVL##(W)	;GET MVPL
	JUMPE	T1,COR13	;SKIP FIRST LINE IF ZERO
	MOVEI	T1,[ASCIZ "Virt. mem. assigned "]
	PUSHJ	P,CONMES	;PRINT TITLE
	PUSHJ	P,VMSIZE##	;GET SIZE OF JOB
	JUMPE	T2,[PUSHJ P,PRCORE	;IF JUST A LOWSEG
		    JRST  COR12]; PRINT ONLY 1 NUMBER
	PUSH	P,T2		;SAVE SIZE OF HISEG
	PUSHJ	P,RADX10	;PRINT SIZE OF LOWSEG
	PUSHJ	P,PRTPLS
	POP	P,T1		;SIZE OF HISEG
	PUSHJ	P,PRCORE	;PRINT THAT
COR12:	HLRZ	T4,.PDCVL##(W)	;GET CVPL
	PUSHJ	P,PRCXPL	;PRINT THAT
	HLRZ	T4,.PDMVL##(W)	;GET MVPL
	SKIPN	T4
	MOVEI	T4,1000
	PUSHJ	P,PRMXPL	;PRINT THAT
	PUSHJ	P,INLMES	;ADD ) CRLF
	ASCIZ	/)
/
COR13:	PUSHJ	P,INLMES
	ASCIZ	/Phys. mem. assigned /
	PUSHJ	P,PRTSEG	;PRINT LOWSEG SIZE
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;START OF CHAIN
COR13A:	SKIPN	T1,.HBLNK(T1)	;NEXT SEGMENT DATA BLOCK
	JRST	COR13B		;NO MORE
	SKIPG	T2,.HBSGN(T1)	;SPY SEG?
	JRST	COR13A
	PUSHJ	P,PRTHGH##	;PRINT SIZE OF HISEG
COR13B:	PUSHJ	P,PRPORK	;PRINT P OR K
	HRRZ	T4,.PDCVL##(W)	;GET CPPL
	TRZN	T4,400000
	JRST	[PUSHJ P,PRCPGL
		 JRST  .+2]
	PUSHJ	P,PRCXPL	;PRINT IT
	MOVEI	T4,0
	MOVSI	P1,PHONLY
	PUSH	P,.PDCVL##(W)
	MOVEI	T1,400000
	ANDCAM	T1,.PDCVL##(W)
	PUSHJ	P,PRMXPL	;PRINT IT
	POP	P,.PDCVL##(W)
;CONTINUED ON NEXT PAGE
	PUSHJ	P,INLMES	;ADD NOISE WORDS
	ASCIZ	/)
Swap space left: /
	MOVE	T1,VIRTAL##	;GET THAT NUMBER
	PUSHJ	P,PRCORE	;PRINT IN RADIX 10
	PJRST	CRLF		;ADD IN A CRLF AND RETURN

COR15:	PUSH	P,T1		;SAVE T1
	PUSHJ	P,UNLOCK##	;SO CALLING GETMIN DOES SOMETHING
	  JFCL			;OOPS
	PUSHJ	P,CLRLPG##	;CLEAR LOCKED PAGES
	PUSHJ	P,GETMIN
	PJRST	TPOPJ##		;AND RETURN


;ROUTINE TO PRINT CURRENT AND MAX LIMITS

PRCPGL:	MOVEI	T1,[ASCIZ " (Guideline: "]
	JRST	PRXXPL
PRCXPL:	SKIPA	T1,[[ASCIZ " (Current limit: "]]
PRMXPL:	MOVEI	T1,[ASCIZ " Max limit: "]
PRXXPL:	PUSH	P,T4
	PUSHJ	P,CONMES	;PRINT THE TITLE
	PUSHJ	P,CORBND##	;GET MAX CORE
	LSH	T1,W2PLSH	;IN PAGES
	SKIPN	(P)		;ANYTHING GIVEN?
	MOVEM	T1,(P)		;CHOOSE GOOD MAX
	POP	P,T1		;RESTORE NUMBER
PRCORE:	PUSHJ	P,RADX10	;PRINT IN DECIMAL
	PJRST	PRPORK		;GIVE UNITS
;ROUTINE TO PRINT PAGE ACCESSIBILITY. CALL WITH P1=HIGHEST PAGE NUMBER IN REGION,
; P2=BITS RETURNED FROM GETPAC (ALTERED!), P3=FIRST PAGE NUMBER IN REGION
PRTACC:	MOVE	T1,P3		;FIRST PAGE IN REGION
	PUSHJ	P,PRTDI8	;PRINT THAT
	CAIN	P1,1(P3)	;EXACTLY 1 PAGE?
	JRST	PRTAC1		;YES, SKIP NEXT
	PUSHJ	P,INLMES	;PRINT A MINUS SIGN
	ASCIZ	/-/
	MOVEI	T1,-1(P1)	;HIGHEST PAGE IN REGION
	PUSHJ	P,PRTDI8	;PRINT THAT
PRTAC1:	MOVEI	T1,[ASCIZ /	/]
	PUSHJ	P,CONMES	;LINE THINGS UP
	MOVEI	T2,-1(P1)	;FIX OFF BY ONE ABOVE
	CAIE	T2,(P3)		;ALWAYS TAB IF NO RANGE
	TRNN	T2,777000	;SEVEN OR MORE CHARACTERS ALREADY BEEN OUTPUT?
	PUSHJ	P,CONMES	;NO, NEED ANOTHER TAB
	MOVEI	T2,0		;COUNT CHARACTERS
	MOVEI	T1,[ASCIZ /EX /];IF ITS NOT A SPY PAGE, ITS EXECUTABLE
	TLNN	P2,(PA.GSP)	;A SPY PAGE?
	PUSHJ	P,[AOJA T2,CONMES] ;NO, OUTPUT
	MOVEI	T1,[ASCIZ /RD /];ASSUME IT CAN BE READ
	TLNE	P2,(PA.RED)	;CAN IT BE
	PUSHJ	P,[AOJA T2,CONMES] ;YES, OUTPUT THAT
	MOVEI	T1,[ASCIZ /WR /];ASSUME IT CAN BE WRITTEN
	TLNE	P2,(PA.WRT)	;CAN IT BE
	PUSHJ	P,[AOJA T2,CONMES] ;YES, OUTPUT THAT
	MOVEI	T1,[ASCIZ /AZ /];ASSUME ABZ
	TLNE	P2,(PA.ZER)	;IS IT?
	PUSHJ	P,[AOJA T2,CONMES] ;YES, OUTPUT THAT
	MOVEI	T1,[ASCIZ /SH /];ASSUME ITS SHARABLE
	TLNN	P2,(PA.GSP)	;WOULD YOU BELIEVE THAT SPY PAGES ARE SHARABLE?
	TLNN	P2,(PA.GSH)	;IS IT?
	CAIA			;NO
	PUSHJ	P,[AOJA T2,CONMES] ;YES, OUTPUT THAT
	MOVEI	T1,[ASCIZ /LK /] ;ASSUME LOCKED
	TLNE	P2,(PA.LCK)	;IS IT?
	PUSHJ	P,[AOJA T2,CONMES] ;YES, OUTPUT THAT
	MOVEI	T1,[ASCIZ /	/]
	TLNN	P2,(PA.GSH)	;NEED A TAB IF SHARABLE
	CAIG	T2,2		;ALSO IF LESS THAT 2 ATTRIBUTES
	PUSHJ	P,CONMES	;LINE THINGS UP
	TLNN	P2,(PA.GSP)	;SPY PAGES?
PRTA1A:	SKIPA	T1,[[ASCIZ /	Private/]] ;NO, ASSUME IT'S PRIVATE
	MOVEI	T1,[ASCIZ /	Spy/] ;SPY
	TLZE	P2,(PA.GSH)	;PRIVATE
	TLNE	P2,(PA.GSP)	;OR SPY?
	JRST	PRTAC4		;YES, WE HAVE AN ATTRIBUTE
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,SAVJW##	;AND J (W ALONG FOR THE RIDE)
	MOVE	P1,P3		;GET PAGE # OF FIRST PAGE
	LSH	P1,P2SLSH	;GET SECTION
	SETZ	T1,		;FIRST SEG THAT SECTION
PRTA1B:	PUSHJ	P,NXSSP1##	;GET NEXT SEGMENT IN THAT SECTION
	  JRST	PRTA1A		;HUH (BITS ZEROED ABOVE)
	SKIPG	J,.HBSGN(T1)	;GET SEGMENT NUMBER
	JRST	PRTA1B		;SPY
	HRRZS	J		;CLEAR JUNK
	LDB	T2,JBYHSO##	;GET ORIGIN OF THAT HIGH SEG
	XOR	T2,P3		;SEE IF IT'S THIS PAGE
	TRNE	T2,HLGPNO	;?
	JRST	PRTA1B		;NO, CHECK NEXT SEGMENT
	MOVE	T2,JBTDEV##(J)	;DEVICE NAME
	PUSHJ	P,PRNAME	;PRINT THAT
	MOVEI	T1,[ASCIZ /:/]	;DEVICE DELIMITER
	PUSHJ	P,CONMES	;PRINT THAT
	MOVE	T2,JBTNAM##(J)	;GET HIGH SEGMENT NAME
	PUSHJ	P,PRNAME	;PRINT THAT
	MOVE	J,JBTPPN##(J)	;GET PPN
	TLNE	J,-1		;PATH OR PPN?
	SKIPA	T2,J		;PPN
	MOVE	T2,(J)		;PATH, PPN IS STORE HERE
	PUSHJ	P,PRTPP1	;PRINT THE LEFT BRACKET, P,PN
	TLNE	J,-1		;IF ONLY A PPN, DONE
	JRST	PRTAC3		;GO PRINT THE RIGHT BRACKET
PRTAC2:	SKIPN	T2,1(J)		;NEXT SFD
	JRST	PRTAC3		;NO MORE, DONE
	PUSHJ	P,PRCOM		;PRINT A COMMA
	PUSHJ	P,PRNAME	;PRINT THE SFD NAME
	AOJA	J,PRTAC2	;NEXT SFD
PRTAC3:	PUSHJ	P,PRTRBK	;PRINT RIGHT BRACKET
	PJRST	CRLF		;PRINT A CRLF AND RETURN

PRTAC4:	PUSHJ	P,CONMES	;OUTPUT WHAT WE HAVE
	CAIN	P1,1(P3)	;EXACTLY ONE PAGE?
	SKIPA	T1,[[ASCIZ / page
/]]
	MOVEI	T1,[ASCIZ / pages
/]
	PJRST	CONMES
;ROUTINE TO PRINT ACCOUNT STRING
CACCT::	MOVEI	T1,.PDACS##(W)	;ADDRESS OF USER'S ACCOUNT STRING
	PUSHJ	P,CONMES	;TYPE IT
	PJRST	PCRLF		;<CRLF>
	SUBTTL	CONTROL-T PRINTOUT

;SUBROUTINE TO PRINT A 1 TO 3 LINE USE STATUS REPORT
;CALLED FROM USESTAT COMMAND IT PRINTS A 1 LINE
; STATUS REPORT OF THE FORM:
;	INCREMENTAL DAY TIME
;	INCREMENTAL RUN TIME
;	INCREMENTAL DISK READS
;	INCREMENTAL DISK WRITES
;	PROGRAM NAME
;	CORE SIZE
;	JOB STATE
;	PC
;
USECOM::TLNN	P4,JNA		;IS THIS A JOB?
	PJRST	ATT4		;NO--SAY "NOT A JOB"
	MOVEI	T1,[ASCIZ 'Day: ']
	PUSHJ	P,CONMES
	PUSHJ	P,PRTWWT	;INCREMENTAL DAYTIME
	MOVE	T1,TIME##	;RESET THE TIMER FOR
	DPB	T1,JBYWCH##	; THE NEXT TIME
	PUSHJ	P,UDCPUT##	;UPDATE RUN TIME IF NECESSARY
	MOVEI	T1,[ASCIZ ' Run: ']
	PUSHJ	P,CONMES
	MOVEI	T1,0		;CLEAR INCREMENTAL RUNTIME
	EXCH	T1,.PDRTM##(W)	; AND PICK UP OLD RUN TIME
	PUSHJ	P,PRTIM		;PRINT THAT
	MOVEI	T1,[ASCIZ ' Rd:']
	PUSHJ	P,CONMES
	PUSHJ	P,PRTWDR##	;DISK READS
	MOVEI	T1,[ASCIZ ' Wr:']
	PUSHJ	P,CONMES
	PUSHJ	P,PRTWDW##	;DISK WRITES
	PUSHJ	P,PRSPC		;ANOTHER SPACE
	MOVE	T2,JBTPRG##(J)	;PROGRAM NAME
	PUSHJ	P,PRNAME	;PRINT THE NAME
	PUSHJ	P,USEHSG	;PRINT JOB'S HIGH SEGMENTS
	PUSHJ	P,PRSPC		;ANOTHER SPACE
	PUSHJ	P,PRTSEG	;LOW SEG SIZE
	PUSHJ	P,PRTHGH##	;HIGH SEG SIZE
	PUSHJ	P,PRPORK	;PRINT P OR K
	PUSHJ	P,CTXPRT##	;PRINT CURRENT CONTEXT NUMBER
	PUSHJ	P,PRSPC		;ANOTHER SPACE
	MOVSI	T2,'^C'		;ASSUME CONTROL-C STATE
	JUMPG	P4,USECM1	;JUMP IF TRUE
	LDB	T1,PJBSTS##	;PICK UP JOB STATE
	IDIVI	T1,3		;DIVIDE BY 3 TO GET WORD NUMBER
	IMULI	T2,^D12		;MULTIPLY REMAINDER BY 12 TO GET POSITION
	MOVE	T3,STSTBL##(T1)	;PICK UP ENTRY
	ROT	T3,(T2)		;GET CORRECT THIRD
	MOVSI	T2,777700	;ONLY LOOK AT TOP 12 BITS
	AND	T2,T3		;COPY STATE
USECM1:	PUSHJ	P,PRNAME	;PRINT THAT
IFN FTLOCK,<
	MOVEI	T3,"&"		;ASSUME LOCKED
	TLNE	P4,NSWP		;SEE IF LOCKED
	PUSHJ	P,PRCHR		;YES, LOCKED
>;END IFN FTLOCK
	MOVEI	T3,"*"		;ASSUME CURRENT JOB
	PUSHJ	P,ANYCPU##	;ARE WE THE CURRENT JOB?
	  PUSHJ	P,PRCHR		;YES--PRINT *
	PUSHJ	P,PRSPC		;ANOTHER SPACE
	MOVSI	T2,'SW '	;ASSUME SWAPPED
	TLNE	P4,SWP!SHF	;IS JOB IN CORE?
	PUSHJ	P,[SKIPE JBTADR##(J)	;ANY PHYS MEM?
		   MOVSI T2,'SW*'	;YES--ADD * TO MEAN SWAPPING
		   PJRST PRNAME]	;PRINT SW OR SW*
	MOVEI	T1,[ASCIZ ' PC:']
	PUSHJ	P,CONMES
	MOVE	T2,JBTPC##(J)	;GET CURRENT PC
	PUSHJ	P,UDPCP##	;PRINT PC IN OCTAL
USECPU:
IFN FTMP,<
	SKIPE	T2,[M.CPU##-1]	;SKIP IF FTMP ON BUT SINGLE CPU MONITOR
	HRRZ	T2,JBTST3##(J)	;GET CDB OF LAST CPU WE RAN ON
	JUMPE	T2,USECP1	;SKIP THIS IF A SINGLE CPU OR NO CORE FOR JOB
	PUSHJ	P,PRSPC		;SPACE OVER
	MOVE	T2,.CPLOG##-.CPCDB##(T2) ;GET CPU NAME
	PUSHJ	P,PRNAME	;PRINT IT
USECP1:
> ;END IFN FTMP
	SKIPN	JBTADR##(J)
	JRST	USECM3
	MOVSI	T1,SWP!SHF	;BIT INDICATING SWAPPED OR BEING SWAPPED
	SKIPE	.USVRT		;VIRTUAL?
	TDNE	T1,JBTSTS##(J)	;AND IN CORE?
	JRST	USECM3		;NO, SKIP THIS
	MOVEI	T1,[ASCIZ /
Faults - IW: /]
	PUSHJ	P,CONMES	;PRINT THE TEXT
	MOVE	T1,.USVCT	;REPORT INCREMEMTAL IN WORKING SET FAULTS
	SUB	T1,.USICT
	HRRZS	T1
	PUSHJ	P,RADX10
	MOVEI	T1,[ASCIZ / NIW: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	MOVE	T1,.USVCT	;REPORT INCREMENTAL NOT IN WORKING SET FAULTS
	SUB	T1,.USICT
	HLRZS	T1
	PUSHJ	P,RADX10
	MOVE	T1,.USVCT	;UPDATE INCREMENTAL STATISTICS
	MOVEM	T1,.USICT
	MOVEI	T1,[ASCIZ / Virt core: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	LDB	T1,LOVSIZ##	;LOW SEGMENT VIRTUAL CORE
	PUSHJ	P,RADX10	;REPORT LOW SEGMENT VIRTUAL CORE
	PUSHJ	P,PRTPLS	;PRINT A PLUS SIGN
	LDB	T1,HIVSIZ##	;HIGH SEG
	PUSHJ	P,PRCORE	;REPORT HIGH SEGMENT VIRTUAL CORE
	MOVEI	T1,[ASCIZ / Page rate: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	MOVE	T1,J
	PUSHJ	P,FPDBT1##
	  TDZA	T3,T3
	HLRZ	T3,.PDVRT##(T1)	;GET PAGING RATE
	SETZB	T1,T2		;ASSUME A RATE OF ZERO
	JUMPE	T3,USECM2	;JUMP IF THE RATE IS ZERO
	MOVEI	T1,RTUPS##	;COMPUTE THE JOBS PAGING RATE
	IDIVI	T1,(T3)
	IMULI	T2,^D100
	IDIVI	T2,(T3)
USECM2:	PUSH	P,T2		;SAVE THE REMAINDER
	PUSHJ	P,RADX10	;PRINT THE RATE
	PUSHJ	P,PRPER		;AND A DOT
	POP	P,T1		;RESTORE THE REMAINDER
	MOVEI	T3,"0"		;ASSUME THE REMAINDER IS IN HUNDREDTHS
	CAIG	T1,^D9		;IS IT?
	PUSHJ	P,PRCHR		;YES, PRINT A LEADING ZERO
	PUSHJ	P,RADX10	;AND PRINT DIGITS FOLLOWING THE DECIMAL PLACE
USECM3:	HRRZ	F,JBTDDB##(J)	;GET DDB ADDRESS
	JUMPE	F,USECM5	;ALL DONE IF NO DDB
IFN FTMP,<
	DDBSRL			;LOCK DDB SEARCH
	MAP	T1,(F)		;MAP DDB ADDRESS
	PUSHJ	P,FLTCHK##	;STILL AROUND?
	  JRST	USECM4		;NO
>
	MOVE	T1,JBTSTS##(J)	;GET STATUS
	CAMLE	F,SYSSIZ##	;DDB IN THE MONITOR?
	TLNN	T1,SWP!SHF	;NO, IS THE JOB IN CORE?
	TRNA			;YES, PROCEED
	JRST	USECM4		;NO, DON'T TRY TO REPORT DEVICE INFO
	MOVE	T3,DEVMOD(F)	;GET DEVICE TYPE FOR TEST
	TRNE	T1,JS.XO	;EXECUTE ONLY?
	TLNN	T3,DVDSK!DVDTA	;AND DISK OR DECTAPE?
	SKIPA	T2,DEVIOS(F)	;NO, TYPE DDB INFO
	JRST	USECM4		;YES TO BOTH, SKIP DDB PRINTOUT
	MOVEI	T1,[ASCIZ "
Input"]
	TLNE	T3,DVTTY	;IS IT A TTY?
	TLNE	T3,DVDSK	;AND NOT NUL:?
	JRST	USECMA		;NO, GO DO NORMAL DEVICE
	TLNE	T2,TTYOUW##	;OUTPUT DIRECTION?
	MOVEI	T1,[ASCIZ "
Output"]
	JRST	USECMB		;TYPE THE MESSAGE
USECMA:	TLNE	T2,IO		;OUTPUT DIRECTION?
	MOVEI	T1,[ASCIZ "
Output"]
USECMB:	PUSHJ	P,CONMES	;PRINT THE TEXT
	MOVEI	T1,[ASCIZ " wait for "]
	PUSHJ	P,CONMES
	PUSHJ	P,PRTDDB	;PRINT FILE SPEC
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS
	TLNE	T1,DVDSK	;IS THIS A DISK?
	PUSHJ	P,DSKCTT##	;YES -- PRINT GOOD STUFF
	MOVE	T1,DEVMOD(F)	;IS THIS A
	TLNE	T1,DVMTA	; TAPE?
	PUSHJ	P,TPMCTT##	;YES--PRINT FILE & RECORD
USECM4:
IFN FTMP,<
	DDBSRU			;UNLOCK DDB
>
USECM5:	SE1ENT			;LDB'S ARE IN SECTION MUMBLE.
	HRRZ	F,LDBDDB##(U)	;GET DDB ADDRESS
	MOVE	T1,LDBDCH##(U)	;GET DEVICE BITS FOR TTY
	TLNE	T1,LDLCOM##	;COMMAND LEVEL?
	TLZ	M,NOPER		;YES--PRINT A PERIOD
	MOVSI	T2,LDBCMF##	;ALWAYS CALL TTYSTR IF
	TDNE	T2,LDBCOM##(U)	;USESTAT COMMAND (NOT ^T)
	TRNN	T1,LDROSU##	;CONTROL-O IN EFFECT
	TLZ	M,NOMESS	;NO--CLEAR NOMESS
	POPJ	P,0		;RETURN
;SUBROUTINE TO PRINT JOB'S HIGH SEGMENT(S) FOR CONTROL-T COMMAND
;CALL WITH:
;	J/ JOB NUMBER

USEHSG:				;WRAPS THE LINE AND TOO LATE FOR DOCUMENTATION
	POPJ	P,		;PATCH TO JFCL TO ENABLE THIS NIFTY FEATURE
	PUSHJ	P,SAVE2##	;FREE UP A FEW ACS
	SETZ	P1,		;START WITH FIRST HIGH SEGMENT
USEHS1:	MOVE	T1,P1		;COPY HSB ADDRESS
	PUSHJ	P,GNXHSB##	;GET NEXT HSB
	  POPJ	P,		;NONE, RETURN
	MOVE	P1,T1		;REMEMBER FOR POSTERITY
	SKIPG	P2,.HBSGN(P1)	;IS THERE A REAL SEGMENT THERE?
	JRST	USEHS1		;NO, SKIP THIS HSB
	PUSHJ	P,PRTPLS	;PRINT A "+"
	MOVE	T2,JBTPRG##(P2)	;GET NAME OF HIGH SEGMENT
	CAME	T2,JBTPRG##(J)	;UNLESS LOW AND HIGH SEG ARE SAME NAME,
	PUSHJ	P,PRNAME	; PRINT NAME OF HIGH SEGMENT
	JRST	USEHS1		;KEEP LOOPING
;SUBROUTINE TO PRINT A FILESPEC FOR A DDB
;CALL WITH:
;	F = DDB ADDRESS
;	U = LDB ADDRESS (OR FIX COMTOA)
;	PUSHJ	P,PRTDDB
;	RETURN HERE
;
PGMMRG:	SKIPA	T1,[[ASCIZ/Merged /]]
PGMFIL:	MOVEI	T1,[ASCIZ/ from /]
	SKIPE	F,USRJDA##+0	;SEE IF DDB AND GET ADDRESS
	TLNN	F,INPB		;WAS AN INPUT DONE?
	POPJ	P,		;NO
	PUSHJ	P,CONMES
PRTDDB::PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,DEVMOD(F)	;GET DEVICE TYPE BITS
	MOVSI	T2,'NUL'	;ASSUME NUL
	PUSHJ	P,NULTST##	;IS IT THE NUL DEVICE?
	  JRST	PRTDD1		;YES
	MOVE	T2,DEVNAM(F)	;GET DEVICE NAME
	HRRZ	T3,DEVUNI##(F)	;UDB POINTER
	JUMPE	T3,PRTDD1	;NO UNIT IF A KNOWN SEGMENT
	TLNN	P1,DVDSK	;IS THIS A DISK?
	JRST	PRTDD1		;NO
	SKIPN	T2,UNILOG(T3)	;YES, PART OF STR?
	MOVE	T2,UDBNAM(T3)	;NO
PRTDD1:	PUSHJ	P,PRNAME	;PRINT IT
	MOVEI	T3,":"		;ADD A COLON
	PUSHJ	P,PRCHR		; ..
	TLNN	P1,DVDSK!DVDTA	;FILE AND EXT?
	JRST	PRTDD2		;NO
	MOVE	T2,DEVFIL(F)	;GET FILE NAME
	JUMPE	T2,CPOPJ##	;PUNT IF NO NAME
	HLRZ	T3,DEVEXT(F)	;IS THIS A UFD
	TLNE	P1,DVDSK	;ON DISK
	CAIE	T3,'UFD'
	JRST	PRTDD3		;NO
	PUSHJ	P,PRTPPN	;YES -- PRINT FILE NAME AS [M,N]
	JRST	PRTDD4		;AND NOT SIXBIT
PRTDD2:
IFE FTTLAB,<POPJ P,>		;RETURN
IFN FTTLAB,<
	TLNE	P1,DVMTA	;IS THIS A MAGTAPE?
	SKIPN	%SITLP##	;AND IS TAPE LABELER RUNNING?
	POPJ	P,		;NO TO EITHER--RETURN
	PUSH	P,U		;SAVE U
	MOVE	U,TDVUDB##(F)	;UDB ADDRESS
	LDB	T1,TUYLTP##	;GET LABEL TYPE
	POP	P,U		;RESTORE U
	JUMPE	T1,CPOPJ##	;RETURN IF NOT A LABELED TAPE
	SKIPN	T2,DEVFIL(F)	;ELSE GET FILE NAME
	POPJ	P,		;UNLESS THERE ISN'T ONE
> ;END IFN FTTLAB
PRTDD3:	PUSHJ	P,PRNAME	;PRINT IT
PRTDD4:	PUSHJ	P,PRPER		;ADD IN A DOT
	HLLZ	T2,DEVEXT(F)	;GET EXTENSION
	PUSHJ	P,PRNAME	;PRINT IT
	TLNE	P1,DVDSK	;IS THIS THE DISK?
	SKIPN	T2,DEVPPN(F)	;FALL INTO PRTPPN IF PPN
	POPJ	P,		;ELSE RETURN
;	PJRST	PRTPTH		;PRINT PATH (NEXT PAGE)
;ROUTINE TO TYPE A PATH WITH SFD'S IF NEEDED

PRTPTH:	PUSHJ	P,PRTPP1	;PROJ, PROG PART OF PATH
	HRRZ	P1,DEVSFD##(F)	;PATH POINTER
	JUMPE	P1,PRTRBK	;IF NO SFD'S
	PUSH	P,[0]		;MARK END OF PATH
PRTPT1:	PUSH	P,NMBNAM##(P1)	;SAVE THE SFD NAME
PRTPT2:	HLRZ	P1,NMBPPB##(P1)	;BACK ONE LEVEL
	TRZN	P1,NMPUPT##	;NAME SHOULD BE OUTPUT?
	JUMPN	P1,PRTPT2	;NO, GET NEXT LEVEL IF NOT AT END
	JUMPN	P1,PRTPT1	;YES, SAVE NAME AND GET NEXT LEVEL
PRTPT3:	POP	P,T2		;RESTORE SFD NAME
	JUMPE	T2,PRTRBK	;IF END, TYPE RIGHT BRACKET AND RETURN
	PUSHJ	P,PRCOM		;PRINT COMMA
	PUSHJ	P,PRNAME	;PRINT THIS SFD NAME
	JRST	PRTPT3		;LOOP OVER WHOLE PATH

PRTPPN::PUSHJ	P,PRTPP1
	PJRST	PRTRBK

PRTPP1:	PUSH	P,T2		;SAVE PPN
	MOVEI	T3,"["		;PRINT [
	PUSHJ	P,PRCHR
	HLRE	T1,(P)
	JUMPGE	T1,PRTPP2	;WILDCARD?
	MOVEI	T3,"*"		;YES
	PUSHJ	P,COMTYO
	SKIPA
PRTPP2:	PUSHJ	P,PRTDI8	;PROJECT
	PUSHJ	P,PRCOM		;COMMA
	HRRE	T1,(P)
	AOJN	T1,PRTPP3	;WILDCARD?
	MOVEI	T3,"*"		;YES
	PUSHJ	P,COMTYO
	JRST	T2POPJ##
PRTPP3:	HRRZ	T1,(P)		;GET PROGRAMMER HALFWORD AGAIN
	PUSHJ	P,PRTDI8	;PRINT IT
	JRST	T2POPJ##

PRTRBK:	MOVEI	T3,"]"
	PJRST	P,PRCHR
	SUBTTL	NETWORK COMMANDS -- LOCATE


CLOCAT::JSP	T2,SAVCTX	;MUST SCHEDULE THIS COMMAND
	SE1ENT			;ENTER SECTION ONE
	PUSHJ	P,CTEXT1	;GET THE ARGUMENT IN SIXBIT
	NETDBJ			;INTERLOCK THIS CODE WITH NETSER
	SKIPN	T1,T2		;COPY TO T1
	SKIPA	T2,JBTLOC##	;USE LOCAL STATION
	PUSHJ	P,CVTOCT##	;TRY TO CONVERT TO OCTAL
	  MOVE	T1,T2		;CAN'T-GET THE NAME BACK
	PUSH	P,T1		;SAVE THE ARG
IFN FTNET,<
	SKIPE	[M.ANF##]	;ANF-10 SOFTWARE?
	PUSHJ	P,SRCNDB##	;SEARCH FOR THE NODE BLOCK
	  JRST	LOCERR		;DOES NOT EXIST
	HLRZ	T2,NDBNNM##(W)	;YES, GET THE NODE NUMBER
	MOVEI	T1,[ASCIZ/Node number out of range/]
	CAILE	T2,77		;KEEP IT REASONABLE FOR BATCH
	JRST	[POP  P,(P)	;CLEAN STACK
		 JRST ERRMES]	;GIVE ERROR
	MOVEM	T2,JBTLOC##(J)	;LOCATE HIM WHERE HE WANTS
	POP	P,(P)		;RESTORE THE STACK
	PUSHJ	P,TYPNDB##	;TYPE THE NODE NAME
	JSP	T1,CONMES	;AND FINISH UP
	ASCIZ	/ located
/
> ;END IFN FTNET
LOCERR:	POP	P,T2		;GET NUMBER BACK
	CAIG	T2,77		;IS IT A NUMBER
	JUMPG	T2,LOCER1	;YES, WILL ALLOW THE LOCATE TO HAPPEN
IFN FTNET,<PJRST UNDERR>	;UNDEFINED NETWORK NODE
IFE FTNET,<
	MOVEI	T1,[ASCIZ \Invalid station address\] ;NO.
	PJRST	ERRMES		;TYPE IT
> ;END IFE FTNET

LOCER1:	MOVEM	T2,JBTLOC##(J)	;STORE THE LOCATION
IFN FTNET,<
	MOVEI	T1,[ASCIZ /%Node (/]
	SKIPN	[M.ANF##]	;ANF-10 SOFTWARE?
> ;END IFN FTNET
	MOVEI	T1,[ASCIZ /Station /]
	PUSHJ	P,CONMES	;PRINT TEXT
	HRRZ	T1,JBTLOC##(J)	;GET THE NUMBER
	PUSHJ	P,PRTDI8	;PRINT THE NUMBER
IFN FTNET,<
	MOVEI	T1,[ASCIZ /) located but offline/]
	SKIPN	[M.ANF##]	;ANF-10 SOFTWARE?
> ;END IFN FTNET
	MOVEI	T1,[ASCIZ / located/]
	PUSHJ	P,CONMES	;PRINT TEXT
	PJRST	PCRLF		;END LINE WITH A CRLF
	SUBTTL	NETWORK COMMANDS -- WHERE


CWHERE::SE1ENT			;ENTER SECTION ONE
IFE FTNET!FTKL10!FTDECNET!FTENET,<
	MOVSI	T1,JLOG		;IF NOT
	TDNN	T1,JBTSTS##(J)	;LOGGED IN
	DPB	T1,PJOBN##	;DON'T LEAVE GHOST JOB
	JSP	T1,ERRMES	;CAN'T DO THESE IF NO NETWORK
	ASCIZ	/No network, DAS78, or DN60 software
/
> ;END IFN FTNET!FTKL10!FTDECNET!FTENET
IFN FTNET!FTKL10!FTDECNET!FTENET,<
	JSP	T2,SAVCTX##	;SAVE THE CONTEXT OF THE JOB
	PUSHJ	P,CTEXT1	;GET FIRST ARG = SIXBIT DEV NAME
IFN FTNET,<
	NETDBJ			;INTERLOCK WITH NETSER
	PUSHJ	P,NETASG##	;TRY TO ASSIGN "NODE_DEVICE"
	  POPJ	P,		;ERROR IN ARGUMENTS (MESSAGE PRINTED)
>;END IFN FTNET
	PUSH	P,T2		;SAVE 6 BIT
	PUSHJ	P,FNDSTA##	;GET OUR STATION
	POP	P,T2		;GET 6 BIT NAME
	MOVE	T1,T2		;INTO T1
	PUSH	P,U		;SAVE U
	PUSHJ	P,DVCNSG##	;SEARCH FOR PHYSICAL DEV NAME
	PJRST	NOTDV1		;PRINT "NO SUCH DEVICE"
	PUSHJ	P,FNDDEV##	;FIND LOCATION
	LDB	T2,PDVTYP##	;GET DEVICE TYPE
IFN FTKL10,<
	CAIN	T2,.TYD78	;IS IT A DAS78?
	PJRST	CWHD78##	;LET D78INT HANDLE IT
> ;END IFN FTKL10
IFN FTNET,<
	CAIE	T2,.TYTTY	;IS IT A TTY?
	PJRST	CWHANF##	;LET NETSER HANDLE NON-TTY DEVICES
> ;END IFN FTNET
	MOVE	U,DDBLDB##(F)	;GET TARGET TTY'S LDB
	MOVE	T4,LDBTTW##(U)	;GET THE TTY USE FLAGS
	TLNN	T4,LTLUSE##	;IS TTY IN USE?
	JRST	CWHNCN		;NO, JUST SAY "NOT CONNECTED"
IFN FTNET,<
	TLNE	T4,LTLANF##	;IF ANF-10,
	PJRST	CWHANF##	;LET NETSER TYPE IT OUT
> ;END IFN FTNET
IFN FTDECNET,<			;IF DECNET,
	TLNE	T4,LTLNRT##	;IF NRT/CTERM
	JRST	CWHNRT##	;LET NRTSER TYPE IT OUT
> ;END IFN FTDECNET
IFN FTENET,<			;IF ETHERNET/LAT
	TLNE	T4,LTLLAT##	;IF LAT TERMINAL
	PJRST	CWHLAT##	;LET LATSER TYPE IT OUT
> ;END IFN FTENET
	TLNE	T4,LTLREM##	;REMOTE?
	PJRST	CWHNCN		;YES, BUT DON'T KNOW WHAT FLAVOR
IFE FTNET,<JRST UPOPJ##>	;GIVE UP
IFN FTNET,<PJRST CWHANF##>	;SAY LOCAL STATION
CWHNCN::PUSHJ	P,INLMES	;DEVICE IS NOT CONNECTED . . .
	ASCIZ	\Device	\
	MOVE	T2,DEVNAM(F)	;GRAB THE DEVICE NAME
	PUSHJ	P,PRNAME	;AND TYPE IT OUT
	PUSHJ	P,INLMES	;NOT CONNECTED
	ASCIZ	/ not connected
/
	PUSHJ	P,TTYKLQ##	;ZAP THE USELESS DDB
        POP	P,U
	POPJ	P,		;RETURN

> ;END IFN FTNET!FTKL10!FTDECNET!FTENET
	SUBTTL	NETWORK COMMANDS -- NODE


CNODE::	SE1ENT			;ENTER SECTION ONE
	JSP	T2,SAVCTX##	;SAVE CONTEXT, RUN AT UUO LEVEL
IFE FTNET!FTDECNET,<
	MOVEI	T1,[ASCIZ /No network support/]
	PJRST	ERRMES		;REPORT ERROR AND RETURN
> ;END IFE FTNET!FTDECNET
IFN FTNET!FTDECNET,<
	SKIPN	[M.NET##]	;NETWORK SUPPORT IN MONITOR?
	JRST	[MOVEI T1,[ASCIZ /No network support/] ;NO
		PJRST ERRMES]	;REPORT ERROR AND RETURN
	PUSHJ	P,CTEXT1	;GET THE ARGUMENT
IFN FTNET,<
	PUSHJ	P,NODE.A##	;ANF-10 NODE?
	  SKIPA			;NO
	POPJ	P,		;DONE
> ;END IFN FTNET
IFN FTDECNET,<
	PUSHJ	P,NODE.D##	;DECNET NODE?
	  SKIPA			;NO
	POPJ	P,		;DONE
>; END IFN FTDECNET

UNDERR::MOVEI	T1,[ASCIZ /Undefined network node/]
	PJRST	ERRMES		;PRINT ERROR MESSAGE AND RETURN
> ;END IFN FTNET!FTDECNET
	SUBTTL	SAVE, SSAVE AND GET - COMMAND SETUP

; "SSAVE DEVICE:FILNAM.EXT [PROJ,R] CORE"
;WORKS LIKE SAVE, EXCEPT THAT HIGH SEG IS SAVED AS SHARABLE(EXT=SHR)
;INSTEAD OF NON-SHARABLE(EXT=HGH)


; "SAVE DEVICE:FILE-NAME[PROJ.,PROG.] CORE" - SAVES JOB AREA ON RETRIEVABLE DEVICE
;ONLY A SAVE OR A GET IN PROGRESS FOR EACH JOB
;NO ATTEMPT IS MADE TO SAVE DEVICE ASSIGNMENTS, AC'S, OR PC
NSAVE::	TLO	S,NSRBIT	;SET FLAG FOR SAVE
NSSAVE::MOVSI	T1,(JS.EXE)	;GET EXE BIT
	IORM	T1,JBTST2##(J)	;SET IT IN JOB STATUS WORD
	JRST	SSAVE2		; AND CONTINUE AS BEFORE

SAVEO::	TLO	S,NSRBIT	;OLD SAVE
	JRST	SSAVE1
CSAVE::	TLO	S,NSRBIT	;SET FLAG FOR NON-SHARABLE EXT(HGH)

SSAVE::	MOVE	T1,CNFST2##	;CHECK CONFIG BIT FOR EXE FILE SAVES
	TRNE	T1,ST%EXE	;IF ON,...
	JRST	NSSAVE		;... PROCEED AS IN "NSAVE"

SSAVE1::MOVSI	T1,(JS.EXE)	;GET EXE BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR IT JUST FOR SAFETY
SSAVE2:	TLO	P1,GTSAV	;FLAG THAT DOING A SAVE
	HRRI	S,SAVJOB	;SETUP TO RUN SAVJOB (S CLEARED BEFORE CALL)
	JRST	SGSETD



; SAVE UUO - CALLED LIKE RUN AND GETSEG UUOS

USAVE::	MOVE	T2,JBTSTS##(J)	;GET JOB STATUS
	TLNE	T2,JLOG		;LOGGED IN?
	 JRST	USAVE1		;YES, OK
	MOVEI	T1,NLIERR	;NOT LOGGED IN ERROR
	PUSHJ	P,SGRELE	;TRY TO TELL USER
	MOVEI	T1,LOGPLM	;ADDRESS OF ERROR TEXT
	JRST	PHOLD##		;START TTY AND STOP JOB
USAVE1:	MOVSI	T2,(JS.EXE)	;EXE-STYLE SAVE BIT
	IORM	T2,JBTST2##(J)	;SET FOR THIS USER
	TLO	P1,GTSAV	;DON'T KILL HISEG IF GETARG ABORTS
	MOVEM	P1,.JDAT+SGAEND	;A SAFER PLACE TO BE
	PUSHJ	P,GETARG	;GET USER'S ARGUMENTS
	SKIPGE .JDAT+SGANEW	;EXTENDED CORE ARG GIVEN?
	JRST	IUUAGL##	;YES, MUSN'T DO THAT FOR SAVE (YET)
	MOVE	T1,DEVMOD(F)	;GET DEVICE TYPE
	TLNN	T1,DVDSK	;IS IT A DISK?
	JRST	[MOVEI T1,ILUERR	;GET ERROR CODE
		 PUSHJ P,SGRELE	;TRY TO TELL USER
		 PJSP T1,PHOLD##	;GIVE UP
		 ASCIZ\SAVE. UUO only valid for disks\]
	TLNE	T1,DVTTY	;IS IT NUL?
	JRST	[POP P,(P)	;POP OFF JUNK
		 JRST CPOPJ1]	;AND GIVE GOOD RETURN
	MOVE	T1,.JDAT+JOBPD1##+1 ;GET UUO RETURN ADDR
	TRNN	T1,^-17		;FROM THE ACS?
	 HRRZS	.JDAT+JOBPD1##	;YES, SAY NOT FROM USER
IFN FTMP,<
	PUSHJ	P,CLRJSP##	;ENSURE MONITOR RUNS ON MASTER CPU
>
	OPEN	0,SGAMOD	;OPEN THE SPECIFIED DEVICE
	 JRST	SGERRU		;DEVICE WENT AWAY
	SKIPL	.JDAT+JOBPD3##+1	;DID USER SPECIFY SHARABLE?
	 TLO	S,NSRBIT	;NO, MAKE IT NONSHARABLE
	MOVEI	T2, 'EXE'	;GET THE LEGAL EXTENSION
	HRLM	T2,.JDAT+SGAEXT	;STORE IN ENTER BLOCK
	PUSHJ	P,SETEXT##	;AND SET UP SGALOW AND SGAHGH
	MOVE	T1,.JDAT+JOBPD1## ;OUR NOMINAL RETURNING FLAGS
	TLNN	T1,USRMOD	;WILL WE EVER RETURN?
	 JRST	USAVE2		;NO, SO SKIP THIS
	PUSH	P,.PDTMI##(W)	;SAVE SOME VM LOCS
	PUSH	P,.PDTMC##(W)
USAVE2:	HLRZ	T1,JBTADR##(J)	;GET HIGHEST ADDRESS IN LOW SEG
	HRRZS	T2,.JDAT+SGANEW	;CLEAR JUNK FROM LH (FOR COMPATABILITY)
	CAMGE	T1,T2		;COMPARE WITH USER STORED CORE ARG
	MOVE	T1,T2		;USER'S WAS LARGER, USE IT
	HRRM	T1,.JDAT+JOBCOR##	;AND SET UP JOBCOR.
	PUSHJ	P,RMVPFH##	;GET RID OF PFH
	PUSHJ	P,ADJCOR##	;SET UP GOOD CORE ARG
	PJRST	SAVEXE		;GO SAVE A FILE
	SUBTTL	SEGOP. UUO

;
;CALL:	XMOVEI	AC,ARGLIS
;	SEGOP.	AC,
;	  ERROR CODE IN AC
;	SUCCESS, AC UNCHANGED
;
;
SEGOP::	PUSHJ	P,SXPCS##	;VALIDATE THE ARG BLOCK POINTER
	  JRST	SOPADC		;ADDRESS ERROR
	MOVE	M,T1		;COPY FOR FETCHING
	PUSHJ	P,GETEWD##	;GET LENGTH,,FCN
	  JRST	SOPADC		;ADDRESS ERROR
	MOVE	T4,T1		;SAVE IT
	HLRZ	T2,T1		;GET LENGTH OF ARG BLOCK
	HRRES	T1		;ISOLATE FUNCTION CODE
	CAML	T1,[SEGCMX]	;LEGAL CUSTOMER FUNCTION?
	CAILE	T1,SEGFMX	;LEGAL FUNCTION CODE?
	JRST	SOPILF		;NOPE
	CAMGE	T2,SEGMLN(T1)	;ARGUMENT LIST LONG ENOUGH?
	JRST	SOPATS		;NO, ARGUMENT LIST TOO SHORT
	MOVE	T1,M		;GET ADDRESS OF ARG LIST
	PUSHJ	P,ARNGE##	;ADDRESS CHECK THE ARG BLOCK ITSELF
	  JRST	SOPADC		;NOT ALL ADDRESSABLE
	  JRST	SOPADC		;CAN'T STORE RESULTS
	HRRE	T1,T4		;GET FCN CODE AGAIN
	PJRST	@SEGJMP(T1)	;AND GO FOR IT

	DEFINE	SOPFNS,<
SOPFUN	(4,SOPINF)		;(0) GET SEGMENT INFO
SOPFUN	(7,SOPGET)		;(1) GET A SEGMENT
SOPFUN	(3,SOPREL)		;(2) RELEASE SEGMENT(S)
SOPFUN	(6,SOPRMP)		;(3) REMAP
SOPFUN	(3,SOPSWP)		;(4) SETUWP
SOPFUN	(6,SOPCOR)		;(5) CORE
SOPFUN	(3,SOPDMP)		;(6) RETURN A LIST OF SEGMENTS IN SOME ADR SPACE
>

	DEFINE	SOPFUN(LENGTH,DISPATCH),<IFIW	DISPATCH>


;DISPATCH TABLE OF SEGOP.
;CUSTOMER FUNCTIONS GO HERE
CSEGJM:
SEGJMP:	SOPFNS
SEGFMX==.-SEGJMP-1
SEGCMX==SEGJMP-CSEGJM

	DEFINE	SOPFUN(LENGTH,DISPATCH),<EXP	LENGTH>

;TABLE OF MINIMUM LEGAL LENGTHS OF ARGUMENT LIST FOR VARIOUS FUNCTIONS

SEGMLN:	SOPFNS			;TABLE OF MINIMUM LENGTHS

;ERROR RETURNS

SOPNSS:	MOVEI	T1,FNFERR	;NO SUCH SEGMENT
	JRST	STOTAC##	;STORE ERROR CODE
SOPNCA:	MOVEI	T1,NECERR	;NOT ENOUGH CORE AVAILABLE
	JRST	STOTAC##	;STORE ERROR CODE
SOPILF:	MOVEI	T1,ILUERR	;ILLEGAL FUNCTION
	JRST	STOTAC##	;STORE ERROR CODE
SOPCCW:	MOVEI	T1,WLKERR	;CAN'T WRITE ENABLE SEGMENT
	JRST	STOTAC##	;STORE ERROR CODE
SOPADC:	MOVEI	T1,ACRERR	;ADDRESS CHECK READING ARGUMENTS
	JRST	STOTAC##	;STORE ERROR CODE
SOPACS:	MOVEI	T1,ACSERR	;ADDRESS CHECK STORING ARGUMENTS
	JRST	STOTAC##	;STORE ERROR CODE
SOPATS:	MOVEI	T1,ATSERR	;ARGUMENT LIST TOO SHORT
	JRST	STOTAC##	;STORE ERROR CODE
SOPIAL:	MOVEI	T1,NZAERR	;ILLEGAL ARGUMENT LIST
	JRST	STOTAC		;STORE ERROR CODE
SOPNSA:	MOVEI	T1,NFSERR	;NO FREE SECTION
	JRST	STOTAC##	;STORE ERROR CODE
SOPSII:	MOVEI	T1,SIIERR	;SEG INFO INCONSISTANT (NAME AND NUMBER DON'T AGREE)
	JRST	STOTAC##	;STORE ERROR CODE
;FUNCTION 0 - GET SEGMENT INFORMATION
SOPINF:	PUSHJ	P,SAVE4##	;SAVE SOME WORKING ACS
	PUSHJ	P,GETEW1##	;GET FLAGS AND CONTEXT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	TRNN	T1,-1		;ALLOW 0 TO MEAN CURRENT CONTEXT
	HRR	T1,.CPJCH##	;GET CURRENT CONTEXT NUMBER
	PUSHJ	P,PUTEWD##	;STORE BACK POSSIBLY UPDATED JCH
	  JRST	SOPACS		;ADDRESS CHECK
	MOVE	P1,T1		;SAVE FLAGS AND CONTEXT NUMBER
	HRRZS	T1		;JUST CONTEXT NUMBER
	PUSHJ	P,CTXSGN##	;GET JBTSGN ENTRY FOR CURRENT CONTEXT
	  JRST	SOPNSS		;NO SUCH SEGMENT
	JUMPE	T1,SOPNSS	;NO SEGMENTS BELONG TO CONTEXT IF JBTSGN = 0
;HERE WITH T1 = JBTSGN FOR SPECIFIED CONTEXT
	MOVE	P2,T1		;SAVE JBTSGN
	PUSHJ	P,GETEW1##	;GET SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	MOVE	P3,T1		;SAVE THAT
	PUSHJ	P,GETEW1##	;GET SEGMENT NAME
	  JRST	SOPADC		;ADDRESS CHECK
	HRRI	M,-1(M)		;BACK M UP TO SEGMENT NUMBER IN CASE OF STORING
	MOVE	P4,T1		;SAVE NAME
	JUMPE	P3,SOPIN1	;JUMPE IF SEGMENT NUMBER = 0
	HRRZ	J,P1		;CONTEXT NUMBER
	HRRZ	T1,P3		;SEGMENT NUMBER
	PUSHJ	P,CFNDHB##	;FIND THE HIGH SEGMENT BLOCK FOR THIS SEGMENT
	  JRST	SOPNSS		;NO SUCH SEGMENT
	MOVE	J,.CPJOB##	;RESTORE JOB NUMBER
	MOVE	P2,T1		;HIGH SEGMENT BLOCK ADDRESS
	JUMPE	P4,SOPIN4	;GO IF NO NAME SPECIFIED
	CAME	P4,.HBHNM(P2)	;NAME SPECIFIED, MUCH MATCH
	JRST	SOPSII		;SEGMENT INFORMATION INCONSISTANT
	JRST	SOPIN4		;COPY SEGMENT INFO AND RETURN
;HERE TO SEARCH FOR A NAME IF GIVEN
SOPIN1:	JUMPE	P4,SOPIN4	;GO IF NO NAME
SOPIN2:	CAMN	P4,.HBHNM(P2)	;NAME MATCH?
	JRST	SOPIN3		;YES, WE HAVE A WINNER
	SKIPE	P2,.HBLNK(P2)	;NEXT SEGMENT BLOCK
	JRST	SOPIN2		;SEE IF IT MATCHES
	JRST	SOPNSS		;NO SUCH SEGMENT
SOPIN3:	MOVE	P3,.HBSGN(P2)	;INDICATE WE HAVE A SEGMENT NUMBER
	MOVE	T1,P3		;ARGUMENT FOR PUTEWD
	PUSHJ	P,PUTEWD##	;STORE SEGMENT NUMBER BACK IN USER'S ARG BLOCK
	  JRST	SOPACS		;ADDRESS CHECK
;HERE TO CHECK FOR STEP FLAG. P1=FLAGS, P2=SEGMENT BLOCK, P3=SEGMENT NUMBER
SOPIN4:	TLNN	P1,(1B0)	;STEP FLAG? (SG.STP)
	JRST	SOPIN6		;NO, RETURN INFO FOR CURRENT SEGMENT
	SKIPE	P3		;IF AT START OF CHAIN, GET FIRST SEGMENT NUMBER
	SKIPE	P2,.HBLNK(P2)	;YES, GET NEXT SEGMENT BLOCK
	JRST	SOPIN5		;GO IF NOT THE LAST
	MOVEI	T1,0		;SIGNIFY END WITH 0 FOR SEGMENT NUMBER AND NAME
	PUSHJ	P,PUTEWD##	;STORE SEGMENT NUMBER
	  JRST	SOPACS		;ADDRESS CHECK
	PUSHJ	P,PUTEW1##	;AND NAME
	  JRST	SOPACS		;ADDRESS CHECK
	JRST	CPOPJ1##	;GOOD RETURN TO THE USER
SOPIN5:	SKIPGE	P3,.HBSGN(P2)	;GET SEGMENT NUMBER (INDICATE ONE FOUND)
	JRST	SOPIN4		;FIND A REAL (NOT SPY) SEGMENT
	MOVE	T1,P3		;FOR PUTEWD
	PUSHJ	P,PUTEWD##	;STORE IT FOR THE USER
	  JRST	SOPACS		;ADDRESS CHECK
SOPIN6:	JUMPE	P3,SOPNSS	;NUMBER AND NAME WERE 0 AND SG.STP WAS OFF
	HRRI	M,-2(M)		;POSITION M FOR COPSGN
	PUSHJ	P,COPSGN	;COPY SEGMENT DATA TO USER'S ARGUMENT BLOCK
	  JRST	STOTAC##	;SOMETHING WENT WRONG
	JRST	CPOPJ1##	;GOOD RETURN
;FUNCTION 1 - GET A SEGMENT
SOPGET:	MOVE	P2,USRJDA##	;THIS IS VERY SENSITVE TO STACK ORDER
				;SEE SGRELE!!!
	PUSHJ	P,SAVE2##	;MAKE AC SPECIFIED IN THE SEGOP. BE AT
				; JOBPD1+3. SGRELE EXPECTS TO FIND IT THERE
	MOVEI	T1,.USUAC	;SPEC SAYS USER'S ACS SURVIVE THIS
	EXCTUX	<BLT T1,.USUAC+17> ;SO SAVE THEM
	PUSHJ	P,GETEW1##	;GET FLAGS WORD
	  JRST	SOPADC		;ADDRESS CHECK
	MOVE	P1,T1		;SAVE FLAGS
	LDB	T1,[POINT 5,P1,17] ;GET SECTION NUMBER FIELD
	TLNN	P1,(1B2)	;SG.FFS? (FIND FREE SECTION)
	JRST	SOPGE2		;NO, SEE IF SECTION NUMBER SPECIFIED
	MOVEI	T1,1		;START AT SECTION 1
SOPGE1:	SKIPN	.UPMP+SECTAB(T1);THIS SECTION FREE?
	JRST	SOPGE3		;YES, USE IT
	CAIGE	T1,MXSECN	;LOOKED AT ALL SECTIONS?
	AOJA	T1,SOPGE1	;NO, LOOK AT NEXT
	JRST	SOPNSA		;NO AVAILABLE SECTIONS
SOPGE2:	TLNN	P1,(1B1)	;SG.USN? (USE SECTION NUMBER)
	JRST	SOPGE4		;NO, USE PCS SECTION
SOPGE3:	EXCH	P1,T1		;SECTION NUMBER TO P1, FLAGS TO T1
	DPB	P1,[POINT 5,T1,17] ;SECTION NUMBER TO RETURNED ARGUMENT
	TLZ	T1,(1B2)	;CLEAR FFS
	TLO	T1,(1B1)	;SET USN
	PUSHJ	P,PUTEWD##	;STORE THAT FOR THE USER
	  JRST	SOPACS		;ADDRESS CHECK
	LSH	P1,S2PLSH	;POSITION SECTION NUMBER FOR .USUSN
	MOVEM	P1,.USUSN	;STORE THAT FOR THE GETSEG
SOPGE4:	UMOVE	T1,5(M)		;GET POINTER TO FILE SPEC
	MOVEI	T2,11		;LENGTH OF FILE SPEC
	PUSHJ	P,ARNGE##	;CHECK IT
	  JRST	SOPADC		;ADDRESS CHECK
	  JFCL			;NOT LEGAL FOR I/O, DON'T CARE SINCE ONLY READING
	MOVE	M,T1		;SETUP M FOR FETCHING FILE SPEC
	PUSHJ	P,GETEWD##	;GET FIRST ARG FROM USER AREA
	  JRST	GETADC		;ADDRESS CHECK (SHOULDN'T HAPPEN)
	MOVEM	T1,.JDAT+SGADEV	;STORE DEVICE NAME
	PUSHJ	P,GETEW1##	;GET NEXT ARG FROM USER AREA
	  JRST	GETADC		;ADDRESS CHECK (SHOULDN'T HAPPEN)
	MOVEM	T1,.JDAT+SGANAM	;STORE FILE NAME FOR LOOKUP (DO NOT STORE FOR LOWSEG)
	PUSHJ	P,GETEW1##	;GET THIRD ARG(EXTENSION WORD E+1)
	  JRST	GETADC		;ADDRESS CHECK (SHOULDN'T HAPPEN)
	MOVEM	T1,.JDAT+SGAEXT	;STORE EXTENSION AND RH FROM USER
	PUSHJ	P,GETEW1##	;GET FOURTH USER ARG FROM USER AREA
	  JRST	GETADC		;ADDRESS CHECK (SHOULDN'T HAPPEN)
	MOVEM	T1,.JDAT+JOBUAL##+2 ;STORE PROJECT PROGRAMER NO. OR 0 IN PATH
	SKIPE	T1		;IF PPN = 0, MAKE E+3 = 0
	MOVEI	T1,JOBUAL##	;ADDRESS OF PATH BLOCK
	MOVEM	T1,.JDAT+SGAPPN	;POINT AT PATH BLOCK
	HLRZ	T2,.JDAT+SGAEXT	;PUT ARG IN T2, SO SAME AS SGSET RETURN FROM CTEXT
	CAIE	T2,'SHR'	;SEE IF THE USER
	CAIN	T2,'HGH'	; GAVE A BAD EXT
	MOVEI	T2,0		;YES--IGNORE IT
	PUSHJ	P,SETEX1##	;SAVE EXT AGAIN IN SGALOW
				; SETUP EXT FOR HIGH SEG(SGAHGH="SHR")
				; SETUP EXTENSION FOR LOW SEG(SGALOW="SAV")
	SKIPN	.JDAT+SGAPPN	;IF PPN = 0,
	JRST	SOPGE6		; DON'T BOTHER WITH SFD'S
	MOVSI	P1,-MAXLVL##	;NUMBER OF SFDS
SOPGE5:	PUSHJ	P,GETEW1##	;GET NEXT SFD
	  JRST	GETADC		;ADDRESS CHECK (SHOULDN'T HAPPEN)
	MOVEM	T1,.JDAT+JOBUAL##+3(P1) ;STORE NEXT SFD
	SKIPE	T1		;DONE IF A ZERO
	AOBJN	P1,SOPGE5	;LOOP FOR ALL SFD'S
	SETZM	.JDAT+JOBUAL##+3(P1) ;TERMINATE LIST (IN CASE MAXLVL SFDS)
SOPGE6:	MOVE	P1,.JDAT+JOBPD3##+1 ;PHONLY
	PUSHJ	P,SG2A		;GO SET UP LOWER CORE
				; DO NOT DO A RESET
	SETZM	USRJDA##	;SO OPEN WON'T RELEASE IT
	MOVSI	T1,GTHGH+GTSGO	;GET ONLY HIGH SEGMENT BEING DONE FROM SEGOP.
	PUSHJ	P,[PUSH P,(P)	;SO SGETHI WILL HAVE SOMETHING TO POP OFF THE
		   JRST SGETHI##] ; SINCE THERE ISN'T A CALL TO GETARG HERE
	  STOPCD	(GETNSS,DEBUG,GDS) ;++GETSEG DIDN'T SKIP
	MOVE	T1,.CPJOB##	;CURRENT JOB'S JOB NUMBER
	PUSHJ	P,CTXJCH##	;GET CURRENT JCH
	  MOVE	T1,.CPJOB##	;NONE, USE CURRENT JOB NUMBER
	HRRZ	M,.JDAT+JOBPD3##+1 ;AC USER SPECIFIED IN THE SEGOP.
	MOVE	M,.USUAC(M)	;ADDRESS OF SEGOP. ARGUMENT BLOCK
	MOVE	J,T1		;FOR FNDFSN AND A CONVENIENT PLACE TO SAVE T1
	PUSHJ	P,GETEW1##	;GET FLAGS WORD
	  JRST	GETADC		;ADDRESS CHECK
	HRR	T1,J		;CURRENT JCH
	PUSHJ	P,PUTEWD##	;STORE THAT (NEEDED FOR COPSGN)
	  JRST	GETADC		;ADDRESS CHECK
	PUSHJ	P,FNDFSN	;FIND SEGMENT NUMBER OF SEGMENT JUST GOTTEN
	  JRST	GETNSS		;REALLY CAN'T HAPPEN
	PUSHJ	P,PUTEW1##	;STORE THAT BACK
	  JRST	GETADC		;ADDRESS CHECK
	SUBI	M,2		;BACK UP TO BEGINNING OF THE BLOCK
	PUSHJ	P,COPSGN	;NOW COPY SEGMENT INFO FOR SEGMENT JUST GOTTEN
	  JRST	GETSEC		;BAD NEWS
	MOVSI	T1,.USUAC	;RESTORE USER'S AC
	EXCTXU	<BLT T1,17>	; ..
	MOVE	T1,.JDAT+JOBPD3##+2 ;USER'S STORED CHANNEL 0
	MOVEM	T1,USRJDA##	;RESTORE THAT
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN

;ERRORS
GETADC:	SKIPA	T1,[ACSERR]
GETNSS:	MOVEI	T1,[FNFERR]
GETSEC:	MOVSI	T2,.USUAC	;RESTORE USER'S ACS
	EXCTXU	<BLT T2,17>	; ..
	MOVE	T2,.JDAT+JOBPD3##+2 ;USER'S STORED CHANNEL 0
	MOVEM	T2,USRJDA##	;RESTORE THAT
	HRRZ	M,.JDAT+JOBPD3##+1 ;USERS AC
	PJRST	PUTWDU##	;STORE ERROR CODE AND RETURN (CAN'T ADDRESS
				; CHECK STORING IN AN AC)
;FUNCTION 2 - RELEASE A SEGMENT OR SEGMENTS
SOPREL:	PUSHJ	P,SAVE1##	;SAVE AN AC
	PUSHJ	P,GETEW1##	;GET THE FLAGS WORD
	  JRST	SOPADC		;ADDRESS CHECK
	MOVE	P1,T1		;SAVE FLAGS
	PUSHJ	P,GETEW1##	;FIRST SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	TLNE	P1,(1B1)	;SG.USN?
	JRST	SOPRL1		;YES
;HERE TO REMOVE ALL SEGMENTS OR A LIST OF SEGMENTS
	JUMPN	T1,SOPRL2	;JUMP IF A LIST
;REMOVE ALL SEGMENTS
	AOS	(P)		;SKIP RETURN
	PJRST	KILHGA##	;REMOVE ALL SEGMENTS
SOPRL1:	LDB	T1,[POINT 5,P1,17]
	PUSHJ	P,SVPCS##	;SETUP PCS FOR THE SECTION IN QUESTION
	SETZ	T1,		;KILL ALL SEGMENTS IN PCS SECTION
	PUSHJ	P,KILHGC##	;DO THE WORK
SOPRL2:	SOS	M		;SO CAN CALL GETEW1
SOPRL3:	PUSHJ	P,GETEW1##	;NEXT SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	JUMPE	T1,CPOPJ1##	;EXIT IF LAST SEGMENT
	PUSHJ	P,FNDHSB##	;FIND THE HIGH SEGMENT BLOCK ADDRESS
	  JRST	SOPRL3		;OK IF THERE ISN'T ONE
	PUSHJ	P,KILHGH##	;KILL OF THIS SEGMENT
	JRST	SOPRL3		;LOOP FOR NEXT SEGMENT NUMBER
;FUNCTION 3 - MAKE A SEGMENT FROM "LOW SEGMENT PAGES" (REMAP)
SOPRMP:	PUSHJ	P,SAVE1##	;SAVE AN AC
	MOVE	P1,M		;THE HARDEST PART OF THIS IS KEEPING TRACK OF M
	HRRI	M,3(M)		;POINT AT NAME WORD
	PUSHJ	P,GETEWD##	;GET NAME
	  JRST	SOPADC		;ADDRESS CHECK
	MOVEM	T1,.JDAT+SGANAM	;STORE IT FOR REMAP
	PUSHJ	P,GETEW1##	;GET CURRENT AND NEW ORIGIN
	  JRST	SOPADC		;ADDRESS CHECK
	HRRZM	T1,.JDAT+JOBUAL##+1 ;CURRENT ORIGIN
	HLRZM	T1,.JDAT+JOBUAL##+2 ;NEW ORIGIN
	PUSHJ	P,GETEW1##	;GET NUMBER OF PAGES TO BE REMAPPED
	  JRST	SOPADC		;ADDRESS CHECK
	MOVEM	T1,.JDAT+JOBUAL## ;NUMBER OF PAGES
	MOVSI	T1,GTSGO	;INDICATE SEGOP
	MOVEM	T1,.JDAT+SGAEND	;WHERE FLAGS ARE STORED
	MOVE	T1,[3,,JOBUAL##];THREE ARGUMENTS AT JOBUAL
	PUSHJ	P,SREMAP##	;DO THE WORK
	  POPJ	P,		;ERROR CODE STORED (SHOULD IT BE REMAPPED?)
	PUSHJ	P,FNDFSN	;GET THE SEGMENT NUMBER OF SEGMENT JUST CREATED
	  JRST	SOPNSS		;NO SUCH SEGMENT - SHOULDN'T HAPPEN
	AOS	M,P1		;POINT M AT FLAGS WORD
	MOVE	P1,T2		;PARINOIA (PUTEWD PROBABLY DOESN'T SMASH T2, BUT ...)
	PUSHJ	P,PUTEW1##	;BUMP M TO SEGMENT NUMBER WORD AND STORE ANSWER
	  JRST	SOPACS		;ADDRESS CHECK
	MOVE	T1,P1		;GET SEGMENT NAME BACK
	PUSHJ	P,PUTEW1##	;STORE THAT FOR THE USER (PROBABLY SAME AS SUPPLIED)
	  JRST	SOPACS		;ADDRESS CHECK
	JRST	CPOPJ1##	;USER DID GOOD
;FUNCTION 4 - SETUWP (ON/OFF) FOR A SEGMENT
SOPSWP:	PUSHJ	P,SAVE2##	;SAVE SOME ACS
	PUSHJ	P,GETEW1##	;GET FLAGS WORD
	  JRST	SOPADC		;ADDRESS CHECK
	MOVE	P1,T1		;SAVE UWP ON/OFF FLAG
	PUSHJ	P,GETEW1##	;GET SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	PUSHJ	P,FNDHSB##	;FIND HIGH SEGMENT BLOCK FOR THIS SEGMENT
	  JRST	SOPNSS		;NO SUCH SEGMENT
	MOVE	T2,T1		;HIGH SEGMENT BLOCK ADDRESS TO T2
	MOVS	M,.USMUO	;MAKE GETTAC WORK
	PUSHJ	P,GETTAC##	;GET CONTENTS OF USER'S AC
	PUSH	P,T1		;SAVE THAT (SOSUWP STORES THERE)
	PUSH	P,T1		;SAVE AS ADDRESS TO WRITE TO AS WELL
	PUSHJ	P,SOSUWP##	;DO THE WORK
	  JRST	[MOVEI T1,WLKERR;FAILED, CAN'T SET UWP OFF FOR THE SEGMENT
		 MOVEM T1,-1(P)	;ERROR CODE FOR THE USER
		 SOS -2(P)	;SET FOR ERROR RETURN
		 JRST .+1]	;CONTINUE
	PUSHJ	P,GETTAC##	;GET WHAT SOSUWP STORED AS CURRENT VALUE OF UWP
	POP	P,M		;BACK UP TO FLAGS WORD
	PUSHJ	P,PUTEW1##	;STORE PREVIOUS (CURRENT IF ERROR) VALUE OF UWP
	  JRST	SOPACS		;ADDRESS CHECK
	POP	P,T1		;CONTENTS OF USER'S AC OR ERROR CODE
	JRST	STOTC1##	;STORE THAT AND RETURN
;FUNCTION 5 - DO A CORE UUO FOR A SEGMENT
SOPCOR:	PUSHJ	P,SAVE2##	;SAVE SOME ACS
	HRRI	M,2(M)		;POINT AT SEGMENT NUMBER
	PUSHJ	P,GETEWD##	;GET SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	SKIPE	P1,T1		;SAVE SEGMENT NUMBER
	PUSHJ	P,FNDHSB##	;VALIDATE HIGH SEGMENT NUMBER
	  JRST	SOPNSS		;NO SUCH SEGMENT
	MOVE	P2,T1		;SAVE ADDRESS OF HIGH SEGMENT BLOCK
	LDB	T1,[PSG2LH+.HBSG2(T1)] ;SECTION CONTAINING THE SEGMENT
	PUSHJ	P,SVPCS##	;SET PCS TO THAT
	HRRI	M,3(M)		;POINT AT SEGMENT SIZE FIELD
	PUSHJ	P,GETEWD##	;GET SIZE (CORE UUO ARGUMENT)
	  JRST	SOPADC		;ADDRESS CHECK
	JUMPLE	T1,SOPIAL	;ZERO OR A NEGATIVE ARGUMENT IS ILLEGAL
	HRRZ	J,.HBSGN(P2)	;GET SEGMENT NUMBER
	LDB	P2,JBYHSO##	;SEGMENT ORIGIN WITHIN SECTION
	LSH	P2,P2WLSH	;CONVERT TO ADDRESS
	LSH	T1,P2WLSH	;SIZE OF SEGMENT IN WORDS AFTER CORE IS DONE
	ADDI	T1,-1(P2)	;HIGHEST RELATIVE ADDRESS IN SEGMENT
	TLNE	T1,-1		;TRYING TO GROW OUTSIDE THE SECTION?
	JRST	SOPIAL		;YES, ILLEGAL ARGUMENT
	HRLZS	T1		;WHERE CHGCOR WANTS THE ARGUMENT
	MOVE	J,P1		;SEGMENT NUMBER TO J
	PUSHJ	P,CHGCOR##	;DO THE CORE UUO
	  JRST	SOPNCA		;NOT ENOUGH CORE
	JRST	CPOPJ1##	;SUCCESS
;FUNCTION 6 - RETURN A LIST OF THE SEGMENTS IN THE SPECIFIED ADDRESS SPACE
SOPDMP:	PUSHJ	P,SAVE4##	;SAVE AN AC
	PUSHJ	P,GETEWD##	;GET THE LENGTH OF THE ARGUMENT BLOCK
	  JRST	SOPADC		;ADDRESS CHECK
	HLRZ	P1,T1		;LENGTH OF THE ARGUMENT BLOCK
	MOVNI	P1,-2(P1)	;MAKE AN AOBJN POINTER
	HRLZS	P1		;TO COUNT ARGUMENTS THAT COULD HAVE BEEN STORED
	PUSHJ	P,GETEW1##	;GET FLAGS WORD
	  JRST	SOPADC		;ADDRESS CHECK
	TRNN	T1,-1		;IF CONTEXT IS ZERO,
	HRR	T1,.CPJCH##	; DEFAULT TO CURRENT CONTEXT
	MOVE	P3,M		;SAVE M
	MOVE	P4,T1		;SAVE FLAGS
	HRRZS	J,T1		;CONTEXT HANDLE TO J AND T1
	PUSHJ	P,CTXSGN##	;GET JBTSGN FOR SPECIFIED CONTEXT
	  JRST	SOPNSS		;NON-EXISTANT
	MOVE	P2,T1		;SAVE JBTSGN
	JUMPE	P2,SOPDM5	;JUMP IF THERE AREN'T
	PUSHJ	P,GETEW1##	;GET STARTING SEGMENT NUMBER
	  JRST	SOPADC		;ADDRESS CHECK
	JUMPE	T1,[TLNN P4,(1B0) ;ST.STP?
		    JRST SOPNSS	;NO, STARTING SEGMENT NUMBER = 0, ST.STP OFF
		    JRST SOPDM1];YES, START AT THE BEGINNING
	HRRZS	T1		;ARGUMENTS FOR FNDHSB
	PUSHJ	P,CFNDHB##	;GET THE HIGH SEGMENT BLOCK FOR THIS CONTEXT
	  JRST	SOPNSS		;NO SUCH SEGMENT
	TLNE	P4,(1B0)	;SG.STP? (STEP FLAG)
	SKIPN	P2,.HBLNK(T1)	;ADVANCE TO NEXT BLOCK IF THERE IS ONE
	SOJA	M,SOPDM5	;THERE IS, RETURN SEGMENT NUMBER FROM IT
SOPDM1:	HRRI	M,-1(M)		;BACK UP TO SEGMENT WORD
SOPDM2:	SKIPG	T1,.HBSGN(P2)	;GET A SEGMENT NUMBER
	JRST	SOPDM3		;SPY SEGMENT
	PUSHJ	P,PUTEW1##	;STORE SEGMENT NUMBER
	  JRST	SOPACS		;ADDRESS CHECK
	AOBJP	P1,SOPDM4	;GO IF ALL THE USER ASKED FOR HAVE BEEN STORED
SOPDM3:	SKIPE	P2,.HBLNK(P2)	;NEXT HIGH SEGMENT BLOCK
	JRST	SOPDM2		;STORE THE NXEXT HIGH SEGMENT NUMBER
	JRST	SOPDM5		;ALL DONE
SOPDM4:	SKIPN	P2,.HBLNK(P2)	;COUNT NUMBER THAT COULD HAVE BEEN STORED
	JRST	SOPDM5		;NO MORE
	SKIPG	.HBSGN(P2)	;A REAL HIGH SEGMENT? (NOT SPY)
	JRST	SOPDM4		;NO, DON'T COUNT IT
	AOJA	P1,SOPDM4	;YES, COUNT ANOTHER SEGMENT
SOPDM5:	JUMPGE	P1,SOPDM6	;IF THERE IS STILL SPACE LEFT,
	MOVEI	T1,0		; TERMINATE SEGMENT NUMBER LIST WITH A 0
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	SOPACS		;ADDRESS CHECK
SOPDM6:	MOVE	M,P3		;RESTORE M
	MOVE	T1,P4		;RESTORE FLAGS
	DPB	P1,[POINT 12,T1,17] ;RETURN NUMBER OF SEGMENTS WHICH
	PUSHJ	P,PUTEWD##	; COULD HAVE BEEN OR WERE RETURNED
	  JRST	SOPACS		;ADDRESS CHECK
	JRST	CPOPJ1##	;SKIP RETURN TO THE USER
;SUBROUTINE TO COPY SEGMENT DATA TO USER ARGUMENT BLOCK.
;CALLING SEQUENCE:
;	MOVEI	M,ADDRESS OF USER ARGUMENT BLOCK
;	PUSHJ	P,COPSGN
;	  ERROR RETURN (ERROR CODE IN T1)
;	GOOD RETURN
;

COPSGN:	PUSHJ	P,SAVE2##	;SAVE SOME WORKING ACS
	PUSHJ	P,GETEWD##	;GET LENGTH,,FUNCTION
	  JRST	COPADC		;ADDRESS CHECK
	HLRZ	P2,T1		;LENGTH OF THE ARGUMENT BLOCK
	SUBI	P2,3		;ACCOUNT FOR MANDATORY RETURNED VALUES
	PUSHJ	P,GETEW1##	;GET FLAGS WORD
	  JRST	COPADC		;ADDRESS CHECK
	MOVEI	J,(T1)		;CONTEXT HANDLE TO J
	PUSHJ	P,GETEW1##	;GET SEGMENT NUMBER WORD
	  JRST	COPADC		;ADDRESS CHECK
	PUSHJ	P,CFNDHB##	;FIND THE HIGH SEGMENT BLOCK FOR THIS SEGMENT
				; IN THE GIVEN CONTEXT
	  JRST	COPNSS		;NO SUCH
	MOVE	P1,T1		;P1 GET ADDRESS OF HIGH SEGMENT BLOCK
	MOVE	T1,.HBSGN(P1)	;GET SEGMENT NUMBER + BITS FROM HSB
	HRRZ	J,T1		;J GETS HIGH SEGMENT NUMBER
	PUSHJ	P,PUTEWD##	;STORE SEGMNET NUMBER + BITS
	  JRST	COPACS		;ADDRESS CHECK
	MOVE	T1,.HBHNM(P1)	;SEGMENT NAME
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	SOJE	P2,CPOPJ1##	;RETURN IF ALL THE USER ASKED FOR HAS BEEN STORED
	MOVE	T1,P1		;ADDRESS OF THE HSB TO T1
	PUSHJ	P,GETHSA	;GET HIGH SEGMENT ADDRESS
	LSH	T1,W2PLSH	;HIGH SEGMENT ORIGIN PAGE NUMBER
	HRLS	T1		;COPY TO THE LEFT HALF
	LDB	T2,[PSG2LH+.HBSG2(P1)] ;SEGMENT ORIGIN SECTION
	LSH	T2,S2PLSH	;MAKE PAGE OFFSET
	SUB	T1,T2		;LOCAL SEGMENT ORIGIN,,SEMENT ORIGIN IF GETSEG
	MOVSS	T1		;PER THE SPEC
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	SOJE	P2,CPOPJ1##	;RETURN IF ALL THE USER ASKED FOR HAS BEEN STORED
	LDB	T1,[PHSSLH+.HBHSZ(P1)] ;SIZE OF THE SEGMENT IN PAGES
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	SOJE	P2,CPOPJ1##	;RETURN IF ALL THE USER ASKED FOR HAS BEEN STORED
	PUSHJ	P,GETEW1##	;GET POINTER TO FILE SPEC
	  JRST	COPADC		;ADDRESS CHECK
	JUMPE	T1,CPOPJ1##	;ALL DONE IF ZERO
	MOVE	M,T1		;FOR STORING THE FILE SPEC
	MOVE	T1,JBTDEV##(J)	;DEVICE SEGMENT CAME FROM
	PUSHJ	P,PUTEWD##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	MOVE	T1,JBTNAM##(J)	;FILE NAME OF FILE SEGMENT CAME FROM
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	MOVE	T1,JBTSTS##(J)	;HIGH SEGMENT STATUS
	TRNE	T1,JS.SFE	;SEGMENT COME FROM AN EXE FILE?
	JRST	COPSG1		;YES, EXTENSION IS 'EXE'
	TLNN	T1,SHRSEG	;NOT FROM AN EXE FILE, IS IT SHARABLE?
	SKIPA	T1,[SIXBIT/HGH/];NO, EXTENSION WAS 'HGH'
	MOVSI	T1,(SIXBIT/SHR/);YES, EXTENSION WAS 'SHR'
	JRST	COPSG2		;STORE EXTENSION
COPSG1:	MOVSI	T1,(SIXBIT/EXE/);EXE EXTENSION
COPSG2:	PUSHJ	P,PUTEW1##	;STORE EXTENSION
	  JRST	COPACS		;ADDRESS CHECK
	SETO	P1,		;ASSUME ONLY A PPN
	MOVE	T1,JBTPPN##(J)	;GET PPN OR PATH POINTER
	TLNE	T1,-1		;PATH POINTER?
	JRST	COPSG4		;NO, ONLY A PPN. GO STORE THAT
	MOVSI	P1,-MAXLVL##-1	;NUMBER OF ELEMENTS TO COPY
	HRR	P1,T1		;POINT AT THE PATH
COPSG3:	MOVE	T1,(P1)		;NEXT PATH ELEMENT
COPSG4:	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	COPACS		;ADDRESS CHECK
	AOBJN	P1,COPSG3	;COPY ALL PATH ELEMENTS
	JUMPN	P1,CPOPJ1##	;EXIT IF PATH COPIED (TERMINATED BY 0 OR 5 SFDS)
	SETZ	T1,		;IF ONLY A PPN,
	PUSHJ	P,PUTEW1##	; TERMINATE PATH WITH A ZERO
	  JRST	COPACS		;ADDRESS CHECK
	JRST	CPOPJ1##	;GOOD RETURN

;ERROR RETURNS
COPADC:	MOVEI	T1,ACRERR	;ADDRESS CHECK
	POPJ	P,		;NON-SKIP RETURN
COPACS:	MOVEI	T1,ACSERR	;ADDRESS CHECK STORING ARGUMENT
	POPJ	P,		;NON-SKIP RETURN
COPNSS:	MOVEI	T1,FNFERR	;NO SUCH SEGMENT
	POPJ	P,		;NON-SKIP RETURN

;SUBROUTINE TO FIND SEGMENT NUMBER OF FIRST SEGMENT IN .HBLNK CHAIN (LAST
; SEGMENT CREATED, REMAPPED, OR GOT)
;CALL WITH J=CONTEXT NUMBER, RETURNS CPOPJ IF NO SUCH SEGMENT, CPOPJ1, T1 =
; SEGMENT NUMBER, T2 = SEGMENT NAME (.HBHNM)

FNDFSN:	MOVE	T1,J		;FOR CTXSGN
	PUSHJ	P,CTXSGN	;GET JBTSGN FOR THIS CONTEXT
	  POPJ	P,		;NO SUCH CONTEXT
	JUMPE	T1,CPOPJ##	;CONTEXT HAS NO SEGMENTS
	MOVE	T2,.HBHNM(T1)	;GET SEGMENT NAME
	MOVE	T1,.HBSGN(T1)	;SEGMENT NUMBER OF FIRST SEGMENT IN THE CHAIN
	JRST	CPOPJ1##	;OK RETURN
; "GET DEVICE:FILE-NAME[PROJ.,PROG.] CORE" - SETS UP JOB AREA FROM RETREIVABLE
;DEVICE AND ASSIGNS CORE.


GET::	HLLZ	T2,SYSTAP##	;SETUP DEFAULT DEVICE
	MOVEI	S,GJOB		;SETUP TO RUN GETJOB
	JRST	RUNCM
				; JOB DATA AREA FOR MONITOR JOB
;AUTOMATIC LOGIN
LOGREF:	PUSHJ	P,ISOPCT	;SKIP IF OPR OR CTY
	  JRST	CLOG2A		;NO, REGULAR LOGIN
	SETZ	T1,		;CLEAR FLAG
	EXCH	T1,REFLAG##	;GET PPN FOR AUTOMATIC LOGIN
	SETZB	T2,T3		;NO USER NAME
	PJRST	MLOGIN		;LOGIN A JOB WITHOUT RUNNING LOGIN


;FRCLIN LOGIN
LOGFRC:	MOVE	T1,FFAPPN##	;GET PPN FOR FRCLIN
	MOVE	T2,[SIXBIT/SYSJOB/]
	SETZ	T3,		;NO SECOND WORD
;	PJRST	MLOGIN		;LOGIN A JOB WITHOUT RUNNING LOGIN


;MONITOR LOGIN
;CALL:	MOVE	T1, PPN
;	DMOVE	T2, USER NAME

MLOGIN::MOVEM	T1,JBTPPN##(J)	;PRJ,PRG NRS. IN REFLAG
	DMOVEM	T2,.PDNM1##(W)
	PUSHJ	P,SETLOG##	;TURN ON JLOG
	MOVE	T1,CNFPRV##	;GET PRIVS WE WANT TO USE
	MOVEM	T1,JBTPRV##(J)	;GIVE OPERATOR ALL DEC PRIVILEGES
	MOVEM	T1,.PDCAP##(W)	;...
	TLZ	M,-1		;CLEAR ALL FLAGS FOR COMRET
	MOVEI	T1,ACTSTL##	;LENGTH OF THE ACCOUNT STRING
	JUMPE	T1,MLOGI1	;JUMP IF NONE
	HRRZ	T2,JBTPDB##+0	;NULL JOBS PDB
	MOVSI	T2,.PDACS##(T2)	;ADDRESS OF THE DEFAULT A.S.
	HRRI	T2,.PDACS##(W)	;ADDRESS OF JOBS A.S.
	BLT	T2,.PDACS##+ACTSTL##-1(W) ;FILL IN THE DEFAULT

MLOGI1:	HLLO	T1,%CNIPQ##	;GET INFLATED SEND AND RECEIVE IPCF QUOTAS
	TSO	T1,%CNIPD##	;ADD IN PID QUOTA DEFAULT
	MOVEM	T1,.PDIPQ##(W)	;SET FOR THE JOB
	MOVE	T1,[HLGPGS+1,,HLGPGS+1]	;MVPL,,MPPL
	PJRST	SETVLM##	;SET THEM
;SUBROUTINE TO CHECK IF LINE POINTS TO OPR OR CTY
;SAVES T1, USES T2
;RETURNS NONSKIP IF NOT OPR OR CTY, SKIP IF EITHER OPR OR CTY


ISOPCT:	MOVE	T2,U		;T2=ADDR OF LINE DATA BLOCK
	CAMN	T2,OPRLDB##	;SKIP IF NOT OPR
	JRST	CPOPJ1##	;YES, IT IS OPR
	SE1XCT	<MOVE T2,LDBDCH##(T2)> ;T2=LINE CHARACTERISTICS
	TRNN	T2,LDRCTY##	;SKIP IF CTY
	POPJ	P,		;NO, NEITHER OPR NOR CTY
	JRST	CPOPJ1##	;YES, IT IS CTY
	SUBTTL	COMMANDS WHICH RUN PROGRAMS

MNTCOM::
IFN FTMDA,<
	SKIPN	%SIDOL##	;MDA RUNNING?
	JRST	RECAL1		;NO. RUN UMOUNT
RUNMDA::MOVE	T1,[SIXBIT/QUEUE/]
	JRST	ARCOM
>
;FOR REMOTE USAGE OF FILE STORAGE SYSTEM
RECALL::SKIPN	[M.TD10##]	;HAVE DECTAPES?
	JRST	COMERR		;NO
RECAL1:	SKIPA	T1,[SIXBIT .UMOUNT.]	;RUN UMOUNT

CCLRUN::MOVE	T1,COMPIL##	;CUSP NAME
	JRST	ARCOM		;RUN IT


;"LOGIN" - LOGIN COMMAND

LOGDET:	JSP	T1,ERRMES
	ASCIZ	/Please KJOB or DETACH
/

CLOGIN::TLNE	P4,JLOG		;FORCE USER TO LOGOUT BEFORE
	JRST	LOGDET		; LOGGING IN ANEW.
	MOVE	T1,VIRTAL##	;AMOUNT OF FREE VIRTUAL CORE LEFT
	CAIGE	T1,LOGSIZ##	;IS THERE AT LEAST ENOUGH FOR LOGIN?
				; CUSTOMER CAN REDEFINE TO BE BIGGER THAN 2
				; WITH MONGEN DIALOG
	JRST	COR4		;NO--GO TELL USER AMOUNT OF CORE LEFT
	SE1ENT			;NEED TO ACCESS LDB
	MOVE	T1,FFAPPN##	;1,2 IF LOGGING IN
	LDB	T2,LDPLNO##	;FRCLIN?
	CAIN	T2,FRCLIN##
	JRST	LOGFRC		;YES, LOG IN THE JOB WITHOUT RUNNING LOGIN
	SKIPE	T1,REFLAG##	;REFLAG SET NON-ZERO FOR AUTOMATIC LOGIN?
	JRST	LOGREF		;YES, LOG USER IN WITHOUT RUNNING CUSP
CLOG2A:	MOVE	T1,JBTLIM##(J)	;GET OUR BATCH/LIMIT WORD
	TLNE	T1,(JB.LBT)	;DOING THIS FOR BATCON?
	S0JRST	RUNAME		;YES, DON'T CLEAR ECHO
	MOVSI	T1,LDLNEC##	;GO TO LOGIN, CLEAR ECHO
	IORM	T1,LDBDCH##(U)
	MOVEI	T1,IOSNEC##	;ALSO IN DDB
	IORM	T1,DEVIOS(F)
	S0JRST	RUNAME
RUNQUE::MOVE	P2,QUEUE##	;SET CUSP NAME
	JRST	RUNAME		;GO RUN IT

IFN FTMIC,<

;HERE TO PROCESS PLEASE COMMAND (SEE IF USER IS RUNNING MIC)
RUNPLS::SE1XCT <SKIPE	LDBMIC##(U)>	;IS HE RUNNING UNDER MIC?
RUNMIC::MOVSI	P2,'MIC'	;YES - ITS A MIC PLEASE
	JRST	RUNAME		;NO - ITS A NORMAL ONE

>
IFN FTNET,<
RUNNET::MOVE	P2,[SIXBIT/NETLDR/]
	PUSH	P,[DLYCM2]
	  PUSH	P,T2
	PUSHJ	P,RUNAMC	;RUN NETLDR
	  JFCL
	AOS	(P)		;SKIP RTURN
	POP	P,(P)
	POP	P,(P)
	SE1ENT			;'CAUSE WE PLAY WITH LDBS
	HRRZ	F,LDBDDB##(U)	;GET THE TTY'S DDB
	SKIPE	F
	PUSHJ	P,PTYDET##	;DETACH NETLDR
	PJRST	DETLDB##	;FREE THE LDB
				;*** KROCK *** NEED TO USE FRCLIN ***
>;END FTNET

RUNMAI::MOVE	P2,[M.MAIL##]	;RUN MAIL
	JRST	RUNAME
RUNLGN::SKIPA	P2,LOGTXT##	;RUN LOGIN
RUNNFT::MOVSI	P2,'NFT'	;RUN NFT
	JRST	RUNAME		;AT NORMAL START ADDRESS
RUNPIC::MOVSI	P2,'PIP'
RUNAMC::MOVEI	P1,1		;SET CCL START
;RUNAME--COMMAND WHICH RUNS CUSP OF SAME NAME
RUNAME::TLNE	P4,JLOG		;SEE IF LOGGED IN
	JRST	RUNAM1		;YES--PROCEED
	MOVE	T1,HLPPPN##	;GET P,PN FOR JOB
	MOVEM	T1,JBTPPN##(J)
	MOVSI	P4,JLOG!JNA	;CLEAR JLOG&JNA SO COMRET DOES ALL GOOD THINGS
	ANDCAB	P4,JBTSTS##(J)
RUNAM1:	PUSHJ	P,TTYATI##	;REATTACH TTY
	  JFCL
	MOVE	T1,P2		;GET CUSP NAME
	JRST	ARCOM		;FALL INTO ARCOM

; HERE ON USER DEFINED COMMANDS

PLNCOM::
;	JRST	ARCOM		;HANDLE LIKE OTHER SPECIAL RUN COMMANDS

; "R CUSPNAME CORE" - DOES "RUN SYS:CUSPNAME"

ARCOM:	MOVEI	T3,12		;MAKE SURE NO MORE ARGS SCANNED
	PUSHJ	P,CTISLC##	; BY MAKING LAST CHAR READ A BREAK
	MOVSI	T2,JLOG		;BIT TO TEST
	TDNN	T2,JBTSTS##(J)	;ARE WE LOGGED IN?
	JRST	ARCOM1		;NO--BYPASS AUTO-SAVE STUFF
	TLZE	M,SACFLG##	;NEED AN ALTERNATE CONTEXT FOR THIS COMMAND?
	PUSHJ	P,CTXATO##	;YES--HANDLE DIFFERENTLY (NEVER RETURNS)
ARCOM1:	CAME	P2,PLNTXT##	;UNLESS USER-DEFINED COMMAND,
	MOVEM	T1,JBTPRG##(J)	;STORE FILE NAME

RCOM::	MOVSI	T2,(SIXBIT /SYS/)	;READ FROM SYS DEVICE
	JRST	RUNCO2
; "RUN DEVICE:FILE[PROJ.,PROG.] (CORE)"
;DOES A CORE,GET,START ALL IN ONE
;IF CORE ARG IS MISSING, SIZE IN DIRECTORY IS USED
;JOB ON DISK OR IN CORE OR NO CORE, BUT NOT IN MIDDLE OF SWAP


RUNCOM::HLLZ	T2,SYSTAP##	;SET DEFAULT DEVICE DISK (DTA IN 10/40)
RUNCO2:	MOVEI	S,RUNJOB
RUNCM:	TLZ	M,ERRFLG	;ZAP ERROR FLAG TO START
IFN FTFDAE,<
	PUSHJ	P,CHKXTM	;SEE IF AN "EXIT" MESSAGE SHOULD BE SENT
				; TO THE FILE DAEMON AND IF SO, SEND IT
>
	MOVSI	T1,JERR		;DON'T ALLOW CONTINUE
	IORM	T1,JBTSTS##(J)	; AFTER THE CORE IMAGE HAS BEEN WIPED OUT
	SETZM	JBTPC##(J)	;THIS IS MEANINGLESS NOW, ALSO
	SKIPN	R,JBTADR##(J)	;ONLY IF JOB HAS NO CORE AT ALL,
	PUSHJ	P,GETMIN	;GET MINIMAL JOB AREA IN CORE OR DISK
	PUSHJ	P,FNDPDB##	;SETUP W
	  JRST	RUNCM1		;NO PDB
	MOVSI	T1,(PD.LGO)	;CLEAR LOGOUT UUO IN PROGRESS IN CASE
	ANDCAM	T1,.PDDFL##(W)	; JOB BOMBED OUT DURING LOGOUT
	MOVSI	T1,(JS.BPR)	;ALLOWED DESPITE FORCED PGM TO RUN ?
	TDNE	T1,JBTST2##(J)
	JRST	[ANDCAM T1,JBTST2##(J)	;YES, CLEAR FLAG
		 JRST RUNCM1]	; AND RUN WHAT HE ASKED FOR
	SKIPN	T1,.PDPGM##(W)	;PROGRAM FORCED?
	JRST	RUNCM1		;NO--CHARGE ON
	MOVEM	T1,JBTPRG##(J)
	MOVSI	T2,(PD.PGR)	;.STPGM RUN IN PROGRESS
	IORM	T2,.PDDFL##(W)	;FLAG FOR LATER USE.
	MOVEI	T2,12		;STOP READING THE COMMAND
	PUSHJ	P,CTISLC##	; BY SAYING LAST CHAR WAS A <LF>
	MOVSI	T2,'SYS'
	MOVSI	P1,PHONLY	;INHIBIT LOG NAMES
RUNCM1:	JUMPN	R,SGSET		;WAS CORE ASSIGNED IN MEMORY? IF YES, GO SCANARGS
	LDB	T1,IMGIN##	;NO CORE IN CORE, CORE ON DISK?
	JUMPE	T1,COR4		;COMPLAIN IF NONE
	SKIPLE	VIRTAL##	;NO, CORE LEFT ON DISK?
	JRST	DLYCM		;YES, DELAY COMMAND UNTIL IN CORE
	JRST	COR4		;NO, PRINT "0K CORE LEFT"
	SUBTTL	ASSIGN, DEASSIGN AND REASSIGN COMMANDS

; "ASSIGN DEV:NAME" - ASSIGN DEVICE TO JOB AND GIVE IT LOGICAL NAME

ASSIGN::JSP	T2,SAVCTX##	;SAVE THE CONTEXT OF THE JOB
	PUSHJ	P,CTXDEV	;GET FIRST ARGUMENT TO T2 "DEV"
	JUMPE	T2,NOTENF	;NO ARGUMENT TYPED IF 0
IFN FTNET,<
	PUSHJ	P,NETASG##	;SEE IF IT'S A "NODE_DEV" FORM
				; AND IF IT IS TRANSLATE IT TO "GGGNNU"
	POPJ	P,		;BAD DEVICE NAME (ERROR MSG ALREADY PRINTED)
>;END IFN FTNET
	MOVE	P4,T2		;SAVE DEVICE NAME
	PUSHJ	P,SKIPS1	;FLUSH SPACES AND TABS
	JRST	ASSG1		;END-OF-LINE IS OK
	PUSHJ	P,CTEX		;NEXT CHAR MUST BE ALPHANUMERIC
	JRST	COMERA		;NOT, THAT'S AN ERROR
ASSG1:	PUSH	P,U		;SAVE TTY LDB
	MOVE	T1,P4		;DEVICE NAME IN T1
	PUSHJ	P,DEVSRC##	;LOOK FOR THE DEVICE (ALSO LOGICAL NAME)
	  JRST	ASSG3		;NOT A PHYSICAL NAME
	JRST	ASSG4		;A SPECIFIC PHYSICAL NAME

ASSG3:	SETZ	T3,		;ANY DEVICE EXIST
	PUSHJ	P,DVSRSP##
	  JRST	ASSFAL		;NO - ERROR
	LDB	T3,DEYSPL##	;YES. SPOOL BIT
	SKIPE	DEVCHR(F)
	TDNE	T3,JBTSPL##(J)	;THIS DEV SPOOLED?
	JRST	ASSG3A		;YES, GO FAKE UP A DDB
	PUSH	P,F
	MOVEI	T3,ASSCON+ASSPRG;FLAG ASSIGNED DEV AS UNACCEPTEABLE
	PUSHJ	P,DVASRC##	;SEARCH FOR GENERIC NAME
	  JRST	ASSG3B
	POP	P,(P)
ASSG3A:	MOVEI	T2,ASSCON	;SET ASSIGNED BY CONSOLE BIT
	PUSHJ	P,ASSASG##	;GO ASSIGN DEVICE
	  JRST	ASSER8		;DEVICE NOT AVAILABLE
	JRST	ASSFIN		;SUCCESS ON ASSIGN
;HERE IF SOME DEVICE OF THIS FLAVOR EXISTS
ASSG3B:	POP	P,F		;F POINTS TO THE DDB IF "DEVX"
	TRNE	T1,770000	;IS IT DEVX:
	TRNE	T1,7700
	TRZA	T1,-1		;NO, CLEAR RIGHT HALF GO TO ASSFAL
	JRST	ASSG4		;YES, TREAT AS PHYSICAL DEVICE

;HERE WHEN A GENERIC ASSIGN FAILS

;USES 3 FLAGS IN LH OF P3
	ASF.SP==1B0	;SOMETHING HAS BEEN PRINTED
	ASF.MJ==1B1	;AT LEAST 1 ASSIGNED TO MY JOB
	ASF.RD==1B2	;RESTRICTED DEVICE

ASSFAL:	POP	P,U		;RESTORE TTY LDB
	JUMPGE	T4,NOTDEV	;NO DEVICES FOUND - GO PRINT
				;NO-SUCH-DEVICE
IFN FTNET,<MOVE	P2,T2>		;COPY NODE NUMBER
	PUSHJ	P,CHKGEN##	;IS IT A VALID GENERIC NAME?
	  JFCL			;START AT DEVLST
				;(A BAD GENERIC DEVICE SHOULD BE...
				;...FOUND ABOVE AT ASSFAL+1!!!)
	PUSHJ	P,FXSNAM##	;FIX NAME IF 2-CHAR
	MOVEI	P3,-1		;NO FLAGS AND ILL JOB NUMBER
ASSFA1:	HLLZ	T4,DEVNAM(F)	;GET GENERIC PHYSICAL NAME
	CAMN	T1,T4		;SEE IF MATCH
	PUSHJ	P,ASSFA3	;YES--DO REST OF CHECKS
	PUSHJ	P,NXDDB##	;NO--GET NEXT DEVICE
	  SKIPE	F		;CONTINUE IF END OF CHAIN
	JRST	ASSFA1		;NOT END, CHECK NEXT
	TLO	M,ERRFLG	;FLAG ERROR
	JUMPL	P3,ASSFA2	;DONE CHECK IF ANY RESTRICTED DEVICES SEEN
	MOVEI	T1,[ASCIZ "Owned by your job, rest must be mounted"]
	TLNN	P3,(ASF.MJ)	;ANY OWNED?
	MOVEI	T1,[ASCIZ "Must be mounted"] ;NO
	TLNN	P3,(ASF.RD)	;ANY RESTRICTED?
	MOVEI	T1,[ASCIZ "Owned by your job"] ;NO
	TLNN	P3,(ASF.RD!ASF.MJ) ;ANYTHING FOUND?
	JRST	NOTDEV		;NO
	JRST	ASSER6		;PRINT MESSAGE AND RETURN

ASSFA2:	TLNN	P3,(ASF.MJ)	;ANYTHING FOR ME?
	JRST	ASFA2A		;NO, CHECK RESTRICTED
	MOVEI	T1,[ASCIZ /, your job/]
	PUSHJ	P,CONMES	;NOTE YOU OWN SOME
ASFA2A:	TLNN	P3,(ASF.RD)	;ANY RESTRICTED DEVICES SEEN?
	JRST	CRLF		;NO
	MOVEI	T1,[ASCIZ/, rest of devices must be mounted/]
	PUSHJ	P,CONMES	;PRINT THE MESSAGE
	PJRST	CRLF		; CR AND RETURN
;HERE WITH F POINTING TO A DDB WE MAY WANT TO LIST
ASSFA3:	PUSH	P,T1		;SAVE DEVICE NAME
	LDB	T1,PJOBN##	;GET JOB NUMBER
IFN FTNET,<
	LDB	T2,PDVSTA##	;GET STATION
	CAME	T2,P2		;CHECK MATCH
	JRST	TPOPJ##
>
	CAMN	T1,J		;ASSIGNED TO US?
	TLO	P3,(ASF.MJ)	;YES--SET FLAG
	CAME	T1,J		;YES--IS IT OTHER JOB?
	CAIN	T1,(P3)		;SEE IF SAME
	JRST	TPOPJ##		;  AS PREVIOUS
	JUMPE	T1,ASSFA5	;CHECK IF THIS IS FREE, RESTRICTED DEVICE
	HRR	P3,T1		;  NO-PRINT
;HERE WHEN T1= JOB NUMBER TO TYPE
	TLOE	P3,(ASF.SP)	;PRINTED ANYTHING YET?
	JRST	ASFA3A		;YES--JUST ADD A COMMA
	PUSH	P,T1		;SAVE GENERIC DEVICE
IFN FTNET,<PUSH P,P2>		;AND STATION
	PUSHJ	P,INLMES	;PRINT MESSAGE
	ASCIZ	/?Assigned to job /
IFN FTNET,<POP P,P2>		;RESTORE STATION
	POP	P,T1		;RESTORE GENERIC NAME
	JRST	ASSFA4		;SKIP COMMA
ASFA3A:	PUSHJ	P,PRCOM		;ISSUE COMMA
ASSFA4:	PUSHJ	P,RADX10	;ISSUE JOB NUMBER
	JRST	TPOPJ##		;AND LOOP
ASSFA5:	MOVSI	T1,DEPRAS##	;GET RESTRICTED BIT ASSIGNMENT
	TDNE	T1,DEVSTA(F)	;DEVICE RESTRICTED?
	TLO	P3,(ASF.RD)	;YES -- SET BIT SAYING SO
	JRST	TPOPJ##		;RETURN
;PHYSICAL NAME MATCHES IF HERE

ASSG4:	MOVE	T2,DEVMOD(F)	;DEVMOD WORD
	TLNN	T2,DVDSK	;IS THIS A DISK?
	JRST	ASSG5		;NO.
	POP	P,U		;RESTORE TTY LDB ADDRESS
	PUSH	P,F		;AND SAVE DEVICE'S DDB
	PUSH	P,T1		;SAVE PHYSICAL NAME
	PUSHJ	P,CTEXT1	;GET LOGICAL NAME ARGUMENT OF "ASSIGN DEV:NAME"
	MOVE	T1,T2		;COPY TO T1 FOR DEVLG
	JUMPE	T1,ASSG8	;NO LOGICAL NAME SPECIFIED, IF 0
	PUSHJ	P,LNMTST##
	  CAIA
	JRST	ASSER7
	PUSH	P,T2		;SAVE LOG. NAME
	PUSHJ	P,DEVLG##	;SEE IF LOGICAL NAME IN USE
	  JRST	ASSG4A		;NO
	CAME	F,-2(P)		;ASS LOGNAME LOGNAME?
	PUSHJ	P,ASSCHK	;YES, SEE IF WE CAN RECLAIM SPACE
	  MOVEI	T1,LOGERR
	PUSHJ	P,CONMES
ASSG4A:	POP	P,T2		;RESTORE LOG. NAME
	POP	P,T1		;GET PHYSICAL NAME BACK
	POP	P,F		;RESTORE DDB ADDRESS
	PUSH	P,T2		;SAVE LOGICAL NAME
	MOVEI	T2,ASSCON
	PUSHJ	P,ASSASG##	;ASSIGN BY CONSOLE
	  JRST	ASSER4		;NO MORE CORE FOR DISK DDB'S
	POP	P,T1		;RESTORE LOGICAL NAME
	  JRST	ASSF2		;FINISH LOGICAL ASSIGNMENT

ASSG5:	MOVEI	T2,ASSCON
	PUSHJ	P,ASSASG##	;TRY TO ASSIGN DEVICE
	JRST	ASSER5		;ALREADY ASSIGNED TO ANOTHER JOB
	JRST	ASSFIN		;SUCCESSFULLY ASSIGNED


ASSG8:	POP	P,T2		;REMOVE GARBAGE FROM PD LIST
	POP	P,F		;RESTORE POINTER TO PROTOTYPE DSK DDB
	JRST	ASSF6
;ALREADY ASSIGNED TO ANOTHER JOB

ASSER2:	LDB	T1,PJOBN##	;GET JOB NUMBER DEVICE ASSIGNED TO
	PUSH	P,T1		;SAVE JOB NO.
	MOVEI	T1,ASSMS2	;TYPE ERROR MESSAGE
	PUSHJ	P,CONMES
	TLO	M,ERRFLG	;INDICATE ERROR
	POP	P,T1		;GET JOB NO. BACK
	JRST	DECLF		;AND TYPE IT

ASSER8:	TLOA	T2,(1B0)	;GOVE NOT ASSIGNABLE
ASSER4:	MOVEM	U,0(P)		;DISCARD LOGICAL NAME VIA NEXT POP INSTR.
ASSER5:	POP	P,U		;GET LDB ADDRESS
	JUMPGE	T2,ASSER2	;JUMP IF NOT RESTRICTED DEVICE
	MOVEI	T1,ASSMS3	;TYPE ERROR MESSAGE
ASSER6:	PUSHJ	P,ERRMES	;Y
	JRST	CRLF

ASSMS2:	ASCIZ	/?Already assigned to job /
ASSMS3:	ASCIZ	/Device not assignable/

ASSER7:	POP	P,(P)		;CLEAN UP STACK
	POP	P,(P)
	MOVEI	T1,ASSMS4
	PJRST	ASSER6		;TYPE ERROR MESSAGE
ASSMS4:	ASCIZ	/Disk logical name already exists/
;DEVICE ASSIGNED, GIVE IT A LOGICAL NAME
ASSFIN:	SETZM	DEVLOG(F)	;CLEAR LOGICAL NAME
	POP	P,U		;RESTORE TTY LDB ADDR
	PUSHJ	P,CTEXT1	;GET SECOND ARG, LOGICAL DEVICE NAME
	SKIPGE	DEVSPL(F)	;IF A SPOOLING DDB,
	JUMPE	T2,[PUSH P,DEVNAM(F)	;SAVE DEVICE NAME BEFORE GIVING BACK DDB
		PUSHJ	P,CLRDDB##	;GIVE DDB BACK TO FREE STORAGE
					; SINCE NO LOGICAL NAME
		JRST	ASSF4]		;GO PRINT "SPOOLED"

	PUSH	P,F		;SAVE DEVICE'S DDB
	PUSH	P,T2		;SAVE LOGICAL NAME
	SKIPE	T1,T2		;IS THERE A LOGICAL NAME SPECIFIED?
	PUSHJ	P,DEVLG##	;YES, SEE IF IT IS ALREADY IN USE BY THIS USER
	  JRST	ASSF3		;NO
	PUSHJ	P,ASSCHK	;YES, SEE IF WE CAN RECLAIM SPACE
	  MOVEI	T1,LOGERR	;YES, PRINT ERROR
	PUSHJ	P,CONMES
ASSF3:	POP	P,T1		;RESTORE LOGICAL NAME FOR THIS DEVICE
	POP	P,F		;DDB OF THE NEWLY ASSIGNED DEVICE
ASSF2:	MOVEM	T1,DEVLOG(F)	;STORE IN DEVICE DATA BLOCK
	MOVSI	T2,DVDIRIN	;CLEAR DIRECTORY IN CORE BIT
	ANDCAB	T2,DEVMOD(F)	;SETUP T2 WITH DEV CHARACTERISTICS FOR ASGHGH
	PUSHJ	P,ASGHGH##	;GO CHECK IF THIS DEVICE HAS
				;  INITIALIZED ANY SHARED SEGMENTS
				;  IF YES, CLEAR SEG NAMES SO NO
				;  NEW SHARING (DTA,MTA ONLY)
ASSF6:	PUSH	P,DEVNAM(F)	;SAVE PHYSICAL DEVICE NAME
	SKIPL	DEVSPL(F)	;IS THIS A SPOOLED DEVICE
	JRST	ASSF5		;NO
;HERE TO TELL USER HE HAS ASSIGNED A SPOOLED DEVICE
ASSF4:	PUSHJ	P,INLMES	;YES, TELL HIM (IN CASE HE DOESN'T KNOW)
	ASCIZ	/Spooled /
ASSF5:	POP	P,T2		;RESTORE PHYSICAL NAME
	PUSHJ	P,PRNAME	;PRINT PHYSICAL NAME IT
	PJSP	T1,CONMES	;AND RETURN

	ASCIZ	/ assigned
/

LOGERR:	ASCIZ	/%Logical name was in use, /
;SUBROUTINE TO CLEAR THE LOGICAL NAME OF A DEVICE
;ENTER WITH F SET UP
;ZEROES DEVLOG, THEN CHECKS FOR DSK/SPOOL TYPE
;IF INIT'ED, CLEAR ASSCON
;IF NOT INIT'ED, CLEAR DDB
;ENTER AT ASSCK1 TO NOT ZERO DEVLOG
;CLOBBERS T2
ASSCHK:	SETZM	DEVLOG(F)	;CLEAR OLD NAME
ASSCK1::MOVE	T2,DEVMOD(F)	;GET MOD WORD
	TLNN	T2,DVDSK	;DISK?
	SKIPGE	DEVSPL(F)	;OR SPOOL?
	SKIPA			;YES, SKIP ALONG
	POPJ	P,		;NO, JUST RETURN
	TRNN	T2,ASSPRG	;INIT'ED?
	PJRST	[PUSHJ	P,CLRDVL##	;NO, CLEAR LOGICAL NAME TABLE ENTRY
		 JRST	CLRDDB##]  ; CLEAR DDB AND RETURN
	MOVEI	T2,ASSCON	;YES, TURN OFF ASSCON
	ANDCAM	T2,DEVMOD(F)	;...
	POPJ	P,		;AND RETURN
;"DEASSIGN DEV" - DEASSIGNS DEVICE FROM CONSOLE

DEASSI::JSP	T2,SAVCTX##	;SAVE THE CONTEXT OF THE JOB
	PUSHJ	P,CTXDEV	;GET DEVICE NAME
	JUMPE	T2,DEASTY	;NO ARG. IF 0, DEASSIGN ALL BUT TTY
	MOVE	T1,T2		;DEVICE NAME
	PUSHJ	P,DEVSRD##	;SEARCH FOR DEVICE
	  JRST	DEAER1		;NOT FOUND
DEASI1:	PUSHJ	P, DEASG	;FOUND, DEASSIGN IT
	  JRST	DEAER2		;NOT PREVIOUSLY ASSIGNED
	PJRST	TTYKLQ##	;KILL TTY DDB IF NOT NEEDED
				;DEVICE DEASSIGNED

NOTDEV::
DEAER1:	SKIPE	J		;IF NOT LOGGED IN (ATTACH FOO)
	PUSHJ	P,TTYFND##
	SKIPA			;RESTORE TTY LINE DATA BLOCK
NOTDV1:	POP	P,U		;RESTORE U
	JSP	T1,ERRMES	;PRINT NO SUCH DEVICE

	ASCIZ	/No such device
/

DEAER2:	PUSH	P,F
	PUSHJ	P,TTYFND##	;RESTORE TTY LDB
	POP	P,F
	MOVE	T2,DEVNAM(F)	;PRINT PHYSICAL DEVICE NAME
	PUSHJ	P,PRNAMQ
	PUSHJ	P,TTYKLQ##	;REMOVE DDB
	JSP	T1,ERRMSN

	ASCIZ	/ wasn't assigned
/
;REASSIGN UUO
;CALL	MOVE AC,JOB NUMBER OR -1(SELF) OR 0(DEASSIGN)
;	MOVE AC+1,SIXBIT /DEVICE/
;	CALL AC,[SIXBIT /REASSIGN/]
;IF C(AC)=0, JOB HAS NOT BEEN INITIALIZED
;IF C(AC+1)=0, DEVICE NOT ASSIGNED TO THIS JOB OR DEVICE IS A TTY

REASSI::SKIPGE	T1		;SEE IF OUR JOB (-1)
	MOVE	T1,.CPJOB##	;YES--GET NUMBER
	PUSH	P,T1		;STACK JOB NUMBER TO BE REASSIGNED TO
	PUSHJ	P,GETWD1##
	MOVE	T2,T1		;DEVICE NAME
	JRST	REASS1


;"REASSIGN DEV:JOB" - REASSIGN DEVICE "DEV" TO JOB "JOB"

REASS::	PUSHJ	P,CTXDEV	;GET DEVICE NAME
	JUMPE	T2,NOTENF	;NULL NAME?
	MOVE	F,T2		;SAVE IT
	PUSHJ	P,GETJOB	;GET NEW JOB NUMBER
	  MOVE	T2,J		;NONE SPECIFIED. ASSUME SELF
	PUSH	P,T2		;PUT JOB NUMBER ON STACK, DEVICE
	MOVE	T2,F		;NAME IN T2
;ROUTINE COMMON TO REASSIGN UUO AND COMMAND
;HERE WITH T2=DEVICE AND (P)=NEW JOB (0=DEASSIGN)

REASS1:	EXCH	P1,(P)		;SAVE P1 IN STACK, P1= NEW JOB NUMBER
	PUSH	P,U		;SAVE U
	MOVE	T1,P1		;T1 = NEW JOB NUMBER
	PUSH	P,T1
	PUSHJ	P,LGLPR1##	;IS JOB NUMBER OUT OF RANGE?
	  JRST	REASE1		;YES, DO NOT REASSIGN
	JUMPE	T1,REAS1A	;JUMP IF DEASSIGN
	MOVE	T1,JBTSTS##(T1)	;NEW JOB STATUS
	TLNN	T1,JNA		;DOES NEW JOB EXIST?
	JRST	REASE1		;NO.
REAS1A:	MOVE	T1,T2
	HLL	P1,-2(P)	;GET PH ONLY BIT FROM ORIGINAL P1
	PUSHJ	P,DVCNSG##	;SEARCH FOR DEV
	  JRST	REASE2		;NOT FOUND
	NOSCHEDULE
	TLZ	F,-1		;CLEAR SYSDEV
	CAIE	F,SWPDDB##
	CAIN	F,DSKDDB##	;TRYING TO REASSIGN DSK?
	JRST	REASE7		;YES, ERROR
	LDB	T2,PJOBN##
	CAME	T2,J		;ASSIGNED TO THIS JOB
	JRST	REASE9		;NO, ERROR IF SOME OTHER
REAS1B:	MOVE	T1,DEVMOD(F)
	LDB	T3,DEYSPL##	;SPOOL BIT
	TDNN	T3,JBTSPL##(J)	;THIS JOB SPOOL THESE?
	JRST	REAS1X		;NO. NO PROBLEM
	LDB	T3,PJOBN##	;YES. HE DOES
	CAME	T3,J		;TO THIS JOB?
	JRST	REASE7		;NO. CAN'T GET IT
REAS1X:	TLNE	T1,TTYATC	;IS IT THE CONSOLE TTY?
	JRST	REASE7		;YES. CAN'T BE REASSIGNED.
;CONTINUED ON NEXT PAGE
IFN FTMDA,<
	SKIPN	0(P)		;DEASSIGN?
	JRST	REAS1C		;YES
	SKIPE	%SIMDA##	;IS MDA RUNNING?
	CAMN	J,MDAJOB##	;YES, IS HE DOING THIS?
	  JRST	REAS1C		;DON'T CHECK
	MOVSI	T1,DVCMDA	;CONTROLLED BIT
	TDNE	T1,DEVCHR(F)	;CONTROLLED?
	JRST	REASE7		;NO CAN'T REASSIGN IT
>;END IFN FTMDA
REAS1C: SKIPE	(P)		;DEASSIGN,
	CAMN	J,(P)		;OR REASSIGN TO SELF?
	JRST	REAS1D		;YES--OK
	HRRZ	T1,F		;GET DDB ADDRESS
	CAIL	T1,.FPMC	;OUT OF FUNNY
	CAIL	T1,.LPMC	;SPACE RANGE?
	JRST	REAS1D		;YES--GO AHEAD
	JRST	REASE7		;NO--CAN'T DO REASSIGN
REAS1D:	MOVE	S,DEVMOD(F)	;SAVE DEVMOD WORD
	MOVEI	T1,ASSCON	;ASSIGN IT BY
	TDNE	T1,DEVMOD(F)	;SEE IF ASSIGNED
	JUMPE	T2,REASE3	;YES--IF TO 0, ERROR
	DPB	J,PJOBN##	;PUT IN OUR NUMBER
	SCHEDULE
	SKIPN	(P)		;SEE IF DEASSIGN
	JRST	REASS7		;YES--GO DO IT
	IORB	T1,DEVMOD(F)
	CAME	J,(P)		;IS IT TO SAME JOB?
	TRNN	T1,ASSPRG	;NO. IS DEVICE INITED?
	JRST	REASS3		;NO.
	JUMPG	M,REASS4	;YES. COMMAND LEVEL?
	HRL	F,(P)		;YES. SCHEDULE RELEASE
	MOVEM	F,.JDAT+JOBFDV##
	POP	P,T2
	POP	P,U
	POP	P,P1
	TLO	M,TTYRNC	;SET TTYRNC SO JOB WILL RUN
	PJSP	T2,MSTART##	;SET UP MONITOR JOB, RETURNS AT PC C(T2)
	JSP	T1,MONSTR##	;START MONITOR JOBS, RETURNS AT UUO LEVEL
	PUSH	P,P1
	PUSH	P,U
	MOVE	J,.CPJOB##
	HLRZ	T1,.JDAT+JOBFDV##
	PUSH	P,T1
	HRRZ	F,.JDAT+JOBFDV##
REASS4:
IFN FTMPXSER,<
	PUSHJ	P,MPXDIS##
	  SKIPA
	JRST	REASS3
>
	HRRZ	T4,DEVSER(F)
	HRRZM	F,.JDAT+JOBFDV##
	MOVEI	P1,0
	PUSH	P,M		;SAVE M
REASS2:	PUSHJ	P,NXTCH##
	  JRST	REAS2A
	HRRZ	F,.JDAT+JOBFDV##
	CAIE	F,(T1)
	JRST	REASS2
	SOS	P1
	HRLM	P1,.USCTA
	PUSHJ	P,JDAADP##
	MOVE	F,(T1)
	PUSHJ	P,URELEA##
	AOJA	P1,REASS2	;INCREMENT CHANNEL AND LOOP
REAS2A:	POP	P,M		;RESTORE M
	MOVE	F,.JDAT+JOBFDV##
	MOVE	J,.CPJOB##	;CURRENT JOB NUMBER

REASS3:	MOVSI	T1,DVDIRIN	;CLEAR DIRECTORY IN CORE BIT
	ANDCAM	T1,DEVMOD(F)	;..
	EXCH	J,(P)
	CAMN	J,(P)		;IS IT TO US?
	JRST	REASS6		;YES--JUST CLEAN UP
	NOSCHEDULE
	PUSH	P,F		;PRESERVE F
	TLZ	P1,PHONLY	;ENABLE LOGICAL SEARCH
	SKIPN	T1,DEVLOG(F)	;SEE IF LOGICAL NAME
				;INUSE BY THAT JOB
	  JRST REASS5		;NO (OR NO LOG. NAME)
	PUSHJ	P,DEVCHN##	;DOES JOB HAVE THIS LOGICAL NAME INUSE?
	  SKIPA	T1,-1(P)	;NO, PHYSICAL--GET CALLER'S JOB
	JRST	REASE8		;YES--ILLEGAL
	MOVE	T2,JBTPPN##(T1)	;GET HIS P,PN
	CAME	T2,FFAPPN##	;SEE IF PRIV.
	CAMN	T2,JBTPPN##(J)	;OR SAME GUY
	JRST	REASS5		;YES--IT'S OK
	JUMPL	M,REASE8	;IF COMMAND, THAT IS ONLY WAY
	MOVE	T2,JBTSTS##(T1)	;ELSE, SEE IF
	TLNE	T2,JACCT	;PRIV. PROGRAM
	JRST	REASS5		;YES--IT'S OK

REASE8:	POP	P,F		;RESTORE F
	SCHEDULE
	MOVEI	T2,ASSCON	;WAS IT ASSIGNED
	TDNN	T2,S		;BEFORE WE STARTED
	XORM	T2,DEVMOD(F)	;NO, MAKE SURE IT IS NOT ASSIGNED
	SETZ	T1,		;0 JOB #
	TDNN	T2,S		;AGAIN, WAS IT ASSIGNED?
	DPB	T1,PJOBN	;NO CLEAR OWNER
	JRST	REASE6		;GIVE ERROR
REASS5:	POP	P,F		;RESTORE F
	DPB	J,PJCHN##	;STORE NEW JOB NUMBER IN DDB
	PUSHJ	P,TPMREA##	;RESET MAGTAPE DDB PARAMETERS
REASS6:	POP	P,J
	POP	P,U		;RESTORE ADDR OF TTY LDB
	POP	P,P1		;RESTORE P1
	TLNN	M,FLMCLV	;SEE IF UUO OR COMMAND LEVEL
	PJUMPL	M,ESTOP##	;UUO--STOP JOB
	POPJ	P,

REASS7:	PUSHJ	P,DEASG1	;DEASSIGN
	  JFCL			;IGNORE ERROR
	JRST	REASS6		;GO FINISH
REASE1:	POP	P,T1
	POP	P,U		;RESTORE ADDR OF TTY LDB
	POP	P,P1		;RESTORE P1
	TLNE	M,FLMCLV	;SEE IF UUO OR COMMAND LEVEL
	JRST	ATT4		;COMMAND--ISSUE MESSAGE
	PJRST	RTZER##		;RETURN 0 IN AC

REASE2:	MOVEI	T1,NOTDEV	;NO SUCH DEVICE
REASE5:	POP	P,T2
	POP	P,U		;RESTORE ADDR OF TTY LDB
	POP	P,P1		;RESTORE P1
	JUMPL	M,(T1)		;JUMP IF COMMAND
	PJRST	RTM1##		;GIVE ERROR CODE OF -1 IN AC

REASE9:	JUMPN	T2,REASE3
IFN FTMDA,<
	SKIPN	%SIMDA##	;MDA RUNNING
	JRST	REAS9E		;CHECK RESTRICTED BIT
	CAMN	J,MDAJOB##	;YES, IS MDA DOING THIS?
	JRST	REAS1B		;YES
	MOVSI	T1,DVCMDA	;CONTROL BIT
	TDNE	T1,DEVCHR(F)	;CONTROLLED?
	JRST	REASE3		;YES, LOSE
>;END IFN FTMDA
REAS9E:	MOVSI	T1,DEPRAS	;IS DEVICE
	TDNN	T1,DEVSTA(F)	; RESTRICTED?
	JRST	REAS1B		;NO
REASE3:	SCHEDULE
	MOVEI	T1,DEAER2	;WASN'T ASSIGNED
	JRST	REASE5

REASE7:	SCHEDULE
	EXCH	J,(P)		;FUDGE CORRECT JOB ON STACK
REASE6:	PJSP	T1,REASE5	;RETURN TO USER IF UUO
	MOVE	J,T2		;RESTORE J IF COMMAND
	MOVE	T2,DEVNAM(F)	;GET DEVICE NAME
	PUSHJ	P,TTYFND##	;RESTORE TTY LDB
	PUSHJ	P,PRNAMQ
	PUSHJ	P,TSETBI##	;CLEAR TYPE AHEAD
	MOVEI	T1,REAS6M	;PICK UP MESSAGE
	TLNN	M,FLMCLV	;SEE IF UUO OR COMMAND LEVEL
	PJRST	PHOLD##		;UUO--GO HOLD JOB
	JRST	ERRMSN		;TYPE MESSAGE IF NOT
REAS6M:	ASCIZ	/ can't be reassigned
/
	SUBTTL	ATTACH AND DETACH COMMANDS


;"ATTACH DEVNAM" -ATTACHES A PREVIOUSLY PARTITIONED DEVICE
;	NOTE-MUST BE LOGGED IN UNDER [1,2] TO DO THIS
; "ATTACH N [PROJ.,PROG.]" - ATTACH CONSOLE TO JOB N
;CHANGES ADDRESS OF TTY DEVICE DATA BLOCK STORED IN -2(P)
;BY THE COMMAND DECODER

ATTACH::PUSHJ	P,DECIN1	;GET JOB NO.
	  JRST	ATTLGN		;NOT A NUMBER--GO RUN LOGIN
	  JRST	DEVATT		;WANTS TO ATTACH A DEVICE
	PUSHJ	P,GETJB1	;VALIDATE
	MOVE	S,T2		;SAVE JOB NO.
	PUSHJ	P,PJPGNO	;GET PROJ.-PROG. NOS. ARG(IF ERROR, POP SUB LEVEL
				; OFF 1, PRINT ERROR, AND DO NOT RETURN HERE)

	MOVE	P2,T2		;DID USER TYPE IN A PROJ,PROG # IN []'S?
	MOVEM	S,T2		;RESTORE
	CAME	P2,JBTPPN##(T2)	;IS THIS THE SAME PERSON WHO DETACHED FROM
				; THIS JOB NUMBER?
	JUMPN	P2,ATT3		;NO-ERROR
	PUSH	P,U
	MOVE	S,F		;SAVE DDB ADDRESS
	MOVE	T3,T2		;SAVE TARGET JOB #
	MOVEI	T4,JOBMAX##	;UPPER LIMIT ON ITERATIONS
	SE1XCT	<LDB T2,LDPLNO##> ;UNIT # ON WHICH COMMAND APPEARED
	PUSHJ	P,CTLJB##	;IF UNIT IS A PTY, RETURN CONTROLLING JOB #
ATLCHK:	JUMPL	T1,ATTOK	;NOT A PTY, ITS COOL
	CAIN	T1,(T3)		;IS CONTROLLING JOB SAME AS TARGET JOB?
	JRST	ATT5		;YES, DISALLOW
	HRRZ	F,TTYTAB##(T1)
	PUSHJ	P,CTLJBD##	;NO, LOOK AT HIS CONTROLLER, IF ANY.
	SOJG	T4,ATLCHK	;ITERATE FOR ALL JOBS, IF NEED BE
	JRST	ATT5		;SHOULDN'T EVER GET HERE

ATTOK:	MOVE	T2,T3		;RESTORE TARGET JOB
	MOVE	F,S		;RESTORE DDB POINTER
	POP	P,U
	PUSH	P,J
	MOVE	J,T2		;CAN NEW TTY ATTACH TO NEW JOB?
	PUSHJ	P,TTYISA##
	  JRST ATT2A		;NO, NO DDB OR ANOTHER DDB ATTACHED AND NOT OPR
	JUMPN	T1,ATTNL	;IF THERE IS SOMEONE THERE MUST BE OPR TO BE OK
				;HENCE NO LOGIN REQUIRED
	MOVE	T1,(P)		;OLD JOB NUMBER IN CASE NOT CTY OR OPR
	MOVE	T1,JBTPPN##(T1)	;PPN IF OLD JOB
	CAMN	T1,FFAPPN##	;NO SKIP IF [1,2]
	JRST	ATTNL		;[1,2] DOESN'T NEED LOGIN
	PUSHJ	P,ISOPCT
	  CAMN P2,T1		;SKIP IF CURRENT JOB NOT SAME PPN AS OBJECT JOB
	JUMPN	T1,ATTNL	;YES, CURRENT JOB DOESN'T REQUIRE LOGIN
	JUMPN	P2,ATTLG1	;MUST RUN LOGIN IF TARGET PPN SPECIFIED
	MOVE	P2,JBTPPN##(J)	;GET TARGET PPN
	CAMN	P2,T1		;IS IT A MATCH?
	JRST	ATTNL		;YES, IT'S A WIN
ATTLG1:	POP	P,J		;NO, RESTORE OLD JOB #
ATTLGN:	TLNN	P4,JLOG
	JRST	ATTDET		;ALREADY DETACHED
	SKIPN	[EXP M.CTX##]	;CONTEXT SERVICE LOADED?
	JRST	[PUSHJ	P,DETAC1;NO--DETACH JOB
		 JRST	ATTDET]
	TLO	M,SACFLG##	;CAUSE AN AUTO-SAVE TO HAPPEN
	PJRST	RUNLGN		;GO RUN LOGIN
ATTDET:	SETZ	J,		;CLEAR SO WILL GET A NEW JOB #
	MOVE	T2,LOGTXT##	;MAKE IT LOOK LIKE A LOGIN COMMAND
	MOVE	P3,[XWD UNQTAB,DISP##] ;P3=UNIQUENESS INFO PLUS LOC OF DISPATCH TABLE
	MOVE	P4,[XWD-DISPL##,COMTAB##] ;P4=LENGTH, LOC
	MOVE	P,.CPISF##	;RESTORE P TO VALUE AT COMGO
	XJRST	[MCSEC1+COM1A]	;*** CALL LOGIN TO VALIDATE THE ATTACH
ATTNL:	JUMPN	P2,ATTNL1	;ALWAYS OK IF PPN WAS TYPED
	MOVE	P2,JBTPPN##(J)	;GET TARGET'S PPN
	MOVE	T1,(P)		;GET STARTING JOB NUMBER
	CAMN	P2,JBTPPN##(T1)	;DO THEY MATCH?
	JRST	ATTNL1		;YES, IT'S LEGAL AFTER ALL
	PUSHJ	P,SKIPS1	;SEE IF AT EOL
	  JRST	NOTENP		;NOT ENOUGH TYPED IF NO PPN
	JRST	COMERP		;INVALID PPN TYPED
ATTNL1:	PUSHJ	P,TTYATT##	;NO, ATTACH TTY
	  JRST	ATT2A		;ERROR CAN'T ATTACH
	EXCH	J,0(P)		;GET OLD JOB #
	MOVSI	T1,JNA		;IS JOB NUMBER
	TDNE	T1,JBTSTS##(J)	; ASSIGNED?
	PUSHJ	P,DETMSG	;NO. TYPE MESSAGE
	POP	P,J		;RESTORE J
	JRST	TTYFND##	;ATTACHED. GO SET UP OUTP. BYTE PTR.
DEVATT:	PUSHJ	P,SETLGL	;SEE IF OPR OR [1,2]
	  JRST	ATTLGN		;NOT PRIV'ED--GO RUN LOGIN
	PUSHJ	P,CTXDEV	;GET DEVICE ARGUMENT
IFN FTMP,<
	PUSHJ	P,CPUFND##	;IS THE ARGUMENT A CPU NAME?
	  CAIA			;NO, DEVICE OR ERROR
	JRST	CPUATT##	;YES, ATTACH THE CPU
>
	MOVE	S,T2		;SAVE DEVICE NAME ACROSS CALL TO SAVCTX
	JSP	T2,SAVCTD##	;THIS MAY CALL NETSER, MUST BE A JOB.
	MOVE	T1,S		;YES-SET UP DEVICE NAME
	PUSHJ	P,DEVSRG##	;SEARCH FOR DEVICE
	  JRST	ATT7		;SEE IF DUAL-PORTED DISK OR IN SYSDET CHAIN
	MOVE	T2,DEVMOD(F)
	TLNE	T2,DVDSK	;DISK?
	JRST	ATT7		;YES, DO IT DIFFERENTLY

	SKIPN	DEVCHR(F)	;IS IT A "FAKE" DDB?
	PJRST	DTATSP		;YES, CAN'T ATTACH SPOOLED DEVICE
	TRNN	T2,ASSCON	;WAS DEVICE DETACHED?
	PJRST	ATT6		;NO ERROR
	LDB	T1,PJOBN##	;GET JOB NUMBER
	JUMPN	T1,ATT6		;IS IT = 0?
	SETZM	DEVLOG(F)
	DPB	J,PJOBN##	;SET JOB NUMBER
	PJRST	TPMRES##	;RESET MAGTAPE DDB PARAMETERS
ATT2A:	POP	P,J		;REMOVE JUNK FROM STACK
	MOVE	T2,DEVNAM(F)	;PRINT PHYSICAL NAME
	PUSHJ	P,PRNAMQ
	JSP	T1,ERRMSN
	ASCIZ	/ already attached
/

ATT5:	MOVE	F,S		;RESTORE DDB POINTER
	POP	P,U
ATT3:	JSP	T1,ERRMES
	ASCIZ	/Can't attach to job
/

ATT6:	JSP	T1,ERRMES
	ASCIZ	/Wasn't detached
/
;HERE TO ATTACH A DISK UNIT
ATT7:	PUSHJ	P,ATTDSK##	;TRY TO PUT IT ON-LINE
	  JRST	ATT8		;NOT DOWN OR NO SUCH UNIT
	  JFCL			;DOESN'T RETURN HERE WHEN CALLED AT UUO LEVEL
	POPJ	P,		;UNITS IS NOW UP

ATT8:	TLZE	U,400000	;IS IT A DSK?
	JRST	NOTDEV		;NO, "NOT A DEVICE"
	JRST	COMERA		;YES, "ATTACH DEV?"
;GETJOB--ROUTINE TO SCAN COMMAND FOR JOB NUMBER
;RETURNS:	CPOPJ IF NULL WITH T2=THIS JOB (IF ANY) OR 0.
;	CPOPJ1 IF OK WITH T2=JOB SPECIFIED, T3=JOBSTS
;GIVES ERROR (NO RETURN) IF DECIMAL IMPROPER OR NOT A JOB.
GETJOB::PUSHJ	P,DECIN1	;READ DECIMAL
	  POPJ P,		;NULL--RETURN
	  JRST COMERP		;NOT DECIMAL--ERROR
	AOS	(P)		;GOOD--ADVANCE RETURN
GETJB1:	MOVE	T1,T2		;T1=JOB NUMBER
	PUSHJ	P,LGLPRC##	;SKIP IF LEGAL JOB NUMBER
	  JRST	ATT1P		;NO - FAIL
	MOVE	T3,JBTSTS##(T2)	;GET TARGET JOB STATUS
	TLNE	T3,JNA		;SEE IF JOB NUMBER
	POPJ	P,		;YES--RETURN
	POP	P,T1		;NO--CLEAN UP STACK
ATT4:	JSP	T1,ERRMES
	ASCIZ	/Not a job
/

ATT1P:	POP	P,T1		;CLEAN UP STACK
ATT1:	JSP	T1,ERRMES
	ASCIZ	/Illegal job number
/
;"DETACH" - DETACH CONSOLE FROM JOB
;"DETACH CPUNAM" - DETACHES CPU FROM THE SYSTEM SOFTWAREWISE
;"DETACH DEVNAM" - DETACHES DEVICE FROM THE SYSTEM SOFTWAREWISE

DETACH::PUSHJ	P,CTXDEV	;GET ARGUMENT
	JUMPE	T2,DETAC1	;ONLY "DET" TYPED
	MOVE	S,T2
	PUSHJ	P,SETLGL	;SEE IF OPR OR [1,2]
	  JRST	COMERA		;NOT LEGAL
	PUSHJ	P,SAVE1##	;SAVE P1
IFN FTMP,<
	MOVE	T2,S		;RESTORE ARGUMENT
	PUSHJ	P,CPUFND##	;SEE IF ARGUMENT IS A CPU NAME
	  CAIA			;NOT, A DEVICE OR AN ERROR
	JRST	CPUDET##	;A CPU, DETACH IT
>
	JSP	T2,SAVCTD##	;AMAY CALL NETSER
	MOVE	T1,S		;YES-SET UP DEVICE NAME
	PUSH	P,U		;SAVE ADDR OF TTY LDB
	PUSHJ	P,DEVPHY##	;SEARCH FOR DEVICE
IFE FTDUAL,<
	  JRST	NOTDV1		;DEVICE NOT FOUND
>
IFN FTDUAL,<
	JRST	DETAC3
>
	MOVE	T2,DEVMOD(F)	;CHECK TO SEE IF THIS IS DSK
	TRNE	T2,ASSPRG	;ASSIGNED BY PROGRAM?
	JRST	NOTDT1
	TLNE	T2,DVDSK	;TRYING TO TAKE DOWN A DISK?
	JRST	DETAC3		;YES, DO IT DIFFERENTLY

	TLNE	T2,DVDSK!DVTTY	;IS IT THE DSK OR A TTY?
	JRST	NOTDV1		;YES-PRINT ERROR MSG.
	MOVEI	T2,ASSCON	;FOUND-SET UP ASSIGNED BY CONSOLE
	PUSHJ	P,ASSASG##	;TRY TO ASSIGN
	JRST	ASSER5		;CAN'T ASSIGN
	SKIPGE	DEVSPL(F)	;SPOOLED?
	JRST	DETAC2		;YES
	TLNE	F,SYSDEV	;IS THIS SYSTEM DEVICE?
	JRST	NOTDV1		;YES-PRINT ERROR MSG.
	MOVEI	T1,0		;NO. SET JOB NUMBER TO ZERO
	DPB	T1,PJOBN##	; ..
	JRST	UPOPJ##		;RESTORE U AND RETURN SUCCESSFUL

DETAC1:	TLNN	P4,JLOG		;CAN'T DETACH
	JRST	ATT4		;IF NOT LOGGED IN
	PUSHJ	P,DETMSG
DETBYE:	SE1XCT	<HRRZ F,LDBDDB##(U)> ;IS THERE A JOB ATTACHED?
	JUMPE	F,CPOPJ##	;IF NONE, DONE NOW
	JRST	TTYDET##	;YES. GO DETACH IT FROM LINE

DETMSG:	PUSHJ	P,INLMES	;TELL USER WHERE HE WAS
	ASCIZ	/From job /
	PJRST	PJOB
DETAC2:	PUSHJ	P,DTATSP	;SAY DEVICE IS SPOOLED
	PUSHJ	P,CLRDDB##	;DEASSIGN THE DEVICE
	PJRST	UPOPJ##		;POP U AND RETURN
DTATSP:	PUSHJ	P,PRQM		;CAN'T DETACH/ATTACH A SPOOLED DEVICE
	MOVE	T2,DEVNAM(F)	;GET DEV NAME
	PUSHJ	P,PRNAME	;TYPE IT
	PUSHJ	P,INLMES
	ASCIZ	/ is spooled/
	POPJ	P,
;HERE TO DETACH A DSK
DETAC3:	POP	P,U
	PUSHJ	P,DETDSK##	;TRY TO DETACH
	  JRST	NOTDEV		;NOT A DSK
	  JRST	COMERA		;CANT DETACH
	POPJ	P,		;WIN

NOTDT1:	POP	P,U		;RESTORE U
	PJSP	T1,ERRMES	;TYPE MESSAGE
	ASCIZ	/Device in use
/
	SUBTTL	DATASET CONNECT & SYSTEM START


;DATAPHONE RESPONSE COMMANDS PHONIED UP BY SCNSER ON DATAPHONE INTERRUPTS

BYECOM::TLNN	P4,JLOG		;LOGGED IN?
	  JRST	BYECM1		;NO-LEAVE ALONE
	LDB	T1,JBYLTM##	;GET JOBS TIME LIMIT
	JUMPN	T1,BYECM1	;JUMP IF ALREADY SET
	MOVEI	T1,M.DTLS##	;GET DEFAULT DETACH TIME LIMIT
	IMUL	T1,TICSEC##	;INTO JIFFIES
	DPB	T1,JBYLTM##	;STORE NEW LIMIT
	MOVSI	T1,(JB.LTL)	;GET DETACHED LIMIT SET
	IORM	T1,JBTLIM##(J)	;REMEMBER FOR LATER
BYECM1:	PJRST	DETBYE		;THEN DETACH IT



HELLO::	MOVE	P2,INITIA##	;GO RUN THE
	PJRST	RUNAME		;HELLO PROGRAM



;SYSTEM RESTARTED MESSAGE - COMMAND PHONIED UP BY SCNSER WHEN
; CALLED FROM IOGO

RESTRT::PUSHJ	P,CRLF		;START A NEW LINE, AND
	MOVEI	T1,CONFIG##	;TYPE OUT CONFIGURATION NAME
	PUSHJ	P,CONMES	;"
	PUSHJ	P,PRSPC		;A SPACE

;	PJRST	DAYTIM		;FALL INTO DAYTIME
	SUBTTL	DAYTIME COMMAND

;DAYTIME - PRINT DAY, DATE, TIME, CRLF


DAYTIM::SKIPE	.UONCE##	;IF USER-MODE MONITOR,
	PUSHJ	P,USRDTM##	;SETUP THE VALUES WE NEED
	PUSHJ	P,PRDOFW	;PRINT DAY OF WEEK
	PUSHJ	P,PRSPC		;SPACE
	PUSHJ	P,DATIME	;TYPE DATE AND TIME
	PJRST	CRLF		;ADD CRLF


;DATIME - PRINT DATE AND TIME (NO CRLF)

DATIME::SKIPE	.UONCE##	;IF USER-MODE MONITOR,
	PUSHJ	P,USRDTM##	;SETUP THE VALUES WE NEED
	PUSHJ	P,PRDAYD	;PRINT DAY AND DATE
	PUSHJ	P,PRSPC		;SPACE
	PJRST	PRNOW		;FINISH OFF WITH TIME

;PRDAYD - PRINT DATE, TIME (NO CRLF)

PRDAYD::MOVE	T1,LOCDAY##	;PRINT DAY
	PUSHJ	P,RADX10
	MOVE	T1,LOCMON##
	MOVE	T1,MONTAB##-1(T1)	;MONTH
	DPB	T1,[POINT 21,DAMESS##,27]
	MOVEI	T1,DAMESS##
	PUSHJ	P,CONMES	;PRINT DAY
	MOVE	T1,LOCYER##
	SUBI	T1,^D1900
	PJRST	RADX10		;PRINT YEAR


;SUBROUTINE TO PRINT TIME OF DAY, CRLF

PRDTIM::MOVE	T1,TIME##	;PRINT TIME OF DAY
PRTIME::PUSHJ	P,PRTIM		;PRINT TIME AS HH:MM:SS(NO CRLF)
	PJRST	CRLF		;AND ADD CRLF
;SUBROUTINE TO PRINT DAY OF WEEK
PRDOFW::HLRZ	T1,DATE##	;GET NBS DATE
	IDIVI	T1,^D7		;GET DAY OF WEEK
	MOVE	T1,DAYTAB##(T2)	;GET THE NAME OF THAT DAY
	PJRST	CONMES		;PRINT THAT

;SUBROUTINE TO PRINT TIME WITH AM/PM
PRAMPM::MOVE	T2,TICMIN##	;GET TICKS/MINUTE
	IMULI	T2,^D60*^D12	;COMPUTE PER HOUR
	CAMGE	T1,T2		;PM?
	 JRST	PRAM.1		;NO--AM
	MOVE	T3,TICMIN##	;GET TICKS/MINUTE AGAIN
	IMULI	T3,^D60*^D13	;COMPUTE FOR 13 HOURS
	CAML	T1,T3		;SEE IF 12:00 TO 12:59:59
	 SUB	T1,T2		;NO--MAKE 1:00 TO 11:59:59
	PUSHJ	P,PRTIMS	;PRINT TIME
	MOVEI	T1,[ASCIZ/ PM/]	;GET SUFFIX
	PJRST	CONMES		;TYPE AND RETURN
PRAM.1:	PUSHJ	P,PRTIMS	;PRINT THE TIME
	MOVEI	T1,[ASCIZ/ AM/]	;GET SUFFIX
	PJRST	CONMES		;TYPE AND RETURN

;This routine is like PRTIM except it always types time as
;HH:MM:SS with leading zeros.
PRTIMS::MOVE	T2,TICSEC##	;ADD 1/2 TICKS/SEC FOR ROUNDING
	LSH	T2,-1
	ADD	T1,T2
	IDIV	T1,TICMIN##	;FORM MINUTES
	PUSH	P,T2		;SAVE REMAINDER IN JIFFIES
	IDIVI	T1,^D60		;HOURS, MINUTES IN T1,T2
	PUSHJ	P,RADX10
	JRST	PR0		;ENTER PRTIM
	SUBTTL	BIG BEN

;ROUTINE TO PRINT THE MONITOR NAME, SYSTEM UPTIME AND CURRENT
;DATE/TIME
;CALL:	MOVEI	U,LDB ADDRESS
;	PUSHJ	P,BIGBEN
;	<RETURN HERE ALWAYS>

BIGBEN::SKIPGE	DEBUGF##	;DEBUGGING?
	POPJ	P,		;KEEP QUIET
	PUSHJ	P,INLMES
	ASCIZ/
Monitor /
	MOVEI	T1,CONFIG##
	PUSHJ	P,CONMES	;PRINT MONITOR NAME
	PUSHJ	P,CRLF		;END THE LINE
	PUSHJ	P,INLMES
	ASCIZ/System uptime /
	MOVE	T1,SYSUPT##	;GET SYSTEM UPTIME
	PUSHJ	P,PRTIME	;PRINT IT
	PUSHJ	P,INLMES
	ASCIZ .Current date/time .
	PUSHJ	P,DAYTIM	;PRINT DATE TIME
	PJRST	CRLF		;END LINE AND RETURN
	SUBTTL	RUNTIME ROUTINE (TIME## COMMAND)

;"TIME (JOB NO.)" - PRINT TOTAL AND INCREMENTAL RUNNING TIME FOR A JOB
;FOLLOWED BY KILO-CORE TICKS
;"TIME 0" IMPLIES RUNTIME FOR NULL JOB
;	IF NO JOB NO. GIVEN-TIME WILL BE FOR CURRENTLY LOGGEN IN JOB NO.


RUNTIM::PUSHJ	P,SAVJW##	;SAVE J (W GETS A RIDE)
	PUSHJ	P,GETJOB	;GET JOB NO. ARG.
	JRST	RUN1		;NO ARG. GIVEN - LOGGED IN?
	MOVE	J,T2		;SETUP DESIRED JOB NUMBER
	JRST	PRTTIM		;PRINT TOTAL RUN TIME+KIL-CORE-SEC
				; BUT DO NOT PRINT INCREMENTAL
RUN1:	MOVSI	T1,JLOG		;IS JOB LOGGED IN?
	TDZN	T1,JBTSTS##(J)	;TEST JOB STATUS BITS AND CLEAR T1 ALWAYS
	JRST	NOTENF		;NO, NEED MORE ARGUMENTS

	EXCH	T1,.PDRTM##(W)	;CLEAR INCREMENTAL TIME
	PUSHJ	P,PRTIME	;PRINT TIME SINCE LAST TIME COMMAND PLUS CRLF
PRTTIM:	PUSHJ	P,FNDPDB##	;ADDRESS OF PDB FOR JOB
	  TDZA	T1,T1		;NO PDB -- GIVE 0
	MOVE	T1,.PDTTM##(W)	;GET TOTAL ACCUMULATED TIME
	JUMPE	W,PRTIME	;EXIT IF NO PDB
	PUSHJ	P,PRTIME
	PUSHJ	P,INLMES	;PRINT "J*CPUSEG=
	ASCIZ	/kilo-core-sec=/
	MOVE	T1,.PDKCT##(W)	;PRODUCT OF NO. OF J CORE* NO. OF JIFFIES RUN

;SUBROUTINE TO PRINT SECONDS, CRLF

	IDIV	T1,TICSEC##	;CONVERT TO SECONDS FROM JIFFIES
	PJRST	DECLF		;PRINT IN DECIMAL, ADD CRLF
	SUBTTL	SEND COMMAND


;ROUTINE TO SEND A LINE OF INFORMATION TO ANOTHER TTY, OR
; TO BROADCAST IT TO ALL TTY'S


SEND::	PUSHJ	P,SAVE2##
	PUSHJ	P,CTEXT1	;GET ARGUMENT DEVICE OF SEND
	JUMPE	T2,NOTENF	;MUST BE ONE
IFN FTNET,<
	SETZ	W,		;CLEAR NODE POINTER
	CAIE	T3,"_"		;TERMINATED BY _
	JRST	SEND0		;NO, CONTINUE NORMAL
	NETDBJ			;INTERLOCK THIS PART
	MOVE	T1,T2		;COPY THE NODE NAME
	PUSHJ	P,CVTOCT##	;CHECK FOR A NUMBER
	  MOVE	T1,T2		;MUST BE A NODE NAME
	SKIPE	T1		;NOT ZERO
	PUSHJ	P,SRCNDB##	;FIND THE NODE DATA BLOCK
	  JRST	[JSP	T1,ERRMES	;NODE DOES NOT EXIST
		 ASCIZ	/Node does not exist
/]
	HLRZ	W,(W)
	SE1ENT
	JRST	SENDA		;DO A PSEUDO SEND ALL
SEND0:> ;END IFN FTNET
	SE1ENT			;ENTER SECTION 1
	MOVE	S,T1		;SAVE WHAT USER TYPED
	MOVS	T1,T2		;GET IT SWAPPED FOR COMPARES
	CAIN	T1,(SIXBIT /JOB/)	;PARTICULAR JOB NUMBER?
	JRST	SENDJ		;YES. GO FIND IT
	CAIN	T1,(SIXBIT /ALL/)	;BROADCAST TO ALL TTY'S?
	JRST	SENDA		;YES.
	HRRZ	P1,T1		;SAVE WHAT WAS TYPED
	PUSH	P,U		;SAVE LINE ADDRESS OF SENDER
	MOVE	T1,T2		;GET DEVICE NAME TO SEARCH FOR
	PUSHJ	P,DEVNFS##	;TRY TO MAKE SENSE OF DEVICE NAME
	  JRST	SEND03		;NOT A DEVICE, TRY OCTAL LINE NUMBER
	MOVE	T2,DEVMOD(F)	;GET THE BITS WORDS
	TLNE	T2,DVTTY	;IS IT A TTY?
	TLNE	T2,DVDSK	;WATCH OUT FOR NUL:
	JRST	SENDE2		;TSK TSK NOT A TTY AT ALL
	MOVE	U,DDBLDB##(F)	;GET ADDRESS OF LDB
	PUSHJ	P,TTYKLQ##	;STOMP AN DDB IF NEED BE
	JUMPN	U,SENDT		;TO DO THE SEND
	JRST	SENDE2		;DUH? ON SECOND THOUGHT, DON'T DO THE SEND
;UNRECOGNIZABLE DEVICE, TRY FOR A STRAIGHT OCTAL LINE NUMBER

SEND03:	TRNE	T1,-1		;IF MORE THAN 3 CHARACTERS
	JRST	SENDE1		;THEN IT'S NO TTY THAT WE KNOW OF
	HLRZ	T1,T1		;POSITION "UNIT" NUMBER IN RH
	HRLI	T1,'TTY'	;GENERIC DEVICE TYPE
	PUSHJ	P,TTYALL##	;SEE IF IT MAKES ANY SENSE NOW
	  JRST	SENDE1		;USER MAKES NO SENSE WHATEVER
;	JRST	SENDT		;AH HA!  WE HAVE A VALID TTY
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
SENDT:
IFN FTNET,<
	SKIPGE	LDBREM##(U)	;IF VTM+ HOSTED AWAY
	JRST	SENDE1		;DON'T SEND
>;END IFN FTNET
	MOVE	T1,0(P)		;SEE IF EITHER GUY IS THE OPR
	CAME	U,OPRLDB##	; ..
	CAMN	T1,OPRLDB##	; ..
	JRST	SENDT1		;YES. DONT BUSY CHECK
	MOVE	T1,LDBDCH##(U)	;NO. SEE IF DEST IS AT COMMAND LEVEL
	HLR	T1,LDBBY2##(U)	;OR HAS ALLOWED SENDS
	TDNE	T1,[LDLCOM##,,L2LSND##]	;OK TO SEND?
	JRST	SENDT1		;YES.  OK TO SEND
	EXCH	U,(P)		;RESTORE U
	PUSHJ	P,SETLGL	;DOESN'T WANT A SEND. OVERRIDE?
	  JRST	SNDBSY		;NO.  HE'S BUSY.
	EXCH	U,(P)		;POINT TOGETHER

SENDT1:	SKIPN	%SIOPR##	;YES, IS ORION RUNNING?
	JRST	SENDT3		;NO, SEND TO OPR THE OLD WAY
	CAIE	P1,'OPR'	;SENDING TO OPERATOR?
	JRST	SENDT3		;NO, NORMAL SEND
	POP	P,U		;SAVE U
	JSP	T2,SAVCTD##	;AND SOME CONTEXT
	PUSHJ	P,SAVE4##	;AND SOME REGS
	MOVE	T2,LDBTIC##(U)	;GET NUMBER OF CHARS IN THE USER'S MESSAGE
	ADDI	T2,4+1		;ROUND OFF (PLUS 1 FOR BELL IN SNOTXS)
	IDIVI	T2,5		;	 TO # WORDS
	MOVSI	P4,1(T2)	;FIGURE TEXT BLOCK LENGTH
	MOVE	P1,T2		;GET # OF WORDS
	IMULI	P1,5		;FIGURE # OF CHARS THAT CAN FIT IN THOSE WORDS
	SOS	P1		;LEAVE ROOM FOR THE ASCIZ IN SNDTXS
	ADDI	T2,5+1+<1+1>+<1+1>+<1+2> ;5 - GALAXY HEADER, 1 - TEXT BLOCK HEADER
				;  2 - FUNCTION BLOCK,   2 - NODE BLOCK
				;  3 - TTY NAME BLOCK
	HRLZ	P2,T2		;SIZE OF THE BLOCK
	PUSHJ	P,GTFWDC##	;GET SOME FUNNY SPACE
	  JRST	[PUSH P,U	;CAN'T, SO SEND IT THE OLD WAY
		 JRST SENDT3]
	PUSHJ	P,SSEC0##	;DO THIS IN SECTION 0
	HRR	P2,T1		;SAVE ADDRS OF SPACE GOTTEN
	MOVSI	T2,(T1)		;FROM FIRST WORD OF SPACE
	HRRI	T2,1(T1)	;TO NEXT WORD OF SPACE
	HLRZ	T3,P2		;LENGTH OF THE SPACE
	ADDI	T3,(T1)		;WORD JUST PAST END OF SPACE
	SETZM	(T1)		;CLEAR THE FIRST WORD
	BLT	T2,-1(T3)	;AND CLEAR THE WHOLE MESSAGE
	HLLZ	T2,P2		;COPY THE MESSAGE LENGTH
	HRRI	T2,.IPCGM##	;SETUP THE MESSAGE TYPE
	MOVEM	T2,(T1)		;.MSTYP - LEN,,TYPE
	MOVSI	T2,(WT.SND)	;INDICATE SEND OPR
	CAMN	U,OPRLDB##
	IORM	T2,3(T1)	;IN MESSAGE TO ORION
	MOVEI	P3,5(T1)	;AIM P3 AT THE 'CURRENT' BLOCK
;
;	P2/	LEN,,ADRS OF THE MESSAGE
;	P3/	ADRS OF 'CURRENT' BLOCK
;
	DMOVE	T1,[XWD	2,.WTUFC ;GET THE FIRST DATA BLOCK HEADER
		   EXP	%QWTO##-.GTQFT##] ;A FUNCTION BLOCK - WTO FUNCTION
	DMOVEM	T1,0(P3)	;STORE 'EM
	ADDI	P3,2		;STEP TO NEXT BLOCK
	AOS	4(P2)		;COUNT THE ARGUMENT BLOCKS
IFN FTNET,<
	HLLZ	T1,S		;NODE NUMBER
	SKIPE	T1
	PUSHJ	P,CVTOCT##	;CONVERT
	  MOVE	T1,JBTLOC##(J)	;USE WHERE LOCATED
	PUSHJ	P,[NETDBJ
		   JRST NODE.S##]
	  JRST SENDT2		;NO NODE, DON'T INCLUDE A NODE BLOCK!
	HLRZ	T1,NDBSNM##(W)
	MOVE	T2,(T1)		;GET THE DESIRED NODE NAME
	MOVE	T1,[2,,.WTDES]	;AND THE ARGUMENT BLOCK HEADER WORD
	DMOVEM	T1,0(P3)	;MAKE THIS BLOCK
	ADDI	P3,2
	AOS	4(P2)		;ONE MORE ARG BLOCK
>
SENDT2:	PUSH	P,U		;SAVE U
	PUSHJ	P,SENDH0	;GO GENERATE SENDER'S TTY NAME
	MOVE	T1,[3,,.WTTTY]	;GET THE ARGUMENT BLOCK HEADER WORD
	DMOVEM	T1,0(P3)	;BUILD PART OF THE BLOCK
	PUSHJ	P,GTNTS0##	;GET [NODE #,,LINE #] IN T1
	  SETOM	T1		;TTY NOT CONNECTED
	MOVEM	T1,2(P3)	;FINISH .WTTTY ARG BLOCK
	POP	P,U		;GET ORIGINAL U BACK
	ADDI	P3,3		;POINT TO NEXT BLOCK
	AOS	4(P2)		;COUNT THIS ARG BLOCK
;BUILD THE TEXT BLOCK
	HRRI	P4,.WTTXT
	MOVEM	P4,0(P3)
	MOVEI	P4,%SIOPR	;WHO GETS THE MESSAGE
	MOVEI	T4,1(P3)
	AOS	4(P2)		;ONE MORE ARG BLOCK
	JRST	SNDTXS
;HERE TO DO THE 'OLD STYLE' SEND OPR COMMAND
SENDT3:	S0PSHJ	SENDHD		;SEND HEADER (CRLF, SEMI, TTY NAME)

SEND1:	PUSHJ	P,SNDTYI	;GET CHARACTER TO SEND OUT
	  JRST SEND2		;END OF LINE
	PUSHJ	P,COMTYO##	;SEND IT (DEST IN LINE)
	JUMPN	T3,SEND1	;LOOP FOR MORE

SEND2:	PUSHJ	P,SNDEOL	;SEND CRLF, MAYBE DOT TO DEST
				;RESTORE STACK, GET SENDER LDB
	PJRST	UPOPJ##		;AND RETURN FROM SEND COMMAND
;MORE OF SEND COMMAND


SENDJ:	PUSHJ	P,GETJOB	;GET DESIRED JOB NUMBER
	  JRST NOTENF		;MUST HAVE AN ARG
	PUSH	P,U		;OK. SAVE SENDER'S LDB
	HRRZ	F,TTYTAB##(T2)	;GET TTY DDB OF DEST JOB
	JUMPE	F,SENDE1	;MUST BE ONE
	MOVE	U,DDBLDB##(F)	;GET LDB ADDRESS
	JUMPN	U,SENDT		;AND GO SEND IT (IF NOT DETACHED)
SENDE1:	POP	P,U		;OOPS. NO SUCH GUY. GET SENDER
	JSP	T1,ERRMES	;AND GIVE HIM THE BAD NEWS
	ASCIZ	/No such tty
/

SENDE2:	POP	P,U
	JSP	T1,ERRMES	;RESTORE THE STACK
				; AND GRIPE AT THE USER
	ASCIZ	/Not a tty
/
SENDA:	PUSHJ	P,SETLGL	;LEGAL? (OPR OR [1,2])
	  JRST	COMERA		;NOT LEGAL
	SKIPE	SNDCTR		;SKIP IF SEND BUFFER IS FREE
	JRST	DLYCM1		;NOT FREE, DELAY THE COMMAND
	PUSH	P,U		;YES. STACK LDB ADR OF OPR
	MOVE	T1,SNDPTR	;PICK UP POINTER
	MOVEM	T1,SNDTMP	;SAVE IN TEMP
	MOVEI	T1,SNDTYO	;INTERCEPT TYPEOUT
	MOVEM	T1,.CPTOA##	;..
	MOVEI	T1,^D85		;PRESET QUOTA
	MOVEM	T1,SNDCNT	; SO WE DON'T WIPE
				; COMCON
	S0PSHJ	SENDHD		;SEND THE HEADER
	MOVEI	T1,CCTYO##	;RESTORE
	MOVEM	T1,.CPTOA##	;.CPTOA
	MOVEI	P1,^D85

SENDA3:	PUSHJ	P,SNDTYI	;GET A CHAR FROM SENDER
	  JRST SENDAX		;NO MORE.
	MOVE	T1,T3		;COPY CHAR
	SOSL	P1
	PUSHJ	P,SNDTYO	;SEND TO ALL LINES
	JRST	SENDA3		;LOOP TILL END OF LINE

SENDAX:	MOVEI	T1,FLLFLG##	;MARK SPOT FOR
	IDPB	T1,SNDTMP	;CRLF
	MOVSI	T1,LOLSAP##	;SEND ALL PENDING
	IDPB	T1,SNDTMP	;MAKE ASCIZ
	AOS	SNDCTR		;ALLOW A LITTLE SLOP TIME
	AOS	SNDCTR		;TO BE SURE THE MESSAGE GETS OUT
	MOVNI	U,1		;LOOP OVER ALL LINES
	JRST	SENDX1		;..
SENDX2:	LDB	U,LDPLNO##	;GET NEXT LINE
	CAIL	U,TTPLEN##-1	;DONE?
	JRST	UPOPJ##		;YES.
SENDX1:	MOVE	U,LINTAB##+1(U)	;NO--GET NEXT LDB
	MOVE	T1,LDBDCH##(U)	;GET BITS
	PUSHJ	P,SHDSND	;SHOULD WE DO A SEND?
	  SKIPA	T2,SNDPTR	;YES, SET UP POINTER
	JRST	SENDX2		;NO--TRY NEXT LINE
	MOVSI	T1,LOLSAP##	;SET UP FLAG
	SCNOFF			;NO INTERRUPTS HERE
	IORM	T1,LDBOST##(U)	;YES--SET FLAG
	AOS	SNDCTR
	SCNON
SENDX3:	PUSHJ	P,TOPOKE##	;START TTY
	JRST	SENDX2		;LOOP FOR MORE
;MORE OF SEND COMMAND

;SUBROUTINE TO GET CHARACTER FROM SENDER, WHOSE LDB IS ON STACK

SNDTYI:	EXCH	U,-1(P)		;GET SENDER'S LDB
	PUSHJ	P,COMTYI##	;GET HIS CHARACTER AND ITS BITS
	EXCH	U,-1(P)		;RESTORE LINE OF SENDEE
	TLNE	T1,CHBRK##	;IS THIS AN END OF LINE?
	POPJ	P,0		;YES. NON-SKIP RETURN FROM SNDTYI
	CAIE	T3,"H"-100	;FILTER ^H
	TLNE	T1,CHUAE##	;NO. IS IT A LOSING CONTROL CHAR?
	JRST	SNDTYI		;YES. FILTER IT OUT
	JRST	CPOPJ1##	;NORMAL CHAR. SKIP RETURN

SENDHD:	PUSHJ	P,INLMES	;SEND START OF SEND MESSAGE
	BYTE(7)15,12,7,";",";",0	;CR,LF,BELL
	EXCH	U,-1+IFN FTXMON,<-1>(P)	;GET SENDER'S LDB ADR
	PUSHJ	P,SENDH0	;GENERATE A TTY NAME
	CAMN	U,OPRLDB##	;IS IT THE OPR?
	MOVSI	T2,(SIXBIT /OPR/)	;YES. SAY OPR INSTEAD
	CAMN	U,LINTAB##+FRCLIN##	;IS IT FROM FRCLIN
	MOVE	T2,[SIXBIT/SYSTEM/]	;YES, USE SYSTEM
	MOVE	U,-1+IFN FTXMON<-1>(P)	;RESTORE RECIPIENT
	MOVEM	T3,-1+IFN FTXMON,<-1>(P)	;PUT PTY POINTER ON STACK
	PUSHJ	P,PRNAME	;OUTPUT THE NAME TO SENDEE
	PUSHJ	P,INLMES	;AND SPACER
	ASCIZ	/: - /		; ..
	POPJ	P,0		;RETURN FROM SENDHD

SENDH0:	MOVE	T1,J		;SET UP T1 FOR FIRST TIME THROUGH
	MOVE	T3,U		;SAVE U IN CASE OF ERROR
	MOVEI	T4,^D20		;MAX DEPTH
SENDH1:	MOVE	T2,JBTLIM##(T1)	;IS SENDER A
	TLNE	T2,(JB.LBT)	;BATCH SUBJOB?
	JRST	SENDH3		;YES, NEVER SAY OPR
	PUSHJ	P,CTLJBU##	;FIND CONTROL JOB
	JUMPE	U,SENDH2	;DETACHED JOB
	JUMPL	T1,SENDH3	;FOUND A TTY
	MOVE	F,TTYTAB##(T1)	;CONTROLLING TTY
	MOVE	U,DDBLDB##(F)	;HIS LINE
	SOJG	T4,SENDH1	;LOOK FOR NEXT PTY
SENDH2:	MOVE	U,T3		;RESTORE U
SENDH3:	PUSH	P,T3		;SAVE POINTER TO PTY LDB

	PUSHJ	P,TTYNAM##	;CONVERT TO REAL NAME IN SIXBIT
	POP	P,T3
	POPJ	P,

SNDEOL:	PUSHJ	P,CRLF		;SEND CR LF TO LINE IN U
	MOVE	T1,LDBDCH##(U)	;SEE IF DEST IS AT COM LEVEL
	TLNE	T1,LDLCOM##	; ..
	PUSHJ	P,PRDOTC	;YES. SEND A DOT TOO
	POPJ	P,0		;RETURN FROM SNDEOL
SHDSND:	SKIPL	LDBOFL##(U)	;SKIP IF OFF LINE?
	TRNE	T1,LDRPTY##	;DON'T SEND TO A PTY
	JRST	CPOPJ1##	;WHICH THIS IS
IFN FTNET,<
	JUMPE	W,SHDND2	;ANY PARTICULAR NODE SPECIFIED
	CAME	W,JBTLOC##	;CHECK FOR THE LOCAL NODE
	JRST	SHDND0		;REMOTE LINE
	SKIPL	LDBTTW##(U)	;LOCAL NODE IS THIS A LOCAL LINE?
	JRST	SHDND1		;YES, CONTINUE
SHDND0:	LDB	T4,LDPRNN##	;GET THE NODE NUMBER OF THE REMOTE LINE
	JUMPE	T4,CPOPJ1##	;UNASSIGNED LINE
	CAIE	T4,(W)		;IS THIS LINE ON THAT NODE
	JRST	CPOPJ1##	;NO, RETURN
	JRST	SHDND1		;YES CONTINUE
SHDND2:	MOVSI	T4,LRLCON##	;TTY
	TDNE	T4,LDBREM##(U)	;  CONNECTED?
	JRST	SHDND1		;YES CONTINUE
	SKIPGE	LDBTTW##(U)	;NO IS IT A REMOTE LINE
	JRST	CPOPJ1##	;YES, GO AWAY
SHDND1:	SKIPGE	LDBREM##(U)	;IF VTM + HOSTED AWAY
	JRST	CPOPJ1##	;YES, GO AWAY
>;END IFN FTNET
IFN FTMP,<
	LDB	T4,LDPCPU##	;CPU OWNING THE TERMINAL
	CAIN	T4,7		;GENERIC BOOT CPU
	MOVE	T4,BOOTCP##	;YES, GET CPU NUMBER
	IMULI	T4,.CPLEN##	;TO CDB OFFSET
	SKIPL	.C0OK##(T4)	;CPU RUNNING
	JRST	CPOPJ1##	;NO, DON'T SEND
>
	PUSH	P,T1		;SAVE T1
	LDB	T1,LDPLNO##	;GET LINE # INTO T1
IFN FTKS10,<
	CAIE	T1,KLILIN##	;KLINIK LINE?
	JRST	SHSND0		;NO
	MOVEI	T4,KLIINI	;KLINIK INITED?
	TDNN	T4,KLIIWD
	JRST	TPOPJ1##	;NO,DON'T SEND
SHSND0:>
	PUSHJ	P,XTCTTY##	;CHECK ON DA-28 LINE
	  PJRST	TPOPJ1##	;INACTIVE LINE - SKIP RETURN
	  JFCL			;ACTIVE LINE - OK
	POP	P,T1		;NORMAL RETURN - RESTORE T1
	HRRZ	T4,LDBDDB##(U)	;GET DDB ADDRESS
	JUMPE	T4,SHSND1	;JUMP IF NO DDB
	MOVE	T4,DEVIOS(T4)	;GET INIT MODE
	TRNE	T4,I!PIMMOD	;IMAGE MODE OR PACKED IMAGE MODE?
	JRST	CPOPJ1##	;YES--DO NOT SEND
SHSND1:	MOVE	T4,LDBBY2##(U)	;GET GAG FLAG
	TLNE	T1,LDLSLV##	;IF NOT SLAVE
	TLNE	T4,L2LSND##	;OR NOT GAGGED
	SKIPA	T4,LDBTTW##(U)	;OK, MAYBE, IF IN USE
	JRST	CPOPJ1##	;DON'T SEND TO GAGGED SLAVE
	TLNN	T4,LTLUSE##	;LINE IN USE?
	AOS	(P)		;NO, DON'T SEND
	POPJ	P,		;YES, SEND


SNDTYO:	;PUSHJ	P,PEVEN8##	;ADD PARITY
	SOSL	SNDCNT		;SKIP IF NO ROOM
	IDPB	T3,SNDTMP	;STORE BYTE
	POPJ	P,		;RETURN
	$LOW
SNDCNT::EXP	^D85
SNDCTR::EXP	0

SNDTMP::POINT	9,SNDTXT	;ACTIVE POINTER
SNDPTR::POINT	9,SNDTXT	;VIRGIN POINTER
SNDTXT:	BLOCK	^D85/4+1	;BUFFER
SNDMXL==:<.-SNDTMP-1>B26
	$HIGH


SNDBSY:	POP	P,T1		;REMOVE SENDEE FROM STACK
SNDBSI:	JSP	T1,ERRMES	;TYPE ERROR AND RETURN
	ASCIZ	/Busy
/
	SUBTTL	VERSION COMMAND & PRVERS SUBROUTINE

;"VERSION" -- COMMAND TO PRINT LOW+HISEG NAME+VERSION
;FORMAT IS:  LOWNAM LOWVER[+[HINAM HIVER]]
;HISEG STUFF ONLY IF VERSION DIFFERENT OR NAME NON-ZERO
;	AND DIFFERENT
;IF HISEG NAME ZERO, HINAM IS OMITTED
;IF NO HISEG, "+" IS OMITTED
;VERSION IS ALWAYS IN FORM VER LET(EDIT)-CUST.

VERCOM::PUSHJ	P,INTLVL##	;AT UUO LEVEL ALREADY?
	  JRST	VERBTH		;YES
	MOVE	S,P2		;SAVE COMMAND NAME AS DATA ITEM
	JSP	T2,SAVCTX##	;SET UP TO RUN AT UUO LEVEL
	MOVE	P2,S		;RESTORE COMMAND NAME
	PUSHJ	P,TTYFUW##
VERBTH::MOVE	T2,JBTNAM##(J)	;GET LOW NAME
	PUSHJ	P,PRNAME	;PRINT IT
	PUSHJ	P,PRSPC		;AND SPACE
	MOVE	T1,.JDAT+.JBVER## ;GET LOW VERSION
	PUSHJ	P,PRVERS	;PRINT IT
VERHGH::PUSHJ	P,SAVE3##
	PUSHJ	P,INTLVL##	;AT UUO LEVEL ALREADY?
	  JRST	VERHG0		;YES
	MOVE	S,P2		;SAVE COMMAND NAME AS DATA ITEM
	JSP	T2,SAVCTX##	;SET UP TO RUN AT UUO LEVEL
	MOVE	P2,S		;RESTORE COMMAND NAME
	PUSHJ	P,TTYFUW##
VERHG0:	TDZA	T1,T1		;CLEAR T1
VERHLP:	MOVE	T1,P3		;RESTORE LAST BLOCK LOOKED AT
VERHL1:	PUSHJ	P,GNXHSB##	;GET NEXT HIGH SEG BLOCK
	  POPJ	P,		;DONE
	SKIPG	P1,.HBSGN(T1)	;GET SEGMENT DATA
	JRST	VERHL1		;SPY SEG
	MOVE	P3,T1		;SAVE HIGH SEG DATA BLOCK ADDR
	PUSHJ	P,INLMES	;INDICATE HI-SEG
	ASCIZ	/ + /
	MOVE	T1,P3		;GET HIGH SEG BLOCK AGAIN
	PUSHJ	P,GETHSA	;GET STARTING ADDRESS OF HI SEG
	MOVE	T2,T1		;SAVE IT A BIT
	HLRZS	T1		;SET PCS TO THIS
	PUSHJ	P,SVPCS##	;SAVE CURRENT PCS, SETUP NEW FOR FLTST
	MOVE	T1,T2		;RESTORE ADDRESS
	PUSHJ	P,FLTST##	;IN CORE?
	  JRST	VERNAA		;NOT IN CORE
VERAOK:	MOVE	T1,P3		;HSB ADDR
	PUSHJ	P,MAPVJD##	;SET .VJDT TO CORRECT LOCATION
	SKIPN	T2,JBTNAM##(P1)	;GET HI NAME
	MOVE	T2,.VJDT+.JBHNM## ;BLANK--USE SAVE
	SKIPE	T1,.VJDT+.JBHVR## ;GET HIGH VERSION
	CAMN	T1,.JDAT+.JBVER## ; COMPARE TO LOW IF PRESENT
	CAME	T2,JBTNAM##(J)	;COMPARE TO LOW NAME
	CAIA			;DIFFERENT, PRINT
	JRST	VERHG2
VERHG1:	PUSHJ	P,PRNAME	;PRINT HI HAME
	PUSHJ	P,PRSPC		;AND SPACE
	MOVE	T1,.VJDT+.JBHVR## ;GET HI VERSION
	PUSHJ	P,PRVERS	;PRINT VERSION #
VERHG2:	MOVE	T1,JBTSTS##(P1)	;GET HISEG FLAGS
	TLNE	T1,SHRSEG	;SHARE SEG?
	JRST	VERHG3		;CONTINUE
	PUSHJ	P,INLMES	;NO--WARN USER
	ASCIZ	" Not sharable "
VERHG3:	CAME	P2,VERTXT##	;IF THIS IS VERSION COMMAND
	AOSE	P2		;OR NOT FIRST TIME
	JRST	VERHLP		;LOOP
	PUSHJ	P,PGMFIL	;ELSE SEE IF WE DID I/O
	JRST	VERHLP

VERNAA:	LSH	T1,W2PLSH	;COULD BE ALLOCATED BUT ZERO
	S1PSHJ	GTPME##		;GET MAP CONTENTS
	TLZ	T2,(PM.NAD)
	CAME	T2,[PM.ZER]
	CAME	P2,VERTXT##	;ONLY ON A VERSION COMMAND
	JRST	VERHLP
	MOVE	T1,P3		;HIGH SEG DATA BLOCK ADDR
	PUSHJ	P,GETHSA	;GET HI SEG ADDRESS AGAIN
	LSH	T1,W2PLSH	;CONVERT TO PAGE NUMBER
	PUSHJ	P,[PUSHJ P,SETASA ;GET THE PAGE INTO CORE AND ACCESSIBLE
		   PUSHJ	P,PAGIA
		     CAIA
		   AOS (P)
		   PUSHJ P,TTYFUW##
		   JRST	CLRASA]
	  JRST	VERHLP	;AND AFTER ALL THAT WORK
	JRST	VERAOK
;PRINT VERSION FROM T1

PRVERS::PUSHJ	P,SAVE1##
	PUSH	P,T1		;SAVE FOR LATER
	LSH	T1,-^D24	;POSITION MAJOR VERSION
	ANDI	T1,777		;CLEAR JUNK
	SKIPE	T1		;IF NON-ZERO,
	PUSHJ	P,PRTDI8	;  PRINT IN OCTAL
	HLRZ	T1,(P)		;GET MINOR VERSION
	ANDI	T1,77		;CLEAR JUNK
	JUMPE	T1,PRVER2	;IF NON-ZERO,
	SUBI	T1,1		;
	IDIVI	T1,^D26		;  PRINT IN ALPHA
	JUMPE	T1,PRVER1	;  ONE OR TWO
	PUSH	P,T2		;  CHARACTERS
	MOVEI	T3,"A"-1(T1)	;  ..
	PUSHJ	P,COMTYO##	;  ..
	POP	P,T2		;  ..
PRVER1:	MOVEI	T3,"A"(T2)	;  ALSO, SECOND ONE
	PUSHJ	P,COMTYO##	;  ..
PRVER2:	HRRZ	T1,(P)		;GET EDIT NUMBER
	JUMPE	T1,PRVER3	;IF NON-ZERO,
	PUSHJ	P,INLMES	;  PRINT (
	ASCIZ	/(/
	HRRZ	T1,(P)		;  GET EDIT NUMBER
	PUSHJ	P,PRTDI8	;  PRINT IN OCTAL
	PUSHJ	P,INLMES	;  PRINT )
	ASCIZ	/)/
PRVER3:	POP	P,P1		;GET CUST. NUMBER
	LSH	P1,-^D33	;POSITION
	JUMPE	P1,CPOPJ##	;IF NON-ZERO,
	PUSHJ	P,INLMES	;  PRINT -
	ASCIZ	/-/
	MOVEI	T3,"0"(P1)	;  GET DIGIT
	PJRST	COMTYO##	;PRINT AND RETURN

;SUBROUTINE TO GET HI SEG ADDRESS, CALL WITH T1=HIGH SEG DATA BLOCK,
;RETURNS T1=ADDRESS
GETHSA::PUSH	P,J		;SAVE JOB NUMBER
	SKIPG	J,.HBSGN(T1)	;IS THERE A REAL HIGH SEG?
	JRST	JPOPJ##		;NO
	HRRZS	J		;CLEAR CRUFT
	LDB	J,JBYHSO##	;ORGIN WITHIN SEGMENT
	LDB	T1,[PSG2LH+.HBSG2(T1)] ;SECTION HI SEG IS IN
	LSH	T1,S2PLSH	;CONVERT TO PAGE
	IORI	T1,(J)		;ADD IN RELATIVE ORIGIN PAGE #
	LSH	T1,P2WLSH	;CONVERT TO VIRTUAL ADDRESS
	JRST	JPOPJ##		;AND RETURN
	SUBTTL	EXAMINE AND DEPOSIT COMMAND


;"EXAMINE LOC" - LOOKS AT CONTENTS OF LOC AND PRINTS IN OCTAL
;IF LOC IS MISSING, NEXT LOC IS PRINTED
;IF PREVIOUS WAS E COMMAND, SAME LOC IF PREVIOUS WAS D COMMAND
;TAB. IS PRINTED INSTEAD OF CRLF(LIKE DDT)


ECOM::	SKIPGE	T2,.JDAT+JOBEXM## ;WAS PREVIOUS D OR E COMMAND, A D COMMAND?
	AOS	T2,.JDAT+JOBEXM## ;NO, IT WAS AN E, INCREMENT IN CASE HE TYPES NO ARG
	TLO	T2,400000	;SET E FLAG
	MOVEM	T2,.JDAT+JOBEXM## ;YES, FLAG THAT E HAPPENED LAST(LH=-1)
	PUSHJ	P,OCTPAR	;GET OCTAL LOCATION
	  MOVE	T2,.JDAT+JOBEXM## ;NONE SPECIFIED, USE LAST LOC OF D OR NEXT OF E
	PUSHJ	P,DEAT		;CHECK FOR AC REFERENCE AND STORE JOBEXM
	PUSHJ	P,FLTTC##	;WILL DOING AN EXAMINE CAUSE A PAGE FAULT?
	  JRST	ECOMA		;NO, BUT OUT OF BOUNDS
	  PUSHJ	P,DEGETP	;OUT, GET IT IN
	MOVE	M,T2		;SET EXAMINE ADDRESS
	MOVEI	T1,0		;ASSUME ALLOCATED BUT ZERO PAGE
	TLZ	T4,(PM.NAD)
	CAMN	T4,[PM.ZER]	;PAGE ABZ?
	JRST	ECOM1		;YES, PRINT 0
IFN FTXMON,<
	PUSHJ	P,[PUSHJ P,SSPCS## ;SAVE PCS
		   MOVE T1,M	;SXPCS WANTS THIS IN T1
		   PUSHJ P,SXPCS## ;SETUP PCS THE WAY GETEWD WANTS IT
		     POPJ P,	;OUT OF BOUNDS
		   PJRST GETEWD##] ;GET WORD FROM LOW OR HIGH SEG
>
IFE FTXMON,<
	PUSHJ	P,GETWRD##	;GET WORD FROM HIGH OR LOW SEG
>
	  JRST	ECOMA		;ERROR, OUT OF BOUNDS
ECOM1:	PUSH	P,T1		;SAVE CONTENTS OF LOC TO BE PRINTED
	MOVE	T1,.JDAT+JOBEXM## ;PRINT LOC BEING EXAMINED
	TLZ	T1,400000	;CLEAR EXAMINE LAST FLAG
	PUSHJ	P,UDPCP##
	PUSHJ	P,INLMES	;PRINT SLASH TAB
	ASCIZ	*/	*
	HLRZ	T1,(P)		;PRINT LEFT HALF
	PUSHJ	P,OCTPNT
	PUSHJ	P,INLMES	;PRINT SPACE
	ASCIZ	/ /
	HRRZ	T1,(P)		;PRINT RIGHT HALF
	PUSHJ	P,OCTPNT
	PUSHJ	P,INLMES	;PRINT FINAL TAB
	ASCIZ	/	/
	PUSHJ	P,CLRASA	;CLEAR AC'S IN SHADOW AREA FLAG
	HRLI	M,NOFLM		;AVOID LEFT MARGIN
	JRST	TPOPJ##		;POP P,T1,POPJ P,
;"DEPOSIT LH RH LOC" - DEPOSITS XWD LH,RH IN LOCATION LOC
;IF LOC IS MISSING, ASSUME NEXT LOC IF PREVIOUS D, SAME LOC IF PREVIOUS E

DCOM::	PUSHJ	P,SAVE2##
	PUSHJ	P,OCTPRR	;READ A WORD TO DEPOSIT, MUST BE 36 BITS
	  JRST	NOTENF		;NOT ENOUGH ARGUMENTS
	MOVE	P2,T2		;SAVE NUMBER TO DEPOSIT
	SKIPL	P1,.JDAT+JOBEXM## ;WAS PREVIOUS D OR E AN E COMMAND?
				; NEGATIVE IF E, POSITIVE IF D
	AOS	P1,.JDAT+JOBEXM## ;NO, INCREMENT IN CASE USER TYPED NO THIRD ARG
				; FOR SUCCESSIVE D'S
	MOVSI	T1,400000	;FLAG THAT A D WAS DONE LAST
	ANDCAM	T1,.JDAT+JOBEXM## ; JOBEXM POSITIVE
	PUSHJ	P,OCTPAR	;GET LOC
	  MOVE	T2,P1		;NOT SPECIFIED, USE LAST OF E OR NEXT OF D
	MOVE	S,P2		;NUMBER TO BE DEPOSITED INTO S
	PUSHJ	P,CHKMED##	;CHECK TO SEE IF HIGH SEG IS SHARABLE
				; IF YES, SET USER-MODE WRITE PROTECT (UWP) ON
				; FOR THIS USER, AND SET MEDDLE FOR THIS USER
				; SO HE CANNOT TURN UWP OFF
	PUSHJ	P,DEAT		;CHECK FOR AC REFERENCE
	PUSHJ	P,FLTTC##	;WILL DOING A DEPOSIT CAUSE A PAGE FAULT?
	  JRST	ECOMA		;NO, BUT OUT OF BOUNDS
	  PUSHJ	P,DEGETP	;OUT, GET IT IN
	MOVE	M,T2		;DEPOSIT ADDRESS TO M
	TLZ	T4,(PM.NAD)	;CLEAR BITS
	CAMN	T4,[PM.ZER]
	PJRST	CREPAG##	;YES, MAKE IT COME TO LIFE
IFN FTXMON,<
	PUSHJ	P,[PUSHJ P,SSPCS## ;SAVE PCS
		   MOVE T1,M	;SXPCS WANTS THIS IN T1
		   PUSHJ P,SXPCS## ;SETUP PCS THE WAY GETEWD WANTS IT
		     POPJ P,	;OUT OF BOUNDS
		   MOVE T1,S	;WHERE PUTEWD WANTS IT
		   PJRST PUTEWD##] ;PUT WORD INTO LOW OR HIGH SEG
>
IFE FTXMON,<
	PUSHJ	P,PUTWRD##	;TRY TO STORE THE WORD IN THE USER'S AREA
>
	  JRST	ECOMA		;OUT OF BOUNDS
	PJRST	CLRASA		;CLEAR AC'S IN SHADOW AREA FLAG
DEAT:	TLZ	T2,400000	;CLEAR LH IN CASE THIS IS A SUCCESSIVE E WITH NO ARG
	DPB	T2,[POINT 23,.JDAT+JOBEXM##,35] ;STORE FOR NEXT TIME, DO NOT TOUCH LH(D OR E LAST)
				; YES, WAS JOB STOPPED IN USER MODE?
	PUSH	P,T2		;SAVE ARG
	TLZ	T2,1		;1,,0-1,,17 ARE ACS
	CAIL	T2,20		;IS IT AN AC?
	JRST	T2POPJ##	;NO
	CAME	J,.CPJOB##	;CURRENT JOB?
	PUSHJ	P,SETASA	;NO, INDICATE AC'S ARE IN THE SHADOW AREA
	JRST	T2POPJ##	;RETURN


ECOMA:	PUSHJ	P,CLRASA	;CLEAR AC'S IN SHADOW AREA FLAG
	JSP	T1,ERRMES	;OUT OF BOUNDS
OUTBMS::ASCIZ	/Out of bounds
/

;ROUTINE TO GET A PAGE IN AND MAKE IT ACCESSIBLE FOR D/E COMMANDS
DEGETP:	MOVEM	S,.JDAT+JOBFDV##;SAVE S FOR THE CALLER
	POP	P,S		;CALLER'S PC
	JSP	T2,SAVCTX##	;GET TO UUO LEVEL
	PUSH	P,S		;SAVE CALLER'S PC FOR RETURN
	MOVE	T1,.JDAT+JOBEXM## ;ADDRESS IN QUESTION
	TLZ	T1,400000	;CLEAR E/D LAST FLAG
	LSH	T1,W2PLSH	;PAGE IN QUESTION
	PUSHJ	P,SETASA	;SO UUO ARGUMENTS ARE FETCHED CORRECTLY
	PUSHJ	P,PAGIA		;PAGE IT IN, TURN ON ACCESS ALLOWED
	  JRST	[POP P,(P)	;SHOULDN'T HAPPEN BUT PRETEND OUT OF BOUNDS
		 PUSHJ P,TTYFUW## ;PAGIA CLOBBERED U
		 JRST ECOMA]
	PUSHJ	P,TTYFUW##	;FIND THE TTY
	MOVE	S,.JDAT+JOBFDV##;RESTORE CALLER'S S
	MOVE	T2,.JDAT+JOBEXM## ;WHERE TO GET/PUT WORD
	TLZ	T2,400000	;CLEAR E/D LAST FLAG
	SETZ	T4,		;SO DOESN'T LOOK LIKE AN ABZ PAGE
	POPJ	P,		;RETURN
;"SCHEDULE" TYPES OUT RH OF STATES, LEGAL FOR ALL.

SKEDUL::HRRZ	T1,STATES##	;SCHEDULE WITH NO ARGUMENTS.
	PUSHJ	P,OCTPNT	;PRINT RH OF STATES.
	JRST	CRLF		;AND RETURN WITH A CRLF


;"BLANK" OR NO ALPHA NUMERIC BEFORE BREAK CHAR COMMAND
;DISPATCHED TO LIKE ANY OTHER COMMAND(0 IN COMMAND TABLE)

CBLANK::SE1ENT			;GET TO A DECENT SECTION
	PUSHJ	P,CTIGLC##	;GET LAST CHARACTER SCANNED
	CAIN	T3,12		;WAS BREAK A LINE-FEED?
	POPJ	P,		;YES--NULL COMMAND
	CAIL	T3,40		;RANGE CHECK FOR SIXBIT
	CAILE	T3,137
	JRST	COMERA		;OUT OF RANGE IS ERROR
	SUBI	T3,40		;CONVERT TO SIXBIT
	LSHC	T2,^D<72-6>	;MAKE A SIXBIT TOKEN
	PUSHJ	P,COMTYS	;READ ANOTHER CHARACTER SO OTHER ROUTINES WORK
	SETZB	P3,P4		;SO DON'T CONFUSE US WITH SET COMMAND
	MOVE	P,.CPISF##	;RESTORE STACK TO VALUE AT COMGO
	JRST	COM1Z		;TRY AGAIN WITH VALUE IN T2
	SUBTTL	TTY COMMAND AND SET TTY COMMAND

;TTY [DEV[:]] [NO] WORD	;SETS OR CLEARS BITS IN LDBDCH FOR TTY LINE
;DEV ARGUMENT LEGAL ONLY IF ASSIGNED TO YOU OR YOU ARE OPR


TTYCMD::SE1ENT			;ENTER SCETION 1
	PUSHJ	P,SAVE2##	;SAVE P1
	PUSH	P,U		;SAVE TYPING TTY'S LDB
	MOVE	P1,U		;ASSUME HIS WILL BE OBJECT
	PUSHJ	P,CTEXT1	;GET AN ARGUMENT
IFN FTNET,<
	CAIE	T3,"_"		;START OF NODE_LINE?
	JRST	TTYC0		;NO, CHECK IF DEVICE
	POP	P,U		;FIX STACK FOR CO-ROUTINING
	NETDBJ			;INTERLOCK THIS PART
	MOVE	T1,T2		;PUT IN RIGHT PLACE FOR NETSER
	PUSH	P,U		;SAVE OUR LINE AGAIN
	PUSHJ	P,SRCNDB##	;FIND THE NODE BY NAME
	 JRST	[JSP	T1,TTYCF	;NODE DOES NOT EXIST
		 ASCIZ	/Node does not exist
/]
	MOVE	P1,T1		;SAVE THE STATION NAME
	PUSHJ	P,CTEXT		;GET THE DEVICE NAME
	JUMPE	T2,NOTENP	;ILLEGAL ARG LIST
	MOVE	P2,T2		;SAVE THE DEVICE NAME
	TRNE	T2,505050	;MUST BE NUMERIC GGGU
	JRST	NOTDV1		;ERROR RETURN
	TLNE	P2,505050	;IS LH A NUMBER?
	JRST	TTYC0B		;NO, CONTINUE NORMALLY
	MOVSS	P2		;FLIP HALVES OF ARGUMENT
TTYC0A:	TRNE	P2,77		;IS RIGHTMOST DIGIT ZERO?
	JRST	TTYC0C		;NO, DONE
	LSH	P2,-6		;SHIFT RIGHT ONE DIGIT
	JRST	TTYC0A		; AND TRY AGAIN
TTYC0C:	TRO	P2,202020	;MAKE IT ALL DIGITS
	HRLI	P2,(SIXBIT/TTY/); AND MAKE LH SAY TTY
TTYC0B:	MOVE	T2,P2		;RESTORE DEVICE NAME
	HLRZ	P1,NDBNNM##(W)	;GET NODE #
	CAMN	P1,JBTLOC##	;LOCAL NODE?
	JRST	TTYC0D		;YES, JUST RETURN
	MOVEI	P1,(W)		;SAVE THE NDB POINTER
	HLRZ	T1,P2		;GENERIC NAME ONLY FROM THE LEFT HALF
	CAIE	T1,'TTY'	;IS IT A TTY?
	JRST	[JSP	T1,TTYCF	;NO. COMPLAIN.
		 ASCIZ	/Not a TTY/]
	HRLZ	T1,P2		;GET THE REMOTE LINE NUMBER
	PUSHJ	P,CVTOCT##	;CONVERT IT TO OCTAL
	  JRST	NOTDV1		;NON NUMERIC LINE NUMBER
	HLL	T1,NDBNNM(W)	;GET THE NODE NUMBER
	PUSHJ	P,GTXTN##	;AND TRY TO CONVERT THE PAIR TO "TTYNNN"
	  JRST	[JSP	T1,TTYCF	;NOT IMMEDIATELY AVAILABLE
		 ASCIZ	/Not connected/]
	MOVE	T2,T1		;COPY THE DEVICE NAME
	JRST	TTYC0D		;WE SUCCEDED.  T2 := DEVICE NAME

TTYC0:
> ;END IFN FTNET
	CAIE	T3,":"		;DEVICE?
	JRST	TTYC1		;NO. A WORD.
	MOVE	T1,T2		;GET THE DEVICE.
TTYC0D:	PUSHJ	P,DEVNFS##	;FIND THE DEVICE
	  JRST	TTYCE		;NO SUCH DEVICE
	MOVE	T2,DEVMOD(F)	;GET DEVICE TYPE BITS
	TLNE	T2,DVTTY	;IS IT A TTY?
	TLNE	T2,DVDSK	;  AND NOT NUL?
	JRST	TTYCE		;NO, ERROR
	MOVE	U,DDBLDB##(F)	;GET LDB ADDRESS
	PUSHJ	P,TTYKLQ##	;GIVE BACK TTY DDB IF NECESSARY
	JUMPE	U,TTYCE		;MAKE SURE WE GOT AN LDB ADDRESS
	MOVE	P1,U		;STORE AS OBJECT OF COMMAND
	MOVE	U,0(P)		;RESTORE LDB FOR TYPER
	PUSHJ	P,SKIPS		;DISCARD THE COLON
	  JRST TTYCE		;SHOULDNT BE END OF LINE
	MOVE	P2,U		;SEE IF THIS IS OPR
	PUSHJ	P,SETLGL	;SKIP IF OPR
	  CAMN	P2,P1		;HIS OWN TTY?
	JRST	TTYCL		;YES. OK.
	LDB	T2,PJOBN##	;NO. WHO OWNS THE TTY IN QUESTION
	JUMPE	T2,TTYCE	;LOSE IF NOBODY
	CAIE	T2,(J)		;OK IF US
	JRST	TTYCE		;OTHERWISE FAIL

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TTYCL:	MOVE	U,0(P)		;RESET LINE TO TYPER
	PUSHJ	P,SKIPS1	;SEE IF ANY MORE ON LINE.
	  JRST	[MOVE   U,P1	;POINT TO TARGET
		 TLZ	U,400000
		 PUSHJ	P,SETCHP##
		 JRST   UPOPJ##];RESTORE U AND RETURN
	PUSHJ	P,CTEXT1	;YES. SEE WHAT IT IS
TTYC1:	MOVE	T1,[-TTCWDN,,TTCWDT]	;POINT TO NAMES
	PUSHJ	P,FNDNAM	;FIND ABBREV.
	  JRST	TTYC4		;ERROR
	HRRZ	T2,TTCWDD(T1)	;GET RESULT
	HRRZ	T3,TTCDAT(T1)	;GET FLAGS FOR COMMAND
TTYC2:	MOVE	T4,P1		;TARGET LDB
	TLZ	T4,400000	;CLEAR "NO" BIT
	CAMN	T4,LINTAB##+FRCLIN## ;IS TARGET FRCLIN?
	TRNN	T3,TT.CIF	;YES, IS THIS FUNCTION ILLEGAL?
	PUSHJ	P,(T2)		;DISPATCH TO ROUTINE
	  JRST	TTYCE		;ERROR
	JRST	TTYCL		;LOOK FOR MORE
TTYC4:	MOVE	T1,[-TTTWDN,,CTTWDT] ;AOBJN POINTER TO TYPES TABLE
	PUSHJ	P,FNDNAM	;SEE IF RECOGNIZED TERMINAL TYPE
	  JRST	TTYCE		;NO, CALL AN ERROR
	MOVEI	T2,TTUTYX	;DISPATCH ADDRESS TO PROCESS TERMINAL TYPE
	MOVEI	T3,TT.CIF	;THIS FUNCTION IS ILLEGAL ON FRCLIN
	MOVE	U,P1		;SETUP TARGET LDB
	TLZ	U,400000	;CLEAR POSSIBLE 'NO' BIT
	JRST	TTYC2		;GO DISPATCH
TTYCE:	POP	P,U		;RESTORE LINE FROM STACK
	JRST	COMERR		;AND GO COMPLAIN.
TTYCF:	POP	P,U		;RESTORE LINE FROM STACK
	PJRST	ERRMES		;AND GIVE OUR MESSAGE
;TABLE FOR SET TTY COMMAND
;MACRO HAS 5 ARGUMENTS:
;	NAME  -  WORD USED IN TTY COMMAND
;	DISP  -  DISPATCH LOCATION TO PROCESS WORD
;	OFST  -  OFFSET WITHIN LDB WHERE ANSWER IS STORED
;	DATA  -  18 BITS OF DATA USED BY PROCESSING ROUTINE
;	BITS  -  FLAGS FOR THIS COMMAND

	TT.CIF==1B18		;THIS COMMAND IS ILLEGAL ON FRCLIN

	DEFINE	TTNAME,<
	TT	ALTMODE,TTCCLR,LDBPAG##,LPLALT##,0
	TT	BLANKS,TTCCLR,LDBPAG##,LPLBLK##,0
	TT	COPY,TTCESC,"_","^",TT.CIF
	TT	CRLF,TTCCLR,LDBDCH##,LDLNFC##,0
	TT	DEFER,TTCDFR,LDBBYT##,L1RDEM##,0
	TT	DISPLAY,TTCSET,LDBATR##,LALDIS##,0
	TT	ECHO,TTCCLR,LDBDCH##,LDLCNE##!LDLNEC##,TT.CIF
	TT	.EDIT,TTCEDT,LDBEDT##,0,TT.CIF
	TT	ESCAPE,TTCMAP,LDPESC##,33,TT.CIF
	TT	EIGHTBIT,TTC8BT,LDBATR##,LAL8BT##,0
 ;	TT	FFHOME,TTCSET,LDBPAG##,LPLFFH##,TT.CIF
 ;	TT	FFSIMU,TTCSET,LDBPAG##,LPLFFF##,TT.CIF
 ;	TT	FFSTOP,TTCSET,LDBPAG##,LPLFFS##,TT.CIF
	TT	FILL,TTCNUM,LDPFLC##,3,0
	TT	FORM,TTCSET,LDBDCH##,LDLFRM##,0
	TT	GAG,TTCCLR,LDBBY2##,L2LSND##,0
	TT	HOLD,TTCESC,"\",<"[">,TT.CIF
	TT	IGNORE,TTCIGN,0,0,TT.CIF
	TT	IGNORE,TTCIGN,0,0,TT.CIF	;MAKE SURE USER WANTS IGNORE
	TT	ISO,TTCSET,LDBATR##,LALISO##,TT.CIF
	TT	LC,TTCCLR,LDBDCH##,LDLLCT##,TT.CIF
	TT	LENGTH,TTCNUM,LDPLNB##,^D255,TT.CIF
	TT	LOCALCOPY,TTCSET,LDBDCH##,LDLLCP##,TT.CIF
	TT	NO,TTCNO,0,0,0
	TT	OVERSTRIKE,TTCSET,LDBATR##,LALCOS##,TT.CIF
	TT	PAGE,TTCPAG,LDPSTB##,^D255,TT.CIF
	TT	QUOTE,TTCSET,LDBBYT##,L1LQOT##,TT.CIF
	TT	RTCOMP,TTCSET,LDBISB##,LILRTC##,0
	TT	REMOTE,TTCREM,LDBDCH##,LDRRMT##,TT.CIF
	TT	SBELL,TTCSET,LDBPAG##,LPLSBL##,TT.CIF
	TT	SLAVE,TTCSLV,LDBDCH##,LDLSLV##,TT.CIF
	TT	SPEED,TTCSPD,0,0,TT.CIF
	TT	SSTOP,TTCSST,LDPSTB##,^D255,TT.CIF
	TT	STOP,TTCSTP,LDPSTB##,^D255,TT.CIF
	TT	TABS,TTCSET,LDBDCH##,LDLTAB##,0
	TT	TAPE,TTCTAP,LDBBY2##,L2LTAP##,TT.CIF
	TT	TYPE,TTCTYP,0,0,TT.CIF
	TT	UC,TTCSET,LDBDCH##,LDLLCT##,TT.CIF
	TT	UNPAUSE,TTCMAP,LDPUNP##,21,TT.CIF
	TT	WIDTH,TTCNUM,LDPWID##,<^D17*^O1000+^D255>,0
	TT	XONXOF,TTCSET,LDBPAG##,LPLXNF##,0
IFN FTPATT,<
	TT	.PATCH,TTYCL,0,0
> ;END FTPATT
> ;END TTNAME MACRO
	XALL
	DEFINE	TT(NAME,DISP,OFST,DATA,BITS),<
	<SIXBIT	/NAME/>
	>
	$LOW
TTCWDT::TTNAME
TTCWDN==.-TTCWDT
TTCMXL==:<TTCWDN-1>B26
	$HIGH
	DEFINE	TT(WORD,DISP,OFST,DATA,BITS)<
	XWD	OFST,DISP
>

TTCWDD:	TTNAME
	DEFINE	TT(WORD,DISP,OFST,DATA,BITS)<
	XWD	DATA,BITS
>

TTCDAT:	TTNAME



	SALL
;HERE TO PROCESS 'TTY SPEED'
TTCSPD:	PUSHJ	P,NUMARG	;GO GET A NUMBER
	  POPJ	P,		;MUST BE ONE
	PUSHJ	P,TTCSP1	;FIND SPEED IN TABLE
	  POPJ	P,		;NOT THERE
	PUSH	P,P2		;SAVE RECEIVE SPEED
	CAIN	T3,","		;ENDED WITH A COMMA?
	PUSHJ	P,COMTYS	;YES, SKIP IT
	PUSHJ	P,NUMARG	;GO GET NEXT NUMBER
	  JRST	[MOVE P2,0(P)	;NONE, USE RECEIVE SPEED
		 JRST TTCSP0]	;AND SKIP TABLE LOOKUP
	PUSHJ	P,TTCSP1	;CHECK TRANSMIT SPEED IN TABLE
	  JRST	TPOPJ		;NOT THERE, ERROR
TTCSP0:	MOVE	U,P1		;SETUP TARGET LDB
	TLZ	U,400000	;CLEAR POSSIBLE "NO" BIT
	DPB	P2,LDPTSP##	;SAVE XMIT SPEED
	POP	P,P2		;RESTORE RECEIVE SPEED
	DPB	P2,LDPRSP##	;SAVE RECEIVE SPEED
	JRST	CPOPJ1##	;GIVE GOOD RETURN

TTCSP1::MOVSI	P2,-LSPLEN	;LENGTH OF TABLE
	CAME	T2,LSPTAB(P2)	;IS THIS IT?
	AOBJN	P2,.-1		;NO--KEEP LOOKING
	JUMPL	P2,CPOPJ1##	;FOUND
	POPJ	P,0		;LOST

LSPTAB::	DEC	0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,1,2
LSPLEN==:.-LSPTAB
;HERE TO PROCESS TTY ESCAPE AND TTY UNPAUSE
TTCMAP:	HLRZ	T2,TTCDAT(T1)	;GET OUR DEFAULT VALUE IF 'NO' FLAVOR
	JUMPL	P1,TTCMA1	;JUMP IF NEGATING
	PUSH	P,T1		;NO, SAVE INDEX
	S0PSHJ	OCTARG		;READ AN OCTAL NUMBER
	  JRST	TTCMA2		;NO, TRY FOR "<CHAR>"
	JRST	TTCMA3		;YES, GO SET IT
TTCMA2:	PUSHJ	P,SKIPS1	;SKIP BLANKS
	  JRST	TPOPJ##		;MUST NOT HAVE EOL HERE
	CAIE	T3,""""		;QUOTING A CHARACTER?
	  JRST	TPOPJ##		;NO, I DON'T UNDERSTAND THIS
	PUSHJ	P,COMTYI##	;GET THE QUOTED CHARACTER
	CAIN	T3,12		;IS IT LINEFEED?
	JRST	TPOPJ##		;YES, ABORT SINCE DON'T KNOW WHAT IT REALLY WAS
	CAIE	T3,""""		;IS THIS ANOTHER QUOTE?
	JRST	TTCMA5		;NO, CHECK FOR ^V
	PUSHJ	P,COMTYI##	;YES, GET NEXT CHARACTER
	CAIE	T3,""""		;IS THIS ALSO QUOTE?
	JRST	TPOPJ##		;NO, BUT IT SHOULD BE
	JRST	TTCMA4		;YES, DON'T TEST FOR ^V
TTCMA5:	LDB	T2,LDPQOT##	;GET TTY QUOTE ENABLED BIT
	SKIPE	T2		;IS IT ENABLED?
	CAIE	T3,"V"-100	;AND IS THIS THE MAGIC CHARACTER?
	JRST	TTCMA4		;NO, DON'T EAT ANOTHER
	PUSHJ	P,COMTYI##	;YES, GET ANOTHER
TTCMA4:	PUSH	P,T3		;NO, SAVE IT
	PUSHJ	P,COMTYI##	;ATTEMPT TO GET THE CLOSING QUOTE
	CAIE	T3,""""		;IS IT HERE?
	CAIN	T3,12		;OR EOL?
	TRNA			;YES, WE'RE GOLDEN
	JRST	TTPOPJ##	;NO, GIVE UP
	PUSHJ	P,COMTYS	;EAT ONE TOO FAR FOR NEXT SKIPS1
	POP	P,T2		;YES, RESTORE VALUE
TTCMA3:	CAIL	T2,0		;IS IT IN RANGE?
	CAILE	T2,CK.CHR	;EITHER WAY?
	JRST	TPOPJ##		;NO, FORGET IT
	POP	P,T1		;YES, RESTORE TABLE INDEX
TTCMA1:	HLRZ	T1,TTCWDD(T1)	;GET THE STORAGE POINTER
	TLZ	P1,400000	;CLEAR THE 'NO' FLAG
	EXCH	P1,U		;SET TO AFFECT REQUESTED TARGET LINE
	DPB	T2,(T1)		;STORE THE VALUE
	PUSHJ	P,TOPNDS##	;SET THE LMLNDS FLAG FOR NETDEV
	EXCH	P1,U		;RESTORE THE LINE POINTERS
	JRST	CPOPJ1##	;SUCCESS
;HERE TO PROCESS TTY IGNORE
TTCIGN:	MOVE	U,P1		;COPY LDB ADDRESS
	TLZ	U,400000	;CLEAR "NO" BIT
	LDB	T1,LDPTSP##	;GET TRANSMIT SPEED
	SKIPL	P1		;SKIP IF 'NO'
	SETZM	T1		;NO--CLEAR T1
	DPB	T1,LDPRSP##	;SET TO RECEIVE SPEED
	TLZ	P1,400000	;CLEAR YES/NO FLAG
	JRST	CPOPJ1##	;RETURN

;HERE TO PROCESS 'TTY REMOTE'
TTCREM:	JUMPGE	P1,TTCRM1	;ANYONE CAN THROW AWAY GOODNESS
				; (AND ONLY GOOD GUYS CAN GET GOOD TTY'S)
	PUSHJ	P,PRVJ		;BUT SETTING GOODNESS REQUIRES GOODNESS
	JRST	TTRSET		;TYPER IS ADEQUATELY PRIVILEGED
	POPJ	P,		;PRIVILEGED COMMAND BUT NO PRIVILEGES
TTCRM1:	EXCH	U,P1		;GET ACS WHERE WE WANT THEM
	LDB	T2,LDPLNO##	;GET OUR LINE NUMBER
	EXCH	U,P1		;RESTORE LDB ADDRESSES
	CAIL	T2,FRCLIN##	;MAKE SURE THAT FRCLIN AND THE CTYS
	CAILE	T2,TCONLN##	;STAY LOCAL
	JRST	TTRSET		;WIMP TERMINAL
	POPJ	P,		;FRCLIN & CTY0-N MUST REMAIN LOCAL

;HERE TO DO 'TTY EIGHTBIT'
TTC8BT:	JUMPL	P1,TTCSET	;ANYONE CAN SET 7-BIT
	MOVSI	T2,LIL7BT##	;DUMB FE BIT
	TDNN	T2,LDBISB##(U)	;SEE IF THIS FE CAN HANDLE 8-BIT
	JRST	TTCSET		;YES--GO DO IT
	POPJ	P,		;NO--WIMP OUT
;HERE TO DO 'TTY PAGE'
TTCPAG:	PUSH	P,T1		;SAVE INDEX
	MOVE	T1,P1		;ADDRESS OF LDB
	ADDI	T1,LDBPAG##	;ADDRESS OF WORD
	MOVSI	P2,LPLXNF##+LPLSTP##	;PAGE BIT
	PUSHJ	P,TTCST1	;GO SET OR CLEAR IT
	  JFCL			;CAN NOT MISS
	PUSHJ	P,NUMARG	;GO READ IN ANY NUMERIC ARGUMENT
	  JRST	TPOPJ1##	;NO CHANGE IN PAGE SIZE
	POP	P,T1		;RESTORE INDEX
	PUSHJ	P,TTCNUP	;PROCESS THE NUMBER
	  POPJ	P,		;OUT OF RANGE
	EXCH	U,P1		;POINT U TO THE LDB
	DPB	T2,LDPLNB##	;ALSO SET TERMINAL LENGTH
	EXCH	P1,U		;RESTORE U
	JRST	CPOPJ1##	;SUCCESSFUL RETURN

;HERE TO DO 'TTY STOP'
TTCSTP:	PUSH	P,T1		;SAVE INDEX
	MOVE	T1,P1		;LDB ADDRESS
	ADDI	T1,LDBPAG##	;ADDRESS OF PAGING CONTROL
	MOVSI	P2,LPLSTP##	;AUTO STOP BIT
	JRST	TTCSS2		;COMMON CODE

;HERE TO DO 'TTY 'SSTOP'
TTCSST:	PUSH	P,T1		;SAVE INDEX
	MOVE	T1,P1		;LDB ADDRESS
	ADDI	T1,LDBPAG##	;ADDRESS OF PAGING CONTROL
	MOVSI	P2,LPLSTP##+LPLSST##  ;AUTO STOP BITS
TTCSS2:	PUSHJ	P,TTCST1	;GO SET/CLEAR BITS
	  JFCL			;DUH?
	PUSHJ	P,NUMARG	;SEE IF ANY NUMERIC ARGUMENT
	  JRST	TTCSS5		;NO, SEE IF NEED TO DEFAULT STOP SIZE
	POP	P,T1		;RESTORE INDEX
	PUSHJ	P,TTCNUP	;YES, PROCESS IT
	  POPJ	P,		;OUT OF RANGE
	JRST	CPOPJ1##	;SUCCESSFUL RETURN

TTCSS5:	POP	P,T1		;RESTORE INDEX
	EXCH	U,P1		;POINT U TO THE LDB
	TLZ	U,400000	;CLEAR "NO" BIT
	LDB	P2,LDPSTB	;GET SIZE OF STOP BASE
	JUMPN	P2,TTCSS6	;IF SET THEN DON'T DEFAULT IT
	LDB	P2,LDPLNB	;PICK UP TTY LENGTH
	DPB	P2,LDPSTB	;AND USE IT FOR THE TTY STOP VALUE
TTCSS6:	EXCH	P1,U		;RESTORE U
	JRST	CPOPJ1##	;SUCCESSFUL RETURN
;HERE TO DO 'TTY DEFER'
TTCDFR:	MOVE	U,P1		;SET UP FOR OUR TARGET
	TLZE	U,400000	;CLEARING?
	TDZA	P2,P2		;YES,
	MOVEI	P2,1		;OR SETTING
	LDB	T2,LDPDEM##	;GET THE CURRENT VALUE
	CAMN	T2,P2		;ARE WE CHANGING IT?
	JRST	CPOPJ1##	;NO, DON'T BOTHER SCNSER
	DPB	P2,LDPDEM##	;YES, SET THE NEW VALUE
	MOVSI	T2,L3LDMC##	;GET THE CHANGE BIT
	IORM	T2,LDBBY3##(U)	;LIGHT IT FOR RECINT
	JRST	CPOPJ1##	;NOW RETURN SUCCESS

;HERE TO DO 'TTY SLAVE'
TTCSLV:	PUSH	P,T1		;SLAVE INDEX
	JUMPL	P1,TTCSL1	;ALWAYS LEGAL TO CLEAR
	MOVE	T1,P1		;COPY TARGET'S LINE POINTER
	MOVE	T1,LDBDCH##(T1)	;GET ITS BITS
	TRNE	T1,LDRPTY##	;IS IT A PTY?
	JRST	TPOPJ##		;YES, GIVE FAIL RETURN (ILLEGAL)
TTCSL1:	PUSH	P,U		;NO, CLEAR
	MOVE	U,P1		;TARGET'S INPUT
	TLZ	U,400000	;CLEAR POSSIBLE "NO" BIT
	PUSHJ	P,TSETBI##	;CLEAR INPUT BUFFER
	POP	P,U
	POP	P,T1		;RESTORE INDEX
	TLZN	P1,400000	;WANT TO CLEAR?
	JRST	TTCSET		;NO--LEAVE LDLCOM ALONE
	MOVSI	P2,LDLCOM##	;YES--SET LINE INTO
	IORM	P2,LDBDCH##(P1)	; COMMAND MODE
	PJRST	TTCCLR		;GO CLEAR SLAVE BIT

;HERE TO SET A RIGHT HALF WORD BIT
TTRSET:	HLRZ	P2,TTCDAT(T1)
	JRST	TTCST2

;HERE TO SET/CLEAR BITS IN THE LDB
TTCCLR:	TLC	P1,400000	;COMPLEMENT THE SENSE
TTCSET:	HLLZ	P2,TTCDAT(T1)	;PICK UP FLAG
TTCST2:	HLRZ	T1,TTCWDD(T1)	;PICK UP OFFSET
	ADD	T1,P1		;GET ACTUAL ADDRESS
TTCST1:	TLZN	P1,400000	;WANT TO CLEAR?
	SKIPA	T2,[IORM P2,(T1)]	;NO--GO SET
	MOVSI	T2,(ANDCAM P2,(T1))	;YES--CLEAR
	TLZ	T1,400000	;CLEAR POSSIBLE "NO" BIT
	XCT	T2
	PJRST	CPOPJ1##	;SKIP RETURN

;HERE ON THE WORD NO
TTCNO:	TLC	P1,400000	;COMPLEMENT FLAG
	JRST	CPOPJ1##	;SKIP RETURN

;HERE TO SEND AN ESCAPE SEQUENCE
TTCESC:	PUSH	P,T1		;SAVE T1
	MOVE	U,P1		;COPY LDB ADDRESS
	TLZ	U,400000	;CLEAR POSSIBLE "NO" BIT
	MOVEI	T3,33		;SEND OUT AN
	PUSHJ	P,COMTYO##	; ESCAPE
	POP	P,T1		;RESTORE INDEX
	HLRZ	T3,TTCDAT(T1)	;ASSUME NORMAL COMMAND
	SKIPGE	P1		;DID HE SAY NO?
	HLRZ	T3,TTCWDD(T1)	;YES--GET ALTERNATE BYTE
	PUSHJ	P,COMTYO##	;SEND TO TTY
	JRST	CPOPJ1##	;GOOD RETURN
;HERE TO PROCESS A NUMBER
TTCNUM:	PUSH	P,T1		;SAVE INDEX
	PUSHJ	P,NUMARG	;GO READ A NUMBER
	  MOVEI	T2,0		;NONE THERE DO DEFAULT
	POP	P,T1		;RESTORE INDEX
TTCNUP:	LDB	P2,[POINT 9,TTCDAT(T1),8]	;IS NUMBER BELOW
	CAMGE	T2,P2		;THE MIN VALUE
	POPJ	P,0		;YES
	LDB	P2,[POINT 9,TTCDAT(T1),17]	;IS NUMBER ABOVE
	CAMLE	T2,P2		;THE MAX
	POPJ	P,0		;YES -- ERROR
	HLRZ	T1,TTCWDD(T1)	;ADDRESS OF BYTE POINTER
	TLZ	P1,400000	;CLEAR THE "CLEAR" FLAG
	EXCH	U,P1
	DPB	T2,(T1)		;STORE
	EXCH	U,P1
	JRST	CPOPJ1##	;SKIP RETURN

;HERE TO PROCESS SET TTY (NO) TAPE COMMAND
;ROUTINE REMEMBERS TO CLEAR L2RXON
TTCTAP:	MOVEI	T2,L2RXON##	;GET REAL STATUS BIT
	MOVE	T4,P1		;COPY ADDRESS
	TLZ	T4,400000	;CLEAR BIT
	SKIPGE	P1		;IS THIS NO TAPE?
	ANDCAM	T2,LDBBY2##(T4)	;YES, CLEAR BIT
	PJRST	TTCSET		;THEN GO DO L2LTAP

;HERE TO PROCESS TTY TYPE COMMAND
TTCTYP:	PUSHJ	P,CTEXT1	;GET TERMINAL TYPE
	MOVE	U,P1		;GET LDB ADDRESS
	TLZ	U,400000	;CLEAR POSSIBLE "NO" BIT
TTUTYP::MOVE	T1,[-TTTWDN##,,CTTWDT##] ;AOBJN POINTER TO TYPES TABLE
	PUSHJ	P,FNDNAM	;FIND THE TERMINAL TYPE
	  POPJ	P,		;FAT FINGERS
TTUTYX:	AOS	(P)		;SUCCESS
	JRST	SETTTC##	;SET DEFAULT CHARACTERSITICS

;HERE TO PROCESS A TTY EDITOR COMMAND
TTCEDT:
IFN FTMP,<
	PUSHJ	P,GETMM##	;MUST HAVE MM TO GET NZS CORE
	  JRST	DLYCM1		;DEFER TO NEXT CLOCK TICK IF CAN'T GET IT
> ;END FTMP
	MOVE	U,P1		;GET THE TARGET LDB
	PUSH	P,P2		;SAVE THE FUNCTION REGISTER
	TLZE	U,400000	;DID HE TYPE 'NO'
	TDZA	P2,P2		;YES, DON'T WANT IT THEN
	MOVEI	P2,1		;ELSE WE WANT A BUFFER
	PUSHJ	P,SCNEDT##	;GO SET THE EDITOR
	  JRST	TTCED1		;RAN OUT OF MEMORY??
	AOS	-1(P)		;SUCCESS,,REMEMBER TO GIVE A SKIP RETURN
	POP	P,P2		;ELSE RESTORE PROPER REGISTERS
IFE FTMP,<POPJ	P,>		;RETURN
IFN FTMP,<PJRST	GIVMM##>	;GIVE UP MM AND RETURN
TTCED1:
IFN FTMP,<PUSHJ P,GIVMM##>	;RETURN THE MM
	JSP	T1,COMER	;TYPE AN ERROR MESSAGE
	ASCIZ	/No buffer memory available/
	SUBTTL	FINISH AND CLOSE COMMANDS

; "FINISH DEVICE" - CLOSES,RELEASE AND DEASSIGNS DEVICE
;JOB MUST HAVE CORE

CFINI::	TDZA	T1,T1		;FINISH - SET T1=0
CLSCOM::SETO	T1,		;CLOSE - T1=-1
	MOVEM	T1,.JDAT+JOBFDV## ;SAVE WHICH COMMAND IN JOBDAT
	PUSHJ	P,SETASA	;SET JS.ASA
	PUSHJ	P,CTXDEV	;GET DEVICE NAME
	JUMPE	T2,FINALL	;ALL DEVICES IF NO OTHER ARG
	MOVE	T1,T2		;PUT NAME IN RIGHT AC
	PUSH	P,U		;SAVE ADDR OF TTY LDB
	PUSHJ	P,DEVSRG##
	  JRST	NOTDV1		;PRINT NOT A DEVICE
	HRRM	F,.JDAT+JOBFDV##  ;STORE DDB ADR. IN JOB DATA AREA
	POP	P,U		;RESTORE ADDR OF TTY LDB
	MOVEI	T1,[ASCIZ /Not legal for disk-like devices
/]
	MOVE	T2,DEVMOD(F)	;IS IT A DISK?
	TLNE	T2,DVDSK
	JRST	ERRMES		;YES,MIGHT BE SEVERAL DDBS,DON'T TRY
	PJSP	T2,MSTART##	;SETUP MONITOR JOB AND RETURN
				; RETURN HERE AT UUO LEVEL WHEN SCHEDULED
	JSP	T1,MONSTR##	;SETUP ACS,R,P
	HRRZ	F,.JDAT+JOBFDV##  ; AND R
	MOVEI	T1,ASSPRG	;SEE IF
	TDNN	T1,DEVMOD(F)	; OPEN
	JRST	[SKIPGE	.JDAT+JOBFDV##	;SEE IF FIN
		JRST	.+1	;NO -- DO IT ANYWAY
		TLZ	M,NOPER!NOCRLF!TTYRNU
		TLO	M,CMWRQ	 ;FIX FLAGS FOR DEASSIGN
		PUSHJ	P,DEASI1 ;DEASSIGN
		JRST	CFINIX]	;STOP JOB
	PUSHJ	P,CFIN		;DO THE ACTUAL FIN (OR CLOSE)
	JRST	CFINIX		;STOP JOB SO HE CANNOT CONTINUE
;SUBROUTINE TO DO ACTUAL FIN
CFIN:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,0		;START AT CHANNEL 0
FDVI:	PUSHJ	P,NXTCH##	;GET NEXT DEVICE
	  JRST	FDV3
	HRRZ	F,.JDAT+JOBFDV## ;GET DEV TO RELEASE
	CAIE	F,(T1)		;IS THIS WHAT WE WANT TO CLOSE?
	JRST	FDVI		;NO, CONTINUE
	PUSHJ	P,WAIT1##	;WAIT FOR INACTIVE DEVICE
	MOVSI	T2,DVTTY	;SET UP TTY BIT
	SKIPN	.USVRT		;IF VIRTUAL JOB
	TDNE	T2,DEVMOD(F)	;OR IF I/O TO A TTY
	SETZM	DEVBUF(F)	;THEN FORGET BUFFERS
	SKIPN	.USVRT		;IF VIRTUAL JOB
	JRST	FDV2		;NOT THE CASE
	MOVSI	T3,0		;SET UP
	PUSHJ	P,RTIEVM##	;TELL MONITOR ABOUT BUFFERS
	MOVSI	T3,0
	PUSHJ	P,RTOEVM##
FDV2:	PUSH	P,DEVMOD(F)
	PUSH	P,.JDAT+SGANEW
	PUSH	P,.JDAT+SGAHGH
	MOVE	T1,[1,,SGAHGH]
	MOVSI	T2,-1(P1)
	HRRI	T2,7
	SKIPL	.JDAT+JOBFDV##
	HRRI	T2,23
	DMOVEM	T1,.JDAT+SGANEW
	FILOP.	SGANEW,
	  JFCL
	POP	P,.JDAT+SGAHGH
	POP	P,.JDAT+SGANEW
	POP	P,T1
	TRNN	T1,ASSCON
	POPJ	P,
FDV3:	MOVE	J,.CPJOB##	;GET JOB NUMBER
	SKIPL	F,.JDAT+JOBFDV##  ;RESET F, SKIP IF NOT FIN
	PUSHJ	P,DEASG		;DEASSIGN DEVICE IF FIN
	  POPJ	P,		;IGNORE IF NOT ASSIGNED BY CONSOLE
	POPJ	P,
;HERE TO FIN ALL DEVICES JOB OWNS
FINALL:	PJSP	T2,MSTART##	;SETUP MONITOR JOB, RETURN AT UUO LEVEL
	JSP	T1,MONSTR##	;SETUP R, R,P
	HLRZ	F,DEVLST##	;START OF DDB CHAIN
FINAL1:	LDB	T1,PJOBN##	;JOB WHICH OWNS DEVICE
	HRRM	F,.JDAT+JOBFDV## ;SAVE DDB ADDR IN CASE CFIN IS CALLED
	CAMN	T1,.CPJOB##	;THIS JOB OWN DEVICE?
	PUSHJ	P,CFIN		;YES, FIN (OR CLOSE) IT
	PUSHJ	P,NXDDB##	;STEP TO NEXT DDB
	  SKIPE	F		;DONE IF 0
	JRST	FINAL1		;TEST NEXT
CFINIX:	HLLZS	JBTDDB##(J)	;NOT IN ANY I/O WAIT ANYMORE
	PUSHJ	P,CLRASA	;CLEAR JS.ASA
	PUSHJ	P,TTYFNU##	;DONE. FIND TTY LINE FOR JOB
	PJRST	HOLD##		;STOP JOB
;"RESOURCES" - PRINT OUT AVAILABLE DEVICES AND FREE BLOCKS ON THE DISK


FREDEV::PUSHJ	P,SAVE2##	;SAVE P1=P2
	PUSHJ	P,DSKRES##	;PRINT DISK INFO
	HLRZ	P1,DEVLST##	;GET DDB POINTER
	MOVEI	P2,0		;SET DEVICE NAME 0 FOR FIRST COMPARE
LOP01:	MOVE	T1,DEVMOD(P1)	;DEVICE CHARACTERISTICS
	TRNN	T1,ASSCON!ASSPRG	;DEVICE ASSIGNED BY CONSOLE OR PROGRAM?
	TLNE	T1,DVTTY!DVDSK	;NO, IS IT A TTY OR DSK?
	JRST	LOP02		;YES DO NOT PRINT
	HLRZ	T1,DEVNAM(P1)	;GET NAME OF NEXT DEVICE IN CHAIN
	SKIPE	DEVNAM(P1)	;DON'T PRINT COMMA IF NO NAME
	CAIN	T1,(SIXBIT /PTY/)	;A PSEUDO TELETYPE?
	JRST	LOP02		;YES. DONT MENTION IT.
	JUMPE	P2,LOP01B	;SUPPRESS LEADING COMMA
	PUSHJ	P,PRCOM		;PRINT COMMA
LOP01B:	MOVS	P3,DEVNAM(P1)	;GET DEVICE NAME
	HLLZ	T2,P3		;ASSUME SAME TYPE AS LAST ONE, PRINT
				; ONLY RH OF NAME (UNIT NUMBER)
	CAIN	P2,0(P3)	;IS IT REALLY THE SAME?
	JRST	LOP01A		;YES. PRINT THE UNIT NUMBER.
	MOVS	T2,P3		;NO. MUST PRINT WHOLE NAME,
	HRRZ	P2,P3		; AND GET THE NEW DEVICE IN FLAG AC.
LOP01A:	PUSHJ	P,PRNAME	;AS BEING FREE
LOP02:	HLRZ	P1,DEVSER(P1)	;GET NEXT DEVICE IN CHAIN
	JUMPN	P1,LOP01	;IS THERE ONE?
	MOVEI	P1,.C0CDB##	;POINT AT THE FIRST ONE
	SETO	P2,		;INDICATE FIRST CPU
LOP03:	SKIPGE	.CPRUN##-.CPCDB##(P1) ;CAN THIS CPU RUN JOBS?
	JRST	LOP04		;NO, DON'T PRINT IT
	PUSHJ	P,PRCOM		;PRINT A COMMA
	MOVE	T2,.CPLOG##-.CPCDB##(P1) ;GET CPU NAME
	AOSE	P2		;UNLESS FIRST TIME,
	HRLZS	T2		; LEAVE OFF THE "CPU" PART
	PUSHJ	P,PRNAME	;PRINT IT
LOP04:	HLRZ	P1,.CPCDB##-.CPCDB##(P1) ;GET LINK TO NEXT CDB
	JUMPN	P1,LOP03	;LOOP BACK IF MORE
	JRST	CRLF		;NO. DONE. PRINT CR, LF AND THEN POPJ
	SUBTTL	SUBROUTINES -- COMMAND SETUP
;ROUTINE TO CHECK FOR ACTIVE DEVICES
;NEVER GET HERE DURING SWAP IN OR OUT
;SINCE COMMAND TABLE SHOULD HAVE NOTRAN BIT ON

RUNCHK:	JUMPE	R,RUNCH1	;DOES JOB HAVE CORE IN MEMORY?
IFN FTMP&FTKL10,<
	PUSHJ	P,SBCCSH##	;MAKE SURE CPU1'S CACHE HAS BEEN
				; SWEPT FOR THIS JOB
>
	 S0PSHJ	ANYACT##	;YES, ARE DEVICES ACTIVE?
	  JRST	RUNCK2		;YES, DELAY COMMAND.
RUNCH1:	HRRZ	F,LDBDDB##(U)	;RESTORE F
	POPJ	P,

RUNCK2:	POP	P,(P)		;POP OFF RETURN ADDRESS (WE AREN'T GOING TO RETURN)
	JRST	CHKDLY		; AND DELAY THE COMMAND
;ROUTINE TO DELAY A COMMAND

;DELAYS COMMAND TO BE EXECUTED WHEN JOB IN CORE MEMORY
;AND CAUSES JOB TO BE SWAPPED IN(COMMAND WAIT BIT IS SET IN JBTSTS)
;AND POPS LEVEL UP ONE.


DLYCM::	PUSHJ	P,DLYCOM##	;SET COMMAND WAIT BIT IN JOB STATUS AND PUT
				; JOB IN COMMAND WAIT QUEUE
				; SO JOB IS NOT RUNNABLE ANY MORE
;ROUTINE TO DELAY A COMMAND IF A SWAP OUT OR IN IS IN PROGRESS
;DIFFERS FROM DLYCM IN THAT JOB IS NOT MADE TO BE SWAPPED IN
;REQUIRED FOR DELAYING COMMAND IF SYSTEM
;TAPE USER TYPES ^C (HALT COMMAND)

DLYCM1::AOS	LINSAV##	;INCR. COMMAND POINTER SO NEXT CALL
				; BY COMMAND DECODER CALL START SCANNING
				; WITH LINE AFTER DELAYED COMMAND.
DLYCM2:	MOVE	P,.CPISF##	;GET INITIAL PDL POINTER BACK
IFN FTRSP,<
	TLNE	M,TTYRNC!TTYRNU ;WILL THIS COMMAND CAUSE JOB TO BE RUN?
	PUSHJ	P,SETRSP##	; RESPONSE, IF NOT ALREADY SET
>
	NTGIVE			;GIVE UP THE INTERLOCK IF IT WAS A NETWORK COMMAND
	JRST	T2POPJ##	;TTY LINE #
				;THEN EXIT FROM COMMAND DECODER.

ABORTC::SKIPN	.CPISF##	;AT UUO LEVEL?
	POPJ	P,		;YES, JUST RETURN
	MOVE	P,.CPISF##	;HERE TO GET OUT OF A COMMAND (CLEAN'S UP THE STACK)
	XJRST	[MCSEC1+COMRET]	;GO TELL SCNSER THE COMMAND IS DONE
	SUBTTL	SUBROUTINES -- GET A WORD


;ROUTINE TO RETURN NEXT ALPHANUMERIC STRING
; IN COMMAND LINE (SIXBIT)
;CALL:	PUSHJ P, CTEXT
; SIXBIT STRING RETURN LEFT JUSTIFIED IN AC T2


CTEXT::	PUSHJ	P,COMTYS	;SKIP CHAR
CTEXT1::PUSHJ	P,SKIPS1	;SKIP LEAD SPACES,TABS,NULLS AND CLEAR T2
	  POPJ P,0		;NOTHING THERE.
	PUSHJ	P,SAVE1##	;SAVE P1
	SKIPA	P1,[POINT 6,T2]
CTEX0:	PUSHJ	P,COMTYS	;ROUTINE IN SCNSER TO PICK UP CHAR.
	PUSHJ	P,CTEX		;IS IT ALPHANUMERIC
	  POPJ P,0		;NO
	TRC	T3,40		;CONVERT TO SIXBIT
	TLNE	P1,770000	;SIX CHARS YET?
	IDPB	T3,P1		;NO. BUILD WORD
	JRST	CTEX0		;LOOP FOR MORE
;SCAN FOR ALPHANUMERIC CHAR IN T3
CTEX:	CAIL	T3, "0"
	CAILE	T3, "Z"		;LETTERS ARE LARGER THAN NOS.
	POPJ	P,0		;NEITHER
	CAILE	T3, "9"
	CAIL	T3, "A"
	AOS	(P)		;LETTER OR NUMBER RETURN
	POPJ	P,0		;NOT-LETTER/NUMBER RETURN

CTXDEV::PUSHJ	P,CTEXT1	;GET A WORD
	CAIN	T3,":"		;AND IF TERM IS A COLON,
	PUSHJ	P,COMTYS	;DISCARD IT
	POPJ	P,0		;RETURN FROM CTXDEV
	SUBTTL	SUBROUTINES -- GET CHARACTER

;ROUTINE TO IGNORE LEADING SPACES, TABS,
;ALSO CLEARS T2
;CALL:	PUSHJ P,SKIPS1	;TO CONSIDER CURRENT CHARACTER
;	PUSHJ P,SKIPS		;TO DISCARD CURRENT CHARACTER
;NON-SKIP RETURN MEANS END OF LINE
;SKIP RETURN MEANS SOMETHING THERE, IN T3 AND .CPMCH



;ROUTINE TO IGNORE LEADING SPACES AND TABS. ALSO, CLEARS T2
;FOR USE BY ANYRIN AND CTEXT

SKIPS::	PUSHJ	P,COMTYS	;DISCARD CURRENT CHARACTER
SKIPS1::MOVEI	T2,0		;CLEAR ANSWER FOR NUMERIC AND TEXT INPUTS
	PUSHJ	P,CTIGLC##	;GET LAST CHAR SCANNED
	CAIE	T3,11		;TAB?
	CAIN	T3,40		;OR SPACE?
	JRST	SKIPS		;YES. DISCARD IT
	CAIL	T3,40		;BREAK CHARACTER?
	AOS	0(P)		;NO. SKIP RETURN
	POPJ	P,0		;RETURN.


;COMTYS - ROUTINE TO READ COMMAND AND STOP ON COMMENT
;CALL:	PUSHJ P,COMTYS
;RETURN WITH CHARACTER IN T3 (12 IF ; OR !)

COMTYS::PUSHJ	P,COMTYI##	;GET CHARACTER
	CAIL	T3,"A"+40	;LOWER CASE?
	CAILE	T3,"Z"+40
	SKIPA
	TRZ	T3,40		;YES, CONVERT TO UPPER CASE
	CAIE	T3,"!"		;SEE IF EXCLAMATION
	CAIN	T3,";"		;SEE IF SEMI-COLON
	MOVEI	T3,12		;YES, CHANGE TO LINEFEED
	PUSHJ	P,CTISLC##	;SAVE AS LAST CHAR SCANNED
	POPJ	P,
	SUBTTL	SUBROUTINES -- COMMAND DECODER TYPE OUT ROUTINES


;ROUTINE TO APPEND A "?" TO INPUT STRING AND SET AS OUTPUT
;CALLED FROM OCTIN, RETURNS TO SECOND LEVEL ON PDL
;CALL:	MOVE T1, BYTE POINTER TO LAST CHAR. IN INPUT STRING
;	PUSHJ P, COMERA

COMERP::POP	P,0(P)		;REMOVE SUB. RETURN BEFORE CALLING COMERA
COMERA::PUSHJ	P,COMTYI##	;SKIP ONE MORE CHARACTER

;ROUTINE TO TYPE ALL OF A COMMAND ACCEPTED, FOLLOWED BY
;A QUESTION MARK
;CALL:	PUSHJ P, COMERR

;COMMAND NOT IN COMMAND DIRECTORY

NOCOM::
COMERR::PUSH	P,T2
	PUSHJ	P,CTIGBP##	;GET THE INPUT BYTE POINTER
	PUSH	P,T1		;SAVE ERROR POSITION ON THE STACK
	PUSHJ	P,TRESCN##	;BACK UP TO START OF COMMAND
	PUSHJ	P,PRQM		;TYPE ? FOR BATCH
COMERL:	PUSHJ	P,COMTYI##	;GET A CHAR FROM COMMAND
	CAIN	T3,3		;^C?
	JRST	COMER1		;BETTER LEAVE OR KAF
	PUSHJ	P,CTIGBP##	;GET THE BYTE POINTER
	SKIPE	T1		; IF IT'S NULL, WE'RE DONE
	CAMN	T1,0(P)		; ..
	JRST	COMER1		;YES
	PUSHJ	P,USEARO##	;NO. TYPE CHAR, IN ARROW MODE
	CAIE	T3,12
	JRST	COMERL		;LOOP FOR MORE

COMER1:	POP	P,T1		;REMOVE OLD POSITION FROM STACK
	POP	P,T2
	PUSHJ	P,PRQM		;APPEND ? TO ERRONEOUS WORD
	TLO	M,ERRFLG	;SET ERROR FLAG
	PUSHJ	P,CRLF		;ADD CRLF
	PJRST	ABORTC		;TERMINATE COMMAND

;ROUTINE TO PRINT ?DEVICE NAME

PRNAMQ:	PUSHJ	P,PRQM
	TLO	M,ERRFLG	;SET ERROR FLAG
	PJRST	PRNAME
; ROUTINE TO PRINT A CRLF, THEN AN ERROR MESSAGE
ERRCRL::PUSH	P,T1		;SAVE ADDRESS OF TEXT
	PUSHJ	P,CRLF		;TYPE A CRLF
	POP	P,T1		;RESTORE TEXT
;	PJRST	ERRMES		;TYPE "?ERROR-TEXT" AND RETURN

;ROUTINE TO PRINT A COMMAND ERROR MESSAGE
;SAME CALL AS CONMES

ERRMES::PUSHJ	P,PRQM
ERRMSN:	TLO	M,ERRFLG	;INDICATE AN ERROR
	PUSHJ	P,CONMES	;PRINT MESSAGE
	MOVEI	J,0		;CLEAR JOB NUMBER TO INDICATE ERROR
	PJRST	CRLF		;FALL INTO CRLF

;ROUTINE TO PRINT "TOO FEW ARGUMENTS"
;CALL:	MOVE U,BYTE POINTER
;	PUSHJ P,NOTENF
NOTENP::POP	P,(P)		;REMOVE SUBROUTINE CALL BEFORE CALLING NOTENF
NOTENF::MOVEI	T1,[ASCIZ	/Too few arguments
/]
	PUSHJ	P,ERRMES	;REPORT THE ERROR
	PJRST	ABORTC		;DIE

;ROUTINE TO PRINT A MONITOR DOT AT LEFT MARGIN
;CALL:	PUSHJ	P,PRDOTC
PRDOTM::
IFN FTNET,<
	SE1ENT			;NEED TO ACCESS THE LDB
	SKIPGE	LDBREM##(U)	;IF SET HOST IN PROGRESS,
	POPJ	P,		;PUNT THE TYPEOUT
> ;END IFN FTNET
	TLNN	M,NOFLM		;UNLESS REQUESTED OTHERWISE,
PRDOTC::PUSHJ	P,COMFLM##	;FORCE LEFT MARGIN IN SCNSER
	PJRST	PRPER		;FALL INTO PRPER
	SUBTTL	SUBROUTINES -- GENERAL TYPE OUT ROUTINES


;ROUTINE TO PRINT CARRIAGE RETURN-LINE-FEED
;CALL:	MOVE U,LDB ADDRESS OF TTY
;	PUSHJ P,CRLF

PCRLF::!			;A ROSE BY ANOTHER NAME ...
CRLF::	MOVEI	T1,[ASCIZ /
/]
;	PJRST	CONMES		;FALL INTO CONMES


;ROUTINE TO MOVE ASCIZ CHAR. STRING TO CONSOLE OUTPUT BUFFER
; CALL:	MOVE U,LDB ADDRESS OF TTY
;	MOVEI T1,ADDRESS OF ASCIZ MESSAGE
;	PUSHJ P,CONMES
;STRING TERMINATED BY NULL

CONMES::HRLI	T1,(POINT 7)	;FORM ASCIZ BYTE POINTER
	PUSH	P,T1		;SAVE BYTE POINTER
CON0:	ILDB	T3,(P)		;GET NEXT CHAR.
	JUMPE	T3,TPOPJ##	;IS IT NULL?(IF YES, DO POP T1, POPJ)
	PUSHJ	P,COMTYO##	;NO, STORE TTY OUTPUT BUFFER
	JRST	CON0		;KEEP GOING


;ROUTINE TO PRINT INLINE ASCIZ MESSAGE
;CALL:	PUSHJ P,INLMES
;	ASCIZ /THE MESSAGE/
;RETURN TO NEXT LOC AFTER MESSAGE

INLMES::POP	P,T1		;SETUP PRINT ADRESS FOR CONMES
	PUSHJ	P,CONMES
	SSX	T1,IFIW		;RETURN IN RIGHT SECTION
	JRST	1(T1)		;RETURN TO NEXT LOC AFTER MESSAGE
;ROUTINE TO TYPE COMMA
;PRESERVES T1
PRCOM::	MOVEI	T3,","
	PJRST	PRCHR

;SUBROUTINE TO PRINT 3 SPACES
PR3SPC::PJSP	T1,CONMES
	ASCIZ	/   /

;SUBROUTINE TO PRINT A SPACE
PRSPC::	PJSP	T1,CONMES
	ASCIZ	/ /

;SUBROUTINE TO PRINT A PLUS
PRTPLS::PJSP	T1,CONMES
	ASCIZ	/+/

;ROUTINE TO PRINT A PERIOD
;CALL:	PUSHJ P,PRPER
PRPER::	JSP	T1,CONMES
	ASCIZ	/./

;ROUTINE TO PRINT A SLASH
PRSLSH::JSP	T1,CONMES
	ASCIZ	./.

;ROUTINE TO APPEND ? TO ERROR MESSAGE
;CALL	PUSHJ P,PRQM
;	RETURN
PRQM::	MOVEI	T3,"?"
PRCHR::	PUSH	P,T1
	PUSHJ	P,COMTYO##
	PJRST	TPOPJ##
;ROUTINE TO TYPE A NUMBER AS HALFWORDS SEPARATED BY COMMAS.
;CALL:	MOVE	T1,NUMBER
;	PUSHJ	P,HWDPNT
;	RETURN

HWDPNT::PUSH	P,T1		;SAVE T1 FOR RH
	HLRZS	T1		;KEEP JUST LH
	PUSHJ	P,OCTPNT	;PRINT AS 6 OCTAL DIGITS
	PUSHJ	P,INLMES	;PRINT THE TWO COMMAS
	ASCIZ	/,,/		;...
	POP	P,T1		;RESTORE T1 FOR RH
	PJRST	OCTPNT		;PRINT RH AND RETURN

;ROUTINE TO TYPE A NUMBER AS HALFWORDS SEPARATED BY COMMAS.
;DIFFERES FROM HWDPNT IN THAT THE NUMBERS ARE NOT ZERO FILLED.
;CALL:	MOVE	T1,NUMBER
;	PUSHJ	P,PRTXWD
;	RETURN

PRTXWD::TLNN	T1,-1		;ANYTHING IN LH?
	PJRST	PRTDI8		;NO, THEN JUST LET PRTDI8 DO ITS THING
	PUSH	P,T1		;SAVE T1
	HLRZS	T1		;GET LEFT HALF
	PUSHJ	P,PRTDI8	;PRINT IT
	PUSHJ	P,INLMES	;ADD SOME NOISE
	ASCIZ	/,,/		;...
	POP	P,T1		;RESTORE T1
	HRRZS	T1		;KEEP JUST RH
	PJRST	PRTDI8		;PRINT RH AND RETURN


;ROUTINE TO PRINT 6 DIGIT OCTAL NUMBER
;CALL:	MOVEI LINE,LINE DATA BLOCK ADDRESS FOR TTY
;	HRR T1, OCTAL NUMBER
;	PUSHJ P,OCTPNT
;	RETURN T2,PRESERVED,T1 DESTROYED

OCTPNT::HRLZ	T1,T1		;MOVE TO LH FOR ROTATING
	TRO	T1,700000	;SETUP AN END FLAG
OCTP1:	ROT	T1,3		;GET NEXT OCTAL DIGIT
	TLNN	T1,777777	;WAS THAT FLAG?
	POPJ	P,		;YES, DO NOT PRINT IT
	PUSH	P,T1		;SAVE T1 OVER I/O ROUTINE
	PUSHJ	P,PRTNUM	;NO, PRINT OCTAL DIGIT
	POP	P,T1		;RESTORE T1
	HRRI	T1,0		;CLEAR RH
	JRST	OCTP1		;GET NEXT OCTAL DIGIT
;ROUTINE TO ADD 1 TO T1 AND PRINT DECIMAL
;SAME CALL AS OCTPNT

DECP1::	AOJA	T1,RADX10	;ADD 1 AND GO PRINT

;ROUTINE TO PRINT DECIMAL
;CALL:	SAME AS OCTPNT
;T2:	PRESERVED

RADX10::PUSH	P,T2		;SAVE T2
	PUSHJ	P,PRTDIG	;PRINT DECIMAL DIGITS
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN

;RECURSIVE DECIMAL PRINT ROUTINE
;CALL:	MOVE T1,DECIMAL NO.
;	PUSHJ P,PRTDIG

PRTDIG::
IFN FTXMON,<
	PUSHJ	P,SSEC0##	;RUN IN SECTION 0
>
PRTDGX:	IDIVI	T1,12		;DIVIDE BY 10
	HRLM	T2,(P)		;RT ON PD LIST
	JUMPE	T1,.+2		;FINISHED?
	PUSHJ	P,PRTDGX	;NO, CALL S OR F
PRTNMM:	HLRZ	T1,(P)		;YES, GET LAST NUMBER
PRTNUM:	MOVEI	T3,"0"(T1)	;CONVERT TO ASCII
	PJRST	COMTYO##	;AND TYPE IT OUT

;RECURSIVE OCTAL PRINT ROUTINE
;CALL:	SAME AS PRTDIG

PRTDI8::
IFN FTXMON,<
	PUSHJ	P,SSEC0##	;RUN IN SECTION 0
>
PRTD8X:	IDIVI	T1,10		;DIVIDE BY 8
	HRLM	T2,(P)		;PUT ON STACK
	JUMPE	T1,PRTNMM	;FINISHED?
	PUSHJ	P,PRTD8X	;NO - LOOP
	PJRST	PRTNMM		;OUTPUT
;SUBROUTINE TO PRINT 22 BIT OCTAL ADDRESS
;CALL:	MOVE	T1,22 BIT ADDRESS
;	PUSHJ	P,PRT22A
;	ALWAYS RETURN

PRT22A::PUSH	P,T1		;SAVE 22 BIT ADDRESS
	HLRZ	T1,(P)		;GET HIGH ORDER HALF
	JUMPE	T1,PRT22B	;IS IT 0 (USUALLY EXCEPT BIG SYSTEMS)
	PUSHJ	P,PRTDI8	;NO, PRINT AS LEADING 0 SUPPRESSED OCTAL
PRT22B:	POP	P,T1		;GET LOW ORDER HALF
	PJRST	OCTPNT		;PRINT AS NON ZERO SUPPRESSED OCTAL (RH ONLY)


;ROUTINE TO PRINT SIXBIT NAME
;CALL	MOVE U,ASCII OUTPUT BYTE POINTER
;	MOVE T2,NAME
;	PUSHJ P,PRNAME

PRNAM1::MOVEI	T1,0
	LSHC	T1,6		;SHIFT IN NEXT CHAR.
	MOVEI	T3," "-' '(T1)	;ASCII VERSION INTO CHREC FOR OUTCHS
	PUSHJ	P,COMTYO##	;OUTPUT CHARACTER
PRNAME::JUMPE	T2,CPOPJ##
	JRST	PRNAM1


;ROUTINE TO PRINT SIXBIT WORD WITH TRAILING SPACES
;CALL:	SAME AS PRNAME.

PRSIXB::MOVEI	T3,6		;NUMBER OF CHARACTERS
	PUSH	P,T3		;SAVE T3
PRSIX0:	SETZ	T3,		;CLEAR RECIPIENT
	ROTC	T2,6		;SHIFT IN NEXT CHARACTER
	ADDI	T3," "-' '	;CONVERT TO ASCII
	PUSHJ	P,COMTYO##	;TYPE IT OUT
	SOSLE	(P)		;MORE TO DO?
	JRST	PRSIX0		;YES, LOOP
	JRST	T3POPJ##	;RESTORE T3 AND RETURN
	SUBTTL	SUBROUTINES -- COMMAND INPUT


;ROUTINE TO RETURN HIGHEST RELATIVE ADDRESS SPECIFIED BY
; THE USER'S CORE ARGEMENT
;CALLING SEQUENCE:
;	PUSHJ	P,CORARG
;	RETURN HERE IF NO ARGUMENT WAS SPECIFIED
;	RETURN HERE - T1=HIGHEST RELATIVE ADDRESS REQUESTED
;NEVER RETURNS IF ARGUMENT IS ILLEGAL
CORARG::PUSHJ	P,SKIPS1	;SKIP LEADING BLANKS, ETC.
CORAR1:	POPJ	P,K2WLSH	;NO ARGUMENT SPECIFIED
	CAIE	T3,"K"		;DON'T ALLOW "P" OR "K"
	CAIN	T3,"P"		; WITHOUT A PRECEEDING #
	JRST	COMERP		; SINCE AMBIGUOUS
	PUSHJ	P,DECIN1	;GET THE ARGUMENT
	  POPJ	P,		;NULL RETURN
	  JRST	CORAR2		;SEE IF "P" OR "K"
	PUSHJ	P,SGSEND	;EOL?
	  CAIN	T3,"/"		;NO, IS WHAT IS LEFT SWITCHES?
	TDZA	T3,T3		;YES TO EITHER IS OK, SET E.O. LINE
	JRST	COMERP		;NO, BAD DELIMITER
	LSH	T2,K2WLSH
	CAILE	T3,40		;AN ARG. WAS TYPED, DELIMITER OKAY?
	JRST	COMERP		;BAD DELIMITER
	JRST	CORAR3
CORAR2:	CAIE	T3,"K"		;CORE ARGUMENT IN # OF K?
	CAIN	T3,"P"		; OR NUMBER OR PAGES
	SKIPA	T1,CORAR1
	JRST	COMERP		;NO, DON'T ALLOW A,B,C, ETC.
	CAIN	T3,"P"		;DID USER TYPE "P"?
	SOS	T1		;YES
	LSH	T2,(T1)		;CONVERT TO WORDS
	PUSHJ	P,COMTYS	;DISCARD "P"OR"K"
CORAR3:	SOSL	T1,T2		;CONVERT TO HIGHEST RELATIVE ADDR.
	JRST	CPOPJ1##	;GIVE ARG FOUND RETURN
	AOJA	T1,CPOPJ1##	;MAKE ZERO BACK INTO ZERO

;SUBROUTINE TO PRINT "P" OR "K" AFTER A CORE TYPE OUT
;CALLING SEQUENCE:
;	PUSHJ	P,PRPORK
;	ALWAYS RETURN HERE

PRPORK:	MOVEI	T3,"P"		;TELL NUMBER OF PAGES
	PJRST	PRCHR		;PRINT "P"
;SUBROUTINE TO READ A NUMBER IN THE FORM X,,Y. RETURNS CPOPJ IF NO NUMBER
; WAS TYPED, 0 IN T2, CPOPJ1 IF A NUMBER WITH SEVEN OR MORE DIGITS (IGNORING
; LEADING ZEROS) WAS TYPED, A NUMBER OF THE FORM X,,Y WAS TYPED, OR A NUMBER
; X <BLANK> Y WAS TYPED. CALL OCTPAR IF AN 18 BIT NUMBER WILL DO. CALL OCTPRR
; IF A 36 BIT NUMBER IS REQUIRED. DOESN'T RETURN IF REQUIREMENTS NOT MET OR
; INVALID NUMBER WAS TYPED.

OCTPAR:	PUSHJ	P,OCTPA0	;DO REAL WORK
	  POPJ	P,		;NOTHING FOUND
	  JRST	COMERP		;ERROR
	JRST	CPOPJ1##	;GOOD RETURN
OCTPRR:	PUSHJ	P,OCTPA0	;DO REAL WORK
	  POPJ	P,		;NOTHING FOUND
	  JRST	COMERP		;ERROR
	JRST	CPOPJ1##		;GOOD RETURN

OCTPA0:	TDZA	S,S		;18 BIT NUMBER IS OK
OCTPR0:	MOVEI	S,1		;INDICATE 36 BIT QUANITY REQUIRED
	PUSHJ	P,OCTIN1	;READ A NUMBER
	  POPJ	P,		;NONE THERE, MAY BE OK
	  JRST	CPOPJ1##	;ILLEGAL CHARACTER
	TLNE	T2,-1		;IF 7 OR MORE DIGITS, ITS A 36 BIT NUMBER
	JRST	CPOPJ2##	;GO USE THE NUMBER
	HRL	S,T2		;SAVE HIGH 18 BITS OF NUMBER
	CAIE	T3,","		;A COMMA TYPED? X,,Y IS A LEGAL CONSTRUCT
	JRST	OCTPA1		;NO, SPACE IS ALSO LEGAL
	PUSHJ	P,SKIPS		;SKIP THE COMMA AND GET THE NEXT CHARACTER
	  JRST	CPOPJ1##	;END OF LINE IS ILLEGAL
	CAIE	T3,","		;IF THERE WAS ONE, THERE MUST BE TWO
	JRST	CPOPJ1##	;NOPE
	PUSHJ	P,COMTYS	;SKIP OVER THE COMMA
	HRRI	S,2		;ALLOW X,,<CRLF> TO MEAN X,,0
OCTPA1:	PUSHJ	P,OCTARG	;READ ANOTHER NUMBER
	  JRST	[TRZE S,2	;SEEN ,,?
		 JRST OCTPA2	;YES, TREAT ,, <CRLF> AS 0
		 TRZE S,1	;A FULL WORD REQUIRED?
		 JRST CPOPJ1##	;YES, LESS THAN A FULL WORD IS ILLEGAL
		 HLRZS S	;18 BIT NUMBER, PUT IT IN THE RIGHT HALF
		 JRST OCTPA2]	;AND RETURN THAT
	TLNE	T2,-1		;MORE THAN A HALFWORD IS ILLEGAL HERE
	JRST	CPOPJ1##	;TELL THE USER THE ERROR OF HIS WAYS
	HRR	S,T2		;36 BIT NUMBER
OCTPA2:	MOVE	T2,S		;WHERE THE CALLER WANTS THE ANSWER
	JRST	CPOPJ2##	;NUMBER READ RETURN
;ROUTINE TO DEASSIGN A DEVICE EXCEPT CONTROLLING TTY
;CALL:	MOVE F, DEVICE DATA BLOCK
;	MOVE J, JOB NUMBER
;	PUSHJ P, DEASG
;	ERROR NOT PREVIOUSLY ASSIGNED
;	OK RETURN WITH DEVICE DEASSIGNED, EXCEPT CONTROLLING TELETYPE (LOGICAL NAME CLEARED)


DEASG:	SKIPN	DEVCHR(F)	;PROTOTYPE SPOOL DDB?
	JRST	CPOPJ1##	;YES
	LDB	T1,PJOBN##	;WAS DEVICE ASSIGNED TO THIS JOB?
	CAME	T1,J
	POPJ	P,		;NO, RETURN
DEASG1::PUSH	P,J		;SAVE JOB NUMBER
	MOVSI	T2,DVDIRI	;CLEAR DIRECTORY IN CORE BIT
	ANDCAB	T2,DEVMOD(F)	;SET DEVICE CHARACTERISTICS FOR TEST
				; AND ASGHGH
	SETZM	DEVLOG(F)	;CLEAR LOGICAL NAME
	TLNE	T2,TTYATC	;CONTROLLING TTY?
	JRST	IPOPJ1##	;YES, CAN'T DEASSIGN THAT!
	TRNE	T2,ASSCON	;IS DEVICE ASSIGNED BY CONSOLE?
	AOS	-1(P)		;YES, DO OK RETURN
	PUSHJ	P,ASGHGH##	;IF DTA OR MTA, CLEAR ANY HIGH SEGMENT NAMES
				; FROM THIS DEVICE SO NO NEW SHARING
				; DEVMOD SETUP IN T2 ON CALL
	MOVEI	T2,ASSCON	;SETUP ASSIGNED BY CONSOLE BIT FOR RELEA6
	PUSHJ	P,RELEA6##	;CLEAR JOB NO. IN DDB IF DDB NOT NEEDED
	PUSHJ	P,TTYKLQ##	;BE SURE TO CLEAN UP ASSIGNED TTY'S
	JRST	IPOPJ##		;RESTORE JOB NUMBER AND RETURN

;DEASTY--ROUTINE TO DEASSIGN ALL DEVICES EXCEPT CONTROLLING (ATTACHED) TTY
;CALL:	MOVE J, JOB NUMBER
;	PUSHJ P, DEASTY



DEASTY:	PUSH	P,F		;SAVE TTY DDB ADDRESS
	HLRZ	F,DEVLST##	;SEARCH ALL DDB'S
DEA1:	PUSHJ	P,DEASG		;TRY TO DEASSIGN IT
	JFCL			;IGNORE IF CAN'T
	PUSHJ	P,NXDDB##
	  JUMPE	F,FPOPJ##	;RESTORE TTY DDB AND EXIT
	JRST	DEA1		;TRY NEXT
;SUBROUTINE TO READ A DECIMAL NUMBER. THIS ROUTINE DIFFERS FROM
; DECIN IN THAT IF THERE IS NO NUMBER TO READ THE CURSOR
; IS NOT MOVED.
;CALL WITH:
;	PUSHJ	P,NUMARG
;	  RETURN HERE IF NO NUMBER (NOTHING CHANGED)
;	RETURN HERE NUMBER IN T2
;
NUMARG:	PUSHJ	P,CTIGBP##	;GET THE BYTE POINTER
	PUSH	P,T1		; AND SAVE THAT
	PUSHJ	P,CTIGLC##	;GET THE "LAST CHAR"
	PUSH	P,T3		;  AND SAVE THAT TOO.
	PUSHJ	P,DECIN1	;READ THE NUMBER
	  JRST	NUMAR1		;NO ARGUMENT
	  JRST	NUMAR1		;ILLEGAL CHARACTER
NUMAR0:	SUB	P,[2,,2]	;REMOVE JUNK FROM STACK
	JRST	CPOPJ1##	;GOOD RETURN
NUMAR1:	POP	P,T3		;GET CHAR TO RETURN
	EXCH	T1,(P)		;SAVE T1, GET BYTE POINTER
	PUSHJ	P,CTISBP##	;STORE THE BYTE POINTER
	PUSHJ	P,CTISLC##	;  AND THE "LAST CHAR READ"
	JRST	TPOPJ##		;RESTORE T1 AND RETURN

;SUBROUTINE TO READ A OCTAL NUMBER. THIS ROUTINE DIFFERS FROM
; NUMARG ONLY IN THE INPUT RADIX.
;CALL WITH:
;	PUSHJ	P,OCTARG
;	  RETURN HERE IF NO NUMBER (NOTHING CHANGED)
;	RETURN HERE NUMBER IN T2
;
OCTARG:	PUSHJ	P,CTIGBP##	;GET THE BYTE POINTER
	PUSH	P,T1		; AND SAVE THAT
	PUSHJ	P,CTIGLC##	;GET THE "LAST CHAR"
	PUSH	P,T3		;  AND SAVE THAT TOO.
	PUSHJ	P,OCTIN1	;READ THE NUMBER
	  JRST	NUMAR1		;NO ARGUMENT
	  JRST	NUMAR1		;ILLEGAL CHARACTER
	JRST	NUMAR0		;GOT IT

;SUBROUTINE TO READ A POTENTIALLY 30 BIT OCTAL ADDRESS
;CALL WITH:
;	PUSHJ	P,OCTPRG
;	  RETURN HERE IF NO NUMBER WAS TYPED (NOTHING CHANGED)
;	RETURNS HERE WITH NUMBER IN T2
;
OCTPRG:	PUSHJ	P,CTIGBP##	;GET THE BYTE POINTER
	PUSH	P,T1		; AND SAVE THAT
	PUSHJ	P,CTIGLC##	;GET THE "LAST CHAR"
	PUSH	P,T3		;  AND SAVE THAT TOO.
	PUSHJ	P,OCTPA0	;READ THE NUMBER
	  JRST	NUMAR1		;NO ARGUMENT
	  JRST	NUMAR1		;ILLEGAL CHARACTER
	JRST	NUMAR0		;GOT IT
;SUBROUTINE TO READ AN ARGUMENT, CALL FNDNAM
;IF NOT FOUND BY FNDNAM CURSOR IS NOT MOVED
;CALL WITH T1=AOBJN WORD FOR TABLE
;RETURNS SKIP IF FOUND BY FNDNAM, T1=INDEX
;RETURNS NON-SKIP IF NOT FOUND (NOTHING CHANGED)
TXTARG::PUSH	P,T1		;SAVE T1
	PUSHJ	P,CTIGBP##	;GET THE BYTE POINTER IN T1
	PUSHJ	P,CTIGLC##	;  THE LAST CHAR IN T3
	EXCH	T1,(P)		;SAVE BYTE POINTER, RESTORE T1
	PUSH	P,T3		;SAVE THE LAST CHAR.
	PUSH	P,T1		;SAVE AOBJN WORD
	PUSHJ	P,CTEXT1	;GET THE ARGUMENT
	POP	P,T1
	JUMPE	T2,NUMAR1
	PUSHJ	P,FNDNAM	;IN TABLE?
	  JRST	NUMAR1		;NO
	JRST	NUMAR0		;YES, CLEAN UP STACK AND GIVE FOUND RETURN
;ROUTINES TO READ NUMBERS FROM COMMAND STRING
;CALL:	MOVE P1,DESIRED INPUT RADIX
;	PUSHJ P, ANYRIN
;	NO ARG. TYPED RETURN, T2=0
;	ILLEGAL CHARACTER RETURN
;	NORMAL EXIT	;AC T2 CONTAINS NUMBER
;SCAN STOPS ON FIRST CR,DASH,SPACE,OR TAB OR ILLEGAL CHAR.
;SKIPS LEADING SPACES AND TABS


DECIN::	PUSHJ	P,COMTYS	;SKIP CHAR
DECIN1::PUSHJ	P,SAVE2##	;PRESERVE P1
	MOVEI	P1,12		;DECIMAL INPUT
	JRST	ANYRIN

OCTIN::	PUSHJ	P,COMTYS	;SKIP CHAR
OCTIN1::PUSHJ	P,SAVE2##	;PRESERVE P1  ;;WARNING -- SEE AOS -3(P) BELOW
	MOVEI	P1,10		;OCTAL INPUT
ANYRIN:	PUSHJ	P,SKIPS1	;SKIP LEADING SPACES, TABS, NULLS
	  POPJ	P,0		;NOTHING LEFT. RETURN.

	MOVEI	P2,0		;CLEAR DECIMAL ACCUMULATOR
	CAIE	T3,"#"		;SEE IF OCTAL FORCED
	JRST	ANYRI1		;NO--PROCEED
	MOVEI	P1,10		;YES--SET OCTAL RADIX
	TLO	P1,400000
	PUSHJ	P,COMTYS	;GET NEXT CHARACTER
ANYRI1:	PUSHJ	P,ANYR2		;SEE IF NULL FIELD
	  JRST .+2		;NOT END, SEE IF DIGIT
	  POPJ P,		;END--RETURN NULL
OCT0:	CAIL	T3,"0"		;IS CHARACTER .GE. A ZERO?
	CAIL	T3,"0"(P1)	;AND WITHIN RADIX BOUNDS?
	JRST	[CAIL	T3,"0"	;NO. NOT A LEGAL DIGIT
		CAILE	T3,"9"
		JRST	ANYR1
		JUMPL	P1,ANYR1
		TLO	P1,200000
		JRST	.+1]
	JFCL	17,.+1
	IMULI	T2,(P1)		;YES. SCALE INPUT SO FAR
	ADDI	T2,-"0"(T3)	;AND ADD IN THIS DIGIT
	IMULI	P2,^D10		;MULTIPLY DECIMAL INPUT
	JOV	ANYR1		;ON OVERFLOW, GIVE ILLEGAL CHARACTER RET
	ADDI	P2,-"0"(T3)	;INCLUDE THIS DIGIT
	PUSHJ	P,COMTYS	;GET ANOTHER CHARACTER
	CAIE	T3,"."		;SEE IF FORCING DECIMAL
	JRST	OCT0		;AND LOOP FOR MORE.
	MOVE	T2,P2		;YES--GET DECIMAL VALUE
	JUMPL	P1,ANYR1
	PUSHJ	P,COMTYS	;GET SEPARATOR
	TLZ	P1,200000
ANYR1:	AOS	-3(P)		;POINT TO ILLEGAL CHARACTER RETURN
	TLNE	P1,200000
	POPJ	P,
	CAILE	T3,40		;CHECK FOR LEGAL TERMINATORS
ANYR2:	CAIN	T3,","		;USED IN VARIOUS ROUTINES
	JRST	CPOPJ1##	;OK
	CAIE	T3,"["		;MORE
	CAIN	T3,"]"		; ..
	JRST	CPOPJ1##	;OK.
	CAIE	T3,"<"		;MORE
	CAIN	T3,">"		; ''
	JRST	CPOPJ1##	;OK.
	CAIE	T3,"("		;L. PAREN?
	CAIN	T3,"-"		;HYPHEN?
	JRST	CPOPJ1##	;OK.
	CAIN	T3,"/"		;SWITCHES?
	JRST	CPOPJ1##	;OK.
	POPJ	P,CPOPJ1##	;NO GOOD. GIVE "BAD CHARACTER RETURN"
; ROUTINE TO INPUT TIME SINCE MIDNIGHT
; LEGAL FORMATS ARE HH:MM[AM,PM] OR HH:MM:SS[AM,PM]
; THE COLONS, "AM", OR "PM" ARE ALL OPTIONAL
; CALL:	PUSHJ	P,RDTIM
;	  <ERROR>		;T1 POINTS TO ERROR TEXT
;	<NORMAL>		;T1 CONTAINS TIME IN SECONDS SINCE MIDNIGHT
;
; AC USAGE: T1 - T4
;
RDTIM::	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	SETZB	P1,T4		;INIT INTERMEDIATE RESULT AND COUNTER
	SETZ	P2,		;CLEAR A FLAG

RDTIM0:	IMULI	P1,^D100	;ADVANCE TO NEXT RESULT
	PUSHJ	P,DECIN		;GET NEXT SUPER-DIGIT
	  TDZA	T2,T2		;MAY HAVE TYPED HH::SS WHICH IS OK
	  JUMPL	T2,RDTIM7	;ERROR IF NEGATIVE
	CAIL	T2,^D60		;RANGE CHECK
	JUMPN	T4,RDTIM6	;TOO BIG FOR MINUTES OR SECONDS
	ADD	P1,T2		;ADD TO ACCUMULATOR
	CAIE	T3,":"		;SEE IF MORE TO COME
	JRST	RDTIM1		;NO--GO CONVERT RESULT
	CAIGE	T4,2		;TOO MAY FIELDS?
	AOJA	T4,RDTIM0	;NO--LOOP BACK FOR MORE
	JRST	RDTIM7		;ILLEGAL FORMAT

RDTIM1:	JUMPN	T4,RDTIM2	;JUMP IF NORE THAN ONE ARGUMENT
	CAILE	P1,^D2359	;A REASONABLE NUMBER FOR HH:MM?
	MOVEI	T4,2		;NO
RDTIM2:	CAIGE	T4,2		;TWO OR LESS ARGUMENTS?
	IMULI	P1,^D100	;YES--HAKE IT HH:MM:00
	CAILE	P1,^D235959	;STILL REASONABLE?
	JRST	RDTIM6		;HH GREATER THAN 23
	PUSHJ	P,RDTIM3	;CONVERT TO TIME IN SECONDS
	JUMPL	P1,CPOPJ##	;RETURN IF FAILURE
	SETZ	P2,		;INIT FLAG
	PUSHJ	P,AMPM		;CHECK FOR AM OR PM
	  JRST	RDTIM8		;NO GOOD--ILLEGAL FORMAT
	MOVE	T1,P1		;GET RESULT
	JRST	CPOPJ1##	;AND RETURN
RDTIM3:	MOVE	T2,P1		;GET RESULT SO FAR
	MOVEI	P1,0		;CLEAR RESULT
	MOVEI	T1,3		;INITIALIZE TO ALLOW THREE FIELDS
	MOVE	P2,P		;SAVE P INCASE OF ERRORS
RDTIM4:	IDIVI	T2,^D100	;SEPARATE TYPEIN
	PUSH	P,T3		;STORE LEAST DIGIT AWAY
	JUMPE	T2,RDTIM5	;JUMP IF ALL DONE
	SOJLE	T1,RDTIM7	;GIVE AN ERROR IF TOO MANY FIELDS
	PUSHJ	P,RDTIM4	;IF NOT, DO SOME MORE
RDTIM5:	POP	P,T1		;GET BACK HIGHEST DIGIT
	IMULI	P1,^D60		;MAKE ROOM IN RESULT
	ADD	P1,T1		;INCLUDE RESULT
	CAILE	T1,^D60		;SEE IF ERROR
	JRST	RDTIM6		;COMPLAIN IF COMPONENT TOO BIG
	POPJ	P,		;RETURN

RDTIM6:	JSP	T2,RDTIM9	;TIME COMPONENT TOO LARGE
RDTIM7:	JSP	T2,RDTIM9	;ILLEGAL FORMAT IN TIME SPECIFICATION
RDTIM8:	JSP	T2,RDTIM9	;ILLEGAL USE OF AM/PM CONSTRUCT
RDTIM9:	SUBI	T2,RDTIM6	;GET ERROR CODE
	TLZ	T2,777777	;STRIP OFF PC FLAGS OR SECTION NUMBER
	MOVE	T1,RDTIMM-1(T2)	;GET ADDRESS OF ERROR TEXT
	MOVNI	P1,1		;SET P1 NEGATIVE TO INDICATE FAILURE
	SKIPE	P2		;CALLED FROM WITHIN RDTIM3?
	MOVE	P,P2		;YES--FIX UP STACK TO AVOID STOPCODES
	POPJ	P,		;AND RETURN

RDTIMM:	[ASCIZ	|Time component too large|]
	[ASCIZ	|Illegal format in time specification|]
	[ASCIZ	|Illegal use of AM/PM construct|]


; CHECK FOR AM OR PM APPENDED TO TIME
AMPM:	MOVE	T1,[-AMPMLN,,AMPMTB] ;AOBJN POINTER TO LEGAL ARGS
	PUSHJ	P,TXTARG	;SEE WHAT WE'VE GOT
	  JRST	CPOPJ1##	;NOTHING
	CAILE	P1,^D12*^D60*^D60 ;GREATER THAN 12:00:00
	  POPJ	P,		;YES--ILLEGAL FORMAT
	SKIPE	T1		;SKIP IF AM
	ADDI	P1,^D12*^D60*^D60 ;OFFSET FOR PM
	JRST	CPOPJ1##	;AND RETURN

AMPMTB:	SIXBIT	/AM/
	SIXBIT	/PM/
AMPMLN==.-AMPMTB
;GET PROJECT-PROGRAMMER NUMBERS
;CALL:	MOVE T1,INPUT BYTE POINTER
;	PUSHJ P,PJPGNO
;
;(T2)LH _ PROJECT NUMBER
;(T2)RH _ PROGRAMMER NUMBER
;(T2) = 0 IF NO [ ]'S TYPED
;THE TERMINAL ] IS OPTIONAL

PJPGNO:	PUSH	P,P1
	MOVEI	P1,0		;PRESET A 0 JUST IN CASE
	PUSHJ	P,SKIPS1
	  JRST	PP2		;NOTHING ON LINE
	CAIE	T3,"["		;IS IT A "[" ?
	CAIN	T3,"<"		;OR 2741 EQUIV.
	SKIPA			;YES
	JRST	PP2		;EXIT.......

	PUSHJ	P,OCTIN		;GET FIRST ARG.-PROJ. NO.
	  JRST	[CAIN T3,"-"	;SEE IF [-]
		JRST	[PUSHJ	P,SKIPS ;YES -- SKIP -
			  JRST	COMERP  ;NOTHING LEFT
			 CAIE	T3,"]"  ;MINUS SIGN MUST BE FOLLOWED
			CAIN	T3,">"  ; BY A LEGAL BRACKET
			JRST	PP1A  ;THEN RETURN 0
			JRST	PP3] ;ELSE ERROR
		HLRZ T2,JBTPPN##(J)  ;NO ARG, DEFAULT TO LOGGED IN
		JRST	.+2]	;AND CONTINUE
	  JRST	PP3		;ILLEGAL OCTAL CHARACTER GIVEN
	TLZ	T2,-1
	JUMPE	T2,PP3		;BOMB IF 0
	HRL	P1,T2		;ENTER
	CAIE	T3,","
	JRST	PP3		;PPN MUST HAVE COMMA
	PUSHJ	P,OCTIN		;GET SECOND ARG.-PROG. NO.
	  JRST	[HRRZ T2,JBTPPN##(J)  ;NO ARG, DEFAULT TO LOGGED IN
		 JRST	.+2]	;AND CONTINUE
	  JRST	PP3		;
	TLZ	T2,-1
	JUMPE	T2,PP3		;BOMB IF 0
	HRR	P1,T2		;ENTER
PP1A:	JUMPL	P1,PP3		;BOMB USER IF INVALID
PP2:	MOVE	T2,P1		;RESULT IN T2
	JRST	P1POPJ##	;RETURN TO CALLER
PP3:	POP	P,P1
	PJRST	COMERP		;LOSE
;ROUTINE TO PRINT TIME AS HOURS,MINUTES,SECONDS, AND HUNDRETHS (NO CRLF)
;FORMAT IS HHMM:SS.HH, MM:SS, OR SS.HH IF HH AND MM ARE 0
;CALL:	MOVE T1,TIME IN JIFFIES(60THS,50THS OR MILLISECONDS)
;	PUSHJ P,PRTIM
;				;CALL PRTIME (ABOVE) TO GET CRLF AFTER TIME
;SCALEING IS DONE USING THE FOLLOWING GLOBAL SYMBOLS DEFINED IN COMMON
;THUS ANY INSTALLATION MAY HAVE ANY RATE CLOCK


;JIFMIN=NO. OF JIFFIES(CLOCK TICKS) PER MINUTE
;JIFSEC=NO. OF JIFFIES PER SECOND
;JIFSC2=1/2*JIFSEC(USED FOR ROUNDING)


PRNOW:	MOVE	T1,TIME##	;GET CURRENT TIME OF DAY
PRTIM::	CAMGE	T1,TICMIN##	;IF LESS THAN A MINUTE
	JRST	PR1		;IN USE DIFFERENT FORMAT
	MOVE	T2,TICSEC##	;ADD 1/2 TICKS/SEC FOR ROUNDING
	LSH	T2,-1
	ADD	T1,T2
	IDIV	T1,TICMIN##	;FORM MINUTES
	PUSH	P,T2		;SAVE REMAINDER IN JIFFIES
	IDIVI	T1,^D60		;HOURS, MINUTES IN T1,T2
	JUMPE	T1,PR0		;SUPPRESS 0 HOURS
	PUSHJ	P,RADX10
PR0:	PUSHJ	P,INLMES	;PRINT "HH:" OR "H:"
	ASCIZ	/:/
	MOVE	T1,T2		;GET MINUTES
	PUSHJ	P,PRT2		;PRINT "MM:"
	PUSHJ	P,INLMES
	ASCIZ	/:/
	POP	P,T1		;RESTORE SECONDS (IN JIFFIES)
	PJRST	PR2		;PRINT AND RETURN (NO CRLF)

PR1:	IDIV	T1,TICSEC##	;JIFFIES PER SECOND
	PUSHJ	P,RADX10	;PRINT SECONDS
	PUSHJ	P,PRPER		;PRINT PERIOD
	MOVE	T1,T2		;NO OF JIFFIES(HUNDRETHS)
	IMULI	T1,^D100	;CONVERT TO HUNDRETHS
PR2:	IDIV	T1,TICSEC##
PRT2::	MOVEI	T3,"0"
	PUSH	P,T1		;SAVE T1 OVER I/O
	CAIGE	T1,^D10
	PUSHJ	P,COMTYO##	;PUT LEADING 0 IF LESS THAN 10
	POP	P,T1		;RESTORE T1
	JRST	RADX10		;PRINT REST OF NUMBER
;ROUTINE TO PRINT SIZE OF LOGICAL SEGMENT (LOW OR HIGH)
;CALL:	MOVE J, HIGH OR LOW SEG NUMBER
;	PUSHJ P,PRT SEG
;	RETURN
;CALLED AT CLOCK LEVEL FROM CORE (UUO ARG) COMMAND AND SEGCON


PRTSEG:	PUSHJ	P,SEGSIZ	;T2=SIZE OF HIGH OR LOW SEG
	MOVE	T1,T2		;RADX10 WANT DEC. NO. IN T1
	JRST	RADX10		;PRINT DECIMAL

;ROUTINE TO RETURN SIZE OF HIGH OR LOW SEG
;CALL:	MOVE J,LOW OR HIGH SEG NUMBER
;	PUSHJ P,SEGSIZ
;	RETURN WITH SIZE IN K IN T2


SEGSIZ::PUSHJ	P,SAVE1##	;SAVE A COUPLE OF ACS
	PUSH	P,J		;SAVE J
	HRRZS	J		;SO CAN CLEAR JUNK
	LDB	T2,IMGIN##	;SEGMENT SIZE
	CAILE	J,JOBMAX##	;LOW SEGMENT?
	JRST	SEGSZ1		;NO, GET HI SEG SIZE
	MOVEI	P1,JBTSGN##-.HBLNK(J) ;START OF SEGMENT DATA BLOCK CHAIN
SEGSZ0:	HRRZ	P1,.HBLNK(P1)	;NEXT SEGMENT DATA BLOCK
	JUMPE	P1,SEGSZ2	;NO MORE
	SKIPLE	J,.HBSGN(P1)	;SPY SEG?
	TLNE	J,SHRSEG	;NON-SHARABLE?
	JRST	SEGSZ0		;NO, CHECK NEXT
	HRRZS	J		;CLEAR JUNK
	HLRZ	J,JBTSWP##(J)	;GET SIZE OF THIS NON-SHARABLE
	SUBI	T2,(J)		;SUBTRACT OUT OF LOW SEG SIZE
	JRST	SEGSZ0		;CONTINUE

SEGSZ1:	JUMPG	T2,JPOPJ##	;GO IF NON-ZERO
	HLRZ	T2,JBTSWP##(J)	;MAYBE A NON-SHARABLE HI SEG
	JRST	JPOPJ##		;RETURN

SEGSZ2:	JUMPE	J,JPOPJ##	;RETURN IF NO CORE
	ADDI	T2,UPMPSZ##	;YES, ACCOUNT FOR UPMP SIZE
	JRST	JPOPJ##		;RESTORE J AND RETURN
;ROUTINE TO ASSIGN A MINIMAL CORE AREA (2000 WORDS)
;CALLED FROM CORE, KJOB, AND RUN COMMANDS
;CALL:	PUSHJ P,GETMIN
;	RETURN R=0 IF UNSUCCESSFUL OR CORE ASSIGNED ON DISK


GETMIN::
IFN FTMP,<
	PUSHJ	P,GETMM##	;TRY TO GET THE MEMORY MANAGEMENT RESOURCE
	  JRST	DLYCM1		;FAILED, TRY AGAIN NEXT TIME
>
	SKIPE	PAGIPC##	;PAGING IN PROGRESS?
	SKIPN	JBTADR##(J)	;YES, PROCEED ONLY IF INCREASING CORE
	JRST	GETMI2		;ENTER COMMON CODE
IFN FTMP,<
	PUSHJ	P,GIVMM##	;GIVE UP THE MM
>
	JRST	DLYCM1		;AND TRY AGAIN NEXT TIME
GETMI1::
IFN FTMP,<
	PUSHJ	P,UPMM##	;GET MM (ALREADY AT UUO LEVEL)
>
GETMI2:	PUSHJ	P,ZAPEPL##	;CLEAR ANY EXTENDED PDL NOW
	PUSH	P,U		;SAVE TTY LDB ADDRESS
	PUSH	P,T2		;SAVE DEVICE NAME(GET)
	PUSH	P,S		;SAVE DISPATCH ADDRESS(ANYACT USES S)
	PUSHJ	P,KILHGA##	;KILL HIGH SEG
IFN FTKL10&FTMP,<
	PUSHJ	P,CLCSN##	;CLEAR SWEEP SERIAL NUMBER FOR JOB
				; SO WE DON'T SWEEP FOR NOTHING
>;END IFN FTKL10&FTMP
IFN FTPEEKSPY,<
	PUSHJ	P,CLRSPG##	;GET RID OF SPY PAGES
>
	PUSHJ	P,KILNZS##	;KILL NON-ZERO SECTIONS
	  JRST	GMIDLY		;GIVE UP A WHILE
	MOVEI	T1,PG.BDY	;BASIC UNIT OF CORE MEMORY
	PUSHJ	P,CORE0##	;ASSIGN 2000 WORDS ON DISK OR MEMORY
	  JFCL			;IGNORE IF CANT(R=0)
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN MM RESOURCE
>
	POP	P,S
	POP	P,T2		;RESTORE PUSHED ACS
	PJRST	UPOPJ##		;RESTORE U AND RETURN

GMIDLY:	POP	P,S
	POP	P,T2
	POP	P,U
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN MM RESOURCE
>
	JRST	DLYCM1

;SUBROUTINE TO GET A MINIMAL AMOUNT OF CORE IN CORE
GETCIC::PUSHJ	P,GETMIN	;TRY TO GET CORE IN CORE
	SKIPN	JBTADR##(J)	;DID WE SUCCEED?
	PJRST	DLYCM		;NO
	POPJ	P,		;YES, RETURN TO CALLER
;FNDNAM--ROUTINE TO SEARCH FOR ABBREV. NAME IN TABLE
;CALL	MOVE	T1,AOBJN POINTER TO LIST OF NAMES
;	MOVE	T2,SIXBIT ABBREVIATION
;	PUSHJ	P,FNDNAM
;NON-SKIP IF UNKNOWN (T1=0) OR DUPLICATE (T1 .NE. 0)
;SKIP RETURN IF FOUND WITH T1=INDEX IN TABLE


FNDNAM::PUSHJ	P,SAVE3##	;SAVE P1,P2,P3
	MOVN	P1,T2		;FIND THE RIGHTMOST
	AND	P1,T2		;NON-ZERO BIT IN COMMAND
	JFFO	P1,.+1		;AND ITS CARDINALITY
	IDIVI	P2,6		;FIND W HERE IN SIXBIT BYTE THE BIT IS
	LSH	P1,-5(P3)	;RIGHT-JUSTIFY THE BIT WITHIN THE BYTE
	SOJ	P1,		;MAKE MASK OF TRAILING BLANKS
	SETZB	T4,P2		;INITIALIZE MATCH POINTER AND COUNT
	MOVE	P3,T1		;SAVE POINTER
FNDNM2:	MOVE	T3,(T1)		;GET NEXT CANDIDATE
	XOR	T3,T2		;COMPARE
	JUMPE	T3,FNDNMW	;WIN
	ANDCM	T3,P1		;MASK IT
	JUMPN	T3,FNDNM3	;LOOSE
	MOVE	T4,T1		;WIN--SAVE POINTER
	ADDI	P2,1		;COUNT SUCCESS
FNDNM3:	AOBJN	T1,FNDNM2	;LOOP FOR ALL ENTRIES
FNDNM4:	MOVE	T1,T4		;RESTORE POSSIBLE WINNER
	SOJN	P2,CPOPJ##	;JUMP IF UNSUCCESSFUL
FNDNMW:	SUB	T1,P3		;COMPUTE INDEX
	TLZ	T1,-1		;REMOVE JUNK
	JRST	CPOPJ1##	;SKIP RETURN
;FNDCOM--ROUTINE TO FIND A COMMAND
;FINDS COMMAND FROM EITHER CUSTOMER TABLE, OR NORMAL TABLE
;CALL	MOVE	T2,SIXBIT ABBREVIATION
;	PUSHJ	P,FNDCOM
;	  DIDN'T FIND IT OR DUPLICATE
;	FOUND IT, T1/ FLAGS,,OFFSET
;		  T3/TYPE OF MATCH FLAGS
;T2 PRESERVED
;USES P3,P4,T1
;NON-SKIP IF UNKNOWN (T1.EQ.0) OR DUPLICATE (T1.NE.0)
FNDCOM:	MOVE	P3,[XWD UNQTBC##,DISPC##] ;CUSTOMER UNIQUENESS BITS,,DISPATCH
	MOVE	P4,[XWD -DISPLC##,CSTTAB##] ;CUSTOMER -LENGHT,,COMMAND TABLE
	TLNN	P4,777777	;ANY CUSTOMER DEFINED COMMANDS?
	JRST	FNDCO1		;NO, DON'T CHECK FOR THEM THEN
	SETZ	T1,		;NO FLAGS FOR FULL WORD LDB POINTER
	PUSHJ	P,FNDABV	;LOOK IT UP
	  JRST	FNDCO1		;ERROR, TRY REGULAR COMMANDS
	TRNE	T3,CEXACT	;EXACT MATCH?
	JRST	CPOPJ1##	;FOUND, RETURN NOW
	PUSH	P,T1		;SAVE THE RESULT ACS IN CASE
	PUSH	P,T3		; THEY MUST BE RETURNED TO THE CALLER
	PUSH	P,P3		;LIKEWISE,
	PUSH	P,P4		;SAVE THE TABLE ACS
	PUSHJ	P,FNDCO1	;GO SEARCH THE MAIN TABLE
	  JRST	FNDCO2		;NOT FOUND, RETURN WHAT WE HAVE
	TRNE	T3,CEXACT	;EXACT MATCH?
	JRST	FNDCO3		;EXACT MATCH, RETURN GOOD
	MOVE	T4,-2(P)	;GET CUSTOMER RESULT BITS
	TRNN	T4,CUNIQ	;IF UNIQUE HERE,
	TRNN	T3,CUNIQ	;OR NOT SO HERE,
	JRST	FNDCO2		;RETURN CUSTOMER COMMAND
	JRST	FNDCO3		;ELSE, RETURN DEC COMMAND

FNDCO2:	POP	P,P4		;RESTORE TABLE ACS
	POP	P,P3		; ...
	POP	P,T3		;RESTORE THE STACK
	POP	P,T1		; FOR RETURN OF CUSTOMER COMMANDS
	JRST	CPOPJ1		;RETURN GOOD

FNDCO3:	ADJSP	P,-4		;DESTROY THE RETURNED CUSTOMER RESULTS
	JRST	CPOPJ1		;AND RETURN GOOD

FNDCO1:	MOVE	P3,[XWD UNQTAB##,DISP##] ;SET P3=UNIQNESS BITS, DISPATCH TABLE
	MOVE	P4,[XWD -DISPL##,COMTAB##] ;SET P4=-LENGTH,TABLE LOC
	SETZ	T1,		;NO FLAGS FOR FULL WORD LDB POINTER
	PUSHJ	P,FNDABV	;LOOK IT UP
	  POPJ	P,		;RETURN ERROR
	JRST	CPOPJ1##	;FOUND, RETURN GOOD
;FNDABV--ROUTINE TO SEARCH FOR ABBREV. NAME IN LIST
;CALL	MOVE	T1,FLAGS
;	MOVE	T2,SIXBIT ABBREVIATION
;	MOVSI	P3,UNQTAB	;POINTER TO UNIQNESS BITS COMPRESSED TABLE
;	MOVE	P4,AOBJN POINTER TO NAMES
;	PUSHJ	P,FNDABV
;	 DIDN'T FIND IT OR DUPLICATE
;	FOUND IT, T1/ FLAGS,,OFFSET
;		  T3/ TYPE OF MATCH FLAGS
;T2 AND P ACS ARE PRESERVED
;NON-SKIP IF UNKNOWN (T1=0) OR DUPLICATE (T1.NE.0)
;

CEXACT==1B18			;COMMAND WAS EXACT MATCH
CUNIQ==1B19			;COMMAND MATCHED ON UNIQUENESS
CAMBIG==1B20			;COMMAND WAS AMBIGUOUS
CMONSB==1B21			;COMMAND IS A SUBSTITUTE MONITOR COMMAND

FNDABV::PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSHJ	P,SAVR##	;NEED YET ANOTHER AC
	PUSH	P,T2		;SAVE FOR A MOMENT
	MOVNS	T2		;NEGATE NAME
	AND	T2,(P)		;FIND RIGHTMOST NON-ZERO BIT
	JFFO	T2,.+1		;IN THE COMMAND
	IDIVI	T3,6		;FIND WHERE IN THE SIXBIT BYTE IT IS
	LSH	T2,-5(T4)	;RIGHT JUSTIFY THE BIT WITHIN THE BYTE
	SOS	T3,T2		;MAKE MASK OF TRAILING BITS
	POP	P,T2		;AND RESTORE THE COMMAND NAME
	HLRZ	P2,P3		;RIGHT HALF POINTER TO UNQTAB
	HRLI	P2,(POINT ^D36,) ;ASSUME SYSTEM COMMAND
	TLNE	T1,1		;IS IT?
	 HRLI	P2,(POINT 6,)	;NO, THEN IT IS USER UNIQTAB
	SETZB	P1,P3		;NO MATCHES FOUND YET (WE HAVEN'T LOOKED!)
	MOVE	R,P4		;COPY THE STARTING AOBJN POINTER
FNDAB2:	MOVE	T4,(P4) 	;GET NEXT CANDIDATE
	XOR	T4,T2		;COMPARE
	JUMPE	T4,FNDEXC	;WIN ON EXACTNESS
	ANDCM	T4,T3		;MASK IT
	JUMPN	T4,FNDAB4	;LOSE
	ILDB	T4,P2		;GET UNIQUENESS INFO
	TRNN	T4,<UNIQ.1!UNIQ.2!UNIQ.3!UNIQ.4> ;ANY UNIQNESS BITS
	JRST	FNDAB3		;NO UNIQUENESS INFO
	TRNE	T4,UNIQ.1	;UNIQUE AT 1 CHAR?
	CAME	T3,[7777,,-1]	;AND ONLY ONE CHAR SEEN?
	CAIA			;NO
	JRST	FNDAWN		;YES, THEN WE HAVE IT
	TRNE	T4,UNIQ.2	;UNIQUE AT 2 CHARS?
	CAME	T3,[77,,-1]	;AND TWO CHARS SEEN?
	CAIA			;NO
	JRST	FNDAWN		;YES, SO WE HAVE IT
	TRNE	T4,UNIQ.3	;UNIQUE AT 3 CHARS
	CAME	T3,[0,,-1]	;AND THREE CHARS SEEN?
	CAIA			;NO
	JRST	FNDAWN		;YES
	TRNE	T4,UNIQ.4	;UNIQUE AT 4 CHARS?
	CAME	T3,[0,,7777]	;AND FOUR CHARS TYPED?
	CAIA			;NO
	JRST	FNDAWN		;YES
FNDAB3:	HRR	P3,P4		;POSSIBLE WIN--SAVE POINTER
	HRL	P3,T4		;AND BITS (IN CASE USER COMMAND)
	AOSA	P1		;COUNT SUCCESS
FNDAB4:	IBP	P2		;ADVANCE
	AOBJN	P4,FNDAB2	;LOOP FOR ALL ENTRIES
	SETZ	T3,		;CLEAR ANY STRAY FLAGS
	JUMPE	P1,CPOPJ##	;NOTHING FOUND, RETURN NOW
	SOJN	P1,FNDAB6	;MAKE SURE WE ONLY GOT A SINGLE COMMAND.
	TLZ	P4,-1		;CLEAR THE LEFT HALF
	SUBI	P3,(R)		;CALCULATE THE OFFSET
	TLNN	T1,1		;SYSTEM TABLE?
	TLZ	P3,-1		;YES, CLEAR FLAGS
	MOVE	T1,P3		;LEAVE WHERE CALLERS CAN FIND IT
	JRST	CPOPJ1##	;AND RETURN SUCCESS

;WIN ON EXACTNESS.
FNDEXC:	ILDB	T4,P2		;GET UNIQUENESS (IN CASE USER COMMAND)
	SKIPA	T3,[CEXACT]	;TELL OF AN EXACT MATCH

;WIN BY VIRTUE OF UNIQNESS BITS. SEARCH NO MORE.
FNDAWN:	MOVEI	T3,CUNIQ	;REMEMBER WE WON UNIQUELY
	SUBI	P4,(R)		;COMPUTE INDEX TO RETURN
	HRR	T1,P4		;COPY OFFSET
	TLNE	T1,1		;SYSTEM TABLE?
	HRLI	T1,(T4)		;NO, COPY FLAGS FOR USER TABLE
	JRST	CPOPJ1##	;AND RETURN SUCCESS

;LOSE THROUGH AMBIGUITY.
FNDAB6:	MOVEI	T3,CAMBIG	;GET THE AMBIGUOUS BIT
	POPJ	P,
	SUBTTL	SAVGET -- PARAMETERS


;SAVGET LOWER CORE LOCATIONS USED FOR UUOS TO MONITOR
;USED IN SAVGET IN APRSER AND SAVGET IN SEGCON
;THESE LOCATIONS ARE DEFINED TO BE IN THE USERS UUO ACS

;FOR LOOKUP,ENTER UUOS:
	XP	SGANAM,0
			;FILE NAME
	XP	SGAEXT,SGANAM+1
			;FILE EXTENSION
	XP	SGADAT,SGANAM+2
			;FILE CREATION DATE+TIME
	XP	SGALEN,SGANAM+3
			;LH=-LENGTH,RH=FIRST LOC-1 DUMPED

			; OR PROJECT-PROGRAMMER NUMBER(DISK)
	XP	SGAEND,SGALEN+1
			;LAST WORD OF DUMP COMMAND LIST=0(SAVE AND GET)
	XP	SGAREN,SGAEND
			; ALSO FIRST WORD FOR RENAME USED AS DELETE
	XP	SGAPPN,SGAREN+3
			;FOURTH WORD-PLACE TO SAVE PROJECT-PROGRAMMER

			; NUMBER USER TYPED

;FOR OPEN UUOS:
	XP	SGAMOD,10
			;S MODE WORD FOR OPEN UUO
	XP	SGADEV,SGAMOD+1
			;DEVICE NAME
	XP	SGAHED,SGAMOD+2
			;INPUT-OUTPUT BUFFER HEADER ADDRESSES=0

;MISC. DATA LOCATIONS:

	XP	SGACOR,13
			;AC FOR CORE UUO'S(HIGHEST USER LOC DESIRED)
	XP	SGADMP,14
			;DUMP COMMAND IOWD
	SGASAV==:SGADMP
	XP	SGANEW,15
			;NEW CORE ASSIGNMENT AS SPECIFIED BY THIRD ARG
	XP	SGAHGH,16
			;LH=EXT TO USE FOR SAVING HIGH SEG

			; RH=EXT TO DELETE(IE SHRHGH OR HGHSHR)
	XP	SGALOW,17
			;LH=EXT WHICH USER TYPED FOR SAVE OR GET COMMAND

			; OR .SAV IF HE DIDN'T TYPE AN ARG WITH LEADING PERIOD

			; RH=0
	SUBTTL	SAVGET -- COMMAND SCAN

;ROUTINE TO SCAN COMMAND STRING ARGUMENTS FOR SAVE,GET,MERGE,RUN AND R
;COMMANDS AND STORE THEM IN JOB DATA AREA WHICH MUST BE IN CORE
;WHEN SGSET IS CALLED FROM COMMAND DECODER
;CALL:	MOVE T2,SIXBIT DEVICE NAME
;	MOVE J,JOB #
;	MOVE U,LDB ADDRESS
;	MOVE S,ADR. OF MONITOR JOB(SAVJOB,GETJOB,MRGJOB,RUNJOB)
;	MOVE R, ADR. OF JOB AREA
;	PUSHJ P,SGSET

SGSETD:	HLLZ	T2,SYSTAP##	;SET DEFAULT DEVICE OF DISK
SGSET:	PUSHJ	P,SETASA	;TURN ON THE EXEC MODE UUO FLAG
	MOVEM	T2,.JDAT+SGADEV	;STORE DEFAULT DEVICE NAME
	MOVEM	P1,.JDAT+SGAMOD	;SAVE PHYSICAL/LOGICAL BIT FOR LATER
	SETZM	.JDAT+SGAPPN	;INDICATE NO DEFAULTING DONE
	SETZM	.USUSN		;ALSO, NO /USE VALUE
	SETZM	.USUSA		;NO USER SUPPLIED START ADDRESS
	CAMN	P2,PLNTXT##	;USER-DEFINED COMMAND?
	JRST	SGSETC		;YES, COPY STUFF FROM BLOCK RATHER THAN COMMAND
	HRRZ	P3,S		;COMMAND
	CAIN	P3,MRGJOB	;MERGE COMMAND?
	JRST	SGSET1		;YES
	CAME	T2,[SIXBIT/SYS/];R COMMAND?
	CAIN	P3,SAVJOB	;OR SAVE COMMAND?
	JRST	SGSET1		;YES, USE OLD DEFAULTS
	MOVSI	T1,(PD.UDS)	;WAS A SAVE COMMAND THE LAST
	TDNE	T1,.PDDFL##(W)	; COMMAND DONE?
	PUSHJ	P,SGSEND	;OR WERE ARGUMENTS TYPED?
	  JRST	SGSET1		;YES, OLD STYLE DEFAULTING
	SKIPN	T1,.PDNAM##(W)	;NAME FROM PREVIOUS GET OR RUN
	JRST	SGSET1		;USE JBTPRG
	MOVEM	T1,.JDAT+SGANAM	;STORE NAME
	MOVEM	T1,JBTPRG##(J)
	MOVE	T1,.PDSTR##(W)	;FILE STRUCTURE
	MOVEM	T1,.JDAT+SGADEV
	MOVE	T1,.PDDIR##(W)	;DIRECTORY
	MOVEM	T1,.JDAT+SGAPPN
	MOVSI	T1,.PDSFD##(W)	;AND SFD'S
	HRRI	T1,.JDAT+JOBUAL##+3
	BLT	T1,.JDAT+JOBUAL##+MAXLVL##+2
	JRST	SGSET4		;GO PROCESS GET OR RUN
SGSET1:	PUSHJ	P,CTEXT1	;GET DEVICE OR NAME
	CAIE	T3,":"		;SEE IF DEVICE
	JRST	SGSET2		;NO--SET FILE NAME
	MOVEM	T2,.JDAT+SGADEV	;YES--SAVE IT
	PUSHJ	P,CTEXT		;AND GET FILE NAME
SGSET2:	SETZM	.JDAT+JOBUAL##+3;ASSUME USER DID NOT SPECIFY SFD'S
	CAIE	T3,"["		;PPN HERE A POSSIBILITY?
	CAIN	T3,"<"		;TO CLOSE ANGLE BRACKET>, OR 2741 STYLE?
	PUSHJ	P,[PUSH P,T2	;SAVE POSSIBLE FILE NAME
		   PUSHJ P,GETPPN ;SEE IF THERE IS A PPN
		     JRST T2POPJ## ;NO, TRY LATER IN THE MORE TRADITIONAL PLACE
		   POP P,T2	;RESTORE POSSIBLE FILE NAME
		   JUMPN T2,CPOPJ## ;GO IF ONE WAS ALREADY TYPED
		   PJRST CTEXT1];HAVEN'T SEEN ONE, GO READ IT NOW
	CAIN	P3,MRGJOB	;MERGE COMMAND?
	JRST	SGSET3		;YES, A FILE NAME IS REQUIRED
	SKIPN	T2		;SEE IF FILE TYPED IN
	MOVE	T2,JBTPRG##(J)	;NO--GET DEFAULT IF ANY
	MOVEM	T2,JBTPRG##(J)	;SAVE FILE NAME FOR SYSTAT COMMAND
SGSET3:	MOVEM	T2,.JDAT+SGANAM	;STORE FILE NAME
	SETZ	T2,		;ASSUME USER DID NO SPECIFY AN EXTENSION
				; 0 WILL BE TURNED INTO SAV OR DMP
	CAIN	T3,"."		;IS AN EXTENSION SPECIFIED
	PUSHJ	P,CTEXT		;YES. GET EXTENSION
	HLRZS	T2		;SEE IF THE USER
	CAIE	T2,(SIXBIT /SHR/) ;HAS SPECIFIED AN
	CAIN	T2,(SIXBIT /HGH/) ;IMPROPER LOW EXTENSION
SGSET4:	MOVEI	T2,0		;YES--IGNORE IT
	HRLZM	T2,.JDAT+SGAEXT	;STORE IT FOR LOOKUP
	MOVSI	T1,(JS.EXE)
	CAIN	T2,(SIXBIT /SAV/)
	ANDCAM	T1,JBTST2##(J)
	PUSHJ	P,SETEXT##	;SET HIGH EXTENSION(SGAHGH) TO .SHR IF SSAVE OR GET
				; ,HGH IF SAVE(LH S=NSRBIT).

	SETZM	.JDAT+SGADAT	;SET DATE(E+2) TO 0, SO MONITOR WILL USE TODAYS
	SKIPN	.JDAT+SGAPPN	;ALREADY READ A PPN?
	PUSHJ	P,GETPPN	;NO, SEE IF THERE IS ONE
	  JFCL			;NOT HERE ANYWAY, SEE IF TYPED EARILER
	SKIPN	.JDAT+JOBUAL##+3 ;A PATH TYPED OR DEFAULTED?
	JRST	SGSET5		;NO
	MOVEI	T1,JOBUAL##	;ADDRESS OF THE PATH
	EXCH	T1,SGAPPN+.JDAT	;STORE PATH AND GET THE PPN
	MOVEM	T1,JOBUAL##+.JDAT+2  ;STORE THE PPN
	SETZM	.JDAT+JOBUAL##+1  ;SO FILSER WILL SCAN IF THE SCAN SWITCH IS ON
SGSET5:	PUSHJ	P,CORARG	;AMOUNT OF CORE (OPTIONAL THIRD ARG.)
	  JRST	SGSET6		;RETURN HERE IF NO ARG.
	TLNE	T2,-1		;USER ARG EXCEED MAX. SIZE OF CORE?
	JRST	SGERRP		;YES, PRINT COMMAND ERROR
SGSET6:	HRRZM	T2,.JDAT+SGANEW	;STORE FOR RUN AND SAVE
	PUSHJ	P,SGSEND	;END OF LINE?
	  CAIA			;READ THE REST
	JRST	SGSET7		;NOTHING MORE TO READ OR IF THERE IS, ITS ILLEGAL
	CAIE	T3,"/"		;SWITCH TYPED?
	JRST	SGSET7		;NO, SKIP ON
SGSE6A:	PUSHJ	P,CTEXT		;READ SWITCH VALUE
	MOVE	T1,[-2,,[SIXBIT /USE/
			 SIXBIT /START/]]
	CAIN	T3,":"		;NEED A ":" BEFORE THE VALUE
	PUSHJ	P,FNDNAM	;SEE IF LEGAL SWITCH VALUE
	  JRST	SGERRP		;NO, PRINT COMMAND ERROR
	CAIN	T1,0		;USE SWITCH?
	CAIE	T1,SAVJOB	;YES, SAVE COMMAND?
	CAIA			;NO TO EITHER
	JRST	SGERRP		;USE SWITCH ON A SAVE COMMAND IS ILLEGAL
	CAIE	T1,1		;START SWITCH?
	JRST	SGSE6B		;NO, GO PROCESS USE SWITCH
	PUSHJ	P,SKIPS		;DISCARD ":"
	  JRST	SGERRP		;EOL IS ILLEGAL HERE
	PUSHJ	P,OCTPAR	;READ VALUE OF START SWITCH
	  JRST	SGEENF		;THERE MUST BE ONE
	CAIE	P3,SAVJOB	;IF NOT A SAVE,
	TLO	T2,400000	;LITE START ADDRESS SPECIFIED BY COMMAND
	MOVEM	T2,.USUSA	;STORE VALUE FOR SAVE OR RUN
	MOVE	S,P3		;OCTPAR CLOBBERED S
	JRST	SGSET7		;CONTINUE
SGSE6B:	PUSHJ	P,OCTIN		;READ VALUE
	  JRST	SGEENF		;NULL VALUE ILLEGAL
	  JRST	SGERRE		;ILLEGAL CHARACTER
	LSH	T2,S2PLSH	;PUT IN SECTION NUMBER FIELD
	MOVEM	T2,.USUSN	;SAVE FOR GET/R/RUN/MERGE PROCESSING
SGSET7:	PUSHJ	P,SGSEND
	  JRST	[CAIE T3,"/"	;ANOTHER SWITCH?
		 JRST SGERRP	;NO, ANYTHING ELSE IS ILLEGAL
		 JRST SGSE6A]	;YES, PROCESS NEXT SWITCH
	HRRZS	T2,S		;SCHEDULE MONITOR JOB
				; GUARRANTEE LH OF PC WORD IS 0, SINCE IT WILL
				; BE ADDED TO STARTING ADDRESS(IF RUN COM)
	SUBI	S,SAVJOB
	MOVSI	T1,(PD.UDS)	;ASSUME RUN,GET COMMAND (REMEMBER DEFAULTS)
	IORM	T1,.PDDFL##(W)
	SKIPN	S		;IS IT?
	ANDCAM	T1,.PDDFL##(W)	;NO, FORGET DEFAULTS
	PUSHJ	P,CHKEXE	;IS THIS AN EXE SAVE?
	  JRST	SGSET8		;YES, MAKE AN EXE FILE
				;NO, FALL THRU TO REGULAR SAVES
	SKIPN	.USREL		;IF NON-CONTIGUOUS CORE IMAGE
	SKIPE	.USVRT		;OR VIRTUAL (1+I SEA)
SGSET8:	JUMPE	S,SGSE10	;GO ELSEWHERE IF SAVE
SGSET9:
IFN FTMP,<
	PUSHJ	P,CLRJSP##	;CLEAR JBTSPS TO ENSURE MONITOR JOB RUNS ON MASTER
>
	PJRST	MSTART##	;START JOB WITH PC IN MONITOR MODE
SGSE10:	HLRZ	T1,JBTADR##(J)	;GET HIGHEST ADDRESS IN LOW SEG
	CAMGE	T1,.JDAT+SGANEW	;COMPARE WITH USER STORED CORE ARG
	MOVE	T1,.JDAT+SGANEW	;USER'S WAS LARGER, USE IT
	HRRM	T1,.JDAT+JOBCOR## ;AND SET UP JOBCOR.
	PUSHJ	P,CHKEXE	;NSAVE OR NSSAVE?
	  JRST	SGSET9		;YES, SAVE AN EXE FILE
				;LOSE SINCE MONITOR CAN'T DO IT ANYWAY


SGERRE:	PUSHJ	P,COMTYI##	;EAT ONE MORE CHARACTER
SGERRP:	PUSHJ	P,CLRASA	;CLEAR SHADOW ACS FLAG
	JRST	COMERR		;GO GIVE ERROR MESSAGE

SGEENF:	PUSHJ	P,CLRASA	;CLEAR SHADOW ACS FLAG
	JRST	NOTENF		;GO REPORT NOT ENOUGH CORE
;SUBROUTINE TO TEST FOR EOL. RETURNS CPOPJ IF NOT, CPOPJ1 IF IT IS

SGSEND:	PUSH	P,T2
        PUSHJ	P,SKIPS1	;SKIP SPACES
	  JRST	T2POJ1##	;EOL
	CAIE	T3,"("		;SEE IF USER ARGUMENTS
	CAIN	T3,"-"		;DITTO (THE OLD WAY)
	JRST	T2POJ1##	;YES, END OF COMMAND LINE
	JRST	T2POPJ##	;NO, MORE TO PROCESS

;SUBROUTINE TO READ A PPN. RETURNS CPOPJ IF NONE FOUND, CPOPJ1 IF FOUND,
; [P,PN,PATH] STORED

GETPPN:	SKIPN	T2,.JDAT+SGAPPN ;PPN DEFAULTED?
	PUSHJ	P,PJPGNO	;GET PROJ. PROG. NO.
	MOVEM	T2,.JDAT+SGAPPN	;STORE 0 IF NO []'S TYPED BY USER
	SETO	P1,
	CAIE	T3,","		;COMMA TYPED?
	JRST	[JUMPE T2,CPOPJ## ;(N0) IF NO PPN, ALL IS OK
		 JRST GETPP1]
	JUMPE	T2,COMERA	;(YES) ERROR IF SFD WITHOUT PPN
	SETZ	P1,		;SET SFD FLAG
GETPP1:	MOVSI	T1,(SIXBIT/SYS/)
	CAME	T1,.JDAT+SGADEV	;DID HE ASK FOR "SYS" BY MISTAKE?
	JRST	GETPP3		;NO, ALL IS OK
	PUSH	P,T3		;SAVE PUNCTUATION
	PUSHJ	P,DEVLG##	;IS "SYS" A LOGICAL NAME?
	  SKIPA			;NO, CHANGE IT TO "DSK"
	JRST	GETPP2		;YES, NO CHANGES (HE KNOWS
				;  WHAT HE IS DOING)
	MOVSI	T1,(SIXBIT /DSK/)
	MOVEM	T1,.JDAT+SGADEV	;HE TYPED .R FOO[N,N]
				;SO CHANGE "SYS" TO "DSK"
GETPP2:	POP	P,T3		;RESTORE PUNCTUATION
GETPP3:	JUMPN	P1,GETPP5	;JUMP IF NO PATH SPECIFIED
	MOVEI	P2,JOBUAL##+.JDAT+3  ;WHERE TO STORE SFD'S
GETPP4:	PUSHJ	P,CTEXT		;GET NEXT SFD
	JUMPE	T2,NOTENF
	MOVEM	T2,(P2)		;STORE SFD IN LOOKUP/ENTER BLOCK
	AOS	P2		;NEXT SFD SLOT
	SETZM	(P2)
	CAIE	T3,","		;WAS ANOTHER SFD TYPED?
	JRST	GETPP5		;NO
	CAIGE	P1,MAXLVL##-1	;EXCEED MAXIMUM NUMBER OF SFD'S?
	AOJA	P1,GETPP4	;NO, GO READ THE NEXT SFD
	JRST	COMERA		;TO MANY SFD'S
				;< SO ANGLE BRACKETS MATCH
GETPP5:	CAIE	T3,">"		;IS 2741 ENDING
	CAIN	T3,"]"		;OR USUAL "]"?
	PUSHJ	P,COMTYS	;YES, DISCARD CHARACTER
	JRST	CPOPJ1##	;AND GIVE [P,PN,PATH] FOUND RETURN
;COPY USER-DEFINED COMMAND INFORMATION TO SGAXXX.
SGSETC:	SE1ENT			;DO THIS IN SECTION 1 (IN CASE GFWNZS)
	SETZM	.JDAT		;CLEAN OUT THE ACS.
	MOVE	T1,[.JDAT,,.JDAT+1] ;BLT POINTER
	BLT	T1,.JDAT+17	;SINCE WE AREN'T TOO CAREFULL.
	HLRZ	T4,P3		;GET POINTER TO OUR BLOCK
;MAYBE	SSX	T4,MS.MEM	;POINT TO PROPER SECTION
	MOVE	T1,(T4)		;GET NUMBER OF WORDS IN OUR BLOCK
	SOJLE	T1,SGSCER	;IF THIS BLOWS UP, WE HAVE A PROBLEM.
	MOVE	T2,1(T4)	;GET DEVICE NAME
	MOVEM	T2,.JDAT+SGADEV	;SAVE AS DEVICE NAME FOR RUN UUO
	SOSG	T1		;HAVE FILE NAME?
	TDZA	T2,T2		;NO, USE BLANK NAME (ASSUME PATHOLOGICAL DEVICE)
	MOVE	T2,2(T4)	;YES, GET NAME OF PROGRAM TO RUN
	MOVEM	T2,.JDAT+SGANAM	;SAVE AS FILENAME FOR RUN UUO
	SOSG	T1		;HAVE EXTENSION WORD?
	TDZA	T2,T2		;NO, DEFAULT IT
	HLRZ	T2,3(T4)	;YES, GET EXTENSION
	CAIE	T2,'SHR'	;IF INVALID LOW EXTENSION,
	CAIN	T2,'HGH'	;OF EITHER TYPE,
	SETZ	T2,		;IGNORE IT
	MOVSM	T2,.JDAT+SGAEXT
	PUSHJ	P,SETEXT##	;SETUP EXTENSION
	SOJLE	T1,[SETZM .JDAT+SGAPPN ;NO PPN
		JRST SGSCEX]	;AND FALL INTO COMMON CODE
;PPN AND SFDS
	MOVEI	T2,JOBUAL##	;WHERE WE ARE GOING TO PUT A PATH BLOCK
	MOVEM	T2,.JDAT+SGAPPN	;POINTER TO PATH BLOCK
	SETZM	.JDAT+JOBUAL##+1 ;ZERO PATH FLAGS
	XMOVEI	T2,4(T4)	;POINTER TO START OF BLOCK TO COPY
	XMOVEI	T3,.JDAT+JOBUAL##+2 ;WHERE TO.
	CAILE	T1,MAXLVL+1	;MAKE SURE WE WILL FIT
SGSCER:	STOPCD	CPOPJ,DEBUG,CBB, ;++COMMAND BLOCK BAD
	PUSHJ	P,XBLTAT##	;COPY THE DATA
	SETZM	(T3)		;ADD IN A TERMINATING ZERO
SGSCEX:	SETZM	.JDAT+SGAMOD	;ALLOW LOGICAL NAMES
	HRRZ	T2,S		;GET ADDRESS TO DISPATCH TO
	TLO	M,NOCRLF	;DO IT LIKE REAL COMMANDS
	PJRST	MSTART##	;AND GET THE MONITOR TO RUN AT UUO LEVEL
	SUBTTL	SAVGET -- RUN AND GETSEG UUO'S

;ROUTINE TO PICKUP ARGUMENTS FOR RUN AND GETSEG UUOS
;THIS ROUTINE DOES SAME THING AS SGSET, EXCEPT THAT ARGUMENTS ARE
;OBTAINED FROM USER UUO ARGUMENTS INSTEAD OF FROM CONSOLE COMMAND
;THE USERS ARG ARE MOVED TO USER ACS(SGA...), THEREBY CLOBBERING HIS ACS
;USER AC FIELD AND START PC OFFSET(RUN UUO) ARE SAVED ON PD LIST AT JOBPD3
;THEN LOWER CORE IS SET UP(SG2 CALLED) RESET IS NOT DONE (FOR GETSEGUUO)
;JBTPRG NOT SET FOR LOW SEG, SINCE GETSEGUUO SHOULD NOT
;CALL:	MOVE T1,CONTENTS OF USER AC(ADR. OF 3 WORD ARG LIST)
;	MOVE R,JOB RELOCATION
;	PUSHJ P,GETARG
;	RETURN


GETARG::HRR	M,T1		;MOVE ADR. OF ARG LIST TO UUO
	EXCH	T1,(P)		;AND PUT ON PD LIST
	PUSH	P,T1		;MOVE RETURN PC UP ONE IN PD LIST
	LDB	T1,PUUOAC##	;USER AC FIELD IN RUN OR GETSEG UUO
	HRRM	T1,-1(P)	;SAVE IN CASE OF ERROR RETURN
	PUSHJ	P,GETWDU##	;GET FIRST ARG FROM USER AREA
	MOVEM	T1,.JDAT+SGADEV	;STORE DEVICE NAME
	PUSHJ	P,GETWD1##	;GET NEXT ARG FROM USER AREA
	MOVEM	T1,.JDAT+SGANAM	;STORE FILE NAME FOR LOOKUP (DO NOT STORE FOR LOWSEG)
	PUSHJ	P,GETWD1##	;GET THIRD ARG(EXTENSION WORD E+1)
	MOVEM	T1,.JDAT+SGAEXT	;STORE EXTENSION AND RH FROM USER
	PUSHJ	P,GETWD1##	;GET FOURTH ARG(DATE WORD)
	MOVEM	T1,.JDAT+SGADAT
	PUSHJ	P,GETWD1##	;GET FIFTH USER ARG FROM USER AREA
	MOVEM	T1,.JDAT+SGAPPN	;STORE PROJECT,PROGRAMMER NO. OR 0
	PUSHJ	P,GETWD1##	;SIXTH ARG FROM USER
	MOVEM	T1,.JDAT+SGANEW	;STORE CORE ARG, PAGE RANGE, OR 0(HIGHEST LOC DESIRED)
	HLRZ	T2,.JDAT+SGAEXT	;PUT ARG IN T2, SO SAME AS SGSET RETURN FROM CTEXT
	CAIE	T2,'SHR'	;SEE IF THE USER
	CAIN	T2,'HGH'	; GAVE A BAD EXT
	MOVEI	T2,0		;YES--IGNORE IT
	PUSHJ	P,SETEX1##	;SAVE EXT AGAIN IN SGALOW
				; SETUP EXT FOR HIGH SEG(SGAHGH="SHR")
				; SETUP EXTENSION FOR LOW SEG(SGALOW="SAV")
	JRST	SG2A		;GO SET UP LOWER CORE AND RETURN
				; DO NOT DO A RESET
;HERE TO GET THE EXTENDED CORE/SECTION ARGUMENT (IF GIVEN) FOR SAVEGET UUOS.
;CALL ONLY AFTER CALLING GETARG.
;USES ONLY T1

UGTSSL::HLRZ	T1,.USUPF	;GET (REAL) PCS
	ANDI	T1,(SECMSK)	;KEEP ONLY SECTION NUMBER
	LSH	T1,S2PLSH	;MAKE INTO A PAGE NUMBER
	MOVEM	T1,.USUSN	;SAVE AS DEFAULT IF EXTENDED ARG NOT GIVEN
	;PJRST	UGTSSN		;FALL INTO UGTSSN

UGTSSN::SKIPL	T1,.JDAT+SGANEW	;SEE IF ARG IS NEGATIVE
	POPJ	P,		;NO, WE'RE DONE HERE
	PUSH	P,M		;MAY NOT BE NECESSARY, BUT ...
	HRRI	M,(T1)		;POINT AT ARGUMENT LIST EXTENSION
	PUSHJ	P,CLRASA	;ALLOW FOR THE POSSIBILITY THAT ARG IS IN ACS
	PUSHJ	P,GETMWD##	;GET THE SECTION NUMBER (USE GETMWD SINCE SETASA ZEROED PCS)
	  JRST	UADERR##	;ADDRESS CHECK
	PUSH	P,T1		;SAVE T1
	HLRE	T1,.JDAT+SGANEW	;GET LENGTH OF ARGUMENT LIST
	CAML	T1,[-1]		;MORE THAN 1 WORD LONG? (MERGE SPECIFYING A RANGE)
	JRST	UGTSS1		;NO, NO MORE ARGUMENTS TO FETCH
	HRRI	M,1(M)		;POINT AT NEXT ARGUMENT
	PUSHJ	P,GETMWD##	;FETCH IT
	  JRST	UADERR##	;ADDRESS CHECK
	MOVEM	T1,.JDAT+SGANEW	;STORE SECOND ARGUMENT HERE
UGTSS1:	PUSHJ	P,SETASA	;RESTORE JS.ASA
	POP	P,T1		;RESTORE SECTION NUMBER
	POP	P,M		;RESTORE M
	SKIPL	T1		;NEGATIVE SECTION NUMBERS ARE ILLEGAL
	CAILE	T1,MXSECN	;LESS THAN THE HIGHEST LEGAL SECTION NUMBER?
	JRST	IUUAGL##	;NO, ILLEGAL UUO ARGUMENT LIST
	LSH	T1,S2PLSH	;CONVERT TO EXTENDED PAGE NUMBER
REPEAT 0,<
	TLO	T1,400000	;INDICATE UUO RATHER THAN COMMAND
>
	MOVEM	T1,.USUSN	;STORE 0 OR SECTION NUMBER FOR GETSEG
	POPJ	P,		;RETURN WITH .USUSN SET UP
	SUBTTL	SAVGET -- SAVE A JOB

;THIS JOB SAVES A JOB AREA ON RETRIEVABLE STORAGE
;THIS JOB RUNS IN EXEC MODE AND CALLS IO ROUTINES USING REGULAR UUOS
;NO ATTEMPT IS MADE TO SAVE STATUS OF IO DEVICES, JOBPDP, OR AC'S
;IN FACT THE ONLY USEFUL THING WHICH MAY BE DONE WITH A JOB AREA
;AFTER IT HAS BEEN SAVED IS TO START EXECUTION OVER AT THE STARTING
;ADDRESS
SAVJOB::JSP	T2,SG1		;SET UP ACS R,P,J, RESET DEVICES
	PUSHJ	P,CLRBTS	;CLEAR BITS
	PUSH	P,[0]		;STORE ZERO IN JOBPD1
				; SO THAT SGRELE CAN
				; TELL SAVE IS IN PROGRESS
	PUSHJ	P,RMVPFH##
	PUSHJ	P,ADJCOR##	;COMPUTE AMOUNT OF CORE FOR BOTH LO+HI SEGS
				; FROM USER'S CORE ARG(IF ANY)
	HLRE	T2,.JDAT+SGADMP	;-NO. OF WORDS TO WRITE
	PUSHJ	P,CKIOWD	;CHECK USER'S CORE ARG(IF ANY) WITH AMOUNT TO WRITE
				; RETURN ONLY IF 0 OR NOT SMALLER
	HRRM	T1,.JDAT+JOBCOR## ;STORE MAX OF SIZE OF FILE OR CORE ARG
				; FOR ASSIGNING INITIAL CORE WHEN FILE GOTTEN
	PUSHJ	P,SGOPEN##	;OPEN THE DEVICE
	MOVE	T1,DEVMOD(F)	;DEVICE BITS
	TLNE	T1,DVTTY	;IF DVTTY IS ON, IT IS NUL:
	PJRST	SAVFIN		; SO WE'RE DONE
	MOVSI	T2,(JS.EXE)	;BIT WHICH SAYS SAVE IN EXE FORMAT
	TLNE	T1,DVDTA	;A DECTAPE ?
	ANDCAM	T2,JBTST2##(J)	;YES, SAVE IN THE OLD OFRMAT
	PUSHJ	P,CHKEXE	;EXE FILE SAVE?
	  JRST	SAVEXE		;YES, GO TO SPECIAL CODE
	PUSHJ	P,SAVHGH##	;INIT DEV,SAVE HIGH SEG, IF ANY, RETURN IF OK
	  JRST	SAVFIN		;HIGH SAVED, BUT NO DATA IN LOW SEG, SO DO
				; NOT WRITE LOW FILE
				; SKIP RETURN IF LOW SEG TO BE WRITTEN
				; SGALEN, AND SGAEXT RESTORED
	OPEN	0,SGAMOD	;RE INIT DEVICE, SO UGETF WILL SET FIRST FREE
				; BLOCK BECAUSE NO LOOKUP OR ENTER DONE
	  JRST	SGERRA		;DEVICE NOT AVAILABLE
	SETZM	.JDAT+SGADAT	;CLEAR DATE, SO GET TODAY FOR CREATION
	UGETF	0,SGAHED	;TELL DECTAPE SERVICE TO START AT FRONT
	MOVEI	T1,-2		;FLAG THAT CORE HAS BEEN COMPRESSED
	HRLM	T1,USRHCU##	;KEEP LH NEG. COMMAND DECODER WILL EXPAND
				; CORE ON START ,DDT,SAVE, REENTER,SSAVE IN CASE
				; THIS SAVE IO DOES NOT GO TO COMPLETION. (CONTROL C
				; OR DEVICE FULL, SO THAT CORE DOES NOT GET EXPANDED)
	ENTER	0,SGANAM	;ENTER FILE NAME IN DIRECTORY
	  JRST	SAVERR		;DIRECTORY FULL OR PROTECTION FAILURE
	MOVE	T1,.JDAT+JOB41## ;SAVE USER UUO HANDLING JSR
	MOVEM	T1,.JDAT+JOBS41##	;IN UPPER PART OF JOB DATA AREA
	SETZM	.JDAT+JOBEXM##	;CLEAR MEMORY OF EXAMINE

	SETZM	.JDAT+JOBFDV##	;CLEAR MEMORY OF FIN
	MOVE	T1,.JDAT+JOBDDT## ;SAVE DDT STARTING ADDRESS HIGHER UP IN JOB DATA AREA
	MOVEM	T1,.JDAT+JOBSDD## ;SO COMPRESS ALWAYS MOVES CODE DOWN
	HRRZ	T3,.JDAT+JOBSA## ;SAV START ADDRESS FOR 10DMP
	MOVEI	T1,JOBSV##	;POINT TO 1ST DATA WORD
	MOVEI	T2,JOBSDD##	;IT STARTS AT JOBSDD
	HLRE	J,.JDAT+SGADMP	;IOWD FOR THIS SIZE CORE(-LENGTH TO WRITE)
	MOVNS	J		;POSITIVE LENGTH
	ADDI	J,JOBSVM##	;ADD IN FIRST LOC-1 TO WRITE=HIGHEST LOC TO WRITE
				; TO MAKE END TEST
	HLL	J,T2		;USE R FOR RELOCATION IF KA
CMPLP1:	MOVEM	T1,U		;SAVE 1ST LOC FOR IOWD
	CAMLE	T2,J		;SEARCH FOR 1ST NON-0 WORD
	AOJA	T1,CMPTHR	;THROUGH
	EXCTUX	<SKIPN @T2>	;THIS A DATA WORD?
	AOJA	T2,.-3		;NO. KEEP LOOKING
	MOVNI	P1,1		;YES. P1 WILL BE AN IOWD
	HRLI	P1,-1(T2)	;1ST LOCATION - 1
CMPLP2:	EXCTUU	<PUSH T1,@T2>	;SAVE A DATA WORD
	AOS	T2
	CAMGE	T2,J		;AT TOP?
	EXCTUX	<SKIPN @T2>	;NO. NEXT WORD NON-0?
	JRST	.+2		;NO. THROUGH THIS BLOCK
	SOJA	P1,CMPLP2	;COUNT THE WORD AND CHECK NEXT
	EXCTUU	<MOVSM P1,(U)>	;SAVE IOWD IN FRONT OF BLOCK
	AOJA	T1,CMPLP1	;LOOK FOR NEXT NON-0 BLOCK
;HERE WHEN THE CORE IMAGE IS ZERO COMPRESSED
CMPTHR:	HRLI	T3,254000	;SET A JRST C(JOBSA)
	EXCTXU	<MOVEM T3,-1(T1)>	;AT END OF FILE
	SUBI	T1,JOBSV##	;COMPUTE WORD COUNT
	MOVNS	T1		;MAKE AN IOWD
	HRL	T1,.JDAT+SGADMP	;START ADDRESS
	MOVSM	T1,.JDAT+SGALEN	;IOWD FOR THE OUTPUT UUO
				; ENTER USES NEGATIVE USRCHU TO SET RIBVER
	PUSHJ	P,SGDOA		;DO OUTPUT,RELEASE,FIND TTY
	OUTPUT	0,SGALEN	;OUTPUT UUO EXECUTED BY SGDO
				; RETURN HERE ONLY IF NO ERRORS
SAVFIN:	MOVE	J,.CPJOB##	;GET JOB NUMBER
	MOVSI	T1,(JS.EXE)	;GET EXE FILE STATUS BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR BIT IN JOB STATUS WORD
	MOVSI	T1,USRMOD	;USER-MODE BIT
	TDNE	T1,.JDAT+JOBPD1## ;WAS THIS A UUO?
	JRST	USVFIN		;YES, GO HANDLE
	PUSHJ	P,FNDPDS##	;FIND PDB
	MOVE	T1,.JDAT+SGANAM	;NAME WHICH WAS ENTERED
	MOVEM	T1,.PDNAM##(W)	;STORE
	SETZM	.PDSFD##(W)	;ZERO SFD INFO
	MOVSI	T1,.PDSFD##(W)	;SET UP A BLT TO CLEAR SFD STUFF
	HRRI	T1,.PDSFD##+1(W)
	BLT	T1,.PDSFD##+MAXLVL##-1(W)
	MOVEI	T1,JOBUAL##
	MOVEM	T1,.JDAT+SGAPPN
	PUSHJ	P,PTHFIL##	;GET PATH WHERE FILE WAS WRITTEN
	PUSHJ	P,NAMSTR##	;STR NAME
	  SKIPA	T1,DEVNAM(F)	;NOT A DSK, DEVICE NAME
	SKIPA	T2,DEVPPN(F)	;GET DIRECTORY
	MOVEI	T2,0		;NO DIRECTORY
	MOVEM	T1,.PDSTR##(W)	;STORE STR OR DEVICE NAME
	MOVEM	T2,.PDDIR##(W)	;DIRECTORY
	MOVSI	T1,.JDAT+JOBUAL##+3 ;WHRE THE SFD'S ARE STORED
	HRRI	T1,.PDSFD##(W)	;WHERE TO STORE PATH
	BLT	T1,.PDSFD##+MAXLVL##-1(W) ;STORE PATH
	PUSHJ	P,SGREL		;RELEASE DEVICE AND FIND TTY
	MOVE	T2,.JDAT+SGANAM	;GET JOB NAME
	PUSHJ	P,PRNAME	;PRINT IT
	JSP	T1,PHOLD##	;PRINT MESSAGE AND STOP JOB
	ASCIZ	/ saved/

USVFIN:	POP	P,.PDTMC##(W)	;RESTORE VM LOCS
	POP	P,.PDTMI##(W)
	PUSH	P,.JDAT+JOBPD1## ;DUPLICATE RETURN ADDRESS
	PUSH	P,.JDAT+JOBPD1##+1	;DITTO
	AOS	(P)		;INCREMENT
	PUSHJ	P,SGREL		;RELEASE DDB
	MOVSI	T1,.JDAT	;RESTORE USER ACS
	EXCTXU	<BLT T1,17>	;FROM SHADOW AREA
IFN FTMP,<
	PUSHJ	P,DPXST##	;SET UP PROPER RUNNABLE BITS FOR THIS JOB IN JBTSPS
>
	JRST	USRXIT##	;GIVE SKIP RETURN FOR UUO

SAVERR::MOVE	J,.CPJOB##	;GET JOB NUMBER
	PUSHJ	P,CLRTAB	;CLEAR BITS AND TABLES
	MOVSI	T1,(JS.EXE)	;GET EXE FILE STATUS BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR BIT IN JOB STATUS WORD
	TLO	P1,GTSAV	;DON'T KILL HISEG IF GETARG ABORTS
	MOVEM	P1,.JDAT+SGAEND	;A SAFER PLACE TO BE
	HRRZS	USRHCU##	;CLEAR SAVE IN PROGRESS FLAG
	MOVEI	T1,PRTERR	;ERROR CODE IN CASE RUN UUO(PROTECTION ERROR)
	PUSHJ	P,SGRELL	;CHANGE TO DISK ENTER ERROR CODE IF DSK
				; RELEASE DEVICE AND RETURN TO USER(IF RUN UUO)
				; OR FIND TTY+PRINT ?CRLF
	PJSP	T1,LKENFL	;PRINT MESSAGE AND STOP JOB
	ASCIZ	/Enter error /
	SUBTTL	SAVGET -- "EXE" SAVE FILES

;THIS ROUTINE DOES A "SAVE" FOR USERS RUNNING
; UNDER A VIRTUAL MEMORY SYSTEM. THE SAVE FILE IS IN THE NEW FORMAT
; (I.E. A VARIABLE-LENGTH DIRECTORY AND A VARIABLE NUMBER OF
; FILE PAGES FOLLOWING IT).

;FLAG BITS USED IN THE LEFT HALF OF P1
SV%SAV==NSRBIT		;USER ISSUED AN "SAVE" COMMAND
;SV%SHR==(1B1)		;THIS BIT MEANS WE SAW A SHARABLE HIGH SEG.
			;IT IS DEFINED IN S AND MUST NOT CHANGE
SV%FUL==:(1B2)		;USER HAD MAX ALLOWABLE CORE, PAGE WAS WRITTEN OUT
SV%PGO==(1B3)		;PHYSICAL LIMIT REACHED, PAGE WAS PAGED OUT
SV%DWO==:(1B4)		;DON'T WRITE OUT DIRECTORY (USED FOR 1ST PASS THRU DIR)
GT%DAF==:(1B5)		;DIRECTORY ALREADY FLUSHED (OCCURS IF
			; THE LAST PAGE TO BE READ IN OVERWRITES THE
			; DIRECTORY PAGE.)
GT%PLE==:(1B6)		;PHYSICAL LIMIT WAS EXCEEDED ON A GET
GTHGH==:(1B7)		;GET HIGH SEGMENT (PARAMETER TO GETNEW)
GTLOW==:(1B8)		;GET LOW SEGMENT (PARAMETER TO GETNEW)
GTBTH==:GTHGH+GTLOW	;GET BOTH HIGH AND LOW SEGMENTS
GT%GTH==:(1B9)		;A HIGH SEGMENT WAS FOUND AND READ IN (FOR VEST.
			; JOB DATA AREA SET-UP)
GT%S1S==:(1B10)		;SAW A SHARABLE PAGE IN THE COURSE OF THIS GET
GT%DW1==:GT%S1S+SV%DWO+GT%GTH ;THESE BITS ARE CLEARED WHEN ROTATING DIRECTORIES
GTMRG==:(1B11)		;MERGE EXE FILE WITH CURRENT CORE IMAGE
GTSAV==:(1B12)		;DOING A SAVE (AS OPPOSED TO RUN, MERGE, OR GETSEG)
SV%DSK==:(1B13)		;PAGE REMOVED (SV%FUL) WAS ON DISK
GTSGO==:(1B14)		;DOING A SEGOP.

;IN SAVEXE, P1-P4 ARE USED FOR SCRATCH AC'S. THEIR CONTENTS ARE:
;
;P1 - 	LH=FLAGS
;	RH=MOVING POINTER TO DIRECTORY PAGE
;
;P2 - 	LH=COUNTER OF # OF DIRECTORY PAGES
;	RH=CURRENT FILE PAGE # FOR DIRECTORY ENTRY
;
;P3 -	USED TO HOLD CURRENT PAGE #'S WHEN PASSING OVER THE PAGE MAP
;
;P4 -	LH=ACCESS BITS OF THE PAGE (IF ANY) WHICH HAD
;		TO BE WRITTEN OUT TO THE DISK TO MAKE ROOM FOR
;		THE DIRECTORY PAGE. THESE BITS ARE SAVED BECAUSE
;		THEY ARE NEEDED FOR THE DIRECTORY, BUT AT THAT TIME,
;		THE PAGE WHICH THEY REPRESENT IS WRITTEN OUT
;		AND CAN'T BE BROUGHT BACK IN UNTIL THE DIRECTORY IS
;		RELEASED.
;	RH = DISK ADDRESS OF PAGE WHICH WAS WRITTEN OUT, OR
;	     THE PAGE NUMBER OF A PAGE WHICH HAD TO BE PAGED OUT
;	     BECAUSE THE CREATION OF THE DIRECTORY CAUSED THE USER'S
;	     PHYSICAL LIMIT TO BE EXCEEDED.
;
;P4 (NON-VM ONLY) - SCRATCH AC
;
;
REPEAT 0,<
	***** EXPLANATION OF THE NSAVE PROCESSING *****


The NSAVE processing is fairly straightforward with a couple
of  exceptions.   First,  a  free  page  is acquired and the
directory is created in it.  Next, the directory is  written
out  and  its  core is released.  Finally, the core image is
written out, one page at a time for the low seg, and in  one
fell swoop for the high seg.

The only minor problem involved in the use of the  directory
is  that  before the 1st entry is created, the length of the
entire directory must be known (in order  to  set  the  file
page  #  field).   This  is  accomplished  by  creating  the
directory as if it were one  page  long,  but  not  actually
writing  it  out  as it is being created.  The end result of
this operation is a valid directory if it is one page  long,
or  the  last  page  of the directory if it is more than one
page long.  In the latter case, the current file page number
is adjusted to be one more than the length of the directory,
and the whole process is repeated with each  directory  page
being   written  out  as  it  is  created.   This  technique
penalizes   only   those   wierdos   with   extremely   long
directories.

Another problem occurs in VM systems when  the  user's  core
image  is  sufficiently  large  that  there are no available
pages to use as a directory.  In this case a random page  is
written  to  disk  and  deleted from the page map.  The disk
address of the page is saved so the page can be read back in
later.   Also,  the  directory  access bits for the page are
computed and stored before the page is written out  so  that
it  won't  have  to  be  read  back in at the point when its
directory entry is being created.

The last problem  in  VM  systems  occurs  when  the  user's
physical  core limit will not allow the directory page to be
actually  created.   In  such  a  case,  a  random  page  is
paged-out  (as distinguished from the previous case) and the
directory is then created.  If the second attempt to  create
the  directory  page  fails, a STOPCD results.  This page is
then later paged back in so that user's may not go "virtual"
inadvertantly.

For all systems, zeroes are  compressed  on  a  page-by-page
basis.  However, on non-VM systems, if the user's core image
is equal to CORMAX##, (i.e.   there  is  no  place  to  put  a
directory), then the directory is created in the user's AC's
and zero-compression is not done.  This implies  that  under
certain  extreme conditions, an EXE file may vary greatly in
size  depending  upon  the  value  of  CORMAX.

>;END OF REPEAT 0
;
;COME HERE TO BEGIN THE SAVE OF A VM SYSTEM CORE IMAGE..
;WE MUST FIRST INIT THE DEVICE AND ENTER THE
; .EXE FILE IN THE USER'S DIRECTORY
;



SAVEXE:	SKIPN	T1,.JDAT+SGALOW	;GET USER EXTENSION, IF ANY
	MOVSI	T1,'EXE'	;SET UP EXTENSION OF "EXE"
	MOVEM	T1,.JDAT+SGAEXT	;STORE IN USER'S AREA
	HRROS	USRHCU##	;SET SAVE IN PROGRESS FLAG IN MONITOR
	ENTER	0,SGANAM	;ENTER THE FILE-NAME IN THE DIRECTORY
	  JRST	SAVERR		;ERROR, ABORT WITH ERROR MESSAGE
	MOVSI	P1,GTSAV	;SET UP TO GET FLAGS
	HLRZ	T1,.JDAT+SGAHGH	;GET EXTENSION SET UP BY SG3
	CAIE	T1,'SHR'	;WAS THIS A NSSAVE?
	TLO	P1,SV%SAV	;NO, SET NON-SHARABLE BIT
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;SEARCH FOR SOME HIGH SEG
SAVEX1:	HRRZ	T1,.HBLNK(T1)	;NEXT SEGMENT
	JUMPE	T1,SAVEX3	;NONE, FORGET CALL TO COPVJD
	SKIPG	J,.HBSGN(T1)	;IS THIS NOT A SPY SEG?
	JRST	SAVEX1		;NO
	PUSHJ	P,COPVJD##	;COPY NUMBERS FROM JOBDAT TO VESTIGIAL JOBDAT
				; (ONLY NECESSARY FOR GETSEG OF UNKNOWN SEGMENTS)
SAVEX3:	SETZM	.JDAT+SGAEXT	;NO PREVIOUS PAGE PAGED OUT

;FALL THRU TO NEXT PAGE.....
;WE MUST NOW SEARCH THRU THE USER'S PAGE MAP TO FIND A FREE
; PAGE THAT WE CAN USE AS THE DIRECTORY PAGE. IF WE FIND
; ONE, THEN THERE'S NO PROBLEM. HOWEVER, IF THE USER'S MAP
; IS FULL, WE MUST TEMPORARILY WRITE ONE OF THE USER'S
; PAGES OUT TO SECONDARY STORAGE AND USE THAT PAGE AS THE
; SCRATCH PAGE. EVEN IF WE FIND A FREE PAGE, WE MAY EXCEED
; THE USER'S PHYSICAL LIMIT BY ATTEMPTING TO CREATE IT, SO WE
; MAY HAVE TO PAGE OUT SOME OTHER PAGE IN ORDER TO CREATE
; THE DIRECTORY PAGE.

	PUSHJ	P,GETDRP	;GET DIRECTORY PAGE
	  JRST	SVABRT		;CAN'T
;COME HERE WHEN WE HAVE FOUND A FREE PAGE TO USE AS THE DIRECTORY

PAGFRE:	MOVE	J,.CPJOB##	;JOB NUMBER
	MOVSI	T1,NSWP!NSHF	;GET LOCKED BITS
	TDNN	T1,JBTSTS##(J)	;JOB LOCKED?
	JRST	PAGFR1		;NO
	MOVEI	T1,SNSERR	;GET LOCKED ERROR CODE
	PUSHJ	P,SGRELE	;RELEASE DEV, RETURN ERROR CODE IF UUO
	PUSHJ	P,EXONLY	;PRESERVE XO BIT
	JSP	T1,PHOLD##	;PRINT MESSAGE AND STOP JOB
	ASCIZ	/ Illegal to save a locked core image/
PAGFR1:	MOVE	T1,CORMAX##	;GET MAX PHYSICAL LIMIT FOR SYSTEM
	LSH	T1,W2PLSH	;MAKE CORMAX INTO PAGE NUMBER
	HRLI	T1,EXESIZ*<MXSECN+1> ;MAKE HIM HAVE A VERY HIGH VIRTUAL LIMIT
	PUSH	P,.PDCVL##(W)	;REPLACE HIS NEW VIRTUAL LIMIT
	PUSH	P,.PDMVL##(W)	;AND SAVE HIS OLD ONE
	MOVEM	T1,.PDCVL##(W)
	MOVEM	T1,.PDMVL##(W)
	MOVEI	T1,EXESIZ*<MXSECN+1>
	PUSH	P,JBTCLM##(J)
	DPB	T1,JBYLCR##
PGFRE2:	MOVE	T1,P3		;GET SAVED PAGE NUMBER
	PUSHJ	P,CRPAGE	;CREATE THE PAGE
	  SKIPA	T1,[1]		;PHYS LIM EXCEEDED, START LOOKING
				; FOR PAGE TO PAGE OUT AT PAGE 1.
	JRST	GOTDIR		;SUCCESS, WE HAVE OUR DIRECTORY
PGFRE3:	PUSHJ	P,PAGOUT	;TRY TO PAGE IT OUT
	  AOSA	T1		;BUMP PAGE #
	JRST	PGFRE4		;OK
	CAIE	T1,EXESIZ*<MXSECN+1> ;THRU UPMP?
	JRST	PGFRE3		;NO, KEEP GOING
	STOPCD	.,STOP,PGL,	;++PAGES GOT LOST
PGFRE4:	TLOE	P1,SV%PGO	;REMEMBER WE DID IT (DONE IT BEFORE?)
	STOPCD	.,STOP,PAO,	;++PAGE ALREADY OUT
	DPB	T1,[POINT PM.SAD,P4,<^L<PM.ADR>+PM.SAD-1>]
				;SAVE PAGE # THAT WAS SENT OUT
	JRST	PGFRE2		;TRY TO CREATE DIRECTORY AGAIN
;COME HERE WHEN WE HAVE CREATED THE DIRECTORY PAGE
GOTDIR:	LSH	P3,P2WLSH	;CONVERT TO ADDRESS
	HRRI	P1,1(P3)	;P1 POINTS TO 2ND WORD OF THE DIRECTORY
	MOVEI	P2,1		;P2=DIR PAGE COUNT,,FILE PAGE #
	TLO	P1,SV%DWO	;DON'T ACTUALLY WRITE DIRECTORY, JUST COMPUTE IT
	SETZ	P3,		;START LOOKING AT PAGE 0 FOR USER'S PAGES
GOTDR2:	PUSHJ	P,MKNTRY	;MAKE A DIRECTORY ENTRY FOR THIS PAGE
	  JRST	THRUDR		;DIRECTORY IS OVER, GO CHECK ITS LENGTH
	AOJA	P3,GOTDR2	;MORE TO GO, GET NEXT PAGE #
;COME HERE WHEN THE DIRECTORY IS FINISHED
;IF THE DIRECTORY IS ONE PAGE LONG, THEN THE FULL DIRECTORY
; IS ALREADY SET UP AND READY TO BE OUTPUT. IF IT'S MORE THAN
; ONE PAGE LONG, ONLY THE LAST PAGE IS SET UP (WHICH OBVIOUSLY
; IS WORTHLESS NOW) AND NO PREVIOUS PAGES HAVE BEEN OUTPUT.
; IN THAT CASE, WE MUST GO THRU THE WHOLE PROCEDURE AGAIN,
; EXCEPT THIS TIME, WE WILL ACTUALLY WRITE OUT EACH PAGE
; AS WE GO.

THRUDR:	MOVNI	T1,EXESIZ
	HRLM	T1,.JDAT+SGALEN	;SET UP LENGTH
	PUSHJ	P,PUTSAB	;OUTPUT ENTRY VECTOR IF USER SPECIFIED A START ADDRESS
	MOVE	T1,[SV.END,,LN.END]	;STORE END BLOCK
	PUSHJ	P,PTDIRW	;..
	TLZ	P1,SV%DWO	;CLEAR "DON'T WRITE OUT" FLAG
	HRRZ	T1,P1		;GET DIRECTORY POINTER
	ANDI	T1,EXESIZ-1	;FIND OFFSET INTO LAST PAGE
	HLRZ	T2,P2		;GET # OF DIR PAGES-1
	LSH	T2,P2WLSH	;FIND LENGTH OF PREVIOUS PAGES
	ADD	T1,T2		;=TOTAL LENGTH OF DIRECTORY
	SUBI	T1,LN.END	;SUBTRACT LENGTH OF END-BLOCK
				;**NOTE**IF NEW BLOCKS ARE ADDED TO
				; THE FILE DIRECTORY, THEIR LENGTHS
				; SHOULD BE SUBTRACTED HERE
	SKIPE	.USUSA		;A START ADDRESS SPECIFIED BY THE USER?
	SUBI	T1,LN.STA	;YES, ACCOUNT FOR THAT
	HRLI	T1,SV.DIR	;SET UP 1ST WORD OF DIRECTORY
	TRZ	P1,EXESIZ-1	;SET POINTER TO TOP OF DIR PAGE
	PUSHJ	P,PTDIRW	;STORE IT AND BUMP POINTER
	TLNN	P2,-1		;WERE THERE MORE THAN 1 DIR PAGE?
	JRST	RELDIR		;NO (HOORAY!), WE CAN JUST OUTPUT PAGE
	HLRS	P2		;YES, SET FILE PAGE # TO BE THE
				; 1ST PAGE AFTER THE DIRECTORY PAGES
	AOS	P2		;MAKE IT ONE MORE THAN LAST DIR PAGE
	TDZA	P3,P3		;START OVER AGAIN AT PAGE 0
THRU2:	AOS	P3		;BUMP PAGE #
	PUSHJ	P,MKNTRY	;FORM A DIRECTORY ENTRY
	  CAIA			;THROUGH, OUTPUT DIRECTORY END BLOCK
	JRST	THRU2		;LOOP UNTIL PAGE 777
	PUSHJ	P,PUTSAB	;OUTPUT ENTRY VECTOR IF USER SPECIFIED A START ADDRESS
	MOVE	T1,[SV.END,,LN.END] ;PUT OUT END BLOCK
	PUSHJ	P,PTDIRW	;STORE IN DIRECTORY

;FALL THRU TO NEXT PAGE...
;WE HAVE NOW FINISHED CREATING THE DIRECTORY.
;WE MUST GET RID OF THE DIRECTORY PAGE, RESTORE ANY
; PAGES THAT HAD TO BE WRITTEN OUT EARLIER,
; AND CREATE THE REST OF THE FILE.

RELDIR:	TRZE	P1,EXESIZ-1	;IS THERE A PARTIAL PAGE LEFT TO OUTPUT?
	PUSHJ	P,PUTDIR	;YES, SEND IT OUT
	HRRZ	T1,P1		;GET PAGE ADDRESS OF DIRECTORY
	MOVE	T2,DEVMOD(F)	;DEVICE CHARACTERISTICS
	TLNE	T2,DVDSK	;RANDOM ACCESS POSSIBLE?
	TLNE	P2,777776	;DIRECTORY NO LONGER THAN ONE PAGE?
	JRST	RELDR6		;MUST WRITE ONE PAGE AT A TIME
	TLNE	P1,SV%FUL	;A PAGE REMOVED FROM THE IMAGE TO MAKE ROOM FOR DIR?
	TLNE	P4,SV%ABZ	;YES, WAS IT JUST AN ABZ PAGE?
	JRST	RELDRX		;YES, CAN DO MULTIPLE PAGE WRITES
RELDR6:	TLNN	P4,SV%ABZ	;READ DIRECTORY INTO AN ABZ PAGE
	JRST	RELDR7		;NO, JUST ZAP THE DIRECTORY PAGE
	PUSHJ	P,MAKABZ	;MAKE IT BACK INTO AN ABZ PAGE
	JRST	RELDR1		;WRITE THE DATA TO THE FILE
RELDR7:	HRRZ	T1,P1		;PAGE ADDRESS
	PUSHJ	P,ZAPPAG	;DESTROY IT
	  STOPCD	RELDR9,DEBUG,DPN, ;++DIRECTORY PAGE NON-EXISTENT
	TLNE	P1,SV%FUL	;DID WE WRITE OUT A PAGE?
	PUSHJ	P,GTSAVP	;YES, GET IT BACK AGAIN
	TLNN	P1,SV%PGO	;DID WE HAVE TO PAGE OUT A PAGE?
				; (WAS PHYS LIMIT EXCEEDED?)
	JRST	RELDR1		;NO
	LDB	T1,[POINT PM.SAD,P4,<^L<PM.ADR>+PM.SAD-1>]
				;YES, GET ITS PAGE #
	PUSHJ	P,PAGIN		;BRING IT IN
	  CAIA			;ERROR
	JRST	RELDR1		;OK
RELDR9:	POP	P,JBTCLM##(J)	;
	POP	P,.PDMVL##(W)
	POP	P,.PDCVL##(W)	;RESTORE VIR,PHY LIMITS
	JRST	SVABRT		;I/O ERROR--ABORT

;SUBROUTINE TO OUTPUT AN ENTRY VECTOR BLOCK IF A START ADDRESS WAS SPECIFIED
; BY THE USER.

PUTSAB:	SKIPN	.USUSA		;A START ADDRESS SPECIFIED?
	POPJ	P,		;NO, NOTHING TO DO
	MOVE	T1,[SV.STA,,LN.STA] ;INDICATE ENTRY VECTOR BLOCK
	PUSHJ	P,PTDIRW	;STORE THAT
	SKIPGE	T1,.USUSA	;USER SPECIFY THE ADDRESS OF THE ENTRY VECTOR?
	JRST	PUTSA1		;YES, USE THAT INSTEAD
	MOVEI	T1,(JRST)	;TRADITION
	PUSHJ	P,PTDIRW	;STORE THAT
	MOVE	T1,.USUSA	;STARTING ADDRESS
	CAIN	T1,1		;IS IT S0 JOBDAT?
	HRRZ	T1,.JDAT+.JBSA## ;YES, FIX IT
	PJRST	PTDIRW		;END OF BLOCK
PUTSA1:	LDB	T1,[POINT 5,T1,5] ;GET LENGTH OF THE ENTRY VECTOR
	PUSHJ	P,PTDIRW	;STORE THAT
	LDB	T1,[POINT 30,.USUSA,35] ;GET ADDRESS OF ENTRY VECTOR
	PJRST	PTDIRW		;AND THAT TOO
;THIS IS THE MAIN LOOP FOR AN EXE FILE SAVE
;EACH PAGE IS WRITTEN OUT INDIVIDUALLY TO INSURE DEVICE AND
; SYSTEM COMPATABILITY

RELDR1:	POP	P,JBTCLM##(J)
	POP	P,.PDMVL##(W)
	POP	P,.PDCVL##(W)	;RESTORE VIR,PHY LIMITS
	SETO	P3,		;WE WILL START LOOKING AT PAGE 0
	HRRZ	J,JBTSGN##(J)	;NEWEST SEGMENT
	JUMPE	J,RELD1A	;?
	SKIPLE	J,.HBSGN(J)	;SKIP IF SPY SEG
	PUSHJ	P,SETHRL##	;YES, SET LH(JOBHRL)
RELD1A:	MOVE	J,.CPJOB##	;RESET J
RELDR2:	AOS	T1,P3		;BUMP PAGE #
	CAIL	T1,EXESIZ*<MXSECN+1> ;TOP OF CORE IMAGE?
	JRST	[HRRZS	USRHCU## ;YES, CLEAR SAVE IN PROGRESS FLAG
		 JRST	SAVFIN] ; WE'RE FINALLY THRU!!!
	PUSHJ	P,CMPBIT	;COMPUTE DIRECTORY BITS
	  JRST	RELDR2		;NON-EXISTENT PAGE
	TLNE	T1,SV%ABZ	;ALLOCATED-BIT-ZERO?
	JRST	RELDR2		;YES, DON'T SAVE IT
	MOVE	T1,P3		;GET PAGE #
	PUSHJ	P,YANKIT	;BRING PAGE IN, IF IT'S OUT
	  JFCL			;SHOULDN'T BE ABZ
	MOVE	T1,P3		;GET PAGE #
	TLNN	T2,(PA.AA)	;ACCESS ALLOWED?
	PUSHJ	P,SETAA		;NO, SET IT
	MOVE	T1,P3		;GET PAGE NUMBER
	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	HRRI	T1,-1(T1)	;=START OF PAGE-1
	HRRM	T1,.JDAT+SGALEN	;STORE IN IOWD
	PUSH	P,P1		;SAVE P1
IFN FTXMON,<
	PUSH	P,DEVISN(F)	;SAVE SECTION NUMBER FOR I/O
	HLRZM	T1,DEVISN(F)	;SET IT UP FOR THE OUTPUT
>
	OUTPUT	SGALEN		;WRITE OUT THIS PAGE
IFN FTXMON,<
	POP	P,DEVISN(F)	;RESTORE DEVISN
>
	POP	P,P1		;RESTORE IT
	PUSHJ	P,SGIOCK	;CHECK FOR ERRORS
	JRST	RELDR2		;NO, GO BACK FOR MORE
;HERE IF PAGES CAN BE WRITTEN A DIRECTORY ENTRIES WORTH AT A TIME
; I.E., NOT A MAGTAPE, NOT A MULTIPLE PAGE DIRECTORY, A PAGE DIDN'T
; HAVE TO BE DELETED FROM THE ADDRESS SPACE TO CREATE THE DIRECTORY

RELDRX:	POP	P,JBTCLM##(J)	;RESTORE LIMITS
	POP	P,.PDMVL##(W)	; ..
	POP	P,.PDCVL##(W)	; ..
	HRRZ	J,JBTSGN##(J)	;POINT TO NEWEST SEGMENT
	JUMPE	J,RELDX0
	SKIPE	J,.HBSGN(J)	;SEGMENT WORD
	PUSHJ	P,SETHRL##	;YES, INSURE JOBHRL IS CORRECT
RELDX0:	MOVE	J,.CPJOB##	;GET JOB NUMBER BACK
	PUSHJ	P,GTDIRW##	;GET DIRECTORY HEADER WORD
	MOVEI	P2,-1(T1)	;LENGTH OF DIRECTORY ENTRIES
RELDX1:	PUSHJ	P,GTDIRE##	;GET NEXT DIRECTORY ENTRY
	  JRST	RELDX2		;DONE
	TRNN	P3,-1		;THIS ENTRY DESCRIBE ABZ PAGES?
	JRST	RELDX1		;YES, DON'T WRITE THEM
	HRRZ	T1,P4		;STARTING PAGE NUMBER
	LSH	T1,P2WLSH	;STARTING ADDRESS
	LDB	T2,[POINT 9,P4,8] ;REPEAT COUNT
	ADDI	T2,1		;ACTUAL NUMBER OF PAGES
	LSH	T2,P2WLSH	;NUMBER OF WORDS TO WRITE
	PUSHJ	P,FSIOWD##	;MAKE AND STORE THE IOWD
	PUSHJ	P,WRSTUF##	;WRITE OUT THE PAGE(S)
	JRST	RELDX1		;DO THE ENTIRE CORE IMAGE
RELDX2:	HRRZS	USRHCU##	;SAVE NO LONGER IN PROGRESS
	HRRZ	T1,P1		;PAGE ADDRESS OF DIRECTORY
	TLNE	P1,SV%FUL	;WAS AN ABZ PAGE USED FOR THE DIRECTORY?
	JRST	RELDX3		;YES, GO MAKE IT ONE AGAIN
	PUSHJ	P,ZAPPAG	;NO, JUST MAKE THE DIRECTORY PAGE GO AWAY
	  JFCL			;A STOPCD WOULDN'T REALLY HELP
	JRST	SAVFIN		;FINISH UP
RELDX3:	LSH	T1,W2PLSH	;PAGE NUMBER
	S1PSHJ	ZERPAG##	;MAKE IT BACK INTO AN "ABZ" PAGE
	JRST	SAVFIN		;AND FINISH UP
;SUBROUTINE TO GET A FREE PAGE FOR THE DIRECTORY

GETDRP::SKIPN	VIRTAL##	;MUST BE ENOUGH VIRTUAL CORE TO CREATE 1 PAGE
	JRST	NEED1P##	;GIVE UP NOW
	PUSHJ	P,GTFREP	;TRY TO FIND A FREE PAGE
	  SKIPA	P3,[XWD 0,PG.BDY] ;COULDN'T, START AT PAGE 777
	SKIPA	P3,T1		;GOT ONE, PUT NUMBER IN P3
	SKIPA	J,.CPJOB##	;SET UP JOB NUMBER
	JRST	CPOPJ1##	;GIVE GOOD RETURN
SAV2:	MOVE	T1,P3		;GET THE PAGE #
	JUMPE	P3,NEED1P##	;IF IT'S PAGE 0, WE LOSE
	PUSHJ	P,CMPBIT	;COMPUTE THE SAVE-FILE BITS FOR THIS PAGE
	  PUSHJ	P,BRCSTP	;ISSUE FATAL STOPCD IF NON-EXISTENT
	TLNE	T1,SV%HIS	;DON'T USE A HIGH SEGMENT PAGE
	SOJA	P3,SAV2		;DECREMENT PAGE #
	HLLZ	P4,T1		;SAVE THESE BITS FOR LATER
	HRRZ	T1,P3		;GET THE PAGE #
	PUSH	P,P3		;SAVE P3
	SETZ	P3,		;FLAG NOT REALLY IPCF
	MOVE	R,JBTADR##(J)	;FOR DCUPR (THE ENTER ABOVE CLOBBERED R AND J)
	PUSHJ	P,IPCRMV##	;REMOVE PAGE FROM LOG. ADR. SPACE
	  JRST	P3POPJ##	;RESTORE P3 AND RETURN
	TLNE	T2,IP.DSK##_-^D18 ;DISK PAGE?
	TLO	P1,SV%DSK	;YES
	POP	P,P3		;RESTORE P3
	TLNE	P4,SV%ABZ	;PAGE ALLOCATED BUT ZERO?
	JRST	[PUSHJ	P,IPCDLX## ;YES, JUST DELETE IT (REAPPEAR IT LATER)
		 JRST	SAV3]	;AND PROCEED
	PUSHJ	P,IPCPAG##	;WRITE PAGE OUT (RETURN WITH T2=PAGE #
				; OR DISK ADDRESS)
	  POPJ	P,		;ERROR
SAV3:	DPB	T2,[POINT PM.SAD,P4,<^L<PM.ADR>+PM.SAD-1>]
				;SAVE ADDRESS WHERE WE PUT IT ON DISK
	TLO	P1,SV%FUL	;REMEMBER THAT WE DID THIS
	JRST	CPOPJ1##	;RETURN
;SUBROUTINE TO PERFORM A PAGE. UUO
;CALL:
;	MOVE	T1,[FUNCTION CODE,,0]
;	MOVE	T2,PAGE #
;	PUSHJ	P,PAGUUO
;	  RETURN HERE IF ERROR RETURN FROM PAGE. UUO
;	GOOD RETURN
;
;
;ON EXIT, T1 CONTAINS THE PAGE NUMBER
PAGUUO::MOVEI	T3,1		;LENGTH OF THE ARGUMENT BLOCK
PAGUUN::PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSH	P,T2		;SAVE PAGE # TO RETURN TO CALLER
	HRRI	T1,SGASAV+1	;POINT TO ARGUMENT BLOCK
	PUSH	P,.JDAT+SGAHGH	;SAVE SGAHGH
	PUSH	P,.JDAT+SGANEW	; AND SGANEW
	MOVEM	T2,.JDAT+SGAHGH	;STORE PAGE NUMBER FOR UUO
	MOVEM	T1,.JDAT+SGASAV ;STORE IN USER AREA
	MOVEM	T3,.JDAT+SGANEW ;STORE LENGTH OF ARGUMENT BLOCK
	PAGE.	SGASAV,		;DO THE UUO
	  SOS	-3(P)		;ERROR
	POP	P,.JDAT+SGANEW
	POP	P,.JDAT+SGAHGH
	MOVE	F,USRJDA##+0	;IOWAIT CLOBBERS F
	JRST	TPOPJ1##	;RESTORE PAGE # AND RETURN
;SUBROUTINE TO SET ACCESS ALLOWED BIT FOR PAGE
;	(BIT MUST BE OFF)
;CALL:
;	MOVE	T1,PAGE#
;	PUSHJ	P,SETAA
;	HERE ALWAYS
SETAA:	HRRZ	T2,T1		;MOVE PAGE #
	MOVSI	T1,.PAGAA	;GET FUNCTION CODE
	PUSHJ	P,PAGUUO	;DO THE PAGE UUO
	  STOPCD	CPOPJ##,DEBUG,CSA,	;++CAN'T SET ACCESS ALLOWED
	POPJ	P,
;SUBROUTINE TO PAGE OUT THE USER'S LOW SEGMENT ON A GETSEG
;THIS IS ONLY CALLED IF THE CURRENT USER IS "VIRTUAL".
;
;CALL:
;	PUSHJ	P,PAGLOW
;	HERE ALWAYS
;
PAGLOW::MOVEI	T1,1		;START AT PAGE 0
	PUSH	P,F		;PAGOUT CLOBBERS F
PGLOW2:	TRNE	T1,HLGPNO	;WRAP A SECTION BOUNDARY?
	JRST	PGLOW4		;YES
	LSH	T1,P2SLSH	;CONVERT TO SECTION #
PGLOW5:	CAILE	T1,MXSECN	;OVER THE TOP?
	JRST	FPOPJ##
	SKIPE	T4,.UPMP+SECTAB(T1) ;GET SECTION POINTER
	TLNE	T4,(<<PM.DCD^!PM.ACD>B2>) ;IS THIS AN INDEPENDENT SECTION?
	AOJA	T1,PGLOW5	;NO, TRY NEXT SECTION
	LSH	T1,S2PLSH	;SECTION OK, PROCEED
	PUSHJ	P,SCDCHK##	;GIVE OTHER PEOPLE A CHANCE
PGLOW4:	S1PSHJ	GTPME##		;GET THE MAP ENTRY
	JUMPE	T2,PGLOW3	;IF NON-EXISTENT, JUMP
	PUSHJ	P,CKDIRP	;IS THIS A DIR PAGE?
	  AOJA	T1,PGLOW2	;YES, DON'T PAGE IT OUT
	PUSHJ	P,PAGOUT	;TRY TO PAGE THIS PAGE OUT
	  JFCL			;COULDN'T
	AOJA	T1,PGLOW2	;GET NEXT PAGE
PGLOW3:	SKIPN	.USREL		;DOES HE HAVE A NON-CONTIGUOUS CORE IMAGE?
	PJRST	FPOPJ##		;NO, WE MUST HAVE COME TO END OF LOW SEG
	AOJA	T1,PGLOW2	;NO
;SUBROUTINE TO MAKE A SINGLE DIRECTORY ENTRY FOR A GIVEN PAGE
;CALL:
;	MOVE	P1,DIRECTORY POINTER
;	MOVE	P2,CURRENT FILE PAGE #
;	MOVE	P3,PAGE #
;	PUSHJ	P,MKNTRY
;	  RETURN HERE IF PAGE # IS TOO HIGH (.GTE. PAGSIZ)
;	RETURN HERE OTHERWISE
;
;THIS ROUTINE EXPECTS THE "LAST" DIRECTORY ENTRY TO BE IN
; T3 AND T4. IT COMPUTES THE DIRECTORY FOR THE PAGE # IN P3,
; AND DETERMINES IF THIS NEW PAGE CAN BE INCLUDED IN THE
; DIRECTORY ENTRY FOR THE LAST GROUP OF PAGES. IF SO,
; THE REPEAT COUNT (IN T4) IS BUMPED AND CONTROL IS RETURNED.
; IF THIS PAGE NEEDS A NEW ENTRY, THE "OLD" ENTRY IS OUTPUT
; TO THE DIRECTORY, THE CURRENT FILE PAGE NUMBER IS UPDATED,
; AND THE NEW DIRECTORY ENTRY REPLACES THE OLD ONE IN T3,T4
;
;
MKNTRY:	CAIL	P3,EXESIZ*<MXSECN+1> ;TOO HIGH?
	JRST	NEWENT		;YES, OUTPUT LAST ENTRY AND EXIT
	PUSHJ	P,CMPBIT	;COMPUTE FLAG BITS FOR THIS PAGE
	  JRST	CPOPJ1##	;NON-EXISTENT PAGE, EXIT AND IGNORE
	JUMPE	P3,[MOVE	T3,T1	;IF THIS IS THE 1ST PAGE,..
		    SETZ	T4,	;MAKE IT THE LAST PAGE
		    JRST	CPOPJ1##]
				;PLEASE NOTE---THIS LAST CHECK ASSUMES
				;THAT PAGE ZERO IS THE 1ST PAGE CHECKED.
				;IF THIS IS NOT TRUE (I.E. IF THE DIRECTORY
				; IS FORMED BY STARTING WITH PAGE 777
				; AND PROCEDING BACKWARDS), THEN THIS
				; ALGORITHM MUST BE CHANGED.
	LDB	T2,[POINT 9,T4,8] ;GET LAST REPEAT COUNT
	CAIE	T2,777		;END OF REPEAT COUNT?
	CAME	T1,T3		;ARE THE FLAG BITS THE SAME AS THE LAST PAGE
	JRST	NEWENT		;NO, FORM A NEW DIR ENTRY
	ADDI	T2,1(T4)	;FIND # OF NEXT CONTIGUOUS PAGE
	CAME	T2,P3		;IS THIS IT?
	JRST	NEWENT		;NO, FORM A NEW ENTRY FOR THIS PAGE
	ADD	T4,[1000,,0]	;YES, BUMP LAST REPEAT COUNT
	JRST	CPOPJ1##	;RETURN
;COME HERE TO FORM A NEW DIRECTORY ENTRY
NEWENT:	TLZE	T3,SV%ABZ	;ALLOCATED BUT ZERO PAGE?
	JRST	NWENT2		;YES
	HRR	T3,P2		;NO, GET CURRENT FILE PAGE #
	LDB	T2,[POINT 9,T4,8]	;GET LAST REPEAT COUNT
	ADDI	P2,1(T2)	;COMPUTE NEW FILE PAGE #
NWENT2:	HRRZ	T2,P3		;GET THIS PAGE #
	EXCH	T1,T3		;GET 1ST WORD OF LAST ENTRY
	EXCH	T2,T4		;GET 2ND WORD
	PUSHJ	P,PTNTRY	;STORE IT IN DIRECTORY
	CAIGE	P3,EXESIZ*<MXSECN+1> ;LAST PAGE?
	AOS	(P)		;NO, SKIP RETURN
	POPJ	P,		;YES, GIVE NON-SKIP RETURN
;SUBROUTINE TO PAGE OUT A PAGE
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,PAGOUT
;	HERE IF CAN'T PAGE IT OUT
;	HERE IF CAN AND DID
;
;T1 IS PRESERVED

PAGOUT::MOVE	J,.CPJOB##	;JUST FOR SAFETY
	LDB	T2,[POINT 9,.JDAT+.JBPFH##,26] ;GET STARTING PAGE OF PFH
	SKIPE	.JDAT+.JBPFH	;IF NO PFH, OR
	CAIGE	T1,(T2)		;THIS PAGE IS BELOW PFH'S STARTING PAGE
	JRST	PAGOU0		;WE'RE SAFE, PAGE THIS ONE OUT
	LDB	T2,[POINT 9,.JDAT+.JBPFH##,26] ;GET ENDING PAGE OF PFH
	CAIG	T1,(T2)		;IS PAGE WE WANT PAST PFH?
	POPJ	P,		;NOPE - THIS PAGE HAS PFH, ERROR RETURN
PAGOU0:	PUSH	P,T1		;SAVE PAGE #
	HRRZ	T1,.JDAT+JOBINT##;GET ADDRESS OF JOBINT BLOCK
	HRRZI	T2,3(T1)	;END ADDRESS OF JOBINT BLOCK
	TRZ	T1,PG.BDY	;MAKE START ADDRESS A PAGE BOUNDARY
	LSHC	T1,W2PLSH	;CONVERT BOTH TO PAGE NUMBERS
	CAME	T1,(P)		;IS START PAGE OF JBINT BLOCK IN THIS PAGE?
	CAMN	T2,(P)		;IS END OF JBINT BLOCK IN PAGE?
	JRST	TPOPJ##		;ERROR RETURN
	MOVE	T1,(P)		;GET PAGE WE WANT TO PAGE OUT
	PUSHJ	P,PSIIVR##	;FIND RANGE OF PAGES FOR PSI VECTOR
	HLRZ	T2,T1		;GET ENDING PAGE
	TLZ	T1,-1		;MAKE IT STARTING PAGE ONLY
	CAML	T1,0(P)		;ARE WE BELOW RANGE OF PSI VECTOR
	CAMLE	T2,0(P)		;OR ABOVE IT?
	SKIPA	T1,0(P)		;WE ARE GOLDEN, GET PAGE FOR GETPAG
	JRST	TPOPJ##		;PAGE CONTAINS PSI VECTOR, LEAVE IT ALONE

	PUSHJ	P,GETPAC##	;GET PAGE ACCESSABILITY
	TLNE	T1,(PA.CPO!PA.NXP!PA.OUT) ;CAN IT BE PAGED OUT?
	JRST	TPOPJ##		;NO, RESTORE T1 AND EXIT
	MOVE	T2,(P)		;GET PAGE #
	TLO	T2,(1B0)	;SET DESTORY BIT
	MOVSI	T1,.PAGIO	;GET FUNCTION CODE
	PUSHJ	P,PAGUUO	;DO THE UUO
	  JRST	TPOPJ##		;I/O ERROR
	JRST	TPOPJ1##	;IT'S OUT
;SUBROUTINE TO PAGE IN A PAGE
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,PAGIN
;	  ERROR RETURN
;	OK RETURN

PAGIN::	PUSH	P,T1		;SAVE PAGE #
	HRRZ	T1,.PDCVL##(W)	;GET USER'S PHYSICAL LIMIT/GUIDELINE
	LDB	T2,IMGIN##	;AND HOW MANY PAGES ARE IN CORE
	TRZ	T1,400000	;CLEAR LIMIT BIT
	SKIPN	.JDAT+SGAEXT	;PAGE PREVIOUSLY PAGED OUT?
	CAML	T2,T1		;EXCEEDING LIMIT?
	JRST	PAGIN2		;YES. GO PAGE OUT A PAGE
PAGIN1:	POP	P,T2		;GET PAGE #
	MOVSI	T1,.PAGIO	;GET FUNCTION CODE
	PUSHJ	P,PAGUUO	;PAGE. UUO
	  SKIPA	T2,.JDAT+SGASAV	;SOMETHING HAPPENED, GET THE ERROR
				; CODE WHICH WAS RETURNED IN USER AC'S
	JRST	[MOVEM	T1,.JDAT+SGAEXT	;SAVE LAST PAGE PAGED OUT FOR NEXT TIME
		 JRST	CPOPJ1##]	;AND INDICATE SUCCESS
	CAIE	T2,PAGLE%	;LIMIT EXCEEDED IS OK
	POPJ	P,		;ANYTHING ELSE IS FATAL
	PUSH	P,T1		;SAVE PAGE-IN PAGE #
PAGIN2:	SKIPN	T1,.JDAT+SGAEXT	;GET LAST PAGE PAGED OUT IF ONE HAS BEEN
	MOVEI	T1,1		;TRY TO PAGE OUT SOME PAGES
PAGIN3:	PUSHJ	P,CKDIRP	;A DIRECTORY PAGE?
	  CAIA			;YES, CAN'T PAGE IT OUT
	PUSHJ	P,PAGOUT	;TRY TO PAGE IT OUT
	  JRST	[CAIE	T1,EXESIZ*<MXSECN+1>-1 ;THRU ALL PAGES?
		 AOJA	T1,PAGIN3	;NO, TRY AGAIN
		 SETZM 	.JDAT+SGAEXT	;NO PREVIOUS PAGE PAGED OUT
		 JRST	PAGIN1]		;YES, FATAL ERROR
	POP	P,T1		;GET PAGE BACK
	SETZM	.JDAT+SGAEXT	;LOOK AT ALL PAGES AS CANDIDATES
	JRST	PAGIN		;TRY AGAIN TO PAGE IT IN
;ROUTINE TO READ IN A PAGE THAT HAD TO BE OUTPUT EARLIER
;CALL:
;	MOVE	P4,DISK-ADDRESS-OF-PAGE
;	MOVE	P1,PAGE-ADDRESS
;	PUSHJ	P,GTSAVP
;	RETURN HERE ALWAYS IF OK

GTSAVP::HRRZ	T1,P1		;GET PAGE ADDRESS
	LSH	T1,W2PLSH	;MAKE INTO A PAGE NUMBER
	LDB	T2,[POINT PM.SAD,P4,<^L<PM.ADR>+PM.SAD-1>]
	TLNE	P1,SV%DSK	;WAS IT A DISK ADR?
	TLO	T2,IP.DSK##_-^D18 ;YES
	PUSHJ	P,IPCINS##	;CREATE PAGE
	  CAIA			;ERROR OF SOME SORT
	POPJ	P,
	CAIE	T1,IPCUP%##	;DUPLICATE PAGE?
	STOPCD	CPOPJ##,DEBUG,DPL ;++DIRECTORY PAGE LOST
	TLZN	T2,IP.DSK##_-^D18 ;DISK PAGE?
	PJRST	DLTPGC##	;NO, JUST DELETE PAGE IN CORE
	PUSHJ	P,ONPOQ##	;ON OUT QUEUE (CAN'T BE ON IP QUEUE)?
	  PJRST	DLTPGD##	;NO, JUST RETURN DISK SPACE
	SSX	T4,MS.MEM	;CLEAR MEMTAB
	SE1XCT	<SETZM MEMTAB(T4)>
	PJRST	DLTPGD##


;SUBROUTINE TO GET A FREE PAGE FROM USER'S PAGE MAP
;CALL:
;	PUSHJ	P,GTFREP
;	  HERE IF COULDN'T
;	HERE IF DID, PAGE # IN T1
;
;IF THIS ROUTINE IS ENTERED AT GTFREP, IT WILL START SEARCHING
; AT PAGE 777.
;IF ENTERED AT GTFRE2, IT WILL START SEARCHING AT THE PAGE # IN T1.
;
GTFREP::MOVEI	T1,PG.BDY	;START AT PAGE 777
	SE1ENT
GTFRE1:	PUSHJ	P,GTPME##	;GET MAP ENTRY
	JUMPE	T2,CPOPJ1##	;IF NON-EXISTENT, ITS OK
	SOJG	T1,GTFRE1	;DECREMENT PAGE # AND TRY AGAIN
	POPJ	P,		;COULDN'T
;SUBROUTINE TO CHECK IF A GIVEN PAGE IS A DIRECTORY PAGE
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,CKDIRP
;	HERE IF THIS PAGE IS A DIRECTORY
;	HERE IF NOT
;
;ON RETURN, T3 POINTS TO WHERE THE DIRECTORY PAGE
;   POINTER IS BEING KEPT (P1, SGANAM, OR SGAEXT)
;T1,T4 PRESERVED
;T2 DESTROYED

CKDIRP::JUMPE	P1,CPOPJ1##	;NOT A DIRECTORY PAGE IF FROM PAGIA
	PUSH	P,T1		;SAVE PAGE NUMBER
	LSH	T1,P2WLSH	;MAKE INTO AN ADDRESS
	HRRZ	T2,P1		;GET CURRENT DIRECTORY POINTER
	TRZ	T2,PG.BDY	;CLEAR OFFSET
	MOVEI	T3,P1		;ASSUME ITS' THERE
	CAMN	T1,T2		;IS THIS A DIR PAGE?
	JRST	TPOPJ##		;YES, RESTORE PAGE # AND EXIT
	JRST	TPOPJ1##	;NOT A DIRECTORY PAGE

;SUBROUTINE TO PAGE IN A PAGE, IF IT'S OUT
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,YANKIT
;	  RETURN HERE IF PAGE ALLOCATED BUT ZERO (T1=PAGE NUMBER)
;	RETURN HERE WITH PAGE BITS IN T2
YANKIZ::SETZM	.JDAT+SGAEXT	;NO PREVIOUS PAGE PAGED OUT
YANKIT::PUSH	P,T1		;SAVE PAGE BITS
	PUSHJ	P,GETPAC##	;GET PAGE BITS
	MOVE	T2,T1		;MOVE BITS
	POP	P,T1		;GET PAGE # BACK
	TLNE	T2,(PA.ZER)
	POPJ	P,
	PUSH	P,T2		;SAVE BITS
	TLNE	T2,(PA.OUT)	;IS IT OUT?
	PUSHJ	P,PAGIN		;YES, BRING IT IN
	  JFCL			;NOT OUT
	JRST	T2POJ1##	;RESTORE PAGE BITS
;SUBROUTINE TO GET A PAGE INTO CORE AND MAKE IT ACCESSIBLE
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,PAGIA
;	  HERE ON FAILURE
;	HERE ON SUCCESS, PAGE IS IN CORE WITH ACCESS ALLOWED ON
;SETS WS SCRAMBLED BIT IF IT DOES ANYTHING, WORRYS ABOUT LIMITS

PAGIA::	PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	MOVEI	P1,.USUAC	;SAVE USER ACS SINCE
	EXCTUX	<BLT P1,.USUAC+17> ; PAGE UUO WILL CLOBBER THEM
	HRRZ	P2,T1		;PAGE TO DOITTOIT
	PUSHJ	P,GETPAC##	;GET PAGE ACCESSIBILITY
	TLNN	T1,(PA.OUT)	;PAGE OUT?
	JRST	PAGIA1		;NO, THEN THIS IS SIMPLIER
	SETZB	P1,.JDAT+SGAEXT	;FOR CKDIRP, ALSO NO PREVIOUS PAGE PAGED OUT
	HRRZ	T1,P2		;PAGE NUMBER
	PUSHJ	P,PAGIN		;GO PAGE IT IN
	  JRST	[SOS (P)	;SIGH, SET FOR FAIL RETURN
		 SETZ P2,	;SINCE WORKING SET HAS NOT CHANGED
		 JRST PAGIA2]	;RESTORE USER ACS AND RETURN
	TLO	P2,400000	;REMEMBER THAT THE WORKING SET HAS BEEN DIDDLED
	PUSHJ	P,GETPAC##	;GET CURRENT ACCESSIBILITY
PAGIA1:	TLNE	T1,(PA.AA)	;ACCESS ALLOWED ON?
	JRST	PAGIA2		;YES, THEN ESSENTIALLY DONE
	HRRZ	T1,P2		;NO, GET PAGE NUMBER AGAIN
	PUSHJ	P,SETAA		;TURN ON AA
	TLO	P2,400000	;AND INDICATE WS HAS CHANGED
PAGIA2:	MOVSI	T1,.USUAC	;RESTORE USER ACS
	EXCTXU	<BLT T1,17>
	JUMPGE	P2,CPOPJ1##	;JUMP IF LENGTHY NOOP
	MOVSI	T1,(UP.WHC!UP.WSS) ;NOTE CHANGE IN WORKING SET FOR PFH
	IORM	T1,.USBTS	;SO IT DOESN'T GET CONFUSED
	JRST	CPOPJ1##	;GOOD RETURN

;SUBROUTINE TO CREATE A SECTION
;CALLING SEQUENCE:
;	PUSHJ	P,CRESSN
;	  ...ERROR RETURN
;	SECTION CREATED

CRESSN::MOVE	T2,.USUSN	;SECTION TO CREATE
	LSH	T2,P2SLSH	; ..
REPEAT 0,<
	CAIG	T2,1		;*** HACK
	JRST	CPOPJ1##	;SECTION ZERO OR SECTION 1 HACK
	TRZ	T2,400000_-P2WLSH ;CLEAR SET BY UUO BIT
>
	JUMPE	T2,CPOPJ1##
	MOVSI	T1,.PAGCS	;***
	PJRST	PAGUUO		;DO IT
;ROUTINE TO COMPUTE THE FLAG BITS FOR THE DIRECTORY ENTRY
;CALL:
;	MOVE	P3,PAGE #
;	PUSHJ	P,CMPBIT
;	  RETURN HERE IF PAGE WAS NON-EXISTENT
;	RETURN HERE OTHERWISE
;
;ON RETURN, T1 WILL HAVE THE FLAG BITS SET UP PRECISELY AS THEY
; SHOULD APPEAR IN THE DIRECTORY ENTRY (I.E. IN THE LEFT-MOST BITS)
;IF THE PAGE IS ALLOCATED-BUT-ZERO, THE "SV%ABZ"
; BIT WILL BE SET ALSO.
; THIS BIT IS LATER TRANSFORMED INTO A FILE PAGE NUMBER OF ZERO.
;
;NOTE THAT THE DIRECTORY PAGE IS TREATED AS BEING
; NON-EXISTENT, EXCEPT IN NON-VM SYSTEMS WHEN
; WE ARE NOT ZERO-COMPRESSING (THE DIRECTORY IS USER AC'S).

CMPBIT:	PUSH	P,T3		;SAVE T3 (T3 AND T4 ARE CURRENT DIRECTORY ENTRY)
	PUSH	P,T4		;SAVE T4
	MOVE	T1,P3		;GET PAGE #
	PUSHJ	P,GETPAC##	;GET PAGE MAP ACCESSABILITY BITS
	MOVE	T2,T1		;SAVE BITS
	POP	P,T4		;RESTORE OLD DIR ENTRY
	POP	P,T3
IFN FTXMON,<
	TRNN	P3,PG.BDY	;FIRST PAGE OF A NEW SECTION?
	TLNN	T2,(PA.NXS+PA.IND) ;YES, PAGE IN A NON-EXISTANT SECTION?
	CAIA			;NO TO EITHER
	JRST	[ADDI P3,PG.BDY ;YES, SKIP THIS SECTION
		 POPJ P,]	;RETURN SAYING NON-EXISTANT PAGE
>
IFN FTPEEKSPY,<
	TLNN	T2,(PA.GSP)	;A SPY PAGE? IF SO TREAT AS NON EX
>
	TLNE	T2,(PA.NXP)	;PAGE EXIST?
	POPJ	P,		;NO, EXIT
	SETZ	T1,		;CLEAR BITS FOR ENTRY
	TLNE	T2,(PA.WRT)	;CAN IT BE WRITTEN?
	TLO	T1,SV%WRT	;YES, SET BIT
	TLNE	T2,(PA.ZER)	;ALLOCATED BUT ZERO?
	TLO	T1,SV%ABZ	;YES, SET THAT BIT IN FLAGS
	TLNN	T2,(PA.GHI)	;PAGE IN A HIGH SEGMENT?
	JRST	CMP2		;ITS NOT IN THE HIGH SEG
	TLO	T1,SV%HIS	;SET HISEG BIT
	TLNN	P1,SV%SAV	;WAS THIS AN "SAVE" COMMAND?
	TLO	T1,SV%SHR	;NO, SET SHARABLE BIT TOO
	MOVEI	T2,JS.XO	; AND EXECUTE ONLY BIT
	TDNE	T2,JBTSTS##(J)	;IS IT SET?
	TLO	T1,SV%CON	;YES, MUST BE CONCEALED
	JRST	CPOPJ1##	;RETURN SINCE DIR CAN'T BE IN HIGH SEG
CMP2:	TLNN	T1,SV%ABZ	;SKIP CALL IF WE ALREADY KNOW THIS
	PUSHJ	P,CHKABZ	;IS THIS PAGE ALL ZEROES?
	  TLO	T1,SV%ABZ	;YES, SET BIT
	HRRZ	T2,P1		;GET ADDRESS OF DIRECTORY PAGE
	LSH	T2,W2PLSH	;CONVERT TO PAGE #
	CAIE	T2,(P3)		;IS THIS THE DIRECTORY PAGE?
	JRST	CPOPJ1##	;NO, RETURN TO CALL+2
	TLNN	P1,SV%FUL	;YES, DID WE HAVE TO WRITE OUT
	POPJ	P,		; A PAGE EARLIER?..EXIT IF NO
				; AND TREAT THE DIRECTORY PAGE AS NON-EXISTENT
	HLLZ	T1,P4		;YES, GET SAVED BITS FOR WRITTEN-OUT
	JRST	CPOPJ1##	; AND EXIT AS IF THIS WERE THAT PAGE
;COME HERE FOR A VARIETY OF USER SINS
GTABRT::
SVABRT:	MOVE	J,.CPJOB##	;GET JOB NUMBER
	MOVSI	T1,(JS.EXE)	;GET EXE SAVE FILE BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR IT
	MOVSI	T1,USRMOD	;GET USER-MODE BIT
	TDNN	T1,.JDAT+JOBPD1## ;UUO?
	JRST	SVABRU		;NO, DON'T RESTORE
	POP	P,.PDTMC##(W)	;YES, RESTORE VM LOCS
	POP	P,.PDTMI##(W)
SVABRU:	HRRZS	USRHCU##	;CLEAR SAVE IN PROGRESS FLAG
	MOVEI	T1,TRNERR	;GET APPROPRIATE ERROR CODE
	PUSHJ	P,SGRELE
	JSP	T1,PHOLD##
	ASCIZ	.I/O error for EXE file.


;COME HERE IF A BAD RETURN FROM "CMPBIT" OCCURED:
BRCSTP:	STOPCD	SAVERR,DEBUG,BRC,	;++BAD RETURN FROM CMPBIT


;ROUTINE TO CHECK IF THIS USER IS TRYING TO SAVE A NEW-STYLE (.EXE)
; SAVE FILE
;
;CALL:
;	MOVE	J,JOB-NUMBER
;	PUSHJ	P,CHKEXE
;	  HERE IF YES
;	HERE IF NO
;
;ALL AC'S PRESERVED
;
CHKEXE::PUSH	P,T1		;SAVDDL NEEDS T1 SAVED
	MOVE	T1,JBTST2##(J)	;GET JOB STATUS WORD
	TLNE	T1,(JS.EXE)	;IS THE "EXE" BIT SET? (WHICH
				; MEANS THAT WE ARE DOING A
				; SAVE OF AN EXE FILE)
	JRST	TPOPJ##		;YES, RESTORE T1 AND EXIT
	JRST	TPOPJ1##	;NO, EXIT AT CALL+2
;SUBROUTINE TO CHECK IF A PAGE IS ALL ZEROES TO ENABLE IT
; TO BE COMPRESSED
;CALL:
;	MOVE	P3,PAGE # TO CHECK
;	PUSHJ	P,CHKABZ
;	RETURN HERE IF PAGE IS ALL ZEROES
;	HERE OTHERWISE
;
; T2 IS DESTROYED
;
CHKABZ:	PUSH	P,T1		;SAVE T1
	PUSH	P,T3		;PRESERVE
	PUSH	P,T4		;OLD ENTRY
	MOVE	T1,P3		;SET PAGE #
	PUSHJ	P,YANKIT	;IF OUT, BRING IT IN
	  JRST	[POP P,T4	;RESTORE OLD ENTRY
		 POP P,T3
		 JRST TPOPJ##]	;ABZ
	TLNN	T2,(PA.AA)
	PUSHJ	P,SETAA
	POP	P,T4		;RESTORE OLD ENTRY
	POP	P,T3
	POP	P,T2		;GET T1 BACK, CAN'T CALL CO-ROUTINES WITH IN ON THE STACK
IFN FTXMON,<
	MOVE	T1,P3		;PAGE NUMBER
	LSH	T1,P2SLSH	;SECTION NUMBER
	JUMPE	T1,ABZ1		;DON'T BOTHER WITH THIS FOR SECTION 0
	PUSHJ	P,SVPCS##	;SAVE PCS, SET IT TO SECTION CURRENTLY BEING SAVED
	SE1ENT			;ENTER SECTION 1
>
ABZ1:	MOVE	T1,T2		;RESTORE SAVED T1
	MOVE	T2,P3		;FETCH PAGE #
	LSH	T2,P2WLSH	;MAKE INTO AN ADDRESS
	HRLI	T2,-EXESIZ	;FORM AOBJ WORD
ABZ2:	EXCTUU	<SKIPE	(T2)>	;IS THIS LOCATION ZERO?
	AOSA	(P)		;NO, SKIP RETURN
	AOBJN	T2,ABZ2		;LOOP THRU ENTIRE PAGE
	POPJ	P,		;PAGE MUST BE ALL ZERO, NON-SKIP RETURN
;SUBROUTINE TO PUT OUT 1 DIRECTORY ENTRY
;CALL:
;	MOVE	T1,1ST WORD OF DIRECTORY ENTRY
;	MOVE	T2,2ND "	"
;	PUSHJ	P,PTNTRY
;	RETURN HERE
;
;
PTNTRY:	PUSH	P,T2		;SAVE T2 IN CASE PAGE MUST BE WRITTEN OUT
	PUSHJ	P,PTDIRW	;OUTPUT THIS WORD
	POP	P,T1		;RESTORE 2ND WORD TO ENTRY AND
;	PJRST	PTDIRW		; STORE IT




;SUBROUTINE TO STORE A WORD IN THE DIRECTORY
;CALL:
;	MOVE	P1,ADDRESS-TO-PUT-WORD
;	MOVE	T1,WORD-TO-PUT
;	PUSHJ	P,PTDIRW
;	RETURN HERE
;
PTDIRW:	HRR	M,P1		;GET CURRENT DIRECTORY POINTER
	PUSHJ	P,PUTWDU##	;STORE WORD IN USER AREA
	AOS	P1		;BUMP POINTER
	TRNE	P1,EXESIZ-1	;DID WE OVERLAP ONTO A NEW PAGE?
	POPJ	P,		;NO
	SUBI	P1,EXESIZ	;YES, BUMP POINTER BACK TO LAST PAGE
;	PJRST	PUTDIR		;OUTPUT DIRECTORY (MAYBE)
;SUBROUTINE TO OUTPUT THE CURRENT DIRECTORY PAGE
;CALL:
;	HRLI	P2,DIRECTORY-PAGE-COUNTER
;	MOVE	P1,ADDRESS-OF-THIS-PAGE
;	PUSHJ	P,PUTDIR
;	RETURN HERE ALWAYS

PUTDIR:	PUSHJ	P,SAVT##	;AT LEAST T3 AND T4 ARE IMPORTANT
	ADD	P2,[1,,0]	;BUMP # OF DIRECTORY PAGES
	MOVEI	T1,-1(P1)	;GET ADDRESS-1 OF I/O
	MOVEI	T2,SGALEN	;SAVE ADDR OF IOWD
	HRRM	T1,.JDAT+SGALEN	;STORE IN IOWD
	PUSH	P,P1		;SAVE P1 (OUTPUT KILLS IT)
	PUSH	P,P4		;SAVE P4 TOO
	TLNN	P1,SV%DWO	;DO WE REALLY WANT TO WRITE IT OUT?
	OUTPUT	(T2)		;YES, DO SO
	POP	P,P4		;GET P4 BACK
	JRST	P1POPJ##	;RESTORE P1 AND RETURN
;ROUTINE TO REPLACE A REAL PAGE WITH AN ABZ PAGE
;
;CALL:
;	MOVE	T1,PAGE-ADDRESS
;	PUSHJ	P,MAKABZ
;	HERE IF ERROR
;	HERE IF OK

MAKABZ::PUSHJ	P,ZAPPAG	;GET RID OF CURRENT PAGE
	  JFCL			;TOUGH NUGGIES
	HRLI	T1,(PG.DSK)	;MAKE AN ABZ PAGE
	PJRST	CRPAGE		;CREATE THAT


;SUBROUTINE TO DESTROY A PAGE
;CALL:
;	MOVE	T1,PAGE-ADDRESS
;	PUSHJ	P,ZAPPAG
;	HERE IF ERROR
;	HERE IF OK

ZAPPAG::LSH	T1,W2PLSH	;CONVERT TO PAGE #
	TLO	T1,(1B0)	;SET DESTORY BIT
;	PJRST	CRPAGE		;DO THE PAGE. UUO


;ROUTINE TO CREATE A PAGE
;
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,CREPAG
;	  COULDN'T
;	COULD AND DID
;
;T1 IS PRESERVED

CRPAGE::MOVE	T2,T1		;MOVE IT INTO ANOTHER AC
	MOVSI	T1,.PAGCD	;SET UP FUNCTION CODE FOR PAGE.
	PUSHJ	P,PAGUUO	;DO THE PAGE. UUO
	  SKIPA	T2,.JDAT+SGASAV	;ERROR--GET THE ERROR CODE
	JRST	CPOPJ1##	;SUCCESSFUL..GIVE SKIP RETURN
	CAIE	T2,PAGNV%	;DID WE TRY TO CREATE AN ALLOCATED-BUT-ZERO
				; PAGE BUT WE WEREN'T VIRTUAL?
	POPJ	P,		;NO, GIVE FATAL ERROR RETURN
	HRRZS	T1		;YES, SO GET JUST PAGE # AGAIN
				; (WITHOUT "CREATE ON DISK" BIT) AND
	JRST	CRPAGE		; TRY TO CREATE IT AGAIN.
	SUBTTL	SAVGET -- GET AND RUN COMMANDS

;THIS JOB GETS A JOB AREA FROM A RETRIEVABLE DEVICE
;THIS JOB RUNS IN EXEC. MODE AND CALLS IO ROUTINES DIRECTLY
;NO ATTEMPT IS MADE TO RESTORE STATUS OF IO DEVICES, PC, OR AC'S
;JOBPC IS SET TO STARTING ADDRESS OF JOB
;CORE MUST ALREADY HAVE BEEN ASSIGNED AND THE FOLLOWING LOC. SETUP IN
;JOB DATA AREA:
;JOBPDP, JOBREL

GJOB:	JSP	T2,SG1		;SETUP ACS, SETUP LOWER CORE(SGALEN,SGADMP)
	PUSHJ	P,CLRTAB	;CLEAR OUT LAST PROGRAM FROM PDB
	PUSHJ	P,RMVPFH##
	PUSH	P,[0]		;CLEAR PC FLAGS SINCE THEY ARE MEANINGLESS
	MOVEI	T1,JS.RUU	;BIT TO SET
	IORM	T1,JBTSTS##(J)	;SO CAN READ XONLY FILES
	PUSHJ	P,GJOBX		;GET THE JOB
	MOVEI	T1,JS.RUU	;GET THE BIT
	ANDCAM	T1,JBTSTS##(J)	;BACK TO NORMAL PROTECTION CHECKING
	JSP	T1,PHOLD##	;RETURN ONLY IF EVERYTING OK
	ASCIZ	/Job setup/

;THIS JOB GETS A JOB AREA FROM A RETRIEVAL DEVICE AND STARTS IT UP
;JOB HAS JUST A JOB DATA AREA ASSIGNED WHEN CONTROL GETS HERE
;THIS MONITOR JOB GETS A JOB AREA FROM A RETREIVABLE DEVICE
;ASSIGNS CORE AND START

RUNJOB:	JSP	T2,SG1		;SETUP ACS, SETUP LOWER CORE(SGALEN,SGADMP)
	PUSHJ	P,CLRTAB	;CLEAR OUT LAST PROGRAM NAME
	PUSH	P,P1		;PUSH A FAKE WORD SO GETBTB CAN CLEAR LH JOBPD1
	PUSHJ	P,RMVPFH##
	HRLZ	T1,P1		;RH P1 = STARTING ADDRESS INCREMENT
	PUSH	P,T1		;FAKE UP BEGINNING OF RUN UUO PD LIST
	JRST	URUN1		;GO FINISH UP AS IF RUN UUO
UMERGE::PUSHJ	P,GETARG
	PUSHJ	P,UGTSSL	;GET OR FAKE EXTENDED CORE ARG
	SKIPL	T1,.JDAT+SGANEW	;EXTENDED CORE ARG GIVEN?
	JRST	[TDNE T1,[777000,,777000] ;SPECIFYING SECTION NUMBERS IN RANGE IS ILLEGAL
		 JRST IUUAGL##	;ILLEGAL ARGUMENT LIST
		 JRST .+2]	;SGANEW SPECIFIES THE RANGE
	SETZM	.JDAT+SGANEW	;YES, CAN'T ALSO GIVE RANGES (YET)
	PUSHJ	P,MERGE
	JRST	TPOPJ1##
CMERGE::SETZB	P1,P2
	JSP	S,SGSETD
MRGJOB:	JSP	T1,MONSTR##
	PUSHJ	P,RMVPFH##
	PUSHJ	P,SG2A
	PUSH	P,.JDAT+SGANAM
	PUSHJ	P,MERGE
	POP	P,T2
	PUSHJ	P,PRNAME
	JSP	T1,PHOLD##
	ASCIZ	/ merged/
MERGE:	MOVSI	T1,'EXE'
	MOVEM	T1,.JDAT+SGAEXT
	PUSHJ	P,SGOPEN##
	MOVEI	T1,JS.XOR!JS.XO	;XONLY RUN
	AND	T1,JBTSTS##(J)	;ARE ANY SET IN JBTSTS##?
	ANDCAM	T1,JBTSTS##(J)	;WELL, CLEAR THEM IF SO
	PUSH	P,T1		;SAVE THE BITS
	LOOKUP	0,SGANAM	;LOOKUP AND SET JS.XOR IF EXEC ONLY FILE
	  JRST	MERBAD
	MOVEI	T1,JS.XOR!JS.XO
	TDNE	T1,JBTSTS##(J)	;DID XONLY GET SET WITH THIS LOOKUP?
	JRST [	MOVEI T1,PRTERR	;YES, DON'T ALLOW MERGE OF XONLY FILE
	        HRRM T1,.JDAT+SGAEXT ;INDICATE PROTECTION FAILURE
		JRST MERBAD]	;AND MAKE THE MERGE FAIL
	POP	P,T1		;GET BACK PREVIOUS XOR BIT
	IORM	T1,JBTSTS##(J)	;SET XOR IF IT WAS SET BEFORE
	MOVSI	T1,(UP.MPF)	;MERGING PFH?
	TDNE	T1,.USBTS	;ARE WE?
	TLNE	F,SYSDEV	;AND DID THIS PFH COME FROM SYS:?
	TRNA			;KOSHER
	PUSHJ	P,CHKMED##	;MERGING PFH FROM USER AREA, MEDDLE.
	MOVSI	P1,GTLOW+GTMRG
	PUSHJ	P,GETEXE##	;GET FILE
	MOVE	J,.CPJOB##
	PUSHJ	P,VERWAT	;SEE IF WATCHING
	  JRST	MERGE1		;NO -SKIP IT
	PUSHJ	P,PGMMRG	;YES--PRINT FILESPEC
	PUSHJ	P,PRRBKC	;PRINT RIGHT BRACKET
MERGE1:	PJRST	SGREL

MERBAD:	MOVEI	T1,JS.XOR!JS.XO	;XONLY FLAGS
	ANDCAM	T1,JBTSTS##(J)	;CLEAR 'EM
	POP	P,T1		;RESTORE ORIGINAL XONLY FLAGS
	IORM	T1,JBTSTS##(J)	;AND RESTORE THEM TO JBTSTS
	MOVSI	P1,GTMRG	;FLAG MERGE BEING DONE
	MOVEM	P1,.JDAT+SGAEND	;FOR SGRELE
	JRST	NOFILE		;AND RETURN ERROR CODE
	SUBTTL	SAVGET -- RUN UUO

;CALL:	MOVE AC,[XWD N,D]
;	CALL AC,[SIXBIT /RUN/]
;	ERROR RETURN		;UNLESS LH=HALT(PRINT CONSOLE MESS. IF YES)
;	IK OK, TRANSFER TO C(JOBSA)+N FOR NEW PROGRAM
;	USERS ACS CLOBBERED SO CANNOT PASS DATA TO NEW PROGRAM

;WHERE:	D/	DEVICE NAME
;	D+1/	FILE NAME
;	D+2/	FILE EXT OR 0 (LH SIXBIT)
;	D+3/	DATE ETC
;	D+4/	PROJECT,PROGRAMMER NO OR 0(CURRENT UFD OR DTA,MTA)
;	D+5/	HIGHEST LOC DESIRED(OR 0) ANALOGOUS TO RUN COMMAND
;		LH IS IGNORED(RATHER THAN ASSIGNING CORE TO HIGH SEG)


URUN::	MOVSI	T1,JLOG		;IS THIS JOB
	TDNE	T1,JBTSTS##(J)	;LOGGED IN?
	JRST	URUN1A		;YES, OK
	MOVEI	T1,NLIERR	;NO, GIVE HIM
	PUSHJ	P,SGRELE	;AN ERROR
	MOVEI	T1,LOGPLM	;SET UP ERROR MESSAGE
	JRST	PHOLD##		;START TTY + STOP JOB

; HERE WHEN RUN UUO CALLED VIA CONTEXT UUO
URUN1A::
IFN FTFDAE,<
	PUSHJ	P,CALLF
	  PUSHJ	P,SNDFXM
>
	PUSHJ	P,RESET##	;RELEASE DEVICES
				; WARNING! THIS GOES VERY DEEP IN
				; PUSHDOWN. SEE MCO 518
				; (AC M PRESERVED IN RESET)
	PUSHJ	P,SAVE1##	;SAVE P1,P2
	PUSHJ	P,GETWDU##	;RESTORE CONTENTS OF USER'S CALLING AC
	PUSHJ	P,GETARG	;GET 6 ARGS FROM USER AND STORE
				; SAVE STARTING ADDRESS INCREMENT(LH OF T1)
				; AND USER AC NUMBER(IN CASE OF ERROR RETURN)
				; SETUP ACS,F TO U
	SETZM	.USUSN		;ASSUME /USE:0
	PUSHJ	P,UGTSSN	;SET UP FROM USER ARG IF GIVEN
	SETZM	.USUSA		;CLEAR MEMORY OF ENTRY VECTOR
REPEAT 0,<
	MOVSI	T1,400000	;SET-BY-UUO BIT
	ANDCAM	T1,.USUSN	;IS NOT FOR RUN
>
	SKIPGE	.JDAT+SGANEW	;IF EXTENDED ARG GIVEN,
	SETZM	.JDAT+SGANEW	;CAN'T (YET) ALSO GIVE CORE SIZE
	HRRZS	.JDAT+SGANEW 	;CLEAR JUNK(FOR COMPATABILITY)
	MOVEI	P1,0		;CLEAR FLAGS

;HERE ON R OR RUN COMMAND
URUN1:	MOVEI	T1,JS.RUU	;BIT TO SET
	IORM	T1,JBTSTS##(J)	;SO CAN READ XONLY FILES
	PUSHJ	P,GJOBX		;GET BOTH LOW AND HIGH SEGMENTS
				;RETURN FILE NAME IF FROM REAL SYS, ELSE 0 IN T1
	HLRZ	T2,(P)		;GET STARTING ADDRESS INCREMENT
				; SUPPLIED BY USER (0 IF RUN COM.)
	CAILE	T2,1		;IS IT GREATER THAN 1 (REGULAR OR CCL
	JRST	URUN2		; ENTRY POINT?)
				;YES, DO NOT CHECK FOR SPECIAL CUSP FROM SYS
				; SINCE IT WILL NOT BE ENTERED PROPERLY
	MOVSI	T2,(JB.LSY)	;PREPARE TO SET FLAG
	JUMPE	T1,URUN3	;  IF IT CAME FROM SYS:
	IORM	T2,JBTLIM##(J)	;  FOR BATCON
	PUSHJ	P,PRVPG
	  JRST	URUN3
	CAME	T1,LGONAM##	;IS THIS THE LOGOUT CUSP?
	CAMN	T1,LGINAM##	;OR THE LOGOUT CUSP IN DRAG?
	SETZM	.PDCVL##(W)	;YES, MAKE SURE IT HAS ENOUGH CORE TO RUN
	CAMN	T1,LGONAM##	;IS THIS THE LOGOUT CUSP?
	PUSHJ	P,CLRJLG##	;YES, CLEAR JLOG
	MOVSI	T2,JACCT	;SET PRIVILEGED PROG. BIT
	MOVE	T3,JBTPPN##(J)
	CAME	T3,FFAPPN##	;OPR IS NEVER XCT ONLY
	HRRI	T2,JS.XO
				;*** MPB HACQUE
	CAME	T1,QUEUE##	;IS IT QUEUE?
	JRST	URUN4		;NO, SKIP CHECK
	SKIPE	%SIQSR##	;YES, QUASAR RUNNING?
	SETZ	T2,		;YES, NO JACCT
				;*** END MPB HACQUE
URUN4:	IORM	T2,JBTSTS##(J)	;SO NO CONTROL C AND ALL ACCESS TO FILES
	JRST	URUN2A		;GO START IT UP
URUN2:	PUSHJ	P,CHKMED##	;SET MEDDLE IF SHARABLE
	MOVEI	T1,JS.XO	;SEE IF EXECUTE ONLY
	TDNN	T1,JBTSTS##(J)	;  IF SO, CLEAR OFFSET
	JRST	URUN3		;NO, GO RUN IT
	SETZM	(P)		;  TO PROTECT JOB
URUN2A:	SKIPGE	T1,.USUSA	;ALSO CLEAR .USUSA IF SET
	TLNE	T1,370000	; BY A COMMAND RATHER THAN FROM THE EXE FILE
	JRST	URUN3		;NOT SET BY COMMAND
	SETZM	.USUSA		;SET BY COMMAND, ZAP IT
URUN3:	MOVSI	T1,(PD.PGR)	;THE .STPGM RUN IN PROGRESS BIT
	ANDCAM	T1,.PDDFL##(W)	;CLEAR IT, SINCE WE MANAGED TO FINISH THE RUN.
	HLRZ	T2,(P)		;GET STARTING ADDRESS INCREMENT(0 IF RUN COM)
	ADD	T2,.JDAT+JOBSA## ;NOW ADD STARTING ADDRESS
	TLZ	T2,-1		;CLEAR JUNK
	SKIPN	.USUSA		;ENTRY VECTOR OR /START:ADDR SEEN?
	JRST	STRTDD		;NO, JUST CHECK FOR /USE:N
	MOVE	T2,.USUSA	;YES, NEED THIS ADDRESS
	TLZ	T2,400000	;IGNORE COMMAND-MODE BIT
	PUSHJ	P,GSADDR	;DEAL WITH POSSIBLE INDIRECTED START ADDR
	HLRZ	T1,(P)		;GET START ADDRESS OFFSET AGAIN
	ADD	T2,T1		;OFFSET IT
	JRST	STARTU		;AND SKIP /USE:N NONSENSE
;HERE FROM VMSER TO START DDT AFTER GETTING DDT
STRTDD:
STARTD::MOVE	T1,.USUSN	;SECTION NUMBER FROM USE SWITCH
	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	HLL	T2,T1		;SECTION NUMBER,,START ADDRESS WITHIN SECTION
	SKIPN	.USUSA		;WAS THERE AN ENTRY VECTOR?
	JRST	STARTU		;NO, WE HAVE OUR ADDRESS
	LDB	T1,[POINT 6,.USUSA,5] ;MAYBE, GET ITS LENGTH AND FLAG
	CAIN	T1,40		;CHECK HARDER
	JRST	STARTU		;DON'T OFFSET FOR /START:ADDR
	HLL	T2,.USUSA	;USE SECTION OF ENTRY VECTOR
	TLZ	T2,770000	;CLEAR POSSIBLE JUNK
STARTU:	TRNN	T2,777700	;SEE IF LEGITIMATE START ADDRESS
	JRST	URUNSA		;NO--GIVE THE USER AN ERROR
	PUSH	P,[XC.USR+IFN FTKL10,<XC.PUB>]
	PUSH	P,T2
IFN FTMP,<
	PUSHJ	P,DPXST##	;SET UP PROPER RUNNABLE BITS FOR THIS JOB IN JBTSPS
>
	MOVE	T1,[JERR,,JS.RUU] ;BITS TO CLEAR FOR FILSER
	ANDCAM	T1,JBTSTS##(J)	; AND FOR CTRL-C TRAPPING
	JRST	USRXIT##	;AND GO TO RETURN TO USER AS IF FROM UUO

URUNSA:	PUSHJ	P,SGRLE2	;RELEASE DEVICE, GET TTY, TYPE ?
URUNSB::MOVEI	T1,MESNSA	;SETUP MESSAGE
	PJRST	PHOLD##		;TYPE MESSAGE

;SUBROUTINE TO DETERMINE IF THE CUSP BEING RUN IS PRIVILEGED
; ENTER WITH T1=NAME OF THE CUSP BEING RUN
; EXIT CPOPJ IF NOT PRIVILEGED, CPOPJ1 IF IT IS
;PRESERVES T4
PRVPG::	MOVSI	T2,-PRVTBL##	;NO. OF PRIVILEGED CUSPS
	CAME	T1,PRVTAB##(T2)	;MATCH?
	AOBJN	T2,.-1		;NO, KEEP LOOKING, FINISHED?
	JUMPL	T2,CPOPJ1##	;JUMP IF FOUND
	POPJ	P,		;NO MATCH
IFN FTFDAE,<
;SUBROUTINE TO CALL FILE DAEMON ON EXIT
;CALLING SEQUENCE:
;	MOVE	J,JOB NUMBER
;	PUSHJ	P,SNDFXM
;RETURNS CPOPJ ALWAYS

SNDFRM::MOVEI	T1,.FDPOP	;POP CODE
	JRST	SNDFX1		;JOIN COMMON CODE
SNDFPM::SKIPA	T1,[.FDPSH]	;PUSH CODE
SNDFXM:	MOVEI	T1,.FDXIT	;EXIT CODE
SNDFX1:	PUSH	P,T1		;PRESERVE FOR A WHILE
	MOVEI	T2,1+4+MAXLVL##	;SPACE FOR CODE, STR, NAME, EXT, PPN, & SFDS
	PUSHJ	P,GTFWDC##	;GET FROM FUNNY SPACE
	  JRST	TPOPJ##		;CAN'T
	POP	P,0(T1)		;RESTORE CODE INTO MESSAGE
	MOVE	T2,.PDSTR##(W)	;STR
	MOVEM	T2,1(T1)
	MOVE	T2,.PDNAM##(W)	;NAME
	MOVEM	T2,2(T1)
	MOVSI	T2,.PDDIR##(W)	;PPN/PATH
	HRRI	T2,4(T1)
	BLT	T2,MAXLVL##+3(T1)
	MOVE	T4,JBTPPN##(J)	;SENDER'S PPN
	PUSHJ	P,SENDFD##	;SEND TO FILDAE
	  JFCL			;COULDN'T
	POPJ	P,		;RETURN

;SUBROUTINE TO SEE IF FILE DAEMON SHOULD BE CALLED ON EXIT
;CALLING SEQUENCE:
;	MOVE	J,JOB NUMBER
;	PUSHJ	P,CALLF
;RETURNS CPOPJ IF FILE DAEMON SHOULD BE CALLED CPOPJ1 IF NOT
;PRESERVES T3,T4

CALLF:	MOVSI	T1,(JS.CFX)	;GET THE BIT
	TDNN	T1,JBTST2##(J)	;WAS IT SET?
	AOSA	(P)		;NO, SET FOR SKIP RETURN AND SKIP
	ANDCAM	T1,JBTST2##(J)	;YES, CLEAR IT NOW
	POPJ	P,		;RETURN

;SUBROUTINE TO SEE IF AN EXIT MESSAGE SHOULD BE SENT TO THE FILE DAEMON
; IF SO, DELAY THE COMMAND UNTIL THE MESSAGE IS SENT
CHKXTM:	POP	P,T4		;RETURN ADDRESS
	PUSHJ	P,CALLF		;NO, SHOULD FILE DAEMON BE CALLED ?
	  CAIA			;YES
	JRST	(T4)		;NO, JUST DO THE COMMAND
	MOVSI	T1,LDBFDX##	;INDICATE PROCESSING FILDAE EXIT MESSAGE
	SE1XCT	<IORM T1,LDBCOM##(U)> ;SO COMRET WILL LEAVE LDBCMF ALONE JUST
				; CLEARING LDBCMR
	TLO	M,LHRUNF!NOMESS	;SO COMRET WILL LET US RUN (SUPPRESS WATCH STATS)
	PJSP	T2,MSTART##	;START THE MONITOR JOB
	JSP	T1,MONSTR##	;SETUP ACS
	PUSHJ	P,SNDFXM	;SEND THE "EXIT" MESSAGE TO THE FD
	PUSHJ	P,TTYFUW##	;FIND THE TTY
	MOVSI	T1,LDBFDX##	;CLEAR
	SE1XCT	<ANDCAM T1,LDBCOM##(U)> ;SO FORCED COMMANDS IF ANY GET DONE NOW
	PUSHJ	P,CNCMOD##	;TTY TO MONITOR MODE
	PUSHJ	P,COMSET##	;MAKE THE ORIGINAL COMMAND VISABLE
	PJRST	ESTOP##		;STOP THE JOB

> ;END IFN FTFDAE
	SUBTTL	SAVGET -- GETSEG## UUO

;UUO TO GET JUST HIGH SEG AND RETURN TO USER
;CALL IS THE SAME AS FOR RUN UUO EXCEPT THAT OK RETURN IS SKIP RETURN
;IF ERROR RETURN HAS HALT IN LH, STANDARD CONSOLE MESSAGE IS PRINTED AND JOB STOPPED

UGTSEG::MOVE	T2,JBTSTS##(J)	;GET JOB STATUS
	TLNE	T2,JACCT	;IS JACCT ON
	TLO	P1,PHONLY	;YES, GETSEG MUST BE PHYSICAL ONLY
	JRST	UGETHI##	;IN SEGCON

UGTERR::MOVEI	T1,ILUERR	;ILLEGAL UUO ERROR CODE
	PUSHJ	P,SGRELE	;SEE IF USER WANTS ERROR
	JRST	UUOERR##	;NO, PRINT ILLEGAL UUO
	SUBTTL	SAVGET -- COMMON CODE

;ROUTINE TO SETUP ACS, RESET IO, AND SETUP LOWER CORE LOCATIONS
;FOR SAVE AND GET(SGALEN SET TO IOWD OR PP IF DTA OR DSK)
;SGADMP SET TO IOWD FOR THIS SIZE CORE
;CALL:	JSP T2,SG1
;	ALWAYS RETURN HERE, UNLESS DEVICE NOT FOUND
;	F SETUP TO DEVICE DATA BLOCK(BUT NOT INITED)
;	SO THAT INIT NOT NECESSARY IF SEG ALREADY KNOWN(NO DTA QUEUEING)
;	DEVICE CHARACTERISTICS WORD(DEVMOD) RETURNED IN AC T2
;	IF DISK SYSTEM


SG1:	JSP	T1,MONSTR##	;SETUP R,P,R,J=JOB NUMBER
				; PUT T2 ON END OF PD LIST(EXEC MODE PC,
				; SO ERROR MESSAGES WILL ALWAYS PRINT(SEE SGRELE)
	PUSHJ	P,RESET##	;RELEASE ALL DEVICES
	MOVE	P1,.JDAT+SGAMOD	;RESTORE PHYSICAL/LOGICAL BIT
SG2A:	MOVEI	T1,DR		;DUMP MODE 16(DUMP BY RECORDS
				; IN CASE THIS IS MAGTAPE)
	PUSHJ	P,CHKEXE	;SAVING AN EXE FILE?
	  MOVEI	T1,D		;YES, ALWAYS USE REGULAR DUMP MODE (WRITE PAGES
				; TO MAGTAPE)
	TLNE	P1,PHONLY	;SEE IF PHYSICAL DEVICE
	TLO	T1,(1B0)	;YES -- SET FOR PHYSICAL OPEN
	MOVEM	T1,.JDAT+SGAMOD	;STORE FOR OPEN UUO
	SETZM	.JDAT+SGAREN+1	;FOR DELETE
	SETZM	.JDAT+SGAREN+2	;FOR DELETE
	HLLZS	.JDAT+JOBCOR##	;0 THIRD ARG IN JOBDATA AREA(SO CHKARG WILL
				; WORK ON FIRST CALL(SAVE AND GET)
	SETZM	.JDAT+SGAHED	;CLEAR BUFFER HEADER ARG. FOR OPEN UUO
	MOVE	T1,.JDAT+SGADEV	;PHYSICAL OR LOGICAL DEVICE NAME
	PUSHJ	P,DEVSRG##	;FIND DEVICE AND SETUP F TO DDB
				; DO NOT INIT DEV SINCE IO MAY NOT BE NECESSARY
				; DO NOT WANT TO WAIT IN DTA SYSTEM
				; TAPE QUEUE IN 10/40 SYS
	  JRST	SGERRA		;NOT AVAILABLE
				;DEVICE INITED(OR FOUND)
	SETZM	.JDAT+SGAEND	;0 END OF DUMPE MODE COMMAND LIST
;COMMON EXIT FROM SAVHGH AND GETHGH ROUTINES(HIGH SEG SAVE AND GET)
;SO THAT SGA... LOCATIONS ARE RESTORED TO ORIGINAL VALUES FOR LOW SEG

SG3::	SKIPN	T1,.JDAT+SGAEXT	;DID USER SPECIFY AN EXTENSION ?
	MOVSI	T1,'SAV'	;NO, USE .SAV
	MOVEM	T1,.JDAT+SGAEXT	;AND STORE FOR LOOK UP OR ENTER

	MOVE	T1,.JDAT+JOBFF## ;FIRST FREE LOC IN JOB(SET FROM LH OF
				; JOBSA WHICH IS SET BY LOADER
	MOVEI	T1,-1(T1)	;MAKE LAST LOC TO SAVE OR GET(MAKE 0=777777)
	SKIPN	USRDDT##	;USER DDT IN USE(IF YES, SAVE ALL OF CORE
				; SO HIS SYMBOLS WILL BE INCLUDED
	PUSHJ	P,IADRCK##	;NO, ADDRESS TOO SMALL OR TOO LARGE?
	  JFCL
	  MOVE	T1,.JDAT+.JBREL## ;YES, DUMP ALL OF CORE RATHER THAN GIVE
				; ADDRESS CHECK MESSAGE-HIGHEST REL.ADR.
	MOVNS	T1		;-HIGHEST ADR TO SAVE OR GET
	ADDI	T1,JOBSVM##	;LOWER CORE NOT DUMPED
	HRLI	T1,JOBSVM##	;IE FIRST LOC-1 TO BE DUMPED
	MOVSM	T1,.JDAT+SGADMP	;STORE IOWD WORD OF THIS SIZE CORE

;ROUTINE TO SET-UP E+3 FOR ENTER
;ENTER:	MOVS T1,DTA IOWD.
;USES T2

SG4::	PUSHJ	P,SETASJ	;SET EXEC MODE UUO FLAG

	MOVE	T2,DEVMOD(F)	;RETURN DEVICE CHARACTERISTICS(IF DISK SYS)
	TLNE	T2,DVDSK	;IS THIS DEVICE A DISK?
	MOVS	T1,.JDAT+SGAPPN	;YES, MAKE SURE FOURTH WORD IS PROJ,R NO.

	MOVSM	T1,.JDAT+SGALEN	;NO, MAKE SURE FOURTH WORD IS IOWD FOR DECTAPE
				; SINCE DECTAPE USES RH TO COMPUTE LENGTH IN K
				; FOR BOTH SAVE AND GET
	POPJ	P,
;ERROR ON INIT OR DEVICE SEARCH


SGERRU:	TLO	P1,GTSAV	;FLAG TO KEEP HISEG
	PUSHJ	P,SGRELE	;RETURN TO USER IF UUO (WITH ERROR IN T1)
	MOVE	T1,.JDAT+SGADEV	;GET DEVICE AGAIN
	PUSHJ	P,DEVSRG##	;SEE IF EXISTS
	 JFCL			;IGNORE NON-SKIP (SHOULD GIVE ERROR RET)
SGERRA::JUMPE	F,SGERR1	;WAS DEVICE FOUND, BUT JUST UNAVAILABLE?
	MOVEM	F,(P)		;YES, SAVE DDB ADDRESS FOR MESSAGE(ERNAM)
	MOVEI	T1,DNAERR	;ERROR CODE IN CASE RUN UUO(DEVICE NOT AVAILABLE)
	PUSHJ	P,SGRELE	;RETURN TO USER IF RUN UUO
				; OR FIND TTY AND PRINT ?CRLF
	PUSHJ	P,ERNAM##	;PRINT DEVICE NAME USING (P)
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/ not available/

SGERR1:	MOVEI	T1,NSDERR	;ERROR CODE IN CASE RUN UUO(NO SUCH DEVICE)
	PUSHJ	P,SGRELE	;RETURN TO USER IF RUN UUO
				; OR FIND TTY AND PRINT ?CRLF
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/No such device/
	SUBTTL	SAVGET -- GET FILE FROM DEVICE (R,RUN,GET,GETSEG)

;ROUTINE TO GET FILE FROM DEVICE(LOW AND/OR HIGH)
;CALL:	ACS R,P,F SETUP
;	MOVE J,JOB NUMBER
;	MOVE T2,DEVMOD(F)	;DEVICE CHAR.
;	PUSHJ P,GETJB
;	RETURN ONLY IF ALL OK
;	VALUE IN T1 = FILE NAME IF FROM REAL SYS, ELSO0., J PRESERVED
;


GJOBX:	MOVE	T1,J
	PUSHJ	P,FPDBT1##	;FIND PDB
	  CAIA			;OH WELL
	SETZM	.PDVRT##(T1)
	PUSHJ	P,SETASA	;SET EXEC MODE UUO FLAG
	MOVSI	T1,(JB.LSY)	;CLEAR GOTTEN FROM SYS: FLAG
	ANDCAM	T1,JBTLIM##(J)	; ..

	MOVEI	T1,JS.XOR	;CLEAR XO-STATUS
	HRLI	T1,JACCT	; AND JACCT
	ANDCAM	T1,JBTSTS##(J)	;  ..
	MOVSI	T1,(UP.CXO)
	ANDCAM	T1,.USBTS	;AND XO CORE IMAGE
IFN FTFDAE,<
	MOVSI	T1,(JS.FXO)
	ANDCAM	T1,JBTST2##(J)
>
	PUSHJ	P,GETHGH##	;SEE IF HIGH SEG ALREADY EXISTS AND BEING SHARED
				; IF NOT, TRY TO LOOKUP AND READ IN HIGH FILE
				; IF .SHR DOESN'T EXIST, TRY .HGH,
				; IF NEITHER-SKIP RETURN
				; T2=DEVMOD(F) IF DISK(DEV CHAR.)
	  JRST	GJOB1		;HIGH SEG NOW IN CORE AND NO LOW FILE NEEDED

	SKIPA	T1,.JDAT+SGAPPN ;LOW FILE NEEDED
				; EITHER BECAUSE NO HIGH SEG OR HIGH SEG ALSO
				; NEEDS LOW FILE
	JRST	GJOB5B		;RETURN HERE IF ENTIRE FILE
				; (HIGH AND LOW SEGS) HAVE BEEN
				; INPUT AND ARE READY TO GO.
	CAIE	T1,JOBUAL##	;DON'T WIPE OUT THE PPN RETURNED BY PATH
	MOVEM	T1,.JDAT+JOBUAL##+2 ;IN CASE MUST GET GET
	PUSHJ	P,LUKFIL	;LOOKUP LOW FILE
	  JRST	NOFILE		;GO PRINT FILE.EXT NOT FOUND
	HLRE	T2,.JDAT+SGALEN	;-NO. OF WORDS IN FILE
	JUMPE	T2,GETERR	;IF 0, GIVE ERROR MESSAGE
	JUMPL	T2,GJOB5	;GO IF NUMBER OF WORDS
	LSH	T2,BLKLSH##	;NO. OF BLOCKS, CONVERT TO WORDS
	MOVNS	T2		;MINUS NO. OF WORDS
	HRLM	T2,.JDAT+SGALEN
GJOB5:	PUSHJ	P,CKIOWD	;CHECK USER'S SUPPLIED CORE ARG TO MAKE SURE NOT
				; TOO SMALL, RETURN LARGER OF FILE SIZE OR CORE ARG
	PUSH	P,T1		;SAVE CORE REQUIRED
	PUSHJ	P,MINGET	;REDUCE TO ONE PAGE IF VIRTUAL
	POP	P,T1		;RESTORE CORE ARG

	PUSHJ	P,GETCOR	;OK, TRY TO GET CORE
	MOVE	T2,DEVMOD(F)	;DEVICE CHARACTERISTICS
	MOVNS	T1
	ADDI	T1,JOBSVM##	;-WORD COUNT FOR ALL USERS CORE
	TLNE	T2,DVMTA	;MAG TAPE?
	HRLM	T1,.JDAT+SGALEN	;YES, USE USER-SPECIFIED CORE ARGUMENT
	HRRZS	.JDAT+JOBPD1##	;TURN OFF USER MODE PC FLAG IN CASE THIS
				; IS A RUN UUO,SO ERRORS WILL NOT TRY TO RETURN TO USER
	PUSHJ	P,SGDO		;READ IN FILE INTO LOW SEGMENT
	  INPUT	0,SGALEN	;EXECUTED FROM SGDO
	HLRZ	T1,.JDAT+JOBSVM##-3	;GET 1ST WORD OF FILE
	CAIN	T1,SV.DIR	;IS THIS AN EXE FILE?
	JRST	EXESAV##	;YES, GIVE ERROR MESSAGE
	MOVE	T1,.JDAT+JOBS41## ;RESTORE USER UUO JSR LOC
	MOVEM	T1,.JDAT+JOB41## ;SAVED BY SAVE
GJOB5B:	PUSH	P,F		;SAVE SYSDEV BIT
	SKIPN	.USREL		;NO LOWFIN IF NON-CONTIGUOUS
	PUSHJ	P,LOWFIN	;MAKE SURE GOT ALL REQUESTED CORE
	POP	P,F		;NOW RESTORE F
	JRST	GJOB2		;GO RELEASE DEVICES AND RETURN
;HERE IF HIGH SEG SAYS NO LOW SEG(AND USER DID NOT TYPE AN EXT)
GJOB1:  SETZM	.JDAT+JOBBPT
	PUSH	P,F		;SAVE F SINCE IF NO LOOKUP WAS DONE IT IS
				; NOT STORED IN USRJDA
	PUSHJ	P,MINGET
	PUSH	P,.CPREL##	;MAX WHICH MUST BE CLEARED
	PUSHJ	P,LOWFIN	;INCREASE OR DECREASE SIZE
	POP	P,T1		;RESTORE PREVIOUS SIZE
	POP	P,F		;RESTORE F
	CAMLE	T1,.CPREL##	;SMALLER YET?
	MOVE	T1,.CPREL##	;
	MOVEI	T2,MJOBDA##(T1)	;NO. OF WORDS TO CLEAR(-JOB DATA AREA)
	ADDM	T2,CLRWRD##	;INCREASE TOT. NO. WORDS CLEARED BY SYSTEM

	MOVEI	T2,JOBDA##+1	;FIRST ABSOLUTE LOC+1 TO CLEAR(JOB DATA
				; AREA+2)=BLT DESTINATION ADR.
	EXCTUU	<SETZM -1(T2)>	;CLEAR THE FIRST WORD
	HRLI	T2,-1(T2)	;SET UP FIRST BLT SOURCE ADR(JOB DATA
				; AREA+1)
	EXCTUU	<BLT T2,(T1)>	;CLEAR FROM 140 TO TOP OF LOW SEG
GJOB2:	HRRZ	T1,JBTSGN##(J)	;GET ADDRESS OF SEGMENT DATA BLOCK IF ANY
	SKIPE	T1		;ONLY IF THERE IS ONE (FIRST IS NEWEST)
	PUSHJ	P,HSVAD##	;GET HIGHEST RELATIVE ADDRESS IN THE HI SEG
	HRRM	T1,.JDAT+JOBHRL##	;SET HIGHEST RELATIVE LOC FOR USER

	MOVE	T1,.JDAT+SGANAM	;FILE NAME OF FILE OR SEGMENT
	PUSH	P,T1		;SAVE POSSIBLE RETURN AS VALUE
	TLNN	F,SYSDEV	;IS DEVICE THE REAL SYS(AS OPPOSED TO LOGICAL)
	SETZM	(P)		;NO, SET FILE NAME TO 0 FOR RETURN
	MOVEM	T1,JBTPRG##(J)	;LOW SEG NAME FOR SYSTAT
	PUSHJ	P,EXONLY	;IF EXECUTE ONLY, PROTECT THE CORE IMAGE
	MOVSI	T1,(UP.CXO)
	TDNE	T2,JBTSTS##(J)	;IF XO HERE,
	IORM	T1,.USBTS	; MARK THE ENTIRE CORE IMAGE AS XO
	TDNE	T2,JBTSTS##(J)	;IS IT EXECUTE ONLY?
	PUSHJ	P,MAPHGH##	;YES, MAKE SURE THE MAP REFLECTS THAT
	PUSHJ	P,FNDPDS##	;FIND THE PDB OR STOP
	MOVE	T1,JBTNAM##(J)	;STORE THE NAME OF THE PROGRAM
	MOVEM	T1,.PDNAM##(W)	; SINCE IT CAN BE CHANGED WITHOUT
				; CHANGING THE CONTENTS OF THE CORE IMAGE
	SETZM	.JDAT+JOBUAL##+3 ;ZERO FIRST SFD WORD (IN CASE OF JUNK FROM LOWFIN)
	HRRZ	T1,F		;IF (F)
	CAIE	T1,DSKDDB##	;=DSKDDB, NO LOOKUP DONE
	JRST	GJOB6		;LOOKUP WAS DONE
	MOVE	J,.CPJOB##	;JOB NUMBER
	HRRZ	T1,JBTSGN##(J)	;HIGH SEGMENT BLOCK
	MOVE	T1,.HBSGN(T1)	;SEGMENT WORD (NEWEST SEGMENT)
	MOVE	T2,JBTPPN##(T1)	;DIRECTORY AND
	MOVE	T1,JBTDEV##(T1)	;STR WHERE PROGRAM CAME FROM
	TLNE	T2,-1		;A PATH TO THE HIGH SEGMENT?
	JRST	GJOB6A		;NO, STORE A ZERO AS FIRST SFD
	MOVSI	T3,1(T2)	;WHERE SFD'S ARE STORED
	MOVE	T2,(T2)		; AND THE PPN
	JRST	GJOB7		;STORE THEM
GJOB6:	CAIN	T1,SWPDDB##	;VIRTUAL PROGRAM?
	MOVE	F,USRJDA	;YES, INSURE F IS SETUP
	MOVEI	T1,JOBUAL##
	MOVEM	T1,.JDAT+SGAPPN
	PUSHJ	P,PTHFIL##	;GET PATH BACK (CLOBBERED BUT BY VIRCHK)
	PUSHJ	P,NAMSTR##	;STR
	  SKIPA	T1,DEVNAM(F)	;NOT A DSK, DEVICE NAME
	SKIPA	T2,DEVPPN(F)	;YES, GET DIRECTORY
	MOVEI	T2,0		;NO, NO DIRECTORY
GJOB6A:	MOVSI	T3,.JDAT+JOBUAL##+3 ;WHERE THE SFD'S ARE STORED
GJOB7:	MOVEM	T1,.PDSTR##(W)	;STORE STR OR DEVICE NAME
	MOVEM	T2,.PDDIR##(W)	;AND DIRECTORY
	HRRI	T3,.PDSFD##(W)	;WHERE TO STORE PATH
	BLT	T3,.PDSFD##+MAXLVL##-1(W) ;STORE PATH
	PUSHJ	P,VERWAT	;SEE IF VERSION WATCHING
	  JRST	GJOB8		;NO
	MOVSI	T2,'S: '	;YES -- PRESET SYS FLAG
	SKIPE	(P)		;SEE IF FROM SYS:
	PUSHJ	P,PRNAME	;YES -- TYPE IT
	PUSH	P,P2		;NOT A VERSION COMMAND
	SETO	P2,		;CALL PGMFIL FOR FIRST SEGMENT
	PUSHJ	P,VERBTH	;PRINT BOTH SEGMENTS
	POP	P,P2
	PUSHJ	P,PRRBKC	;PRINT RIGHT BRACKET <CRLF>
GJOB8:	PUSHJ	P,SGREL		;RELEASE DDB
	MOVSI	T1,.JDAT
	EXCTXU	<BLT T1,17>	;SETUP USER'S ACS FROM SG AREA
	JRST	TPOPJ##		;RETURN WITH T1 = FILE NAME ONLY
				; IF FROM REAL SYS,ELSE 0
;ROUTINE TO LOOKUP A LOW-SEGMENT FILE
;
;CALL:
;	PUSHJ	P,LUKFIL
;	  HERE IF NOT FOUND
;	HERE IF FOUND
;
LUKFIL::MOVE	T1,DEVMOD(F)	;DEVICE CHARACTERISTICS
	SKIPN	T2,JBTSGN##(J)	;MIGHT THERE HAVE BEEN A HIGH SEGMENT?
	TLNN	T1,DVDSK	;YES, AND DID IT COME FROM THE DISK
	JRST	LUKFI3		;NO, JUST DO THE LOOKUP
	MOVE	T1,.JDAT+SGANAM	;GET NAME HIGH SEG SHOULD HAVE COME FROM
	SKIPLE	T2,.HBSGN(T2)	;REALLY WAS A HIGH SEG?
	CAME	T1,JBTPRG##(T2)	;SAME NAME?
	JRST	LUKFI3		;NO
	SKIPN	T1,DEVPPN(F)	;PPN FROM WHENCE THE HIGH SEGMENT CAME
	MOVE	T1,JBTPPN##(T2)	;NO LOOKUP WAS DONE FOR THE HI SEG
	TLNE	T1,-1		;PATH TO THE HI SEG STORED?
	JRST	[SKIPE DEVPPN(F) ;NO, USE PPN OR PATH FROM HI SEG LOOKUP
		 JRST LUKFI1
		 JRST LUKFI2]
	HRLI	T1,.JDAT+JOBUAL##+2 ;YES, USE PATH TO THE HI SEG
	MOVSS	T1		; TO LOOKUP THE LOW SEG
	BLT	T1,.JDAT+JOBUAL##+MAXLVL##+2
LUKFI1:	MOVEI	T1,JOBUAL##	;ADDRESS OF THE PATH
LUKFI2:	MOVEM	T1,.JDAT+SGALEN ;STORE IT FOR THE LOOKUP
LUKFI3:	LOOKUP	0,SGANAM	;LOOKUP LOW SEG FILE(EXT=SAV.DMP OR LOW(IF HIGH SEG
				; REQUIRES LOW SEG AND USER DID NOT TYPE EXT)
				; MODE=SAVMOD SO DECTAPE SERVICE WILL RETURN
				; IOWD IN E+3(TEMPORARY)
	  POPJ	P,		;NOT FOUND
	JRST	CPOPJ1##	;FOUND, SKIP RETURN


;ROUTINE TO CHECK VIRTUAL LIMITS ON A GET.
;
;CALL:
;	MOVE	T1,WORDS-NEEDED
;	PUSHJ	P,CKVLIM
;	  HERE IF NO ROOM
;	HERE IF OK
;
CKVLIM:	LSH	T1,W2PLSH	;PAGE #
	HLRZ	T2,.PDCVL##(W)	;GET VIRTUAL LIMIT
	MOVSI	T3,(UP.GET)	;CHECK GET BIT
	TDNN	T3,.USBTS
	CAIL	T1,(T2)		;WANT MORE THAN THAT?
	POPJ	P,		;YES
	JRST	CPOPJ1##	;NO
;VERWAT -- START VERSION WATCH IF ON
;RETURN CPOPJ IF NOT OR DETACHED
;SKIP IF SO WITH U SETUP AND LEFT BRACKET TYPED

VERWAT::MOVSI	T1,JW.WVR	;SEE IF WATCHING
	TDNN	T1,JBTWCH##(J)	;  ..
	POPJ	P,		;NO
	PUSHJ	P,TTYFND##	;GET LDB
	JUMPE	U,CPOPJ##	;NONE
	PUSHJ	P,PRLBK		;PRINT LEFT BRACKET
	JRST	CPOPJ1##	;SKIP RETURN


;SUBROUTINE TO DETERMINE IF JOB OR SEGMENT WAS READ FROM AN EXECUTE
; ONLY FILE. IF SO PROTECT THE CORE IMAGE BY SETTING THE EXECUTE
; ONLY BIT. IF NOT CLEAR EXECUTE ONLY.

EXONLY::MOVE	J,.CPJOB##	;GET THIS JOB NUMBER
	MOVE	T1,[JACCT,,JS.XOR]
	MOVEI	T2,JS.XO
	MOVE	T3,[IORM T2,JBTSTS##(J)]
IFN FTFDAE,<
	MOVSI	T4,(JS.FXO)
	TDNE	T4,JBTST2##(J)
	JRST	EXONL1
>
	MOVE	T4,JBTPPN##(J)
	CAME	T4,FFAPPN##	;DONT SET EXEC.ONLY FOR [1,2]
	TDNN	T1,JBTSTS##(J)	;EXEC.ONLY FILE?
	HRLI	T3,(ANDCAM T2,(J))
EXONL1:	MOVEI	T1,JS.RUU
	TDNN	T1,JBTSTS##(J)
	CAME	T3,[ANDCAM T2,JBTSTS##(J)]
	XCT	T3		;SET OR CLEAR EXECUTE ONLY CORE IMAGE
	POPJ	P,		;RETURN
;SUBROUTINE TO REDUCE LOW SEGMENT SIZE TO ONE PAGE
; IF THE PROGRAM IS VIRTUAL. THIS IS NECESSARY
; (ONLY IN THE CASE OF A RUN UUO - RUN COMMAND
; CALLED GETMIN) TO MAKE SURE THAT THE MAP
; CONTAINS NO DISK ADDRESSES AND TO REMOVE PFH
; IF IT IS CONTAINED IN THE CORE IMAGE

MINGET:	SKIPN	.USVRT		;VIRTUAL?
	SKIPE	.USMEM		;OR NON-CONTIGUOUS
	SKIPA	T1,MINCOR	;YES
IFN FTPEEKSPY,<
	PJRST	CLRSPG##	;ZAP SPY PAGES
>
IFE FTPEEKSPY,<
	POPJ	P,		;RETURN
>
GET1PG::
IFN FTMP,<
	PUSHJ	P,[PUSHJ P,GGVMM## ;NEED MM
		   PJRST KILNZS##]
>
IFE FTMP,<
	PUSHJ	P,KILNZS##
>
	  JFCL			;ALWAYS SKIPS AT UUO LEVEL
	HRRZM	T1,.JDAT+SGACOR	;ONE PAGE
	CALLI	SGACOR,200011	;REDUCE LOW SEG IMAGE TO PAGE ZERO
	  JFCL			;CAN'T FAIL
	PUSHJ	P,ZAPEPL##	;CLEAR EXTENDED PDL
	HRRZ	T1,.JDAT+JOBPD1## ;ADDRESS OF UUO
	CAML	T1,.CPREL##	;IN CASE THE USER DID THE UUO IN PAGE 0
	HRRZS	.JDAT+JOBPD1##	;CLEAR USER MODE SINCE CAN'T RETURN TO USER
IFN FTPEEKSPY,<
	PJRST	CLRSPG##	;ZAP SPY PAGES IF ANY
>
IFE FTPEEKSPY,<
	POPJ	P,		;AND RETURN
>
;SUBROUTINE TO CLEAR VARIOUS ITEMS WHEN THE CONTENTS OF A CORE
; IMAGE IS CHANGED OR RENAMED (SAVE)
CLRTAB:	PUSHJ	P,CLRBTS	;CLEAR BITS IN JOB TABLES
	PUSHJ	P,FNDPDS##	;POINT TO PDB
	SETZM	.PDNAM##(W)	;ZERO NAME
	SETZM	.PDSTR##(W)	; AND STR
	SETZM	.PDDIR##(W)	; AND PPN
MINCOR:	POPJ	P,PG.BDY	;RETURN

CLRBTS:	MOVE	T1,[JACCT,,JS.XO!JS.XOR] ;CLEAR EXECUTE ONLY SO
	ANDCAM	T1,JBTSTS##(J)	; USER WILL NOT BE RESTRICTED
	MOVSI	T1,(UP.CXO)
	ANDCAM	T1,.USBTS	;CLEAR XO CORE IMAGE
	MOVSI	T1,(JB.LSY)	;NO LONGER A PROGRAM
	ANDCAM	T1,JBTLIM##(J)	; FROM SYS
	POPJ	P,		;RETURN
	SUBTTL	SAVGET -- IO ROUTINES

;ROUTINE TO RELEASE DEVICE AND FIND TTY

SGREL::	SKIPN	F,USRJDA##	;HAS CHANNEL BEEN RELEASED ALREADY?
	JRST	SGREL2		;YES, FIND TTY AND WAIT FOR OUTPUT TO FINISH
	PUSH	P,S		;NO,
	MOVE	T1,DEVMOD(F)
	TLNE	T1,DVDSK	;DISK?
	CLOSE	0,CLSNMB	;YES, KEEP THE ACCESS TABLES
	TLNE	T1,DVMTA	;MAGTAPE?
	TLNN	F,INPB		;YES, WAS AN INPUT DONE?
	JRST	SGREL1		;NO
	SETZM	DEVBUF(F)	;INSURE NO PAGE FAULTS
	CLOSE	0,CLSOUT	;YES, CLOSE MTA INPUT
	STATO	0,IOTEND+IODEND	;AT END OF TAPE?
	MTAPE	0,16		;NO SKIP TO EOF
SGREL1:	RELEASE	0,		;NO RELEASE DEVICE
	POP	P,S
SGREL2:	PUSHJ	P,TTYFNU##	;FIND TTY FOR CURRENT USER SET J TO CURRENT JOB
	MOVSI	T1,(UP.CTX)	;RUN UUO ERROR BIT FOR CTXSER
	ANDCAM	T1,.USBTS	;CLEAR IT
	PJRST	CLRASA		;CLEAR EXEC MODE UUO FLAG
;SUBROUTINE TO ADJUST LOW SEG CORE ACCORDING TO ARG
; ON GET OR PREVIOUS SAVE
;CALL:	PUSHJ P,LOWFIN
;	ALWAYS RETURN

LOWFIN:	HRRZ	T1,.JDAT+JOBCOR## ;CORE ARG FROM PREVIOUS SAVE(THIS MONITOR
				; ALWAYS STORES SOMETHING)
	SKIPN	T1		;IS THIS AN OLD FORMAT FILE WITH NO CORE ARG TO SAVE?
	MOVE	T1,.CPREL##	;YES, USE ASSIGNMENT MADE WHEN LOW FILE READ IN
	PUSHJ	P,CKSARG	;RETURN ONLY IF USER'S SUPPLIED ARG IS 0 OR NOT
				; SMALLER THAN SAVE CORE ARG, RETURN LARGER
	HRRZM	T1,.JDAT+SGACOR	;STORE CORE ARGUMENT
	PUSH	P,T1		;SAVE IN CASE OF AN ERROR
	PUSHJ	P,GETSSN##	;SECTION 0 OR SECTION 1 PROGRAM?
	  JUMPN	T1,LOWFI1	;NO, DO THINGS DIFFERENTLY
	MOVE	T1,(P)		;CORE ARG
	CAMG	T1,.CPREL##	;IF GREATER, EXE FILE DICTATES
	JRST	TPOPJ##		;ALL DONE
	MOVE	T1,.JDAT+SGANAM	;NAME OF PROGRAM
	TLNE	F,SYSDEV	;IS PROGRAM FROM SYS  ?
	PUSHJ	P,PRVPG		;YES, SHOULD IT BE NON-VIRTUAL?
	  TDZA	T1,T1		;NO
	MOVEI	T1,UPHNLY	;YES, LIGHT PHYSICAL-ONLY BIT
	CALLI	SGACOR,11(T1)	;TRY TO GET THE CORE (VIRTUAL OR PHYSICAL)
	  JRST NOROOM		;NOT AVAILABLE
	MOVE	T1,.CPREL##	;HIGHEST LOC ASSIGNED TO LOW SEG
	HRRM	T1,.JDAT+JOBCOR## ;SET INITIAL CORE ASSIGNMENT IN JOB DATA AREA FOR
				; USER TO USE TO RESET CORE TO INITIAL SETTING WHEN
				; PROGRAM IS RESTARTED
REPEAT 0,<
	SKIPG	.USUSN		;MAP SECTION 0 AND 1 TOGETHER?
>
	JRST	TPOPJ##		;NO, ALL DONE
REPEAT 0,<
	MOVSI	T1,.PAGCS	;SET TO MAP SECTION 0 AND 1 TOGETHER
	MOVE	T2,[PG.SLO+1]	;ARGUMENT TO PAGE UUO
	PUSHJ	P,PAGUUO	;DO IT
	  JRST	OVRERR##	;MUST OVERLAP
	JRST	TPOPJ##		;OK, RETURN
>
LOWFI1:	POP	P,T2		;HIGHEST ADDRESS WITHIN THE SECTION TO ALLOCATE
	CAIN	T2,PG.BDY	;NOT CHANGING ANYTHING?
	POPJ	P,		;YES, JUST EXIT
	PUSHJ	P,SVPCS##	;SAVE PCS, SET IT TO (.USUSN)
	PUSHJ	P,CLRASA	;ALCORE WORKS WITH JS.ASA OFF
	MOVEI	T1,PAGSIZ	;START ALLOCATING AT PAGE 1
	PUSHJ	P,ALCORE##	;ALLOCATE THE NEEDED NZS CORE
	PJRST	SETASA		;TURN JS.ASA BACK ON AND RETURN
;ROUTINE TO EXECUTE DUMP MODE COMMAND LIST SETUP IN SGALEN(R)
;AND CHECK FOR ERRORS. USED ONLY TO READ LOW FILE.
;CALL:	PUSHJ P,SGDO
;	INPUT 0,SGALEN OR OUTPUT 0,SGALEN
;	OK RETURN(NO ERRORS)
;SGDOA CALLED FROM SAVE, IT HAS ALREADY SET LH OF USRHCU=-2
;TO INDICATE CORE IS COMPRESSED


SGDO:	HRROS	USRHCU##	;SET LH OF USRCHU-1 AS A FLAG TO INDICATE SAVE GET
				; LOW FILE IO IN PROGRESS, SO MONITOR WILL
				; NOT STORE HIGH SEG PROTECTION IN JOBHRL WHICH
				; HAS IOWD FOR ZERO COMPRESSION
SGDOA:	SETZM	.JDAT+SGAEND
	XCT	@(P)		;EXECUTE INPUT OR OUTPUT UUO
	MOVE	J,.CPJOB##	;READ INTO PROTECTED PART OF JOB DATA AREA
	PUSHJ	P,EXPAND	;EXPAND CORE IMAGE
	  JRST	ADRERR##	;ADDRESS CHECK, PRINT MESSAGE AND STOP JOB
	MOVE	T1,.JDAT+JOBDDT##	;COPY DDT STARTING ADR
	MOVEM	T1,USRDDT##	;INTO MONITOR PROTECTED AREA(IN CASE THIS IS GET)
	SETZM	USRHCU##	;FLAG THAT SAVE-GET IO FINISHED AND CORE EXPANDED
	AOS	(P)		;SKIP OVER UUO IN CALLING SEQUENCE

;ROUTINE TO CHECK FOR IO ERRORS(CALLED FROM SEGCON)
;CALL:	MOVE F,DEVICE DATA BLOCK ADDRESS
;	PUSHJ P,SGIOCK
;	RETURN ONLY IF NO ERRORS


SGIOCK::MOVE	S,DEVIOS(F)	;IO STATUS WORD FOR THIS DEVICE
	TRNN	S,IOBKTL!IODTER!IODERR!IOIMPM	;ANY ERRORS ON SAVE-GET DEVICE?
	POPJ	P,		;NO, GIVE OK RETURN
	MOVSI	T1,USRMOD	;USER-MODE BIT
	TDNN	T1,.JDAT+JOBPD1## ;FROM A UUO?
	 JRST	SGIO2		;NO, SKIP THIS
	POP	P,.PDTMC##(W)	;RESTORE VM LOCS
	POP	P,.PDTMI##(W)
SGIO2::	MOVEI	T1,TRNERR	;YES, ERROR CODE IN CASE THIS IS RUN UUO
				; (TRANSMISSION ERROR)
	PUSHJ	P,SGRELE	;RELEASE DEVICE AND ERROR RETURN TO USER IF RUN UUO
				; OR FIND TTY AND PRINT ?CRLF
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/Transmission error/
	SUBTTL	SAVGET -- EXPAND COMPRESSED FILES

;ROUTINE TO EXPAND CORE AFTER A SAVE(LOW SEG ONLY)
;CALL:	MOVE F,DEVICE ADR.
;	MOVE R,JOBADR.
;	MOVE J,JOB NUMBER
;	PUSHJ P,EXPAND
;	ERROR RETURN, ADR. CHECK, OR NEED CORE BUT NOT CURRENT USER(COMMAND
;			DECODER EXPANDING AFTER USER HAS REDUCE CORE)
;	OK RETURN, CORE EXPANDED
;CALLED FROM SAVE AND COMMAND DECODER
;START,CSTART,DDT,REENTER,SAVE,SSAVE COMMANDS IF CORE STILL COMPRESSED

EXPAND:	HLRE	P3,.JDAT+SGALEN	;-LENGTH OF FILE
	MOVNS	P3		;+LENGTH OF FILE
	ADDI	P3,JOBSVM##	;ADD FIRST LOC-1 TO FORM HIGHEST LEGAL ADR.

	SKIPL	T1,.JDAT+JOBSV##	;IF FIRST LOC IS POSITIVE
	JRST	SGDO1		;OLD FORMAT, SO DONT EXPAND
	AOJE	T1,SGDO2	;DO NOT EXPAND IF NOT COMPRESSED
	PUSHJ	P,SAVE1##	;SAVE P1
	HRRZ	T1,.JDAT+JOBSV##	;LOOK AT 1ST WORD OF FILE
	CAILE	T1,JOBDDT##	;IS IT BELOW JOBJDA?
	JRST	EXPND1		;NO. NEW COMPRESSED FORMAT
	CAIE	T1,JOBSAV##	;IS JOBDDT THE DATA WORD?
	JRST	EXPND1		;NO. EXPAND
	SKIPN	.JDAT+JOBSV3##	;IS THE SAVE FILE FROM CONVERT?
				; CONVERT DOES NOT ZERO COMPESS
				; IT JUST WRITES ENTIRE FILE WITH 1 IOWD IN FRONT
	SOJA	P3,SGDO1	;YES, GO BLT DATA DOWN AS IF OLD DISK SAVE FILE
				; (NON-COMPRESSED)
	HRROI	T1,JOBSD1##	;YES. CHANGE TO IOWD 1,JOBSDD
	EXCH	T1,.JDAT+JOBSV##	;ZAP. THE IOWD IS FIXED
	HLRES	T1		;WORD COUNT OF IOWD
	AOJE	T1,EXPND1	;JUST 1 DATA WORD - THROUGH
	MOVSI	T1,1(T1)	;MAKE IOWD N-2,JOBSAV
	JUMPE	T1,EXPZ
	HRRI	T1,JOBSAV##	;SO NEXT DATA WDS WILL BE SKIPPED
	MOVEI	T2,.JDAT+JOBSV##
	MOVEM	T1,2(T2)	;STORE IN COMPRESSED DATA
	JRST	EXPND1
EXPZ:	MOVSI	T1,-2
	HLLM	T1,.JDAT+JOBSV##
;COME HERE TO DO THE ACTUAL EXPANSION OF A FILE
EXPND1:	MOVEI	T1,JOBSV##	;IT WAS READ INTO JOBSV
	EXCTUX	<MOVE T2,@T1>	;GET FIRST IOWD
EXPLP1:	HRRZ	P1,T2		;ADDRESS OF IOWD
	CAIGE	P1,JOBSD1##	;LEGAL?
	AOJA	P1,TOOLOW	;NO. DELETE DATA WHICH IS TOO LOW
	HLRE	P1,T2		;YES. GET WORDCOUNT
	MOVNS	P1		;+N
	HRLM	P1,T2		;CONVERT IOWD TO +N IN LH
	ADDI	T1,1(P1)	;ADDRESS OF NEXT IOWD
	CAMLE	T1,P3		;IN BOUNDS?
	JRST	GETERR		;NO. COMPLAIN
	ADDI	T2,(P1)		;YES. CHANGE RH OF IOWD
	EXCTUU	<EXCH T2,@T1>	;MAKE IT XWD +N,A+N-1 AFTER DATA BLOCK
	JUMPL	T2,EXPLP1	;CONTINUE IF NEXT THING IS AN IOWD
	HLRZ	P1,T2		;GET LH OF SUSPECTED STARTING
	CAIE	P1,(JRST)	;IS IT JRST?
	CAIN	P1,(HALT)	;OR HALT?
	SKIPA			;YES,
	JRST	EXPLP1		;NO, LOOP BACK AND ASSUME JUST
				; A COUNT OF GREATER THAN 128K
				; GET ADDRESS CHECK MESSAGE IF FILE
				; WAS NOT THAT BIG
	PUSH	P,T1		;SAVE DATA LOCATION
	EXCTUX	<HRRZ T1,@T1>	;TOP REAL LOCATION NEEDED

	TRO	T1,PG.BDY	;MAKE IT NK-1
	HLRZ	T2,R		;PRESENT SIZ OF LOW SEG
	CAMG	T1,T2		;IS THERE ENOUGH?
	JRST	EXPCOR		;YES,
	CAME	J,.CPJOB##		;NO, IS TIS THE CURENT JOB?
	JRST	SGDOER		;NO, GIVE ERROR RETURN, MUST BE COMMAND DECODER
				; DOING EXPAND AFTER USER HAS REDUECED CORE
	PUSH	P,.JDAT+JOBUAL##+6 ;DEFEND AGAINST PAGE UUO
	PUSHJ	P,GETCOR	;YES. GET IT
	POP	P,.JDAT+JOBUAL##+6
EXPCOR:	POP	P,T2

	MOVEI	P1,@T2		;TOP  DATA LOC
	HRLI	P1,1(P1)	;SET TO ZERO TO TOP OF CORE
	HRRI	P1,2(P1)
	EXCTXU	<SETZM -1(P1)>	;ZERO FIRST LOC
	EXCTUU	<BLT P1,@T1>	;CLEAR CORE
	MOVEI	T4,JOBSV##	;SET UP END-OF-LOOP WORD
	HLL	T4,T2		;R IN LH(T4) IF KA10
	HRROI	T1,@T2		;FROM DATA POINTER
EXPLP2:	EXCTUX	<HRRZ	P1,(T1)>	;TO DATA POINTER
	MOVSS	R		;CHECK ADR OF, IOWD
	CAILE	P1,(R)		;IN BOUNDS?
	JRST	GETER0		;NO-ERROR
	MOVSS	R		;YES. OK
	CAIGE	P1,(T1)		;MAKE SURE WE DO NOT GO BACKWARDS
	JRST	GETERR		; CAN HAPPEN IF TOO MANY IOWDS W/O 0'S.
	EXCTUX	<HLRZ	P2,(T1)>	;WORD COUNT
	SUBI	T2,1(P2)	;POINT T2 TO PREVIOUS IOWD
	JUMPE	P2,EXPLP5	;FORGET IT IF ZERO WORD-COUNT
	EXCTXU	<SETZM (T1)>
	SOSA	T1		;POINT TO DATA
EXPLP3:	SOS	P1
	CAIGE	P1,JOBSDD##
	JRST	EXPLP5
	JRST	EXPLP6
EXPLP5:	SOSA	T1
EXPLP6:	EXCTUU	<POP T1,(P1)>	;MOVE A DATA WORD
	EXCTUU	<SETZM 1(T1)>	;ZERO WHERE IT CAME FROM
	SOJG	P2,EXPLP3	;LOOP IF MORE DATA
	CAMLE	T2,T4		;THROUGH?
	JRST	EXPLP2		;NO. DO NEXT BLOCK
	EXCH	P2,.JDAT+JOBSDD##	;YES. ZERO JOBSDD
	MOVEM	P2,.JDAT+JOBDDT##	;SET USER DDT STR ADR
	JRST	SGDO2		;AND SETUP USRDDT IN MONITOR PROTECTED
				; FROM THIS USER
;THIS ROUTINE WILL DELETE ALL DATA FROM A COMPRESSED FILE
;WHICH IS BELOW JOBSDD (PROBABLY WRITTEN BY TENDUMP)

TOOLOW:	EXCTUX	<HLRE P2,@T1>	;WORDCOUNT OF OFFENDING IOWD
	JUMPGE	P2,GETERR	;PROHIBIT AGAINST UNFORMATTED SAVE FILES
	SUB	P1,P2		;ADDRESS+N
	HLRZ	T2,R		;PROTECTION
	CAILE	P1,(T2)		;ADR TOO HIGH?
	JRST	GETERR		;YES, COMPLAIN
	CAIG	P1,JOBSDD##	;IS ANY DATA IN IT LEGAL?
	AOJA	T1,NXIOWD	;NO, TEST NEXT IOWD
	SUBI	P1,JOBSDD##	;YES, NUMBER OF WORDS TO KEEP
	MOVNS	P2		;TOTAL NUMBER OF WORDS
	SUBB	P2,P1		;NUMBER OF WORDS TO DROP
	HRLS	P2		;INTO BOTH HALVES
	EXCTUX	<ADD P2,@T1>	;NEW IOWD FOR ONLY GOOD DATA
	ADDI	T1,(P1)		;POINT T1 TO LAST BAD DATA LOC
	EXCTXU	<MOVEM P2,@T1>	;STORE UPDATED IOWD OVER IT
	JRST	IOWBLT		;GO BLT OVER BAD DATA
NXIOWD:	SUB	T1,P2		;POINT T1 TO NEXT IOWD
	CAMLE	T1,P3		;PROTECTION
	JRST	SGDOR2
	EXCTUX	<HRRZ P1,@T1>	;GET ADDRESS
	CAIGE	P1,JOBSD1##	;LEGAL?
	AOJA	P1,TOOLOW	;NO, AT LEAST PART OF THE DATA IS LOW
IOWBLT:	EXCTUX	<MOVSI T2,@T1>	;YES. KEEP THE ENTIRE IOWD DATA
	HRRI	T2,JOBSV##	;T2 IS A BLT POINTER
	SUBI	T1,JOBSV##	;RH OF T1 IS AMOUNT BEING DELETED
	SUBI	P3,(T1)		;P3 POINTS TO TOP OF DATA READ IN-(N)
	EXCTUU	<BLT T2,@P3>	;MOVE ONLY GOOD DATA DOWN
	JRST	EXPND1		;GO EXPAND THE GOOD DATA
SGDO1:	MOVEI	T1,JOBDDT##	;MOVE EVERYTHING DOWN )MUST BE NON-COMPRESSED DSK FILE
	HRLI	T1,JOBSVD##(T1)	;OR CONVERT SAVE FILE
	SKIPGE	.JDAT+JOBSV##	;IS THIS CONVERT FILE(FIRST WORD IS IOWD)?
	HRLI	T1,JOBSDP##(T1)	;YES, ALSO SKIP OVER IOWD
	SUBI	P3,JOBSVD##
	EXCTUU	<BLT T1,(P3)>
SGDO2:	AOSA	(P)		;SET FOR OK RETURN
SGDOER:	POP	P,T1
SGDOR2:	SETZM	USRHCU##	;CLEAR LH AND SET HIGHEST USER CHAN. IN
				; USE TO 0(WHERE IT SHOULD BE ANYWAY)
	POPJ	P,		;ERROR RETURN OR OK RETURN
;ROUTINE TO CHECK USER SUPPLIED CORE ARG AND CHECK TO SEE IF 0
;OR GREATER THAN OR EQUAL TO IOWD USED TO SAVE OR GET FILE
;CALL:	HLRE T2,-NO. OF WORDS IN FILE
;	PUSHJ P,CKIOWD
;	RETURN WITH LARGER OF 2 POSITIVE NOS. IN T1(1777 ORED IN)
;	DO NOT RETURN IF CORE ARG SUPLLIED BY USER IS TOO SMALL
;CALLED FROM SAVE AND GET


CKIOWD:	MOVEI	T1,JOBSVM##	;FIRST LOC-1 READ OR WRITTEN IN USER AREA
	HRRM	T1,.JDAT+SGALEN	;RESTORE RH TO JOBSAV AFTER LOOKUP
	SUB	T1,T2		;HIGHEST LOC=FIRST LOC-1+LENGTH OF FILE
				; FALL INTO CHSARG

;ROUTINE TO CHECK USER SUPPLIED CORE ARG AND CHECK IF 0
;OR GREATER THAN OR EQUAL TO CORE ARG FOR PREVIOUS SAVE
;CALL:	HRRZ T1,JOBCOR(R)	;WRITTEN WHEN FILE SAVED
;	PUSHJ P,CKSARG
;	RETURN WITH LARGER OF 2 IN AC T1, ONLY IF USER ARG NOT TOO SMALL
;CALLED ONLY FROM GET AFTER JOB DATA AREA LOADED FROM FILE(JOBCOR) OR HIGH SEG


CKSARG:	IORI	T1,PG.BDY	;MAKE SURE 1K-1
	CAMLE	T1,.JDAT+SGANEW	;IS USER SUPPLIED ARG BIGGER?
	JRST	CKSAR1		;NO
	MOVE	T1,.JDAT+SGANEW	;YES, RETURN IT
	POPJ	P,
CKSAR1:	PUSH	P,T1		;IN CASE OF ERROR
	SKIPN	.JDAT+SGANEW	;DID USER SUPPLY ONE?
	PJRST	TPOPJ##		;NO, RETURN LARGER OF TWO

;ROUTINE TO PRINT #K OF CORE NEEDED
;CALL:	PUSH	P,HIGHEST REL. USER ADR.
;	JRST	NROOM
;	NEVER RETURN

NOROOM::MOVEI	T1,NECERR	;NOT ENOUGH CORE ERROR CODE
NROOM::	PUSHJ	P,SGRELE	;RELEASE DEVICE AND ERROR RETURN TO USER IF RUN UUO
				; OR FIND TTY AND PRINT ?CRLF
	PUSHJ	P,EXONLY	;SET JS.XO AS APPROPRIATE
	HRRZ	T1,(P)		;GET AMOUNT OF CORE REQUESTED
	LSH	T1,W2PLSH	;CONVERT TO NO. OF 1K BLOCKS-1
	PUSHJ	P,DECP1		;ADD 1 TO T1 AND PRINT DECIMAL
	PUSHJ	P,PRPORK	;PRINT "P" OR "K"
	JSP	T1,PHOLD##	;START TTY ADN STOP JOB
	ASCIZ	/ of core needed/
	SUBTTL	SAVGET -- SUBROUTINES


;ROUTINE TO ASSIGN CORE FOR LOW  AND HIGH SEG
;CALL:	MOVE R,LOW SEG RELOCATION
;	HRR T1,HIGHEST LOC DESIRED
;	PUSHJ P,GETCOR
;	RETURN ONLY IF ASSIGNED


GETCOR::PUSHJ	P,SAVE1##	;SAVE P1 FOR EXE FILES
	HRRZM	T1,.JDAT+SGACOR	;SOTRE CORE ARG FOR CORE UUO IN USER AC
	PUSH	P,T1		;SAVE IN CASE OF ERROR
	MOVE	J,.CPJOB##
REPEAT 0,<
	MOVE	T4,T1
	SKIPN	T2,.USREL
	HLRZ	T2,R
	IORI	T4,PG.BDY
	SUB	T4,T2
	LSH	T4,W2PLSH
	PUSHJ	P,GSIZT##
	  JRST	GETGET
	  SKIPA	T2,.USBTS
	JRST	GETCR1
	TLNN	T2,(UP.GET)
	JRST	GETGET
>

GETCR1:	CALLI	SGACOR,200011	;DO PHYSICAL-ONLY CORE UUO
	  JRST	NOROOM		;NOT AVAILABLE, PRINT ERROR AND AMOUNT TRYING FOR
	JRST	TPOPJ##		;OK, REMOVE T1 FROM PD LIST AND RETURN
SETASJ::PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;J=JOB NUMBER OF CURRENT JOB
	PUSHJ	P,SETASA	;MAKE AC REFERENCES BE TO THE SHADOW AREA
	JRST	JPOPJ##		;RESTORE J AND RETURN

SETASA::PUSH	P,T1		;SAVE T1
IFN	FTXMON,<
	MOVEI	T1,0		;SET PCS TO 0 SO REFERENCES TO JOBUAL WORK
	PUSHJ	P,STPCS##	;CORRECTLY (DON'T IME)
>
	MOVEI	T1,JS.ASA	;LITE THE BIT WHICH INDICATES REFERENCES TO
	IORM	T1,JBTSTS##(J)	; LOCATIONS 0-17 IN THE USER'S AREA ARE TO SHADOW ACS
	JRST	TPOPJ##		;RETURN

CLRASA::PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,JS.ASA	;CLEAR THE BIT WHICH INDICATES REFERENCES TO
	ANDCAM	P1,JBTSTS##(J)	; USER LOCATIONS 0-17 ARE TO SHADOW ACS
	POPJ	P,		;AND RETURN
;ROUTINE TO PRINT NOT A SAVE FILE IF WRONG FORMAT FILE DETECTED


GETER0:	MOVSS	R		;"SAVE" FILE ISN'T RIGHT
GETERR::MOVEI	T1,NSFERR	;ERROR CODE IN CASE THIS IS RUN UUO(NOT SAVE FILE)
	PUSHJ	P,SGRELE	;RELEASE DEVICE AND ERROR RETURN TO USER IF RUN UUO
				; OR FIND TTY AND PRINT ?CRLF
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/Not a save file/

;ROUTINE TO PRINT FILE NOT FOUND OR NEEDS 2 RELOC REG


NOFILE::MOVEI	T1,FNFERR	;ERROR CODE IN CASE THIS IS RUN UUO(FILE NOT FOUND)
				; CHANGE ERROR CODE TO DISK ERROR CODE IF DEV IS DSK
	PUSHJ	P,SGRELL	;RETURN DISK LOOKUP OR ENTER ERROR CODE IF DSK
				; RELEASE DEVICE AND ERROR RETURN TO USER IF HE WANTED
				; OR FIND TTY AND PRINT ?CRLF
	HRRZ	T1,.JDAT+SGAEXT	;SEE WHICH ERROR
	JUMPN	T1,LOOKFL	;NOT NOT FOUND
	SKIPN	T2,.JDAT+SGANAM	;PRINT FILE NAME
	JRST	NOLKFL		;NO FILE PROVIDED
	PUSHJ	P,PRNAME
	PUSHJ	P,PRPER		;PRINT PERIOD
	HLLZ	T2,.JDAT+SGAEXT	;PRINT EXTENSION
	PUSHJ	P,PRNAME
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/ not found/

NOLKFL:	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/No file specified /

LOOKFL:	PJSP	T1,LKENFL	;LOOKUP ERROR - PRINT MESSAGE
	ASCIZ	/Lookup error /


LKENFL:	PUSHJ	P,CONMES	;ISSUE MESSAGE
	HRRZ	T1,.JDAT+SGAEXT	;GET ERROR
	SKIPE	T1		;SEE IF = 0
	PUSHJ	P,PRTDI8	;NO - PRINT IN OCTAL
	PJRST	HOLD##		;STOP JOB
;ROUTINE TO RELEASE DEVICE ON AN ERROR AND CHECK TO SEE
;IF THIS IS A MONITOR COMMAND OR USER UUO
;IF USER UUO, GIVE ERROR RETURN TO USER UNLESS THERE IS A HALT
;IN LH OF EROR RETURN WORD, IN WHICH CASE FIND TTY, PRINT ?CRLF
;AND RETURN TO CALLER SO CAN ADD MORE INFO TO ERROR MESSAGE AND STOP JOB
;CALL:	MOVEI T1,ERROR CODE(DEFINED IN S.MAC)
;	PUSHJ P,SGRELE
;DO NOT RETURN TO CALLER IF USER WANTS ERROR RETURN ON RUN AND GETSEG UUOS


SGRELL:				;LOOKUP OR ENTER FAILURE
	MOVE	T2,DEVMOD(F)	;IS THIS DEVICE A DISK?
	TLNE	T2,DVDSK
	HRRZ	T1,.JDAT+SGAEXT	;YES, RETURN DISK SERVICE ERROR CODE

SGRELE::PUSH	P,T1		;SAVE T1
	MOVE	J,.CPJOB##	;GET JOB #
	CAMN	J,CAUSER##	;DO WE OWN THE CA?
	PUSHJ	P,CAFREE##	;YES, FREE IT
	MOVE	P1,.JDAT+SGAEND	;GET FLAGS
	TLNN	P1,GTMRG!GTSAV!GTSGO ;DON'T RELEASE HI-SEG IF MERGING OR SEGOPING
	SKIPN	.JDAT+JOBPD1##	;SKIP IF SAVE IS IN PROGRESS
				; IF IT IS NOT WE WANT TO KILL ANY
				; HISEG WE MAY HAVE GOTTEN.  THIS
				; PREVENTS US FROM LEAVING AN EXECUTE
				; ONLY HISEG ADDRESSABLE WHEN A RUN UUO
				; FAILS.
	JRST	SEGRLX		;MERGING OR SAVING, KEEP HIGH SEG
	HRRZ	T1,JBTSGN##(J)	;RELEASE SEGMENT JUST GOTTEN
IFE FTMP,<
	PUSHJ	P,KILHSH##	;KILL THE HISEG IF NOT SAVE
>
IFN FTMP,<
	PUSHJ	P,[PUSHJ P,GGVMM## ;MUST OWN THE MM RESOURCE
		   PJRST KILHSH##] ;REMOVE THE HI SEG
>
SEGRLX:	MOVEI	T2,JS.RUU	;CLEAR RUN FLAG
	ANDCAM	T2,JBTSTS##(J)	;  SO FILSER STOPS ITS CHECKS
	MOVSI	T1,(UP.CTX)	;IF RUN UUO FAILED WHILE BEING
	TDNE	T1,.USBTS	; CALLED BY THE CONTEXT UUO, THEN
	JRST	SGRLE1		;  THE UUO PC ISN'T IN ORIGINAL USER CORE
	MOVE	T2,.JDAT+JOBPD1## ;GET PC FLAGS OFF OF PD LIST
	TLNN	T2,USRMOD	;IS IT IN USER MODE(IE USER UUO)?
	JRST	SGRLE1		;NO, MUST BE MONITOR COMMAND OR CALLER OVERLAYED
				; RELEASE DEVICE, FIND TTY, AND RETURN TO CALLER
	MOVE	M,.JDAT+JOBPD1##+1 ;ADDRESS OF RETURN AFTER RUN OR GETSEG UUO
	TRNN	M,777760	;FROM AC'S?
	JRST	SGRLE1		;YES - TYPE MESSAGE
	PUSHJ	P,GETWRD##	;GET ERROR RETURN WORD FROM RUN OR GETSEG UUO
	  MOVSI	T1,(HALT)
	LSH	T1,-^D23	;ISOLATE OP CODE
	CAIN	T1,<HALT>B58	;IS IT HALT?
	JRST	SGRLE1		;YES, RELEASE DEVICE,FIND TTY, AND RETURN TO CALLER
SGRLE0:	SKIPE	USRJDA##	;DO NOT RELEASE CHANNEL 0 IF NOT INITED YET
				; UUO HANDLER DOES NOT ALLOW THIS FROM EXEC MODE
	RELEAS	0,		;RELEASE DEVICE(IF INITED)
	PUSHJ	P,CLRASA	;CLEAR EXEC MODE UUO FLAG
	HRR	M,.JDAT+JOBPD3##+1 ;NO, AC NUMBER OF RUN OR GETSEG UUO
	POP	P,T1		;RESTORE ERROR CODE
	TLNE	P1,GTSGO	;SEGOP?
	JRST	[MOVSI T2,.USUAC;YES, DO THAT DIFFERENTLY
		 EXCTXU <BLT T2,17> ;RESTORE THE USER'S ACS
		 MOVE T2,.JDAT+JOBPD3##+2 ;STORED USRJDA FOR USER CHANNEL 0
		 MOVEM T2,USRJDA## ;RESTORE THAT AS WELL
		 JRST .+1]	;STORE ERROR CODE AND RETURN TO THE USER
	PUSHJ	P,PUTWDU##	;STORE ERROR NUMBER IN USER AC
	JRST	ERRGOU##	;PUT RETURN ON END OF PDLIST
				; AND RETURN TO USER TO HANDLE ERROR

SGRLE1:	POP	P,T1		;REMOVE ERROR CODE FROM LIST
	MOVSI	T2,(UP.CTX)	;IF CALLED BY THE CONTEXT UUO
	TDNE	T2,.USBTS	; THEN NO MORE CAN BE DONE HERE AND
	PJRST	CTXRUE##	;  CTXSER MUST FINISH ERROR RECOVERY
	MOVSI	T1,.JDAT	;SAVUAC WILL STORE OVER
	EXCTXU	<BLT T1,17>	; SHADOW ACS, SO SET USERS ACS
SGRLE2:	PUSHJ	P,SGREL		;RELEASE DEVICE AND FIND TTY
	PUSHJ	P,TTYFUW##	;MAKE SURE ATTACHED FOR ERROR MESSAGES
	PUSHJ	P,TSETBI##	;CLEAR TYPE AHEAD
	SETZM	JBTPRG##(J)	;CLEAR NAME SINCE LOST
	MOVSI	T1,(PD.PGR)	;WAS THIS A .STPGM RUN?
	TDNN	T1,.PDDFL##(W)
	JRST	PPQCRL		;NO, BYPASS CODE
	ANDCAM	T1,.PDDFL##(W)	;CLEAR BIT (JUST PARANOIA)
	MOVE	T1,LGINAM##	;GET NAME OF LOGOUT CUSP
	MOVEM	T1,.PDPGM##(W)	;AND STORE AS CUSP-TO-RUN.
	PUSHJ	P,INLMES	;AND TELL THE USER WHAT HAPPENED TO HIM
	ASCIZ	\
%.STPGM run failed, logging job out.
\
PPQCRL::PJSP	T1,CONMES	;PRINT ? ON SAME LINE AS ERROR MSG,
				;FOR BATCH AND SCRIPT, RETURN TO CALLER
				; WHO WILL PRINT REST OF ERROR MESSAGE AND STOP JOB
	ASCIZ	/
?/
	$LIT
COMEND:	END			;END OF COMCON