Google
 

Trailing-Edge - PDP-10 Archives - bb-k345a-sb - path.mac
There are 5 other files named path.mac in the archive. Click here to see a list.
TITLE	PATH -- Monitor level SETSRC commands plus enhancements
SUBTTL	G.M. Uhler/GMU  19-Jun-80


;COPYRIGHT (C) 1978, 1979, 1980 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


	SEARCH	JOBDAT,MACTEN,SCNMAC,UUOSYM
	.DIRECTIVE .XTABM,FLBLST
	SALL		; CLEAN UP LISTING

;
;Show versions of universal files

	%%JOBD==%%JOBD
	%%MACT==%%MACT
	%%SCNM==%%SCNM
	%%UUOS==%%UUOS


	PTHVER==1	; DEC VERSION
	PTHMIN==0	; DEC MINOR VERSION
	PTHEDT==11	; DEC EDIT NUMBER
	PTHWHO==0	; WHO LAST EDITED

	TWOSEG
	RELOC	400000
	LOC	.JBVER
	VRSN.	(PTH)	; VERSION NUMBER TO JOB DATA AREA
	RELOC
	SUBTTL	Revision history


COMMENT `

[1]	26-Mar-79	The sequence .PATH<CR> .CONTINUE<CR> caused
			I/O to unassigned channel.  Make CONTINUE act
			the same as REENTER.
[2]	12-May-79	Change the logical name code to know about the
			new format for the logical name block.
[3]	29-May-79	If PATH gets an error return trying to do a /CLEAR,
			it loops forever retrying the UUO.  Give up with
			an appropriate message if the /CLEAR fails
[4]	07-Aug-79	If /PHYSICAL is applied to any component in a
			logical name definition, PATH will ignore any
			existing logical name in performing the substitution
			for the component.
[5]	21-Aug-79	In search list switches where the user types
			a * with no modifiers (e.g., NOCREATE), keep
			the existing modifier bits for each structure
			represented by the *.
[6]	15-Nov-79	APLSTK was AOBJNing on the wrong AC sometimes
			causing a loop.  Correct the AC.
[7]	06-Dec-79	"pa/mod:dskb:write" (note the lower case) would
			result in "?PTHUSM Unknown structure modifier 7RITE"
			Call .SIXSW instead of .SIXSC.
[10]	18-Jun-80	Change the job search list before changing the
			default path so the user can do both in the same
			command if the SFDs in the path only exist on the
			structure being added.
[11]	18-Jun-80	Change the processing of /SEARCH and /LIB to
			reflect the new monitor algorithm.

`	; End revision history
	SUBTTL	Symbol definitions


;AC definitions
;
	F==0		; FLAGS
	T1==1		; FIRST OF FOUR TEMPORARIES
	T2==2
	T3==3
	T4==4
	P1==5		; FIRST OF FOUR PRESERVED REGISTERS
	P2==6
	P3==7
	P4==10
	N==P3		; SCAN CONVENTION
	C==P4		; SCAN CONVENTION
	P==17		; PDL POINTER
;
;Miscellaneous definitions
;
	ND .PDLEN,100	; LENGTH OF PDL
	ND DEBUG$,0	; NO DEBUG FEATURES
	TTY==1		; TTY CHANNEL
;Flag bits in F
;
	FL.ERR==1B0	; FATAL ERROR ENCOUNTERED
	FL.WRN==1B1	; WARNING MESSAGE ISSUED
	FL.TEL==1B2	; INFORMATIVE MESSAGE ISSUED
	FL.SDP==1B3	; USER TYPED SOMETHING REQUIRING NEW DEFAULT PATH
	FL.SAP==1B4	; USER TYPED SOMETHING REQUIRING NEW ADDITIONAL PATH
	FL.SLN==1B5	; USER TYPED SOMETHING REQUIRING LOGICAL NAME
	FL.JSL==1B6	; USER TYPED SOMETHING REQUIRING NEW SEARCH LIST
	FL.SSL==1B7	; USER TYPED SOMETHING REQUIRING NEW SYSTEM SEARCH LIST
	FL.CPT==1B8	; USER WANTS TO CHANGE HIS DEFAULT PATH
	FL.RDP==1B9	; PTSDP CONTAINS CURRENT DEFAULT PATH
	FL.RAP==1B10	; PTSAP CONTAINS CURRENT ADDITIONAL PATH
	FL.CLN==1B11	; USER WANTS TO CHANGE A LOGICAL NAME
	FL.GSO==1B12	; USER TYPED GLOBAL SWITHES ONLY
	FL.LSN==1B13	; USER WANTS TO LIST A LOGICAL NAME
	FL.FST==1B14	; GENERAL FLAG USED TO INDICATE 1ST TIME SOMETHING HAPPENS
	FL.TOF==1B15	; TTY OPEN FAILED, USE OUTCHRS
	FL.SLS==1B16	; USER TYPED AT LEAST ONE SYS SEARCH LIST SWITCH
	FL.JLS==1B17	; USER TYPED AT LEAST ONE JOB SEARCH LIST SWITCH
	FL.CSL==1B18	; ALREADY COPIED CURRENT SEARCH LIST INTO NEW SL
;
;The following flags are stored in L.LIST by SCAN when it processes
;the /[NO]LIST switch.  They are then moved to F for processing.
;
	FL.LST==1B<^D36-<LSW.L+1>> ; LIST THINGS IN CONTEXT OF COMMAND (/L)
	FL.LAL==1B<^D36-LSWALL>	   ; LIST EVERYTHING (/L:ALL)
	FL.LLN==1B<^D36-LSWNAMES>  ; LIST LOGICAL NAMES (/L:NAMES)
	FL.LSS==1B<^D36-LSWSSL>    ; LIST SYSTEM SEARCH LIST (/L:SSL)
	FL.LJS==1B<^D36-LSWJSL>    ; LIST JOB SEARCH LIST (/L:JSL)
	FL.LPT==1B<^D36-LSWPATH>   ; LIST PATH (/L:PATH)
	FL.LCG==1B<^D36-LSWCHANGE> ; LIST THOSE THINGS THAT HAVE CHANGED (/L:CHANGE)
	FL.LSW==FL.LLN!FL.LSS!FL.LJS!FL.LPT!FL.LCG ; ALL LIST FLAGS MINUS FL.LST AND FL.LAL
	SUBTTL	Macro definitions


;The following symbols define the error option selected by the third
;argument to the ERROR, WARN, and TELL macros.
;
	EO.NUL==0		; NO OPTION GIVEN
	EO.STP==1		; STOP PROGRAM ON THIS ERROR
	EO.NCR==2		; NO CRLF AT END OF THIS MESSAGE
	EO.MAX==2		; MAX NUMBER OF ERROR OPTIONS


;Macro to type a fatal error message.  The arguments are:
;
;	PRFX	- Error prefix, e.g., the XXX in ?PTHXXX ...
;	FIRST	- The message to be typed
;	OPTION	- Error option; may be STOP, NOCRLF, or blank
;	LABEL	- Label to jump to after message is issued
;
	DEFINE	ERROR	(PRFX,FIRST,OPTION,LABEL), <
	  ERRFLG==EO.NUL
	  IFIDN	<OPTION>,<STOP>,   <ERRFLG==EO.STP>
	  IFIDN	<OPTION>,<NOCRLF>, <ERRFLG==EO.NCR>

	  PUSHJ	P,.ERR
	  XLIST
	  F..'PRFX==.
	  IFNB	<LABEL>, <CAIA ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]
			  JRST LABEL
			 >
	  IFB	<LABEL>, <CAI  ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]>
	  LIST
	> ; End DEFINE ERROR
;Macro to type a warning message.  The arguments are:
;
;	PRFX	- Error prefix, e.g., the XXX in %PTHXXX ...
;	FIRST	- The message to be typed
;	OPTION	- Error option; may be STOP, NOCRLF, or blank
;	LABEL	- Label to jump to after message is issued
;
	DEFINE	WARN	(PRFX,FIRST,OPTION,LABEL), <
	  ERRFLG==EO.NUL
	  IFIDN	<OPTION>,<STOP>,   <ERRFLG==EO.STP>
	  IFIDN	<OPTION>,<NOCRLF>, <ERRFLG==EO.NCR>

	  PUSHJ	P,.WARN
	  XLIST
	  W..'PRFX==.
	  IFNB	<LABEL>, <CAIA ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]
			  JRST LABEL
			 >
	  IFB	<LABEL>, <CAI  ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]>
	  LIST
	> ; End DEFINE WARN


;Macro to type an informative message.  The arguments are:
;
;	PRFX	- Error prefix, e.g., the XXX in [PTHXXX ...]
;	FIRST	- The message to be typed
;	OPTION	- Error option; may be STOP, NOCRLF, or blank
;	LABEL	- Label to jump to after message is issued
;
	DEFINE	TELL	(PRFX,FIRST,OPTION,LABEL), <
	  ERRFLG==EO.NUL
	  IFIDN	<OPTION>,<STOP>,   <ERRFLG==EO.STP>
	  IFIDN	<OPTION>,<NOCRLF>, <ERRFLG==EO.NCR>

	  PUSHJ	P,.TELL
	  XLIST
	  T..'PRFX==.
	  IFNB	<LABEL>, <CAIA ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]
			  JRST LABEL
			 >
	  IFB	<LABEL>, <CAI  ERRFLG,[XWD ''PRFX'',[ASCIZ\FIRST\]]>
	  LIST
	> ; End DEFINE TELL
;Macro to type debug information on entry to a subroutine. Debugging
;information is typed if one of the following conditions is met:
;
;	1. PATH is assembled with DEBUG$ non-zero to assemble
;	   the debugging package.
;	2. The location DEBALL is deposited non-zero.  This will
;	   type debugging information for all subroutines.
;	3. If information about a particular routine in desired,
;	   leave DEBALL zero and change the SKIPE DEBALL before
;	   each call to .DEBUG to a JFCL.
;
;the arguments are as follows:
;
;	$NAME - NAME of the routine
;	$LIST - LIST of locations to type on entry
;
;If the switch DEBUG$ is zero, this macro assembles
;nothing.

	DEFINE	TRACE$	($NAME,$LIST), <
	  IFN DEBUG$, <		;; ASSEMBLE ONLY IF DEBUG IS ON
	    SKIPE DEBALL	;; TYPE ONLY IF WANTED
	    XLIST
	    PUSHJ P,.DEBUG	;; CALL DEBUG ROUTINE
	    CAI	  [SIXBIT/$NAME/	;; GENERATE ROUTINE NAME
	    IFNB <$LIST>, <
	      IRP $LIST, <		;; FOR ALL ELEMENTS OF $LIST
	        EXP   $LIST	;; PLUS ADDRESS
	      >	;; END IRP $LIST
	    >	;; END IFNB $LIST
	    XWD   -1,0]		; -1,,0 TERMINATES BLOCK
	    LIST
	  >	;; END IFN DEBUG$
	>	;; END DEFINE TRACE$
;Macro to generate the storage words for those switches that are
;entirely processed by SCAN, i.e., those for which SCAN doesn't call us.
;Symbols generated are as follows:
;
;	S.XXXX		Non-file specific switch storage
;	F.XXXX		File specific switch storage that will be
;			moved into the scan block
;	P.XXXX		Sticky default storage for file-specific
;			switches.  (parallel table to F.XXXX)
;	$SWXXX		Offset of the switch relative to the start
;			of the specific switch block
;	$FXXXX		Offset in the scan block of file-specific
;			switch storage and extra word storage
;
	DEFINE	SWTGEN  ($SLIST,$FLIST,$XLIST), <
	  XLIST
	  SW.BGN==.		;; DEFINE START OF SWITCH AREA
	  ;;
	  ;; GENERATE STORAGE WORDS FOR EACH SWITCH
	  ;;
	  S.BGN==.		;; DEFINE START OF NON-FILE SWITCH AREA
	  IRP $SLIST, <
	    $SW'$SLIST==.-S.BGN	;; DEFINE OFFSET OF SWITCH IN AREA
	    S.'$SLIST: BLOCK 1	;; LOCATION CONTAINING VALUE OF SWITCH
	  >  ; END IRP $SLIST
	  S.END==.-1		;; DEFINE END OF NON-FILE SWITCH AREA
	  S.LEN==S.END-S.BGN+1	;; DEFINE LENGTH OF NON-FILE SWITCH AREA

	  F.PTR==.FXLEN		;; LOCAL FILE SWITCH SCAN BLOCK AREA STARTS HERE
	  F.BGN==.		;; DEFINE START OF FILE SWITCH AREA
	  IRP $FLIST, <
	    $SW'$FLIST==.-F.BGN	;; DEFINE OFFSET OF SWITCH IN AREA
	    $FX'$FLIST==F.PTR	;; DEFINE OFFSET OF SWITCH IN SCAN BLOCK
	    F.PTR==F.PTR+1	;; BUMP SCAN BLOCK POINTER
	    F.'$FLIST: BLOCK 1	;; VALUE OF FILE SWITCH GOES HERE
	  >  ; END IRP $FLIST
	  F.END==.-1		;; DEFINE END OF FILE SWITCH AREA
	  F.LEN==F.END-F.BGN+1	;; DEFINE LENGTH OF FILE SWITCH AREA
	  $FXLLS==F.PTR-1	;; DEFINE OFFSET OF LAST SWITCH IN SCAN BLOCK
	  SW.END==.-1		;; DEFINE END OF SWITCH AREA
	  SW.LEN==SW.END-SW.BGN+1  ;; DEFINE LENGTH OF SWITCH AREA

	  IRP $XLIST, <
	    $FX'$XLIST==F.PTR	;; DEFINE EXTRA WORDS IN SCAN BLOCK
	    F.PTR==F.PTR+1	;; ADVANCE POINTER
	  >  ; END IRP $XLIST
	  $FXLEN==F.PTR		;; DEFINE TOTAL LENGTH OF SCAN BLOCK

	  P.BGN==.		;; STICKY DEFAULT SWITCH AREA STARTS HERE
	  ;;
	  ;; GENERATE WORDS FOR STICKY DEFAULTS
	  ;;
	  IRP $FLIST, <
	    P.'$FLIST: BLOCK 1	;; VALUE OF STICKY DEFAULT GOES HERE
	  >  ; END IRP $FLIST

	  P.END==.-1		;; DEFINE END OF STICKY DEFAULT AREA
	  LIST
	>  ; END DEFINE SWTGEN
;In order to process the search list switches, we define two types of
;blocks.  The first, defined below, is associated with each search list
;switch and gives parameters specific to each switch.
;
;	!=======================================================!
;	!                    PJSP T1,?SLSWT                     ! $SLJSP
;	!-------------------------------------------------------!
;XXXBLK:!Address of first word of block containing switch values! $SLSPT
;	!-------------------------------------------------------!
;	!   AOBJP pointer to next free slot for switch values   ! $SLSAB
;	!-------------------------------------------------------!
;	!     Count of structures specified by this switch      ! $SLSCT
;	!=======================================================!

	$SLJSP==-1	; OFFSET TO PJSP T1,?SLSWT
	$SLSPT==0	; OFFSET TO ADDR OF SWITCH VALUE BLOCK
	$SLSAB==1	; OFFSET TO AOBJP POINTER TO NEXT FREE
			; SLOT IN SWITCH VALUE BLOCK
	$SLSCT==2	; OFFSET OF COUNT OF STRS IN SWITCH VALUE
			; BLOCK
	$SLSLN==3	; LENGTH OF POSITIVE OFFSET BLOCK
			; (I.E., NOT INCLUDING $SLJSP)


;The following block gives information about the search list (either
;job or system) that is independent of the particular switch specified.
;
;	!=======================================================!
;	!      Count of structures in current search list       ! $SLCCT
;	!-------------------------------------------------------!
;	!    Address of block containing current search list    ! $SLCPT
;	!-------------------------------------------------------!
;	!        Count of structures in new search list         ! $SLNCT
;	!-------------------------------------------------------!
;	!      Address of block containing new search list      ! $SLNPT
;	!-------------------------------------------------------!
;	!AOBJP pointer to next available slot in new search list! $SLNAB
;	!-------------------------------------------------------!
;	! Max number of structures allowed in this search list  ! $SLMAX
;	!=======================================================!

	$SLCCT==0	; COUNT OF STRS IN CURRENT SEARCH LIST
	$SLCPT==1	; ADDRESS OF CURRENT SEARCH LIST BLOCK
	$SLNCT==2	; COUNT OF STRS IN NEW SEARCH LIST
	$SLNPT==3	; ADDRESS OF FIRST STR IN NEW SEARCH LIST BLOCK
	$SLNAB==4	; AOBJP POINTER TO NEXT FREE SLOT IN NEW
			; SEARCH LIST
	$SLMAX==5	; MAX STRS ALLOWED IN THIS SEARCH LIST
	$SLXLN==6	; LENGTH OF THE BLOCK

	SL.WLD==1B35	; FLAG SET IN .DFJST WORD OF A SEARCH LIST BLOCK
			; TO INDICATE THAT THIS STR WAS ADDED TO THE
			; NEW SEARCH LIST BY A * REFERENCE.
;Macro to relocate to the high segment if not already there.

	DEFINE	$HIGH, <
	  IFL	<.-400000>, <
	    XLIST
	    LIT
	    RELOC
	    LIST
	  >
	>


;Macro to relocate to the low segment if not already there.

	DEFINE	$LOW, <
	  IFGE	<.-400000>, <
	    XLIST
	    LIT
	    RELOC
	    LIST
	  >
	>
