Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-06 - 43,50441/wilder.mac
There are no other files named wilder.mac in the archive.
	TITLE	WILDER
	SUBTTL	WILD CARD HANDLING MODULE

	.REQUEST LIB

	COMMENT	^

WILDER WILL FIND FILES MATCHING WILD SPECIFICATIONS.  WILDER IS
WRITTEN TO BE USED WITH SCNNER, SO IT EXPECTS DATA BLOCKS OF THE
TYPE RETURNED BY SCNNER.

THE CALL TO WILDER IS AS FOLLOWS:

	MOVE	1,[ROUTINE TO CALL WHEN FILE FOUND,,ADDR OF DATA BLOCK]
	PUSHJ	17,WILDER##

WHENEVER A FILE IS FOUND MATCHING WILD SPECIFICATIONS, THE SPECIFIED
ROUTINE IS PUSHJ'D TO.  THE DEVICE OPEN BLOCK IS AT NEWDEV##, AND AN
EXTENDED LOOKUP BLOCK (WITH EXTRA SPACE FOR VERY EXTENDED LOOKUPS)
STARTS AT LABEL NEWFIL##.  IF THERE ARE ANY SFD'S, THE PPN SPECIFICATION
IN THE LOOKUP BLOCK WILL POINT TO NEWPTH##.

WILDER USES CHANNEL "CHN", WHICH IS PROBABLY DEFINED HERE AS CHANNEL
ZERO.  THIS CHANNEL MAY BE USED BY THE USER TO LOOKUP OR RENAME FILES,
BUT IT SHOULD NOT BE RELEASED OR ALTERED.

