Google
 

Trailing-Edge - PDP-10 Archives - dec-10-omona-u-mc9 - 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 - V1156
SUBTTL /PFC/RCC/DAL   05 APR 77
	SEARCH	F,S
	$RELOC
	$HIGH
;***COPYRIGHT 1973,1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VCOMCN,1156
				;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

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

;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

;CONTINUED ON NEXT PAGE
;   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, DETACH AND EXCHANGE 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
;   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::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
		POPJ	P,]	;RETURN
IFN FTMS,<
	MOVEM	J,COMJOB##	;TO AVOID JOBSTS UUO RACE
>
IFN FTKI10!FTKL10,<
	PUSHJ	P,COMUBR##	;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
IFN FTCAFE&FT2741,<
	MOVEI	T3,377
	MOVEI	T1,LDR2741##	; TRUE MAGIC OF THE
	TDNE	T1,LDBDCH##(U)	; 2741 COMMUNICATIONS
	PUSHJ	P,COMTYO##	; TERMINAL
>	;END FTCAFE&FT2741
	MOVEI	P3,DISP		;SET P3=LOC OF DISPATCH TABLE
	MOVE	P4,[XWD -DISPL,COMTAB];SET P4=-LENGTH,TABLE LOC
	LDB	T1,LDPCMX##	;GET FORCED COMMAND INDEX, IF ANY
	HRLM	T1,(P)		;SAVE IT FOR COMPARISON
	MOVSI	T2,LDBCMF##	;IS COMMAND FORCED?
	TDNE	T2,0(U)		; ..
	SKIPA	T2,TTFCOM##(T1)	;YES. GET SIXBIT NAME OF COMMAND
COM1:	PUSHJ	P,CTEXT		;SCAN COMMAND NAME, RETURN IT IN T2
	CAIN	T3,"C"-100	;BREAK ON CONTROL-C?
	MOVE	T2,HALTXT	;YES--TURN COMMAND INTO HALT
;HERE WITH T2=COMMAND, P3=DISPATCH TABLE, P4=AOBJN TABLE
COM1A:	MOVE	T1,P4		;COPY POINTER
	PUSHJ	P,FNDNAM	;LOOK IT UP
	  SETOM	T1		;ERROR--SET FLAG
	ADDI	T1,(P4)		;COMPUTE MATCH LOCATION
	MOVE	P2,(T1)		;SAVE NAME OF COMMAND
IFN FTCCL,<
	TLZ	T1,-1		;CLEAR JUNK
	CAILE	T1,COMPIL	;SEE IF COMPIL
	CAIL	T1,LASCCL	;  ..
	JRST	.+2		;NO
	MOVEI	T1,COMPIL	;YES
>
	SUBI	T1,(P4)		;INDEX OF TABLE
	ADDI	P3,(T1)		;POINT P3 TO DISPATCH ENTRY
	SKIPGE	T1		;SEE IF ERROR
	MOVEI	P3,COMERD	;YES--SET DISPATCH
	MOVE	M,(P3)		;GET DISPATCH TABLE ENTRY
	MOVE	P4,JBTSTS##(J)	;JOB STATUS WORD FOR THIS JOB
IFN FTCAFE&FT2741!FTNET,<
	TLNE	P4,JLOG		; WHILE NOT LOGGED IN?
	JRST	NT2741		;NO--LEAVE ALONE
	JUMPGE	T1,NT2741	;JUMP IF NOT COMMAND ERROR
	CAMN	T2,[SIXBIT .YQAOS.]
	HRRI	M,SET987
	CAMN	T2,[SIXBIT .VI.];DID HE TYPE LOGIN WITH WRONG BALL?
	HRRI	M,SET988	;YES--SET TTY ELEMENT 988
NT2741:> ;END FTCAFE&FT2741!FTNET
IFN FTEL&FTSWAP,<
	TRNE	P4,JS.DEP	;IS JOB BEING STOPPED ON ERROR SO DAEMON CAN LOG?
	JRST	CHKDLY		;YES, DELAY COMMAND UNTIL DAEMON IS FINISHED LOGGING
>
IFN FTLOGIN,<
	TLNN P4,JLOG		;IS JOB LOGGED IN?
	TLNE M,NOLOGIN		;NO, CAN COMMAND PROCEED WITH NO LOGIN?
	JRST CHKNO		;YES
LOGPLS:	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:	MOVE	P4,JBTSTS##(J)	;SCAN FOR FREE JOB NO.
	TLNN	P4,JNA+CMWB+JRQ	;THIS NUMBER ASSIGNED?
	JRST	NEWJOB		;NO, SO USE THIS NUMBER
	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,(U)
	JRST	NEWJER		;NO, OKAY TO COMPLAIN
	MOVEI	T1,LDRREM##	;IF FROM NETWORK, PROBABLY INITIA OR
	TDNE	T1,LDBDCH##(U)	; .NETLD SO DELAY IT
	JRST	CHKDLY
>
NEWJER:	JSP	T1,COMER	;YES, NONE LEFT, PRINT "JOB CAPACITY EXCEEDED"
	ASCIZ	/Job capacity exceeded
/

				; 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	NEWJER		;IF CAN'T, NO DDB'S. SAY JOB CAP EXC
IFE FTPDBS,< ;IF WE HAVE PDB'S IN CORE THIS IS A LITTLE DIFFERENT
	PUSHJ	P,CREPDB##	;CREATE A PDB FOR THIS JOB
	  JRST	[PUSHJ	P,TTYKIL  ;KILL TTY DDB OBTAINED ABOVE
		 JRST	NEWJER]	;CAN'T GET A PDB, SAY JOB CAP EXC
	PUSHJ	P,CLRJBT##	;GO CLEAR ALL THE JOB TABLES AND PDB
> ;END IN CORE CASE
IFN FTPDBS,< ;IF PDB'S SWAP 
	PUSHJ	P,CLRJBT##	;GO CLEAR ALL THE JOB TABLES
	PUSHJ	P,CREPDB##	;CREATE A PDB FOR THIS JOB
	  JRST	[PUSHJ	P,TTYKIL  ;KILL TTY DDB OBTAINED ABOVE
		 JRST	NEWJER]	;CAN'T GET A PDB, SAY JOB CAP EXC
	JUMPE	W,PDBDLY	;IF PDB WAS CREATED ON THE DISK, WE MUST
				; DELAY THIS COMMAND UNTIL IT IS IN CORE.
> ;END FTPDBS
	MOVE	T2,DATE##
	MOVEM	T2,JBTJLT##(J)
IFN FTTLIM,<
	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:>
IFN FTWATCH,<
	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:	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:	IFN	FTTLIM,<
	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
IFN FTSWAP,<
	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		;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
CHKCO1:	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
/


IFN FTPDBS,< ;CAN ONLY HAPPEN IF PDB'S SWAP
;HERE IF PDB IS NOT IN CORE YET

PDBDLY:	HRRI	M,DLYCM		;SET UP TO DELAY COMMAND
	JRST	COMDIS		;GO OFF AND WAIT
>;END IFN FTPDBS
CHKXPN:	TLNN	M,INCORE	;DOES THIS COMMAND NEED CORE TO BE EXPANDED?
	JRST	COMGO		;NO
	HLRE	S,JOBHCU##(R)	;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
IFN FTJCON,<
	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
	PUSHJ	P,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)
IFN FTSWAP,<
	JRST	CHKDLY		;DELAY COMMAND BECAUSE COMMAND DECODER ACS ARE
				; ALL GONE, NEXT TIME JOBHCU WILL BE 0
>

IFE FTSWAP,<
	HRRI	M,DLYCM1	;DELAY COMMAND TILL NEXT CLOCK TICK
	JRST	COMDIS
>

COMER:	MOVSI	M,NOINCK
	HRRI	M,ERRMES	;CALL ERROR MESSAGE ROUTINE

COMGO:	TLNN	P4,CMWB		; WAS JOB IN COMM WAIT
	TLZ	M,CMWRQ		;NO, CLEAR REQUEU BIT IN DISP. FLAGS
	MOVSI	S,CMWB		;CLEAR CMWB
	ANDCAM	S,JBTSTS##(J)


COMDIS:	MOVEI	S,0		;CLEAR S FOR SETTING DISPATCH ADDRESSES
	TLO	M,FLMCOM!FLMCLV	;SET COMMAND AT COMMAND LEVEL FLAGS
	PUSHJ	P,(M)		;DISPATCH TO COMMAND
	  JFCL			;IGNORE ERROR RETURN
	SUBTTL	COMMAND RETURN AND CLEANUP

;RETURN FROM COMMAND SETUP ROUTINE

COMRET:	HLRZ	T1,(P)		;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)
IFN FTACCT,<
	MOVSI	T1,1		;UPDATE NUMBER COMMANDS TYPED
	ADDM	T1,DDBBCC##(F)
>
	TLNN	M,ERRFLG	;ERROR?
	JRST	COMRT1		;NO, PROCEDE
	SETZM	J		;YES, CLEAR J
	TLZ	M,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)
IFE FTLOGIN, <
	PUSHJ	P,INLMES	;AND PRINT "JOB "
	ASCIZ	/Job /
	MOVE	T1,J		;PRINT JOB NUMBER
	PUSHJ	P,RADX10##
	PUSHJ	P,PRSPC
	MOVEI	T1,CONFIG##	;PRINT SYSTEM CONFIGURATION NAME
	PUSHJ	P,CONMES
	PUSHJ	P,PRSPC
	PUSHJ	P,DAYTIM
>
PCRLFA:
IFN FTJCON,<
	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
>
IFN FTWATCH,<
	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)?
	PUSHJ	P,WCHBEG	;YES, PRINT [HH:MM:SS] STARTED TO WAIT FOR RESPONSE
>
PCRLF0:	TLNN	M,NOCRLF	;SUPRESS CRLF?
	PUSHJ	P,CRLF		;NO
	TLNN	M,NOPER		;SUPRESS PRINTING PERIOD?
	PUSHJ	P,PRPER		;NO
	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
	TLNN	M,NOJOBN	;WAS NO JOB NUMBER NEEDED?
	TLNE	M,ERRFLG	;OR DID AN ERROR OCCUR?
	PUSHJ	P,TTYKLQ##	;YES, KILL TTY IN CASE NO JOB LEFT
	PUSHJ	P,DECHJB##	;DECREMENT HIGHJB IF APPROPRIATE
IFN FTMS,<
	SETOM	COMJOB##	;NO JOB IN COMCON NOW
>

IFN	FTSWAP, <

	JUMPE	F,CPOPJ##	;IF NO JOB, QUIT
	LDB	J,PJOBN##	;GET ATTACHED JOB # FROM TTY DDB
	JUMPE	J,CPOPJ##
	CAME	J,JOB##		;NEVER SET JRQ FOR CURRENT JOB!
	TLNN	M,CMWRQ		;REQUEUE JOB AFTER COMMAND WAIT OR ERROR?
	POPJ	P,
	JRST	REQUE##		;YES
>

IFE FTSWAP,<
	POPJ	P,
>
	SUBTTL	COMMAND TABLE



;BITS CHECKED BEFORE DISPATCHING TO COMMAND SETUP ROUTINE

NOCORE==1B18	;NO CORE NEEDED FOR COMMAND
NOJOBN==1B19	;NO JOB NUMBER NEEDED FOR COMMAND
NOLOGIN==1B35	;JOB DOES NOT NEED TO BE ALREADY LOGGED IN.
NOACT==1B34	;COMMAND MUST BE DELAYED IF JOB HAS ACTIVE DEVICES.
NORUN==1B33	;AN EXPLICIT ^C MUST BE TYPED BY USER BEFORE COMMAND
		; IS EXECUTED IF JOB IS RUNNING
		; JOB MUST BE SWAPPED IN IF IT HAS LOGICAL CORE
INCORE==1B32	;COMMAND MUST BE DELAYED IF JOB HAS LOGICAL CORE
		; WHICH IS ON DISK OR ON ITS WAY IN OR OUT.
		; JOB WILL BE SWAPPED IN (SEE DLYCOM)
		; AND IS NOT SITTING QUIETLY IN CORE(IE NO SWAPPING TRANSFER)
NXONLY==1B31	;NOT LEGAL IF EXECUTE ONLY PROGRAM
NBATCH==1B30	;NOT LEGAL FROM BATCH JOB


;BITS PLACED IN LH(M) AND CHECKED AFTER RETURN FROM COMMAND SETUP ROUTINE

CUSTMR==1B29	;RESERVED TO CUSTOMERS
NOINCK==1B28	;NO CHECK FOR JOB INITIALIZATION (JNA=0)
NOCRLF==1B27	;NO PRINTING OF CRLF
NOPER==1B26	;NO PRINTING OF PERIOD
TTYRNU==1B25	;SET TTY TO USER MODE AND START JOB
		; WHEN COMMAND RESPONSE STOPS TYPING
TTYRNC==1B24	;KEEP TTY IN COMMAND MODE AND START JOB
		; WHEN COMMAND RESPONSE STOPS TYPING
TTYRNW==1B23	;SET TTY TO USER LEVEL AND IO WAIT IF IT WAS IN IOW BEFORE
CMWRQ==1B22	;REQUEUE JOB AFTER COMMAND WAIT
NOMESS==1B21	;NO COMMAND RESPONSE EVER, DO NOT CALL TTYSTR OR TYPE WATCH BEGIN.
NOCRLP==:NOCRLF!NOPER!	;NEEDED FOR INTERNAL
TTYRNM==:TTYRNW!NOMESS	;TTY TO USER MODE AND NO MESSAGE
ERRFLG==1B20	;COMMAND ERROR
RUNFLG==:NOCORE!NOPER!TTYRNU!NOACT!NORUN!INCORE!NOCRLF
ECMFLG==:NOCRLF!NOPER!NOMESS!TTYRNC


;FLAG BITS IN LH(M)

FLMCOM==:1B18	;1=COMMAND, 0=UUO
FLMCLV==1B19	;COMMAND RUNNING AT COMMAND LEVEL
DEFINE NAMES<
	C	START,START,NOPER!TTYRNU!INCORE!NOACT!NORUN!NOLOGIN!NOJOBN
	C	.HALT,STOPF,NOCORE!NOJOBN!NOLOGIN!NOINCK!CMWRQ
	C	HALT,STOP,NOCORE!NOJOBN!NOLOGIN!NOINCK!CMWRQ,HALTXT
	C	KJOB,KJOB,NOCORE!NOJOBN!NOINCK!NOLOGIN!NOACT!NOPER!NOCRLF!NOMESS!INCORE!NORUN
	C	<>,CBLANK,NOCORE!NOJOBN!NOLOGIN!NOINCK!NOCRLF
	C	R,RCOM,NOCORE!NOPER!TTYRNU!NOACT!NORUN!INCORE
	C	RUN,RUNCOM,NOCORE!NOPER!TTYRNU!NOACT!NORUN!INCORE
	C	CORE,CORE,NOCORE!CMWRQ!INCORE!NOACT
	C	GET,GET,RUNFLG
	C	SAVE,SAVE,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
IFN FT2REL,<
	C	SSAVE,SSAVE,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
>
IFN FTEXE,<
	C	NSAVE,NSAVE,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
	C	OSAVE,SAVEO,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
IFN FT2REL,<
	C	NSSAVE,NSSAVE,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
	C	OSSAVE,SSAVE1,NOCRLF!NOPER!TTYRNU!INCORE!NOACT!NORUN!NXONLY
>	;END OF IFN FT2REL
>	;END OF IFN FTEXE
	C	CONTINUE,CONT,NOPER!TTYRNW!INCORE!NORUN!NOJOBN!NOLOGIN!NOINCK,CONTXT
IFN FTJCON,<
	C	JCONTINUE,JCONT,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	.FCONT,FCONT,NOPER!NOCRLF!NOMESS!NORUN!INCORE!NOJOBN!NOLOGIN!NOINCK,FCOTXT
>
IFN FTEXAMINE,<
	C	D,DCOM,CMWRQ!INCORE!NXONLY
	C	E,ECOM,NOCRLF!CMWRQ!INCORE!NXONLY
>
IFE FTPJOB,<
	C	PJOB,PJOB,NOCORE
>
IFN FTPJOB,<
	C	PJOB,PJOBX,NOCORE!NOJOBN!NOLOGIN!NOINCK
>;END IFN FTPJOB
IFN FTMODM!FTNET,<
	C	.HELLO,HELLO,RUNFLG!NOLOGIN
	C	.BYE,BYECOM,NOCORE!NOLOGIN!NOJOBN!NOINCK
>
IFN FTNET,<
	C	ASSIGN,ASSIGN,NOCORE!INCORE
	C	.NETLD,RUNNET,RUNFLG!NOLOGIN
	C	NODE,NODE.C##,INCORE!NOCORE!NOPER!NOCRLF!NOLOGIN
	C	DEASSI,DEASSIG,NOCORE!NOINCK!INCORE
>	;END FTNET
IFE FTNET,<
	C	ASSIGN,ASSIGN,NOCORE
	C	DEASSI,DEASSIG,NOCORE!NOINCK
>
	C	DDT,DDTGO,NOPER!TTYRNU!INCORE!NORUN!NOLOGIN!NOJOBN
IFN FTFINISH,<
	C	FINISH,CFINI,TTYRNU!NOACT!INCORE!NORUN!NOPER!NOCRLF
	C	CLOSE,CLSCOM,TTYRNU!NOACT!INCORE!NORUN!NOPER!NOCRLF
>
	C	REENTER,REENTER,TTYRNU!NOPER!INCORE!NORUN!NOLOGIN!NOJOBN
	PAGE
IFN FTATTACH,<
	C	CSTART,STARTC,TTYRNC!INCORE!NOACT!NORUN!NBATCH
	C	CCONTINUE,CONTC,TTYRNC!INCORE!NORUN!NBATCH
	C	DETACH,DETACH,NOCORE!NOJOBN!NOINCK!NBATCH!NOLOGIN
	C	ATTACH,ATTACH,NOCORE!NOJOBN!NOLOGIN!NOINCK!NBATCH
IFN FTDHIA,<
	C	XCHNGE,XCHUNI,NOCORE!NOJOBN!NOLOGIN!NOINCK
>
>
	C	DAYTIME,DAYTIM,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	.RESTA,RESTRT,NOCORE!NOJOBN!NOLOGIN!NOINCK
IFN FTTIME,<
	C	TIME,RUNTIM,NOCORE!NOLOGIN!NOINCK!NOJOBN
	C	RESOURCES,FREDEV,NOCORE!NOJOBN!NOLOGIN!NOINCK
IFN FTWATCH,<
	C	USESTAT,USECOM,NOCORE!NOJOBN!NOLOGIN!NOINCK!NOPER!NOMESS
>
>
IFN FTVERS,<
	C	VERSION,VERCOM,CMWRQ!INCORE,VERTXT
>
IFN FTDISK,<
IFN FTDSTT,<
	C	DSK,DSKCOM##,NOCORE!NOINCK
>
IFN FTCCLX,<
	C	MOUNT,RECALL,RUNFLG
	C	DISMOUNT,RECALL,RUNFLG
>
IFN FTQCOM,<
	C	QUEUE,RUNQUE,RUNFLG!NOLOGIN,QUEUE
	C	CPUNCH,RUNQUE,RUNFLG!NOLOGIN
	C	PLOT,RUNQUE,RUNFLG!NOLOGIN
	C	PRINT,RUNQUE,RUNFLG!NOLOGIN
	C	PUNCH,RUNQUE,RUNFLG!NOLOGIN
	C	SUBMIT,RUNQUE,RUNFLG!NOLOGIN
	C	TPUNCH,RUNQUE,RUNFLG!NOLOGIN
IFN FTGALAXY,<
	C	ALLOCA,RUNQUE,RUNFLG
	C	FREE,RUNQUE,RUNFLG
>>>
IFN FTBCOM,<
	C	IF,BAONLY,NOCORE
	C	GOTO,BAONLY,NOCORE
	C	BACKTO,BAONLY,NOCORE
	C	OPERATOR,BAONLY,NOCORE
	C	NOOPERATOR,BAONLY,NOCORE
	C	ERROR,BAONLY,NOCORE
	C	NOERROR,BAONLY,NOCORE
	C	SILENCE,BAONLY,NOCORE
	C	REVIVE,BAONLY,NOCORE
>
	PAGE
IFN FTTALK,<
	C	SEND,SEND,NOCORE!NOJOBN!NOLOGIN!NOINCK!NBATCH
>
	C	.TYPE,RETYPE##,NOCORE!NOJOBN!NOLOGIN!NOINCK!NOCRLF!NOMESS!NOPER
IFN	FTMIC,<
	C	I,RUN..I,NOCORE!NOLOGIN!NOPER!TTYRNU!NOCRLF!NOACT!NORUN!INCORE
	C	COJOB,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN
	C	WHENEVER,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	ON,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	LET,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	IF,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	GOTO,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	BACKTO,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	OPERATOR,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	NOOPERATOR,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	ERROR,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	NOERROR,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	SILENCE,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	PLEASE,RUNPLS,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	REVIVE,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	MIC,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
	C	DO,RUNMIC,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
>		;END OF FTMIC STUFF
IFN FTLOGIN,<
	C	SCHEDULE,SKEDUL,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	LOGIN,CLOGIN,RUNFLG!NOLOGIN,LOGTXT
>
IFE FTLOGIN,<
	C	LOGIN,CPOPJ##,NOCORE!NOACT!NORUN!INCORE,LOGTXT
>
IFN FTREASSIGN,<
	C	REASSI,REASS,NOCORE!NOACT!INCORE!CMWRQ!NORUN
>
IFN FTSET,<
	C	SET,SET,NOCORE!NOJOBN!NOLOGIN!NOINCK
>
	C	TTY,TTYCMD,NOCORE!NOLOGIN!NOJOBN!NOINCK!NBATCH
IFN FTNET,<
	C	LOCATE,CLOCATE##,NOCORE
	C	WHERE,CWHERE##,INCORE!NOCORE!NOLOGIN
>
IFN FTDAEM,<
	C	DCORE,DCORE,NOCORE!NOACT!NORUN!NOCRLF!NOPER!TTYRNU!INCORE!NXONLY
	C	DUMP,DCORE,NOCORE!NOACT!NORUN!NOCRLF!NOPER!TTYRNU!INCORE!NXONLY,DUMP
	C	.DUMP,CDUMPR,NOCORE!NOACT!NORUN!NOCRLF!NOPER!NOMESS!TTYRNU!INCORE
>
	C	INITIA,RUNAME,RUNFLG!NOLOGIN,INITXT
IFN FTCCLX,<
	C	DIRECT,RUNAME,RUNFLG
	C	HELP,RUNAME,NOCORE!NOLOGIN!NOPER!TTYRNU!NOCRLF!NOACT!NORUN!INCORE
	C	SYSTAT,RUNAME,RUNFLG!NOLOGIN
	C	FILE,RECALL,RUNFLG
IFE FTMIC,<
	C	PLEASE,RUNAME,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN!NBATCH
>
	C	FUDGE,RUNPIC,RUNFLG
	C	CREF,RUNAMC,RUNFLG
	C	SOS,RUNAME,RUNFLG
IFN FTLOGIN&FTACCT&FTDAEM,<
	C	CSHIFT,CSHIFT,RUNFLG
>
IFN FTLOGIN&FTACCT,<
	C	ACCOUNT,CACCT,NOCORE
	C	SESSION,CSESSN,RUNFLG
>
>
IFN FTCCL,<
	C	COMPILE,CCLRUN,RUNFLG,COMPIL
	C	DEBUG,CCLRUN,RUNFLG
	C	EXECUTE,CCLRUN,RUNFLG
	C	LOAD,CCLRUN,RUNFLG
>
	PAGE
IFN FTCCLX,<
	C	CREATE,CCLRUN,RUNFLG
	C	DELETE,CCLRUN,NOCORE!NOPER!TTYRNU!NOCRLF!INCORE!NOACT!NORUN
	C	EDIT,CCLRUN,RUNFLG
	C	LIST,CCLRUN,RUNFLG
	C	MAKE,CCLRUN,RUNFLG
	C	RENAME,CCLRUN,RUNFLG
	C	TECO,CCLRUN,RUNFLG
	C	TYPE,CCLRUN,RUNFLG
	C	COPY,CCLRUN,RUNFLG
	C	PRESERVE,CCLRUN,RUNFLG
	C	REWIND,CCLRUN,RUNFLG
	C	UNLOAD,CCLRUN,RUNFLG
	C	ZERO,CCLRUN,RUNFLG
	C	SKIP,CCLRUN,RUNFLG
	C	BACKSPACE,CCLRUN,RUNFLG
	C	EOF,CCLRUN,RUNFLG
	C	PROTECT,CCLRUN,RUNFLG
	C	LABEL,CCLRUN,RUNFLG
>
IFN FTCCL,<
	C	CTEST,CCLRUN,RUNFLG ;ALWAYS LAST CCLRUN
>
>
DEFINE SNAMES,<
IFN FTSET,<
IFN FTWATCH,<
	C	WATCH,SETWAT,NOCORE
>
IFN FTTLIM,<
	C	TIME,SETIME,NOCORE
>
IFN FTSPL,<
	C	SPOOL,SETSPL,NOCORE
	C	CDR,SETCDR,NOCORE
>
	C	SCHEDULE,SETSCD,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	CORMAX,SETMAX,NOCORE!NOJOBN!NOLOGIN!NOINCK
IFN FTLOCK,<
	C	CORMIN,SETMIN,NOCORE!NOJOBN!NOLOGIN!NOINCK
>
IFN FTSEDAT,<
	C	DAYTIM,SETDAY,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	DATE,SETDAT,NOCORE!NOJOBN!NOLOGIN!NOINCK
>
	C	OPR,SETOPR,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	TTY,TTYCMD,NOCORE!NOJOBN!NOLOGIN!NOINCK!NBATCH
IFN FTHPQ,<
	C	HPQ,HPQCMD##,NOCORE
>
IFN FTMTSET,<
	C	DENSITY,MTADEN,NOCORE!NOACT
	C	BLOCKSIZE,MTABLK,NOCORE!NOACT
IFN FTDX10,<
	C	RETRY,MTARTY,NOCORE!NOACT
>
>
IFN FTMS,<
	C	CPU,CPUCMD##,NOCORE
>
IFN FTDBAD!FTCAFE!FTDAS78,<
	C	NOMESS,DSKSIL,NOCORE!NOJOBN!NOLOGIN!NOINCK
> ;END FTDBAD!FTCAFE!FTDC78
IFN FTDPRI,<
	C	DSKPRI,DSKPRI,NOCORE
>
	PAGE
	C	DSKFUL,FULSTP,NOCORE
	C	BREAK,SETBRK##,NOCORE
IFN FTVM,<
	C	VMMAX,SETVMX##,NOCORE!NOJOBN!NOLOGIN!NOINCK
	C	VIRTUAL,SETUVC##,NOCORE
	C	PHYSICAL,SETUPC##,NOCORE
>
IFN FTNET,<
	C	HOSTESS,HOST.C##,INCORE!NOCORE!NOPER!NOCRLF!NOLOGIN
>
IFN FTMONL!FTMOFFL,<
	C	MEMORY,SETMEM,NOCORE!NOLOGIN!INCORE
>
IFN FTGALAXY,<
	C	DEFER,SETDFC,NOCORE
	C	NODEFER,SETNDC,NOCORE
>;END IFN FTGALAXY
	C	DEFAULT,SETDFL,NOCORE
IFN FTPATT,<
	C	CTEST,CPOPJ##,NOCORE!NOJOBN!NOLOGIN!NOINCK  ;ALWAYS LAST