;Macro to store a constant in consecutive memory locations (The one in
;MACTEN doesn't work right for FIRST==LAST).  Note that this macro has
;the restriction that it must be called only after the locations
;specified by FIRST and LAST are defined.  If this restriction is not
;met, MACRO will generate phase errors since it doesn't know how many
;words to generate on pass 1.
;The arguments are:
;
;	AC	- AC to use
;	FIRST	- FIRST location into which to store
;	LAST	- Last location into which to store
;	CONS	- Constant to store

	DEFINE	STORE(AC,FIRST,LAST,CONS), <
	  IFB <LAST>,< LAST%%==FIRST>	;; IF NO LAST, ASSUME FIRST
	  IFNB <LAST>,<LAST%%==LAST>	;; OTHERWISE USE LAST
	  IFL <LAST%%-FIRST>,<
	    PRINTX % FINAL LOCATION .LT. STARTING LOCATION IN STORE MACRO
	  >
	  IFE <CONS>,<  SETZM	FIRST>	;;IF CONS=0, CLEAR FIRST
	  IFE <CONS>+1,<SETOM	FIRST>	;;IF CONS=-1, SET FIRST TO -1
	  IFN <CONS>*<<CONS>+1>, <
	    MOVX	AC,<CONS>	;;ELSE DO IT
	    MOVEM AC,FIRST		;; THE HARD WAY
	  >
	  XLIST
	  IFG <LAST%%-FIRST>,<		;;IF MORE THAN ONE LOCATION
	    MOVE  AC,[FIRST,,FIRST+1]
	    BLT   AC,LAST%%		;;DISTRIBUTE THE CONSTANT
	  >
	  LIST
	>
	SUBTTL	Path switch definitions

;Define the prefixes for all search list switches.

	DEFINE	SLSWCH,<
	  XLIST
	  X	CR,J		;; /CREATE
	  X	AD,J		;; /ADD
	  X	RM,J		;; /REMOVE
	  X	MD,J		;; /MODIFY
	  X	CR,S		;; /SCREATE
	  X	AD,S		;; /SADD
	  X	RM,S		;; /SREMOVE
	  X	MD,S		;; /SMODIFY
	  LIST
	> ; End DEFINE SLSWCH


;Define the default maxima for each switch

	DEFINE	X ($PREFX,$TYPE), <
	  DM	'$PREFX'$TYPE',0,0,0 ;; MUST SPECIFY VALUE FOR SWITCH
	>

	SLSWCH			; GENERATE ALL DEFAULT MAXIMA


;Define the valid switches for SCAN

	DEFINE	SWTCHS, <
	  XLIST
	  SP	ADD,0,ADJSWT,ADJ,FS.LRG!FS.NFS!FS.VRQ ; /ADD:LIST
	  SS	CLEAR,S.CLEAR,1,FS.NFS			; /CLEAR
	  SP	CREATE,0,CRJSWT,CRJ,FS.LRG!FS.NFS!FS.VRQ ; /CREATE:LIST
	  SL	*LIST,L.LIST,LSW,FL.LST,FS.NFS!FS.OBV	;/LIST:OPTIONS
	  SP	MODIFY,0,MDJSWT,MDJ,FS.LRG!FS.NFS!FS.VRQ ; /MODIFY:LIST
	  SN	NEW,S.NEW,FS.NFS			; /[NO]NEW
	  SP	REMOVE,0,RMJSWT,RMJ,FS.LRG!FS.NFS!FS.VRQ ; /REMOVE:LIST
	  SP	SADD,0,ADSSWT,ADS,FS.LRG!FS.NFS!FS.VRQ ; /SADD:LIST
	  SN	SCAN,S.SCAN,FS.NFS			; /[NO]SCAN
	  SP	SCREATE,0,CRSSWT,CRS,FS.LRG!FS.NFS!FS.VRQ ; /SCREATE:LIST
	  SN	SEARCH,F.SEARCH				; /[NO]SEARCH
	  SP	SMODIFY,0,MDSSWT,MDS,FS.LRG!FS.NFS!FS.VRQ ; /SMODIFY:LIST
	  SP	SREMOVE,0,RMSSWT,RMS,FS.LRG!FS.NFS!FS.VRQ ; /SREMOVE:LIST
	  SN	SYS,S.SYS,FS.NFS			; /[NO]SYS
	  LIST
	> ; End DEFINE SWTCHS


;Define the valid keys for the /LIST switch

	KEYS	LSW,<CHANGE,PATH,JSL,SSL,NAMES,ALL>


;Generate the scan tables for SCAN

	DOSCAN	(PTHSW)		; GENERATE THE SWITCH TABLES
	SUBTTL	High segment data locations


;.ISCAN block

.ISCBK:	IOWD	1,[SIXBIT/PATH/]  ; IOWD TO TABLE OF LEGAL MONITOR COMMANDS
	XWD	OFFSET,'PTH'	; STARTING OFFSET,,SIXBIT CCL NAME
.ISBL1==.-.ISCBK		; LENGTH IF TTY OPEN FAILS
	XWD	0,W.TTY		; 0,,ADDRESS OF CHARACTER OUTPUT RTN
	EXP	0		; POINTER TO INDIRECT FILE BLOCK
	XWD	PROMPT,XITCLS	; ADDR OF PROMPT RTN,,ADDR OF EXIT RTN
.ISCBL==.-.ISCBK


;.TSCAN block

.TSCBK:	IOWD	PTHSWL,PTHSWN	; IOWD TO LEGAL SWITCH NAMES
	XWD	PTHSWD,PTHSWM	; DEFAULT SWITCH AREA,,PROCESSOR SWITCH TABLE
	XWD	0,PTHSWP	; 0,,ADDR OF SWITCH POINTERS FOR STORING
	EXP	-1		; LET HELPER PROVIDE THE HELP
	XWD	CLRALL,CLRFIL	; CLEAR ALL ANSWERS,,CLEAR FILE ANSWER
	XWD	ALCINP,ALCOUT	; ALLOCATE INPUT,,ALLOCATE OUTPUT
	XWD	MEMSTK,APLSTK	; MEMORIZE STICKY DEFAULTS,,APPLY STICKY DEFAULTS
	XWD	CLRSTK,FS.MIO	; CLEAR STICKY DEFAULTS,,ALLOW MIXED SWITCHES
.TSCBL==.-.TSCBK


;.OSCAN block

.OSCBK:	IOWD	PTHSWL,PTHSWN	; IOWD TO LEGAL SWITCH NAMES
	XWD	PTHSWD,PTHSWM	; DEFAULT SWITCH AREA,,PROCESSOR SWITCH TABLE
	XWD	0,PTHSWP	; 0,,ADDR OF SWITCH POINTERS FOR STORING
.OSCBL==.-.OSCBK


;Table of break characters (Carriage return intentionally left out)

BRKTBL:	1_<.CHBEL>!1_<.CHLFD>!1_<.CHVTB>!1_<.CHFFD>!1_<.CHCNZ>!1_<.CHESC>


;The following tables give the legal modifiers for search list switches
;and the corresponding flag bits to use if that modifier is seen.

SLNTAB:	SIXBIT/CREATE/
	SIXBIT/WRITE/
	SIXBIT/NOCREA/
	SIXBIT/NOWRIT/
SLNTBL==.-SLNTAB

SLITAB:	0+(FS.MNC)		; /CREATE = CLEAR NO-CREATE BIT
	0+(FS.MWL)		; /WRITE = CLEAR NO-WRITE BIT
	FS.MNC+(FS.MNC)		; /NOCREATE = SET NO-CREATE BIT
	FS.MWL+(FS.MWL)		; /NOWRITE = SET NO-WRITE BIT
;Generate one table for each type of search list (job and system)
;giving the address of the routine to process that switch and
;the address of the switch block.
;
	DEFINE	X ($PREFX,$TYPE), <
	  IFIDN <$TYPE>,<J>, <
	    XWD	CHK'$PREFX'X,$PREFX'$TYPE'BLK
	    ..ZZ==..ZZ+1
	  >
	>

	..ZZ==0
JSBLST:	SLSWCH			; GENERATE ONE WORD FOR EACH JOB SWITCH
JSBPTR:	XWD	-..ZZ,JSBLST	; AND AOBJN POINTER TO THE TABLE

	DEFINE	X ($PREFX,$TYPE), <
	  IFIDN <$TYPE>,<S>, <
	    XWD CHK'$PREFX'X,$PREFX'$TYPE'BLK
	    ..ZZ==..ZZ+1
	  >
	>

	..ZZ==0
SSBLST:	SLSWCH			; GENERATE ONE WORD FOR EACH SYS SWITCH
SSBPTR:	XWD	-..ZZ,SSBLST	; AND AOBJN POINTER TO THE TABLE
	SUBTTL	Low segment data locations


	$LOW


;From here to Z.END zeroed on every time through PTHSCN

Z.BGN==.
GTNSAV:	BLOCK	1		; SAVE AOBJP POINTER TO SWITCH LIST HERE
				; WHILE DOING CURRENT SL
SCNIFS:	BLOCK	1		; POINTER TO FIRST INPUT SCAN BLOCK
SCNILS:	BLOCK	1		; POINTER TO LAST INPUT SCAN BLOCK
SCNOFS:	BLOCK	1		; POINTER TO FIRST OUTPUT SCAN BLOCK
SCNOLS:	BLOCK	1		; POINTER TO LAST OUTPUT SCAN BLOCK
L.LIST:	BLOCK	1		; LISTING SWITCH BITS
P.LIST:	BLOCK	1		; LISTING BITS FROM COMMAND LINE
JSLBLK:	BLOCK	$SLXLN		; JOB SEARCH LIST PARAMETER BLOCK
SSLBLK:	BLOCK	$SLXLN		; SYSTEM SEARCH LIST PARAMETER BLOCK
SSWCNT:	BLOCK	1		; TOTAL STRS IN ALL SSL SWITCHES
JSWCNT:	BLOCK	1		; TOTAL STRS IN ALL JSL SWITCHES
PTHPTR:	BLOCK	1		; ADDRESS OF SIXBIT NAME PATH BLOCK
LNMPTR:	BLOCK	1		; ADDRESS OF LOGICAL NAME SUBSTITUTION BLOCK
DSCBLK:	BLOCK	.DCSAJ+1	; DSKCHR BLOCK
PTSDP:	BLOCK	.PTMAX		; DEFAULT PATH BLOCK
PTSAP:	BLOCK	.PTMAX		; ADDITIONAL PATH BLOCK
PTSLN:	BLOCK	.PTLLB		; LOGICAL NAME BLOCK
SLBLK:	BLOCK	.DFGST+1	; GOBSTR AND JOBSTR BLOCKS GO HERE

;	SWTGEN  (<Non-file switch list>,<File switch list>,<Extra words list>)
	SWTGEN  (<CLEAR,NEW,SCAN,SYS>,<SEARCH>,<LNK>)

;Define the search list switch blocks

	DEFINE	X ($PREFX,$TYPE), <
	  $PREFX'$TYPE'SWT: BLOCK 1	;; PJST T1,?SLSWT
	  $PREFX'$TYPE'BLK: BLOCK $SLSLN ;; THE BLOCK
	>

	SLSWCH			; GENERATE ALL SWITCH BLOCKS
Z.END==.-1			; END OF AREA TO ZERO


OFFSET:	BLOCK	1		; ENTRY POINT OFFSET
MINCOR:	BLOCK	1		; INITIAL VALUE OF .JBFF
XSLMAX:	BLOCK	1		; MAX SSL STRS,,MAX JSL STRS
MYJOB:	BLOCK	1		; NUMBER OF OUR JOB
MYPATH:	BLOCK	.PTMAX		; OUR CURRENT PATH
PDL:	BLOCK	.PDLEN		; PDL
TOBUF:	BLOCK	.BFCTR+1	; TTY OUTPUT BUFFER

	$HIGH
	SUBTTL	Initialization


PATH:	PORTAL	.+2		; ALLOW PROTECTED EXECUTION
	PORTAL	.+2		; DITTO FOR CCL ENTRY
	TDZA	T1,T1		; CLEAR CCL ENTRY FLAG AND SKIP
	  MOVEI	T1,1		; INDICATE CCL ENTRY
	MOVEM	T1,OFFSET	; STORE ENTRY POINT OFFSET FOR SCAN
	RESET			; CLEAR THE WORLD
	MOVE	P,[IOWD .PDLEN,PDL] ; SETUP PDL
	SETZM	F		; CLEAR FLAGS
	MOVEI	T1,PATH		; GET REENTER ADDRESS
	MOVEM	T1,.JBREN	;  AND SAVE IN JOB DATA REGION
	MOVX	T1,%LDMSS	; GETTAB TO RETURN MAX STRS IN SL'S
	GETTAB	T1,		; GET IT
	  MOVE	T1,[^D36,,^D10]	; USE THE DEFAULT
	MOVEM	T1,XSLMAX	; SAVE FOR LATER
	PJOB	T1,		; GET OUR JOB NUMBER
	MOVEM	T1,MYJOB	;   AND SAVE IT FOR LATER
	MOVX	T1,.IOASC!UU.PHS; GET PHYSICAL DEVICE IN ASCII MODE
	MOVX	T2,SIXBIT/TTY/	; DEVICE IS A TTY
	MOVX	T3,<TOBUF,,0>	; OUTPUT BUFFER IS TOBUF
	OPEN	TTY,T1		; OPEN THE TTY
	  TXOA	F,FL.TOF	; FAILED, SET FLAG AND SKIP OUTBUF
	OUTBUF	TTY,1		; USE ONE OUTPUT BUFFER
	MOVE	T1,.JBFF	; GET SMALLEST CORE VALUE
	MOVEM	T1,MINCOR	;  AND SAVE FOR LATER

	MOVSI	T1,.ISCBL	; GET NORMAL LENGTH OF .ISCAN BLOCK
	TXNE	F,FL.TOF	; TTY OPEN FAIL?
	  MOVSI	T1,.ISBL1	; YES, USE SHORT BLOCK
	HRRI	T1,.ISCBK	; MAKE IT LEN,,ADDR
	PUSHJ	P,.ISCAN##	; INITIALIZE SCAN
	SUBTTL	Main scanner loop


;Here to processes each command.  Call .TSCAN to crack the command
;string and .OSCAN to get the defaults from SWITCH.INI.

PTHSCN:	MOVE	P,[IOWD	.PDLEN,PDL] ; INSURE PDL IS IN PHASE
	ANDX	F,FL.TOF	; CLEAR ALL BUT TTY OPEN FLAG
	STORE	T1,Z.BGN,Z.END,0 ; CLEAR ALL APPROPRIATE STORAGE
	PUSHJ	P,INISLB	; INITIALIZE SEARCH LIST SWITCH BLOCKS
	MOVE	T1,MINCOR	; GET INITIAL VALUE OF .JBFF
	MOVEM	T1,.JBFF	; RESTORE IT
	CORE	T1,		; CORE DOWN TO A MINIMUM
	 JFCL			; DON'T CARE
	PUSHJ	P,GETPTH	; GET OUR CURRENT PATH

	MOVE	T1,[XWD	.TSCBL,.TSCBK]	; POINT TO .TSCAN BLOCK
	PUSHJ	P,.TSCAN##	; CRACK THE COMMAND LINE

	TXZE	F,FL.ERR!FL.WRN	; ANY ERRORS OR WARNINGS ON THAT COMMAND?
	  JRST	PTHSCN		; YES, GIVE UP ON IT

	MOVE	T1,L.LIST	; GET COMMAND STRING LIST BITS
	MOVEM	T1,P.LIST	; SAVE FOR LATER
	SETZM	L.LIST		; CLEAR BITS FOR SWITCH.INI SETTINGS

	MOVE	T1,[XWD	.OSCBL,.OSCBK]	; POINT TO .OSCAN BLOCK
	PUSHJ	P,.OSCAN##	; READ SWITCH.INI

	SKIPN	T1,P.LIST	; SKIP IF COMMAND STRING LIST SWITCH SPECIFIED
	  MOVE	T1,L.LIST	;   ELSE USE SWITCH.INI DEFAULTS
	TXZE	T1,FL.LAL	; CLEAR /L:A BIT AND SKIP IF NOT SET
	  TXO	T1,FL.LSW	; SET ALL OTHER LIST BITS
	ANDX	T1,FL.LSW!FL.LST; ISOLATE JUST THE BITS
	IORM	T1,F		;   AND STORE THEM IN THE FLAG WORD
;
;SCAN has the annoying habit of giving us a free input scan block even
;though no input specifications were seen when only global switches were 
;typed.  This type of scan block may be distinguished by a zero device
;word.  To avoid problems later, clear the input scan block pointers if 
;we get one of these scan blocks and set a flag telling what happened.

	MOVE	T1,SCNIFS	; GET ADDRESS OF INPUT SCAN BLOCKS
	JUMPE	T1,CHKOUT	; IF NONE, DON'T CHANGE LIST SCNILS
	CAMN	T1,SCNILS	; ONLY ONE OF THEM?
	 SKIPE	.FXDEV(T1)	;  AND SCAN GIVE US A FREE ONE?
	  JRST	CHKOUT		; NO, CONTINUE WITH THE CHECKING
	SETZM	SCNIFS		; PRETEND LIKE NO INPUT BLOCKS
	SETZM	SCNILS		; ...
	TXO	F,FL.GSO	; SET "GLOBAL SWITCHES ONLY" BIT
	SUBTTL	Command validation and error checking


;Here when SCAN has finished cracking the command line.  At this point,
;we know that the command is at least superficially syntactically
;correct.  We must now rigorously check it for both syntactic and
;semantic correctness before we perform any required functions.  First,
;the output scan blocks...

CHKOUT:	SKIPN	P1,SCNOFS	; LOGICAL NAME DEFINITION SPECIFIED?
	  JRST	CHKINP		; NO, CHECK INPUT SCAN BLOCKS
	MOVX	T1,FX.NDV	; GET NULL DEVICE BIT
	TDNE	T1,.FXMOD(P1)	; MUST HAVE SPECIFIED A LOGICAL NAME
	  ERROR	NLN,<Null logical name illegal>,,PTHSCN
	SKIPE	.FXNMM(P1)	; CAN'T HAVE A FILENAME
	  ERROR	FLD,<Filename illegal in logical name definition>,,PTHSCN
	SKIPE	.FXEXT(P1)	;   OR AN EXTENSION
	  ERROR	ELD,<Extension illegal in logical name definition>,,PTHSCN
	MOVX	T1,FX.DIR	; GET "DIRECTORY-SPECIFIED" BIT
	TDNN	T1,.FXMOD(P1)	; CAN'T HAVE A DIRECTORY
	 TDNE	T1,.FXMOM(P1)	;   OR [-]
	  ERROR	DLD,<Directory illegal in logical name definition>,,PTHSCN
	TXO	F,FL.SLN	; LIGHT "SET LOGICAL NAME" BIT
;Here when we have validated the output scan block.  We must now do the 
;same for all input scan blocks.


CHKINP:	SKIPN	P1,SCNIFS	; GET FIST POINTER TO INPUT SCAN BLOCKS
	  JRST	CHKZLN		; NONE THERE, CHECK /CLEAR
CHKIN1:	MOVE	T1,P1		; POINT TO BLOCK
	MOVX	T2,$FXLEN	;   AND GET LENGTH
	PUSHJ	P,.OSDFS##	; LET SCAN APPLY THE SWITCH.INI DEFAULTS
	PUSHJ	P,MOVSTK	; NOW APPLY DEFAULTS FOR OUR SWITCHES
	TXNN	F,FL.SLN	; DEFINING LOGICAL NAME?
	  JRST	CHKIN4		; NO, GO CHECK OTHER STUFF
	SKIPE	.FXNMM(P1)	; CAN'T HAVE FILENAME
	  ERROR	FLC,<Filename illegal in logical name component>,,PTHSCN
	SKIPE	.FXEXT(P1)	; CAN'T HAVE EXTENSION EITHER
	  ERROR	ELC,<Extension illegal in logical name component>,,PTHSCN
	SKIPL	$FXSEA(P1)	;USER SAY /[NO]SEARCH HERE?
	  ERROR	AIC,<SEARCH attribute illegal in logical name component>,,PTHSCN
	MOVX	T1,FX.DIR	; GET "DIRECTORY SPECIFIED" BIT
	TDNN	T1,.FXMOM(P1)	; DID HE SPECIFY ONE?
	  JRST	CHKIN3		; NO, SETSLN WILL HANDLE SUBSTITUTIONS
	PUSHJ	P,CHKWLD	; CHECK FOR WILDCARD IN THE DIRECTORY
	  ERROR	WLC,<Wildcards illegal in directory for logical name component>,,PTHSCN
CHKIN3:	HRRZ	P1,$FXLNK(P1)	; ADVANCE TO NEXT SCAN BLOCK
	JUMPN	P1,CHKIN1	; LOOP IF NOT AT END
	JRST	CHKZLN		; GO CHECK FOR /CLEAR
;Here when there are no output scan blocks.  We now know that the user
;either typed a new default path or an existing logical name which he
;either wants to change or list.

CHKIN4:	CAME	P1,SCNILS	; CAN ONLY HAVE ONE SPEC (FOR NOW)
	  ERROR	MLN,<Multiple logical names illegal>,,PTHSCN
	MOVX	T1,FX.NDV	; GET NULL DEVICE BIT
	TDNE	T1,.FXMOD(P1)	; IF NULL DEVICE, ASSUME NEW PATH
	  JRST	CHKIN5
	SKIPE	.FXNMM(P1)	; CAN'T HAVE FILENAME HERE
	  ERROR	FLN,<Filename illegal in logical name>,,PTHSCN
	SKIPE	.FXEXT(P1)	;   OR AN EXTENSION
	  ERROR	ELN,<Extension illegal in logical name>,,PTHSCN
	MOVX	T1,FX.DIR	; GET "DIRECTORY SPECIFIED" BIT
	TDNN	T1,.FXMOD(P1)	; CAN'T HAVE A DIRECTORY
	 TDNE	T1,.FXMOM(P1)	;   OR [-]
	  ERROR	DLN,<Directory illegal in logical name>,,PTHSCN
	SKIPL	$FXSEA(P1)	; USER WANT TO CHANGE SEARCH STATUS?
	 TXOA	F,FL.CLN	; YES, SET THE BIT
	  TXO	F,FL.LSN	; NO, LIST THIS NAME
	JRST	CHKZLN		;   AND CONTINUE

CHKIN5:	SKIPE	.FXNMM(P1)	; CAN'T HAVE FILENAME HERE
	  ERROR	FPC,<Filename illegal in default path change>,,PTHSCN
	SKIPE	.FXEXT(P1)	;   OR AN EXTENSION
	  ERROR	EPC,<Extension illegal in default path change>,,PTHSCN
	PUSHJ	P,CHKWLD	; CHECK FOR WILD CARDS IN PATH
	  ERROR	WPC,<Wildcards illegal in default path change>,,PTHSCN
	SKIPL	$FXSEA(P1)	; CAN'T HAVE /[NO]SEARCH HERE
	  ERROR	SPC,</SEARCH illegal in default path change>,,PTHSCN
	TXO	F,FL.CPT	; LIGHT "CHANGE PATH" BIT
;
;Check to make sure the user didn't say /CLEAR with any other logical
;name command.
;
CHKZLN:	SKIPG	S.CLEAR		; USER SAY /CLEAR?
	  JRST	SETUP		; NO
	TXNE	F,FL.SLN!FL.CLN!FL.LSN ; ANY OTHER LOGICAL NAME COMMANDS?
	  ERROR	CNC,</CLEAR may not be included with logical name changes>,,PTHSCN
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LLN	; YES, SET /L:NAMES
	SUBTTL	Function setup


;Here when the command has been validated by the checks above. We must
;now setup the blocks to perform the required functions.
;
;Check for /[NO]NEW
;
SETUP:	SKIPGE	P1,S.NEW	; USER SAY /[NO]NEW?
	  JRST	SETSYS		; NO
	PUSHJ	P,GETCAP	; INSURE CURRENT VALUES ARE SETUP
	DPB	P1,[POINTR PTSAP+.PTSWT,PT.SNW] ; SET NEW VALUE IN BLOCK
	TXO	F,FL.SAP	; LIGHT "SET ADDITIONAL PATH" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LPT	; YES, SET /LIST:PATH ALSO
;
;Check for /[NO]SYS
;
SETSYS:	SKIPGE	P1,S.SYS	; USER SAY /[NO]SYS?
	  JRST	SETSCN		; NO
	PUSHJ	P,GETCAP	; INSURE CURRENT VALUES ARE SETUP
	DPB	P1,[POINTR PTSAP+.PTSWT,PT.SSY] ; SET NEW VALUE IN BLOCK
	TXO	F,FL.SAP	; LIGHT "SET ADDITIONAL PATH" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LPT	; YES, SET /L:PATH ALSO
;
;Check for /[NO]SCAN
;
SETSCN:	SKIPGE	P1,S.SCAN	; USER SAY /[NO]SCAN?
	  JRST	SETPTH		; NO
	PUSHJ	P,GETCDP	; INSURE CURRENT VALUES ARE SETUP
	ADDX	P1,.PTSCN	; CONVERT 0/1 TO .PTSCN/.PTSCY
	DPB	P1,[POINTR PTSDP+.PTSWT,PT.SCN] ; SET NEW VALUE IN BLOCK
	TXO	F,FL.SDP	; LIGHT "SET DEFAULT PATH" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LPT	; YES, SET /L:PATH ALSO
;
;Check for new default path
;
SETPTH:	TXNN	F,FL.CPT	; USER WANT TO CHANGE HIS PATH?
	  JRST	SETSLN		; NO
	PUSHJ	P,GETCDP	; INSURE CURRENT VALUES ARE SETUP
	MOVE	T1,SCNIFS	; GET SCAN BLOCK ADDRESS
	MOVX	T2,<-.FXLND,,0>	;   AND AOBJN POINTER TO PTSDP
SETPT1:	SKIPN	T3,.FXDIR(T1)	; GET NEXT WORD OF DIRECTORY
	  JRST	SETPT2		; FOUND ZERO TERMINATOR
	MOVEM	T3,PTSDP+.PTPPN(T2) ; STORE IN PATH BLOCK
	ADDI	T1,2		; SKIP OVER MASK WORD IN SCAN BLOCK
	AOBJN	T2,SETPT1	; BUMP PATH BLOCK INDEX AND LOOP IF MORE
SETPT2:	SETZM	PTSDP+.PTPPN(T2); INSURE ZERO WORD TERMINATOR IN PATH BLOCK
	TXO	F,FL.SDP	; LIGHT "SET DEFAULT PATH" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LPT	; YES, SET /L:PATH ALSO
;Check for logical name definition
;
SETSLN:	TXNN	F,FL.SLN	; USER WANT TO SET A LOGICAL NAME?
	  JRST	SETCLN		; NO
	MOVE	P1,SCNOFS	; GET POINTER TO OUTPUT SCAN BLOCK
	SKIPL	$FXSEA(P1)	; WANT /[NO]SEARCH ON THIS ONE?
	  PUSHJ	P,SETSEA	; YES, SETUP THE BLOCK
	MOVE	T1,.FXDEV(P1)	; GET LOGICAL NAME
	MOVEM	T1,PTSLN+.PTLNM	; STORE IN THE BLOCK
	MOVEI	P2,PTSLN+.PTLSB-1; BUILD RH OF AOBJP POINTER TO BLOCK
	HRLI	P2,-<.PTLLB-.PTLSB+1> ; COMPLETE LH
	SKIPN	P1,SCNIFS	; SKIP IF DEFINITION
	  JRST	[MOVX	T1,PT.UDF ; GET "UNDEFINE" BIT
		 MOVEM	T1,PTSLN+.PTLNF ; AND STORE IN BLOCK
		 MOVEI	P1,SCNIFS-$FXLNK; MAKE HRRZ BELOW RETURN ZERO
		 JRST	SETLN7	; BIND OFF BLOCK
		]
SETLN1:	PUSHJ	P,FNDPTH	; FIND PATH ASSOCIATED WITH THIS DEVICE
	CAXE	T1,.FPIPP	; THIS ONE HAVE AN IMPLIED PPN?
	 CAXN	T1,.FPLNM	;  OR A LOGICAL NAME?
	  JRST	SETLN2		; YES, ALWAYS DO THE SUBSTITUTION
	MOVX	T2,FX.DIR	; GET "DIRECTORY SPECIFIED" BIT
	TDNN	T2,.FXMOM(P1)	; USER SPECIFY ONE FOR THIS SPEC?
SETLN2:	  JRST	@[EXP SETLN3,SETLN5,SETLN5,SETLN6](T1) ; DISPATCH
	JRST	SETLN4		; YES, LEAVE IT ALONE
;Here if no path associated with this name. Use our default path.
;
SETLN3:	PUSHJ	P,SUBCDP	; SUBSTITUTE OUR CURRENT PATH
SETLN4:	PUSHJ	P,INSSCB	; INSERT SCAN BLOCK INTO THIS LOGICAL NAME
	  JRST	E$$TMC		; TOO MANY FOR THIS SPEC
	JRST	SETLN7		; JOIN COMMON CODE
;
;Here if the path for the device is a simple path spec.
;
SETLN5:	PUSHJ	P,INSPTH	; INSERT PATH INTO THIS LOGICAL NAME
	  JRST	E$$TMC		; TOO MANY FOR THIS SPEC
	JRST	SETLN7		; JOIN COMMON CODE
;
;Here if this device is really a logical name. Substitute the components
;into the logical name block.
;
SETLN6:	PUSHJ	P,INSLNM	; INSERT LOGICAL NAME INTO THIS SPEC
	  JRST	E$$TMC		; TOO MANY
SETLN7:	HRRZ	P1,$FXLNK(P1)	; ADVANCE TO NEXT SCAN BLOCK
	JUMPN	P1,SETLN1	; LOOP IF NOT AT END
	AOBJP	P2,E$$TMC	; INSURE NO BLOCK OVERFLOW
	SETZM	(P2)		; DO FINAL TERMINATOR
	AOBJP	P2,E$$TMC	; INSURE NO BLOCK OVERFLOW
	SETZM	(P2)		;  AND ONE MORE TO END THE BLOCK
	SUBI	P2,PTSLN-1	; CONVERT TO COUNT OF WORDS IN BLOCK
	HRRZM	P2,PTSLN+.PTFCN	; STORE COUNT AS ADVERTISED
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LLN	; YES, SET /L:NAMES ALSO
	JRST	SETCLN		; SKIP THE ERROR MESSAGE

E$$TMC:	ERROR	TMC,<Too many logical name components>,,PTHSCN
;Check for logical name change
;
SETCLN:	TXNN	F,FL.CLN	; USER WANT TO CHANGE LOGICAL NAME?
	  JRST	SETLLN		; NO
	MOVE	P1,SCNIFS	; GET INPUT SCAN BLOCK ADDRESS
	MOVE	T1,.FXDEV(P1)	; GET LOGICAL NAME
	PUSHJ	P,GETSLN	; READ THE INFORMATION
	  JRST	[PUSHJ	P,E$$NSL ; TELL OF NO SUCH NAME
		 TXZ	F,FL.CLN!FL.SLN ; CLEAR LOGICAL NAME FLAGS
		 JRST	SETJSL	; AND CONTINUE
		]
	SKIPL	$FXSEA(P1)	; GET SEARCH FLAG
	  PUSHJ	P,SETSEA	; YES, SETUP THE BLOCK
	MOVEI	T1,PTSLN+.PTLSB	; POINT TO BLOCK JUST RETURNED
SETCL1:	SKIPN	0(T1)		; LOOK FOR TWO ZEROS
	 SKIPE	1(T1)		; TERMINATING BLOCK
	  CAIA			; NOT FOUND, CONTINUE WITH THIS BLOCK
	   JRST	SETCL3		; FOUND THEM
	ADDX	T1,.PTLPP	; STEP TO START OF PATH BLOCK
SETCL2:	SKIPE	0(T1)		; LOOK FOR ZERO TERMINATING PATH BLOCK
	  AOJA	T1,SETCL2	; LOOP FOR NEXT WORD
	AOJA	T1,SETCL1	; STEP TO START OF NEXT GROUP
SETCL3:	SUBI	T1,PTSLN-2	; COMPUTE THE NUMBER OF WORDS
	HRRZM	T1,PTSLN+.PTFCN	; STORE IN THE BLOCK AS ADVERTISED
	TXO	F,FL.SLN	; CHANGE TO SET LOGICAL NAME
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LLN	; YES, SET /L:NAMES ALSO

SETLLN:	TXNE	F,FL.LSN	; USER WANT TO LIST THIS LOGICAL NAME?
	  TXO	F,FL.LLN	; YES, SET /L:NAMES ALSO
;Check for new job search list
;
SETJSL:	TXNN	F,FL.JLS	; ANY JOB SEARCH LIST SWITCHES SPECIFIED?
	  JRST	SETSSL		; NO, CHECK SYSTEM SEARCH LIST
	MOVE	P1,ADJBLK+$SLSCT ; GET COUNT OF STRS IN /ADD
	ADD	P1,RMJBLK+$SLSCT ; ADD TOTAL FROM /REMOVE
	ADD	P1,MDJBLK+$SLSCT ; ADD TOTAL FROM /MODIFY
	JUMPE	P1,SETJS1	; OK IF ZERO
	SKIPE	CRJBLK+$SLSCT	; CAN'T HAVE ABOVE WITH /CREATE
	  ERROR	COS,<CREATE illegal with other search list switches>,,PTHSCN
SETJS1:	PUSHJ	P,GETJSL	; GET CURRENT JOB SEARCH LIST
	  JRST	SETSSL		; FAILED, FORGET IT
	MOVE	T1,JSLBLK+$SLMAX ; GET MAX STRS ALLOWED IN SEARCH LIST
	LSH	T1,1		; TIMES 2 FOR SLOP
	MOVX	T2,.FSDSO	; ADDITIONAL WORDS FOR HEADER
	PUSHJ	P,BLDAOB	; ALLOCATE CORE AND RETURN AOBJP POINTER
	MOVEM	T1,JSLBLK+$SLNPT ; SAVE START ADDRESS IN BLOCK
	MOVEM	T2,JSLBLK+$SLNAB ;  ALONG WITH AOBJP POINTER
	MOVEI	P2,JSLBLK	; POINT TO JSL PARAMETER BLOCK
	MOVE	P3,JSBPTR	; GET AOBJN POINTER TO SWITCH BLOCK TABLE
	PUSHJ	P,CHKSLB	; INVOKE ROUTINE FOR ALL SWITCHES WITH
				; NON-ZERO STR COUNTS
	TXO	F,FL.JSL	; LIGHT "SET NEW JOB SEARCH LIST" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET
	  TXO	F,FL.LJS	; YES, SET /L:JSL
;
;Check for new system search list
;
SETSSL:	TXNN	F,FL.SLS	; ANY SYS SEARCH LIST SWITCHES SPECIFIED?
	  JRST	DOFNC		; NO, GO DO FUNCTIONS
	MOVE	P1,ADSBLK+$SLSCT ; GET COUNT OF STRS IN /SADD
	ADD	P1,RMSBLK+$SLSCT ; ADD TOTAL FROM /SREMOVE
	ADD	P1,MDSBLK+$SLSCT ; ADD TOTAL FROM /SMODIFY
	JUMPE	P1,SETSS1	; OK IF ZERO
	SKIPE	CRSBLK+$SLSCT	; CAN'T HAVE ABOVE WITH /SCREATE
	  ERROR	SOS,<SCREATE illegal with other search list switches>,,PTHSCN
SETSS1:	PUSHJ	P,GETSSL	; GET CURRENT SYSTEM SEARCH LIST
	  JRST	DOFNC		; FAILED, FORGET IT
	MOVE	T1,SSLBLK+$SLMAX ; GET MAX STRS ALLOWED IN SEARCH LIST
	LSH	T1,1		; TIMES 2 FOR SLOP
	MOVX	T2,.FSDSO	; PLUS WORDS FOR HEADER
	PUSHJ	P,BLDAOB	; ALLOCATE CORE AND RETURN AOBJP POINTER
	MOVEM	T1,SSLBLK+$SLNPT ; SAVE STARTING ADDRESS OF BLOCK
	MOVEM	T2,SSLBLK+$SLNAB ;  ALONG WITH AOBJP POINTER
	MOVEI	P2,SSLBLK	; POINT TO SSL PARAMETER BLOCK
	MOVE	P3,SSBPTR	; GET AOBJN POINTER TO SWITCH BLOCK TABLE
	PUSHJ	P,CHKSLB	; INVOKE ROUTINE FOR ALL SWITCHES THAT HAVE
				; A NON-ZERO STR COUNT
	TXO	F,FL.SSL	; LIGHT "SET NEW SYSTEM SEARCH LIST" BIT
	TXNE	F,FL.LCG!FL.LST	; /L OR /L:C SET?
	  TXO	F,FL.LSS	; YES, SET /L:SSL
	SUBTTL	Function execution


;Here to finally perform any functions as indicated by the command.
;The code on the last few pages setup all the necessary UUO blocks so
;the only thing we should have to do is perform the appropriate UUOs.

DOFNC:	TXNE	F,FL.JSL	; NEED TO SET NEW JOB SEARCH LIST?
	  PUSHJ	P,STNJSL	; YES, DO IT
	TXNE	F,FL.SDP	; NEED TO SET NEW DEFAULT PATH?
	  PUSHJ	P,SETNDP	; YES, DO IT
	TXNE	F,FL.SAP	; NEED TO SET NEW ADDITIONAL PATH?
	  PUSHJ	P,SETNAP	; YES, DO IT
	TXNE	F,FL.SSL	; NEED TO SET NEW SYSTEM SEARCH LIST?
	  PUSHJ	P,STNSSL	; YES, DO IT
	SKIPLE	S.CLEAR		; NEED TO CLEAR ALL LOGICAL NAMES?
	  PUSHJ	P,CLRLNM	; YES, DO IT
	TXNE	F,FL.SLN	; NEED TO SET ANY LOGICAL NAMES?
	 PUSHJ	P,SETLNM	; YES, DO IT
	  JFCL			; IGNORE ERROR RETURN
	SKIPN	SCNIFS		; IF ANY SCAN BLOCKS,
	 SKIPE	SCNOFS		;   THEN DON'T DIDDLE WITH LIST SWITCHES
	  JRST	DOFNC1		;   SO SKIP THE CODE
	TXNN	F,FL.GSO	; IF PATH <CR>
	  TXO	F,FL.LPT	;   THEN SET /L:PATH
	TXNE	F,FL.LST	; /L SET?
	 TXNE	F,FL.LSW	;   AND NOTHING ELSE?
	  CAIA			; NO
	   TXO	F,FL.LPT	; YES, SET /L:P
DOFNC1:	TXNE	F,FL.LPT	; USER WANT PATH LISTED?
	  PUSHJ	P,LSTPTH	; YES, DO IT
	TXNE	F,FL.LJS	; USER WANT SEARCH LIST LISTED?
	  PUSHJ	P,LSTJSL	; YES, DO IT
	TXNE	F,FL.LSS	; USER WANT SYSTEM SL LISTED?
	  PUSHJ	P,LSTSSL	; YES, DO IT
	TXNE	F,FL.LLN	; USER WANT LOGICAL NAMES LISTED?
	  PUSHJ	P,LSTLNM	; YES, DO IT
	JRST	PTHSCN		;   AND DO IT ALL OVER FOR THE NEXT COMMAND
	SUBTTL	Listing routines


;Routine to type the user's current path information.
;The call is:
;
;		PUSHJ	P,PTHLST
;		 <always return here>

LSTPTH: TRACE$	LSTPTH		; TYPE DEBUGGING INFO
	PUSHJ	P,GETCDP	; GET DEFAULT PATH IF WE DON'T ALREADY HAVE IT
	PUSHJ	P,GETCAP	; GET ADDITIONAL PATH FOR /LIB
	MOVEI	T1,[ASCIZ/Path:	/] ; TELL HIM WHAT THIS IS
	PUSHJ	P,.TSTRG##	; PRINT IT
	MOVEI	T1,PTSDP+.PTPPN	; POINT TO START OF PATH
	TLO	T1,TS.DRP	; PATH BLOCK FLAG TO .TDIRB
	PUSHJ	P,.TDIRB##	; LET SCAN TYPE THE DEFAULT PATH
	MOVEI	T1,0		; ZERO MESSAGE ADDRESS
	LDB	T2,[POINTR PTSDP+.PTSWT,PT.SCN] ; GET SCAN SWITCH
	CAXN	T2,.PTSCN	; /NOSCAN?
	  MOVEI	T1,[ASCIZ\/NOSCAN\] ; YES, SETUP MESSAGE
	CAXN	T2,.PTSCY	; /SCAN?
	  MOVEI	T1,[ASCIZ\/SCAN\] ; YES, SETUP THAT ONE
	SKIPE	T1		; ONLY PRINT IF THERE IS A MESSAGE
	  PUSHJ	P,.TSTRG##	; TYPE THE STRING
	MOVE	T2,PTSDP+.PTSWT	; GET SWITCHES FROM BLOCK
	MOVEI	T1,[ASCIZ\/NEW\] ; SETUP FOR /NEW TEST
	TXNE	T2,PT.NEW	; USER HAVE /NEW SET?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM
	MOVE	T2,PTSDP+.PTSWT	; GET SWITCHES BACK
	MOVEI	T1,[ASCIZ\/SYS\] ; SETUP FOR /SYS TEST
	TXNE	T2,PT.SYS	; USER HAVE /SYS SET?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM
	SKIPN	PTSAP+.PTPPN	; /LIB EXIST?
	  PJRST	.TCRLF##	; NO, END THE LINE AND RETURN
	MOVEI	T1,[ASCIZ\/LIB:\] ; GET MESSAGE
	PUSHJ	P,.TSTRG##	; TYPE IT
	MOVEI	T1,PTSAP+.PTPPN	; POINT AT LIB
	TLO	T1,TS.DRP	; TELL SCAN IT'S A PATH BLOCK
	PUSHJ	P,.TDIRB##	; TYPE VALUE
	PJRST	.TCRLF##	; END WITH CRLF AND RETURN
;Routine to list the job search list.
;The call is:
;
;		PUSHJ	P,LSTJSL
;		 <always return here>

LSTJSL:	TRACE$	LSTJSL		; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE1##	; SAVE P1
	STORE	T1,SLBLK,SLBLK+.DFGST,0 ;CLEAR THE BLOCK
	MOVEI	T1,[ASCIZ/Job search list:	/]
	PUSHJ	P,.TSTRG##	; TYPE A HEADER
	SETOB	P1,SLBLK+.DFJNM	; SET FIRST STR INDICATION
LSTJS1:	MOVX	T1,<.DFJST+1,,SLBLK>	; POINT TO BLOCK
	JOBSTR	T1,		; GET THE NEXT STRUCTURE
	  WARN	RJS,<Can't read job search list>,,.POPJ##
	SKIPN	T1,SLBLK+.DFJNM	; HANDLE FENCE SPECIALLY
	  JRST	[MOVEI	T1,[ASCIZ/, FENCE/] ; TELL OF FENCE
		 AOSN	P1		    ; UNLESS NO SL
		   MOVEI T1,[ASCIZ/FENCE/]   ; NO COMMA
		 PUSHJ	P,.TSTRG##	    ; TYPE THE STRING
		 SETZM	P1		    ; FLAG NOT FIRST STR
		 JRST	LSTJS1		    ; AND DO PASSIVE SL
		]
	AOJE	T1,.TCRLF##	; END WITH CRLF AND RETURN
	MOVEI	T1,[ASCIZ/, /]	; GET SEPARATOR
	AOSE	P1		; DON'T PRINT FOR FIRST STR
	  PUSHJ	P,.TSTRG##	; TYPE THE SEPARATOR
	MOVE	T1,SLBLK+.DFJNM	; GET STR NAME
	PUSHJ	P,.TSIXN##	;   AND TYPE IN SIXBIT
	PUSHJ	P,.TCOLN##	;   FOLLOWED BY A COLON
	MOVE	P1,SLBLK+.DFJST	; GET STATUS BITS FOR THIS STR
	MOVEI	T1,[ASCIZ\/NOWRITE\]
	TXZE	P1,DF.SWL	; IS IT SOFTWARE WRITE LOCKED?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM
	MOVEI	T1,[ASCIZ\/NOCREATE\]
	TXZE	P1,DF.SNC	; HOW ABOUT NO CREATE?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM THAT ALSO
	JRST	LSTJS1		; GO GET NEXT STRUCTURE
;Routine to list the system search list.
;The call is:
;
;		PUSHJ	P,LSTSSL
;		 <always return here>

LSTSSL:	TRACE$	LSTSSL		; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE1##	; SAVE P1
	STORE	T1,SLBLK,SLBLK+.DFGST,0	;CLEAR THE BLOCK
	MOVEI	T1,[ASCIZ/System search list:	/]
	PUSHJ	P,.TSTRG##	; TYPE A HEADER
	SETOB	P1,SLBLK+.DFGNM	; SET FIRST STR INDICATION
LSTSS1:	MOVX	T1,<.DFGST+1,,SLBLK>	; POINT TO BLOCK
	GOBSTR	T1,		; GET THE NEXT STRUCTURE
	  WARN	RSS,<Can't read system search list>,,.POPJ##
	SKIPE	T1,SLBLK+.DFGNM	; STOP ON FENCE
	 AOSN	T1		;   OR ON LAST STRUCTURE
	  JRST	.TCRLF##	; RETURN AFTER TYPING CRLF
	MOVEI	T1,[ASCIZ/, /]	; GET SEPARATOR
	AOSE	P1		; DON'T PRINT FOR FIST STR
	  PUSHJ	P,.TSTRG##	; TYPE THE SEPARATOR
	MOVE	T1,SLBLK+.DFGNM	; GET STR NAME
	PUSHJ	P,.TSIXN##	;   AND TYPE IN SIXBIT
	PUSHJ	P,.TCOLN##	;   FOLLOWED BY A COLON
	MOVE	P1,SLBLK+.DFGST	; GET STATUS BITS FOR THIS STR
	MOVEI	T1,[ASCIZ\/NOWRITE\]
	TXZE	P1,DF.SWL	; IS IT SOFTWARE WRITE LOCKED?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM
	MOVEI	T1,[ASCIZ\/NOCREATE\]
	TXZE	P1,DF.SNC	; HOW ABOUT NO CREATE?
	  PUSHJ	P,.TSTRG##	; YES, TELL HIM THAT ALSO
	JRST	LSTSS1		; GO GET NEXT STRUCTURE
;Routine to list logical names based on what was typed in the Command
;string.  The algorithm used is as follows:
;
;IF no input scan blocks THEN the user either typed no
;  logical names or is undefining one, so list all existing names
;ELSE IF output scan block, THEN the user is defining a new
;       name so just list that one
;     ELSE IF FL.LSN is set, THEN the user wants a list of one
;            specific name so list that one
;          ELSE user typed a default path so list all existing names
;
;The call is:
;
;		PUSHJ	P,LSTLNM
;		 <always return here>

LSTLNM:	TRACE$	LSTLNM,<F,SCNIFS,SCNOFS> ; TYPE DEBUGGING INFO
	TXO	F,FL.FST	; SET FIRST TIME FLAG
	PUSHJ	P,.SAVE1##	; SAVE P1
	SKIPE	P1,SCNIFS	; SKIP IF NO INPUT SCAN BLOCKS
	 TXNN	F,FL.LSN	;   OR IF NO LOGICAL NAMES SET
	  JRST	LSTLN1		;   THEN LIST ALL EXISTING NAMES
	SKIPE	SCNOFS		; IF AN OUTPUT SCAN BLOCK
	  MOVE	P1,SCNOFS	; THEN LIST JUST THAT ONE
	MOVE	T1,.FXDEV(P1)	; GET NAME TO LIST
	PUSHJ	P,GETSLN	; READ THAT LOGICAL NAME
	  CAIA			; NAME NOT THERE
	PJRST	LSTNAM		; LIST IT AND RETURN

E$$NSL:	WARN	NSL,<No such logical name >,NOCRLF
	MOVE	T1,.FXDEV(P1)	; GET BAD NAME
	PJRST	TYPNAM		; TYPE NAME AND RETURN
;
;Here to list all existing logical names
;
LSTLN1:	SETZM	PTSLN+.PTLNM	; SET NAME TO 0 TO GET THE FIRST ONE
LSTLN2:	PUSHJ	P,GETNLN	; GET THE NEXT ONE IN LINE
	  WARN	RLN,<Can't read logical names>,,.POPJ##
	SKIPN	T1,PTSLN+.PTLNM	; DONE IF WE GOT BACK A ZERO
	  POPJ	P,		;   SO RETURN
	PUSHJ	P,LSTNAM	; LIST THIS NAME
	JRST	LSTLN2		;   AND GO GET NEXT ONE
;Routine to list the logical name stored at PTSLN.
;The call is:
;
;		PUSHJ	P,LSTNAM
;		 <always return here>

LSTNAM:	TRACE$	LSTNAM		; TYPE DEBUGGING INFO
	MOVEI	T1,[ASCIZ/Logical name definitions:
/]
	TXZE	F,FL.FST	; FIRST TIME HERE?
	  PUSHJ	P,.TSTRG##	; YES, TYPE THE HEADER
	PUSHJ	P,.SAVE1##	; SAVE P1
	MOVE	T1,PTSLN+.PTLNM	; GET THE LOGICAL NAME
	PUSHJ	P,.TSIXN##	; TYPE IT
	PUSHJ	P,.TCOLN##	; FOLLOWED BY A COLON
	MOVEI	T1,[ASCIZ\/SEARCH\] ; SETUP FOR /SEARCH
	MOVE	T2,PTSLN+.PTLNF	; GET THE FLAGS
	TXNE	T2,PT.SEA	; IS THIS ONE LIB'ED?
	  PUSHJ	P,.TSTRG##	; YES TELL HIM
	MOVEI	T1,[ASCIZ/ = /]	; GET SEPARATOR
	PUSHJ	P,.TSTRG##	;  AND TYPE IT
	MOVEI	P1,PTSLN+.PTLSB	; POINT TO FIRST COMPONENT
LSTNA1:	SKIPN	0(P1)		; DONE WITH THE LIST YET?
	 SKIPE	1(P1)		; ?
	  CAIA			; NO, CONTINUE
	   JRST	.TCRLF##	; YES, END WITH CRLF AND RETURN
	CAIE	P1,PTSLN+.PTLSB	; THIS THE FIRST ONE IN THE LIST
	  PUSHJ	P,.TCOMA##	; NO, TYPE A COMMA
	SKIPN	T1,.PTNOD(P1)	; ANY NODE SPECIFIED?
	  JRST	LSTNA2		; NO, CONTINUE
	PUSHJ	P,.TSIXN##	; TYPE IT
	MOVEI	T1,"_"		; GET SEPARATOR
	PUSHJ	P,.TCHAR##	; TYPE IT
LSTNA2:	MOVE	T1,.PTLSL(P1)	; GET SEARCH LIST OF THIS ONE
	PUSHJ	P,.TSIXN##	; TYPE THE SEARCH LIST
	PUSHJ	P,.TCOLN##	; FOLLOWED BY A COLON
	SKIPN	T1,.PTFIL(P1)	; ANY FILENAME SPECIFIED?
	  JRST	LSTNA3		; NO, CONTINUE
	HLRZ	T2,.PTEXT(P1)	; GET EXTENSION
	CAIN	T2,'UFD'	; THIS A UFD?
	 JUMPGE	T1,[PUSHJ P,.TPPNW## ; YES, PRINT PPN IF NOT SIXBIT
		    JRST  .+2	     ; AND SKIP THE SIXBIT TYPE
		   ]
	PUSHJ	P,.TSIXN##	; TYPE FILENAME
	MOVEI	T1,"."		; GET SEPARATOR
	PUSHJ	P,.TCHAR##	; TYPE IT
	HLLZ	T1,.PTEXT(P1)	; GET EXTENSION
	PUSHJ	P,.TSIXN##	; TYPE IT
LSTNA3:	MOVX	T1,.PTLPP	; GET OFFSET TO START OF PATH
	ADDB	T1,P1		; POINT TO IT
	TLO	T1,TS.DRP	; FLAG AS DIRECTORY BLOCK
	PUSHJ	P,.TDIRB##	; LET SCAN TYPE IT
LSTNA4:	SKIPE	(P1)		; FIND LAST WORD IN PATH BLOCK
	  AOJA	P1,LSTNA4	; LOOP UNTIL FOUND
	AOJA	P1,LSTNA1	; BUMP ONCE MORE AND TYPE NEXT
	SUBTTL	Routines that perform PATH. and STRUUO functions


;Routine to set any new default path required by the command string.
;Call after setting up the default path block at PTSDP.
;The call is:
;
;		PUSHJ	P,SETNDP
;		 <return here always>

SETNDP:	TRACE$	SETNDP		; TYPE DEBUGGING INFO
	TXZ	F,FL.RDP	; FORCE GETCDP TO REREAD BLOCK
	MOVX	T1,.PTFSD	; FUNCTION TO DEFINE DEFAULT PATH
	MOVEM	T1,PTSDP+.PTFCN	; STORE IN PATH. BLOCK
	MOVX	T1,PT.SCN	; GET MASK FOR /SCAN SWITCH
	ANDM	T1,PTSDP+.PTSWT	; CLEAR ALL BUT THE SWITCH
	MOVX	T1,<.PTMAX,,PTSDP> ; POINT TO PATH BLOCK
	PATH.	T1,		; SET NEW DEFAULT PATH
	  CAIA			; FAILED, ANALYZE ERROR
	POPJ	P,		; RETURN OK

	AOSE	T1		; AC==-1 => NON-EXISTENT SFD
	  WARN	NMS,<No monitor SFD support>,,.POPJ##
	WARN	NES,<Non-existent SFD>,,.POPJ##


;Routine to set any new additional path required by the command string.
;Call after setting up the additional path block at PTSAP.
;The call is:
;
;		PUSHJ	P,SETNAP
;		 <always return here>

SETNAP:	TRACE$	SETNAP		; TYPE DEBUGGING INFO
	TXZ	F,FL.RAP	; FORCE GETCAP TO REREAD BLOCK
	MOVX	T1,.PTFSL	; FUNCTION TO DEFINE ADDITIONAL PATH
	MOVEM	T1,PTSAP+.PTFCN	; STORE IN PATH BLOCK
	MOVX	T1,PT.SNW!PT.SSY ; GET MASK FOR IMPORTANT BITS
	ANDM	T1,PTSAP+.PTSWT	; CLEAR ALL BUT THOSE
	MOVX	T1,PT.DTL	; GET "DON'T TOUCH LIB" BIT
	IORM	T1,PTSAP+.PTSWT	; SET IT SO WE DON'T CLOBBER LIB
	MOVX	T1,<.PTMAX,,PTSAP> ; POINT TO BLOCK
	PATH.	T1,		; SET NEW ADDITIONAL PATH
	  WARN	LNS,<Libraries not supported>,,.POPJ##
	POPJ	P,		; RETURN
;Routine to set a new job search list.  Call with JSLBLK+$SLNCT
;containing the number of STRS in the list and JSLBLK+$SLNPT containing
;a pointer to the start of the list.
;The call is:
;
;		PUSHJ	P,STNJSL
;		 <always return here>

STNJSL:	TRACE$	STNJSL		; TYPE DEBUGGING INFO
	SKIPG	T1,JSLBLK+$SLNCT ; MORE THAN ONE STRUCTURE?
	 TELL	LSJ,<Removing last structure from job search list>
	CAMLE	T1,JSLBLK+$SLMAX ; GREATER THAN MAX ALLOWED?
	  PJRST	E$$TMS		; YES, TELL HIM
	MOVE	T1,JSLBLK+$SLNPT ; GET POINTER TO START OF LIST
	SUBI	T1,.FSCSO	; POINT TO START OF BLOCK FOR JSL
	MOVX	T2,.FSSRC	; FUNCTION TO DEFINE NEW SL
	MOVEM	T2,.FSFCN(T1)	; STORE IN BLOCK
	MOVE	T2,JSLBLK+$SLNCT ; GET NUMBER OF STRS IN LIST
	IMULI	T2,.DFJBL	; MULTIPLY BY # WORDS PER STR
	HRLI	T1,.FSCSO(T2)	; ADD STARTING OFFSET AND MOVE TO T1
	STRUUO	T1,		; SET NEW SL
	  WARN	JSF,<Job search list definition failed>
	POPJ	P,		; RETURN
;Routine to set a new system search list.  Call with SSLBLK+$SLNCT
;containing the number of STRS in the list and SSLBLK+$SLNPT containing
;a pointer to the start of the list.
;The call is:
;
;		PUSHJ	P,STNSSL
;		 <always return here>

STNSSL:	TRACE$	STNSSL		; TYPE DEBUGGING INFO
	SKIPG	T1,SSLBLK+$SLNCT ; MORE THAN ONE STRUCTURE?
	  TELL	LSS,<Removing last structure from system search list>
	CAMLE	T1,SSLBLK+$SLMAX ; GREATER THAN MAX ALLOWED?
	  PJRST	E$$TMS		; YES, TELL HIM
	MOVE	T1,SSLBLK+$SLNPT ; GET POINTER TO START OF LIST
	SUBI	T1,.FSDSO	; POINT TO START OF BLOCK FOR JSL
	MOVX	T2,.FSDSL	; FUNCTION TO DEFINE NEW SSL
	MOVEM	T2,.FSFCN(T1)	; STORE IN BLOCK
	SETZM	.FSDJN(T1)	; ZERO JOB NUMBER (SYS:)
	SETZM	.FSDPP(T1)	;   AND PPN
	MOVX	T2,DF.SRM	; GET "REMOVE FROM SL COMPLETELY" BIT
	MOVEM	T2,.FSDFL(T1)	; STORE IN FLAGS WORD
	MOVE	T2,SSLBLK+$SLNCT ; GET NUMBER OF STRS IN LIST
	IMULI	T2,.DFJBL	; MULTIPLY BY # WORDS PER STR
	HRLI	T1,.FSDSO(T2)	; ADD STARTING OFFSET AND MOVE TO T1
	STRUUO	T1,		; SET NEW SL
	  CAIA			; FAILED, ANALYZE ERROR
	POPJ	P,		; RETURN

	CAXN	T1,FSNPV%	; NOT PRIVILEGED?
	  WARN	NPV,<Not privileged to set system search list>,,.POPJ##
	WARN	SSF,<System search list definition failed>,,.POPJ##
;Routine to CLEAR the definitions of all existing logical names.
;The call is:
;
;		PUSHJ	P,CLRLNM
;		 <always return here>

CLRLNM:	TRACE$	CLRLNM		; TYPE DEBUGGING INFO
CLRLN1:	SETZM	PTSLN+.PTLNM	; CLEAR NAME TO READ FIRST ONE
	PUSHJ	P,GETNLN	; READ THE NEXT DEFINED NAME
	  POPJ	P,		; GIVE UP ON ERROR
	SKIPN	PTSLN+.PTLNM	; DONE IF NEXT NAME IS ZERO
	  POPJ	P,		; SO RETURN
	MOVX	T1,PT.UDF	; GET "UNDEFINE" BIT
	MOVEM	T1,PTSLN+.PTLNF	; STORE IN FLAGS WORD
	SETZM	PTSLN+.PTLSB	; ZERO NEXT WORD
	SETZM	PTSLN+.PTLSB+1	;   AND NEXT TO INSURE DOUBLE ZERO TERMINATOR
	MOVEI	T1,.PTLSB+1+1	; GET LENGTH OF BLOCK
	MOVEM	T1,PTSLN+.PTFCN	; STORE LENGTH FOR SETLNM
	PUSHJ	P,SETLNM	; UNDEFINE THIS ONE
	  POPJ	P,		; GIVE UP IF WE GOT AN ERROR RETURN
	JRST	CLRLN1		;   AND LOOP FOR ALL
;Routine to define a new logical name or change and existing one.  Call
;after setting up the logical name block at PTSLN and storing the length
;of the block at PTSLN+.PTFCN.
;The call is:
;
;		PUSHJ	P,SETLNM
;		 <return here if error>
;		 <return here if set succeeded>

SETLNM:	TRACE$	SETLNM		; TYPE DEBUGGING INFO
	MOVX	T1,PT.SEA!PT.UDF; GET MASK FOR IMPORTANT BITS
	ANDM	T1,PTSLN+.PTLNF	; AND CLEAR ALL BUT THOSE BITS
	MOVX	T1,.PTFSN	; FUNCTION TO DEFINE LOGICAL NAME
	EXCH	T1,PTSLN+.PTFCN	; STORE IN BLOCK AND GET LENGTH
	MOVSS	T1		; PUT INTO LEFT HALF
	HRRI	T1,PTSLN	;   AND POINT AT THE BLOCK
	PATH.	T1,		; DEFINE THE NAME
	  CAIA			; FAILED, CHECK ERROR CODE
	JRST	.POPJ1##	; RETURN SUCCESSFUL

	SKIPL	T1		; FOR NEGATIVE ERROR CODES
	 CAILE	T1,PTERLN	;   OR ONES GREATER THAN WE KNOW ABOUT
E$$LNF:	  WARN	LNF,<Logical name definition failed>,,.POPJ##
	JRST	@PTERTB(T1)	; PRINT APPROPRIATE MESSAGE

PTERTB:	EXP	E$$LNF		; DON'T KNOW ABOUT THIS ONE
	EXP	E$$TMC		; TOO MANY ENTRIES IN THIS LIST
	EXP	E$$TMN		; TOO MANY NAMES
	EXP	E$$NND		; ATTEMPT TO UNDEFINE A NON-EXISTENT NAME
	EXP	E$$NFS		; NO FUNNY SPACE
	EXP	E$$ANE		; ASSIGNED NAME EXISTS
PTERLN==.-PTERTB

E$$TMN:	WARN	TMN,<Too many defined logical names>,,.POPJ##
E$$NFS:	WARN	NFS,<No per-process monitor-free-core>,,.POPJ##
E$$NND:	WARN	NND,<Name not defined >,NOCRLF,SETLNT
E$$ANE:	WARN	ANE,<ASSIGNed name already exists >,NOCRLF
SETLNT:	MOVE	T1,PTSLN+.PTLNM	; GET THE NAME IN ERROR
	PJRST	TYPNAM		; TYPE NAME AND RETURN
;Routine to read the default path into the block starting at PTSDP.
;The call is:
;
;		PUSHJ	P,GETCDP	; To read into PTSDP
;		 <always return here>
;
;			-or-
;
;		PUSHJ	P,GETPTH	; To read into MYPATH
;		 <always return here>

GETCDP:	TRACE$	GETCDP		; TYPE DEBUGGING INFO
	TXOE	F,FL.RDP	; ALREADY HAVE THE INFORMATION?
	  POPJ	P,		; YES, JUST RETURN
	SKIPA	T2,[PTSDP]	; PLACE TO PUT THE PATH
GETPTH:	MOVEI	T2,MYPATH	; ALTERNATE PLACE TO PUT IT
	MOVX	T1,.PTFRD	; FUNCTION TO READ CURRENT DEFAULT PATH
	MOVEM	T1,.PTFCN(T2)	; STORE IN BLOCK
	HRLI	T2,.PTMAX	; MAKE IT LEN,,ADDR
	PATH.	T2,		; READ THE INFO INTO THE BLOCK
	  ERROR	DPN,<Default path not available>,,PTHSCN
	POPJ	P,		;   AND RETURN


;Routine to read the additional path into the block starting at PRSAP.
;The call is:
;
;		PUSHJ	P,GETCAP
;		 <always return here>

GETCAP:	TRACE$	GETCAP		; TYPE DEBUGGING INFO
	TXOE	F,FL.RAP	; ALREADY HAVE THE INFORMATION?
	  POPJ	P,		; YES, JUST RETURN
	MOVX	T1,.PTFRL	; FUNCTION TO READ ADDITIONAL PATH
	MOVEM	T1,PTSAP+.PTFCN	; STORE IN BLOCK
	MOVX	T1,<.PTMAX,,PTSAP> ; POINT AT BLOCK
	PATH.	T1,		; READ THE INFO INTO THE BLOCK
	  ERROR	APN,<Additional path not available>,,PTHSCN
	POPJ	P,		;   AND RETURN
;Routine to read the definition of a specific logical name into the
;block at PTSLN.  Call GETSLN to read the name in T1, GETNLN to read the
;name after the one already in the block.
;The call is:
;
;		MOVE	T1,logical name to read
;		PUSHJ	P,GETSLN
;		 <return here if no such name>
;		 <return here with block at PTSLN>
;
;			-or-
;
;		PUSHJ	P,GETNLN
;		 <return here if no such name>
;		 <return here with block at PTSLN>

GETSLN:	TRACE$	GETSLN,T1	; TYPE DEBUGGING INFO
	MOVEM	T1,PTSLN+.PTLNM	; STORE NAME TO READ IN BLOCK
	SKIPA	T1,[PT.RCN]	; SET "READ CURRENT NAME" FLAG
GETNLN:	MOVEI	T1,0		; SET NO FLAGS
	MOVEM	T1,PTSLN+.PTLNF	; STORE THE FLAGS IN THE BLOCK
	MOVX	T1,.PTFRN	; FUNCTION TO READ LOGICAL NAMES
	MOVEM	T1,PTSLN+.PTFCN	; STORE IN BLOCK
	MOVX	T1,<.PTLLB,,PTSLN> ; POINT TO THE BLOCK
	PATH.	T1,		; READ THE NAME
	  POPJ	P,		; FAILED, PROPAGATE ERROR
	JRST	.POPJ1##	; RETURN SUCCESS
;Routine to determine if there is a path associated with the device of
;the current logical name component.
;The call is:
;
;		MOVEI	P1,Address of current scan block
;		PUSHJ	P,FNDPTH
;		 <always return here>
;
;Returns one of the following in T1:
	.FPNON==0 ; if no path associated
	.FPSPT==1 ; if device should be replaced with a simple path
		  ; (path block pointed to by PTHPTR)
	.FPIPP==2 ; if device has an implied PPN (path block pointed to
		  ; by PTHPTR)
	.FPLNM==3 ; if device is a logical name and should be replaced
		  ; with it's components (path block pointed to by LNMPTR)

FNDPTH:	TRACE$	FNDPTH,P1	; TYPE DEBUGGING INFO
	PUSH	P,[.FPNON]	; INITIALIZE RETURN VALUE
	SKIPE	T1,PTHPTR	; ALREADY HAVE SPACE?
	  JRST	FNDPT1		; YES
	MOVX	T1,.PTMAX	; AMOUNT OF SPACE WE NEED
	PUSHJ	P,GETCOR	; GET THAT MUCH
	  JRST	E$$NEC		; NO CORE!!!
	MOVEM	T1,PTHPTR	; SAVE FOR NEXT (MAYBE) CALL
FNDPT1:	MOVE	T2,.FXDEV(P1)	; GET DEVICE FOR THIS COMPONENT
	MOVEM	T2,.PTSTR(T1)	; STORE IN PATH. BLOCK
	MOVEI	T2,(T1)		; COPY ADDRESS OF BLOCK
	HRLI	T2,.PTMAX	; MAKE IT LEN,,ADDRESS
	PUSHJ	P,DOPHYS	; EXECUTE .+1 WITH/WITHOUT UU.PHY
	PATH.	T2,		; GET PATH FOR THIS NAME
	  JRST	T1POPJ		; NONE, RETURN .FPNON
	AOS	(P)		; MAKE RETURN VALUE .FPSPT
	MOVE	T2,.PTSWT(T1)	; GET SWITCHES FOR THIS ONE
	TXNE	T2,PT.IPP	; DEVICE HAVE AN IMPLIED PPN?
	  AOS	(P)		; YES, MAKE IT .FPIPP
	MOVE	T3,.FXMOD(P1)	; GET FLAG BITS FOR THIS SCAN BLOCK
	TXNN	T3,FX.PHY	; IF /PHYSICAL
	 TXNN	T2,PT.DLN	;   OR THIS IS NOT A LOGICAL NAME,
	  JRST	T1POPJ		;   RETURN .FPSPT OR .FPIPP
	SKIPE	T1,LNMPTR	; ALREADY HAVE SPACE FOR A LOGICAL NAME?
	  JRST	FNDPT2		; YES
	MOVX	T1,.PTLLB	; AMOUNT OF SPACE WE NEED
	PUSHJ	P,GETCOR	; GET THAT MUCH
	  JRST	E$$NEC		; NO CORE!!
	MOVEM	T1,LNMPTR	; SAVE FOR NEXT (MAYBE) CALL
FNDPT2:	MOVE	T2,.FXDEV(P1)	; GET LOGICAL NAME TO READ
	MOVEM	T2,.PTLNM(T1)	; STORE IN BLOCK
	MOVX	T2,PT.RCN	; GET "READ CURRENT NAME" BIT
	MOVEM	T2,.PTLNF(T1)	; STORE IN BLOCK
	MOVX	T2,.PTFRN	; GET FUNCTION TO READ LOGICAL NAMES
	MOVEM	T2,.PTFCN(T1)	; STORE IN BLOCK
	HRLI	T1,.PTLLB	; MAKE IT LEN,,ADRESS
	PATH.	T1,		; READ THE LOGICAL NAME
	  JRST	T1POPJ		; CAN'T???...RETURN .FPSPT OR .FPIPP
	AOS	(P)		; MAKE RETURN VALUE .FPLNM
T1POPJ:	POP	P,T1		; RETURN VALUE IN T1 AS ADVERTISED
	POPJ	P,		;   AND RETURN
;Routine to read the current job search list.
;The call is:
;
;		PUSHJ	P,GETJSL
;		 <return here if we can't read it>
;		 <return here if all OK with $SLCCT and $SLCPT OF JSLBLK setup>
;
;Note that this routine does not return a block that has the proper
;header words that will allow a STRUUO to be done directly.

GETJSL:	TRACE$	GETJSL		; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE1##	; SAVE P1
	MOVE	T1,JSLBLK+$SLMAX ; GET MAX NUMBER OF STRS IN JSL
	IMULI	T1,.DFJBL	; TIMES WORDS/BLOCK
	PUSHJ	P,GETCOR	; GET ENOUGH CORE
	  JRST	E$$NEC		; NO CORE, DIE
	MOVEM	T1,JSLBLK+$SLCPT ; SAVE POINTER TO BLOCK
	MOVEI	P1,(T1)		; POINT TO FIRST STR BLOCK
	SETOM	SLBLK+.DFJNM	; SET NAME TO -1 TO GET FIRST STR
GETJS1:	MOVX	T2,<.DFJST+1,,SLBLK> ; POINT TO JOBSTR BLOCK
	JOBSTR	T2,		; GET NEXT STR IN SL
	  WARN	RJS,<Can't read job search list>,,.POPJ##
	SKIPN	T2,SLBLK+.DFJNM	; STOP ON THE FENCE
	  JRST	.POPJ1##
	AOJE	T2,.POPJ1##	; OR ON END OF LIST
	MOVSI	T2,SLBLK+.DFJNM	; GET SOURCE ADDRESS
	HRRI	T2,(P1)		;   AND DESTINATION ADDRESS
	BLT	T2,.DFJBL-1(P1)	; MOVE TO STRUUO BLOCK
	AOS	JSLBLK+$SLCCT 	; BUMP STR COUNT
	ADDI	P1,.DFJBL	; BUMP STRUUO POINTER
	JRST	GETJS1		;   AND LOOP FOR MORE
;Routine to read the current system search list.
;The call is:
;
;		PUSHJ	P,GETSSL
;		 <return here if we can't read it>
;		 <return here if all OK with $SLCCT and $SLCPT of SSLBLK setup>
;
;Note that this routine does not return a block that has the proper
;header words that will allow a STRUUO to be done directly.

GETSSL:	TRACE$	GETSSL		; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE1##	; SAVE P1
	MOVE	T1,SSLBLK+$SLMAX ; GET MAX NUMBER OF STRS IN SSL
	IMULI	T1,.DFJBL	; TIMES WORDS/BLOCK
	PUSHJ	P,GETCOR	; GET ENOUGH CORE
	  JRST	E$$NEC		; NO CORE, DIE
	MOVEM	T1,SSLBLK+$SLCPT ; SAVE POINTER TO BLOCK
	MOVEI	P1,(T1)		; POINT TO FIRST STR BLOCK
	SETOM	SLBLK+.DFGNM	; SET NAME TO -1 TO GET FIRST STR
GETSS1:	MOVX	T2,<.DFGST+1,,SLBLK> ; POINT TO GOBSTR BLOCK
	GOBSTR	T2,		; GET NEXT STR IN SL
	  WARN	RSS,<Can't read system search list>,,.POPJ##
	SKIPN	T2,SLBLK+.DFGNM	; STOP ON THE FENCE
	  JRST	.POPJ1##
	AOJE	T2,.POPJ1##	; OR ON END OF LIST
	MOVSI	T2,SLBLK+.DFGNM	; GET SOURCE ADDRESS
	HRRI	T2,(P1)		;   AND DESTINATION ADDRESS
	BLT	T2,.DFJBL-1(P1)	; MOVE TO STRUUO BLOCK
	AOS	SSLBLK+$SLCCT 	; BUMP STR COUNT
	ADDI	P1,.DFJBL	; BUMP STRUUO POINTER
	JRST	GETSS1		;   AND LOOP FOR MORE
	SUBTTL	Routines that interface with SCAN


;Routine to allocate space for an input scan block for SCAN.
;The call is:
;
;		PUSHJ	P,ALCINP
;		 <always return here>
;
;Returns T1 = Address of scan block
;	 T2 = Length of scan block

ALCINP:	TRACE$	ALCINP		; TYPE DEBUGGING INFO
	MOVX	T1,$FXLEN	; GET LENGTH OF A SCAN BLOCK
	PUSHJ	P,GETCOR	; GET THAT MUCH
	  JRST	E$$NEC		; NO CORE, DIE
	SKIPN	SCNIFS		; THIS THE FIRST INPUT SPEC
	  MOVEM	T1,SCNIFS	; YES, SAVE THE ADDRESS
	SKIPE	T2,SCNILS	; IF THERE WAS A PREVIOUS BLOCK,
	  HRRZM	T1,$FXLNK(T2)	;   STORE CURRENT ADDR IN LINK OF LAST
	MOVEM	T1,SCNILS	; SAVE AS LAST ONE ALSO
	MOVX	T2,<F.BGN,,0>	; GET SOURCE OF FILE SWITCHES
	HRRI	T2,.FXLEN(T1)	;   AND DESTINATION IN SCAN BLOCK
	BLT	T2,$FXLLS(T1)	; MOVE THEM TO THE SCAN BLOCK
	MOVX	T2,$FXLEN	; RETURN LENGTH TO SCAN
	POPJ	P,		;  AND RETURN
;Routine to allocate space for an output scan block for SCAN.
;The call is:
;
;		PUSHJ	P,ALCOUT
;		 <always return here>
;
;Returns T1 = Address of scan block
;	 T2 = Length of scan block

ALCOUT:	TRACE$	ALCOUT		; TYPE DEBUGGING INFO
	MOVX	T1,$FXLEN	; GET LENGTH OF SCAN BLOCK
	PUSHJ	P,GETCOR	; GET THAT MUCH CORE
	  JRST	E$$NEC		; NO CORE, DIE
	SKIPN	SCNOFS		; THIS THE FIRST BLOCK ALLOCATED
	  MOVEM	T1,SCNOFS	; YES, SAVE THE ADDRESS
	SKIPE	T2,SCNOLS	; IF THERE WAS A PREVIOUS BLOCK,
	  HRRZM	T1,$FXLNK(T2)	;   STORE CURRENT ADDR IN LINK OF LAST
	MOVEM	T1,SCNOLS	; SAVE AS LAST ADDRESS ALSO
	MOVX	T2,<F.BGN,,0>	; GET SOURCE OF FILE SWITCHES
	HRRI	T2,.FXLEN(T1)	;   AND DESTINATION IN SCAN BLOCK
	BLT	T2,$FXLLS(T1)	; MOVE THEM TO THE SCAN BLOCK
	MOVX	T2,$FXLEN	; RETURN LENGTH FOR SCAN
	POPJ	P,		;  AND RETURN

E$$NEC:	ERROR	NEC,<Not enough core>,STOP
;Routine to memorize sticky defaults.  These defaults are stored in the
;area starting at P.BGN.
;The call is:
;
;		PUSHJ	P,MEMSTK
;		 <return here always>
;
;Returns after saving sticky defaults starting at P.BGN

MEMSTK:	TRACE$	MEMSTK		; TYPE DEBUGGING INFO
	MOVSI	T1,-F.LEN	; BUILD AOBJN POINTER TO SWITCH AREA
MEMST1:	SETCM	T2,F.BGN(T1)	; GET NEXT SWITCH
	JUMPE	T2,MEMST2	; SKIP IF NONE SPECIFIED
	SETCAM	T2,P.BGN(T1)	; STORE IN STICKY DEFAULT AREA
MEMST2:	AOBJN	T1,MEMST1	; LOOP FOR ALL SWITCHES
	POPJ	P,		;  AND RETURN


;Routine to apply sticky defaults.  These defaults are stored starting
;at P.BGN and transferred to the area starting at F.BGN if and only if
;the local switch is not specified and the sticky default was specified.
;The call is:
;
;		PUSHJ	P,APLSTK
;		 <return here always>

APLSTK:	TRACE$	APLSTK		; TYPE DEBUGGING INFO
	MOVSI	T1,-F.LEN	; BUILD AOBJN POINTER TO SWITCHES
APLST1:	SETCM	T2,F.BGN(T1)	; GET VALUE OF NEXT SWITCH
	JUMPN	T2,APLST2	; DON'T DEFAULT IF SPECIFIED
	SETCM	T2,P.BGN(T1)	; GET STICKY DEFAULT
	JUMPE	T2,APLST2	; SKIP IF NO STICKY DEFAULT
	SETCAM	T2,F.BGN(T1)	; DEFAULT THE SWITCH
APLST2:	AOBJN	T1,APLST1	; LOOP FOR ALL SWITCHES
	POPJ	P,		;  AND RETURN
;Routine to apply the SWITCH.INI defaults to the scan block. The words
;in the scan block are defaulted if and only if the current value is
;unspecified and the sticky default was specified.
;The call is:
;
;		MOVEI	P1,address of scan block
;		PUSHJ	P,MOVSTK
;		 <return here always>

MOVSTK:	TRACE$	MOVSTK		; TYPE DEBUGGING INFO
	MOVSI	T1,-F.LEN	; BUILD AOBJN POINTER TO SWITCHES
	MOVE	T2,P1		; COPY SCAN BLOCK ADDRESS
MOVST1:	SETCM	T3,.FXLEN(T2)	; GET NEXT SWITCH FROM SCAN BLOCK
	JUMPN	T3,MOVST2	; DON'T DO THIS ONE IF IT IS SPECIFIED
	SETCM	T3,P.BGN(T1)	; GET STICKY DEFAULT
	JUMPE	T3,MOVST2	; DON'T DO IT IF NOT SPECIFIED
	SETCAM	T3,.FXLEN(T2)	; STORE STICKY DEFAULT IN BLOCK
MOVST2:	AOS	T2		; BUMP SCAN BLOCK POINTER
	AOBJN	T1,MOVST1	;   AND LOOP FOR ALL SWICHES
	POPJ	P,		; RETURN WHEN DONE
;Routine to clear the sticky default area starting at P.BGN.
;The call is:
;
;		PUSHJ	P,CLRSTK
;		 <always return here>

CLRSTK:	TRACE$	CLRSTK		; TYPE DEBUGGING INFO
	STORE	T1,P.BGN,P.END,-1 ; CLEAR ALL STICKY DEFAULTS
	POPJ	P,		;  AND RETURN


;Routine to clear the file specific switch area starting at F.BGN
;The call is:
;
;		PUSHJ	P,CLRFIL
;		 <always return here>

CLRFIL:	TRACE$	CLRFIL		; TYPE DEBUGGING INFO
	STORE	T1,F.BGN,F.END,-1 ; CLEAR THE SWITCH AREA
	POPJ	P,		;  AND RETURN


;Routine to clear all switch areas.
;The call is:
;
;		PUSHJ	P,CLRALL
;		 <always return here>

CLRALL:	TRACE$	CLRALL		; TYPE DEBUGGING INFO
	STORE	T1,SW.BGN,SW.END,-1
	POPJ	P,
;Common routines to process all search list switches.  SCAN calls the
;switch specific routine preceding the search list block when one of
;these switches is seen and that routine in turn calls us.
;The calls are of the form:
;
;		MOVEI	T1,address of switch block
;		PUSHJ	P,?SLSWT
;		 <never return here>
;		 <always return here to prevent SCAN from storing value>

JSLSWT:	TXOA	F,FL.JLS	; SET JSL SWITCH SEEN FLAG
SSLSWT:	TXO	F,FL.SLS	; SET SSL SWITCH SEEN FLAG
	SKIPA	N,[JSLBLK]	; GET POINTER TO JSL PARAMETER BLOCK
	MOVEI	N,SSLBLK	; DITTO FOR SYSTEM SEARCH LIST
	TRACE$	XSLSWT,T1	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE2##	; SAVE P1-P2
	PUSHJ	P,.PSH4T##	; SAVE T1-T4
	MOVEI	P1,(T1)		; SAVE SWITCH BLOCK ADDRESS IN P1
	MOVEI	P2,(N)		; SAVE SL PARAMETER BLOCK ADDRESS IN P2
	MOVEI	T4,0		; START WITH NO MODIFIER BITS
	PUSHJ	P,.SIXSW##	; GET STRUCTURE NAME
	JUMPN	N,XSLSW1	; GO IF WE GOT A STR NAME
	CAIE	C,"*"		; USER WANT ALL STRS IN CURRENT SL?
	  JRST	E$$NSI		; NO, NULL STR IS AN ERROR
	MOVX	N,SIXBIT/*/	; RETURN SIXBIT STAR AS STR NAME
	PUSHJ	P,.TIALT##	; FLUSH THE STAR
XSLSW1:	PUSH	P,N		; SAVE THE STR NAME FOR LATER
XSLSW2:	CAIE	C,":"		; STR TERMINATED BY A COLON?
	  JRST	XSLSW3		; NO, CAN'T BE ANY MODIFIERS
	PUSHJ	P,.SIXSW##	; TRY TO GET A MODIFIER
	SKIPN	T2,N		; FIND ONE?
	  JRST	XSLSW3		; NO, MUST BE STR:,STR:,...
	PUSH	P,T4		; SAVE MODIFIER BITS
	MOVE	T1,[IOWD SLNTBL,SLNTAB] ; IOWD TO MODIFIER TABLE
	PUSHJ	P,.LKNAM##	; LOOKUP NAME IN TABLE
	  JRST	XSLSW4		; NOT FOUND, GIVE ERROR MESSAGE
	POP	P,T4		; RESTORE MODIFER BITS
	MOVEI	T1,-SLNTAB(T1)	; COMPUTE OFFSET IN TABLE
	TSZ	T4,SLITAB(T1)	; CLEAR BIT IN P2 SPECIFIED BY FLAG
	TDO	T4,SLITAB(T1)	; NOW SET ANY BITS NECESSARY
	JRST	XSLSW2		; AND LOOP FOR NEXT

XSLSW3:	POP	P,N		; RESTORE STR NAME
	PUSHJ	P,STOXSL	; STORE NAME AND BITS
	  JRST	E$$TMS		; BLOCK OVERFLOW
	PUSHJ	P,.POP4T##	; RESTORE T1-T4
	PJRST	.POPJ1##	; GIVE SKIP RETURN

XSLSW4:	SKIPGE	T1		; T1 .GE. 0 IF AMBIGUOUS MODIFIER
	ERROR	USM,<Unknown structure modifier >,NOCRLF,XSLSW5
	ERROR	ASM,<Ambiguous structure modifier >,NOCRLF
XSLSW5:	MOVE	T1,N		; GET BAD MODIFIER
	PUSHJ	P,TYPNAM	; TYPE THE NAME IN SIXBIT
	PJRST	PTHSCN		; AND GIVE UP

E$$NSI:	ERROR	NSI,<Null structure illegal in search list switch>,,PTHSCN
E$$TMS:	ERROR	TMS,<Too many structures specified in search list switch>,,PTHSCN
;Routine to store a structure name and modifier bits in the next
;available slot in the block for a search list switch.
;The call is:
;
;		MOVE	N,str name to store
;		MOVEI	P1,address of switch block (XXXBLK)
;		MOVEI	P2,address of SL parameter block
;		MOVEI	T4,Bits (NOWRITE, NOCREATE,...)
;		PUSHJ	P,STOXSL
;		 <return here if block overflowed>
;		 <return here if all ok with name stored>

STOXSL:	TRACE$	STOXSL,<N,T4,P1,P2> ; TYPE DEBUGGING INFO
	SKIPE	T2,$SLSAB(P1)	; ALREADY HAVE A BLOCK?
	  JRST	STOXS1		; YES
	MOVE	T1,$SLMAX(P2)	; MAX NUMBER OF STRS IN SEARCH LIST
	MOVEI	T2,0		; NO HEADER WORDS NECESSARY
	PUSHJ	P,BLDAOB	; ALLOCATE THE CORE AND RETURN AOBJP PTR
	MOVEM	T1,$SLSPT(P1)	; SAVE STARTING ADDRESS OF BLOCK
STOXS1:	ADDX	T2,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJP	T2,.POPJ##	; PLUS ONE MORE IF NO OVERFLOW
	MOVEM	T2,$SLSAB(P1)	; SAVE NEW AOBJP POINTER FOR NEXT TIME
	MOVEM	N,.DFJNM(T2)	; SAVE STR NAME IN BLOCK
	CAXN	N,SIXBIT/*/	; USER SPECIFY ALL STRUCTURES?/
	  TXO	T4,SL.WLD	; YES, SET WILD STR FLAG
	MOVEM	T4,.DFJST(T2)	; PLUS MODIFIER BITS
	AOS	$SLSCT(P1)	; BUMP STR COUNT
	PJRST	.POPJ1##	; GIVE SKIP RETURN


;Routine to allocate and build an AOBJP pointer to a block of core for
;a search list switch.
;The call is:
;
;		MOVEI	T1,number of STR blocks needed
;		MOVEI	T2,number of header words
;		PUSHJ	P,BLDAOB
;		  <always return here>
;
;Returns T1=address of first STR in block
;	 T2=AOBJP pointer to first STR block

BLDAOB:	TRACE$	BLDAOB,<T1,T2>	; TYPE DEBUGGING INFO
	MOVNI	T3,(T1)		; SAVE -VE BLOCK COUNT FOR LATER
	IMULI	T1,.DFJBL	; TIMES WORDS PER BLOCK
	ADDI	T1,(T2)		; PLUS NUMBER OF HEADER WORDS
	PUSHJ	P,GETCOR	; ALLOCATE THAT MUCH CORE
	  PJRST	E$$NEC		; FAILED, DIE
	ADDI	T1,(T2)		; POINT TO FIRST STR IN BLOCK
	MOVEI	T2,-.DFJBL(T1)	; BUILD RH OF AOBJP POINTER
	HRLI	T2,-1(T3)	; PLUS -<CNT+1> TO LH
	POPJ	P,		; RETURN
;Routine to print the prompt character on the TTY.
;The call is:
;
;		MOVX	T1,prompt character or -1 for continuation
;		PUSHJ	P,PROMPT	; From SCAN's prompt routine
;		 <always return here>

PROMPT:	TRACE$	PROMPT,T1	; TYPE DEBUGGING INFO
	SKPINL			; DEFEAT ^O
	  JFCL			; DON'T CARE ABOUT RETURN
	SKIPGE	T1		; CONTINUATION?
	  MOVX	T1,"#"		;   YES, USE A "#"
	PUSHJ	P,W.TTY		; WRITE IT OUT
	OUTPUT	TTY,		; MAKE SURE HE SEES IT
	POPJ	P,		;   AND RETURN


;Routine to close and release the TTY channel when we exit.
;The call is:
;
;		PUSHJ	P,XITCLS	; From SCAN's exit routine
;		 <always return here>

XITCLS:	TRACE$	XITCLS,F	; TYPE DEBUGGING INFO
	TXNE	F,FL.TOF	; TTY OPEN SUCCEED?
	  PJRST	.MNRET##	; NO, JUST RETURN
	CLOSE	TTY,		; CLOSE THE TTY
	RELEAS	TTY,		;   AND RELEASE THE CHANNEL
	PUSHJ	P,.MNRET##	; RETURN TO SCAN
	PJRST	PATH		; START OVER IF CONTINUE


;Routine to output one character to the TTY.  Flushes the buffer on a
;control character.
;The call is:
;
;		MOVX	T1,character
;		PUSHJ	P,W.TTY
;		 <always return here>

W.TTY:	SOSG	TOBUF+.BFCTR	; ANY ROOM LEFT IN THE BUFFER
	  OUTPUT TTY,		; NO, FLUSH THE BUFFER
	IDPB	T1,TOBUF+.BFPTR	; STORE THE CHARACTER IN THE BUFFER
	PUSH	P,T2		; GET A REGISTER TO USE
	MOVEI	T2,1		; GET A BIT TO SHIFT
	LSH	T2,(T1)		; SHIFT 1B35 BY VALUE OF CHARACTER
	TDNE	T2,BRKTBL	; IS THIS A BREAK CHARACTER?
	  OUTPUT TTY,		; YES, FLUSH THE BUFFER
	POP	P,T2		; RESTORE T2
	POPJ	P,		;   AND RETURN
	SUBTTL	Search list setup routines


;Routine to initialize the static data in the search list switch
;blocks.
;The call is:
;
;		PUSHJ	P,INISLB
;		  <always return here>

INISLB:	TRACE$	INISLB		;TYPE DEBUGGING INFO
	MOVE	T1,[PJSP T1,JSLSWT] ; GET INSTRUCTION TO STORE
	MOVE	T2,JSBPTR	; GET AOBJN POINTER TO TABLE
INISL1:	HRRZ	T3,0(T2)	; GET ADDRESS OF NEXT BLOCK
	MOVEM	T1,$SLJSP(T3)	; SAVE INSTRUCTION
	AOBJN	T2,INISL1	; LOOP FOR ALL BLOCKS
	HRRI	T1,SSLSWT	; NOW DO THE SAME FOR THE SYS SL
	MOVE	T2,SSBPTR	; GET AOBJN POINTER
INISL2:	HRRZ	T3,0(T2)	; GET ADDRESS OF NEXT BLOCK
	MOVEM	T1,$SLJSP(T3)	; SAVE INSTRUCTION
	AOBJN	T2,INISL2	; LOOP FOR ALL
	MOVE	T1,XSLMAX	; GET MAX SSL STRS,,MAX JSL STRS
	HLRZM	T1,SSLBLK+$SLMAX ; SAVE SSL MAX
	HRRZM	T1,JSLBLK+$SLMAX ;  AND JSL MAX
	POPJ	P,		; RETURN


;Routine to call the search list processing routine for each search list
;block that has a non-zero STR count.
;The call is:
;
;		MOVEI	P2,address of search list parameter block
;		MOVE	P3,AOBJN pointer to block address table
;		PUSHJ	P,CHKSLB
;		  <always return here>

CHKSLB:	TRACE$	CHKSLB,<P2,P3>	; TYPE DEBUGGING INFO
CHKSL1:	HRRZ	P1,0(P3)	; GET ADDRESS OF NEXT SWITCH BLOCK
	HLRZ	T1,0(P3)	; AND ADDRESS OF PROCESSING ROUTINE
	SKIPE	$SLSCT(P1)	; THIS BLOCK HAVE A NON-ZERO COUNT?
	  PUSHJ	P,(T1)		; YES, CALL ROUTINE
	AOBJN	P3,CHKSL1	; LOOP FOR ALL BLOCKS
	POPJ	P,		; RETURN
;Routine to build a new job/system search list from the block built for
;the /CREATE or /SCREATE switches.
;The call is:
;
;		MOVEI	P1,address of switch block (XXXBLK)
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,CHKCRX
;		 <always return here>

CHKCRX:	TRACE$	CHKCRX,<P1,P2>	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE4##	; SAVE P1-P4
	MOVN	P4,$SLNCT(P2)	; GET -COUNT IN ORIGINAL BLOCK (PROBABLY 0)
	MOVEI	P3,0		; INDICATE FIRST CALL FOR GTNSTR
CHKCR1:	PUSHJ	P,GTNSTR	; GET NEXT STR
	  JRST	[MOVSI	T1,(P4)	; -COUNT TO LH OF T1
		 HRR	T1,$SLNPT(P2) ; MAKE AOBJN POINTER TO BLOCK
		 PJRST	ZROCMP	; COMPRESS ANY ZERO ENTRIES
		]
	PUSHJ	P,CHKSTR	; MAKE SURE WE CAN ADD IT
	  JRST	CHKCR1		; CAN'T, IGNORE IT
	MOVSI	T3,(P4)		; GET -COUNT OF STRS IN TOTAL BLOCK
	HRR	T3,$SLNPT(P2)	; MAKE AN AOBJN POINTER TO BLOCK
CHKCR2:	CAME	T1,.DFJNM(T3)	; ALREADY THERE?
	  JRST	CHKCR4		; NO, CONTINUE
	HRRZ	T4,.DFJST(T3)	; GET SL.WLD FOR OTHER STR
	XORI	T4,(T2)		; XOR WITH SL.WLD FOR NEW STR
	TXNN	T4,SL.WLD	; ILLEGAL IF BOTH ON OR BOTH OFF
	  PUSHJ	P,E$$DPS	; SO TELL HIM
	AND	T4,.DFJST(T3)	; NOW AND WITH OLD STR BIT
	TXNN	T4,SL.WLD	; IF SET, CLEAR OLD AND ADD THIS ONE
	  JRST	CHKCR1		; SINCE OTHER ONE WAS WILD
	SETZM	.DFJNM(T3)	; PREVIOUS ONE WAS WILD, DELETE NAME
	SOS	$SLNCT(P2)	; AND DECREMENT STR COUNT
CHKCR4:	ADDX	T3,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJN	T3,CHKCR2	; LOOP FOR ALL
	PUSHJ	P,STOSTR	; STORE IN NEXT SLOT IN NEW BLOCK
	SUBI	P4,1		; DECREMENT -BLOCK COUNT
	JRST	CHKCR1		; LOOP FOR NEXT
;Routine to add any new structures to the job/system search list as
;specified by the /ADD or /SADD switches.
;The call is:
;
;		MOVEI	P1,address of switch block (XXXBLK)
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,CHKADX
;		 <always return here>

CHKADX:	TRACE$	CHKADX,<P1,P2>	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE3##	; SAVE P1-P3
	TXON	F,FL.CSL	; ALREADY HAVE A NEW SEARCH LIST?
	  PUSHJ	P,MOVCSL	; NO, MOVE CURRENT SL TO NEW BLOCK
	MOVEI	P3,0		; INDICATE FIRST CALL TO GTNSTR
CHKAD1:	PUSHJ	P,GTNSTR	; GET NEXT STR IN LIST
	  POPJ	P,		; NONE LEFT, RETURN
	PUSHJ	P,CHKSTR	; CHECK TO MAKE SURE WE CAN ADD IT
	  JRST	CHKAD1		; CAN'T, IGNORE IT
	MOVN	T3,$SLNCT(P2)	; GET CURRENT COUNT STRS IN SL
	MOVSI	T3,(T3)		; MOVE TO LH
	HRR	T3,$SLNPT(P2)	; MAKE AN AOBJN POINTER TO THAT
CHKAD2:	CAMN	T1,.DFJNM(T3)	; SAME AS THE ONE HE WANTS TO ADD?
	  JRST	[PUSHJ	P,E$$DPS ;TELL USER OF ERROR
		 JRST	CHKAD1	;   AND IGNORE IT
		]
	ADDX	T3,.DFJBL-1	; BUMP BY ONE LESS THAN THE BLOCK LENGTH
	AOBJN	T3,CHKAD2	; LOOP FOR NEXT EXISTING STR
	PUSHJ	P,STOSTR	; STORE IN NEXT SLOT IN NEW BLOCK
	JRST	CHKAD1		; LOOP FOR NEXT

E$$DPS:	WARN	DPS,<Duplicate structure >,NOCRLF
	PJRST	TYPSTR
;Routine to remove any structures from the job/system search list as
;specified by the /REMOVE or /SREMOVE switches.
;The call is:
;
;		MOVEI	P1,address of switch block (XXXBLK)
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,CHKRMX
;		 <always return here>

CHKRMX:	TRACE$	CHKRMX,<P1,P2>	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE4##	; SAVE P1-P4
	TXON	F,FL.CSL	; ALREADY HAVE A NEW SEARCH LIST?
	  PUSHJ	P,MOVCSL	; NO, MOVE CURRENT SEARCH LIST TO NEW BLK
	MOVN	P4,$SLNCT(P2)	; GET -COUNT OF STRS IN NEW SL
	MOVSI	P4,(P4)		; MOVE TO LH
	HRR	P4,$SLNPT(P2)	; MAKE IN AN AOBJN POINTER
	PUSH	P,P4		; SAVE FOR LOOP
	MOVEI	P3,0		; INDICATE FIRST CALL TO GTNSTR
CHKRM1:	PUSHJ	P,GTNSTR	; GET NEXT STR IN LIST
	  JRST	[POP	P,T1	; GET BACK ADDRESS OF BLOCK
		 PJRST	ZROCMP	; COMPRESS ZERO ENTRIES AND RETURN
		]
	PUSHJ	P,CHKSTR	; MAKE SURE IT'S OK
	  JRST	CHKRM1		; NOT, SO IGNORE IT
	MOVE	P4,(P)		; REFRESH POINTER TO EXISTING LIST
CHKRM2:	CAMN	T1,.DFJNM(P4)	; SAME AS THIS ONE IN EXISTING LIST?
	  JRST	[SETZM	.DFJNM(P4) ; YES, ZAP THE NAME
		 SOS	$SLNCT(P2);    AND DECREMENT THE STR COUNT
		 JRST	CHKRM1     ; CONTINUE WITH THE NEXT
		]
	ADDX	P4,.DFJBL-1	; BUMP EXISTING LIST POINTER
	AOBJN	P4,CHKRM2	;   AND LOOP FOR ALL
	PUSHJ	P,E$$SNS	; NOT THERE, TELL HIM
	JRST	CHKRM1		; LOOP FOR NEXT

E$$SNS:	WARN	SNS,<Structure not in search list >,NOCRLF
	PJRST	TYPSTR		; TELL OF HIS ERROR
;Routine to modify any structures in the job/system search list as
;specified by the /MODIFY or /SMODIFY switches.
;The call is:
;
;		MOVEI	P1,address of switch block
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,CHKMDX
;		 <always return here>

CHKMDX:	TRACE$	CHKMDX,<P1,P2>	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE4##	; SAVE P1-P4
	TXON	F,FL.CSL	; ALREADY HAVE A NEW SEARCH LIST?
	  PUSHJ	P,MOVCSL	; NO, MOVE CURRENT SEARCH LIST
	MOVN	P4,$SLNCT(P2)	; GET -COUNT OF STRS IN NEW SL
	MOVSI	P4,(P4)		; MOVE TO LH
	HRR	P4,$SLNPT(P2)	; MAKE AN AOBJN POINTER
	PUSH	P,P4		; SAVE FOR LOOP
	MOVEI	P3,0		; INDICATE FIRST CALL TO GTNSTR
CHKMD1:	PUSHJ	P,GTNSTR	; GET NEXT STR
	  JRST	T1POPJ		; FLUSH STACK AND RETURN
	TXNN	T2,SL.WLD	; THIS A WILD STR?
	  JRST	CHKMD3		; NO, CONTINUE
	MOVN	T3,$SLSCT(P1)	; GET -COUNT OF STRS IN THIS SWITCH
	MOVSI	T3,(T3)		; MOVE TO LH
	HRR	T3,$SLSPT(P1)	; MAKE AOBJN POINTER TO SWITCH LIST
CHKMD2:	CAMN	T1,.DFJNM(T3)	; WILD STR SAME AS EXPLICIT STR IN LIST?
	  JRST	CHKMD1		; YES, EXPLICIT STR OVERRIDES
	ADDX	T3,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJN	T3,CHKMD2	; INCREMENT AGAIN AND LOOP
CHKMD3:	PUSHJ	P,CHKSTR	; MAKE SURE IT'S OK
	  JRST	CHKMD1		; BAD, IGNORE
	MOVE	P4,(P)		; REFRESH AOBJN POINTER TO EXISTING SL
CHKMD4:	CAMN	T1,.DFJNM(P4)	; MATCH WITH THIS ONE?
	  JRST	[HRLZ	T1,T2	      ; GET VALID BITS FOR THIS STR
		 ANDCAM	T1,.DFJST(P4) ; CLEAR IN THIS ENTRY
		 HLLZ	T1,T2	      ; GET BITS SPECIFIED
		 IORM	T1,.DFJST(P4) ; AND SET IN THIS ENTRY
		 JRST	CHKMD1	; LOOP FOR NEXT
		]
	ADDX	P4,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJN	P4,CHKMD4	; INCREMENT AND LOOP IF MORE
	PUSHJ	P,E$$SNS	; NO SUCH STR
	JRST	CHKMD1		; LOOP FOR NEXT
;Routine to get the next structure from the switch block being processed.
;If a SIXBIT * is found as a structure name, the users current search
;list is returned, one at a time in place of the *.
;The call is:
;
;		MOVEI	P1,address of the switch block
;		MOVEI	P2,address of the SL parameter block
;		MOVEI	P3,0 on first call, previous value of P3
;			     on successive calls
;		PUSHJ	P,GTNSTR
;		 <return here when list is exhausted>
;		 <return here with next STR>
;Returns T1=SIXBIT STR name
;	 T2=corresponding modifier bits

GTNSTR:	TRACE$	GTNSTR,<P1,P2,P3> ; TYPE DEBUGGING INFO
	JUMPN	P3,GTNST1	; GO IF NOT FIRST CALL
	MOVN	P3,$SLSCT(P1)	; GET -COUNT OF STRS IN INPUT BLOCK
	MOVSI	P3,-1(P3)	; MOVE -<CNT+1> TO LH
	HRR	P3,$SLSPT(P1)	; ADDRESS OF FIRST BLOCK TO RH
	SUBI	P3,.DFJBL	; MAKE IT AN AOBJN POINTER
GTNST1:	ADDX	P3,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJP	P3,GTNST2	; GO IF END OF LIST
	MOVE	T1,.DFJNM(P3)	; GET NEXT STR NAME
	SKIPE	T2,GTNSAV	; DOING CURRENT SL NOW?
	 MOVE	T2,.DFJST(T2)	; YES, GET MODIFIER BITS FROM *, IF ANY
	  TRNN	T2,-1-SL.WLD	; ANY BUT SL.WLD SET?
	   IOR	T2,.DFJST(P3)	; NO, KEEP BITS FROM EXISTING STRUCTURE
	CAXE	T1,SIXBIT/*/	; WANT CURRENT SEARCH LIST?
	  PJRST	.POPJ1##	; NO, JUST RETURN IT
	MOVEM	P3,GTNSAV	; SAVE CURRENT POINTER
	MOVN	P3,$SLCCT(P2)	; GET -COUNT OF STRS IN CURRENT SL
	MOVSI	P3,-1(P3)	; MOVE -<CNT+1> TO LH
	HRR	P3,$SLCPT(P2)	; POINT TO FIRST STR BLOCK
	SUBI	P3,.DFJBL	; MAKE IT AN AOBJP POINTER
	JRST	GTNST1		; GET NEXT STR FROM CURRENT SL
GTNST2:	SKIPN	P3,GTNSAV	; DOING CURRENT SL NOW?
	  POPJ	P,		; NO, GIVE END-OF-LIST RETURN
	SETZM	GTNSAV		; NO LONGER DOING CURRENT SL
	JRST	GTNST1		; AND LOOP FOR NEXT
;Routine to move the current search list into the new block being
;built.
;The call is:
;
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,MOVCSL
;		  <always return here>

MOVCSL:	TRACE$	MOVCSL,P2	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE3##	; SAVE P1-P3
	MOVN	P3,$SLCCT(P2)	; GET -COUNT OF STRS IN CURRENT SL
	JUMPGE	P3,.POPJ##	; DONE IF NONE THERE
	MOVSI	P3,(P3)		; MOVE TO LH
	HRR	P3,$SLCPT(P2)	; MAKE AN AOBJN POINTER
MOVCS1:	MOVE	T1,.DFJNM(P3)	; GET NAME OF NEXT STR
	MOVE	T2,.DFJST(P3)	; GET MODIFIER BITS
	PUSHJ	P,STOSTR	; STORE IT IN NEW BLOCK
	ADDX	P3,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJN	P3,MOVCS1	; INCREMENT TO BLOCK AND LOOP
	POPJ	P,		; RETURN


;Routine to store a STR name and modifier bits in the next slot of
;the new search list.
;The call is:
;
;		MOVE	T1,STR name
;		MOVE	T2,modifier bits
;		MOVEI	P1,address of switch block
;		MOVEI	P2,address of SL parameter block
;		PUSHJ	P,STOSTR
;		 <always return here>

STOSTR:	TRACE$	STOSTR,<T1,T2,P1,P2> ; TYPE DEBUGGING INFO
	MOVE	T3,$SLNAB(P2)	; GET AOBJP POINTER TO NEW BLOCK
	ADDX	T3,.DFJBL-1	; INCREMENT TO NEXT BLOCK-1
	AOBJP	T3,E$$TMS	; GIVE ERROR IF TOO MANY BLOCKS
	MOVEM	T3,$SLNAB(P2)	; STORE BACK NEW POINTER
	AOS	$SLNCT(P2)	; BUMP STR COUNT
	MOVEM	T1,.DFJNM(T3)	; STORE NAME IN BLOCK
	MOVEM	T2,.DFJST(T3)	; STORE THOSE ALSO
	POPJ	P,		; RETURN
;Routine to insure that a structure is available to be added to our
;search list.  Handles conversion to real structure name.
;The call is:
;
;		MOVE	T1,name of structure to check
;		PUSHJ	P,CHKSTR
;		 <return here if not available with message typed>
;		 <return here if available to be added>
;
;Uses only T1
;Returns T1=Real name of structure

CHKSTR:	TRACE$	CHKSTR,T1	; TYPE DEBUGGING INFO
	PUSHJ	P,.SAVE1##	; GET A REGISTER TO USE
	MOVE	P1,T1		; SAVE THE STRUCTURE NAME
	MOVEM	P1,DSCBLK+.DCNAM ; PUT NAME INTO DSKCHR BLOCK
	DEVCHR	T1,		; GET THE DEVICE CHARACTERISTICS
	TXNN	T1,DV.DSK	; MUST BE A DISK
	  JRST	CHKST2		; NO, GO BITCH
	TXNN	T1,DV.AVL	;   AND AVAILABLE TO OUR JOB
	  WARN	SNA,<Structure not available >,NOCRLF,TYPSTR
	MOVX	T1,<.DCSAJ+1,,DSCBLK> ; POINT TO BLOCK
	DSKCHR	T1,		; GET DISK CHARACTERISTICS
	  JRST	CHKST2		; FAILED, GO BITCH
	TXNE	T1,DC.NNA	; NO NEW ACCESSES?
	  WARN	NNA,<No new access allowed for structure >,NOCRLF,TYPSTR
	TXNE	T1,DC.STS	; PACK MOUNTED?
	  WARN	UST,<Unusable structure >,NOCRLF,TYPSTR
	SKIPLE	T1,DSCBLK+.DCSAJ ; SINGLE ACCESS?
	  JRST	[CAME	T1,MYJOB ; YES, BY MY JOB?
		   WARN SAS,<Single access structure >,NOCRLF,TYPSTR
		 JRST	.+1	; YES, CONTINUE
		]
	CAMN	P1,DSCBLK+.DCSNM ; THIS THE REAL STRUCTURE NAME?
	  JRST	CHKST1		; YES
	TELL	RST,< >,NOCRLF
	MOVE	T1,P1		; GET NAME HE TYPED
	PUSH	P,T2		; SAVE T2 ACROSS CALLS
	PUSHJ	P,.TSIXN##	; TYPE IN SIXBIT
	MOVEI	T1,[ASCIZ/ represents structure /]
	PUSHJ	P,.TSTRG##	; TYPE THE STRING
	MOVE	T1,DSCBLK+.DCSNM ; GET THE REAL NAME
	PUSHJ	P,.TSIXN##	; TYPE IT IN SIXBIT
	MOVEI	T1,[ASCIZ/]
/]
	PUSHJ	P,.TSTRG	; END THE LINE
	POP	P,T2		; RESTORE T2
CHKST1:	MOVE	T1,DSCBLK+.DCSNM ; GET THE REAL NAME TO RETURN
	PJRST	.POPJ1##	;    AND RETURN SUCCESS

CHKST2:	WARN	UDF,<Undefined structure >,NOCRLF,TYPSTR
	SUBTTL	Miscellaneous routines


;Routine to allocate a block of core.
;The call is:
;
;		MOVEI	T1,number of words needed
;		PUSHJ	P,GETCOR
;		 <return here if no core available>
;		 <return here if core allocated>
;
;	Returns T1 = Address of the start of the block

GETCOR:	TRACE$	GETCOR,<T1,.JBFF,.JBREL> ; TYPE DEBUGGING INFO
	PUSH	P,.JBFF		; SAVE CURRENT VALUE OF .JBFF
	ADDB	T1,.JBFF	; BUMP BY LENGTH OF REQUESTED BLOCK
	CAMG	T1,.JBREL	; > THAN WHAT WE HAVE?
	  JRST	GETCO1		; NO, GO ZERO THE BLOCK
	CORE	T1,		; REQUEST THE ADDITIONAL CORE
	  JRST	[POP	P,.JBFF ; CAN'T GET IT, RESTORE .JBFF
		 POPJ	P,	;  AND RETURN ERROR
		]
GETCO1:	SETZM	@(P)		; ZERO FIRST WORD OF BLOCK
	HRRZ	T1,(P)		; GET ADDRESS OF FIRST WORD OF BLOCK
	HRLI	T1,1(T1)	; MAKE IT ADDR+1,,ADDR
	MOVSS	T1		; BLT POINTER IS ADDR,,ADDR+1
	BLT	T1,@.JBFF	; BLT THROUGH CURRENT VALUE OF .JBFF
	POP	P,T1		; RETURN ADDRESS TO USER
	JRST	.POPJ1##	; RETURN SUCCESS


;Routine to execute an instruction with or without UU.PHY depending
;on the state of FX.PHY in the current scan block.
;The call is:
;
;		MOVEI	P1,Address of current scan block
;		PUSHJ	P,DOPHYS
;		Instruction to execute
;		 <Return here if instruction did not skip>
;		 <Return here if instruction skipped>
;Uses T3 and T4

DOPHYS:	TRACE$	DOPHYS,P1	; TYPE DEBUG INFO
	MOVE	T3,@0(P)	; GET INSTRUCTION TO EXECUTE
	MOVE	T4,.FXMOD(P1)	; GET FLAG BITS FROM SCAN BLOCK
	TXNE	T4,FX.PHY	; /PHYSICAL SET?
	  TXO	T3,UU.PHY	; YES, SET PHYSICAL ONLY IN UUO
	XCT	T3		; DO THE UUO
	  CAIA			; PROPAGATE NON-SKIP
	AOS	0(P)		; INCREMENT RETURN
	JRST	.POPJ1##	; RETURN SKIP/NON-SKIP (AFTER INSTRUCTION)
;Routine to check for wildcards in a directory. Handles [-], [,]
;correctly.
;The call is:
;
;		MOVEI	P1,Address of scan block to check
;		PUSHJ	P,CHKWLD
;		 <return here if wildcards found in directory>
;		 <return here if none found>

CHKWLD:	TRACE$	CHKWLD,P1	; TYPE DEBUG INFO
	MOVX	T1,FX.DIR	; GET "DIRECTORY SPECIFIED" BIT
	TDNN	T1,.FXMOD(P1)	; [-]?
	  JRST	[AOS	(P)	; YES, GIVE SKIP RETURN
		 PJRST	SUBCDP	; AND GO HANDLE THAT CASE
		]
	SETCM	T1,.FXDIM(P1)	; GET MASK FOR PPN
	JUMPN	T1,.POPJ##	; ERROR IF WILDCARDS
	MOVE	T1,.FXDIR(P1)	; GET THE PPN
	TLNN	T1,-1		; PROJECT NUMBER SPECIFIED?
	  HLL	T1,.MYPPN##	; NO, USE OURS
	TRNN	T1,-1		; PROGRAMMER NUMBER SPECIFIED?
	  HRR	T1,.MYPPN##	; NO, USE OURS
	MOVEM	T1,.FXDIR(P1)	; STORE IT BACK
	MOVEI	T1,.FXDIR+2(P1)	; POINT TO START OF SFDS
	HRLI	T1,-<.FXLND-1>	; MAKE IT AN AOBJN POINTER
CHKWL1:	SKIPN	(T1)		; SKIP IF NOT END OF LIST
	  JRST	.POPJ1##	; RETURN SUCCESS
	SETCM	T2,1(T1)	; GET MASK FOR SFD
	JUMPN	T2,.POPJ##	; WILDCARDS ARE ILLEGAL
	ADDI	T1,1		; ADVANCE POINTER BY ONE
	AOBJN	T1,CHKWL1	;  BUMP AGAIN AND LOOP FOR ALL
	JRST	.POPJ1##	; RETURN SUCCESS
;Routine to substitute the current default path for the [-] case in the
;scan block.
;The call is:
;
;		MOVEI	P1,Address of scan block
;		PUSHJ	P,SUBCDP
;		 <always return here>

SUBCDP:	TRACE$	SUBCDP,P1	; TYPE DEBUGGING INFO
	SETZM	.FXDIR(P1)	; CLEAR FIRST WORD OF BLOCK
	HRLZI	T1,.FXDIR(P1)	; POINT TO FIRST WORD
	HRRI	T1,.FXDIR+1(P1)	;   AND NEXT WORD
	BLT	T1,.FXDIR+<2*.FXLND>-1(P1) ; CLEAR THE BLOCK
	MOVEI	T1,.FXDIR(P1)	; POINT TO PLACE TO STORE
	MOVEI	T2,MYPATH+.PTPPN ;   AND PLACE TO GET IT FROM
SUBCD1:	SKIPN	T3,(T2)		; SKIP IF NOT END OF LIST
	  POPJ	P,		; RETURN WITH PATH SETUP
	MOVEM	T3,(T1)		; STORE THE NEXT WORD
	SETOM	1(T1)		; SET MASK
	ADDI	T1,2		; BUMP OUTPUT POINTER
	AOJA	T2,SUBCD1	; AND INPUT POINTER AND LOOP


;Routine to set or clear the /SEARCH attribute bit from a PATH.
;block.  Call with PATH. block in PTSLN.
;The call is:
;		MOVEI	P1,Address of scan block
;		PUSHJ	P,SETSEA
;		 <always return here>

SETSEA:	TRACE$	SETSEA		; TYPE DEBUGGING INFO
	PUSHJ	P,GETCAP	; GET ADDITIONAL PATH (FOR /LIB)
	SKIPE	T1,$FXSEA(P1)	; IF /NOSEARCH WAS SPECIFIED
	 SKIPN	PTSAP+.PTPPN	;   OR NO /LIB EXISTS,
	  JRST	SETSE1		;   SKIP THE MESSAGE
	TELL	DOL,<Deleting old-style /LIB definition>
	SETZM	PTSAP+.PTPPN	; CLEAR THE LIB PPN
SETSE1:	DPB	T1,[POINTR PTSLN+.PTLNF,PT.SEA] ; STORE THE BIT IN THE SCAN BLOCK
	POPJ	P,		; RETURN
;Routine to move the device and path for a logical name component from
;the current scan block to the PATH. block being built for a logical
;name definition.
;The call is:
;
;		MOVEI	P1,Address of scan block
;		MOVE	P2,AOBJP pointer to the PATH. block
;		PUSHJ	P,INSSCB
;		 <return here if AOBJP pointer runs out>
;		 <return here if all OK>
;
;Returns with P2 updated.
;
;Note that this routine is VERY sensitive to the order of the PATH.
;block.  If the format changes, this routine must change also.

INSSCB:	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	SETZM	(P2)		; CLEAR NODE WORD (.PTNOD)
	MOVE	T1,.FXDEV(P1)	; GET DEVICE FOR THIS COMPONENT
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; STORE IN PATH. BLOCK (.PTLSL)
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	SETZM	(P2)		; CLEAR FILENAME WORD (.PTFIL)
	AOBJP	P2,.POPJ##	; CHECK AGAIN
	SETZM	(P2)		; CLEAR EXTENSION WORD (.PTEXT)
	MOVEI	T2,.FXDIR(P1)	; POINT TO INPUT BLOCK
	HRLI	T2,-.FXLND	; MAKE IT AN AOBJN POINTER
INSSC1:	MOVE	T1,(T2)		; GET NEXT WORD OF PATH
INSSC2:	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; STORE IN OUTPUT BLOCK (.PTLPP-.PTLEL)
	ADDI	T2,1		; SKIP THE MASK WORD IN THE SCAN BLOCK
	JUMPE	T1,.POPJ1##	; RETURN AT END OF PATH
	AOBJN	T2,INSSC1	; LOOP FOR ALL
	MOVEI	T1,0		; GET A ZERO TERMINATOR FOR THE
	JRST	INSSC2		; PATH BLOCK AND STORE IT
;Routine to move the device and path for a logical name component from
;the PATH. block returned by FNDPTH to the PATH. block being built for a
;logical name definition.
;The call is:
;
;		MOVE	P1,Address of scan block
;		MOVE	P2,AOBJP pointer to output block
;		PUSHJ	P,INSPTH
;		 <return here if AOBJP pointer runs out>
;		 <return here if all OK>
;
;Returns with P2 updated
;
;Note that this routine is VERY sensitive to the order of the PATH.
;block.  If the format changes, this routine must change also.

INSPTH:	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	SETZM	(P2)		; CLEAR NODE WORD (.PTNOD)
	MOVE	T1,.FXDEV(P1)	; GET DEVICE NAME HE SPECIFIED
	PUSHJ	P,DOPHYS	; EXECUTE .+1 WITH/WITHOUT UU.PHY
	DEVNAM	T1,		; CONVERT TO REAL NAME
	  MOVE	T1,.FXDEV(P1)	; NONE, USE HIS
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; SAVE IN OUTPUT BLOCK (.PTLSL)
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	SETZM	(P2)		; CLEAR FILENAME WORD (.PTFIL)
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	SETZM	(P2)		; CLEAR EXTENSION WORD (.PTEXT)
	MOVE	T2,PTHPTR	; GET ADDRESS OF INPUT PATH. BLOCK
	MOVEI	T2,.PTPPN(T2)	; POINT AT INPUT PATH STORAGE
INSPT1:	MOVE	T1,(T2)		; GET NEXT WORD OF PATH
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; STORE IN OUTPUT BLOCK (.PTLPP-.PTLEL)
	JUMPE	T1,.POPJ1##	; RETURN AT END OF PATH
	AOJA	T2,INSPT1	; BUMP INPUT POINTER AND LOOP
;Routine to move the components of a logical name into the PATH. block
;for a new logical name being built.  This is done when the user
;specifies an existing logical name as a component of one being defined.
;The call is:
;
;		MOVE	P2,AOBJP pointer to output block
;		PUSHJ	P,INSLNM
;		 <return here if AOBJP pointer runs out>
;		 <return here if all OK>
;
;Returns with P2 updated
;
;Note that this routine is VERY sensitive to the order of the PATH.
;block.  If the format changes, this routine must change also.

INSLNM:	MOVE	T2,LNMPTR	; GET ADDRESS OF INPUT PATH. BLOCK
	MOVEI	T2,.PTLSB(T2)	; POINT TO START OF COMPONENTS
INSLN1:	SKIPN	T1,0(T2)	; LOOK FOR TWO WORD TERMINATOR
	 SKIPE	1(T2)		; AT END OF BLOCK
	  CAIA			; NOT FOUND, CONTINUE WITH THIS ONE
	   JRST	.POPJ1##	; RETURN AT END OF BLOCK
	HRLI	T2,-<.PTEXT-.PTNOD+1> ; MAKE AOBJN POITNER FOR 4 WORDS
INSLN2:	MOVE	T1,(T2)		; GET NEXT WORD
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; STORE IN BLOCK (.PTNOD-.PTEXT)
	AOBJN	T2,INSLN2	; LOOP FOR ALL
INSLN3:	MOVE	T1,(T2)		; GET NEXT WORD OF PATH
	AOBJP	P2,.POPJ##	; CHECK FOR BLOCK OVERFLOW
	MOVEM	T1,(P2)		; STORE IN OUTPUT BLOCK
	SKIPE	T1		; END OF PATH?
	  AOJA	T2,INSLN3	; NO CONTINUE
	AOJA	T2,INSLN1	; LOOP FOR NEXT COMPONENT
;Routine to type the name of the structure in error.
;The call is:
;
;		PUSHJ	P,TYPSTR
;		 <always return here>

TYPSTR:	TRACE$	TYPSTR		; TYPE DEBUGGING INFO
	MOVE	T1,DSCBLK+.DCNAM ; GET THE NAME HE TYPED
;;	PJRST	TYPNAM		; FALL INTO TYPNAM


;Routine to type a name in SIXBIT followed by a CRLF.
;The call is:
;
;		MOVE	T1,name to type
;		PUSHJ	P,TYPNAM
;		  <always return here>

TYPNAM:	TRACE$	TYPNAM,T1	; TYPE DEBUGGING INFO
	PUSH	P,T2		; SAVE T2 (.TSIXN DESTROYS IT)
	PUSHJ	P,.TSIXN##	; TYPE IN SIXBIT
	POP	P,T2		; RESTORE T2
	PJRST	.TCRLF##	; END LINE AND RETURN


;Routine to compress the zero entries from a STRUUO block.
;The call is:
;
;		MOVE	T1,AOBJN pointer to block
;		PUSHJ	P,ZROCMP
;		 <always return here>

ZROCMP:	TRACE$	ZROCMP,T1	; TYPE DEBBUGGING INFO
	MOVE	T2,T1		; COPY POINTER (USE T1 AS HOLE FINDER)
				;	       (USE T2 AS NEXT FREE POINTER)
ZROCM1:	SKIPN	(T1)		; NEXT ONE EMPTY?
	  JRST	ZROCM2		; YES, JUST ADVANCE HOLE FINDER
	HRLI	T3,(T1)		; GET SOURCE ADDRESS
	HRRI	T3,(T2)		;   AND DESTINATION ADDRESS
	BLT	T3,.DFJBL-1(T2)	; MOVE TO NEXT FREE BLOCK
	ADDI	T2,.DFJBL	; ADVANCE NEXT FREE POINTER
ZROCM2:	ADDI	T1,.DFJBL-1	; ALWAYS ADVANCE HOLE FINDER
	AOBJN	T1,ZROCM1	; AND LOOP FOR ALL BLOCKS
	POPJ	P,		; RETURN
	SUBTTL	Message processing routines


;Routines to print a fatal, warning, or informative message on the TTY.
;All are called as follows:
;
;		PUSHJ	P,.XXX
;		CAI	Code,[XWD Prefix,[Message]]
;		<return here unless EO.STP specified>
;
;Where Code is the error option code (see EO.XXX)
;      Prefix is the path error message prefix
;      Message is the message to be printed

.ERR:	TXO	F,FL.ERR	; SET FATAL ERROR FLAG
	PUSHJ	P,.PSH4T##	; SAVE T1-T4
	MOVX	T4,"?"		; GET ERROR CHARACTER
	PJRST	ERRCOM		; JOIN COMMON ROUTINE

.WARN:	TXO	F,FL.WRN	; SET WARNING MESSAGE FLAG
	PUSHJ	P,.PSH4T##	; SAVE T1-T4
	MOVX	T4,"%"		; GET ERROR CHARACTER
	PJRST	ERRCOM		; JOIN COMMON ROUTINE

.TELL:	TXO	F,FL.TEL	; SET INFO MESSAGE FLAG
	PUSHJ	P,.PSH4T##	; SAVE T1-T4
	MOVX	T4,"["		; GET ERROR CHARACTER
;;	PJRST	ERRCOM		; JOIN COMMON CODE

ERRCOM:	MOVSI	T1,'PTH'	; GET OUR MNEMONIC
	HRRZ	T2,-4(P)	; GET ADDR OF CAI WORD (OFFSET FOR .PSH4T)
	MOVE	T2,@(T2)	; GET PREFIX,,ADDR OF MESSAGE
	HLR	T1,T2		; ADD PREFIX ERROR CODE
	HRL	T2,T4		; PUT IN LEADING CHARACTER
	PUSHJ	P,.ERMSG##	; LET SCAN DO THE WORK
	LDB	T1,[POINT 4,@-4(P),12] ; GET CODE FROM AC FIELD OF CAI WORD
	TXZE	F,FL.TEL	; WAS IT INFORMATIVE?
	 CAXN	T1,EO.NCR	;   OR NO CRLF WANTED?
	  CAIA			; YES, DON'T TYPE RIGHT BRACKET
	   PUSHJ P,.TRBRK##	; PUT OUT A RIGHT BRACKET
	LDB	T1,[POINT 4,@-4(P),12] ; GET CODE BACK
	CAXG	T1,EO.MAX	; LARGER THAN MAX?
	  JUMPN	T1,@[DOEXIT
		     ERRCO1]-1(T1) ; DISPATCH BASED ON ERROR CODE
	PUSHJ	P,.TCRLF##	; END MESSAGE WITH CRLF
ERRCO1:	PUSHJ	P,.POP4T##	; RESTORE T1-T4
	PJRST	.POPJ1##	; RETURN, SKIPPING CAI WORD

DOEXIT:	PUSHJ	P,.MONRT##	; LET SCAN KILL THE PROGRAM
	JRST	.-1		; NO CONTINUE
	SUBTTL	Debug package


;Routine to print debug information upon entry to a subroutine.
;Assembled and called only if the switch DEBUG$ is non-zero.
;The call is:
;
;		PUSHJ	P,.DEBUG	; From TRACE$ macro
;		CAI	[SIXBIT/NAME/	; Routine name
;			 EXP	LOC1	; Address of first loc
;			 EXP	LOC2	; Address of second loc
;			     :
;			 EXP	LOCN	; Address of nth loc
;			 XWD	-1,0]	; -1,,0 terminates block
;		<always return here>
IFN DEBUG$, <			; ASSEMBLE ONLY IF DEBUGGING
.DEBUG:	MOVEM	16,DEBAC+16	; SAVE AC 16
	MOVX	16,<0,,DEBAC>	; BUILD BLT POINTER
	BLT	16,DEBAC+15	; SAVE ALL AC'S
	HRRZ	P1,@0(P)	; GET ADDRESS OF CAI BLOCK
	MOVEI	T1,[BYTE (7)76,76,40,0,0] ; TWO ANGLE BRACKETS AND A SPACE
	PUSHJ	P,.TSTRG##	;TYPE IT
	MOVE	T1,(P1)		; GET SIXBIT ROUTINE NAME
	PUSHJ	P,.TSIXN##	; TYPE IN SIXBIT
	MOVEI	T1,[ASCIZ/ called from PC /]
	PUSHJ	P,.TSTRG##	; TYPE IT
	HRRZ	T1,-1(P)	; GET PC OF CALLER OF SUBROUTINE
	SUBI	T1,1		; MAKE IT POINT TO THE CALLER
	MOVEI	P2,(T1)		; SAVE IN P2
	PUSHJ	P,.TOCTW##	; TYPE IN OCTAL
	MOVEI	T1,[ASCIZ/ = /]	; SEPARATOR
	PUSHJ	P,.TSTRG##	; TYPE IT
	PUSHJ	P,STSRCH	; FIND PC SYMBOLIC LOC AND TYPE IT
	PUSHJ	P,.TCRLF##	; END THE LINE
.DEBU1:	SKIPGE	1(P1)		; DONE ALL OF THEM YET?
	  JRST	.DEBU2		; YES
	MOVEI	T1,[ASCIZ/	C(/] ; PREFIX FOR LOCATION NAME
	PUSHJ	P,.TSTRG##	; TYPE IT
	MOVE	P2,1(P1)	; GET ADDRESS OF LOCATION
	PUSHJ	P,STSRCH	; SEARCH SYMBOL TABLE FOR IT
	MOVEI	T1,[ASCIZ/) = /]
	PUSHJ	P,.TSTRG##	; TYPE SEPARATOR
	CAIG	P2,16		; IS IT AN AC?
	  MOVEI	P2,DEBAC(P2)	; YES, POINT AT AC BLOCK
	MOVE	T1,(P2)		; GET VALUE OF ADDRESS
	PUSHJ	P,.TXWDW##	; TYPE AS HALFWORDS
	PUSHJ	P,.TCRLF##	; END THE LINE
	AOJA	P1,.DEBU1	; BUMP CAI BLOCK POINTER AND LOOP
.DEBU2:	MOVX	16,<DEBAC,,0>	; SETUP BLT POINTER TO RESTORE AC'S
	BLT	16,16		;   AND DO SO
	PJRST	.POPJ1##	; RETURN SKIPPING CAI WORD
;Routine to search the symbol table for an address and print the
;symbolic name of that address.  If no exact match is found, the closest
;symbolic name plus offset from that name is printed.
;The call is:
;
;		MOVEI	P2,Address to find
;		PUSHJ	P,STSRCH
;		 <always return here>

STSRCH:	SKIPN	T2,.JBSYM	; HAVE A SYMBOL TABLE?
	  JRST	[MOVEI	T1,(P2) ; NO, GET OCTAL VALUE OF ADDRESS
		 PJRST	.TOCTW## ;  AND PRINT IT IN OCTAL
		]
	SETZB	P3,P4		; P3=CLOSEST ST PTR, P4=CLOSEST VALUE
STSRC1:	MOVE	T1,1(T2)	; GET VALUE OF NEXT SYMBOL
	CAML	T1,P4		; IF LESS THAN THE CLOSEST WE'VE SEEN
	 CAILE	T1,(P2)		;   OR GREATER THAN THE ONE WE WANT,
	  JRST	STSRC2		;  IGNORE IT
	MOVEI	P3,(T2)		; SAVE POINTER TO CLOSEST ONE WE'VE SEEN
	MOVE	P4,T1		;  PLUS VALUE OF THAT SYMBOL
STSRC2:	AOBJP	T2,STSRC3	; QUIT WHEN WE RUN OUT OF SYMBOL TABLE
	CAME	P2,T1		;  OR IF WE FIND AN EXACT MATCH
	AOBJN	T2,STSRC1	; ELSE LOOP FOR NEXT SYMBOL
STSRC3:	MOVE	T2,0(P3)	; GET RADIX50 NAME FOR THE SYMBOL
	PUSHJ	P,PRDX50	;  AND PRINT IT
	MOVEI	T1,(P2)		; GET ADDRESS WE WANTED TO FIND
	SUB	T1,P4		; COMPUTE OFFSET FROM ADDRESS WE FOUND
	JUMPE	T1,.POPJ##	; IF EXACT MATCH, QUIT NOW
	PUSH	P,T1		; SAVE OFFSET
	MOVEI	T1,"+"		; TO INDICATE OFFSET
	PUSHJ	P,.TCHAR##	; PRINT THE PLUS
	POP	P,T1		; RESTORE THE OFFSET
	PJRST	.TOCTW##	; PRINT IT AND RETURN


;Routine to print a radix 50 symbol on the terminal.  The
;call is:
;
;		MOVE	T2,Symbol to print
;		PUSHJ	P,PRDX50
;		 <always return here>

PRDX50:	MOVEI	T1,6		; NUMBER OF CHARS TO PRINT
	TXZ	T2,17B3		; CLEAR CODE FROM SYMBOL TABLE
	MOVEI	T4,0		; T4=REGISTER IN WHICH TO BUILD SIXBIT NAME
PRDX51:	IDIVI	T2,50		; GET NEXT CHAR IN T3
	ROT	T3,-1		; INDEX IN RH, HALFWORD FLAG IN 1B0
	SKIPGE	T3		; SKIP IF CHARACTER IN LH OF RDX50T
	 SKIPA	T3,RDX50T(T3)	; PICK UP RH CHARACTER
	  MOVS	T3,RDX50T(T3)	; PICK UP LH CHARACTER
	LSHC	T3,-6		; SHIFT INTO ACCUMULATED SIXBIT WORD
	SOJG	T1,PRDX51	; LOOP FOR NEXT CHARACTER
	MOVE	T1,T4		; GET ACCUMULATED SIXBIT EQUIVALENT
	PJRST	.TSIXN##	; PRINT IN SIXBIT AND RETURN
;Table of SIXBIT equivalent characters indexed by the RADIX 50
;character set.

RDX50T:	XWD	' ','0'		; SPACE, ZERO
	XWD	'1','2'		; ONE, TWO
	XWD	'3','4'		; THREE, FOUR
	XWD	'5','6'		; FIVE, SIX
	XWD	'7','8'		; SEVEN, EIGHT
	XWD	'9','A'		; NINE, A
	XWD	'B','C'		; B, C
	XWD	'D','E'		; D, F
	XWD	'F','G'		; F, G
	XWD	'H','I'		; H, I
	XWD	'J','K'		; J, K
	XWD	'L','M'		; L, M
	XWD	'N','O'		; N, O
	XWD	'P','Q'		; P, Q
	XWD	'R','S'		; R, S
	XWD	'T','U'		; T, U
	XWD	'V','W'		; V, W
	XWD	'X','Y'		; X, Y
	XWD	'Z','.'		; Z, PERIOD
	XWD	'$','%'		; DOLLAR SIGN, PERCENT SIGN

	$LOW
DEBAC:	BLOCK	17		; AC SAVE AREA
DEBALL:	EXP	0		; DEPOSIT NON-ZERO TO TYPE INFO
	$HIGH
>	; END IFN DEBUG$



	END	PATH