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