>
>	;END CONDITIONAL ON FTSET
>	;CLOSE DEFINITION OF SNAMES
;GENERATE TABLE OF SIXBIT COMMAND NAMES
	$LOW
DEFINE C(A,B,D,E) <
IFNB <E>,<E:>
	<SIXBIT /A/>
>
XALL

COMTB2::SNAMES
DISPL2==.-COMTB2	;LENGTH
COMMX2==:<DISPL2-1>B26
COMTAB::NAMES
LASCCL==.
DISPL==.-COMTAB	;LENGTH OF TABLE
COMMXL==:<DISPL-1>B26
	$HIGH

;GENERATE THE DISPATCH TABLE PLUS SPECIAL BITS

DEFINE C(A,B,D,E) <
IFN FTCCL,<IFDEF DISP,<IFG .-DISP-COMPIL+COMTAB,<
IFDIF <B><CCLRUN>,<IF1,<PRINTX ? B DOES NOT PRECEDE CCLRUN IN COMTAB>>
RELOC .-1>>>
Z	B	(D)
>


DISP2:	SNAMES


DISP:	NAMES


;AND ONE MORE FOR AN UNKNOWN COMMAND DISPATCH

COMERD:	XWD	NOCORE+NOJOBN+NOLOGIN+NOINCK,NOCOM
	SALL
	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:	PUSHJ	P,RESET##	;RELEASE ALL IO DEVICES ASSIGNED TO THIS JOB
	PUSHJ	P,TTYFNU##	;FIND TTY FOR THIS JOB(SETUP J WITH JOB NO.)
ZAPPGM::
IFN FTSWAP,<
	PUSHJ	P,NOCORQ##	;PUT JOB IN NO CORE Q
	PUSHJ	P,ZERSWP##	;CLEAR SWAP SPACE (IF ANY) FOR LOW SEG
				; AND CLEAR SWP,SHF,IMGIN,IMGOUT FOR LOW SEG
>
IFN FT2REL,<
	PUSHJ	P,KILHGH##	;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
>

IFE FTVM,<
	SKIPE	T2,USREPL##	;DOES THIS JOB HAVE AN EXTENDED EXEC PD LIST?
				; (WAS THERE A PDL OV IN MONITOR)
	PUSHJ	P,GIVEPL##	;YES, GIVE BACK MONITOR FREE CORE
>	;END IFE FTVM
	PUSHJ	P,CLRTAB	;CLEAR BITS AND TABLE ENTRIES
 	MOVEI	T1,0		;RETURN BOTH PHYSICAL AND LOGICAL CORE
	SOS	(P)		;NEGATE SKIP RETURN WHICH CORE1 WILL DO
	JRST	CORE1##		;GO DO IT AND RETURN TO CALLER
	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

IFN FTPJOB,<

;THIS PRINTS OUT:
;
; JOB N   USER NAME   [P,PN]   TTY#
;
PJOBX:	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
	PUSHJ	P,PRNAME##	;PRINT IT
IFN FTKI10!FTKL10,<
	DMOVE	T1,.PDNM1##(W)	;GET USERS NAME
	JUMPE	T2,PJOBX2	;IF LAST PART IS NULL WE'RE DONE
				; WITH THE NAME PRINTOUT
>;END IFN FTKI10!FTKL10
IFN FTKA10,<
	SKIPN	T2,.PDNM2##(W)	;SEE IF LAST PART OF USERS NAME
				; IS NULL
	  JRST	PJOBX2		;IT IS NULL
	MOVE	T1,.PDNM1##(W)	;GET FIRST PART OF USERS NAME
>;END IFN FTKA10
	TRNN	T1,77		;DOES FIRST NAME END WITH A SPACE?
	  PUSHJ	P,PRSPC		;YES, GIVE A SPACE
	MOVE	T2,.PDNM2##(W)	;GET LAST PART OF USERS NAME
	PUSHJ	P,PRNAME##	;PRINT IT
PJOBX2:	PUSHJ	P,INLMES	;GIVE FOLLOWING MESSAGE
	ASCIZ	\   [\		;
	HLRZ	T1,JBTPPN##(J)	;GET PROJECT NUMBER
	PUSHJ	P,PRTDI8##	;PRINT IT
	PUSHJ	P,PRCOM		;PRINT A COMMA
	HRRZ	T1,JBTPPN##(J)	;GET PROGRAMMER NUMBER
	PUSHJ	P,PRTDI8##	;PRINT IT
	PUSHJ	P,INLMES	;GIVE FOLLOWING MESSAGE
	ASCIZ	\]   \		;
	MOVE	T2,@TTYTAB##(J)	;GET TTY NAME
	TLNN	T2,-1		;SEE IF DETACHED
	  HRLI	T2,'DET'	;DETACHED SO TACK DET TO TTY NUMBER
	PUSHJ	P,PRNAME##	;PRINT THE TTY NAME
	PJRST	CRLF		;END WITH A CRLF

>;END IFN FTPJOB

; "KJOB" KILL ATTACHED JOB


KJOB:	JUMPE	J,ATT4		;WAS JOB INITIALIZED?
IFN	FTLOGIN, <
	TLNN	P4,JLOG		;TEST JLOG ALSO IN CASE JOB NOT LOGGED IN
	JRST	KJOB2		;IF JOB NOT LOGGED IN
IFN	FTSWAP, <
	PUSHJ	P,TTYATI##	;ATTACH TTY
	  JFCL
>
	TLO	M,TTYRNU	;SET TTYRNU FOR COMRET
IFN FTPHYO,<
	MOVSI	P1,PHONLY	 ;SET PHYSICAL I/O FORCE SYSTEM KJOB
>
IFN FTSET,<
	MOVSI	T1,(JS.BPR)	;SET BYPASS PROGRAM TO RUN
	IORM	T1,JBTST2(J)	;TO INSURE KJOB REALLY RUNS
>
IFN FTMS,<
	PUSHJ	P,ALLJSP##	;SET CPU SPECIFICATION TO MAKE THIS JOB RUNNABLE
				; ON ALL CPU'S. THIS ALSO LEAVES A REASONABLE
				; SPECIFICATION FOR THE NEXT USER WHO GETS
				; THIS JOB NUMBER
>
IFN FTGALAXY,<
	SKIPE	%SIQSR##	;QUASAR RUNNING?
	SETOM	ISGALX##	;YES ITS A GALAXY SYSTEM
	SKIPE	ISGALX##	;IS IT A GALAXY SYSTEM?
				;IS QUASAR RUNNING
	MOVE	P2,LGONAM	;YES, JUST RUN LOGOUT
>
	JRST	RUNAME		;GO RUN CUSP
>
KJOB2:
IFE FTSWAP+FTLOGIN,<
	JUMPE	R,JOBKA		;YES. DOES JOB HAVE CORE IN MEMORY?
>
	PUSHJ	P,GETMIN	;GET MINIMAL JOB AREA ON DISK OR CORE
	JUMPE	R,DLYCM		;DELAY COMMAND IF CORE ASSIGNED ON DISK
	JSP	T2,MONJOB##	;YES, SCHEDULE MONITOR JOB(PC IN EXEC MODE)
				; RETURN HERE AT UUO LEVEL WHEN SCHEDULED
JOBKL::	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
IFN FTDISK,<
	PUSHJ	P,DSKKJB##	;CLEAR UP CORE BLOCKS ON A KJOB COMMAND
				; MAY GO INTO WAIT, SO DO BEFORE GIVING UP USER CORE
>
IFN FTIPCF,<
	PUSHJ	P,IPCLGO##	;TELL [SYSTEM] INFO THAT JOB IS GONE
>
IFN FTHSLN,<
	JUMPE	W,JOBKL1	;IF THIS JOB HAS A PDB,
	SKIPGE	.PDDVL##(W)	; AND IF THERE ARE TOO MANY LOGICAL NAMES FOR THE TABLE,
	SETZM	.PDDVL##(W)	; DON'T TRY TO REBUILD THE TABLE
				; SINCE IT IS COUNTER PRODUCTIVE
				; AND CAN CAUSE PDLOVF AFTER CORE HAS BEEN FLUSHED
JOBKL1:>
IFE FTLOGIN, <
JOBKA:
IFN FTTIME,<
	PUSHJ	P,PRTTIM	;PRINT JUST TOTAL RUN TIME
>
	PUSHJ	P,PRRSP4	;PRINT CR,LF,PERIOD
	MOVSI	T1,LDLECS##
	IORM	T1,LDBDCH##(U)	;SET BIT TO EAT COMMAND
	PUSHJ	P,TTYSTR##	;START TTY
	MOVSI	T1,LDLECS##
	ANDCAM	T1,LDBDCH##(U)	;ONLY
	MOVSI	T1,LDLCMF	;INCREMENT COMCNT ONE
	IORM	T1,(U)
>
	PUSHJ	P,DEASTY	;DEASSIGN ALL BUT TTY
	PUSHJ	P,JOB1		;FLUSH CORE AFTER RELEASING DEVICES
	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,OCTIN1	;CONVERT POSSIBLE OCTAL NO ARG.
	  JRST	SNOARG		;NO ARG SPECIFIED RETURN
	  JRST	COMERA		;ILLEGAL CHARACTER
IFN FTLOGIN,<
	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
IFN FT2REL,<
	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.
>
	TLZ	T2,-1		;CLEAR JUNK
	JRST	STARTN		;START IN USER MODE
IFN FTLOGIN,<
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


REENTER:
	HRRZ	T2,JOBREN##(R)	;GET REENTER ADDRESS FROM JOB DATA AREA

	JRST	CHKPCM		;CHECK IF PC IS IN MONITOR

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


DDTGO:
IFN FTVM,<
	JUMPE	R,STARTE	;ERROR IF NO CORE (NOT A JOB)
>
	HRRZ	T2,JOBDDT##(R)	;DDT STARTING ADR. IN JOB DATA AREA
IFN FTVM,<
	JUMPN	T2,CHKPCM	;OK IF WE HAVE DDT
	TLNN	P4,JLOG		;MAKE SURE LOGGED IT
	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)
STARTN:
	MOVE	T1,JOBPC##(R)	;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
	HRRZ	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:
	HRRZ	T2,JOBSA##(R)	;START ADR. SPECIFIED BY LINKING LOADER
				; FROM END STATEMENT
				;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
	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 adr
/
	SUBTTL	DUMP & DCORE COMMANDS

IFN FTDAEM,<
IFN FTVM,<
DAECOM:	HLL	M,DISP+DUMP-COMTAB	;GET BITS FOR COMRET
>
DCORE:	PUSHJ	P,STDAEM##
	  JRST	NODAEM
	MOVEI	T1,JDC
	ORM	T1,JBTSTS##(J)
	PJRST	REQUE##

NODAEM:	JSP	T1,ERRMES
	ASCIZ	/DAEMON NOT RUNNING
/

;HERE TO RUN DUMP AT CCL ENTRY POINT

CDUMPR:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	T1,DUMP		;NAME OF PROGRAM TO RUN
	MOVEI	P1,1		;LH=0 FOR PHYSICAL ONLY, RH=OFFSET FOR CCL ENTRY
	JRST	ARCOM		;GO RUN THE CUSP

>

IFN FTLOGIN&FTACCT&FTDAEM,<
CSHIFT:	PUSHJ	P,OPRLGL	;MUST BE OPR
	  JRST	COMERA		;ILLEGAL IF NOT OPR
	JRST	DCORE		;GO START UP DAEMON
>
	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:
	JUMPE	J,STOPB
IFN FTJCON!FTDAEM,<
	TLNE	P4,JACCT	;JACCT AND WAITING
	TRNN	P4,JDCON	;..
	JRST	STOPD		;NO--PROCEDE
	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!JDC	;CLEAR JCONT.ABLE (DEV OK?) AND DAEMON BIT
	ANDCAM	T1,JBTSTS##(J)	; SO USER CAN STOP ONCE-A-MINUTE STUFF
>
IFN FTMS,<
	PUSHJ	P,SPSTOP##	;TEST IF JOB ON SLAVE, IF SO SIGNAL TO STOP IT,
	  JRST	DLYCM1		;  AND DELAY COMMAND
>
IFE FTDISK,<
	CAMN	J,STUSER##	;IS THIS SYSTEM TAPE USER?
	JRST	CFINS		;YES, DO FINISH SYS COMMAND
>
IFN FTDISK,<

	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		;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
IFN FTWATCH,<
	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:
IFN FTLOGIN,<
	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:
IFN FTSET,<
	SKIPL	JBTSTS##(J)	;RUNNING?
	PUSHJ	P,FNDPDB	;FIND PDB
	  POPJ	P,
	MOVEI	T1,TTFCXU##	;FORCE .DUMP
	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
>
IFE FTSET,<
	POPJ	P,0
>
STOPX:	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::
IFN FTWATCH,<
	PUSHJ	P,WCHEND	;PRINT SYSTEM RESPONSE DATA IF USER IS WATCHING IT.
>
PRRSP4::PUSHJ	P,CRLF		;PRINT CR-LF
PRRSP5::PJRST	PRPER		;PRINT PERIOD
	SUBTTL	SET COMMAND AND UUO  -- DISPATCH

;SET COMMAND/UUO

IFN FTSET,<
SET:	MOVEI	P3,DISP2	;START OF SET-TABLE
	MOVE	P4,[XWD -DISPL2,COMTB2]	;LENGTH, NAME
	POP	P,T1		;REMOVE RETURN ADR FROM STACKS
	JRST	COM1		;GO INTERPRET 2ND PART OF COMMAND
>	;END CONDITIONAL ON FTSET

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

SETLGF==FUPOPJ##
SETLGK==FUPOJ1##
SETLGL::PUSHJ	P,OPRLGL	;OPR?
	  SKIPA	T2,JBTPPN##(T1)	;NO, CHECK FURTHER
	JRST	CPOPJ1##	;YES, OK
	CAMN	T2,FSFPPN##	;1,2?
	AOS	(P)		;YES, OK
	POPJ	P,		;RETURN
OPRLGL:	PUSH	P,U		;PRESERVE LINE
	PUSH	P,F		;AND F
	MOVE	T1,J
	HRRZ	T3,OPRLDB##	;SEE IF OPR
	CAIN	T3,(U)		;ALSO OPR
	JRST	SETLGK		;WE WIN
IFN FT5UUO,<			;CONDITIONAL BECAUSE OF CTLJB
	MOVE	T2,JBTSTS##(J)	;GET JOB STATUS
	TLNE	T2,JLOG!JNA	;A JOB ON THE TTY?
	JRST	SETLGF		;YES. COMMAND LOSES
	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
	HRRZ	U,DDBLDB##(U)	;THEN GET LDB
	JUMPE	U,SETLGF	;IF CONTROL JOB DETACHED STOP SCAN AND FAIL
	MOVE	T2,JBTLIM##(J)	;GET BATCH JOB BITS
	TLNE	T1,(JB.LBT)
	JRST	SETLGF		;YES. COMMAND LOSES
	CAIN	T3,(U)		;OR HIS TTY?
	JRST	SETLGK		;YES. COMMAND WINS
>	;END CONDITIONAL ON FT5UUO
	JRST	SETLGF		;LOSE

	SUBTTL	SET COMMAND AND UUO -- JBSET.

IFN FTSET,<
;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
JBSET.::IFN FTLOGIN,<
	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
	MOVEI	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
IFN FTLOGIN,<NOSCHED
	PUSH	P,JBTPPN##(J)	;SAVE PPN
	MOVE	T2,FSFPPN##	;GET A GOOD PPN
	MOVEM	T2,JBTPPN##(J)	;FAKE OUT PRIVJ AND PRVBIT
>
	PUSH	P,J
	PUSH	P,W		;PRDSERVE W
	PUSHJ	P,FNPDBS##	;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
IFN FTLOGIN,<
	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
SETUUO::HRRZ	T2,T1		;ARGUMENT
	HLRZS	T1		;FUNCTION
	CAILE	T1,SETLEN	;A LEGAL FUNCTION?
	POPJ	P,		;NO, RETURN DOING NOTHING
IFN FTLOGI,<
	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
IFN FTLOGI,<
	POPJ	P,		;NO, RETURN DOING NOTHING
>
>	;END CONDITIONAL ON FTSET
IFE FTSET,<
XP JBSET.,CPOPJ##
XP SETUUO,CPOPJ##
>
;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
;PRVBT RESPECTS T2
IFN FTPRV,<
PRVBT::
PRVBIT::TDNE	T1,JBTPRV##(J)	;IS REQUESTED BIT ON IN TABLE?
	POPJ	P,0		;YES. OK RETURN
;	PJRST PRVJ		;NO. CHECK FOR JACCT OR FSFPNN
IFE FTLOGIN,<JRST CPOPJ1##>	;ERROR RETURN IN NON-LOGIN SYSTEM
>	;END CONDITIONAL ON FTPRV


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

IFN FTLOGIN,<

PRVJ::	MOVE	T3,JBTSTS##(J)	;JBTSTS WORD
	SKIPGE	M		;COMMAND LEVEL?
	TLZ	T3,JACCT	;YES--CLEAR JACCT
	MOVE	T4,JBTPPN##(J)	;JOB'S PRJ-PRG
	CAME	T4,FSFPPN##	;=1,2?
	TLNE	T3,JACCT	;NO, JACCT ON?
	POPJ	P,		;YES, OK
	PJRST	CPOPJ1##	;NO, ERROR RETURN
>	;END CONDITIONAL ON FTLOGIN
IFN FTSET,<
;TABLE FOR SETUUO
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
	IFN	FTTLIM,<XWD NEDPRV,CORELM##>
	IFE	FTTLIM,<XWD NEDPRV,CPOPJ##>
	XWD	NEDPRV,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
IFN FTVM,<
	XWD	NEDPRV,SETVM1##	;(22) - SET VMMAX (SYSTEM-WIDE)
	XWD	NEDPRV,CPOPJ1	;(23) - HISTORICAL
	XWD	NEDPRV,SETUVL##	;(24) - SET VM MAXIMA (USER)
	EXP	SETUV1##	;(25) - SET CURRENT VM MAXIMA (USER)
	EXP	SETVTM##	;(26) - SET TIME FOR VIRTUAL TIME INTERRUPTS
>
IFE FTVM,<
	EXP	CPOPJ##
	EXP	CPOPJ##
	EXP	CPOPJ##
	EXP	CPOPJ##
	EXP	CPOPJ##
>
	EXP	SETABR##	;(27)-SET ADDRESS BREAK
	EXP	SETPGM		;(30)-SET PROGRAM TO RUN
IFN FTGALAXY,<
	EXP	SETDFU		;(31)-SET DEFERED SPOOLERS
>
IFE FTGALAXY,<
	EXP	CPOPJ##
>
IFN FTNET,<
	XWD	NEDPRV,HOST.U##	;(32)-SET HOST
>
IFE FTNET,<
	EXP	CPOPJ##
>
	EXP	SETDLU		;(33)-SET DEFAULTS
IFN FTPATT,<
	EXP	CPOPJ##		;ROOM FOR PATCHING
>
SETLEN==.-SETTBL-1
IFE FTLOCK,<
SETMN1==CPOPJ##
>
IFE FTSPL,<
SETSPI==CPOPJ##
SETSPB==CPOPJ##
SETSPL==CPOPJ##
>
IFE FTWATCH,<
SETWTU==CPOPJ##
>

IFE FTSEDAT,<
SETDT1==CPOPJ##
SETDA1==CPOPJ##
>

IFE FTTLIM,<
SETIM1==CPOPJ##
>
IFE FT5UUO,<
SETKSY==CPOPJ##
>
IFN FTTLIM,<>
;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- CORMAX AND CORMIN

IFN FTLOCK,<
SETMX1:	SKIPN	LOCK##		;JOB BEING LOCKED?
	JRST	SETMX2		;NO - OK
	POPJ	P,		;YES - CAN'T CHANGE CORMAX
>
SETMAX:	PUSHJ	P,CORLGL	;GET DECIMAL ARG IF LEGAL
IFN FTLOCK,<
	SKIPE	LOCK##		;IF A JOB IS BEING LOCKED,
	JRST	DLYCM1		;WAIT TILL LATER
>
SETMX2:				;SET NEW VALUE IN CORMAX
IFE FTLOCK,<
SETMX1==SETMX2
>
	MOVE	T1,MAXMAX##	;MAXMAX IS HIGHEST CORMAX
	CAMG	T2,T1		;TRY TO SET IT TOO HIGH?
	JRST	SETAOK		;NO
	JUMPGE	M,CPOPJ
	PUSHJ	P,INLMES
	ASCIZ	/
%Exceeds physical maximum-/
	MOVE	T1,MAXMAX##	;GET MAXIMUM
	LSH	T1,W2PLSH##	;SET UP FOR P OR K
	PUSHJ	P,PRCORE	;TELL WHAT IT IS
	MOVE	T2,MAXMAX##	;REDUCE TO PHYSICAL LIMIT
SETAOK:	CAILE	T2,MINMAX##	;TOO SMALL?
	JRST	SETIOK		;NO
	JUMPGE	M,CPOPJ
	PUSHJ	P,INLMES
	ASCIZ	/
%Below minimum-/
	MOVEI	T1,MINMAX##	;GET MINIMUM
	LSH	T1,W2PLSH##
	PUSHJ	P,PRCORE	;REPORT IT
	MOVEI	T2,MINMAX##
SETIOK:	CAMGE	T2,CORMAX##	;DECREASING?
	PUSHJ	P,CHKMAX	;YES. CHECK JOB SIZES
	MOVEM	T2,CORMAX##	;SAVE NEW VALUE
	LSH	T2,W2PLSH##	;REDUCE TO N
	HRRM	T2,CORLIM##	;SAVE IN RH(CORLIM)
	JRST	CPOPJ1##	;AND SKIP RETURN
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 #
	SKIPG	J,JBTSGN##(J)	;GET ITS HISEG (IF ANY)
	JRST	CHKMX2		;NONE
	MOVSI	T3,NSWP!NSHF
	TDNE	T3,JBTSTS##(J)	;HISEG LOCKED?
	JRST	CHKMX2		;YES
	MOVE	P3,T2		;SAVE LOW SEG SIZE
	PUSHJ	P,SEGSIZ	;GET HISEG SIZE
	ADDI	T2,(P3)		;TOTAL
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,CPOPJ
	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
	JRST	JPOPJ##

IFN FTLOCK,<
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::
IFN FTLOGIN,<
	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::
IFN FTLOGI,<
	PUSHJ	P,SETLGL	;TEST FOR LEGALITY
	  JRST	COMERP		;NOT LEGAL
>
DECLG1:	PUSHJ	P,DECIN1	;LEGAL - GET DECIMAL NUMBER
	  PJRST NOTENP		;NOT ENOUGH ARGS
	  PJRST COMERP		;NOT A NUMBER
	POPJ	P,		;OK - RETURN
;STILL IN FTSET CONDITIONAL
IFN FTMONL!FTMOFFL,<
;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	SETME1		;NONE WAS TYPED
	JUMPN	T1,SETME1	;SKIP ON IF "FROM" WAS TYPED
	MOVE	T1,[-1,,[SIXBIT /FROM/]]
	PUSHJ	P,TXTARG	;"LINE" WAS TYPED, EAT "FROM" IF ITS THERE
	  JFCL			;DON'T CARE WHETHER IT WAS ON NOT