THUS, WHEN LOADED WITH SCNNER, A TYPICAL CALL TO WILDER WOULD BE:

	MOVE	1,[TAG,,DEVSPC##]	;POINT TO SCNNER DATA
	PUSHJ	P,WILDER##		;GO FIND WILD THINGS
	EXIT				;ONLY RETURN

TAG:	OPEN	FIL,NEWDEV##		;OPEN DEVICE
	  HALT
	LOOKUP	FIL,NEWFIL##		;LOOKUP FILE
	  HALT
;DO SOMETHING WITH FILE
	POPJ	P,			;RETURN TO WILDER

WILDER ONLY USES ONE DATA CHANNEL, WHICH IS DEFINED AS "CHN".
THIS MAY NOT BE TAMPERED WITH BY THE USER PROGRAM.

NOTE -- .JBFF IS USED TO DETERMINE BUFFERS.  THESE BUFFERS ARE ALLOCATED
AND RELEASED AS WILDER RUNS.  IF YOU DO NOT WANT BUFFERS RELEASED,
SET KEPCOR## TO A NON-ZERO VALUE WHEN WILDER CALLS THE USER-SPECIFIED
ROUTINE.  EVERY CALL TO WILDER ZERO'S KEPCOR##.

NOTE THAT THE SCNNER BLOCKS MUST ALWAYS USE EXTENDED PATH BLOCKS.
WARNING ... WILDER CAN GO DEEP IN A PDL!

	^
	SUBTTL	DEFINITIONS


	IFNDEF	CITPPN,<CITPPN==0>	;CALTECH-TYPE PPN'S
	IFNDEF	.HI.,<	.HI.==-1>	;DEFAULT TO HI SEG
		IFN	.HI.,<	TWOSEG>	;TWO SEGMENTS IF SPECIFIED
	IFNDEF	NDSKOK,<NDSKOK==1>	;SET TO ATTEMPT TO OK NON-DISKS

;AC'S USED

	F=0	;FLAGS
	T1=1	;TEMPORARY
	T2=2
	T3=3
	T4=4
	T5=5
	LVL=6	;CURRENT LEVEL OF DIRECTORY NESTING
	NDX=7	;FIRST ADDRESS OF DATA BLOCK
	LNDX=10	;SAME AS NDX, BUT INCREMENTED BY LEVEL OF NESTING
	PTR=11	;POINTER TO DIRECTORY BUFFER
	P=17	;PUSH DOWN POINTER


;FLAGS

	F$ALL==1B35	;USE DEVICE "ALL" SEARCH LIST
	F$DSK==1B34	;USE JOB SEARCH LIST
	F$FILF==1B33	;SET IF ANY FILE FOUND
	F$LOWL==1B32	;WE HAVE REACHED THE LOWEST LEVEL OF NESTING
	F$WILD==1B30	;SET IF THERE ARE ANY WILD CARDS
	F$WLOW==1B29	;SET IF LOWEST LEVEL REACH ON WILD SEARCH
	F$DEV==1B28	;SET ON SUCCESSFUL DEVICE OPEN
	F$SCAN==1B27	;SET TO SCAN HIGHER LEVELS FOR FILES
	F$BACK==1B26	;SET TO SCAN FILES BEFORE DIRECTORIES


;USEFUL OPDEF'S

	OPDEF	PJRST	[JRST]
	OPDEF	PJSP	[JSP]


;DATA CHANNEL FOR WILDER

	CHN==0
;I/O DATA

	.IODMP==17		;DUMP MODE
		PHONLY==1B0	;PHYSICAL ONLY OPEN

	DV.TTY==10,,0		;DEVICE IS A TTY
	DV.DTA==100,,0		;DEVCHR BIT INDICATING DECTAPE


;JOB DATA

	.JBREL==44		;0,,HIGH LEGAL ADDR IN LOW SEG
	.JBFF==121		;0,,FIRST FREE ADDR IN LOW SEG


;RIB DATA

	.RBPPN==1		;PPN
	.RBNAM==2		;FILE NAME
	.RBEXT==3		;FILE EXTENSION
	.RBSIZ==5		;FILE SIZE IN WORDS


;RELATIVE LOCATIONS OF WORDS IN DATA BLOCK

	DEVSPC==0		;DEVICE OPEN BLOCK
	FILSPC==3		;FILE LOOKUP BLOCK
	PTHSPC==10		;PATH LIST
	FILMSK==20		;FILE MASK
	EXTMSK==21		;EXTENSION MASK
	PPNMSK==22		;MAKS FOR PPN
	PTHMSK==23		;MASK FOR SFD'S


;DSKCHR VALUES

	.DCSNM==4		;FILE STRUCTURE NAME


;LOOKUP ERRORS

	ERFNF%==0		;FILE NOT FOUND
	ERIPP%==1		;NO SUCH UFD
	ERPRT%==2		;PROTECTION FAILURE
	ERSNF%==23		;NO SUCH SFD
	SUBTTL	DATA STORAGE

	RELOC	0			;START IN LOW SEG

	INTERN	NEWDEV,NEWFIL,NEWPTH,KEPCOR,ALLWLD,SCNWRD,BCKWRD

	FRSZER==.		;FIRST ADDR TO ZERO

NEWDEV:	BLOCK	3		;NEW OPEN BLOCK
NEWFIL:	BLOCK	40		;NEW LOOKUP BLOCK
NEWPTH:	BLOCK	11		;PATH BLOCK

MFDPPN:	BLOCK	1		;PPN FOR UFD'S
MAKPTH:	BLOCK	6		;BUILD UP PATH HERE

KEPCOR:	BLOCK	1		;IF NON-ZERO, DON'T RELEASE CORE
GOBBLK:	BLOCK	3		;BLOCK FOR GOBSTR
DSKBLK:	BLOCK	.DCSNM+1	;BLOCK FOR DSKCHR

SRCTRY:	BLOCK	1		;LEVEL AT WHICH DIR SEARCH ATTEMPTED
SRCSUC:	BLOCK	1		;LEVEL AT WHICH RESULTS ARE FOUND
MSTWRD:	BLOCK	1		;HOLDS VALUE OF NESTING LEVEL ON FAILURE
MSTFIL:	BLOCK	4		;BLOCK FOR BAD LOOKUP
MSTPTH:	BLOCK	10		;PATH BLOCK FOR BAD LOOKUP

	LSTZER==.-1		;LAST ADDR TO ZERO

SAV0:	BLOCK	1		;SAVE AC 0
SAVAC:	BLOCK	10		;SAVE AC'S 2-11
ALLWLD:	BLOCK	1		;SET TO NON ZERO TO FORCE WILD CARDS
SCNWRD:	BLOCK	1		;SET TO ONES BY USER BEFORE WILDER
				; CALL TO PREVENT SCAN OF HIGHER SFD LEVELS
BCKWRD:	BLOCK	1		;SET BY USE TO CAUSE FILE SCAN BEFORE DIR SCAN
	SUBTTL	MAIN ROUTINES
	ENTRY WILDER
	IFN	.HI.,<	RELOC	400000>	;HI SEG

;HERE IS THE ENTRY POINT.  FIRST INITIALIZATION.

WILDER:	MOVEM	0,SAV0			;SAVE AC 0
	MOVE	0,[2,,SAVAC]		;SAVE THE REST
	BLT	0,SAVAC+7		;BLITTTT
	PUSH	P,[EXP RSTACS]		;RESTORE ON POPJ
	MOVE	NDX,T1			;SAVE PTR TO DATA AND ADDR
	MOVEI	LNDX,-1(T1)		;SET UP SPECIAL INDEX
	SETZB	F,FRSZER		;ZERO FLAGS AND DATA
	AOSE	SCNWRD			;DID USER DISENABLE SCANNING?
	  TRO	F,F$SCAN		;NO, SET SCAN FLAG
	AOSN	BCKWRD			;DID USER REQUEST BACKWARDS SCAN?
	  TRO	F,F$BACK		;YES, FLAG IT
	MOVE	T2,[FRSZER,,FRSZER+1]	;BLT SETUP
	BLT	T2,LSTZER		;BLIIITTTT
	MOVE	T2,[1,,1]		;SET UP MFDPPN
	MOVEM	T2,MFDPPN		; ..
	SETOB	LVL,MSTWRD		;INITIALIZE LEVEL OF DESCENT
	SETOM	SRCTRY			;INITIALIZE SEARCH WORDS
	SETOM	SRCSUC			; ..
	HRLI	T1,CHN			;FIRST OPEN CHANNEL
IFN <DEVSPC>,<
	ADDI	T1,DEVSPC		;RH OF T1 POINTS TO OPEN BLOCK>
	PUSHJ	P,OPNDEV##		;OPEN IT
	  POPJ	P,			;ERROR -- QUIT
	MOVE	T1,[3,,T2]		;POINTER
	MOVEI	T2,CHN			;CHANNEL IN T2
;*****KLUDGE FOR MONITOR BUG
	MOVEI	T5,CHN			;SET UP CHANNEL
	DEVNAM	T5,			;SEE WHERE IT GOES
	  HALT	.
	CAME	T5,['NUL   ']		;REJECT THE NULL DEVICE
;*****END OF KLUDGE
	PATH.	T1,			;LEARN ABOUT CHANNEL
	  JRST	NOTDSK			;IT'S NOT A DISK!
	SETOM	GOBBLK+1		;GOBSTR WILL USE MY PPN
	SETOM	GOBBLK+2		;START WITH FIRST STRUCTURE
	TRNE	T3,1B30			;IGNORE USER PPN?
	  MOVEM	T4,FILSPC+.RBPPN(NDX)	;YES, USE FUNNY PPN
	LDB	T1,[POINT 3,T3,29]	;GET DEVICE CODE FROM PATH.
;*****KLUDGE FOR MONITOR BUG
	CAMN	T2,['DSK   ']		;IF DISK SPECIFIED
	TRNN	T5,-1			;BUT THE CHANNEL IS MORE SPEC.
	  JRST	.+2			;NOT THE CASE
	  MOVE	T2,T5			;THEN USE MORE SPECIFIC DEVICE
	CAME	T2,['DSK   ']		;IF DISK
	CAMN	T2,['LIB   ']		;OR LIB
	  MOVEI	T1,1			;THEN USE JOB SEARCH LIST
;*****END OF KLUDGE

;CONTINUED
	XCT	[JRST	[MOVEM	T2,DSKBLK	;PUT DEVICE IN BLOCK
			 MOVE	T1,[.DCSNM+1,,DSKBLK]
			 DSKCHR	T1,		;FIND OUT ABOUT STR
			  HALT
			 MOVE	T2,DSKBLK+.DCSNM;GET REAL STR
			 JRST	.+1]
		 JRST	[TRO	F,F$DSK	;USE SYSTEM SEARCH LIST
			 SETOM	GOBBLK	; ..
			 JRST	.+1]
		 TRO	F,F$ALL		;USE ALL SEARCH LIST
		 TRO	F,F$DSK		;USE JOB SEARCH LIST
				](T1)

	SKIPN	FILSPC+.RBNAM(NDX)	;SEE IF NAME OR WILD NAME GIVEN
	SKIPE	FILMSK(NDX)		; ..
	  JRST	WILD1			;YES, NAME GIVEN
	PJSP	T1,LINOUT##		;NONE GIVEN -- TYPE MESSAGE
	  ASCIZ/? No file name given
/
WILD1:	MOVSI	T1,-10			;NOW CHECK FOR WILD CARDS
	ADDI	T1,(NDX)		;RELOCATE TO DATA AREA
	SKIPN	ALLWLD			;IF WILD CARD LOOKUP ALWAYS
WILD3:	SKIPE	FILMSK(T1)		;ANY MASK?
	  TROA	F,F$WILD		;IF SO, SET FLAG
	AOBJN	T1,WILD3		;LOOP FOR MORE

;NOW FALL INTO DEVICE LOOP
;NOW GO THROUGH THIS LOOP ONCE FOR EVERY DEVICE SEARCHED

DODEV:	MOVE	T1,[PHONLY!.IODMP]	;SET UP OPEN BLOCK
	MOVEM	T1,NEWDEV		;DEVICE BLOCK
	SETZM	NEWDEV+2		;NO BUFFERS
	TRNN	F,F$DSK			;USING DSK SEARCH LIST?
	  JRST	DODEV1			;NO, SKIP ON
	MOVE	T1,[3,,GOBBLK]		;GOBSTR PTR
	GOBSTR	T1,			;GET NEXT DEVICE
	  HALT	.
	SKIPA	T2,GOBBLK+2		;GET DEVICE IN T2
DODEV1:	TRNN	F,F$ALL			;USING ALL?
	  JRST	DODEV2			;NO, SKIP ON
	MOVE	T2,NEWDEV+1		;GET LAST DEVICE
	SYSSTR	T2,			;WHAT IS NEXT?
	  HALT	.
DODEV2:	JUMPE	T2,DONE			;DONE IF NO DEVICE IN T2
	TRO	F,F$DEV			;FLAG REASONABLE DEVICE
	MOVEM	T2,NEWDEV+1		;SAVE IN OPEN BLOCK
	OPEN	CHN,NEWDEV		;OPEN IT
	  JRST	[PUSHJ	P,STROUT##	;EXPLAIN PROBLEM
		   ASCIZ/? Open failure on device /
		 MOVE	T1,NEWDEV+1	;GET IT
		 PUSHJ	P,WRDOUT##	;TYPE NAME
		 PUSHJ	P,TCRLF##	;AND CRLF
		 JRST	DODEV3]		;AND CONTINUE
	PUSHJ	P,DOWILD		;GO DO WILD SEARCH
DODEV3:	TRNE	F,F$ALL!F$DSK		;MORE THAN ONE LOOP POSSIBLE?
	  JRST	DODEV			;YES, LOOP BACK

;FALL INTO EXIT ROUTINE
;FINAL ROUTINE CHECKS FOR ERRORS AND RETURNS CONTROL TO CALLER


DONE:	RELEAS	CHN,			;GIVE UP CHANNEL
	TRNE	F,F$FILF		;FIND ANYTHING?
	  POPJ	P,			;YES, JUST RETURN
	TRNE	F,F$DEV			;ANY DEVICES IN SEARCH LIST?
	  JRST	DONDEV			;YES, SKIP ON
	PUSHJ	P,STROUT##		;TELL THE CLOWN
	  ASCIZ/? Search list empty for device /
	MOVE	T1,DEVSPC+1(NDX)	;GET DEVICE
	PUSHJ	P,WRDOUT##		;TYPE IT
	PJRST	TCRLF##			;CRLF AND RETURN

DONDEV:	TRNN	F,F$WILD		;IF NO WILD CARDS
	  JRST	DONONE			;GIVE ERROR
	TRNE	F,F$WLOW		;SEE IF REACHED LOWEST LEVEL
	  JRST	DONE1			;YES, GIVE FILES REJECTED MSG
	MOVE	T1,SRCTRY		;GET LOWEST LEVEL OF UFD SEARCH
	CAME	T1,SRCSUC		;WAS UFD FOUND AT THAT LEVEL?
	  JRST	DONE0			;NO, NO SUCH PATH
	MOVSI	T1,-6			;SIX LEVELS OF NESTING
	MOVEI	T2,(NDX)		;GET INDEX TO DATA
	SETZ	T3,			;T3 WILL BE FLAG
DONELP:	MOVE	T4,MSTPTH+2(T1)		;GET DIRECTORY
	TDZE	T4,PPNMSK(T2)		;ZERO MASKED PARTS
	  SETO	T3,			;FLAG MASK FOUND
	MOVEM	T4,PTHSPC+2(T2)		;SAVE IN ORIGINAL DATA AREA
	AOJ	T2,			;INCREMENT INDEX
	AOBJN	T1,DONELP		;LOOP BACK IF MORE
	JUMPL	T3,DONEFA		;JUMP IF SOMETHING MASKED
DONONE:	MOVEI	T1,MSTPTH		;POINTER TO PATH
	MOVEM	T1,MSTFIL+.RBPPN	;PUT IN LOOKUP BLOCK
	MOVEI	T1,MSTFIL		;PTR TO BAD LOOKUP BLOCK
	HRLI	T1,DEVSPC(NDX)		;LH GETS BAD OPEN BLOCK
	PJRST	LOOKFA##		;TYPE LOOKUP FAILURE MSG
;HERE WHEN ALL FILES ARE REJECTED

DONEFA:	MOVSI	T1,MSTFIL		;GET FILE BLOCK IN LH
	HRRI	T1,FILSPC(NDX)		;DATA BLOCK IN RH
	MOVEI	T2,FILSPC+.RBEXT(NDX)	;LAST ADDR TO FILL
	BLT	T1,(T2)			;TRANSFER
	SETZM	FILMSK(NDX)		;NO MASK TO TYPE
	SETZM	EXTMSK(NDX)		; ..
	MOVEI	T1,[ASCIZ/? Non-existent  /]
	JRST	DONE1+1			;GIVE MESSAGE
DONE0:	SKIPA	T1,[[ASCIZ/? No such path  /]]
DONE1:	MOVEI	T1,[ASCIZ/? All files rejected  /]
	PUSHJ	P,LINOUT##		;SAD MESSAGE
	MOVE	T1,DEVSPC+1(NDX)	;GET DEVICE
	PUSHJ	P,WRDOUT##		;TYPE IT
	MOVEI	T1,":"			;COLON
	PUSHJ	P,CHROUT##		;TYPE IT
	MOVE	T1,FILSPC+.RBPPN(NDX)	;GET PPN FOR FILE
	CAMN	T1,MFDPPN		;IS IT 1,,1
	  JRST	DONE4			;YES, SPECIAL FORMAT
	MOVE	T2,FILSPC+.RBNAM(NDX)	;GET FILE NAME
	MOVE	T4,FILMSK(NDX)		;AND MASK
	PUSHJ	P,WLDOUT		;TYPE WILD PROPERLY
	MOVEI	T1,"."			;DOT
	PUSHJ	P,CHROUT##		;TYPE IT
	HLLZ	T2,FILSPC+.RBEXT(NDX)	;SAME FOR EXTENSION
	HLLZ	T4,EXTMSK(NDX)		; ..
	HLRO	T3,T4			;SEE IF EXT COMPLETELY WILD
	AOJN	T3,.+2			;IF IT WAS -1
	  SETO	T4,			;THEN WE HAD FULL WILD EXT
	PUSHJ	P,WLDOUT		;TYPE EXT
	MOVE	T1,PTHSPC+2(NDX)	;GET PPN
	PUSHJ	P,WLDPPN		;START TO TYPE IT
	HRLI	NDX,-5			;MAKE INDEX AN IOWD
DONE2:	MOVE	T2,PTHSPC+3(NDX)	;GET SFD
	MOVE	T4,PTHMSK(NDX)		;AND MASK
	JUMPN	T2,.+2			;IF MORE, CONTINUE
	JUMPE	T4,DONE3		;EXIT IF NO MORE SFD'S
	MOVEI	T1,","			;TYPE COMMA
	PUSHJ	P,CHROUT##		; ..
	PUSHJ	P,WLDOUT		;TYPE SFD
	AOBJN	NDX,DONE2		;LOOP
DONE3:	PJSP	T1,LINOUT##		;FINISH
	  ASCIZ/]