SETME1:	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
	MOVE	T1,[-1,,[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]
;STILL IN FTMONL, FTMOFFL, FTSET CONDITIONAL
	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
	JUMPE	P1,MEMONL##	;GO SET THE MEMORY IN THE SPECIFIED RANGE ON-LINE
IFE FTMOFFL,<
	JRST	COMERA		;ERROR IF NOT SUPPORTED
>

;STILL IN FTMONL, FTMOFFL, FTSET CONDITIONAL
IFN FTMOFFL,<
	SKIPN	[LOKINC##]	;MUST HAVE THE LOCK UUO TO SET MEMORY OFF
	JRST	COMERA		;ERROR IF KILOCK NOT LOADED
	PUSHJ	P,CKMOL##	;CHECK THAT RANGE DOESN'T OVERLAP THE MONITOR
	  JRST	SETME6		;IT DOES SO WE CAN'T DO IT
SETME2:	PUSH	P,T1		;SAVE LOWER BOUND
	PUSH	P,T2		;AND UPPER BOUND
	MOVEI	P1,[ASCIZ /?Job(s) to 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,ERRMES	;TELL COMRET THAT THERE WAS AN ERROR
	PUSHJ	P,PRJBNM##	;DISPLAY INFO. ABOUT THE PROBLEM JOB
	JRST	TPOPJ##		;RESTORE T1, AND RETURN

>;END FTMOFFL CONDITIONAL
>;END FTMONL, FTMOFFL CONDITIONAL
;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- DAYTIME AND SCHED

IFN FTSEDAT,<
SETDAY:	PUSHJ	P,DECLGL	;GET DECIMAL TIME IF LEGAL
SETDA1:	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,TIMLST##
	PJRST	SETDT2		;FIXUP 'DATE' & SKIP RETURN

>
SETSCD:
IFN FTLOGI,<
	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:	HRRM	T2,STATES##	;SAVE NUMBER
	JRST	CPOPJ1##	;AND SKIP RETURN

IFN FTTLIM,<SETIM1:	IMUL	T2,TICSEC##	;CONVERT TO JIFFIES
	JRST	SETIM2		;GO STORE

SETIME:	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:
IFN FTLOGI,<
	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

SETOP2:	PUSHJ	P,STDOPR##	;CHANGE DEVICE
	  POPJ P,0		;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
	POPJ	P,
	MOVEM	T2,LOGMAX##
	JRST	CPOPJ1##

SETBMX:	CAIL	T2,0		;BATMAX MUST BE .GE. 0
	CAILE	T2,15		;  AND .LE. 15
	POPJ	P,
	MOVEM	T2,BATMAX##
	JRST	CPOPJ1##

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

;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- WATCH

IFN FTWATCH,<
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.WDY	;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: day,run,wait,read,write,version,mta,all,none/
$LOW
WATTAB::<SIXBIT /DAY/>
	<SIXBIT	/RUN/>
	<SIXBIT	/WAIT/>
	<SIXBIT	/READS/>
	<SIXBIT	/WRITES/>
	<SIXBIT	/VERSION/>
	<SIXBIT	/MTA/>
;ADD NEW ITEMS HERE AND IN ERROR COMMENT AND IN S.MAC
WATLEN==.-WATTAB
WTCMXL==:<WATLEN-1>B26
>	;END FTWATCH
IFN FTWATCH!FTSPL,<
;THIS TABLE MUST BE IN ORDER NO, ALL, NONE
;AND MUST FOLLOW WATTAB IF FTWATCH IS NON-ZERO
NOTTAB:	<SIXBIT	/NO/>
	<SIXBIT	/ALL/>
	<SIXBIT	/NONE/>
NOTLEN==.-NOTTAB
$HIGH
>	;END FTWATCH!FTSPL
;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- DATE

IFN FTSEDAT,<

SETDAT:	PUSHJ	P,SETLGL	;TEST FOR LEGALITY
	  JRST	COMERA		;NOT PRIVILEGED
	MOVEI	T1,LOCYER##

	PUSHJ	P,GTDATE	;ACCEPT E.G. 3-JAN-72
	  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
	MOVE	T2,HIGHJB##	;GET HIGHEST JOB ASSIGNED
SETDT3:	SKIPE	JBTJLT##(T2)	;ANYTHING THERE?
	ADDM	T1,JBTJLT##(T2)	;YES, ADJUST IT
	SOJG	T2,SETDT3	; AND LOOP
IFN FTDAEM&FTACCT,<
	HRRZ	U,T1		;TIME PART
	HLRZ	F,T1		;DATE PART
	MOVEI	T1,.ERDTC	;DATE OR TIME CHANGE
	PUSHJ	P,DAERPT##	;TELL DAEMON
>
IFN FTKL10,<
	PUSHJ	P,THSDA##	;RECOMPUTE 12 BIT DATE
	PJRST	COMSDT##	;TELL ANY FRONT ENDS THAT NEED TELLING
				; ABOUT NEW DATE.  COUNT ON SET DAYTIME
				; GETTING HERE WITH NEW TIME ALSO.
>;END IFN FTKL10

IFN FTKA10!FTKI10,<
	PJRST	THSDA##		;RECOMPUTE 12 BIT DATE AND RETURN
>;END IFN FTKA10!FTKI10


SETDT1:	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
>

IFN FT5UUO,<
SETKSY:	MOVEM	T2,SYSKTM##	;STORE VALUE FOR CLOCK1
	JRST	CPOPJ1##	;RETURN
>
;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- SPOOL

IFN FTSPL,<
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	T3,PVNSPL	;NO, IS JOB ALLOWED TO UNSPOOL?
	TDNN	T3,JBTPRV##(J)
;NOTE THIS CODE DEPENDS ON PVNSPL=ST.NSP
IFN PVNSPL-ST.NSP,<PRINTX ST.NSP DOESN'T=PVNSPL>
	TSNE	T3,STATES##
	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
	SKIPN	T2		;ANYTHING THERE?
	POPJ	P,		;NO, RETURN
	JRST	SETSP0		;AND SET ITS BIT

;STILL IN FTSPL CONDITIONAL
;STILL IN FTSET CONDITIONAL
	SUBTTL	SET COMMAND AND UUO -- DEFER/NODEFER
IFN FTGALAXY,<
;ENTER HERE ON SETUUO
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

>;END INF FTGALAXY
;STILL IN FTSPL CONDITIONAL
;STILL IN FTSET CONDITIONAL
	SUBTTL SET COMMAND AND UUO -- DEFAULTS

SETDFL:	PUSHJ	P,CTEXT		;GET DEFAULT ARGEMENT 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
	JRST	@DFLCTB(T1)	;DISPATCH TO SET THE DEFAULT

;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?
	POPJ	P,		;NO, ERROR RETURN
	JRST	@DFLUTB(T1)	;DISPATCH TO SET THE DEFAULT

DEFINE NAMES<
	C	PROTECTION,DFLPRT
>
DEFINE C(A,B,D,E)<
IFNB<E>,<E:>
	<SIXBIT /A/>
>
XALL
DFLTTB:	NAMES
DFLTTL==.-DFLTTB
DEFINE C(A,B,D,E)<
Z	B	(D)
>
DFLCTB:	NAMES
DFLUTB:	EXP	DFLPRU
DFLUTL==.-DFLUTB-1
;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 ?
	POPJ	P,		;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
	SUBTTL	SET COMMAND AND UUO -- CDR

;ENTER HERE ON SET CDR UUO
SETSPI:	HRLOS	T2		;GET NAME, -1
	AOSA	(P)		;AND SKIP COMMAND ENTRY AND FORCE SUCCESS RETURN
;SET CDR COMMAND
SETCDR:	PUSHJ	P,CTEXT1	;GET FILE NAME
	JUMPE	T2,NOTENF	;NONE SPECIFIED
	HLLM	T2,JBTSPL##(J)	;SAVE NAME
	POPJ	P,		;AND RETURN



;HERE TO SET SPOOL BITS BY UUO
SETSPB:
IFN FTPRV,<
	SETCM	T3,T2		;-BITS HE WANTS ON
	ANDI	T3,.SPALL
	TDNN	T3,JBTSPL##(J)	;CLEARING SOME BITS FROM JBTSPL?
	JRST	SETSPC		;NO - OK
	MOVSI	T3,PVNSPL	;YES. IS HE ALLOWED?
	TDNN	T3,JBTPRV##(J)
;NOTE THIS CODE DEPENDS ON PVNSPL=ST.NSP
IFN PVNSPL-ST.NSP,<PRINTX ST.NSP DOESN'T=PVNSPL>
	TSNE	T3,STATES##
	JRST	SETSPC		;YES. GO DO IT.
	PUSHJ	P,PRVJ		;NO. SEE IF PRIV. JOB
	  JRST SETSPC		;YES. GO DO IT.
	POPJ	P,0		;NO. FAILURE RETURN
>	;END CONDITIONAL ON FTPRV

SETSPC:	DPB	T2,[POINT 5,JBTSPL##(J),35]  ;YES, DO IT
	JRST	CPOPJ1##	;SUCCESS RETURN
>	;END CONDITIONAL ON FTSPL
;STILL IN CONDITIONAL ON FTSET
IFN FTDBAD!FTCAFE!FTDAS78!FTNET,<
DSKSIL:	PUSHJ	P,SETLGL	;LEGAL?
	  JRST	COMERA		;NO
	PUSHJ	P,CTEXT1	;YES, GET DRIVE NAME
	MOVE	T1,T2		;INTO T1
IFN FTCAFE!FTDAS78!FTNET,<
	CAMN	T2,[SIXBIT 'PDP11'] ;DOES HE WANT TO STOP PDP-11 MESSAGE?
	PJRST	D76SIL##	;YES--GO SHUT HIM UP
>
	PUSHJ	P,TPMSIL##	;SEE IF A TAPE KONTROLLER
	  PJRST	CPOPJ1##	;YES - EXIT
IFN FTDBAD,<
	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

IFN FTDPRI,<
;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,
>
IFN FTDPRI!FTHPQ,<
PRIERR::JSP	T1,ERRMES
	ASCIZ	/NO PRIVS TO SET PRIORITY THAT HIGH
/
>;END FTDPRI!FTHPQ
;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 - 7
	PJRST	STOTC1##	;STOTAC, THEN CPOPJ1
;UUO TO SET PROGRAM TO RUN
SETPGM:
IFN FTTLIM,<
	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: ?
	POPJ	P,		;NO, ERROR
>	;END OF FTTLIM
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,FNPDBS##
	MOVEM	T1,.PDPGM##(W)
	JRST	CPOPJ1##

	SUBTTL	SET COMMAND AND UUO -- ROUTINE TO READ DATE

>	;END CONDITIONAL ON FTSET
;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

IFN FTWATCH,<

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
>	;END FTWATCH

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

IFN FTWATCH,<

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,FNPDBS##	;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
	TDZE	T1,JBTWCH##(J)	;DOES USER WANT TO WATCH IT?
	PUSHJ	P,@WCHTAB(P1)	;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:
IFN FTTIME,<
	XWD	JW.WRN,PRTWRN	;PRINT RUN TIME
	XWD	JW.WWT,PRTWWT	;PRINT WAIT TIME
>
IFN FTDISK&FTDSTT,<
	XWD	JW.WDR,PRTWDR##	;PRINT # DISK BLOCKS READ
	XWD	JW.WDW,PRTWDW##	;PRINT # DISK BLOCKS WRITTEN
>
				;ADD NEW DATA HERE
WCHLEN==.-WCHTAB
>	;END FTWATCH
;ROUTINE TO PRINT INCREMENTAL RUNTIME(NO CRLF)
;CALL:	MOVEI T1,0
;	PUSHJ P,PRTWRN

IFN FTWATCH&FTTIME,<

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)
>				;END FTWATCH & FTTIME


IFN FTWATCH,<
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
>
IFN FTMTSET,<
MTADEN:	PUSHJ	P,MTFIND	;GET THE REST OF COMMAND AND FIND MTA DDB
	  JRST	COMERR		;NOT NUMERIC
	MOVE	T1,[-DNTBLN,,DENTAB]
	MOVE	T3,0(T1)	;GET ENTRY FROM TABLE
	CAIE	T2,(T3)		;MATCH?
	AOBJN	T1,.-2		;NO - TRY NEXT
	JUMPGE	T1,COMERA	;ERROR IF NONE FOUND
	HLRZ	T1,T3		;GET CODE
	DPB	T1,TDYDN1##	;YES, STORE CODE IN DDB
	JRST	CPOPJ1##	;RETURN (SKIP)

MTABLK:	PUSHJ	P,MTFIND	;GET REMAINDER OF COMMAND AND FIND MTA DDB
	  JRST	COMERR		;NOT NUMERIC
	AOS	T2		;GET BLOCK SIZE +1
	CAILE	T2,NOISEW##	;LESS THAN NOISE RECORD?
	CAIL	T2,10000	;NO, GREATER THAN BYTE SIZE?
	JRST	COMERR		;YES, ERROR
	DPB	T2,PBUFSZ##	;PUT IT IN DDB
	JRST	CPOPJ1##	;SKIP RETURN
IFN FTDX10,<
MTARTY:	PUSHJ	P,MTFIND	;GET REST OF COMMAND, SET UP F
	  HLRZS	T2		;NON-NUMERIC RETURN (NORMAL)
	MOVSI	T1,MTSNAR##	;NO AUTO-RECOVERY BIT
	CAIN	T2,'ON '		;CLEAR OR SET IF 'ON' OR 'OFF'
	JRST	[ANDCAM	T1,DEVIOS(F)
		 PJRST	CPOPJ1##]
	CAIE	T2,'OF '
	CAIN	T2,'OFF'
	JRST	[IORM	T1,DEVIOS(F)
		 PJRST	CPOPJ1##]
	JRST	COMERR		;NOT A LEGAL ARGUMENT
>
MTFIND:
	PUSHJ	P,CTXDEV	;PICK UP DEVICE ARGUMENT
	SKIPE	T1,T2		;DEVSRG EXPECTS NAME IN T1
	PUSHJ	P,DEVSRG##	;SEARCH FOR DDB
	  PJRST MTFERR		;NO SUCH DEVICE
	LDB	T1,PJOBN##	;GET OWNER'S JOB NUMBER
	CAME	T1,J		;US?
	  PJRST MTFERR		;NO, LOSE!
	MOVE	T1,DEVMOD(F)
	MOVE	U,TTYTAB##(J)	;RESTORE U
	HRRZ	U,DDBLDB##(U)
	TLNN	T1,DVMTA	;IS DEVICE A MAGTAPE?
	  PJRST COMERP		;NO, LOSE!
	PUSHJ	P,DECIN1	;GET LAST ARGUMENT
	  PJRST NOTENP		;NO ARGUMENT FOUND
	  PJRST	CTEXT1		;NOT NUMERICAL, READ SIXBIT
	JRST	CPOPJ1		;RETURN.
MTFERR:	MOVE	U,TTYTAB##(J)	;TTY DDB
	HRRZ	U,DDBLDB##(U)	;LDB BACK INTO LINE
	PJRST	COMERP		;TYPE ERROR MESSAGE

;TABLE OF VALID DENSITIES

DENTAB:	RB.D2,,^D200
	RB.D5,,^D556
	RB.D8,,^D800
	RB.D16,,^D1600
	RB.D62,,^D6250
DNTBLN==.-DENTAB
>	;END CONDITIONAL ON FTMTSET
	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
	TLNN	P4,JERR		;IS JOB ERROR BIT SET?
	POPJ	P,		;COMMAND DECODER WILL DO THE REST
	JSP	T1,ERRMES	;YES, PRINT CANT CONTINUE

	ASCIZ	/Can't continue
/

IFN FTJCON,<
;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"
;STILL IN FTJCON CONDITIONAL
;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
>	;END CONDITIONAL ON FTJCON
IFN FTJCON!FT5UUO,<


;SUBROUTINE TO FORCE COMMAND
;ARGS	T1=JOB NUMBER
;	T2=INDEX OF FORCED COMMAND


COMFRC::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
	MOVE	T1,T2		;T1=COMMAND TO FORCE
	MOVSI	T2,LDBCMF##	;ANY FORCED COMMAND
IFN FTKL10,<
	CONO	PI,PIOFF##	;TEMPORARY TO GET AROUND PI SYSTEM BUS
	CONO	PI,SCNOFF##+PI.ON
>
IFE FTKL10,<
	CONO	PI,SCNOFF##	;TURN OF SCANNER PI
>
	TDNE	T2,(U)		;FOR THIS JOB ALREADY
	JRST	JCONDL		;YES
	PUSHJ	P,TTFORC##	;SET UP FORCED COMMAND
	CONO	PI,SCNON##	;SCANNER BACK ON
	POP	P,J		;RESTORE JOB
	PJRST	LPOPJ##		;RETURN

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

JCONDL:	CONO	PI,SCNON##	;SCANNER ON
JCONDM:	POP	P,J		;RESTORE JOB NUMER
	JRST	LPOPJ1##	;CAN'T ENTER - SKIP RETURN
>	;END CONDITIONAL ON FTJCON!FT5UUO
IFN FTJCON,<
;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,
	TLZ	M,NOCRLF!NOMESS	;RESET NOMESS
	TLO	M,TTYRNW	;SET FOR RESCHEDULE
	PUSHJ	P,INLMES	;TELL USER HE'S CONT
	ASCIZ	/Cont by opr/
	POPJ	P,
>	;END CONDITIONAL ON FTJCON
	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	COR3		;NO ARG. SPECIFIED, JUST TYPE FREE BLOCK LEFT
	JUMPL	P4,[MOVEI T1,RUNERR  ;RUNNING?
		JRST ERRMES]	;YES, LOOSE
	JUMPE	T1,COR0		;RELEASE DEVICES IF USER ASKING FOR 0 CORE
	TRNE	P4,JS.XO!JS.RUU	;SEE IF EXECUTE ONLY
	PJRST	ILLXO		;YES -- GO GIVE ERROR

IFN FT2REL,<	SKIPE	T2,TWOREG##	;SEE IF REENTRANT HARDWARE/SOFTWARE
	SKIPLE	T2,JBTSGN##(J)	;GET HI SEG # IF ANY
	JUMPG	T2,COR4		;YES - GO COMPUTE LO SEG SIZE
COR5:				;RETURN WITH HIGHEST REL. ADDR. OF LO SEG
>
IFN FTVM,<
	PUSH	P,T1
	SKIPN	R,JBTADR##(J)
	PUSHJ	P,GETMIN
	POP	P,T1
	JUMPN	R,COR5A		;IF DIDN'T GET CORE IN CORE,
	LDB	T2,IMGOUT##	; DID!WE GET CORE ON DSK?
	JUMPE	T2,COR2		;ERROR IF NONE
COR5A:
	JUMPE	R,DLYCM
>
	PUSHJ	P,CORE0##	;TRY TO ASSIGN CORE (NONE OR SPY)
	  JRST	COR2		;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##
IFN FT2REL,<
COR4:	HLRZ	T2,JBTADR##(T2)	;GET HI SEG SIZE
	SUBI	T1,1(T2)	;COMPUTE LO SEG SIZE
	JUMPGE	T1,COR5		;OK RETURN
	PUSHJ	P,INLMES	;TOO SMALL AN ARG.
ASCIZ	/?Try larger arg.
/
>
COR2:	MOVE	U,-1(P)		;RESTORE TTY LDB ADDRESS
	PUSHJ	P,PRQM		;TYPE ? FOR BATCH
	PUSHJ	P,COR3
	TLO	M,ERRFLG	;SET ERROR FLAG
	POPJ	P,
IFE FTVM,<
COR3:	PUSHJ	P,PRTSEG	;PRINT SIZE OF LOW SEG
IFN FT2REL,<
	PUSHJ	P,PRTHGH##	;PRINT SIZE OF HIGH SEG (+0 IF NONE)
				; NOTHING IF NOT 2 REG. MACHINE OR SOFTWARE
>
	PUSHJ	P,INLMES
	ASCIZ	"/"

IFE FTSWAP,<
	MOVE	T1,CORTAL##	;NO. OF FREE 1K BLOCKS
>
IFN FTSWAP,<
	PUSHJ	P,CORBND##	;PRINT MAX. NO. OF BLOCKS IN PHYSICAL CORE
	LSH	T1,W2PLSH##	;AVAILABLE TO A SINGLE USER(AS SET
				; BY MONGEN, ONCE OR SET)
IFN FTKI10!FTKL10,<
	ADDI	T1,UPMPSZ##
>
>
	PUSHJ	P,RADX10##	;PRINT NO. OF 1K BLOCKS AVAILABLE
	PUSHJ	P,PRPORK	;PRINT "P" OR "K"
IFE FTSWAP,<
	JSP	T1,CONMES
	ASCIZ	/ core
/
>
IFN FTSWAP,<
	PUSHJ	P,INLMES
	ASCIZ	/ core
vir. core left=/
	MOVE	T1,VIRTAL##	;PRINT AMOUNT OF FREE SWAP SPACE LEFT
	PUSHJ	P,RADX10##	;PRINT DECIMAL
	PUSHJ	P,PRPORK	;LABEL IT AS PAGES OR K
	PJRST	PCRLF		;CRLF
>
> ;END FTVM
IFN FTVM,<
;HERE TO GIVE CURRENT CORE SIZE FOR VM USER
COR3:	PUSHJ	P,FNDPDS##	;FIND PDB FOR JOB
	LDB	T1,[POINT 10,.PDMVL##(W),17]  ;GET MVPL
	JUMPE	T1,COR3B	;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  COR3A]; 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
COR3A:	HLRZ	T4,.PDCVL##(W)	;GET CVPL
	PUSHJ	P,PRCXPL	;PRINT THAT
	LDB	T4,[POINT 10,.PDMVL##(W),17]  ;GET MVPL
	SKIPN	T4
	MOVEI	T4,1000
	PUSHJ	P,PRMXPL	;PRINT THAT
	PUSHJ	P,INLMES	;ADD ) CRLF
	ASCIZ	/)
/
COR3B:	PUSHJ	P,INLMES
	ASCIZ	/Phys. mem. assigned /
	PUSHJ	P,PRTSEG	;PRINT LOWSEG SIZE
	SKIPLE	JBTSGN##(J)	;SKIP IF NO HISEG
	PUSHJ	P,PRTHGH##	;PRINT SIZE OF HISEG
	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



;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
> ;END FTVM
PRCORE:	PUSHJ	P,RADX10##	;PRINT IN DECIMAL
	PJRST	PRPORK		;GIVE UNITS

IFN FTLOGIN&FTACCT,<
;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
IFN FTWATCH,<

;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
	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,PRSPC		;ANOTHER SPACE
	PUSHJ	P,PRTSEG	;LOW SEG SIZE
	PUSHJ	P,PRTHGH##	;HIGH SEG SIZE
	PUSHJ	P,PRPORK	;PRINT P OR K
	PUSHJ	P,PRSPC		;ANOTHER SPACE
;STILL IN FTWATCH
	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
	CAMN	J,.C0JOB##	;ARE WE THE CURRENT JOB?
	PUSHJ	P,PRCHR		;YES--PRINT *
IFN FTMS,<
	PUSHJ	P,OTHCPU##	;ARE WE ON CPU1?
	  PUSHJ	P,PRCHR		;YES--PRINT *
>
	PUSHJ	P,PRSPC		;ANOTHER SPACE
	MOVSI	T2,'SW '	;ASSUME SWAPPED
	TLNE	P4,SWP		;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
	HRRZ	T1,JBTPC##(J)	;GET CURRENT PC
	PUSHJ	P,OCTPNT##	;PRINT PC IN OCTAL
IFN FTVM,<
	SKIPN	JBTADR##(J)
	JRST	USECM3
	MOVSI	T1,SWP		;BIT INDICATING SWAPPED OR BEING SWAPPED
	SKIPE	.UPMP+.UPVRT	;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,.UPMP+.UPVCT	;REPORT INCREMEMTAL IN WORKING SET FAULTS
	SUB	T1,.UPMP+.UPICT
	HRRZS	T1
	PUSHJ	P,RADX10##
	MOVEI	T1,[ASCIZ / NIW: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	MOVE	T1,.UPMP+.UPVCT	;REPORT INCREMENTAL NOT IN WORKING SET FAULTS
	SUB	T1,.UPMP+.UPICT
	HLRZS	T1
	PUSHJ	P,RADX10##
	MOVE	T1,.UPMP+.UPVCT	;UPDATE INCREMENTAL STATISTICS
	MOVEM	T1,.UPMP+.UPICT
	MOVEI	T1,[ASCIZ / VIRT CORE: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	LDB	T1,[POINT 9,JBTVRT##(J),35]
	PUSHJ	P,PRCORE	;REPORT LOW SEGMENT VIRTUAL CORE
	PUSHJ	P,PRTPLS	;PRINT A PLUS SIGN
	LDB	T1,[POINT 9,JBTVRT##(J),26]
	PUSHJ	P,PRCORE	;REPORT HIGH SEGMENT VIRTUAL CORE
	MOVEI	T1,[ASCIZ / PAGE RATE: /]
	PUSHJ	P,CONMES	;PRINT TEXT
	HLRZ	T3,JBTVRT##(J)	;GET THE JOBS PAGING INTERVAL
	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:>	;END FTVM
	HLRZ	F,JBTPC##(J)	;GET DDB ADDRESS
	JUMPE	F,USECM4	;ALL DONE IF NO DDB
	MOVE	T2,DEVIOS(F)
	MOVEI	T1,[ASCIZ "
INPUT"]
	TLNE	T2,IO
	MOVEI	T1,[ASCIZ "
OUTPUT"]
	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:	HRRZ	F,LDBDDB(U)	;GET DDB ADDRESS
	HLL	U,LDBDCH##(U)	;GET DEVICE BITS FOR TTY
	TLNE	U,LDLCOM##	;COMMAND LEVEL?
	TLZ	M,NOPER		;YES--PRINT A PERIOD
	TLNN	U,LDLOSU##	;CONTROL-O IN EFFECT
	TLZ	M,NOMESS	;NO--CLEAR NOMESS
	POPJ	P,0		;RETURN
>;END FTWATCH
;SUBROUTINE TO PRINT A FILESPEC FOR A DDB
;CALL WITH:
;	F = DDB ADDRESS
;	U = LDB ADDRESS (OR FIX COMTOA)
;	PUSHJ	P,PRTDDB
;	RETURN HERE
;
PGMFIL::HRRZ	F,USRJDA##
	JUMPE	F,CPOPJ##
	PUSHJ	P,INLMES
	ASCIZ	/ from /
PRTDDB::PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,DEVMOD(F)	;GET DEVICE TYPE BITS
	MOVE	T2,DEVNAM(F)	;GET DEVICE NAME
	HRRZ	T3,DEVUNI##(F)	;UDB POINTER
	JUMPE	T3,PRTDD0	;NO UNIT IF A KNOWN SEGMENT
	TLNE	P1,DVDSK	;IS THIS A DISK?
	MOVE	T2,UNILOG##(T3)	;YES--PRINT STR NAME
PRTDD0:	PUSHJ	P,PRNAME##	;PRINT IT
	MOVEI	T3,":"		;ADD A COLON
	PUSHJ	P,PRCHR		; ..
	TLNN	P1,DVDSK!DVDTA	;FILE AND EXT?
	POPJ	P,0		;NO--ALL DONE
	MOVE	T2,DEVFIL(F)	;GET FILE NAME
	JUMPE	T2,PRTDD3	;PUNT IF NO NAME
	HLRZ	T3,DEVEXT(F)	;IS THIS A UFD
	TLNE	P1,DVDSK	;ON DISK
	CAIE	T3,'UFD'
	JRST	PRTDD1		;NO
	PUSHJ	P,PRTPPN	;YES -- PRINT FILE NAME AS [M,N]
	JRST	PRTDD2		;AND NOT SIXBIT
PRTDD1:	PUSHJ	P,PRNAME##	;PRINT IT
PRTDD2:	PUSHJ	P,PRPER		;ADD IN A DOT
	HLLZ	T2,DEVEXT(F)	;GET EXTENSION
	PUSHJ	P,PRNAME##	;PRINT IT
PRTDD3:	TLNN	P1,DVDSK	;IS THIS THE DISK?
	POPJ	P,0		;NO--ALL DONE
	SKIPN	T2,DEVPPN(F)	;FALL INTO PRTPPN IF PPN
	POPJ	P,		;ELSE RETURN
PRTPPN:	PUSH	P,T2		;SAVE PPN
	MOVEI	T3,"["		;PRINT [
	PUSHJ	P,PRCHR
	HLRZ	T1,(P)
	PUSHJ	P,PRTDI8##	;PROJECT
	PUSHJ	P,PRCOM		;COMMA
	HRRZ	T1,(P)
	PUSHJ	P,PRTDI8##	;PROG
	MOVEI	T3,"]"
	PUSHJ	P,PRCHR
	JRST	T2POPJ##
	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
IFN FTEXE,<
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
>	;END OF IFN FTEXE

SAVEO:	TLO	S,NSRBIT	;OLD SAVE
	JRST	SSAVE1
SAVE:IFN FT2REL,<
	TLO	S,NSRBIT	;SET FLAG FOR NON-SHARABLE EXT(HGH)
>
SSAVE:
IFN FTEXE,<
	MOVE	T1,CNFST2##	;CHECK CONFIG BIT FOR EXE FILE SAVES
	TRNE	T1,1B21		;IF ON,...
	JRST	NSSAVE		;... PROCEED AS IN "NSAVE"
>
SSAVE1:
IFN FTEXE,<
	MOVSI	T1,(JS.EXE)	;GET EXE BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR IT JUST FOR SAFETY
SSAVE2:
>	;END OF IFN FTEXE
	HRRI	S,SAVJOB	;SETUP TO RUN SAVJOB (S CLEARED BEFORE CALL)
	JRST	SGSETD


; "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
IFN FTLOGIN,<	;AUTOMATIC LOGIN AFTER DSK REFRESH OR WHEN REFLAG SET


LOGREF:	PUSHJ	P,ISOPCT	;SKIP IF OPR OR CTY
	  JRST	CLOG2A		;NO, REGULAR LOGIN
LOGRF1:	MOVEM	T1,JBTPPN##(J)	;PRJ,PRG NRS. IN REFLAG
	PUSHJ	P,SETLOG##	;TURN ON JLOG

IFN FTPRV,<
	SETOM	JBTPRV##(J)	;GIVE OPERATOR ALL PRIVILEGES
>
	TLZ	M,-1		;CLEAR ALL FLAGS FOR COMRET
	SETZM	REFLAG##	;ONLY ONCE
	POPJ	P,

;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:	HRRZ	T2,U		;T2=ADDR OF LINE DATA BLOCK
	CAMN	T2,OPRLDB##	;SKIP IF NOT OPR
	JRST	CPOPJ1##	;YES, IT IS OPR
	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
>	;END CONDITIONAL ON FTLOGIN
	SUBTTL	COMMANDS WHICH RUN PROGRAMS

IFN FTCCLX&FTLOGIN,<
;FOR REMOTE USAGE OF FILE STORAGE SYSTEM
RECALL:	SKIPA	T1,[SIXBIT .UMOUNT.]	;RUN UMOUNT
>	;END CONDITIONAL OF FTCCLX&FTLOGIN
;IFE FTCCLX&FTLOGIN,<
;RECALL==COMERR
;>
IFN FTCCL,<

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

>
;"LOGIN" - LOGIN COMMAND

IFN FTLOGIN,<
LOGDET:	JSP	T1,ERRMES
IFN FTATTACH,<
	ASCIZ	/Please KJOB or DETACH
/
>
IFE FTATTACH,<
	ASCIZ	/please KJOB
/
>
CLOGIN:	TLNE	P4,JLOG		;FORCE USER TO LOGOUT BEFORE
	JRST	LOGDET		; LOGGING IN ANEW.
IFN FTSWAP,<
	MOVE	T1,VIRTAL##	;AMOUNT OF FREE VIRTUAL CORE LEFT
	CAIGE	T1,LOGSIZ##	;IS THERE AT LEAST 2K FOR LOGIN?
				; CUSTOMER CAN REDEFINE TO BE BIGGER THAN 2 
				; WITH MONGEN DIALOG
	JRST	COR2		;NO--GO TELL USER AMOUNT OF CORE LEFT
>
	SKIPE	T1,REFLAG##	;REFLAG SET NON-ZERO FOR AUTOMATIC LOGIN?
	JRST	LOGREF		;YES, LOG USER IN WITHOUT RUNNING CUSP
CLOG2A:	MOVSI	T1,LDLNEC##	;GO TO LOGIN, CLEAR ECHO
	IORM	T1,LDBDCH##(U)
	MOVEI	T1,NOECHO##	;ALSO IN DDB
	IORM	T1,DEVIOS(F)
	JRST	RUNAME
>
IFN FTLOGIN&FTACCT,<
CSESSN:	MOVE	P2,LOGTXT	;SIXBIT /LOGIN/
	JRST	RUNAME		;GO RUN IT
>
IFN FTQCOM,<
RUNQUE:	MOVE	P2,QUEUE	;SET CUSP NAME
	JRST	RUNAME		;GO RUN IT
>
IFN FTMIC,<
;HERE TO RUN MIC IN RESPONSE TO A WHOLE BUNCH OF COMMANDS
RUNMIC:	MOVSI	P2,'MIC'
	JRST	RUNAME

;HERE TO PROCESS I COMMAND TO AVOID CONFLICT WITH I FOR IF
RUN..I:	MOVE	P2,[SIXBIT /INITIA/]
	JRST	RUNAME

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

>
IFN FTNET,<
RUNNET:	MOVE	P2,[SIXBIT/NETLDR/]
	JRST	RUNAMC
>;END FTNET
IFN FTCCLX,<
RUNPIC:	MOVSI	P2,'PIP'	;SET NAME UNTIL FUDGE2 GET CCLS STUFF
>
RUNAMC:	MOVEI	P1,1		;SET CCL START
;RUNAME--COMMAND WHICH RUNS CUSP OF SAME NAME
RUNAME:
IFN	FTLOGIN,<	TLNE	P4,JLOG		;SEE IF LOGGED IN
	JRST	RUNAM1		;YES--PROCEED
	MOVE	T1,HELPPP##	;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)
>	;END CONDITIONAL ON FTLOGIN
RUNAM1:
IFN	FTSWAP,<
	PUSHJ	P,TTYATI##	;REATTACH TTY
	  JFCL
>
	MOVE	T1,P2		;GET CUSP NAME
; "R CUSPNAME CORE" - DOES "RUN SYS:CUSPNAME"


ARCOM:	MOVEI	T3,12		;MAKE SURE NO MORE ARGS SCANNED
	MOVEM	T3,TTCMCH##	; ..
	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:
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
	PUSHJ	P,GETMIN	;GET MINIMAL JOB AREA IN CORE OR DISK
IFN FTSET,<
	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
	PUSHJ	P,FNDPDB##	;SETUP W
	  JRST	RUNCM1		;NO PDB
	SKIPN	T1,.PDPGM##(W)	;PROGRAM FORCED?
	JRST	RUNCM1		;NO--CHARGE ON
	MOVEM	T1,JBTPRG##(J)
	MOVEI	T1,12
	MOVEM	T1,TTCMCH##
	MOVSI	T2,'SYS'
	MOVSI	P1,PHONLY	;INHIBIT LOG NAMES
RUNCM1:
>;END FTSET
	JUMPN	R,SGSET		;WAS CORE ASSIGNED IN MEMORY? IF YES, GO SCANARGS
IFN FTVM,<
	LDB	T1,IMGIN##	;NO CORE IN CORE, CORE ON THE DISK?
	JUMPE	T1,COR2		;COMPLAIN IF NONE
>
IFN FTSWAP,<
	SKIPLE	VIRTAL##	;NO, CORE LEFT ON DISK?
	JRST	DLYCM		;YES, DELAY COMMAND UNTIL IN CORE
>
	JRST	COR2		;NO, PRINT "0K CORE LEFT"
	SUBTTL	ASSIGN, DEASSIGN AND REASSIGN COMMANDS

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

ASSIGN:
IFN FTNET,<
	SKIPN	JBTADR##(J)	;ANY CORE ASSIGNED
	PUSHJ	P,GETMIN	;NO, GET SOME CORE
	JUMPE	R,DLYCM		;DELAY THE COMMAND
	PUSHJ	P,SAVCTX##	;SAVE THE CONTEXT OF THE JOB
>;END IFN FTNET
	PUSHJ	P,CTXDEV	;GET FIRST ARGUMENT TO T2 "DEV"
	JUMPE	T2,NOTENF	;NO ARGUMENT TYPED IF 0
IFN FTNET,<
	CAIN	T3,"_"		;CHECK FOR A NODE SPECIFICATION
	JRST	NETASG##	;YES, DO A NETWORK ASSIGN
ASSIGC::			;RE-ENTRY IF NODE SPEC IS LOCAL
				; OR WHEN THE DEVICE IS CONNECTED FROM
				; THE NETWORK VIA CONNECT
>	;END IFN FTNET
IFE FTDISK,<
	CAME	T2,[SIXBIT .SYS.] ;"ASSIGN SYS:DEV" USED TO CHANGE ASSIGNMENT
				; OF SYS. LEGAL ONLY FOR PROJECT 1 USER
	JRST	ASSG6		;NOT "SYS"
	PUSHJ	P,SETLGL	;SEE IF OPR OR [1,2]
	PUSHJ	P,CTEXT1	;GET NEW DEVICE NAME IN T2
	JUMPE	T2,NOTENF	;NO ARGUMENT TYPED IF 0
	SKIPL	STREQ##		;SYSTEM TAPE AVAILABLE?
	JRST	DLYCM1		;NO
	MOVEM	T2,SYSTAP##	;REDEFINE SYSTAP
	POPJ	P,
ASSG6:>
	MOVE	P4,T2		;SAVE DEVICE NAME
	PUSH	P,U		;SAVE TTY LDB
	MOVE	T1,T2		;DEVICE NAME IN T1
	PUSHJ	P,DEVPHY##	;DO SOMETHING (LOOK FOR TTY MAYBE)
	  JRST	ASSG3		;NOT A PHYSICAL NAME
	JRST	ASSG4		;A SPECIFIC PHYSICAL NAME
ASSG3:
IFN FTGSRC!FTNET,<
	SETZ	T3,		;ANY DEVICE EXIST
	PUSHJ	P,DVSRSP##
	  JRST	ASSFAL		;NO - ERROR
IFN FTSPL,<
	LDB	T3,DEYSPL##	;YES. SPOOL BIT
	SKIPE	DEVCHR(F)
	TDNE	T3,JBTSPL##(J)	;THIS DEV SPOOLED?
	JRST	ASSG3A		;YES, GO FAKE UP A DDB
>	;END CONDITIONAL ON FTSPL
	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	ASSG3		;IN THE UNUSUAL CASE THAT A HIGHER PRIORITY
				;INTERRUPT HAS TAKEN THE CHOSEN
				;DEVICE FROM US WE MUST TRY AGAIN
	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
;STILL IN CONDITIONAL ON FTGSRC!FTNET
;HERE WHEN A GENERIC ASSIGN FAILS
;USES 2 FLAGS IN LH OF P3
	ASF.SP==1B0	;SOMETHING HAS BEEN PRINTED
	ASF.MJ==1B1	;AT LEAST 1 ASSIGNED TO MY JOB

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
	HLRZ	F,DEVSER(F)	;NO--GET NEXT DEVICE
	JUMPN	F,ASSFA1	;CONTINUE IF END-OF-CHAIN
	TLO	M,ERRFLG	;FLAG ERROR
	JUMPL	P3,CRLF		;DONE IF MESSAGE PRINTED
	MOVEI	T1,ASSMS3	;ASSUME EVERYTHING RESTRICTED
	TLNE	P3,(ASF.MJ)	;ALL ASSIGNED TO OUT JOB
	MOVEI	T1,[ASCIZ "ASSIGNED TO YOUR JOB"]
	JRST	ASSER6		;PRINT MESSAGE 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,TPOPJ##	;CHECK FOR 0 JOB NUMBER
	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
>	;END CONDITIONAL ON FTGSRC!FTNET
IFE FTGSRC!FTNET,<
	MOVEI	T2,ASSCON	;SET UP ASSIGNED BY CONSOLE BIT
	HLRZ	F,DEVLST##	;PREPARE TO SEARCH DDB'S
ASSG0:	MOVE	T1,DEVNAM(F)	;GET DEVICE NAME FROM DDB
	CAMN	P4,T1		;SKIP IF NOT DEVICE REQUESTED
	JRST	ASSG4		;TRY TO ASSIGN IT
ASSG1:
IFE FTDISK,<
	CAMN	T1,SYSTAP##	;IS THIS THE SYSTEM DEVICE?
	JRST	ASSG2		;YES, KEEP LOOKING
>
	LDB	P3,PJOBN##	;OLD JOB # FOR THIS DEVICE
	TRZ	T1,-1		;COMPARE LEFT HALF ONLY (DTA,MTA)
	CAMN	T1,P4		;SKIP IF DOESN'T MATCH
	PUSHJ	P,ASSASG##	;MATCH, TRY TO ASSIGN DEVICE
	  JRST	ASSG2		;CAN'T ASSIGN, KEEP LOOKING
	JUMPE	P3,ASSFIN	;SUCCESS IF OLD JOB #0, DEVICE PREVIOUSLY UNASSIGNED
ASSG2:	HLRZ	F,DEVSER(F)	;STEP TO NEXT DEVICE
	JUMPN	F,ASSG0		;KEEP LOOKING IF ANOTHER DEVICE
	JRST	NOTDV1		;NO SUCH DEVICE
>	;END CONDITIONAL ON FTGSRC!FTNET
;PHYSICAL NAME MATCHES IF HERE

ASSG4:
IFN FTDISK,<
	MOVE	T2,DEVMOD(F)	;DEVMOD WORD
	TLNN	T2,DVDSK	;IS THIS A DISK?
	JRST	ASSG5		;NO.
	SETZM	DEVLOG(F)	;YES. CHECK FOR LOGICAL NAME
	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
	PUSH	P,T2		;SAVE LOG. NAME
	PUSHJ	P,DEVLG##	;SEE IF LOGICAL NAME IN USE
	JRST	ASSG4A		;NO
	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
>	;END FTDISK CONDITIONAL

ASSG5:	IFE	FTDISK<
	CAMN	T1,SYSTAP##	;IS THIS SYSTEM DEVICE
	JRST	ASSFIN		;YES, DO NOT ASSIGN
>
	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

ASSER3:	POP	P,T1		;CLEAN UP P.D. LIST
ASSER0:	MOVEM	U,0(P)		;DISCARD LOGICAL NAME VIA NEXT POP INSTR
ASSER1:	POP	P,U		;GET LDB ADDRESS
ASSER2:	LDB	T1,PJOBN##	;GET JOB NUMBER DEVICE ASSIGNED TO
	PUSH	P,T1		;SAVE JOB NO.
	MOVEI	T1,ASSMS2	;TYPE ERROR MESSAGE
	PUSHJ	P,ERRMES
	POP	P,T1		;GET JOB NO. BACK
	JRST	DECLF		;AND TYPE IT

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/
;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
IFN FTSPL,<
	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
ASSF1:	POP	P,F		;DDB OF THE NEWLY ASSIGNED DEVICE
ASSF2:	MOVEM	T1,DEVLOG(F)	;STORE IN DEVICE DATA BLOCK
	PUSHJ	P,SETDVL##
	MOVSI	T2,DVDIRIN	;CLEAR DIRECTORY IN CORE BIT
	ANDCAB	T2,DEVMOD(F)	;SETUP T2 WITH DEVICE CHARACTERISTICS FOR ASGHGH
IFN FT2REL,<
	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)
>
IFE FTSPL,<			;NO SPOOLING?
	MOVE	T2,DEVNAM(F)	;PHYSICAL DEVICE NAME
>
ASSF6:
IFN FTSPL,<			;SPOOLING?
	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
>				;END FTSPL
	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:
IFN FTNET,<
	SKIPN	JBTADR##(J)	;ANY CORE ASSIGNED
	PUSHJ	P,GETMIN	;NO, GET SOME CORE
	JUMPE	R,DLYCM		;DELAY THE COMMAND
	PUSHJ	P,SAVCTX##	;SAVE THE CONTEXT OF THE JOB
>	;END IFN FTNET
	PUSHJ	P,CTXDEV	;GET DEVICE NAME
	JUMPE	T2,DEASTY	;NO ARG. IF 0, DEASSIGN ALL BUT TTY
	MOVE	T1, T2		;DEVICE NAME
	PUSHJ	P, DEVSRG##	;SEARCH FOR DEVICE
	  JRST	DEAER1		;NOT FOUND
DEASI1:
	PUSHJ	P, DEASG	;FOUND, DEASSIGN IT
	  JRST	DEAER2		;NOT PREVIOUSLY ASSIGNED
	PUSHJ	P,TTYKLQ##	;KILL TTY DDB IF NOT NEEDED
	POPJ	P,		;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
/
IFE FTREASSIGN,<
REASSI=UUOERR##
>

IFN FTREASSIGN,<

;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,JOB##	;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
IFE FT5UUO,<
	PUSHJ	P,DEVSRC##	;SEARCH FOR DEVICE
>
IFN FT5UUO,<
	PUSHJ	P,DVCNSG##	;SEARCH FOR DEV
>
	  JRST	REASE2		;NOT FOUND
	PUSHJ	P,TTYKLQ##	;KILL TTY DDB IF NOT NEEDED
	NOSCHEDULE
IFN FTDISK,<
	TLZ	F,-1		;CLEAR SYSDEV
IFN FTSWAP,<
	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 FTGALAXY,<
	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
	TDNN	T1,DEVCHR(P)	;CONTROLLED?
	JRST	REAS1C		;NO
	MOVSI	T1,DVDATJ	;ALLOCATED BIT
	TDNN	T1,DEVCHR(F)	;ALLOCATED?
	JRST	REASE7		;NO CAN'T REASSIGN IT
>;END IFN FTGALAXY
REAS1C:	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,JOBFDV##(R)
	POP	P,T2
	POP	P,U
	POP	P,P1

	TLO	M,TTYRNC	;SET TTYRNC SO JOB WILL RUN
	PJSP	T2,MSTART##
	JSP	T1,MONSTR##
	PUSH	P,P1
	PUSH	P,U
	MOVE	J,JOB##
	HLRZ	T1,JOBFDV##(R)
	PUSH	P,T1
	HRRZ	F,JOBFDV##(R)
REASS4:
IFN FTMSGSER,<
	PUSHJ	P,MPXDIS##
	  SKIPA
	JRST	REASS3
>
	HRRZ	T4,DEVSER(F)
	HRRZM	F,JOBFDV##(R)
	MOVE	P1,USRHCU##
	PUSH	P,M		;SAVE M
REASS2:	MOVE	F,USRJDA##(P1)	;GET XWD UUO BITS,DDB ADDRESS
	HRRZ	T1,JOBFDV##(R)	;GET ADDR. OF DDB SAVED BY COMMAND
	DPB	P1,PUUOAC##	;SET CHANNEL # FOR CLOSE
	CAIN	T1,(F)		;IS CHOSEN DEVICE ON THHS CHANNEL?
	PUSHJ	P,RELEA1##	;YES, RELEASE DEVICE
	SOJGE	P1,REASS2
	POP	P,M		;RESTORE M
	MOVE	F,JOBFDV##(R)
	MOVE	J,JOB##		;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
IFN FTPHYO,<
	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)

IFN FTLOGIN,<
	PUSHJ	P,DEVLG##	;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,FSFPPN##	;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
	JRST	REASE6		;GIVE ERROR
REASS5:	POP	P,F		;RESTORE F
	PUSHJ	P,SETDVL##	;PUT IN NEW JOB NUMBER AND ADD NAME TO LOG NAME TABLE
IFN FTMTSET,<
	HRRI	T1,MTSIZ##+1	;GET DEFAULT MAGTAPE BLOCK SIZE
	HLL	T1,DEVMOD(F)	;
	TLNN	T1,DVMTA	;MAGTAPE?
	JRST	REASS8		;NO,IGNORE
	DPB	T1,PBUFSZ##
	SETZ	T1,
	DPB	T1,TDYDN1##	;RESET ANY USER DENSITY
	DPB	T1,PBUFRM##	;RESET MAX FRAME-COUNT
IFN FTDX10,<
	DPB	T1,PMTRTY##	;ENABLE AUTO ERROR-RETRY
>
>	;END CONDITIONAL ON FTMTSET
REASS8:	SCHEDULE
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
REASE4:	MOVEI	T1,0		;CLEAR C(AC)
	SOJA	M,PUTWDU##

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)
	AOJA	M,REASE4

REASE9:	JUMPN	T2,REASE3
IFN FTGALAXY,<
	SKIPE	%SIMDA##	;MDA RUNNING
	CAMN	J,MDAJOB##	;YES, IS MDA DOING THIS?
	JRST	REAS9E		;YES
	MOVSI	T1,DVCMDA	;CONTROL BIT
	TDNE	T1,DEVCHR(F)	;CONTROLLED?
	JRST	REASE3		;YES, LOSE
>;END IFN FTGALAXY
REAS9E:	MOVSI	T1,DEPRAS
	TDNN	T1,DEVSTA(F)
	JRST	REAS1B
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)
	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, DETACH AND EXCHANGE COMMANDS

IFN FTATTACH,<

;"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	NOTENF		;NOT A NUMBER OR NONE SPECIFIED
	JRST	DEVATT		;WANTS TO ATTACH A DEVICE
IFN FTLOGIN,<
	TLNE	P4,CMWB		;NO SKIP IF COMMAND WAS DELAYED TRYING FOR LOGIN
	JRST	ATTDLY		;WORK IS DONE, GO IMMEDIATELY TO LOGIN
>
	PUSHJ	P,GETJB1	;VALIDATE
IFN FTLOGIN,<
	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)

	SKIPN	P2,T2		;DID USER TYPE IN A PROJ,PROG # IN []'S?
	MOVE	P2,JBTPPN##(J)	;NO, ASSUME PROJ,PROG NUMBER FOR CURRENT JOB
				; SO USER CAN AVOID TYPEING PROJPROG NO. IF GOING
				; FROM 1 JOB TO ANOTHER UNDER SAME PROJ,PROG
	MOVEM	S,T2		;RESTORE
	CAME	P2,JBTPPN##(T2)	;IS THIS THE SAME PERSON WHO DETACHED FROM
				; THIS JOB NUMBER?
	JRST	ATT3		;NO-ERROR
IFN FTPTYUUO,<
	PUSH	P,U
	MOVE	S,F		;SAVE DDB ADDRESS
	MOVE	T3,T2		;SAVE TARGET JOB #
	MOVEI	T4,JOBMAX##	;UPPER LIMIT ON ITERATIONS
	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
>	;END CONDITIONAL ON FTPTYUUO
	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,FSFPPN##	;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
	JRST	ATTNL		;YES, CURRENT JOB DOESN'T REQUIRE LOGIN
	POP	P,J		;OLD JOB # 
	SKIPE	J		;SKIP IF NO JOB CURRENTLY
	PUSHJ	P,DETAC1	;DETACH CURRENT JOB
	SETZ	J,		;CLEAR J SO LOGIN COMMAND WILL ASSIGN A NEW JOB
ATTDLY:	POP	P,T2		;*** POP OFF WHAT WAS ON STACK (RETURN)
				;*** BECAUSE WILL SIMULATE LOGIN
	MOVE	U,(P)		;RESTORE LINE IN CASE IT WAS CLOBBERED
	MOVE	T2,LOGTXT	;MAKE IT LOOK LIKE A LOGIN COMMAND
	MOVEI	P3,DISP		;P3=LOC OF DISPATCH TABLE
	MOVE	P4,[XWD-DISPL,COMTAB]	;P4=LENGTH, LOC
	JRST	COM1A		;*** CALL LOGIN TO VALIDATE THE ATTACH
ATTNL:
>	;END CONDITIONAL ON FTLOGIN

IFE FTLOGIN,<
	PUSH	P,J
	MOVE	J,T2		;JOB NUMBER TO J
>
	PUSHJ	P,TTYATT##	;NO, ATTACH TTY
	  JRST	ATT2A		;ERROR CAN'T ATTACH
	EXCH	J,0(P)		;GET OLD JOB #
	SKIPE	J		;IS IT 0
	PUSHJ	P,DETMSG	;NO. TYPE MESSAGE
	POP	P,J		;RESTORE J
	JRST	TTYFND##	;ATTACHED. GO SET UP OUTP. BYTE PTR.
DEVATT:
IFN FTLOGI,<
	PUSHJ	P,SETLGL	;SEE IF OPR OR [1,2]
	  JRST	COMERA		;NOT LEGAL
>
	PUSHJ	P,CTXDEV	;GET DEVICE ARGUMENT
	  JFCL			;SHOULD NEVER RETURN
	MOVE	T1,T2		;YES-SET UP DEVICE NAME
	PUSHJ	P,DEVSRG##	;SEARCH FOR DEVICE
IFE FTDHIA&FTDUAL,<
	  JRST	NOTDEV		;NOT FOUND
>
IFN FTDHIA&FTDUAL,<
	  JRST	ATT7		;SEE IF DUAL-PORTED DISK
>
	MOVE	T2,DEVMOD(F)
IFN FTDHIA,<
	TLNE	T2,DVDSK	;DISK?
	JRST	ATT7		;YES, DO IT DIFFERENTLY
>
	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
IFN FTMTSET,<
	HRRI	T1,MTSIZ##+1	;GET DEFAULT MAGTAPE BLOCK SIZE
	HLL	T1,DEVMOD(F)
	TLNN	T1,DVMTA	;MAGTAPE?
	JRST	DEVAT1		;NO, IGNORE
	DPB	T1,PBUFSZ##	;RESTORE DEFAULT BLOCK SIZE
	SETZ	T1,
	DPB	T1,TDYDN1##	;CLEAR USER SET DEFAULT DENSITY
	DPB	T1,PBUFRM##	;CLEAR MAX FRAME-COUNT
IFN FTDX10,<
	DPB	T1,PMTRTY##	;ENABLE AUTO ERROR-RETRY
>
>	;END CONDITIONAL ON FTMTSET
DEVAT1:	POPJ	P,
ATT2A:	POP	P,J		;REMOVE JUNK FROM STACK
ATT2:	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 att to job
/

ATT6:	JSP	T1,ERRMES
	ASCIZ	/Wasn't det
/
IFN FTDHIA,<
;HERE TO ATTACH A DISK UNIT
ATT7:	PUSHJ	P,ATTDSK##	;TRY TO PUT IT ON-LINE
	  JRST	ATT8		;NOT DOWN OR NO SUCH UNIT
	  JRST	DLYCM		;NEED KONTROL, CANT GET IT RIGHT NOW
	POPJ	P,		;UNIT IS NOW UP

ATT8:	TLZE	U,400000	;IS IT A DSK?
	JRST	NOTDEV		;NO, "NOT A DEVICE"
	JRST	COMERA		;YES, "ATTACH DEV?"

;"XCHNGE UNIT UNIT  - EXCHANGES THE 2 UNITS
XCHUNI:	PUSHJ	P,XCHDSK##
	  JRST	COMERA		;SOME FLAVOR OF FOULUP
	POPJ	P,		;GOODNESS
>	;END FTDHIA
>	;END FTATTACH
;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
/
IFN FTATTACH,<

;"DETACH" - DETACH CONSOLE FROM JOB
;"DETACH DEVNAM" - DETACHES DEVICE FROM THE SYSTEM SOFTWAREWISE

DETACH:	PUSHJ	P,CTXDEV	;GET ARGUMENT
	JUMPE	T2,DETAC1	;ONLY "DET" TYPED
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,T2
IFN FTLOGI,<
	PUSHJ	P,SETLGL	;SEE IF OPR OR [1,2]
	  JRST	COMERA		;NOT LEGAL
>
	MOVE	T1,P1		;YES-SET UP DEVICE NAME
	PUSH	P,U		;SAVE ADDR OF TTY LDB
	PUSHJ	P,DEVPHY##	;SEARCH FOR DEVICE
IFE FTDHIA&FTDUAL,<
	  JRST	NOTDV1		;DEVICE NOT FOUND
>
IFN FTDHIA&FTDUAL,<
	JRST	DETAC3
>
	MOVE	T2,DEVMOD(F)	;CHECK TO SEE IF THIS IS DSK
IFN FTDHIA,<
	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.
	SKIPGE	DEVSPL(F)	;SPOOLED?
	  JRST	DETAC2		;YES
	MOVEI	T2,ASSCON	;FOUND-SET UP ASSIGNED BY CONSOLE
	PUSHJ	P,ASSASG##	;TRY TO ASSIGN
	JRST	ASSER5		;CAN'T ASSIGN
	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
	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,PRQM		;CAN'T DETACH A SPOOLED DEVICE
	MOVE	T2,DEVNAM(F)	;GET DEV NAME
	PUSHJ	P,PRNAME##	;TYPE IT
	PUSHJ	P,INLMES
	ASCIZ	/ IS SPOOLED/
	PJRST	UPOPJ##
IFN FTDHIA,<
;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
>
>	;CLOSE FTATTACH CONDITIONAL
	SUBTTL	DATASET CONNECT & SYSTEM START


IFN FTMODM!FTNET,<
;DATAPHONE RESPONSE COMMANDS PHONIED UP BY SCNSER ON DATAPHONE INTERRUPTS

IFN FTATTACH,<
BYECOM=DETACH			;UNTIL THIS IS CLEVERED UP

>
IFE FTATTACH,<BYECOM==CPOPJ##>
HELLO:	MOVE	P2,INITXT	;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	PRDTIM		;AND TIME OF DAY, CRLF.
	SUBTTL	DAYTIME COMMAND

;"DAYTIME" - PRINT TIME OF DAY


DAYTIM::
	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
	PUSHJ	P,RADX10##	;PRINT YEAR
	PUSHJ	P,PRSPC
PRDTIM:	MOVE	T1,TIME##	;PRINT TIME OF DAY

;SUBROUTINE TO PRINT TIME OF DAY, CRLF

PRTIME:	PUSHJ	P,PRTIM		;PRINT TIME AS HH:MM:SS(NO CRLF)
	PJRST	CRLF		;AND ADD CRLF


IFN FTBCOM,<
BAONLY:	JSP	T1,ERRMES
	ASCIZ	/Batch only
/
>
	SUBTTL	RUNTIME ROUTINE (TIME COMMAND)

IFN FTTIME,<
;"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,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:
IFE FTLOGIN,<
	MOVEI	T1,0		;GET SET TO CLEAR INCREMENTAL RUN TIME
>
IFN FTLOGIN,<
	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
	SKIPE	T1,W		;SKIP IF NO PDB - GIVE 0
	.MOVE	T1,.PDTTM##(W)	;GET TOTAL ACCUMULATED TIME
IFE FTKCT,<
	JRST	PRTIME		;PRINT IT, CRLF, AND RETURN
>
IFN FTKCT,<
	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
>				;END OF FTKCT
>				;END OF FTTIME

;SUBROUTINE TO PRINT SECONDS, CRLF

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

IFN FTTALK,<

;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
	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)
	JRST	SENDA		;DO A PSEUDO SEND ALL
SEND0:
>;END IFN FTNET
	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.
	PUSH	P,U		;SAVE LINE ADDRESS OF SENDER
	MOVE	T1,T2		;GET DEVICE NAME TO SEARCH FOR
	PUSHJ	P,TTYPHY##	;SEE IF IT'S A TTY
	  JRST SENDD		;NO. FAILURE.
SENDT:	HRRZ	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
IFN FTLOGI,<
	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:	PUSHJ	P,SENDHD	;SEND HEADER (CRLF, SEMI, TTY NAME)

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

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

;STILL IN FTTALK CONDITIONAL
;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,SENDF		;MUST BE ONE
	HRRZ	U,DDBLDB##(F)	;GET LDB ADDRESS
	JUMPN	U,SENDT		;AND GO SEND IT (IF NOT DETACHED)
SENDF:	POP	P,U		;OOPS. NO SUCH GUY. GET SENDER
	JSP	T1,ERRMES	;AND GIVE HIM THE BAD NEWS
	ASCIZ	/No such tty
/

SENDD:	HLRZ	T1,T1		;CHANGE TEXT FROM AAABBB
	HRLI	T1,'TTY'	; TO TTYAAA
	PUSHJ	P,TTYPHY##	;SEE IF THAT IS GOOD
	  JRST SENDF		;NO
	JRST	SENDT		;YES

SENDA:
IFN FTLOGI,<
	PUSHJ	P,SETLGL	;LEGAL? (OPR OR [1,2])
	  JRST	COMERA		;NOT LEGAL
>
	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,COMTOA##	;..
	MOVEI	T1,^D85		;PRESET QUOTA
	MOVEM	T1,SNDCNT	; SO WE DON'T WIPE
				; COMCON
	PUSHJ	P,SENDHD	;SEND THE HEADER
	MOVEI	T1,CCTYO##	;RESTORE
	MOVEM	T1,COMTOA##	;COMTOA

SENDA1:	MOVEI	P1,^D85

SENDA3:	PUSHJ	P,SNDTYI	;GET A CHAR FROM SENDER
	  JRST SENDAX		;NO MORE.
SENDA4:	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,LPLSAP##	;SEND ALL PENDING
	IDPB	T1,SNDTMP	;MAKE ASCIZ
	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:	HRRZ	U,LINTAB##+1(U) ;NO--GET NEXT LDB
	MOVE	T1,LDBDCH##(U)	;GET BITS
	PUSHJ	P,SHDSND	;SHOULD WE DO A SEND?
	  SKIPA			;YES
	JRST	SENDX2		;NO--TRY NEXT LINE
	MOVSI	T1,LPLSAP##	;SET UP FLAG
	MOVE	T2,SNDPTR	;POINTER
	CONO	PI,PIOFF##	;NO INTERRUPTS HERE
	SKIPN	LDBFLP##(U)	;POINTER SET UP?
	JRST	[MOVEM T2,LDBFLP##(U) ;NO-SET NEW POINTER
	  JRST	.+2]
	IORM	T1,LDBPAG##(U)	;YES--SET FLAG
	CONO	PI,PION##
	SKIPL	LDBDCH##(U)
	PUSHJ	P,TOPOKE##	;START TTY
	JRST	SENDX2		;LOOP FOR MORE

;STILL IN FTTALK CONDITIONAL
;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(P)		;GET SENDER'S LDB ADR
IFN  FTPTYU,<
	MOVE	T1,J		;SET UP T1 FOR FIRST TIME THROUGH
	MOVE	T3,U		;SAVE U IN CASE OF ERROR
	MOVEI	T4,^D20		;MAX DEPTH
IFN FTTLIM,<
SENDH1:	MOVE	T2,JBTLIM##(T1)	;IS SENDER A
	TLNE	T2,(JB.LBT)	;BATCH SUBJOB?
	JRST	SENDH3		;YES, NEVER SAY OPR
>	;END IFN FTTLIM
	PUSHJ	P,CTLJBU##	;FIND CONTROL JOB
	JUMPE	U,SENDH2	;DETACHED JOB
	JUMPL	T1,SENDH3	;FOUND A TTY
	MOVE	F,TTYTAB##(T1)	;CONTROLLING TTY
	HRRZ	U,DDBLDB##(F)	;HIS LINE
	SOJG	T4,SENDH1	;LOOK FOR NEXT PTY
SENDH2:	MOVE	U,T3		;RESTORE U
>	;END FTPTYU
SENDH3:
IFN FTPTYU,<
	PUSH	P,T3		;SAVE POINTER TO PTY LDB
>
	PUSHJ	P,TTYNAM##	;CONVERT TO REAL NAME IN SIXBIT
IFN FTPTYU,<
	POP	P,T3
>
	CAMN	U,OPRLDB##	;IS IT THE OPR?
	MOVSI	T2,(SIXBIT /OPR/)	;YES. SAY OPR INSTEAD
IFN FTPTYU,<
	MOVE	U,-1(P)		;RESTORE RECIPIENT
	MOVEM	T3,-1(P)	;PUT PTY POINTER ON STACK
>
IFE FTPTYU,<
	EXCH	U,-1(P)
>
	PUSHJ	P,PRNAME##	;OUTPUT THE NAME TO SENDEE
	PUSHJ	P,INLMES	;AND SPACER
	ASCIZ	/: - /		; ..
	POPJ	P,0		;RETURN FROM SENDHD

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,PRPER		;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,SHDND1	;ANY PARTICULAR NODE SPECIFIED
	CAME	W,JBTLOC##	;CHECK FOR THE LOCAL NODE
	JRST	SHDND0		;REMOTE LINE
	TRNN	T1,LDRREM##	;LOCAL NODE IS THIS A LOCAL LINE
	JRST	SHDND1		;YES, CONTINUE
SHDND0:	HLRZ	T4,LDBREM##(U)	;GET THE NODE ADDRESS OF REMOTE LINE
	JUMPE	T4,CPOPJ1##	;UNASSIGNED LINE
	HLRZ	T4,(T4)
	CAIE	T4,(W)		;IS THIS LINE ON THAT NODE
	JRST	CPOPJ1##	;NO, RETURN
SHDND1:
>;END IFN FTNET
	PUSH	P,T1		;SAVE T1
	LDB	T1,LDPLNO##	;GET LINE # INTO T1
	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 IN IT MODE
	TRNE	T4,I		;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
	POPJ	P,		;OK
	JRST	CPOPJ1##	;DON'T SEND TO GAGGED SLAVE


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

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


>	;END OF FTTALK CONDITIONAL
SNDBSY:	POP	P,T1		;REMOVE SENDEE FROM STACK
SNDBSI:	JSP	T1,ERRMES	;TYPE ERROR AND RETURN
	ASCIZ	/Busy
/

	SUBTTL	VERSION COMMAND & PRVERS SUBROUTINE

	IFN	FTVERS,<
;"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:
VERBTH::MOVE	T2,JBTNAM##(J)	;GET LOW NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	PUSHJ	P,PRSPC		;AND SPACE
	MOVE	T1,.JBVER##(R)	;GET LOW VERSION
IFN FT2REL,<
	PUSHJ	P,PRVERS	;PRINT IT
VERHGH::PUSHJ	P,SAVE2##
	SKIPG	P1,JBTSGN##(J)	;GET HI-SEG
	POPJ	P,		;NONE--ALL DONE
	PUSHJ	P,INLMES	;INDICATE HI-SEG
	ASCIZ	/ + /
IFN FTVM,<			;SEG NO. IN J
	EXCH	J,P1
	LDB	T1,JBYHSO##	;GET START PAGE OF SEG
	EXCH	J,P1		;RESTORE J
	LSH	T1,P2WLSH##	;START ADR
	PUSHJ	P,FLTST##	;IN CORE?
	  JRST	[CAME P2,VERTXT
		 POPJ P,
		 PJRST DAECOM]	;NO, HAVE DAEMON DO IT
>
	MOVE	P2,JBTADR##(P1)
	SKIPN	T2,JBTNAM##(P1)	;GET HI NAME
	MOVE	T2,.JBHNM##(P2)	;BLANK--USE SAVE
	SKIPE	T1,.JBHVR##(P2)	;GET HIGH VERSION
	CAMN	T1,.JBVER##(R)	; COMPARE TO LOW IF PRESENT
	CAME	T2,JBTNAM##(J)	;COMPARE TO LOW NAME
	JRST	VERHG1		;DIFFERENT--PRINT
	JRST	VERHG2
VERHG1:	PUSHJ	P,PRNAME##	;PRINT HI HAME
	PUSHJ	P,PRSPC		;AND SPACE
	MOVE	T1,.JBHVR##(P2)	;GET HI VERSION
	PUSHJ	P,PRVERS	;PRINT VERSION #
VERHG2:	MOVE	T1,JBTSTS##(P1)	;GET HISEG FLAGS
	TLNE	T1,SHRSEG	;SHARE SEG?
	POPJ	P,0		;YES
	PJSP	T1,CONMES	;NO--WARN USER
	ASCIZ	" Not sharable "
>	;END FT2REL,

;PRINT VERSION FROM T1		;FALL HERE

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

>	;END	FTVERS
	SUBTTL	EXAMINE AND DEPOSIT COMMAND

IFN FTEXAMINE,<

;"EXAMINE LOC" - LOOKS A 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	JOBEXM##(R)	;WAS PREVIOUS D OR E COMMAND, A D COMMAND?
	AOS	JOBEXM##(R)	;NO, IT WAS AN E, INCREMENT IN CASE HE TYPES NO ARG
ECOM1:	HRROS	JOBEXM##(R)	;YES, FLAG THAT E HAPPENED LAST(LH=-1)
	PUSHJ	P,OCTIN1	;GET OCTAL LOCATION
	SKIPA	T2,JOBEXM##(R)	;NONE SPECIFIED, USE LAST LOC OF D OR NEXT OF E
	JRST	COMERA		;ILLEGAL CHARACTER
	PUSHJ	P,DEAT		;CHECK FOR AC REFERENCE AND STORE JOBEXM
	HRR	M,T2		;IGNORE LH
IFN FTVM,<
	HRRZ	T1,T2		;ADDRESS BEING EXAMINED
	PUSHJ	P,FLTTC##	;WILL DOING AN EXAMINE CAUSE A PAGE FAULT?
	  JRST	ECOMA		;NO, BUT OUT OF BOUNDS
IFE FTDAEM,<
	  JRST	ECOMA		;YES, SAY OUT OF BOUNDS
>
IFN FTDAEM,<
	  PJRST	DAECOM		;YES, START UP DAEMON TO DO IT
>
	MOVEI	T1,0		;ASSUME ALLOCATED BUT ZERO PAGE
	CAIN	T4,PM.ZER	;PAGE ALLOCATED BUT ZERO?
	JRST	ECOM2		;YES, PRINT 0
>
	PUSHJ	P,GETWRD##	;GET WORD FROM LOW OR HIGH SEG
	JRST	ECOMA		;ERROR, OUT OF BOUNDS
ECOM2:	PUSH	P,T1		;SAVE CONTENTS OF LOC TO BE PRINTED
	HRRZ	T1,JOBEXM##(R)	;PRINT LOC BEING EXAMINED
	PUSHJ	P,OCTPNT##
	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	/	/
IFN FTKI10!FTKL10,<
	PUSHJ	P,CLRASA	;CLEAR AC'S IN SHADOW AREA FLAG
>
	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,SAVE1##
	PUSHJ	P,OCTIN1	;GET LH
	JRST	NOTENF		;NOT ENOUGH ARGUMENTS
	JRST	COMERA		;ILLEGAL CHARACTER
	HRLM	T2,S		;SAVE LH
	PUSHJ	P,OCTIN1	;GET RH
	JRST	NOTENF		;NOT ENOUGH ARGUMENTS
	JRST	COMERA		;ILLEGAL CHARACTER
	HRRM	T2,S		;SAVE RH
	MOVE	P1,JOBEXM##(R)	;WAS PREVIOUS D OR E AN E COMMAND?
			; LH=-1 IF E, LH=0 IF D
	JUMPL	P1,DCOM1	;JUMP IF YES
	AOS	P1,JOBEXM##(R)	;NO, INCREMENT IN CASE USER TYPED NOT THIRD ARG
			; FOR SUCCESSIVE D'S
DCOM1:
	HRRZS	JOBEXM##(R)	;FLAG THAT A D WAS DONE LAST(LH=0)
	PUSHJ	P,OCTIN1	;GET LOC
	SKIPA	T2,P1		;NOT SPECIFIED, USE LAST OF E OR NEXT OF D
	JRST	COMERA		;ILLEGAL CHARACTER
IFN FT2REL,<
	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
IFN FTVM,<
	HRRZ	T1,T2		;ADDRESS BEING DEPOSITED INTO
	PUSHJ	P,FLTTC##	;WILL DOING A DEPOSIT CAUSE A PAGE FAULT?
	  JRST	ECOMA		;NO, BUT OUT OF BOUNDS
IFE FTDAEM,<
	  JRST	ECOMA		;YES, SAY OUT OF BOUNDS
>
IFN FTDAEM,<
	  PJRST	DAECOM		;YES, START UP DAEMON TO DO IT
>

	CAIN	T4,PM.ZER	;PAGE ALLOCATED BUT ZERO?
	PJRST	CREPAG##	;YES, MAKE IT COME TO LIFE
>
	MOVE	T1,S		;SETUP UP ARG TO PUTWRD
	HRR	M,T2
	PUSHJ	P,PUTWRD##	;TRY TO STORE THE WORD IN THE USER'S AREA
	JRST	ECOMA		;OUT OF BOUNDS
IFN FTKA10,<
	POPJ	P,		;RETURN
>
IFN FTKI10!FTKL10,<
	PJRST	CLRASA		;CLEAR AC'S IN SHADOW AREA FLAG
>
DEAT:	TLZ	T2,-1		;CLEAR LH IN CASE THIS IS A SUCCESSIVE E WITH NO ARG
	HRRM	T2,JOBEXM##(R)	;STORE FOR NEXT TIME, DO NOT TOUCH LH(D OR E LAST)
				; YES, WAS JOB STOPPED IN USER MODE?
	CAIL	T2,20		;IS IT AN AC?
	POPJ	P,		;NO
	MOVE	T1,JOBPC##(R)
IFN FTKI10!FTKL10,<
	CAME	J,.C0JOB##	;CURRENT JOB?
	PUSHJ	P,SETASA	;NO, INDICATE AC'S ARE IN THE SHADOW AREA
	POPJ	P,		;RETURN
>
IFN FTKA10,<
	TLNE	T1,USRMOD	;USER MODE?
	ADDI	T2,20		;YES USER ACS ARE AT 20 INSTEAD OF 0
	POPJ	P,
>

ECOMA:
IFN FTKI10!FTKL10,<
	PUSHJ	P,CLRASA	;CLEAR AC'S IN SHADOW AREA FLAG
>
	JSP	T1,ERRMES	;OUT OF BOUNDS
OUTBMS::ASCIZ	/Out of bounds
/
>	;END CONDITIONAL ON FTEXAMINE
IFN FTLOGIN,<
;"SCHEDULE" TYPES OUT RH OF STATES, LEGAL FOR ALL.


SKEDUL:
IFE FTSET,<	;IF NO SET COMMAND GIVE A WAY TO SET STATES
	PUSHJ	P,OCTIN		;GET THE ARG IF ANY
	  JRST	SKED1		;NO ARG
	  JRST	COMERA		;BAD SYNTAX IN OCTAL NUMBER
	MOVE	P2,T2		;SAVE ARG IN PRESERVED AC
	PUSHJ	P,SETLGL	;SEE IF LEGAL FOR THIS USER
	  JRST COMERR
	HRRM	P2,STATES##	;STORE ARG IN RH OF STATES
	POPJ	P,
SKED1:
>	;END CONDITIONAL ON FTSET
	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:	REPEAT	1,<		;WAIT FOR NEXT BATCON AND 5.07
	MOVE	T3,TTCMCH##	;GET BREAK CHARACTER
	CAIE	T3,12		;WAS BREAK A LINE-FEED?
	PJRST	COMERA		;NO--ERROR
>
	POPJ	P,		;YES--NULL COMMAND

	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:	PUSHJ	P,SAVE2##	;SAVE P1
	PUSH	P,U		;SAVE TYPING TTY'S LDB
	HRRZ	P1,U		;ASSUME HIS WILL BE OBJECT
	PUSHJ	P,CTEXT1	;GET AN ARGUMENT
	CAIE	T3,":"		;DEVICE?
	JRST	TTYC1		;NO. A WORD.
	MOVE	T1,T2		;GET THE DEVICE.
	PUSHJ	P,GETDDB##	;AND FIND OUT WHERE IT IS
	  JRST TTYCE		;NOT A TTY. ERROR.
	PUSHJ	P,TTYKLQ##	;KILL TTY DDB IF NOT NEEDED
	HRRZ	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
	HRRZ	P2,U		;SEE IF THIS IS OPR
	PUSHJ	P,SETLGL	;SKIP IF OPR
	CAIN	P2,(P1)		;HIS OWN TTY?
	JRST	TTYCL		;YES. OK.
	LDB	T2,PJOBN##	;NO. WHO OWNS THE TTY IN QUESTION
	MOVE	T1,LDBDCH##(P1)	;AND IS IT SLAVED?
	CAIN	T2,(J)
	TLNN	T1,LDLSLV##	;CHECK THESE TWO CRITERIA
	JRST	TTYCE		;NOT SLAVED BY TYPER. ERROR.
TTYCL:	MOVE	U,0(P)		;RESET LINE TO TYPER
	PUSHJ	P,SKIPS1	;SEE IF ANY MORE ON LINE.
IFN	FTCAFE,<
	  JRST	[MOVE   U,P1	;POINT TO TARGET
		 MOVEI  T1,ISRCHP## ;CHANGE HARDWARE PARAMETERS
		 PUSHJ  P,@LDBISR##(U) ;UPDATE THEM NOW
		 JRST   UPOPJ##];RESTORE U AND RETURN
> ;END IFN FTCAFE
IFE FTCAFE,<
	JRST	UPOPJ##		;RESTORE U AND RETURN
> ;END IFE FTCAFE
	PUSHJ	P,CTEXT1	;YES. SEE WHAT IT IS
TTYC1:	MOVE	T1,[-TTCWDN,,TTCWDT]	;POINT TO NAMES
	PUSHJ	P,FNDNAM	;FIND ABBREV.
	  JRST	TTYCE		;ERROR
	HRRZ	T2,TTCWDD(T1)	;GET RESULT
	PUSHJ	P,(T2)		;DISPATCH TO ROUTINE
	  JRST	TTYCE		;ERROR
	JRST	TTYCL		;LOOK FOR MORE
TTYCE:	POP	P,U		;RESTORE LINE FROM STACK
	JRST	COMERR		;AND GO COMPLAIN.

;TABLE FOR SET TTY COMMAND
;MACRO HAS 4 ARGUMENTS:
;	NAME  -  WORD USED IN TTY COMMAND
;	DISP  -  DISPATCH LOCATION TO PROCESS WORD
;	OFST  -  OFSET WITHIN LDB WHERE ANSWER IS STORED
;	DATA  -  18 BITS OF DATA USED BY PROCESSING ROUTINE

	DEFINE	TTNAME,<
	TT	ALTMODE,TTCCLR,LDBPAG##,LPLALT##
IFN FTTBLK,<
	TT	BLANKS,TTCCLR,LDBPAG##,LPLBLK##
> ;END FTTBLK
	TT	COPY,TTCESC,"_","^"
	TT	CRLF,TTCCLR,LDBDCH##,LDLNFC##
IFN FT2741!FTNET,<
	TT	DEBREAK,TTCSET,LDBISR##,LILDBK##
> ;END FT2741!FTNET
	TT	ECHO,TTCCLR,LDBDCH##,LDLLCP##
IFN FTCAFE&FT2741!FTNET,<
	TT	ELEMENT,TTCELE,0,0
> ;END FTCAFE&FT2741!FTNET
	TT	FILL,TTCNUM,LDPFLC##,3
	TT	FORM,TTCSET,LDBDCH##,LDLFRM##
	TT	GAG,TTCCLR,LDBBY2##,L2LSND##
	TT	HOLD,TTCESC,"\",<"[">
IFN FTCAFE,<
	TT	IGNORE,TTCIGN,0,0
> ;END FTCAFE
	TT	LC,TTCCLR,LDBDCH##,LDLLCT##
	TT	NO,TTCNO,0,0
IFN FTTPAG,<
	TT	PAGE,TTCPAG,LDPPSZ##,77
> ;END FTTPAG
	TT	RTCOMP,TTCSET,LDBISR##,LILRTC##
	TT	SLAVE,TTCSLV,LDBDCH##,LDLSLV##
IFN FTCAFE!FTNET,<
	TT	SPEED,TTCSPD,0,0
> ;END FTCAFE!FTNET
	TT	TABS,TTCSET,LDBDCH##,LDLTAB##
	TT	TAPE,TTCSET,LDBBY2##,L2LTAP##
IFN FTCAFE,<
IFN FT2741,<
	TT	TIDY,TTCSET,LDBISR##,LILTDY##
>> ;END FTCAFE AND FT2741
	TT	UC,TTCSET,LDBDCH##,LDLLCT##
	TT	WIDTH,TTCNUM,LDPWID##,<^D17*^O1000+^D200>
IFN FTPATT,<
	TT	.PATCH,TTYCL,0,0
> ;END FTPATT
> ;END TTNAME MACRO
	XALL
	DEFINE	TT(NAME,DISP,OFST,DATA),<
	<SIXBIT	/NAME/>
	>
	$LOW
TTCWDT::TTNAME
TTCWDN==.-TTCWDT
TTCMXL==:<TTCWDN-1>B26
	$HIGH
$HIGH
	DEFINE	TT(WORD,DISP,OFST,DATA)<
	XWD	OFST,DISP
>

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

TTCDAT:	TTNAME



	SALL
;HERE TO PROCESS 'TTY SPEED'
IFN FTCAFE!FTNET,<
TTCSPD:	PUSHJ	P,NUMARG	;GO GET THE NUMBER
	  POPJ	P,0		;MUST BE ONE
	PUSHJ	P,TTCSP1	;FIND SPEED IN TABLE
	  POPJ	P,0		;NO THERE
	EXCH	U,P1		;FLIP AROUND POINTERS
	DPB	P2,LDPRSP##	;SET RECEIVE SPEED
	EXCH	U,P1		;GET ACS BACK
	MOVE	P2,T2		;SAVE OLD ANSWER
	PUSHJ	P,NUMARG	;GET NEW NUMBER
	  MOVE	T2,P2		;RESTORE LAST VALUE
	PUSHJ	P,TTCSP1	;FIND SPEED IN TABLE
	  POPJ	P,0		;COMMAND ERROR IF NOT THERE
	MOVE	U,P1		;SETUP U
	DPB	P2,LDPTSP##	;TRANSMIT SPEED
	JRST	CPOPJ1##	;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
	RADIX	10
LSPTAB::	EXP	0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,1,2
LSPLEN==.-LSPTAB
	RADIX	8

;STILL IN FTCAFE!FTNET
;HERE TO PROCESS 'TTY ELEMENT'
SET987:	SKIPA	T2,[EXP ^D987]
SET988:	MOVEI	T2,^D988
	MOVE	P1,U
	JRST	TTCEL1
TTCELE:	PUSHJ	P,NUMARG	;GO GET THE NUMBER
	  POPJ	P,0		;MUST BE ONE
TTCEL1:	MOVE	T3,T2		;SETUP CORRECT AC
IFN FTNET,<
	MOVEI	T1,LDRREM##	;GET REMOTE BIT
	TDNE	T1,LDBDCH##(P1)	;CHECK IT
	JRST	TTCEL2		;YES, CONTINUE
>
	SKIPL	LDBISR##(P1)	;IS THIS A DC76 LINE?
	JRST	CPOPJ1##	;NO--MAKE A NO OP
IFN FTNET,<
TTCEL2:
>
	EXCH	U,P1		;D76ELE USES LDPLNO
	MOVEI	T1,ISRELE##	;FUNCTION
	PUSHJ	P,@LDBISR(U)	;CALL ISR
	  SOS	(P)		;PASS ON NON-SKIP
	EXCH	P1,U		;RESTORE AC'S
	JRST	CPOPJ1##	;RETURN

;STILL IN FTCAFE!FTNET
;HERE TO PROCESS TTY IGNORE
TTCIGN:	MOVE	U,P1		;COPY LDB ADDRESS
	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,-1		;CLEAR YES/NO FLAG
	JRST	CPOPJ1##	;RETURN

> ;END FTCAFE!FTNET
;HERE TO DO 'TTY PAGE'
IFN FTTPAG,<
TTCPAG:	PUSH	P,T1		;SAVE INDEX
	MOVEI	T1,LDBPAG##(P1)	;ADDRESS OF WORD
	MOVSI	P2,LPLPAG##	;PAGE BIT
	PUSHJ	P,TTCST1	;GO SET OR CLEAR IT
	  JFCL			;CAN NOT MISS
	POP	P,T1		;RESTORE INDEX
	PJRST	TTCNUM		;AND PROCESS THE NUMBER
> ;END FTTPAG

;HERE TO DO 'TTY SLAVE'
TTCSLV:	PUSH	P,T1		;SLAVE INDEX
	PUSH	P,U		;CLEAR
	MOVEI	U,(P1)		;TARGET'S INPUT
	PUSHJ	P,TSETBI	;CLEAR INPUT BUFFER
	POP	P,U
	POP	P,T1		;RESTORE INDEX
	SKIPL	P1		;WANT TO CLEAR?
	JRST	TTCSET		;NO--LEAVE LDLCOM ALONE
	MOVSI	P2,LDLCOM##	;YES--SET LINE INTO
	IORM	P2,LDBDCH##(P1)	; COMMAND MODE
	PJRST	TTCSET		;GO SET SLAVE BIT

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

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

;HERE TO SEND AN ESCAPE SEQUENCE
TTCESC:	PUSH	P,T1		;SAVE T1
	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		;RESETORE INDEX
	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
	EXCH	U,P1
	DPB	T2,(T1)		;STORE
	EXCH	U,P1
	JRST	CPOPJ1##	;SKIP RETURN
	SUBTTL	FINISH AND CLOSE COMMANDS

IFN FTFINISH,<
; "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,JOBFDV##(R)	;SAE WHICH COMMAND IN JOBDAT
	PUSHJ	P,CTXDEV	;GET DEVICE NAME
	JUMPE	T2,FINALL	;ALL DEVICES IF NO OTHER ARG
IFE FTDISK,<
	SKIPA	T1,T2		;SEARCH FOR SIXBIT DEVICE NAME
>>	;END CONDITIONAL ON FTFINISH
IFE FTDISK,<
CFINS:	MOVE	T1,SYSTAP##	;HERE ON CONTROL C ON SYSTEM TAPE USER
				; DO A FINISH SYS COMMAND FOR HIM
>
IFN FTDISK&FTFINISH,<
	MOVE	T1,T2
>
IFN FTFINISH!<FTDISK+1>,<
	PUSH	P,U		;SAVE ADDR OF TTY LDB
	PUSHJ	P,DEVSRG##
	  JRST	NOTDV1		;PRINT NOT A DEVICE
	HRRM	F,JOBFDV##(R)	;STORE DDB ADR. IN JOB DATA AREA
	POP	P,U		;RESTORE ADDR OF TTY LDB
	MOVEI	T1,ASSPRG	;SEE IF
	TDNN	T1,DEVMOD(F)	; OPEN
	JRST	[SKIPGE	JOBFDV##(R)	;SEE IF FIN
		JRST	.+1	;NO -- DO IT ANYWAY
		TLZ	M,NOPER!NOCRLF!TTYRNU
		PJRST	DEASI1]	;GO DEASSIGN
	PJSP	T2,MSTART##	;SETUP MONITOR JOB AND RETURN
				; RETURN HERE AT UUO LEVEL WHEN SCHEDULED
	JSP	T1,MONSTR##	;SETUP ACS,R,P
	HRRZ	F,JOBFDV##(R)	; AND R
	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
	MOVE	P1,USRHCU##	;HIGHEST USER CHANNEL IN USE
FDVI:	HRRZ	F,USRJDA##(P1)	;GET NEXT DEVICE
	HRRZ	T1,JOBFDV(R)	;GET DEV TO RELEASE
	CAIE	F,(T1)		;IS THIS WHAT WE WANT TO CLOSE?
	JRST	FDV3		;NO, CONTINUE
IFN FTVM,<
	PUSHJ	P,WAIT1##	;WAIT FOR INACTIVE DEVICE
>
	MOVSI	T2,DVTTY	;SET UP TTY BIT
IFN FTVM,<
	SKIPN	.UPMP+.UPVRT	;IF VIRTUAL JOB
>
	TDNE	T2,DEVMOD(F)	;OR IF I/O TO A TTY
	SETZM	DEVBUF(F)	;THEN FORGET BUFFERS
IFN FTVM,<
	SKIPN	.UPMP+.UPVRT	;IF VIRTUAL JOB
	JRST	FDV2		;NOT THE CASE
	MOVSI	T3,R		;SET UP
	PUSHJ	P,RTIEVM##	;TELL MONITOR ABOUT BUFFERS
	PUSHJ	P,RTOEVM##
FDV2:>
	MOVSI	M,(CLOSE)	;ASSUME CLOSE
	SKIPL	JOBFDV(R)	;RIGHT?
	MOVSI	M,(RELEAS)	;NO, FIN COMMAND
	DPB	P1,PUUOAC##	;KPUT CHANNEL IN AC FIELD
	XCT	M
FDV3:	SOJGE	P1,FDVI
	MOVE	J,JOB##		;GET JOB NUMBER
	SKIPL	F,JOBFDV##(R)	;RESET F, SKIP IF NOT FIN
	PUSHJ	P,DEASG		;DEASSIGN DEVICE IF FIN
	  POPJ	P,		;IGNORE IF NOT ASSIGNED BY CONSOLE
	POPJ	P,
>	;END CONDITIONAL ON FTFINISH!<FTDISK+1>


IFN FTFINISH,<
;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,JOBFDV##(R)	;SAVE DDB ADDR IN CASE CFIN IS CALLED
	CAMN	T1,JOB##	;THIS JOB OWN DEVICE?
	PUSHJ	P,CFIN		;YES, FIN (OR CLOSE) IT
	HLRZ	F,DEVSER(F)	;SKIP TO NEXT DDB IN CHAIN
	JUMPN	F,FINAL1	;TEST IT IF NON-0
>	;END CONDITIONAL ON FTFINISH
IFN FTFINISH!<FTDISK+1>,<
CFINIX:	PUSHJ	P,TTYFNU##	;DONE. FIND TTY LINE FOR JOB
	PJRST	HOLD##		;STOP JOB
>
IFN FTTIME, <
;"RESOURCES" - PRINT OUT AVAILABLE DEVICES AND FREE BLOCKS ON THE DISK


FREDEV:

	PUSHJ	P,SAVE2##	;SAVE P1=P2
IFN FTDISK, <
	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?
	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:	IFE	FTDISK,<
	CAMN	J,STUSER##	;SYSTEM TAPE USER?
	JRST	DLYCM1		;YES. DELAY,BUT DO NOT STOP JOB
>
ACTCHK:	JUMPE	R,ACTCH1	;DOES JOB HAVE CORE IN MEMORY?
IFN FTMS&FTKL10,<
	PUSHJ	P,CKCP1C##	;MAKE SURE CPU1'S CACHE HAS BEEN
				; SGPET FOR THIS JOB
>
	  PUSHJ	P,ANYACT##	;YES, ARE DEVICES ACTIVE?
	  JRST	DLYCM		;YES, DELAY COMMAND.
ACTCH1:	HRRZ	F,LDBDDB##(U)	;RESTORE F
	POPJ	P,

;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:	POP	P,T1
IFN FTRSP,<	TLNE	M,TTYRNC!TTYRNU	;WILL THIS COMMAND CAUSE JOB TO BE RUN?
	PUSHJ	P,SETRSP##	; RESPONSE, IF NOT ALREADY SET
>
	POP	P,T2		;TTY LINE #
	AOS	LINSAV##	;INCR. COMMAND POINTER SO NEXT CALL
				; BY COMMAND DECODER CALL START SCANNING
				; WITH LINE AFTER DELAYED COMMAND.
				;THEN EXIT FROM COMMAND DECODER.
	POPJ	P,

	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.

CTEX1:	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"
	JRST	CPOPJ1##	;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 TTCMCH



;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
	MOVE	T3,TTCMCH##	;GET CURRENT CHARACTER
	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
	MOVEM	T3,TTCMCH##	;REMEMBER IN CASE DIFFERENT
	POPJ	P,
	SUBTTL	SUBROUTINES -- 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,TTCMCA##	;SAVE ERROR POSITION IN SCAN ON 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
	MOVE	T1,TTCMCA##	;PASS BAD CHAR YET?
	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
	PUSHJ	P,PRQM		;APPEND ? TO ERRONEOUS WORD
	TLO	M,ERRFLG	;SET ERROR FLAG
	PJRST	CRLF		;ADD CRLF

;ROUTINE TO PRINT ?DEVICE NAME

PRNAMQ:	PUSHJ	P,PRQM
	TLO	M,ERRFLG	;SET ERROR FLAG
	PJRST	PRNAME##
IFE FTCCLX&FTLOGIN,<
RECALL==COMERR
>
;ROUTINE TO PRINT A COMMAND ERROR MESSAGE
;SAME CALL AS CONMES

ERRMES::PUSHJ	P,PRQM

ERRMSN:	TLO	M,ERRFLG	;INDICATE AN ERROR
	TDZA	J,J		;CLEAR JOB NUMBER TO INDICATE ERROR
				; SKIP INTO CONMES ROUTINE

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


PCRLF::				; COMERR SKIPS TO HERE(SEE ABOVE)
CRLF::	MOVEI	T1,[ASCIZ /
/]

;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,440700	;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
	JRST	1(T1)		;RETURN TO NEXT LOC AFTER MESSAGE

;ROUTINE TO TYPE COMMA
;PRESERVES T1
PRCOM::	MOVEI	T3,","
	PJRST	PRCHR
;ROUTINE TO APPEND ? TO ERROR MESSAGE
;CALL	PUSHJ P,PRQM
;	RETURN
PRQM::	MOVEI	T3,"?"
PRCHR:	PUSH	P,T1
	PUSHJ	P,COMTYO##
	PJRST	TPOPJ##

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

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

;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::JSP	T1,ERRMES

ASCIZ /Too few arguments
/

;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 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"
	CAIE	T3,"-"		;IF HYPHEN
	CAIN	T3,"("		;OR L. PAREN.
	MOVEI	T3,0		;SET E.O. LINE
	CAILE	T3,40		;AN ARG. WAS TYPED, DELIMITER OKAY?
	JRST	COMERP		;BAD DELIMITER
	LSH	T2,K2WLSH
	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:
IFN FTKA10,<
	MOVEI	T3,"K"		;ASSUME "K"
>
IFN FTKI10!FTKL10,<
	MOVEI	T3,"P"		;KI10, TELL NUMBER OF PAGES
>
	PJRST	PRCHR		;PRINT "P" OR "K"
;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:	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
	JRST	IPOPJ1##
	TRNE	T2,ASSCON	;IS DEVICE ASSIGNED BY CONSOLE?
	AOS	-1(P)		;YES, DO OK RETURN
IFN FT2REL,<
	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
>
	MOVE	T2,DEVMOD(F)	;IF IT IS A TTY
IFE FTNUL,<
	TLNN	T2,DVTTY	;THAT MAY BE AN
	JRST	DEASG2		;ORPHAN - NOT
>
IFN FTNUL,<
	TLNE	T2,DVTTY	;IF NOT A TTY,
	PUSHJ	P,NULTST##	; OR THE NUL DEVICE,
	  JRST	DEASG2		; DON'T CLEAR ASSPRG
>
	TLNE	T2,TTYATC	;CONTROLLING
	JRST	DEASG2		;AND NOT
	SKIPN	DDBLDB(F)	;ATTACHED
	SKIPA	T2,[ASSCON!ASSPRG]  ;THEN
				;CLEAR INIT ALSO
DEASG2:	MOVEI	T2,ASSCON	;SETUP ASSIGNED BE 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
	HLRZ	F,DEVSER(F)
	JUMPN	F,DEA1
	PJRST	FPOPJ##		;RESTORE TTY DDB ADDRESS
;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:	PUSH	P,TTCMCA##	;SAVE POINTERS
	PUSH	P,TTCMCH##	; ..
	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,TTCMCH##	;RESTORE POINTERS 
	POP	P,TTCMCA##	; ON ANY ERROR
	POPJ	P,0		; AND GIVE FAIL RETURN
IFN FTVM!FTMONL!FTMOFFL!FTSET,<
;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,TTCMCA##	;SAVE CURSOR LOC
	PUSH	P,TTCMCH##
	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
>	;END FTVM
;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 FOCED
	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, FIVE 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.
	POPJ	P,CPOPJ1##	;NO GOOD. GIVE "BAD CHARACTER RETURN"
IFN FTLOGIN,<
;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.......

PP1:	PUSHJ	P,OCTIN		;GET FIRST ARG.-PROJ. NO.
	  JRST	[CAIN T3,"-"	;SEE IF [-]
		JRST	[PUSHJ P,COMTYS	;YES--SKIP -
		 JRST	PP1A]	;THEN RETURN 0
		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:	CAIE	T3,">"		;IS 2741 ENDING?
	CAIN	T3,"]"		;IS USUAL ENDING A "]"?
	PUSHJ	P,COMTYS	;YES, SKIP IT SO FINAL ] IS OPTIONAL
	JUMPL	P1,PP3		;BOMB USER IF INVALID
PP2:	MOVE	T2,P1		;RESULT IN T2
	POP	P,P1
	POPJ	P,		;RETURN TO CALL
PP3:	POP	P,P1
	PJRST	COMERP		;LOSE
>				;END FTLOGIN CONDITIONAL
;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)


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::
IFE FTVM,<
IFN FTSWAP,<
	LDB	T2,IMGIN##	;SIZE WHEN NEXT SWAPPED IN(IN K)
	JUMPN	T2,SEGSZ1	;0 MEANS NOT SWAPPED OUT
>
	HLRZ	T2,JBTADR##(J)	;SIZE-1 LOW LOW OR HIGH SEG IN WORDS IN CORE
	JUMPE	T2,CPOPJ##	;IS IT IN CORE?
	LSH	T2,W2PLSH##	;YES, CONVERT TO #K-1
	AOJA	T2,SEGSZ1	;ADD 1 AND RETURN NUMBER OF K
>
IFN FTVM,<
	CAILE	J,JOBMAX##	;LOW SEGMENT?
	JRST	SEGSZ0		;NO, GET HI SEG SIZE
	SKIPLE	T2,JBTSGN##(J)	;IS THERE A REAL HI SEG?
	TLNE	T2,SHRSEG	;YES, IS IT NON-SHARABLE?
	JRST	SEGSZ0		;NO
	HLRZ	T2,JBTSWP##(T2)
	MOVNS	T2		;HI SEG SIZE
	ADD	T2,JBTSWP##(J)	;INCLUDED IN LOW SEG SIZE
	ANDI	T2,777		;CLEAR JUNK
	JRST	SEGSZ2		;ADD UPMP SIZE AND RETURN
SEGSZ0:	LDB	T2,IMGIN##	;SEGMENT SIZE
	JUMPN	T2,SEGSZ1	;GO IF NON-ZERO
	HLRZ	T2,JBTSWP##(J)	;MAYBE A NON-SHARABLE HI SEG
	JUMPE	T2,CPOPJ##	;RETURN IF NO CORE
>
IFN FTKI10!FTKL10,<
SEGSZ1:	CAIG	J,JOBMAX##	;IS THIS A LOW SEGMENT?
SEGSZ2:	ADDI	T2,UPMPSZ##	;YES ACCOUNT FOR THE SIZE OF THE UPMP
	POPJ	P,
>

IFN FTKA10,<
SEGSZ1==CPOPJ##
>

;ROUTINE TO ASSIGN A MINIMAL CORE AREA(2000 WORDS)
;CALLED FROM CORE,KJOB, AND RUN COMMANDS
;THIS ROUTINE PRESERVES INPUT BYTE POINTER IN T1
;CALL:	PUSHJ P,GETMIN
;	RETURN R=0 IF UNSUCCESSFUL OR CORE ASSIGNED ON DISK


GETMIN::PUSH	P,U		;SAVE TTY LDB ADDRESS
	PUSH	P,T2		;SAVE DEVICE NAME(GET)
	PUSH	P,S		;SAVE DISPATCH ADDRESS(ANYACT USES S)
IFN FT2REL,<
	PUSHJ	P,KILHGH##	;KILL HIGH SEG
>
IFN FTKL10&FTMS,<
	PUSHJ	P,CLCSN##	;CLEAR SWEEP SERIAL NUMBER FOR JOB
				; SO WE DON'T SWEEP FOR NOTHING
>;END IFN FTKL10&FTMS
	MOVEI	T1,PAGSIZ##-1	;BASIC UNIT OF CORE MEMORY
	PUSHJ	P,CORE0##	;ASSIGN 2000 WORDS ON DISK OR MEMORY
	  JFCL			;IGNORE IF CANT(R=0)
	POP	P,S
	POP	P,T2		;RESTORE PUSHED ACS
	PJRST	UPOPJ##		;RESTORE U AND RETURN
;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
	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
	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
	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
IFN FTEXE,<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,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,RUNJOB)
;	MOVE R, ADR. OF JOB AREA
;	PUSHJ P,SGSET


SGSETD:	HLLZ	T2,SYSTAP##	;SET DEFAULT DEVICE OF DISK
SGSET:
IFN FTVM,<
	MOVEM	P1,.UPMP+.UPUAC+6
	MOVEM	P2,.UPMP+.UPUAC+4	;SAVE COMMAND FOR GET
>
	PUSHJ	P,SETASA	;TURN ON THE EXEC MODE UUO FLAG
	MOVEM	T2,SGADEV(R)	;STORE DEFAULT DEVICE NAME
	MOVEM	P1,SGAMOD(R)	;SAVE PHYSICAL/LOGICAL BIT FOR LATER
	PUSHJ	P,CTEXT1	;GET DEVICE OR NAME
	CAIE	T3,":"		;SEE IF DEVICE
	JRST	SGSETF		;NO--SET FILE NAME
	MOVEM	T2,SGADEV(R)	;YES--SAVE IT
	PUSHJ	P,CTEXT		;AND GET FILE NAME
SGSETF:	SKIPN	T2		;SEE IF FILE TYPED IN
	MOVE	T2,JBTPRG##(J)	;NO--GET DEFAULT IF ANY
	JUMPE	T2,NOTENF	;THERE MUST BE A FILE NAME
	MOVEM	T2,SGANAM(R)	;STORE FILE NAME
	MOVEM	T2,JBTPRG##(J)	;SAVE FILE NAME FOR SYSTAT COMMAND
	MOVEI	T2,0		;ASSUME USER DID NOT 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
	MOVEI	T2,0		;YES--IGNORE IT
	HRLZM	T2,SGAEXT(R)	;STORE IT FOR LOOKUP
IFN FTEXE,<
	MOVSI	T1,(JS.EXE)
	CAIN	T2,(SIXBIT /SAV/)
	ANDCAM	T1,JBTST2##(J)
>
IFN FT2REL,<
				; LOOKUP OR ENTER
	PUSHJ	P,SETEXT##	;SET HIGH EXTENSION(SGAHGH) TO .SHR IF SSAVE OR GET
				; ,HGH IF SAVE(LH S=NSRBIT).
>
	SETZM	SGADAT(R)	;SET DATE(E+2) TO 0, SO MONITOR WILL USE TODAYS
IFN FTLOGIN,<
	PUSHJ	P,PJPGNO	;GET PROJ. PROG. NO.
	MOVEM	T2,SGAPPN(R)	;STORE 0 IF NO []'S TYPED BY USER
	JUMPE	T2,SGSET4	;IF NO PPN, ALL IS OK
	MOVSI	T1,(SIXBIT /SYS/)
	CAME	T1,SGADEV(R)	;DID HE ASK FOR "SYS" BY MISTAKE?
	JRST	SGSET4		;NO, ALL IS OK
	PUSHJ	P,DEVLG##	;IS "SYS" A LOGICAL NAME?
	  SKIPA			;NO, CHANGE IT TO "DSK"
	JRST	SGSET4		;YES, NO CHANGES (HE KNOWS
				;  WHAT HE IS DOING)
	MOVSI	T1,(SIXBIT /DSK/)
	MOVEM	T1,SGADEV(R)	;HE TYPED .R FOO[N,N]
				;SO CHANGE "SYS" TO "DSK"
SGSET4:
>
	PUSHJ	P,CORARG	;AMOUNT OF CORE (OPTIONAL THIRD ARG.)
	JRST	SGSET1		;RETURN HERE IF NO ARG.
	TLNE	T2,-1		;USER ARG EXCEED MAX. SIZE OF CORE?
	JRST	COMERR		;YES, PRINT COMMAND ERROR
SGSET1:
	HRRZM	T2,SGANEW(R)	;STORE FOR RUN AND SAVE
	PUSHJ	P,SKIPS1	;SKIP TRIALING SPACES
	  JRST	SGSET3		;THAT'S ALL, SO OK
	CAIE	T3,"("		;SEE IF USER ARGUMENTS
	CAIN	T3,"-"		;SEE IF USER ARGUMENT (OLD WAY)
	SKIPA			;YES--OK TO FINISH UP
	JRST	COMERR		;NO--ERROR
SGSET3:
IFN FTVM,<
	PUSHJ	P,RMVPFH##	;DELETE PFH IF GOT IT FROM SYS
>
	HRRZS	T2,S		;SCHEDULE MONITOR JOB
				; GUARRANTEE LH OF PC WORD IS 0, SINCE IT WILL
				; BE ADDED TO STARTING ADDRESS(IF RUN COM)
IFN FTVM,<
	SUBI	S,SAVJOB
IFN FTEXE,<
	PUSHJ	P,CHKEXE	;IS THIS AN EXE SAVE?
	  JRST	SGST1A		;YES, MAKE AN EXE FILE
				;NO, FALL THRU TO REGULAR SAVES
>	;END OF IFN FTEXE
	SKIPN	.UPMP+.UPREL	;IF NON-CONTIGUOUS CORE IMAGE
	SKIPE	.UPMP+.UPVRT	;OR VIRTUAL (1+I SEA)
SGST1A:	JUMPE	S,SGSET2	;GO ELSEWHERE IF SAVE
IFN FTMS,<	PUSHJ	P,CLRJSP##	;CLEAR JBTSPS TO ENSURE MONITOR JOB RUNS ON MASTER
>
>
	PJRST	MSTART##	;START JOB WITH PC IN MONITOR MODE
IFN FTVM,<
SGSET2:	HLRZ	T1,JBTADR(J)	;GET HIGHEST ADDRESS IN LOW SEG
	CAMGE	T1,SGANEW(R)	;COMPARE WITH USER STORED CORE ARG
	MOVE	T1,SGANEW(R)	;USER'S WAS LARGER, USE IT
	HRRM	T1,JOBCOR##(R)	;AND SET UP JOBCOR.
	PUSHJ	P,CLRASA
IFN FTEXE,<
	PUSHJ	P,CHKEXE	;NSAVE OR NSSAVE?
	  JRST	MSTART##	;YES, SAVE AN EXE FILE
>	;END OF IFN FTEXE
IFN FTDAEM,<
	PJRST	DAECOM		;YES, LET DAEMON DO THE SAVE
>
IFE FTDAEM,<
	JRST	COMERA		;LOSE SINCE MONITOR CAN'T DO IT ANYWAY
>
>
	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,SGADEV(R)	;STORE DEVICE NAME
	PUSHJ	P,GETWD1##	;GET NEXT ARG FROM USER AREA
	MOVEM	T1,SGANAM(R)	;STORE FILE NAME FOR LOOKUP (DO NOT STORE FOR LOWSEG)
	PUSHJ	P,GETWD1##	;GET THIRD ARG(EXTENSION WORD E+1)
	MOVEM	T1,SGAEXT(R)	;STORE EXTENSION AND RH FROM USER
	HLRZ	T2,T1		;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
IFN FT2REL,<
	PUSHJ	P,SETEX1##	;SAVE EXT AGAIN IN SGALOW
				; SETUP EXT FOR HIGH SEG(SGAHGH="SHR")
				; SETUP EXTENSION FOR LOW SEG(SGALOW="SAV")
>
	PUSHJ	P,GETWD1##	;GET FOURTH ARG(DATE WORD)
	MOVEM	T1,SGADAT(R)
	PUSHJ	P,GETWD1##	;GET FIFTH USER ARG FROM USER AREA
	MOVEM	T1,SGAPPN(R)	;STORE PROJECT,PROGRAMMER NO. OR 0
	PUSHJ	P,GETWD1##	;SIXTH ARG FROM USER
	HRRZM	T1,SGANEW(R)	;STORE CORE ARG OR 0(HIGHEST LOC DESIRED)
				; IGNORE LH
	JRST	SG2A		;GO SET UP LOWER CORE AND RETURN
				; DO NOT DO A RESET
	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,CLRTAB	;CLEAR BITS AND TABLES
	PUSH	P,[0]		;STORE ZERO IN JOBPD1
				; SO THAT SGRELE CAN
				; TELL SAVE IS IN PROGRESS
IFN FT2REL,<	PUSHJ	P,ADJCOR##	;COMPUTE AMOUNT OF CORE FOR BOTH LO+HI SEGS
				; FROM USER'S CORE ARG(IF ANY)
>
	HLRE	T2,SGADMP(R)	;-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,JOBCOR##(R)	;STORE MAX OF SIZE OF FILE OR CORE ARG
				; FOR ASSIGNING INITIAL CORE WHEN FILE GOTTEN
	SETOM	JOBSV##(R)	;FLAG LOW SEGMENT AS NOT COMPRESSED SO
				; WILL NOT TRY TO EXPAND IT IF I/O DOES NOT
				; GO TO COMPLETION
	PUSHJ	P,SGOPEN##	;OPEN THE DEVICE
IFN FTEXE,<
	MOVE	T1,DEVMOD(F)	;DEVICE BITS
	MOVSI	T2,(JS.EXE)	;BIT WHICH SAYS SAVE IN EXE FORMAT
IFN FTVM,<
	TLNE	T1,DVMTA	;A MAGTAPE
	SKIPN	.UPMP+.UPREL	; AND VIRTUAL ?
>
	TLNE	T1,DVDTA	; OR 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
>	;END OF IFN FTEXE
IFN FT2REL,<
	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
IFE FT2REL,<
	PUSHJ	P,SG3		;RESTORE SGALEN
>
	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	SGADAT(R)	;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,JOB41##(R)	;SAVE USER UUO HANDLING JSR
	MOVEM	T1,JOBS41##(R)	;IN UPPER PART OF JOB DATA AREA
IFN FTEXAMINE,<
	SETZM	JOBEXM##(R)	;CLEAR MEMORY OF EXAMINE
>
	SETZM	JOBFDV##(R)		;CLEAR MEMORY OF FIN
	MOVE	T1,JOBDDT##(R)	;SAVE DDT STARTING ADDRESS HIGHER UP IN JOB DATA AREA
	MOVEM	T1,JOBSDD##(R)	;SO COMPRESS ALWAYS MOVES CODE DOWN
	HRRZ	T3,JOBSA##(R)	;SAV START ADDRESS FOR 10DMP
	MOVEI	T1,JOBSV##	;POINT TO 1ST DATA WORD
	MOVEI	T2,JOBSDD##	;IT STARTS AT JOBSDD
IFN FTKA10,<
	HRLI	T2,R		;RELOCATE IF PDP-6, KA-10
>
	TLNE	T2,R
	ADDI	T1,(R)		;RELOCATE IF KA
	HLRE	J,SGADMP(R)	;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
	TLNE	T2,R
	SUBI	T1,(R)		;REMOVE RELOCATION IF KA
	MOVNS	T1		;MAKE AN IOWD
	HRL	T1,SGADMP(R)	;START ADDRESS
	MOVSM	T1,SGALEN(R)	;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:
IFN FTEXE,<
	MOVE	J,JOB##		;GET JOB NUMBER
	MOVSI	T1,(JS.EXE)	;GET EXE FILE STATUS BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR BIT IN JOB STATUS WORD
>
	PUSHJ	P,SGREL		;RELEASE DEVICE AND FIND TTY
	MOVE	T2,JBTNAM##(J)	;GET JOB NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	JSP	T1,PHOLD##	;PRINT MESSAGE AND STOP JOB
	ASCIZ	/ saved/

SAVERR::
IFN FTEXE,<
	MOVE	J,JOB##		;GET JOB NUMBER
	MOVSI	T1,(JS.EXE)	;GET EXE FILE STATUS BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR BIT IN JOB STATUS WORD
>
	HRRZS	USRHCU##	;CLEAR SAVE IN PROGRESS FLAG
	HRRZS	JOBHCU##(R)	; AND THE JOB DATA AREA
	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 

IFN FTEXE,<
;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

;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,SGALOW(R)	;GET USER EXTENSION, IF ANY
	MOVSI	T1,'EXE'	;SET UP EXTENSION OF "EXE"
	MOVEM	T1,SGAEXT(R)	;STORE IN USER'S AREA
	HRROS	USRHCU##	;SET SAVE IN PROGRESS FLAG IN MONITOR
	HRROS	JOBHCU##(R)	; AND IN USER JOB DATA AREA
	ENTER	0,SGANAM	;ENTER THE FILE-NAME IN THE DIRECTORY
	  JRST	SAVERR		;ERROR, ABORT WITH ERROR MESSAGE
	MOVEI	P1,0		;SET UP TO GET FLAGS
	HLRZ	T1,SGAHGH(R)	;GET EXTENSION SET UP BY SG3
	CAIE	T1,'SHR'	;WAS THIS A NSSAVE?
	TLO	P1,SV%SAV	;NO, SET NON-SHARABLE BIT
	PUSHJ	P,COPVJD##	;COPY NUMBERS FROM JOBDAT TO VESTIGUAL JOBDAT
				; (ONLY NECESSARY FOR GETSEG OF UNKNOWN SEGMENTS)

;FALL THRU TO NEXT PAGE.....

;STILL IN IFN FTEXE CONDITIONAL
IFN FTVM,<

;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.

	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,PAGSIZ##-1]	;COULDN'T, START AT PAGE 777
	JRST	[MOVE	P3,T1	;GOT ONE, PUT ITS NUMBER IN P3
		 JRST	PAGFRE]
				; NOW FIND ONE TO OUTPUT TEMPORARILY
	MOVE	J,JOB##		;SET UP JOB NUMBER
SAV2:	MOVE	T1,P3		;GET THE PAGE #
	PUSHJ	P,TPAHS##	;TEST FOR SHARABLE HISEG
	  SOJA	P3,SAV2		;CAN'T USE THIS ONE, TRY NEXT LOWER PAGE
				; WE MUST FIND A PAGE THAT ISN'T IN THE
				; SHARABLE HI SEG SO EVENTUALLY, WE
				; WILL SKIP
	JUMPE	P3,NEED1P##	;IF IT'S PAGE 0, WE LOSE
	PUSHJ	P,CMPBIT	;COMPUTE THE SAVE-FILE BITS FOR THIS PAGE
	 JRST	BRCSTP		;ISSUE FATAL STOPCD IF NON-EXISTENT
	TLNE	T1,SV%ABZ	;DON'T REMOVE AN ABZ PAGE
	SOJA	P3,SAV2		;DECREMENT PAGE #
	HLLZ	P4,T1		;SAVE THESE BITS FOR LATER
	HRRZ	T1,P3		;GET THE PAGE #
	PUSHJ	P,IPCRMV##	;REMOVE PAGE FROM LOG. ADR. SPACE
	 JRST	SVABRT		;I/O ERROR
	PUSHJ	P,IPCPAG##	;WRITE PAGE OUT (RETURN WITH T2=PAGE #
				; OR DISK ADDRESS)

	 JRST	SVABRT		;ERROR
	HRR	P4,T2		;SAVE ADDRESS WHERE WE PUT IT ON DISK
	TLO	P1,SV%FUL	;REMEMBER THAT WE DID THIS

	;FALL INTO PAGFREE
>;END IFN FTVM

;STILL IN IFN FTEXE CONDITIONAL
IFN FTVM,<


;COME HERE WHEN WE HAVE FOUND A FREE PAGE TO USE AS THE DIRECTORY

PAGFRE:	HRRZ	T1,CORMAX##	;GET MAX PHYSICAL LIMIT FOR SYSTEM
	LSH	T1,W2PLSH##	;MAKE CORMAX INTO PAGE NUMBER
	HRLI	T1,^D512	;MAKE HIM HAVE A VERY HIGH VIRTUAL LIMIT
	EXCH	T1,.PDCVL##(W)	;REPLACE HIS NEW VIRTUAL LIMIT
	PUSH	P,T1		;AND SAVE HIS OLD ONE
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,PAGSIZ##	;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
	HRR	P4,T1		;SAVE PAGE # THAT WAS SENT OUT
	JRST	PGFRE2		;TRY TO CREATE DIRECTORY AGAIN
>;END IFN FTVM

IFE FTVM,<
;IF THIS IS A NON-VM SYSTEM, WE MUST ACQUIRE A FREE PAGE TO USE AS THE
; DIRECTORY. IF THE CORE UUO FAILS, THEN WE HAVE NO EXTRA PAGES TO USE
; AS THE DIRECTORY AND WE MUST USE THE USER'S SHADOW AC AREA. THIS ALSO
; IMPLIES THAT NO ZERO-COMPRESSION IS POSSIBLE BECAUSE THE DIRECTORY
; MUST BE KEPT SHORT (I.E. 6 WORDS). THEREFORE, THERE ARE SEVERAL
; CHECKS LATER ON TO SEE WHERE THE DIRECTORY WAS FORMED.
;THESE CHECKS ARE OF THE FORM "TRNN P1,PAGNUM" WHICH WILL SKIP IF THE
; DIRECTORY WAS CREATED ANYWHERE EXCEPT PAGE 0.

	HRRZ	T1,USRREL##	;GET TOP OF LOW SEGMENT
	ADDI	T1,EXESIZ	;BUMP IT BY LENGTH OF DIRECTORY
	MOVEM	T1,SGACOR(R)	;STORE FOR CORE UUO
	PUSH	P,P1		;CORE UUO'S CLOBBER P1
	CALLI	SGACOR,200011	;DO PHYSICAL-ONLY CORE UUO
	 TDZA	P3,P3		;COULDN'T GET EXTRA PAGE, SET DIRECTORY
				; PAGE TO BE PAGE 0, AND DON'T ZER0-COMPRESS
	HRRZ	P3,USRREL##	;GET EXTRA PAGE, GET TOP OF LOW SEGMENT
	LSH	P3,WXPLSH	;=PAGE # OF DIRECTORY
	POP	P,P1		;RESTORE P1
>;END IFE FTVM




;COME HERE WHEN WE HAVE CREATED THE DIRECTORY PAGE
GOTDIR:
IFN FTVM,<
	POP	P,.PDCVL##(W)	;RESTORE VIR,PHY LIMITS
>;END IFN FTVM
	LSH	P3,PXWLSH	;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
	TDZA	P3,P3		;START LOOKING AT PAGE 0 FOR USER'S PAGES
GOTDR2:	AOS	P3		;BUMP PAGE #
	PUSHJ	P,MKNTRY	;MAKE A DIRECTORY ENTRY FOR THIS PAGE
	 JRST	THRUDR		;DIRECTORY IS OVER, GO CHECK ITS LENGTH
	JRST	GOTDR2		;MORE TO GO, GET NEXT PAGE #


;STILL IN IFN FTEXE CONDITIONAL
;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
IFE FTVM,<
	TRNE	P1,PAGNUM	;DIRECTORY IN PAGE 0?
	JRST	.+4		;NO
	HRLM	T1,SGAHGH(R)	;USE OTHER IOWD
	SETZM	SGALOW(R)	;CLEAR END
	SKIPA
>
	HRLM	T1,SGALEN(R)	;SET UP LENGTH
	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,PXWLSH	;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
	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
	  SKIPA	T1,[SV.END,,LN.END]	;THRU, PUT OUT END BLOCK
	JRST	THRU2		;LOOP UNTIL PAGE 777
	PUSHJ	P,PTDIRW	;STORE IN DIRECTORY

;FALL THRU TO NEXT PAGE...

;STILL IN IFN FTEXE

;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
IFN FTVM,<
	HRRZ	T1,P1		;GET PAGE ADDRESS OF DIRECTORY
	PUSHJ	P,ZAPPAG	;DESTROY IT
	  STOPCD	CPOPJ,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
	HRRZ	T1,P4		;YES, GET ITS PAGE #
	PUSHJ	P,PAGIN		;BRING IT IN
	  JRST	SVABRT		;I/O ERROR--ABORT
>;END IFN FTVM
IFE FTVM,<
	HRRZ	T1,USRREL##	;GET TOP OF LOW SEGMENT
IFN FTKA10,<
	SUBI	T1,EXESIZ*2	;ROUND DOWN TO 1K
>
IFN FTKI10,<
	SUBI	T1,EXESIZ	;GET RID OF DIRECTORY PAGE
>
	TRNE	P1,PAGNUM	;DID WE USE PAGE 0 AS THE DIRECTORY PAGE?
	PUSHJ	P,GETCOR	;NO, REDUCE CORE BY ONE PAGE
	MOVNI	T1,EXESIZ	;SIZE OF PAGE
	HRLM	T1,SGALEN(R)	;RESET LENGTH IN CASE WE
	SETZM	SGAEND(R)	; ARE USING PAGE 0 AS THE
				; DIRECTORY, IN WHICH CASE SGALEN
				; HAD PART OF THE DIRECTORY IN IT
>;END IFE FTVM
;THIS IS THE MAIN LOOP FOR AN EXE FILE SAVE
;EACH PAGE IS WRITTEN OUT INDIVIDUALLY TO INSURE DEVICE AND
; SYSTEM COMPATABILITY

RELDR1:	SETO	P3,		;WE WILL START LOOKING AT PAGE 0
	SKIPLE	J,JBTSGN##(J)	;IS THERE A HI SEG
	PUSHJ	P,SETHRL##	;YES, SET LH(JOBHRL)
	MOVE	J,JOB##		;RESET J
RELDR2:	AOS	T1,P3		;BUMP PAGE #
	CAIL	T1,EXESIZ	;THRU UPMP?
EXEXIT:	JRST	[HRRZS	USRHCU##	;YES, CLEAR SAVE IN PROGRESS FLAG
		 HRRZS	JOBHCU##(R)
		 JRST	SAVFIN]		; WE'RE FINALLY THRU!!!
IFN FTVM,<
	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
>;END IFN FTVM

;FALL THRU TO NEXT PAGE....
IFE FTVM,<
	PUSHJ	P,CMPBIT	;COMPUTE ACCESS BITS FOR THIS PAGE
	 JRST	RELDR2		;PAGE IS NON-EXISTENT, DON'T SAVE IT
	TLNE	T1,SV%ABZ	;IS THE PAGE ALLOCATED-BUT-ZERO?
	TRNN	P1,PAGNUM	;YES, BUT ARE WE ZERO-COMPRESSING?
	SKIPA			;NO TO EITHER
	JRST	RELDR2		;YES, DON'T SAVE THIS PAGE
	TLNN	T1,SV%HIS	;IS THIS THE HIGH SEG?
	JRST	RELDR3		;NO
	MOVSI	T1,(JS.EXE)	;EXE BIT MUST BE CLEARED ON
	ANDCAM	T1,JBTST2##(J)	; A HIGH SEGMENT SAVE
	MOVNI	T1,4		;SET LEFT HALF OF THESE LOCS
	HRLM	T1,USRHCU##	; TO INDICATE A HIGH SEG
	HRLM	T1,JOBHCU##(R)	; SAVE IS IN PROGRESS
	MOVE	J,JBTSGN##(J)
	PUSHJ	P,OUTHGH##	;OUTPUT HIGH SEG
	PUSHJ	P,SGIOCK	;ERRORS?
	JRST	EXEXIT		;AND EXIT
>;END IFE FTVM
RELDR3:	MOVE	T1,P3		;GET PAGE NUMBER
	LSH	T1,PXWLSH	;CONVERT TO ADDRESS
	SOS	T1		;=START OF PAGE-1
	HRRM	T1,SGALEN(R)	;STORE IN IOWD
	PUSH	P,P1		;SAVE P1
	OUTPUT	SGALEN		;WRITE OUT THIS PAGE
	POP	P,P1		;RESTORE IT
	PUSHJ	P,SGIOCK	;CHECK FOR ERRORS
	JRST	RELDR2		;NO, GO BACK FOR MORE




;STILL IN  FTEXE CONDITIONAL
IFN FTVM,<
;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::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,SGAHGH(R)	;SAVE SGAHGH
	PUSH	P,SGANEW(R)	; AND SGANEW
	MOVEM	T2,SGAHGH(R)	;STORE PAGE NUMBER FOR UUO
	MOVEI	T2,1		;LENGTH OF ARG BLOCK
	DMOVEM	T1,SGASAV(R)	;STORE IN USER AREA
	PAGE.	SGASAV,		;DO THE UUO
	  SOS	-3(P)		;ERROR
	POP	P,SGANEW(R)
	POP	P,SGAHGH(R)
	JRST	TPOPJ1##	;RESTORE PAGE # AND RETURN

;STILL IN IFN FTEXE AND IFN FTVM CONDITIONAL

;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,
>;END IFN FTVM
IFN FTVM,<
;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
PGLOW2:	PUSHJ	P,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	.UPMP+.UPREL	;DOES HE HAVE A NON-CONTIGUOUS CORE IMAGE?
	POPJ	P,		;NO, WE MUST HAVE COME TO END OF LOW SEG
	CAIGE	T1,PAGSIZ##-1	;YES, ARE WE THRU ALL OF CORE?
	AOJA	T1,PGLOW2	;NO
	POPJ	P,		;YES, EXIT

;STILL IN FTEXE CONDITIONAL
>;END IFN FTVM
;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	;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.
	CAME	T1,T3		;ARE THE FLAG BITS THE SAME AS THE LAST PAGE
	JRST	NEWENT		;NO, FORM A NEW DIR ENTRY
	LDB	T2,[POINT 9,T4,8]	;GET LAST REPEAT COUNT
	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
;STILL IN IFN FTEXE CONDITIONAL..
;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
	CAIL	P3,EXESIZ	;LAST PAGE?
	POPJ	P,		;YES, GIVE NON-SKIP RETURN
	JRST	CPOPJ1##	;NO, SKIP RETURN


;STILL IF IFN FTEXE CONDITIONAL...
IFN FTVM,<

;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,JOB##		;JUST FOR SAFETY
	PUSH	P,T1		;SAVE PAGE #
	LSH	T1,P2WLSH##	;CONVERT IT TO AN ADDRESS
	MOVE	T2,T1
	PUSHJ	P,INPFH##	;THIS PAGE PART OF PFH?
	 JRST	TPOPJ##		;YES, RESTORE T1 AND RETURN
	HRRZ	T1,JOBINT##(R)	;GET START OF INTERRUPT BLOCK
	TRZ	T1,PAGSIZ##-1	;FIND START OF PAGE
	CAIN	T1,(T2)		;IS THIS THAT PAGE?
	JRST	TPOPJ##		;RESTORE PAGE # AND RETURN
	MOVE	T1,0(P)		;GET PAGE # BACK AGAIN
	PUSHJ	P,GETPAC##	;GET PAGE ACCESSABILITY
	TLNE	T1,(PA.CPO)	;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

;STILL IN FTVM AND FTEXE CONDITIONAL...


>;END IFN FTVM
IFN FTVM,<
;SUBROUTINE TO PAGE IN A PAGE
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,PAGIN
;	 ERROR RETURN
;	OK RETURN

PAGIN::
	MOVE	T2,T1		;GET PAGE #
	MOVSI	T1,.PAGIO	;GET FUNCTION CODE
	PUSHJ	P,PAGUUO	;PAGE. UUO
	SKIPA	T2,SGASAV(R)	;SOMETHING HAPPENED, GET THE ERROR
				; CODE WHICH WAS RETURNED IN USER AC'S
	JRST	CPOPJ1##	;SUCCESS
	CAIE	T2,PAGLE%	;LIMIT EXCEEDED IS OK
	POPJ	P,		;ANYTHING ELSE IS FATAL
	PUSH	P,T1		;SAVE PAGE-IN PAGE #
	MOVEI	T1,1		;TRY TO PAGE OUT SOME PAGES
PAGIN3:	PUSHJ	P,PAGOUT	;TRY TO PAGE IT OUT
	  JRST	[CAIE	T1,PAGSIZ##-1	;THRU ALL PAGES?
		 AOJA	T1,PAGIN3	;NO, TRY AGAIN
		 JRST	TPOPJ]		;YES, FATAL ERROR
	POP	P,T1		;GET PAGE BACK
	JRST	PAGIN		;TRY AGAIN TO PAGE IT IN


;STILL IN IFN FTEXE AND IFN FTVM CONDITIONAL

;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	T2,P4		;GET DISK ADDRESS
	HRRZ	T1,P1		;GET PAGE ADDRESS
	LSH	T1,W2PLSH##	;MAKE INTO A PAGE NUMBER
	PUSHJ	P,IPCINS##	;CREATE PAGE
	 STOPCD CPOPJ,DEBUG,DPL,	;++DIRECTORY PAGE LOST
	POPJ	P,


;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,PAGSIZ##-1	;START AT PAGE 777
GTFRE2::PUSHJ	P,GTPME##	;GET MAP ENTRY
	JUMPE	T2,CPOPJ1##	;IF NON-EXISTENT, ITS OK
	SOJN	T1,GTFRE2	;DECREMENT PAGE # AND TRY AGAIN
	POPJ	P,		;COULDN'T


;STILL (YES, STILL) IN IFN FTEXE AND IFN FTVM CONDITIONAL...

;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::PUSH	P,T1		;SAVE PAGE NUMBER
	LSH	T1,P2WLSH##	;MAKE INTO AN ADDRESS
	HRRZ	T2,P1		;GET CURRENT DIRECTORY POINTER
	TRZ	T2,PAGSIZ##-1	;CLEAR OFFSET
	MOVEI	T3,P1		;ASSUME ITS' THERE
	CAMN	T1,T2		;IS THIS A DIR PAGE?
	JRST	TPOPJ##		;YES, RESTORE PAGE # AND EXIT
	MOVEI	T3,SGANAM(R)	;ASSUME IT'S HERE
	CAMN	T1,SGANAM(R)	;IS IT?
	JRST	TPOPJ##		;YES, RESTORE T1 AND EXIT
	CAMN	T1,SGAEXT(R)	;IS IT THIS ONE?
	AOJA	T3,TPOPJ##	;YES
	AOJA	T3,TPOPJ1##	;NO, SKIP RETURN

;SUBROUTINE TO PAGE IN A PAGE, IF IT'S OUT
;CALL:
;	MOVE	T1,PAGE #
;	PUSHJ	P,YANKIT
;	  RETURN HERE IF PAGE ALLOCATED BUT ZERO
;	RETURN HERE WITH PAGE BITS IN T2
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
>;END IFN FTVM

;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:
IFN FTVM,<
	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
	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
	SKIPN	.UPMP+.UPHSS	;IS THERE A HISEG?
	JRST	CMP2		;NO
	MOVE	T2,P3		;YES, GET PAGE #
	LSH	T2,P2WLSH##	;MAKE INTO AN ADDRESS
	CAML	T2,.UPMP+.UPHSS	;MUST BE GREATER THABN HISEG START
	CAMLE	T2,.UPMP+.UPHSE	; AND LESS THAN END
	JRST	CMP2		;ITS NOT IN THE HIGH SEG
	TLO	T1,SV%HIS	;SET HISEG BIT
>;END IFN FTVM
IFE FTVM,<
	MOVE	P4,P3		;GET PAGE # TEMPORARILY
	LSH	P4,PXWLSH	;MAKE INTO AN ADDRESS
	MOVE	J,JOB##		;INSURE THAT JOB # IS CORRECT
	HLRZ	T2,JBTADR##(J)	;GET PROTECTION FOR LOW SEG
	CAMLE	P4,T2		;IS THIS ADDRESS IN THE LOW SEG?
	JRST	NOLOW		;NO
	MOVSI	T1,SV%WRT	;YES, SET WRITABLE BIT IN DIRECTORY
	JRST	CMP2		; AND CONTINUE
NOLOW:	PUSHJ	P,HSVAD##	;GET HIGH SEG LIMITS
	CAML	P4,T2		;IF IT'S LESS THAN START OF HIGH SEG
	CAMLE	P4,T1		; OR HIGH THAN TOP OF HIGH SEG
	POPJ	P,		;THEN, IT'S A NON-EXISTENT PAGE
	MOVSI	T1,SV%HIS	;IT'S IN THE HIGH SEG, SET THAT BIT
>;END IFE FTVM
	TLNN	P1,SV%SAV	;WAS THIS AN "SAVE" COMMAND?
	TLO	T1,SV%SHR	;NO, SET SHARABLE BIT TOO
	MOVE	J,JOB##		;GET JOB #
	SKIPG	JBTSGN##(J)	;SPY SEG?
	POPJ	P,		;YES, IGNORE IT
IFN FTKI10!FTKL10,<
	MOVEI	T2,JS.XO	; AND EXECUTE ONLY BIT
	TDNE	T2,JBTSTS##(J)	;IS IT SET?
	TLO	T1,SV%CON	;YES, MUST BE CONCEALED
>;END IFN FTKI10
	JRST	CPOPJ1##	;RETURN SINCE DIR CAN'T BE IN HIGH SEG
CMP2:
IFE FTVM,<
	TRNN	P1,PAGNUM	;ARE WE ZERO-COMPRESSING?
	JRST	CMP3		;NO, IGNORE THIS STUFF
>
	PUSH	P,T3		;SAVE OLD ENTRY
	PUSH	P,T4
	PUSHJ	P,CHKABZ	;IS THIS PAGE ALL ZEROES?
	  TLO	T1,SV%ABZ	;YES, SET BIT
	POP	P,T4		;RESTORE IT
	POP	P,T3
CMP3:	HRRZ	T2,P1		;GET ADDRESS OF DIRECTORY PAGE
	LSH	T2,WXPLSH	;CONVERT TO PAGE #
IFN FTVM,<
	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
>;END IFN FTVM
IFE FTVM,<
	JUMPE	T2,CPOPJ1##	;OK IF DIR IS IN PAGE 0
IFN FTKA10,<
	CAIE	P3,-1(T2)	;IS THIS 1ST PAGE OF EXTRA 1K?
>
	CAIN	P3,(T2)		;IS THIS THE DIRECTORY PAGE?
				; OR ON KA'S, IT MAY BE EXTRA PAGE
				; ALLOCATED ON 1K BOUNDRY
	POPJ	P,		;YES, TREAT PAGE AS NON-EXISTENT
	JRST	CPOPJ1##	;NO, PAGE IS VALID
>;END IFE FTVM
;COME HERE FOR A VARIETY OF USER SINS
GTABRT::
SVABRT:	MOVE	J,JOB##		;GET JOB NUMBER
	MOVSI	T1,(JS.EXE)	;GET EXE SAVE FILE BIT
	ANDCAM	T1,JBTST2##(J)	;CLEAR IT
	HRRZS	USRHCU##	;CLEAR SAVE IN PROGRESS FLAG
	HRRZS	JOBHCU##(R)	;AND IN USER'S JOB DATA AREA
	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
IFN FTVM,<
	MOVE	T1,P3		;SET PAGE #
	PUSHJ	P,YANKIT	;IF OUT, BRING IT IN
	  JRST	TPOPJ##
	TLNN	T2,(PA.AA)
	PUSHJ	P,SETAA
>	;END OF FTVM
	MOVE	T2,P3		;FETCH PAGE #
	LSH	T2,PXWLSH	;MAKE INTO AN ADDRESS
IFN FTKA10,<
	ADDI	T2,(R)		;RELOCATE ADDRESS
>;END IFN FTKA10
	HRLI	T2,-EXESIZ	;FORM AOBJ WORD
ABZ2:	EXCTUU	<SKIPE	(T2)>	;IS THIS LOCATION ZERO?
	JRST	TPOPJ1##	;NO, SKIP RETURN
	AOBJN	T2,ABZ2		;LOOP THRU ENTIRE PAGE
	JRST	TPOPJ##		;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
IFE FTVM,<
	TRNE	P1,PAGNUM	;PAGE 0 CORRECT?
	JRST	.+3		;NO
	HRRM	T1,SGAHGH(R)	;STORE IT
	SKIPA	T2,[SGAHGH]
>
	HRRM	T1,SGALEN(R)	;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
PUTD2:	POP	P,P4		;GET P4 BACK
	POP	P,P1		;GET P1 BACK AGAIN
	POPJ	P,		;RETURN OK
;ROUTINE TO SET UP AN IOWD IN SGALEN
;
;CALL:
;	MOVE	T1,ADDRESS-OF-I/O
;	PUSHJ	P,STIOWD
;	HERE ALWAYS
;
;T2 IS DESTORYED

STIOWD::HRRM	T1,SGALEN(R)	;STORE ADDRESS
	SOS	SGALEN(R)	;=LOC-1
	MOVNI	T2,EXESIZ	;GET SIZE OF I/O (PAGE ASSUMED)
	HRLM	T2,SGALEN(R)	;STORE IN IOWD
	POPJ	P,		;RETURN


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

IFN FTVM,<
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,SGASAV(R)	;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.
>;END OF IFN FTVM

>;END OF IFN FTEXE (WHICH BEGAN AT SAVEXE)
	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,GJOBX		;GET THE JOB
	PUSH	P,[0]		;CLEAR PC FLAGS SINCE THEY ARE MEANINGLESS
	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)
	PUSH	P,P1		;PUSH A FAKE WORD SO GETBTB CAN CLEAR LH JOBPD1
	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
;TABLE OF PRIVILEGED CUSPS
;USED TO TURN ON JACCT WHEN R OR RUN COMMAND OR RUN UUO

PRVTAB:
IFN FTLOGIN,<
LGONAM::SIXBIT	/LOGOUT/	;NAME FOR "LOGOUT" (TURN OFF JLOG TOO)
	SIXBIT	/LOGIN/
QUENAM:	SIXBIT	/QUEUE/
	SIXBIT	/SPRINT/
IFN FTATTACH,<
	SIXBIT	/REATTA/
>
>
IFN FTCCLX,<
	SIXBIT	/PLEASE/
>
	SIXBIT	/UMOUNT/
IFN FTDAEM,<
	SIXBIT	/DAEMON/
	SIXBIT	/SAVER/
>
IFN FTPRV,<
	SIXBIT	/SYSTAT/	;FOR PEEK UUO PRIVILEGE
>
IFN FTNET,<
				;FOR REMOTE SPOOLERS TO
	SIXBIT	/LPTSPL/	;FULL FILE ACCESS.  SPOOLERS
	SIXBIT	/NETLDR/	;PREVENT ABUSE OF THIS CAPABILITY.
>
PRIVN==.-PRVTAB			;NO. OF PRIVILEGED CUSPS
IFN PRIVN&FTPATT,<0>			;SAVE A WORD FOR PATCHING OVER

	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 Y ERROR MESSAGE
	JRST	PHOLD##		;START TTY + STOP JOB
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
	MOVEI	P1,0		;CLEAR FLAGS
IFN FTVM,<
	MOVE	T1,['RUNUUO']	;NEED TO KNOW IF WE RUN GET
	MOVEM	T1,.UPMP+.UPUAC+4
	MOVS	T1,(P)
	MOVEM	T1,.UPMP+.UPUAC+6
>
;HERE ON R OR RUN COMMAND
URUN1:
	PUSHJ	P,GJOBX		;GET BOTH LOW AND HIGH SEGMENTS
				;RETURN FILE NAME IF FROM REAL SYS, ELSE 0 IN T1
IFN PRIVN!FTTLIM!FT2REL,<
	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
>
IFN FTTLIM,<	MOVSI	T2,(JB.LSY)	;PREPARE TO SET FLAG
	JUMPE	T1,URUN3	;  IF IT CAME FROM SYS:
	IORM	T2,JBTLIM##(J)	;  FOR BATCON
>
IFN PRIVN,<
	PUSHJ	P,PRVPG
	  JRST	URUN3
IFN FTVM,<
	CAME	T1,LGONAM	;IS THIS THE LOGOUT CUSP?
	JRST	URUN4		;NO
	SETZM	.PDCVL##(W)	;YES, MAKE SURE IT HAS ENOUGH CORE TO RUN
IFN FTGALAXY,<
	PUSHJ	P,CLRLOG##	;AND CLEAR JLOG
>>
URUN4:	MOVSI	T2,JACCT	;SET PRIVILEGED PROG. BIT
	MOVE	T3,JBTPPN##(J)
	CAME	T3,FSFPPN##	;OPR IS NEVER XCT ONLY
	HRRI	T2,JS.XO
IFN FTGALAXY,<
	CAME	T1,QUENAM	;IS IT QUEUE?
	JRST	URUN4A		;NO, SKIP CHECK
	SKIPE	%SIQSR		;YES, QUASAR RUNNING?
	SETZ	T2,		;YES, NO JACCT
>	;END IFN FTGALAXY
URUN4A:
	IORM	T2,JBTSTS##(J)	;SO NO CONTROL C AND ALL ACCESS
				; TO FILES
>;END PRIV.CUSPS
IFN PRIVN!FTTLIM!FT2REL,<
	JRST	URUN3		;GO START IT UP
URUN2:	IFN FT2REL,<		;HERE IF BAD OFFSET
	PUSHJ	P,CHKMED##	;SET MEDDLE IF SHARABLE
>
	MOVEI	T1,JS.XO	;SEE IF EXECUTE ONLY
	TDNE	T1,JBTSTS##(J)	;  IF SO, CLEAR OFFSET
	SETZM	(P)		;  TO PROTECT JOB
>				;END PRIVN!FTTLIM!FT2REL
URUN3:
	HLRZ	T2,(P)		;GET STARTING ADDRESS INCREMENT(0 IF RUN COM)

	ADD	T2,JOBSA##(R)	;NOW ADD STARTING ADDRESS
;HERE FROM VMSER TO START DDT AFTER GETTING DDT
STARTU::TRNN	T2,777700	;SEE IF LEGITIMATE START ADDRESS
	JRST	URUNSA		;NO--GIVE THE USER AN ERROR
	HRLI	T2,USRMOD	;SET USER MODE BIT IN PC
	PUSH	P,T2		;PUT ON PD LIST
IFN FTMS,<	PUSHJ	P,DPXST##	;SET UP PROPER RUNNABLE BITS FOR THIS JOB IN JBTSPS
>
	JRST	USRXIT##	;AND GO TO RETURN TO USER AS IF FROM UUO

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

;SUBROUTINE TO DETERMINE IF THE CUSP BEING RUN IS PRIVILEDGED
; ENTER WITH T1=NAME OF THE CUSP BEING RUN
; EXIT CPOPJ IF NOT PRIVILEDGED, CPOPJ1 IF IT IS
;PRESERVES T4
IFN PRIVN,<
PRVPG::	MOVSI	T2,-PRIVN	;NO. OF PRIVILEDGED 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,<
SNDFXM:	MOVEI	T1,.FDXIT
	MOVEM	T1,FILMSG##
	MOVE	T1,[FILMSG##+3,,FILMSG##+4]
	SETZM	FILMSG##+3
	BLT	T1,FILMSG##+11
	MOVE	T1,.PDSTR##(W)
	MOVEM	T1,FILMSG##+1
	MOVE	T1,.PDNAM##(W)
	MOVEM	T1,FILMSG##+2
	MOVE	T1,.PDDIR##(W)
	MOVEM	T1,FILMSG##+4
	MOVE	T4,JBTPPN##(J)
	PUSHJ	P,SENDFD##
	  POPJ	P,
	POPJ	P,

;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)
	TDNN	T1,JBTST2##(J)
	AOSA	(P)
	ANDCAM	T1,JBTST2##(J)
	POPJ	P,

;SUBROUTINE TO SEE IF AN EXIT MESSAGE SHOULD BE SEND 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 DEAMON BE CALLED ?
	  CAIA			;YES
	JRST	(T4)		;NO, JUST DO THE COMMAND
	TLO	M,RUNFLG	;SO COMRET WILL LET US RUN
	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
	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::
IFN FTVM,<
	MOVE	T2,['GETSEG']
	MOVEM	T2,.UPMP+.UPUAC+4
	MOVE	T2,JOBPD1##(R)
	MOVEM	T2,.UPMP+.UPUAC+6
>	
IFN FT2REL,<
	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, UNLESS FT2REL=0)
;	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,SGAMOD(R)	;RESTORE PHYSICAL/LOGICAL BIT
SG2A:	MOVEI	T1,DR		;DUMP MODE 16(DUMP BY RECORDS
				; IN CASE THIS IS MAGTAPE)
IFN FTPHYO,<
	TLNE	P1,PHONLY	;SEE IF PHYSICAL DEVICE
	TLO	T1,(1B0)	;YES -- SET FOR PHYSICAL OPEN
>

	MOVEM	T1,SGAMOD(R)	;STORE FOR OPEN UUO
	SETZM	SGAREN+1(R)	;FOR DELETE
	SETZM	SGAREN+2(R)	;FOR DELETE
	HLLZS	JOBCOR##(R)	;0 THIRD ARG IN JOBDATA AREA(SO CHKARG WILL
				; WORK ON FIRST CALL(SAVE AND GET)
	SETZM	SGAHED(R)	;CLEAR BUFFER HEADER ARG. FOR OPEN UUO
IFE FT2REL,<
	MOVEM	W,SGAEND(R)	;SAVE W
IFN FTKI10!FTKL10,<
	PUSHJ	P,SETASA	;SET EXEC MODE UUO FLAG
>
	OPEN	0,SGAMOD	;TRY TO ASSIGN DEVICE, SINCE IT MUST BE DONE
>
IFN FT2REL,<
	MOVE	T1,SGADEV(R)	;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)
IFE FT2REL,<
	MOVE	W,SGAEND(R)	;RESTORE W
>
	SETZM	SGAEND(R)	;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,SGAEXT(R)	;DID USER SPECIFY AN EXTENSION ?
	MOVSI	T1,SAVDMP##	;NO, USE .SAV OR .DMP
	MOVEM	T1,SGAEXT(R)	;AND STORE FOR LOOK UP OR ENTER

	MOVE	T1,JOBFF##(R)	;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?
	  MOVE	T1,USRREL##	;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,SGADMP(R)	;STORE IOWD WORD OF THIS SIZE CORE

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

SG4::
IFN FTKI10!FTKL10,<
	PUSHJ	P,SETASJ	;SET EXEC MODE UUO FLAG
>
IFN FTDISK,<
	MOVE	T2,DEVMOD(F)	;RETURN DEVICE CHARACTERISTICS(IF DISK SYS)
	TLNE	T2,DVDSK	;IS THIS DEVICE A DISK?
	MOVS	T1,SGAPPN(R)	;YES, MAKE SURE FOURTH WORD IS PROJ,R NO.
>
	MOVSM	T1,SGALEN(R)	;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


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
;	IFN FTDISK,<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:	PUSHJ	P,SETASA	;SET EXEC MODE UUO FLAG
IFN FTTLIM,<	MOVSI	T1,(JB.LSY)	;CLEAR GOTTEN FROM SYS: FLAG
	ANDCAM	T1,JBTLIM##(J)	; ..