/
DONE4:	MOVE	T1,FILSPC+.RBNAM(NDX)	;GET UFD NAME
	PUSHJ	P,WLDPPN		;TYPE IT
	PJSP	T1,LINOUT##		;FINISH
	  ASCIZ/].UFD
/
;OUTPUT SUBROUTINES

;HERE TO START TYPE OUT OF PPN.  GIVE PPN IN T1, 0 HALF INDICATES WILD.

WLDPPN:	PUSHJ	P,STROUT##		;START WITH BRACKET
	  ASCIZ/[/
	HRLM	T1,(P)			;SAVE PROGRAMMER NO.
	HLRZS	T1			;GET PROJECT NO.
	JUMPN	T1,WLDP1		;JUMP IF NOT WILD
	PUSHJ	P,TYPSTR		;TYPE A STAR
	JRST	WLDP2			;SKIP

WLDP1:
IFN CITPPN,<	PUSHJ	P,DECOUT##	;DECIMAL OUTPUT>
IFE CITPPN,<	PUSHJ	P,OCTOUT##	;OCTAL PROGRAMMER NUMBER>
WLDP2:	MOVEI	T1,","			;COMMA
	PUSHJ	P,CHROUT##		;TYPE IT
	HLRZ	T1,(P)			;RESTORE PROGRAMMER NO.
IFN CITPPN,<	JUMPN	T1,R64OUT##	;TYPE IT CALTECH STYLE>
IFE CITPPN,<	JUMPN	T1,OCTOUT##	;DREARY OCTAL PPN'S>

TYPSTR:	PJSP	T1,LINOUT##		;IF WILD, STAR AND RETURN
	  ASCIZ/*/


;HERE TO TYPE WILD WORD.  GIVE SIXBIT IN T2, MASK IN T4

WLDOUT:	AOJE	T4,TYPSTR		;GO IF FULL WILD CARD
	SOJA	T4,WLDOT2		;NOT FULL, ENTER LOOP
WLDOT1:	SETZB	T1,T3			;CLEAR INTERMEDIATE AC'S
	LSHC	T1,6			;GET A LETTER
	LSHC	T3,6			;AND MASK
	JUMPE	T3,.+2			;WILD CARD?
	  MOVEI	T1,'?'			;YES, USE "?"
	ADDI	T1,"0"-'0'		;MAKE ASCII
	PUSHJ	P,CHROUT##		;TYPE IT
WLDOT2:	JUMPN	T2,WLDOT1		;LOOP IF MORE
	JUMPN	T4,WLDOT1		; ..
	POPJ	P,			;DONE
;HERE IF DEVICE SPECIFIED IS NOT A DISK

NOTDSK:
IFE NDSKOK,<	;IF WE ALWAYS BLOW UP AT THIS POINT ...
	PUSHJ	P,STROUT##		;START UP
	  ASCIZ/? Device not a disk /
	MOVE	T1,DEVSPC+1(NDX)	;GET DEVICE
	PUSHJ	P,WRDOUT##		;TYPE IT
	PJRST	TCRLF##			;CRLF AND RETURN
>	;END NDSKOK
IFN NDSKOK,<	;IF WE TRY IT ANYWAY
	HRLI	T1,DEVSPC(NDX)		;OLD OPEN BLOCK IN LH OF T1
	HRRI	T1,NEWDEV		;NEW ONE IN RH
	BLT	T1,NEWDEV+1		;TRANSFER MODE AND DEVICE
	MOVE	T1,DEVSPC+1(NDX)	;GET SPECIFIED DEVICE
	MOVEM	T1,NEWDEV+1		;SAVE IN OPEN BLOCK
	SKIPN	T2,FILSPC+.RBNAM(NDX)	;FILE NAME GIVEN?
	  MOVE	T2,T1			;NO, USE DEVICE NAME
	MOVEM	T2,NEWFIL+.RBNAM	;SAVE IN ENTER BLOCK
	MOVEI	T1,CHN			;GET CHANNEL NUMBER
	DEVCHR	T1,			;GET DEVICE CHARACTERISTICS
	TLNN	T1,(DV.TTY)		;CATCH NUL DEVICE
	TLNN	T1,(DV.DTA)		;DON'T TAKE DECTAPE
	  JRST	[PUSHJ	P,CALLER	;CALL USER
		 RELEAS	CHN,		;GIVE UP CHANNEL
		 POPJ	P,]		;AND RETURN
	PJSP	T1,LINOUT##		;NO CODE HERE FOR DTA'S
	  ASCIZ/? I don't know about dectapes!
/
REPEAT 0,<	;THKIS ROUTINES PROVES UNNCECESSARY
;HERE TO CHECK FOR ONLY ONE FILE WITH NO WILDCARDS

DOONE:	MOVEI	LVL,5			;SET HI LEVEL
	TRO	F,F$LOWL		;NO FARTHER DOWN TO GO
	HRLI	T1,FILSPC(NDX)		;MOVE LOOKUP BLOCK INTO NEWFIL
	HRRI	T1,NEWFIL		; ..
	BLT	T1,NEWFIL+.RBEXT
	HRLI	T1,PTHSPC(NDX)		;SAME FOR PATH
	HRRI	T1,NEWPTH		; ..
	HRRZM	T1,NEWFIL+.RBPPN	;POINTER TO PATH BLOCK
	BLT	T1,NEWPTH+7		; ..
	PUSHJ	P,FNDONE		;FIND FILE
	  POPJ	P,			;NONE
;	PJRST	CALLER			;GOT IT -- CALL USER AND RETURN
>	;END REPEAT 0



;HERE TO CALL USER WITH FILE SPEC'S

CALLER:	TRO	F,F$FILF		;FLAG SUCCESS!
	MOVEI	T1,NEWPTH		;POINTER TO PATH LIST
	MOVEM	T1,NEWFIL+.RBPPN	;SAVE AS PPN
	PUSH	P,F			;SAVE AC'S
	PUSH	P,NDX
	PUSH	P,LVL
	PUSH	P,LNDX
	PUSH	P,PTR
	MOVEI	T1,.RBEXT		;SET UP DEFAULT LOOKUP BLOCK
	MOVEM	T1,NEWFIL		; ..
	HLRZ	T1,NDX			;GET ADDR OF USER ROUTINE
	PUSHJ	P,(T1)			;CALL IT
	  JFCL				;IN CASE USER ROUTINE SKIPS
	POP	P,PTR			;RESTORE AC'S
	POP	P,LNDX
	POP	P,LVL
	POP	P,NDX
	POP	P,F
	POPJ	P,			;AND RETURN
;HERE IS THE MAIN RECURSIVE ROUTINE
;AC NDX KEEPS COUNT OF THE LEVEL OF DESCENT WE HAVE REACHED.


DOWILD:	AOJ	LVL,			;INCREMENT LEVEL OF NESTING
	AOJ	LNDX,			;AND SPECIAL INDEX
	PUSH	P,.JBFF			;SAVE .JBFF
	SKIPE	PPNMSK(LNDX)		;ARE THERE MASKS AT THIS LEVEL?
	  JRST	WLDPTH			;YES, WE NEED WILD CARD LOOKUPS
	CAIG	LVL,5			;REACHED MAX LEVEL OF NESTING?
	SKIPN	T1,PTHSPC+2(LNDX)	;OR IS THIS LEVEL NULL?
	  JRST	GETFIL			;ONE IS TRUE, NEED FINAL FILE
	MOVEM	T1,MAKPTH(LVL)		;SAVE THIS LEVEL OF PATH
	PUSHJ	P,DOWILD		;AND BE RECURSIVE
	JRST	DONLVL			;DONE


;HERE WHEN WE HAVE REACHED THE BOTTOM LEVEL OF NESTING.  WE NOW WANT
;FILES RATHER THAN MORE DIRECTORIES

GETFIL:	TRO	F,F$LOWL		;FLAG LOWEST LEVEL
	SKIPN	FILMSK(NDX)		;SEE IF ANY MASK FOR FILE
	SKIPE	EXTMSK(NDX)		;OR EXTENSION
	  JRST	WLDPTH			;YES, SKIP INDIVIDUAL LOOKUP
	SKIPE	ALLWLD			;DIRECTORY SEARCH BEING FORCED?
	  JRST	WLDPTH			;YES, GO DO IT
	HRLI	T1,FILSPC+.RBNAM(NDX)	;ADDR OF NAME IN LH
	HRRI	T1,NEWFIL+.RBNAM	;WHERE WE WANT TO MOVE IT
	BLT	T1,NEWFIL+.RBEXT	;TRANSFER NAME AND EXT
	MOVE	T1,[MAKPTH,,NEWPTH+2]	;MOVE PATH TO PATH BLOCK
	BLT	T1,NEWPTH+7		; ..
	MOVEI	T1,NEWPTH		;NOW SET UP POINTER
	MOVEM	T1,NEWFIL+.RBPPN	; ..
	MOVEI	T1,1			;NO SCANNING
	MOVEM	T1,NEWPTH+1		; ..
	PUSHJ	P,FNDONE		;TRY TO FIND IT
	  JRST	FAIL			;CAN'T
	PUSHJ	P,CALLER		;GOT IT -- CALL USER
	JRST	DONLVL			;AND QUIT
WLDPTH:	MOVSI	T1,'UFD'		;ASSUME EXT. OF 'UFD'
	CAIL	LVL,2			;UNLESS LOWER NESTING LEVEL
	  MOVSI	T1,'SFD'		;THEN USE SFD'S
	MOVEM	T1,NEWFIL+.RBEXT	;USE AS EXT
	MOVE	T1,MAKPTH-1(LVL)	;GET LAST SAVED DIRECTORY
	MOVEM	T1,NEWFIL+.RBNAM	;WANT TO LOOK THIS UP
	CAIGE	LVL,2			;SKIP IF USING AN SFD
	  SKIPA	T1,MFDPPN		;GET 1,,1 IN T1
	  MOVEI	T1,NEWPTH		;PUT PATH PTR IN T1
	MOVEM	T1,NEWFIL+.RBPPN	;SAVE AS PPN
	MOVE	T1,[MAKPTH,,NEWPTH+2]	;TO TRANSFER PATH ...
	CAIL	LVL,2			;ONLY IF USING AN SFD
	  BLT	T1,NEWPTH(LVL)		;WHERE TO FIND LAST DIRECTORY
	SETZM	NEWPTH+1(LVL)		;MAKE SURE PATH LIST ENDS
	PUSHJ	P,FNDFIL		;GO FIND IT
	  JRST	DONLVL			;CAN'T, QUIT
	TRNE	F,F$LOWL		;IF AT LOWEST LEVEL
	  TRO	F,F$WLOW		;FLAG SUCCESFUL DIRECTORY LKP
	SKIPN	T1,NEWFIL+.RBSIZ	;GET SIZE IN WORDS
	  JRST	DONLVL			;NONE, QUIT
	MOVN	T2,T1			;NEG. COUNT IN T2
	HRL	T2,T2			;PUT NEG. IN LH OF T2
	HRR	T2,.JBFF		;FIRST FREE ADDR IN RH OF IOWD
	SOS	PTR,T2			;SUBTRACT 1 FROM IOWD
	SUB	PTR,[1,,0]		;FIX COUNT OF POINTER
	ADDB	T1,.JBFF		;INCREASE .JBFF APPROPRIATELY
	CAMLE	T1,.JBREL		;IF WE NEED IT
	  CORE	T1,			;THEN GET MORE CORE
	  JFCL
	SETZ	T3,			;ZERO SECOND IOWD
	IN	CHN,T2			;READ IN DIRECTORY
	  JRST	SRCDIR			;GOT IT -- GO SEARCH

	PUSHJ	P,STROUT##		;REPORT ERROR
	  ASCIZ/% Input error; status = /
	GETSTS	CHN,T1			;GET STATUS
	SETSTS	CHN,.IODMP		;CORRECT STATUS
	PUSHJ	P,OCTOUT##		;TYPE IT
	PUSHJ	P,STROUT##		;MORE
	  ASCIZ/ from /
	MOVE	T1,[NEWDEV,,NEWFIL]	;DEV BLOCK, LOOKUP BLOCK
	PUSHJ	P,TYPSPC##		;TYPE IT
	JRST	DONLVL			;AND QUIT AT THIS LEVEL
;HERE TO SEARCH DIRECTORY THAT HAS BEEN READ IN

SRCDIR:	TRNN	F,F$LOWL		;IF NOT ON LOWEST LEVEL
	CAMG	LVL,SRCTRY		;AND THIS LEVEL NOT RECORDED
	  SKIPA				;NOT THE CASE
	  MOVEM	LVL,SRCTRY		;THEN RECORD IT
	PUSH	P,PTR			;SAVE DIRECTORY POINTER
	JUMPE	LVL,SRCD0		;WILD MFD SEARCH -- NEVER CALL USER
	TRNN	F,F$BACK		;IF GOING BACKWARDS, DON'T CHECK FILE FIRST
	TRNN	F,F$LOWL!F$SCAN		;ANY REASON TO LOOK FOR SPECIFIC FILE?
	  SKIPA				;NOT YET, SKIP
	  PUSHJ	P,SRCDX			;YES, DO FILE SEARCH
	MOVE	PTR,(P)			;RESTORE PTR
SRCD0:	TRNN	F,F$LOWL		;IF NOT AT LOWEST LEVEL
	  PUSHJ	P,SRCDY			;THEN LOOK FOR GOOD DIRECTORY
	JUMPE	LVL,SRCD1		;DON'T CHECK FILE IF SEARCHING MFD
	TRNN	F,F$BACK		;IF FUNNY BACKWARDS SEARCH
	  JRST	SRCD1			;NOT, DONE
	MOVE	PTR,(P)			;RESTORE POINTER AGAIN
	TRNN	F,F$LOWL		;SKIP IF WE WANT TO LOOK FOR FILE
	TRNE	F,F$SCAN		;DON'T SKIP IF WE WANT TO LOOK
	  PUSHJ	P,SRCDX			;DO FILE SEARCH
SRCD1:	POP	P,PTR			;JUNK OFF STACK
	JRST	DONLVL			;DONE WITH THIS LEVEL
;CALLED BY SRCDIR TO FIND MATCHING FILE OR DIRECTORY SPEC'S

SRCDX:	TRO	F,F$WLOW		;FLAG THAT WE SEARCHED FOR FILE
	AOBJP	PTR,CPOPJ		;GO IF DONE
	AOBJP	PTR,CPOPJ		;FILE AND EXT NEED TWO INCREMENTS
	SKIPN	T1,-1(PTR)		;GOT FILE NAME?
	  JRST	SRCDX			;IGNORE NULL NAME
	HLLZ	T2,(PTR)		;GET EXTENSION
	TDZ	T1,FILMSK(NDX)		;CLEAR MASKED BITS
	TDZ	T2,EXTMSK(NDX)		; ..
	CAMN	T1,FILSPC+.RBNAM(NDX)	;CHECK FOR MATCH
	CAME	T2,FILSPC+.RBEXT(NDX)	; ..
	  JRST	SRCDX			;NO, TRY NEXT
	MOVE	T1,-1(PTR)		;RESTORE NAME
	MOVEM	T1,NEWFIL+.RBNAM	;AND SAVE
	HLLZ	T1,(PTR)		;AND EXT
	MOVEM	T1,NEWFIL+.RBEXT	;SAVE
	MOVE	T1,[MAKPTH,,NEWPTH+2]	;SET UP
	BLT	T1,NEWPTH+7		;COPY NEW PATH
	PUSHJ	P,CALLER		;CALL USER WITH FILE
	JRST	SRCDX			;AND GET NEXT

SRCDY:	AOBJP	PTR,CPOPJ		;GO IF DONE
	AOBJP	PTR,CPOPJ		; ..
	SKIPN	T1,-1(PTR)		;NAME?
	  JRST	SRCDY			;NO
	TDZ	T1,PPNMSK(LNDX)		;ZAP WITH DIRECTORY MASK
	CAME	T1,PTHSPC+2(LNDX)	;LOOKING FOR IT?
	  JRST	SRCDY			;NO
	HLRZ	T1,(PTR)		;GET EXTENSION
	CAIE	T1,'SFD'		;IF AN SFD
	  JUMPN	LVL,SRCDY		;OR IF SEARCHING MFD
	MOVE	T1,-1(PTR)		;THEN THIS IS A MATCH
	MOVEM	T1,MAKPTH(LVL)		;SO RESTORE NAME
	CAMLE	LVL,SRCSUC		;SUCCESS THIS DEEP YET?
	  MOVEM	LVL,SRCSUC		;NO, NOTE IT
	PUSH	P,PTR			;SAVE PTR
	PUSHJ	P,DOWILD		;GO DEEPER
	POP	P,PTR			;RESTORE PTR
	SETZM	MAKPTH(LVL)		;REMOVE THAT PART OF PATH NOW
	JRST	SRCDY			;LOOP
;HERE TO LOOKUP FILE SPECIFIED IN NEWFIL
FNDFIL:	MOVSI	T1,1			;NO SCANNING
	MOVSM	T1,NEWPTH+1		;SET IN PATH BLOCK
	TROA	T1,.RBSIZ		;USE LONG LOOKUP
FNDONE:	 MOVEI	T1,.RBEXT		;IN WHICH CASE USE SHORT
	HRRZM	T1,NEWFIL		;LOOKUP
	LOOKUP	CHN,NEWFIL		;FIND IT
	  JRST	FNDF1			;CAN'T!
	CAIGE	LVL,2			;IF GRABBING A UFD
	  JRST	CPOPJ1			;THEN DON'T BOTHER TO CONFIRM IT
FOUND:	IFE <CHN>,<
	SETZM	NEWPTH			;PLACE CHANNEL IN NEWPTH>
	IFN <CHN>,<
	MOVEI	T1,CHN
	MOVEM	T1,NEWPTH>
	MOVE	T1,[10,,NEWPTH]		;POINTER FOR PATH.
	PATH.	T1,			;SEE WHAT WE FOUND
	  HALT	.
	MOVE	T1,NEWPTH+2		;GET RETURNED PPN
	TRNE	F,F$WILD		;IF NO WILD CARDS
	CAMN	T1,MAKPTH		;OR FILE FOUND WHERE EXPECTED
CPOPJ1:	 AOS	(P)			;THEN SKIP RETURN
CPOPJ:	POPJ	P,			;RETURN

FNDF1:	HRRZ	T1,NEWFIL+.RBEXT	;GET ERROR CODE
	CAIE	T1,ERPRT%		;IF PROTECTION FAILURE
	  JRST	FNDF1A			;NOT THE CASE, SKIP ON
	JUMPE	LVL,.+3			;UNLESS SEARCHING FOR MFD
	SKIPN	PPNMSK-1(LNDX)		;OR USING WILD UFD
	  TRO	F,F$FILF		;FLAG LIMITED SUCCESS
	MOVE	T2,NEWFIL		;GET LOOKUP TYPE
	CAIN	T2,.RBEXT		;IF ALSO SHORT LOOKUP
	  JRST	FOUND			;THEN SAY WE FOUND IT!
FNDF1A:	JUMPE	T1,FNDF2		;NOT FOUND IS OK
	CAIE	T1,ERIPP%		;IF NO SUCH UFD
	CAIN	T1,ERSNF%		;OR NO SUCH SFD
	  JRST	FNDF2			;THEN WAIT TO REPORT ERROR
	MOVE	T1,[NEWDEV,,NEWFIL]	;WE HAVE SERIOUS ERROR NOW
	PJRST	LOOKFA##		;SO REPORT IT
FNDF2:	CAMGE	LVL,MSTWRD		;LEVEL OF NESTING DEEPER HERE?
	  POPJ	P,			;NO, IGNORE THIS ERROR
	JUMPE	T1,FNDF3		;IF NOT FOUND, REMEMBER IT
	HRRZ	T2,MSTFIL+.RBEXT	;ELSE GET LAST ERROR, IF ANY
	SKIPL	MSTWRD			;SKIP IF MSTWRD NOT USED YET
	  JUMPE	T2,CPOPJ		;OLD ERROR 0 IS BEST
	CAIG	T1,(T2)			;ONLY RECORD IF (T1)=23,(T2)=1
	  POPJ	P,			;NOT THE CASE, RETURN
FNDF3:	MOVEM	LVL,MSTWRD		;SAVE NEW LEVEL
	MOVE	T1,[NEWFIL,,MSTFIL]	;BLT PTR
	BLT	T1,MSTFIL+3		;SAVE BAD LOOKUP
	MOVE	T1,[NEWPTH,,MSTPTH]	;AND BAD PATH
	BLT	T1,MSTPTH+7		; ..
	POPJ	P,			;RETURN
;HERE WHEN DONE AT THIS LEVEL

FAIL:	HRRZ	T1,NEWFIL+.RBEXT	;GET ERROR CODE
	JUMPN	T1,DONLVL		;IF NOT FNF, SKIP
	  TRO	F,F$WLOW		;ELSE FLAG LOW LEVEL LOOKUP
DONLVL:	TRZ	F,F$LOWL		;NO LONGER AT LOWEST LEVEL
	SETZM	MAKPTH(LVL)		;ZERO DIRECTORY AT THIS LEVEL
	SOJ	LNDX,			;DECREMENT DESCENT INDEX
	POP	P,T1			;RESTORE .JBFF
	SKIPN	KEPCOR			;GIVE UP CORE?
	CAMN	T1,.JBFF		;IS THERE ANY CORE TO GIVE UP?
	  SOJA	LVL,CPOPJ		;NO, DECREMENT AND RETURN
	MOVEM	T1,.JBFF		;YES, RESTORE OLD .JBFF
	SOJ	T1,			;ONE LESS IS ALL WE NEED
	MOVEI	T2,2000(T1)		;ADD 1K
	CAMG	T2,.JBREL		;SKIP IF THIS WILL NOT GIVE UP
	CORE	T1,			;ELSE GIVE UP CORE
	  JFCL
	SOJA	LVL,CPOPJ		;DECREMENT AND RETURN




;HERE WHEN DONE TO RESTORE AC'S

RSTACS:	MOVE	0,[SAVAC,,2]		;GET BLOCK OF AC'S
	BLT	0,11			;BLIIITTTT!
	MOVE	0,SAV0			;RESTORE AC 0
	POPJ	P,			;RETURN


	END