>
	MOVEI	T1,JS.RUU	;SET RUN UUO/COMMAND FLAG
	IORM	T1,JBTSTS##(J)	;  SO FILSER CAN READ EXECUTE-ONLY FILES
	MOVEI	T1,JS.XOR	;CLEAR XO-STATUS
IFN PRIVN,<
	HRLI	T1,JACCT	; AND JACCT
>
	ANDCAM	T1,JBTSTS##(J)	;  ..
IFN FTFDAE,<
	MOVSI	T1,(JS.FXO)
	ANDCAM	T1,JBTST2##(J)
>
IFN FT2REL,<
	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

IFN FTEXE,<
	SKIPA			; 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.
>;END OF IFN FTEXE CONDITIONAL
>;END OF IFN FT2REL
	PUSHJ	P,LUKFIL	;LOOKUP LOW FILE
	  JRST	NOFILE		;GO PRINT FILE.EXT NOT FOUND
GJOB4:	HLRE	T2,SGALEN(R)	;-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,SGALEN(R)
GJOB5:	PUSHJ	P,CKIOWD	;CHECK USER'S SUPPLIED CORE ARG TO MAKE SURE NOT
				; TOO SMALL, RETURN LARGER OF FILE SIZE OR CORE ARG
IFN FTVM,<
	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,SGALEN(R)	;YES, USE USER-SPECIFIED CORE ARGUMENT
	HRRZS	JOBPD1##(R)	;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
IFN FTEXE,<
	HLRZ	T1,JOBSVM##-1(R)  ;GET 1ST WORD OF FILE
	CAIN	T1,SV.DIR	;IS THIS AN EXE FILE?
	JRST	EXESAV##	;YES, GIVE ERROR MESSAGE
>	;END OF IFN FTEXE
	MOVE	T1,JOBS41##(R)	;RESTORE USER UUO JSR LOC
	MOVEM	T1,JOB41##(R)	;SAVED BY SAVE
GJOB5B:	PUSH	P,F		;SAVE SYSDEV BIT
IFN FTVM,<
	SKIPN	.UPMP+.UPREL	;NO LOWFIN IF NON-CONTIGUOUS
>;END OF IFN FTVM
	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:	PUSH	P,F		;SAVE F SINCE IF NO LOOKUP WAS DONE IT IS
				; NOT STORED IN USRJDA

IFN FTVM,<
	PUSHJ	P,MINGET
>
	PUSH	P,USRREL##	;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,USRREL##	;SMALLER YET?
	MOVE	T1,USRREL##	;
IFN FTTIME,<	MOVEI	T2,MJOBDA##(T1)	;NO. OF WORDS TO CLEAR(-JOB DATA AREA)
	ADDM	T2,CLRWRD##	;INCREASE TOT. NO. WORDS CLEARED BY SYSTEM
>
IFN FTKI10!FTKL10,<
				;SET T3=0 IF KI10
	MOVEI	T3,0		; (USE XCT PAGED)
>
IFN FTKA10,<
	HRRZ	T3,R		;SET TO RELOCATE IF KA
>
	MOVEI	T2,JOBDA##+1(T3)	;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)
	ADDI	T1,(T3)		;RELOCATE FINAL DEST.ADR.
	EXCTUU	<BLT T2,(T1)>	;CLEAR FROM 140 TO TOP OF LOW SEG
GJOB2:	IFN FTVM,<
	PUSHJ	P,HSVAD##	;GET HIGHEST RELATIVE ADDRESS IN THE HI SEG
	HRRM	T1,.JDAT+JOBHRL## ;SET HIGHEST RELATIVE LOC FOR USER
>
	MOVE	T1,SGANAM(R)	;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
IFN FTKI10!FTKL10,<
	TDNE	T2,JBTSTS##(J)	;IS IT EXECUTE ONLY?
	PUSHJ	P,MAPHGH##	;YES, MAKE SURE THE MAP REFLECTS THAT
>
	MOVEI	T1,JS.RUU	;CLEAR FLAG OF
	ANDCAM	T1,JBTSTS##(J)	;  RUN UUO
IFN FTFDAE,<
	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
	HRRZ	T1,F		;IF (F)
	CAIE	T1,DSKDDB##	;=DSKDDB, NO LOOKUP DONE
	JRST	GJOB6		;LOOKUP WAS DONE
	MOVE	J,JOB##		;JOB NUMBER
	MOVE	T1,JBTSGN##(J)	;HIGH SEGMENT NUMBER
	MOVE	T2,JBTPPN##(T1)	;DIRECTORY AND
	MOVE	T1,JBTDEV##(T1)	;STR WHERE PROGRAM CAME FROM
	JRST	GJOB7		;STORE THEM
GJOB6:	PUSHJ	P,NAMSTR##	;STR
	  MOVE	T1,DEVNAM(F)	;NOT A DSK, DEVICE NAME
	MOVSI	T2,DVDSK	;DEVICE IS A DSK BIT
	TDNE	T2,DEVMOD(F)	;IS IT A DSK?
	SKIPA	T2,DEVPPN(F)	;YES, GET DIRECTORY
	MOVEI	T2,0		;NO, NO DIRECTORY
GJOB7:	MOVEM	T1,.PDSTR##(W)	;STORE STR OR DEVICE NAME
	MOVEM	T2,.PDDIR##(W)	;AND DIRECTORY
>
IFN FTWATCH&FTVERS,<
	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
	PUSHJ	P,VERBTH	;PRINT BOTH SEGMENTS
	PUSHJ	P,PGMFIL
	PUSHJ	P,PRRBKC	;PRINT RIGHT BRACKET <CRLF>
>
GJOB8:	PUSHJ	P,SGREL		;RELEASE DDB
IFN FTKI10!FTKL10,<
	MOVSI	T1,(R)
	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
	SKIPLE	T2,JBTSGN(J)	;WAS THERE A HIGH SEGMENT?
	TLNN	T1,DVDSK	;YES, AND DID IT COME FROM THE DISK
	JRST	GJOB3		;NO, JUST DO THE LOOKUP
	SKIPN	T1,DEVPPN(F)	;PPN FROM WHENCE THE HIGH SEGMENT CAME
	MOVE	T1,JBTPPN##(T2)	;NO LOOKUP WAS DONE FOR THE HI SEG
	PUSH	P,T1		;SAVE THE PPN
	MOVE	T1,SGAPPN(R)	;GET USER SPECIFIED PPN
	MOVEM	T1,SGANAM+3(R)	;AND USE FOR LOOKUP
	LOOKUP	0,SGANAM	;LOOKUP LOW SEGMENT FILE
	  SETOM	DEVPPN(F)	;NOT FOUND
	POP	P,T1		;RESTORE HIGH SEGMENT PPN
	CAMN	T1,DEVPPN(F)	;WAS LOW SEGMENT FOUND IN THE SAME UFD?
	JRST	CPOPJ1##	;SKIP ON
	EXCH	T1,DEVPPN(F)	;GET RETURNED VALUE, REAL HISEG PPN
	AOJE	T1,CPOPJ	;GO IF REAL LOOKUP ERROR
	HLLZS	SGAEXT(R)	;FILE NOT FOUND ERROR AS
	POPJ	P,		; SOMEONE IS TRYING TO CHEAT
GJOB3:	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
;
IFN FTVM,<
CKVLIM:	LSH	T1,W2PLSH##	;PAGE #
	HLRZ	T2,.PDCVL##(W)	;GET VIRTUAL LIMIT
	MOVSI	T3,(UP.GET)	;CHECK GET BIT
	TDNN	T3,.UPMP+.UPBTS
	CAIL	T1,(T2)		;WANT MORE THAN THAT?
	POPJ	P,		;YES
	JRST	CPOPJ1##	;NO
>	;END OF IFN FTVM
IFN FTWATCH&FTVERS,<
;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
IFN FTMS,<
	PUSHJ	P,ONCPU0##
>
	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,.C0JOB##	;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,FSFPPN##	;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
IFN FTVM,<
;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	.UPMP+.UPVRT	;VIRTUAL?
	SKIPE	.UPMP+.UPMEM	;OR NON-CONTIGUOUS
GET1PG::SKIPA	T1,MINCOR	;YES
MINCOR:	POPJ	P,PAGSIZ##-1	;NO, RETURN
	HRRZM	T1,SGACOR(R)	;ONE PAGE
	CALLI	SGACOR,200011	;REDUCE LOW SEG IMAGE TO PAGE ZERO
	  JFCL			;CAN'T FAIL
	HRRZS	JOBPD1##(R)	;CLEAR USER MODE SINCE CAN'T RETURN TO USER
	POPJ	P,		;AND RETURN
>

;SUBROUTINE TO CLEAR VARIOUS TEM WHEN THE
; CONTENTS OF A CORE IMAGE IS CHANGED OR
; RENAMED (SAVE)

CLRTAB:	MOVE	T1,[JACCT,,JS.XO]  ;CLEAR EXECUTE ONLY SO
	ANDCAM	T1,JBTSTS##(J)	; USER WILL NOT BE RESTRICTED
	MOVSI	T1,(JB.LSY)	;NO LONGER A PROGRAM
	ANDCAM	T1,JBTLIM##(J)	; FROM SYS
IFN FTFDAE,<
	PUSHJ	P,FNDPDS##	;POINT TO PDB
	SETZM	.PDNAM##(W)	;ZERO NAME
	SETZM	.PDSTR##(W)	; AND STR
	SETZM	.PDDIR##(W)	; AND PPN
>
	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,DVMTA	;MAGTAPE?
	TLNN	F,INPB		;YES, WAS AN INPUT DONE?
	JRST	SGREL1		;NO
	CLOSE	0,CLSOUT	;YES, CLOSE MTA INPUT
	STATO	0,IOTEND+IODEND	;AT END OF APTE?
	MTAPE	0,16		;NO SKIP TO EOF
SGREL1:	RELEASE	0,		;NO RELEASE DEVICE
	POP	P,S
SGREL2:
	PUSHJ	P,CLRASA	;CLEAR EXEC MODE UUO FLAG
	PUSHJ	P,TTYFNU##	;FIND TTY FOR CURRENT USER SET J TO CURRENT JOB
IFE FTVM,<
	SKIPE	T2, USREPL##	;DID SAVE, GET, R, OR RUN CAUSE EXTENDED PD LIST?
	PJRST	GIVEPL##	;YES, RETURN IT TO FREE CORE
>	;END IFE FTVM
	POPJ	P,
;SUBROUTINE TO ADJUST LOW SEG CORE ACCORDING TO ARG
; ON GET OR PREVIOUS SAVE
;CALL:	PUSHJ P,LOWFIN
;	ALWAYS RETURN

LOWFIN:
	HRRZ	T1,JOBCOR##(R)	;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,USRREL##	;YES, USE ASSIGNMENT MADE WEN LOW FILE READ IN
	PUSHJ	P,CKSARG	;RETURN ONLY IF USER'S SUPLLIED ARG IS 0 OR NOT
				; SMALLER THAN SAVE CORE ARG, RETURN LARGER
IFE FTVM,<
	PUSHJ	P,GETCOR	;TRY TO GET THIS AMOUNT OF CORE
>
IFN FTVM,<
	HRRZM	T1,SGACOR(R)	;STORE CORE ARGUMENT
	PUSH	P,T1		;SAVE IN CASE OF AN ERROR
	MOVE	T1,SGANAM(R)	;NAME OF PROGRAM
	PUSHJ	P,PRVPG		;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,USRREL##	;HIGHEST LOC ASSIGNED TO LOW SEG
	HRRM	T1,JOBCOR##(R)	;SET INITIAL CORE ASSIGNMENT IN JOB DATA AREA FOR
				; USER TO USE TO RESET CORE TO INITIAL SETTING WHEN
				; PROGRAM IS RESTARTED
IFE FTVM,<
	POPJ	P,
>
IFN FTVM,<
	JRST TPOPJ##
>
;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:
IFN FTEXE,<
	SETZM	SGAEND(R)
>
	XCT	@(P)		;EXECUTE INPUT OR OUTPUT UUO
	MOVE	J,JOB##		;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,JOBDDT##(R)	;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
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,SGALEN(R)	;-LENGTH OF FILE
	MOVNS	P3		;+LENGTH OF FILE
	ADDI	P3,JOBSVM##	;ADD FIRST LOC-1 TO FORM HIGHEST LEGAL ADR.
IFN FTKI10!FTKL10,<
	HRLI	P3,0		;KI10 STYLE RELOCATION
				;IF KI10, LEAVE LH(P3)=0
				; (USE XCT PAGED INSTEAD)
>
IFN FTKA10,<
	HRLI	P3,R		;PUT R IN LH FOR COMPARE
				; P3 SET FOR ADDRESS CHECKING BELOW
>
	SKIPL	T1,JOBSV##(R)	;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,JOBSV##(R)	;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	JOBSV3##(R)	;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,JOBSV##(R)	;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,JOBSV##(R)
	MOVEM	T1,2(T2)	;STORE IN COMPRESSED DATA
	JRST	EXPND1
EXPZ:	MOVSI	T1,-2
	HLLM	T1,JOBSV##(R)
;COME HERE TO DO THE ACTUAL EXPANSION OF A FILE
EXPND1:	MOVEI	T1,JOBSV##	;IT WAS READ INTO JOBSV
	HLL	T1,P3		;LH(T1)=R IF KA,=0 IF KI
	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,JOB##		;NO, IS TIS THE CURENT JOB?
	JRST	SGDOER		;NO, GIVE ERROR RETURN, MUST BE COMMAND DECODER
				; DOING EXPAND AFTER USER HAS REDUECED CORE
	PUSHJ	P,GETCOR	;YES. GET IT
EXPCOR:	POP	P,T2
IFN FTKI10!FTKL10,<
	HLRZ	T3,T2		;T3=0 IFF KI10
>
	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
	HLL	T1,T2		;R INTO LH(T1) IF KA10
	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
IFN FTKA10,<
	ADDI	P1,(R)		;RELOCATE
>
	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
IFN FTKI10!FTKL10,<
	CAIGE	P1,JOBSDD##
	JRST	EXPLP5
	JRST	EXPLP6
>				;END CONDITIONAL FTKI10
IFN FTKA10,<
	CAIGE	P1,JOBSDD##	;DON'T STORE DATA BELOW JOBSDD
>
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,JOBSDD##(R)	;YES. ZERO JOBSDD
	MOVEM	P2,JOBDDT##(R)	;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
IFN FTKA10,<
	ADDI	T2,(R)		;RELOCATE 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
IFN FTKA10,<
	ADDI	T1,(R)		;RELOCATE
>
	HRLI	T1,JOBSVD##(T1)	;OR CONVERT SAVE FILE
	SKIPGE	JOBSV##(R)	;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	JOBHCU##(R)	;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,SGALEN(R)	;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,SGANEW(R)	;IS USER SUPPLIED ARG BIGGER?
	JRST	CKSAR1		;NO
	MOVE	T1,SGANEW(R)	;YES, RETURN IT
	POPJ	P,
CKSAR1:	PUSH	P,T1		;IN CASE OF ERROR
	SKIPN	SGANEW(R)	;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
	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::
IFN FTEXE,<
	PUSHJ	P,SAVE1##	;SAVE P1 FOR EXE FILES
>
	HRRZM	T1,SGACOR(R)	;SOTRE CORE ARG FOR CORE UUO IN USER AC
	PUSH	P,T1		;SAVE IN CASE OF ERROR
IFN FTVM,<
	MOVE	J,.C0JOB##
	MOVE	T4,T1
	SKIPN	T2,.UPMP+.UPREL
	HLRZ	T2,R
	IORI	T4,PG.BDY##
	SUB	T4,T2
	LSH	T4,W2PLSH##
	PUSHJ	P,GSIZT##
	  JRST	GETGET
	  SKIPA	T2,.UPMP+.UPBTS
	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
IFN FTVM,<
GETGET::MOVE	T4,T1
	MOVE	T1,SGANAM(R)
	TLNE	F,SYSDEV
	PUSHJ	P,PRVPG
	  SKIPA	T1,JBTSTS##(J)
	JRST	GETCR1
	TLNE	T1,JACCT
	JRST	GETCR1
GETGTS::LSH	T4,W2PLSH##
	HLRZ	T2,.PDCVL##(W)	;CURRENT VIRTUAL LIMIT FOR JOB
	MOVSI	T3,(UP.GET)
	TDNN	T3,.UPMP+.UPBTS
	CAIL	T4,(T2)		;WANT MORE THAN THAT?
	JRST	NOROOM		;YES, ERROR
	IORM	T3,.UPMP+.UPBTS
	JSP	T1,MONSTR##	;RESET P TO AVOID PDL OVF SINCE STARTING ALL OVER
	PUSHJ	P,RMVPFH	;DELETE DEFAULT PFH, IF THERE
	HRRZS	USRHCU##
	HRRZS	JOBHCU##(R)
	MOVEI	T1,JS.RUU
	ANDCAM	T1,JBTSTS##(J)
	MOVEI	T1,.UPMP+.UPUAC-1
	PUSH	T1,SGADEV(R)	;NO, SAVE WHAT HE WANTS TO GET
	PUSH	T1,SGANAM(R)
	PUSH	T1,SGAEXT(R)
	HLRZ	T2,SGAEXT(R)
	MOVE	T3,SGAHGH(R)
	CAIN	T2,'LOW'
	HLLZM	T3,(T1)
	PUSH	T1,SGAPPN(R)
	SETZM	SGAPPN(R)
	AOBJP	T1,.+1		;SKIP SIXBIT COMMAND OR UUO NAME	
	PUSH	T1,SGANEW(R)
	MOVE	T1,[PHONLY,,DR]
	MOVSI	T2,'SYS'
	SETZB	T3,T4
	DMOVEM	T1,SGAMOD(R)
	DMOVEM	T3,SGAMOD+2(R)
	MOVSI	T1,'GET'
	MOVEM	T1,SGANAM(R)
	DMOVEM	T3,SGANAM+2(R)
	MOVE	T1,['SHRHGH']
	MOVEM	T1,SGAHGH(R)
	MOVE	T1,.UPMP+.UPUAC+4
	TRNN	T1,-1
	PUSHJ	P,GETMIN
	HRRZS	JOBPD1##(R)
IFN FTEXE,<
	MOVSI	T1,GTHGH
>
	PUSHJ	P,GETSEG##
	 JRST	NOFILE
IFN FTEXE,<
	  JFCL
>
;CONTINUED ON NEXT PAGE
	PUSHJ	P,CLRASA
	MOVSI	T1,.UPMP+.UPUAC
	EXCTXU	<BLT T1,7>
	HRRZ	T2,.VJDT+.JBHSA##
	MOVE	T1,['GETSEG']
	CAMN	T1,.UPMP+.UPUAC+4
	JRST	STARTU
	HRLZ	T1,.VJDT+.JBHSA##
	PUSH	P,T1
	HLLZS	JOBSA##(R)
	JRST	URUN3
>

SETASJ::PUSH	P,J		;SAVE J
	MOVE	J,.C0JOB##	;J=JOB NUMBER OF CURRENT JOB
	PUSHJ	P,SETASA	;MAKE AC REFERENCES BE TO THE SHADOW AREA
	JRST	JPOPJ##		;RESTORE J AND RETURN

SETASA::PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,JS.ASA	;LITE THE BIT WHICH INDICATES REFERENCES TO
	IORM	P1,JBTSTS##(J)	; LOCATIONS 0-17 IN THE USER'S AREA ARE TO SHADOW ACS
	POPJ	P,		;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,SGAEXT(R)	;SEE WHICH ERROR
	JUMPN	T1,LOOKFL	;NOT NOT FOUND
	MOVE	T2,SGANAM(R)	;PRINT FILE NAME
	PUSHJ	P,PRNAME##
	PUSHJ	P,PRPER		;PRINT PERIOD
	HLLZ	T2,SGAEXT(R)	;PRINT EXTENSION
	PUSHJ	P,PRNAME##
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/ not found/

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


LKENFL:	PUSHJ	P,CONMES	;ISSUE MESSAGE
	HRRZ	T1,SGAEXT(R)	;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
IFN FTDISK,<
	MOVE	T2,DEVMOD(F)	;IS THIS DEVICE A DISK?
	TLNE	T2,DVDSK
	HRRZ	T1,SGAEXT(R)	;YES, RETURN DISK SERVICE ERROR CODE
>
SGRELE::PUSH	P,T1		;SAVE T1
	MOVE	J,.C0JOB##	;GET JOB #
	SKIPE	JOBPD1##(R)	;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.
	PUSHJ	P,KILHSH##	;KILL THE HISEG IF NOT SAVE
	MOVEI	T2,JS.RUU	;CLEAR RUN FLAG
	ANDCAM	T2,JBTSTS##(J)	;  SO FILSER STOPS ITS CHECKS
	MOVE	T2,JOBPD1##(R)	;GET FIRST PC ON 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
	HRR	M,T2		;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)
	HLRZ	T2,T1		;GET OP CODE
	CAIN	T2,(HALT)	;IS LH HALT?
	JRST	SGRLE1		;YES, RELEASE DEVICE,FIND TTY, AND RETURN TO CALLER
	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,JOBPD3##(R)	;NO, AC NUMBER OF RUN OR GETSEG UUO
	POP	P,T1		;RESTORE ERROR CODE
	PUSHJ	P,PUTWDU##	;STORE ERROR NUMBER IN USER AC
	PUSH	P,JOBPD1##(R)	;PUT RETURN ON END OF PDLIST
	JRST	USRXIT##	;AND RETURN TO USER TO HANDLE ERROR

SGRLE1:	POP	P,T1		;REMOVE ERROR CODE FROM LIST
IFN FTKI10!FTKL10,<
	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
	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