.MCALL .MODULE .MODULE SRCWCD,VERSION=09,COMMENT=,IDENT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only 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 except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL EDIT HISTORY ;+ ; 001 09-Jul-87 RHH Fix wildcard-on-magtape crashes ; ; 007 04-Aug-89 RHH Fix wildcard failure when multiple ; percent signs are issued on both ; input filespecs ; ; 008 07-Jan-91 WFG Fix wildcard failure with FILNAMs ; of different length in MAT2: ; ; (009) 11-Aug-91 MBG Extended magtape error checking ; ;- .SBTTL WILDCARD PROCESSING ;+ ; ; THIS IS THE SRCCOM WILDCARD PROCESSING MODULE. ; IT WAS TAKEN FROM BINCOM AND IS ALMOST THE SAME, BUT ; NOT QUITE. ; ; ALL SWITCHES ARE VALID WITH WILDCARDING. ; THERE CANNOT BE A SLP OUTPUT FILE. ; ; WILDCARDING IS SET UP SO THAT THE REST OF SRCCOM THINKS ; THAT THE USER TYPED IN A CSI COMMAND LINE FOR EACH ; TWO FILES BEING COMPARED. ; ; ALL THE FOLLOWING ROUTINES ARE USED BY WILDCARDING ONLY. ; ; MOST OF THEM ARE REQUIRED ONLY ONCE. ; ; THE PROCESSING SEQUENCE IS: ; ; 1. DETERMINE IF THERE IS WILDCARDING (WILCRD AND WCDCHR) ; 2. IF THERE IS, DO THE I/O FOR IT (WCDIO) ; A. DETERMINE IF THERE ARE ANY OUTPUT FILES (WCDOUT) ; B. FIND THE DEVICE TYPES (WCDDEV) ; C. FETCH THE HANDLERS (WCDFET) ; D. ALLOCATE THE BUFFERS WHICH WILL CONTAIN THE ; ASCII FILESPECS MATCHING THE WILDCARDING ; (WCDBUF). IF THERE IS WILDCARDING ON ONE INPUT ; SPEC ONLY, BUFFER WCSAV1 WILL BE USED. ; E. DO NON-FILE-STRUCTURED (NFS) LOOKUPS ON THE ; INPUT DEVICES (WCDFIL) ; F. DO DIRECTORIES ON THE INPUT DEVICES (WCDISP, WCDIR, ; MATCH, AND MATCH1). THESE DIRECTORIES FIND ALL ; FILES MATCHING THE WILDCARDING IN THE SPECS. ; VALID DEVICES ARE DISKS (DKDIR), AND MAGTAPES (MTDIR). ; CHCKSB, READMT, SPFUN, AND SPFUN1 ARE SUPPORT ; ROUTINES FOR MAGTAPES. ; G. DETERMINE WHICH FILENAMES FOUND BY THE DIRECTORY ; ROUTINES MATCH THE SRCCOM WILDCARDING (WCDMAT) ; 3. LOOKUP THE NEXT SET OF INPUT FILES (WCDLKI) ; ; ALL THE SUBROUTINES IN 1 AND 2 ARE PERFORMED ONLY ONCE. ; IF MORE THAT ONE MATCH IS FOUND, WCDINT (WILDCARD INITIALIZATION) ; REINITIALIZES SRCCOM, WCDLKI SELECTS THE NEXT MATCHING ; FILES(S) AND PERFORMS THE .LOOKUP(S) FOR THEM, AND WCDPUT ; RESETS DEFAULTS. ; ; WCDINT, WCDLKI, AND WCDPUT ARE CALLED FROM 30$ AND 40$ UNDER RETRY. ; ; NOTES: ; 1. RTOA, GETNAM, GETNUM, .SAVRG, CONR50, MOVR50, ; AND MOVASC ARE SUPPORT ROUTINES FOR WILDCARDING. ; 2. BOTSPC IS A MACRO USED TO TEST IF THERE IS WILDCARDING ; ON BOTH INPUT SPECS ; ; WCDINT, WCDIO, WCDFET, AND WCDLKI ARE DIFFERENT IN SRCCOM AND BINCOM. ; WCDLKO IS NOT USED IN SRCCOM. ; SOME VARIABLE NAMES ARE DIFFERENT: ; ; SRCCOM BINCOM USE ; IN1 INFILE INPUT FILE 1 ; IN2 INFILE+10 INPUT FILE 2 ; OUTSP OUTFIL LIST FILE ; ; THE ERROR MESSAGES ERD, ILD, DNA, AND ISM ARE USED IN BOTH ; SRCCOM AND BINCOM. ; ; WMATCH IN SRCCOM AND MATCH IN BINCOM ARE THE SAME ROUTINES. ;- .SBTTL .MCALL AND MACROS .ENABL GBL .MCALL .CLOSE .DATE .DSTATU .ENTER .FETCH .GTIM .MCALL .LOOKUP .PRINT .RCTRLO .READW .SETTOP SOB .MCALL .SPFUN .LIBRARY "SRC:SYSTEM.MLB" .MCALL .ERMDF ;Magtape error codes .MCALL .SFMDF ;Magtape special function codes .ERMDF .SFMDF ;+ ; BOTSPC WILL DETERMINE IF THERE IS WILDCARDING ON BOTH SPECS ; IF THERE IS, THE PROGRAM WILL TAKE AN EQ BRANCH ;- .MACRO BOTSPC MOV WC.FLG,-(SP) ;PUT WILDCARD FLAG ON STACK BIC #^C,@SP ;CLEAR ALL EXCEPT BITS 2,3 CMP #WC.BOT,(SP)+ ;ARE BOTH SET? .ENDM BOTSPC ;+ ; .SAVRG SETS UP TO USE ULBLIB ROUTINE $SAVRG ; IT IS USED BY MATCH2 ;- .MACRO .SAVRG .DSABL CRF .GLOBL $SAVRG .ENABL CRF JSR R5,$SAVRG .ENDM .SAVRG .SBTTL WILDCARD VARIABLES AND CONSTANTS .PSECT IMPURE,D,RW .EVEN WC.FLG::.WORD 0 ;WILDCARD FLAG ; VALUES FOR WC.FLG WC.ENB == 000001 ;WILDCARDING SPECIFIED WC.1FL == 000002 ;WILDCARDING ON INPUT SPEC 1 WC.2FL == 000004 ;WILDCARDING ON INPUT SPEC 2 WC.BOT == WC.1FL+WC.2FL ;WILDCARDING ON BOTH SPECS WC.NXT == 000100 ;WILDCARDING NOT-FIRST-LOOP WCSAV1::.WORD 0 ;ADDRESS OF WCD BUFFER 1 WC1PTR::.WORD 0 ;PTR TO CURRENT LOCATION IN WCSAV1 WCEND:: .WORD 0 ;1ST FREE BYTE AFTER WCSAV1 WCSAV2::.WORD 0 ;ADDRESS OF WCD BUFFER 2 WC2PTR::.WORD 0 ;PTR TO CURRENT LOCATION IN WCSAV2 WDEV1:: .WORD 0 ;WILDCARD DEV 1 TYPE WDEV2:: .WORD 0 ;WILDCARD DEV 2 TYPE DEVIN:: .WORD 0 ;Flag to indicate device type (wildcarding) DEVMT == 000001 ;Flag to indicate magtape input LIM:: .WORD 0 ;NEW HIGH LIMIT LSTFIL::.WORD 0 ;FLAG TO INDICATE OUTPUT FILE SPECIFIED MATFND::.WORD 0 ;FLAG TO INDICATE IF A MATCH WAS FOUND ONEMAT == 000001 ;AT LEAST ONE MATCH WAS FOUND (WC ON 2 SPECS) MATPAS == 000002 ;MATCH FOUND THIS PASS (WC ON 2 SPECS) MAT == ONEMAT+MATPAS ;BOTH OF THE ABOVE FLAGS STR1A:: .BLKW 4 ;FILENAME 1 SAVE AREA (WC ON 2 SPECS) STR1B:: .BLKW 4 ;FILE TYPE 1 SAVE AREA STR2A:: .BLKW 4 ;FILENAME 2 SAVE AREA STR2B:: .BLKW 4 ;FILETYPE 2 SAVE AREA SAVR1:: .WORD 0 ;SAVE AREA FOR R1 SAVR5:: .WORD 0 ;SAVE AREA FOR R5 SAVPTR::.WORD 0 ;SAVE AREA FOR FILENAME START SAVPT2::.WORD 0 ;SAVE AREA FOR WCSAV2 START BUFST1::.WORD 0 ;FILE 1 EMT BUFFER START BUFST2::.WORD 0 ;FILE 2 EMT BUFFER START CHARS:: .BLKW 6 ;AREA FOR ASCII OF FILENAME ENBSAV::.WORD 0 ;SAVE END BLOCK FOR /E FIXSPC::.WORD 0 ;ASCII OF INPUT SPEC 1 OR 2 LASTFR::.WORD 0 ;HIGHEST FREE WORD IN1ASC::.BLKW 6 ;ASCII OF INFILE1 IN2ASC::.BLKW 6 ;ASCII OF INFILE2 MATTMP::.BLKW 6 ;TEMP SAVE AREA FOR FILENAME 2 OBUFPT::.WORD 0 ;LIST FILE BUFFER POINTER SAVR50::.BLKW 3 ;STORAGE AREA FOR RAD50 FILENAME STBSAV::.WORD 0 ;SAVE START BLOCK FOR /S TTNAM: .RAD50 \TT \ ;DEFAULT DEVICE FOR OUTPUT $ERRBY =: 52 ;EMT error byte FILLEN == 13 ;LENGTH OF ASCII FILENAME RETURNED BY RTOA SEQDEV == 100000 ;.DSTATUS status word. 0 => sequential device NRTDIR == 10000 ;.DSTATUS status word. 1 => non RT-11 ; directory structured device (MT) MMIDEN == 11 ;.DSTATUS MM identification number MTIDEN == 20 ;.DSTATUS MT identification number MSIDEN == 35 ;.DSTATUS MS identification number MUIDEN == 60 ;.DSTATUS MU identification number DEFTYP::.WORD 0 ;Default listing type for file sizes DEVSEQ::.WORD 0 ;Flag to indicate sequential output device ASTERK == 52 ;ASCII '*' PRCENT == 45 ;ASCII '%' BLANK == 40 ;ASCII ' ' COMMA == 54 ;ASCII ',' EQUALS == 75 ;ASCII '=' DOT == 56 ;ASCII '.' ASCB:: .ASCII / / ;ASCII BLANKS ICHAN:: .WORD 0 ;INPUT FILE CHANNEL NUMBER MABBAD::.WORD 0 ;Flag to indicate maybe-bad-block ; DISK CONSTANTS DH.AVL == 0 ;Number of available directory segments DH.NXT == 2 ;Pointer to next directory segment DH.HI == 4 ;Highest directory segment open DH.EXB == 6 ;Number of extra bytes in directory entries DH.STB == 10 ;Starting block number for files in segment DH.SIZ == 12 ;Size of directory header words HOMBLK == 1 ;Disk home block DK.VID == 730 ;Offset to volume id DK.VLN == 14 ;Length of volume id DK.OWN == 744 ;Offset to owner name DK.OLN == 14 ;Length of owner name DK.VAL == 726 ;Offset to volume validation pattern ; Disk directory entry offsets and symbolics DE.ST == 0 ;Entry status DS.TNT == 400 ; 1 => tentative entry DS.EMP == 1000 ; 1 => empty entry DS.PRM == 2000 ; 1 => permanent entry DS.EOS == 4000 ; 1 => end-of-segment entry DE.FN1 == 2 ;Offset to first word of filename DE.FN2 == 4 ;Offset to second word of filename DE.TYP == 6 ;Offset to filetype DE.LEN == 10 ;Offset to filesize DE.DAT == 14 ;Offset to file creation date DE.SIZ == 16 ;Size of directory entry ;MAGTAPE CONSTANTS MT.SEQ = 31. ;Offset to file sequence number MT.FSZ = 54. ;Offset to file size (records) MT.FID = 4 ;Offset to filename ; Magtape directory offsets and symbolics MT.VOL == "VO ;VOL label identification MT.VID == 4 ;Offset to magtape volume id MT.VLN == 6 ;Length of magtape volume id MT.OWN == 37. ;Offset to magtape owner name MT.VP1 == 'D ;First part of owner validation pattern MT.VP2 == "%B ;Second part. MT.OLN == 12 ;Length of magtape owner name MT.HDR == "HD ;HDR label identification MT.HFI == 4 ;Offset to file identifier MT.HDT == 41. ;Offset to file creation date MT.EOF == "EO ;EOF label identification LABSIZ == 400 ;Size of RT-11 labels in words INBFSZ == 2000 ;Size of input buffer in bytes R50V3A == ^RV3A ;RAD50 'V3A' AVAIL:: .WORD 0 ;Number of available directory segments EOSFLG::.WORD 0 ;Flag to indicate end-of-segment encountered HISEG:: .WORD 0 ;Highest directory segment in use NXTDSG::.WORD 0 ;Next directory segment to read NXTFIL::.WORD 0 ;Pointer to next directory entry RBLK:: .WORD 0 ;Physical block to read SBLOCK::.WORD 0 ;Starting block number of current file XTRABY::.WORD 0 ;Number of extra bytes in directory entry MBUF:: .WORD 0 ;Magtape input buffer address MVAL:: .WORD 0 ;Flag for which magtape buffer to use DBUF:: .BLKW 1000 ;Disk Input buffer IBUF:: .BLKW 1000 ;Magtape Input buffer LKBLK:: .BLKW 4 ;Used in .LOOKUP's and magtape .SPFUN's .SBTTL WILCRD - DETERMINE IS THERE IS WILDCARDING ;+ ; WILCRD ; ; INPUTS: ; INFILE = RAD50 INPUT FILE 1 ; INFILE+10 = RAD50 INPUT FILE 2 ; OUTPUTS: ; WC.FLG <> 0 WHEN THERE IS WILDCARDING ; FL.WCD IN $FLAGS IS USED FOR THE LAST LOOP THROUGH ; NON-WC SRCCOM SO THAT IT ENDS CORRECTLY ;- .PSECT SRCCOM,I,RO WILCRD:: MOV #INFILE,R0 ;POINT TO FIRST INPUT SPEC CALL WCDCHR ;FIND IF THERE ARE WILDCARDS TST R2 ;WILDCARDS? BEQ 10$ ;NO, BRANCH BIS #WC.1FL,WC.FLG ;YES, WC ON INPUT SPEC 1 10$: MOV #IN1ASC,R3 ;SAVE AREA FOR ASCII FILENAME CALL MOVASC ;SAVE INPUT FILENAME 1 MOV #,R0 ;POINT TO SECOND INPUT SPEC CALL WCDCHR ;TEST FOR WILDCARDING TST R2 ;WILDCARDING ON SPEC 2? BEQ 20$ ;NO, BRANCH BIS #WC.2FL,WC.FLG ;YES, WC ON SPEC 2 20$: TST WC.FLG ;ANY WILDCARDING? BEQ 100$ ;IF NO, BRANCH MOV #IN2ASC,R3 ;SAVE AREA FOR ASCII FILENAME CALL MOVASC ;SAVE ASCII FILENAME OF SPEC 2 BIS #WC.ENB,WC.FLG ;TURN WC ON BIS #FL.WCD,$FLAGS ;TURN LAST TIME THRU WC ON 100$: RETURN ; ; WCDCHR WILL TEST IF THE INPUT FILE SPECS ; CONTAIN THE WILDCARDING CHARACTERS '*' OR '%' ; ; INPUTS: R0 -> START OF RAD50 INPUT FILE SPEC ; OUTPUTS: R2 <> 0 WHEN A WILDCARDING CHAR IS FOUND ; WCDCHR: CLR R2 ;ASSUME FAILURE ADD #2.,R0 ;POINT TO INPUT FILENAME MOV #CHARS,R1 ;STORAGE AREA FOR ASCII OF FILENAME CALL RTOA ;CONVERT RAD50 TO ASCII MOV #FILLEN,R4 ;# OF CHARS IN RETURN SPEC MOV #CHARS,R1 ;GET START OF ASCII 10$: MOVB (R1)+,R3 ;GET ASCII CHAR IN R3 CMPB #ASTERK,R3 ;IS IT AN '*'? BEQ 20$ ;IF YES, BRANCH CMPB #PRCENT,R3 ;IS IT A '%'? BEQ 20$ ;IF YES, BRANCH SOB R4,10$ ;CONTINUE UNTIL END OF FILENAME BR 100$ 20$: INC R2 ;TURN WILDCARDING ON 100$: RETURN ;RETURN .SBTTL WCDINT - WILDCARD INITIALIZATION ;+ ; WCDINT ; ; WILDCARDING USES THIS INITIALIZATION ROUTINE FOR THE ; SECOND AND SUBSEQUENT WILDCARDING COMPARES ;- WCDINT:: MOV #<$SDB1+S.LNO>,R0 ;Get line pointer in SDB 1 MOV #6,R2 ;There are 6 pointers 10$: CLR (R0)+ ;Clear them DEC R2 BGT 10$ MOV #$INFD1,R0 ;Get FDB 1 start MOV BUFST1,F.IOBF(R0) ;Get EMT buffer start CLR F.IOBK(R0) ;Clear EMT block number CLR F.ERR(R0) ;Clear EOF from previous file MOV #<$SDB2+S.LNO>,R0 ;Get line pointer in SDB 2 MOV #6.,R2 ;There are 6 pointers 20$: CLR (R0)+ ;Clear them DEC R2 BGT 20$ MOV #$INFD2,R0 ;Get FDB 2 start MOV BUFST2,F.IOBF(R0) ;Get EMT buffer start CLR F.IOBK(R0) ;Clear EMT block number CLR F.ERR(R0) ;Clear EOF from previous file MOV #$LSTFD,R0 ;Get list file FDB start MOV OBUFPT,F.BPTR(R0) ;Get original buffer ptr TST LSTFIL ;List file wanted? BEQ 30$ ;If no, branch TST $DIFCT ;Were any differences found? BEQ 40$ ;No, don't touch block number INC F.IOBK(R0) ;Increment block number BR 40$ 30$: CLR F.IOBK(R0) ;Clear EMT block number 40$: .GTIM #IOAREA,#TIME ;Get time-of-day (and maybe cause date roll) .DATE ;Get the date MOV R0,DATE ;Save it CLR $DIFCT ;Clear differences count .RCTRLO ;Reset CTRL/O RETURN .SBTTL WCDIO - WILDCARD I/O ;+ ; WCDIO ; ; THIS ROUTINE WILL CALL THE OTHER WILDCARDING ROUTINES ; NECESSARY TO SET UP FOR SRCCOM ; ; OUTPUTS: ; SRCCOM IS READY TO COMPARE THE FIRST TWO ; MATCHING FILES ; ; NOTE: THESE SUBROUTINES MUST BE PERFORMED IN THIS ORDER ;- WCDIO:: CALL WCDOUT ;TEST IF THERE ARE ANY OUTPUT FILES MOV #INFILE,R1 ;GET DEVICE TYPE CALL WCDDEV ;FOR INPUT DEV 1 MOV DEVIN,WDEV1 ;SAVE DEV 1 STRUCTURE MOV #,R1 ;GET DEVICE TYPE CALL WCDDEV ;FOR INPUT DEV 2 MOV DEVIN,WDEV2 ;SAVE DEV 2 STRUCTURE CALL WCDFET ;FETCH HANDLERS FOR THE DEVICES CALL WCDBUF ;ALLOCATE BUFFERS CALL WCDFIL ;LOOKUP THE INPUT DEVICES CALL WCDISP ;DO DIRECTORIES ON THE DEVICES ;AND SAVE MATCHING FILESPECS CALL WCDMAT ;FIND FILES FOR COMPARISON CALL WCDLKI ;LOOKUP FIRST INPUT FILES 100$: RETURN ;END OF WILDCARD I/O .SBTTL WCDOUT - LOOK FOR OUTPUT FILE ;+ ; WCDOUT ; ; THIS ROUTINE DETERMINES IF AN OUTPUT FILE WAS SPECIFIED ; IN THE COMMAND LINE. THERE CAN ONLY BE A LIST FILE, NO ; PATCH FILE. ; ; OUTPUTS: ; LSTFIL <> 0 WHEN A PRINT FILE WAS SPECIFIED ;- WCDOUT:: CLR LSTFIL ;CLEAR OUTPUT FILE FLAG MOV #OUTFIL,R0 ;GET START OF OUTPUT SPECS TST @R0 ;IS THERE A LIST FILE? BEQ 10$ ;BRANCH IF NOT CMP @R0,TTNAM ;TT: SPECIFIED? BEQ 10$ ;IF YES, BRANCH INC LSTFIL ;SAY LIST FILE WANTED 10$: ADD #10.,R0 ;POINT TO PATCH FILE BLOCK TST @R0 ;PATCH FILE WANTED? BEQ 100$ ;IF NOT, BRANCH .ERR #ERAREA,#ILC,LEVEL=FATAL,RETURN=NO 100$: RETURN .SBTTL WCDDEV - WILDCARDING DEVICES ;+ ; WCDDEV ; ; THIS ROUTINE DETERMINES WHAT KIND OF DEVICE EACH INPUT ; FILE RESIDES ON. ; ; IT WILL BE CALLED TWICE, ONCE FOR EACH OF THE TWO INPUT FILES ; ; INPUTS: ; R1 = ADDRESS OF THE RAD50 DEVICE NAME ; OUTPUTS: ; DEVIN = 0 FOR A RANDOM ACCESS DEVICE ; DEVIN <> 0 FOR A MAGTAPE ;- WCDDEV:: .DSTATU #IOAREA,R1 ;Find out what it is BCC 20$ ;Branch if no error 10$: .ERR #ERAREA,#ILC,LEVEL=FATAL,RETURN=NO 20$: CLR DEVIN ;Clear device type flag MOV IOAREA,R3 ;Get the status and device id number BMI 100$ ;Branch if it's random access. BIT #NRTDIR,R3 ;Is it directory structured? BEQ 10$ ;Branch if not. Illegal device. 30$: CMPB #MTIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so. CMPB #MMIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so CMPB #MSIDEN,R3 ;Magtape? BEQ 40$ ;Branch if so CMPB #MUIDEN,R3 ;Magtape? BNE 100$ ;Branch if not 40$: BIS #DEVMT,DEVIN ;Remember it 100$: RETURN .SBTTL WCDFET - FETCH HANDLERS ;+ ; WCDFET ; ; ALLOCATE THE HANDLERS ABOVE THE PROGRAM HIGH LIMIT ; ; INPUTS: ; LIMITS+2 CONTAINS THE FIRST FREE WORD ; ABOVE THE PROGRAM ; OUTPUTS: ; LIM CONTAINS THE NEW HIGH LIMIT ; R0 IS DESTROYED ;- WCDFET:: MOV ,LIM ;GET LIMIT .FETCH LIM,#INFILE ;FETCH HANDLER FOR INPUT DEV 1 BCS 20$ ;IF CS, BRANCH MOV R0,LIM ;SAVE PROGRAM LIMIT .FETCH LIM,# ;FETCH SECOND DEVICE HANDLER BCS 20$ ;IF CS, BRANCH MOV R0,LIM ;SAVE PROGRAM LIMIT TST LSTFIL ;AN OUTPUT FILE WANTED? BEQ 10$ ;IF NO, BRANCH .FETCH LIM,#OUTFIL ;YES, GET HANDLER BCS 20$ ;IF CS, ERROR MOV R0,LIM ;SAVE LIMIT BR 100$ ;GO OUT 10$: .FETCH LIM,#TTNAM ;MAKE TT OUTPUT DEVICE BCC 30$ ;IF CC, BRANCH 20$: .ERR #ERAREA,#ISM,LEVEL=FATAL,RETURN=NO 30$: MOV R0,LIM ;SAVE LIMIT 100$: .SETTOP R0 ;GET NEW PROGRAM HI LIMIT RETURN .SBTTL WCDBUF - ALLOCATE WILDCARDING BUFFER 1 ;+ ; WCDBUF ; ; THIS ROUTINE PLACES WCSAV1, THE FIRST WILDCARDING BUFFER, ; ABOVE THE HANDLERS. ; WCSAV2, IF NEEDED, WILL START AFTER WCSAV1. ; WCSAV2 IS ALLOCATED IN WCDISP. ; ; INPUTS: ; LIM ; OUTPUTS: ; WCSAV1, WC1PTR POINT TO THE FIRST BYTE IN ; WILDCARDING BUFFER AREA 1 ;- WCDBUF:: MOV #LIM,R3 ;R3 -> WORD CONTAINING PROG LIMIT MOV (R3)+,R1 ;R1 -> FIRST BUFFER AREA WORD MOV R1,WCSAV1 ;SET WCD BUFFER 1 TO START OF FREE MEM MOV R1,WC1PTR ;SET BUF 1 PTR TO THE SAME PLACE RETURN ;RETURN .SBTTL WCDFIL - Do .LOOKUP's on the input devices ;+ ; WCDFIL ; This routine ; 1) .LOOKUP's the input devices ; 2) If an input device is MT, positions the tape ;- WCDFIL:: MOV #IBUF,MBUF ;Buffer address for magtapes CLR MVAL ;Clear tape 2 flag MOV INFILE,LKBLK ;Move spec 1 to LOOKUP block CLR LKBLK+2 ;for non-file structured LOOKUP MOV #ICHAN1,ICHAN ;Channel 3 for input file 1 MOV WDEV1,DEVIN CALL LOOK ;Do LOOKUP MOV ,LKBLK ;Move spec 2 to LOOKUP block CLR LKBLK+2 ;for non-file structured LOOKUP MOV #ICHAN2,ICHAN ;Channel 4 for input file 2 MOV WDEV2,DEVIN TST DEVIN ;A magtape? BEQ 10$ ;if not, branch CMP WDEV1,WDEV2 ;Two magtapes? BNE 10$ ;If no, branch MOV #DBUF,MBUF ;Yes, use disk buf for 2nd tape 10$: CALL LOOK ;Do LOOKUP RETURN LOOK: .LOOKUP #IOAREA,ICHAN,#LKBLK,#0 ;NFS LOOKUP BCC 20$ ;Branch if no error CMPB @#$ERRBY,#1 ;Device inactive? BNE 10$ ;If yes, branch .ERR #ERAREA,#INE,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 10$: .ERR #ERAREA,#DNA,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 20$: TST DEVIN ;Is the input device directory structured? BEQ 90$ ;Branch if yes 30$: ;Input a magtape JSR R5,SPFUN ;Rewind the magtape .BYTE 377,SF.MRE MOV MBUF,R1 ;Get read buffer address CALL READMT ;Read a record BCC 40$ ;Branch if no error CALL CHCKSB ;Check for a short record BEQ 40$ ;Branch if it was. We'll use it .ERR #ERAREA,#ERD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 40$: CMP @R1,#MT.VOL ;VOL1 label? BEQ 50$ ;Branch if so .ERR #ERAREA,#ILD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 50$: MOV MBUF,R3 ;Get buffer start ADD #MT.OWN,R3 ;Point to the owner name CMPB (R3)+,#MT.VP1 ;Is it a DEC written magtape? BNE 60$ ;Branch if not. CMP (R3)+,#MT.VP2 ;Written on an 11? BEQ 70$ ;Branch if so 60$: MOV SP,MABBAD ;Flag that it may be bad 70$: CALL READMT ;Position to the first HDR label BCC 80$ ;Branch if no error CALL CHCKSB ;Check for a short block read error BEQ 80$ ;No error, branch .ERR #ERAREA,#ILD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 80$: CMP @R1,#MT.HDR ;HDR1 label? BNE 70$ ;Branch if not. Try again BR 100$ 90$: .READW #IOAREA,ICHAN,#DBUF,#400,#HOMBLK ;Read the home block BCC 100$ ;Branch on no error .ERR #ERAREA,#ERD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 100$: RETURN .SBTTL WCDISP - DISPATCH TO THE DIRECTORY ROUTINES ;+ ; WCDISP ; ; THIS ROUTINE WILL SET UP AND DISPATCH TO THE ; DIRECTORY ROUTINES. ; ; IT WILL FILL UP WCSAV1 AND WCSAV2 WITH THE ASCII FILENAMES ; MATCHING THE WILDCARDING. A ZERO BYTE FLAGS THE END OF ; WCSAV1 AND WCSAV2. WCSAV2 IS USED ONLY WHEN THERE IS ; WILDCARDING ON BOTH SPECS. ; ; ON RETURN FROM WCDIR, R5 POINTS TO A DIRECTORY ENTRY ;- WCDISP:: MOV #IBUF,MBUF ;GET MAGTAPE BUFFER 1 MOV #1,NXTDSG ;INIT FOR DIR ROUTINES MOV #ICHAN1,ICHAN ;POINT TO FIRST INPUT FILE MOV WDEV1,DEVIN ;GET DEVICE TYPE MOV INFILE,LKBLK ;GET ERROR MSG, IF NEEDED BIT #WC.1FL,WC.FLG ;WILDCARDING ON INPUT FILE 1? BNE 10$ ;IF YES, BRANCH MOV #ICHAN2,ICHAN ;NO, WILDCARDING ON SPEC 2 ONLY MOV WDEV2,DEVIN ;GET DEVICE TYPE MOV ,LKBLK ;GET ERROR MSG, IF NEEDED 10$: CALL WCDIR ;GET A DIRECTORY ENTRY BCS 30$ ;IF C SET, NO MORE ENTRIES MOV #IN1ASC,R3 ;POINT TO ASCII INPUT SPEC BIT #WC.1FL,WC.FLG ;WILDCARDING ON SPEC 1? BNE 20$ ;IF YES, BRANCH MOV #IN2ASC,R3 ;POINT TO ASCII OF SPEC 2 20$: CALL MATCH1 ;FIND MATCH, IF ANY TST R0 ;ANY MATCHES? BEQ 10$ ;BRANCH IF NONE MOV WC1PTR,R3 ;POINT TO START OF BUF 1 CALL MOVASC ;SAVE ASCII FILENAME IN WCSAV1 MOV R3,WC1PTR ;SAVE BUFFER POINTER BR 10$ ;GET ANOTHER DIRECTORY ENTRY 30$: CMP WCSAV1,WC1PTR ;IF NO MATCHES, THESE TWO ARE BNE 60$ ;EQUAL 40$: BIT #WC.1FL,WC.FLG ;WILDCARDING ON INPUT FILE 1? BEQ 50$ ;IF NOT, BRANCH .ERR #ERAREA,#FNF,LEVEL=FATAL,RETURN=NO,FILE=#INFILE 50$: .ERR #ERAREA,#FNF,LEVEL=FATAL,RETURN=NO,FILE=# 60$: MOV WC1PTR,R3 ;FLAG END OF WCSAV1 CLRB (R3)+ ;WITH A ZERO BYTE MOV R3,WCEND ;SAVE WCSAV1 END 70$: BOTSPC ;WILDCARDING ON BOTH SPECS? BNE 100$ ;IF NOT, BRANCH MOV R3,WCSAV2 ;START WCSAV2 AT END OF WCSAV1 MOV R3,WC2PTR ;INIT BUFFER POINTER MOV #1,NXTDSG ;INIT FOR DIR ROUTINES CLR EOSFLG INC MVAL ;SET TAPE 2 FLAG, IF NEEDED MOV #ICHAN2,ICHAN ;GET CHANNEL NUMBER MOV WDEV2,DEVIN ;GET DEVICE TYPE MOV ,LKBLK ;GET ERROR MSG, IF NEEDED 80$: CALL WCDIR ;GET DIRECTORY ENTRY BCS 90$ ;IF C SET, END OF DIRECTORY MOV #IN2ASC,R3 ;POINT TO ASCII OF SPEC 2 CALL MATCH1 ;FIND MATCH, IF ANY TST R0 ;ANY MATCHES? BEQ 80$ ;BRANCH IF NONE MOV WC2PTR,R3 ;POINT TO START OF BUF 2 CALL MOVASC ;SAVE ASCII FILENAME IN WCSAV2 MOV R3,WC2PTR ;SAVE BUFFER POINTER BR 80$ ;GET ANOTHER DIRECTORY ENTRY 90$: CMP WCSAV2,WC2PTR ;IF NO MATCHES, THESE TWO ARE BEQ 50$ ;EQUAL MOV WC2PTR,R3 ;FLAG END OF WCSAV2 CLRB (R3)+ ;WITH A ZERO BYTE MOV R3,WCEND ;SAVE WCSAV2 END 100$: RETURN .SBTTL WCDIR Get a directory entry ;+ ; WCDIR ; This routine determines which of the directory entry routines ; should be used (DKDIR or MTDIR). It then JMP's to ; the appropriate routine, which returns to WCDISP. ;- WCDIR:: TST DEVIN ;Input device a disk? BEQ DKDIR ;Branch if yes TST MVAL ;Are we reading a 2nd tape? BEQ 10$ ;If no, branch MOV #DBUF,MBUF ;Get 2nd magtape buffer 10$: JMP MTDIR ;Read a tape .SBTTL DKDIR-Get a disk directory entry ;+ ; DKDIR ; This routine points R5 at the next directory entry of a disk directory. ; R5 cannot be modified once DKDIR has been called. ; OUTPUTS: ; R5 -> next directory entry, if one exists ; C-bit = 1 if no more directory entries ;- DKDIR:: TST EOSFLG ;Have we got a segment? BNE 7$ ;Branch if yes 1$: MOV NXTDSG,RBLK ;Get the next directory segment BNE 2$ ;If NE then we're not at end SEC ;Flag no more entries BR 9$ ; and return to caller 2$: MOV SP,EOSFLG ;Fix the end-of-segment flag ASL RBLK ;Each directory segment is 2 blocks ADD #4,RBLK ;Offset to block 6 for 1st one MOV #DBUF,R5 ;Point R5 at the input buffer MOV R5,NXTFIL ;Set the pointer to the next file ADD #DH.SIZ,NXTFIL ;Skip the header words .READW #IOAREA,ICHAN,R5,#INBFSZ/2,RBLK ;Read a directory segment BCC 3$ ;Branch if no error .ERR #ERAREA,#ERD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 3$: MOV DH.EXB(R5),XTRABY ;Set the number of extra bytes BIT #1,XTRABY ;Odd number of extra bytes? BNE 4$ ;Branch if so. Illegal directory. MOV DH.NXT(R5),NXTDSG ;Set the next directory segment MOV DH.STB(R5),SBLOCK ;Get starting block number for segment BNE 5$ ;If EQ, then illegal directory 4$: .ERR #ERAREA,#ILD,LEVEL=FATAL,RETURN=NO,FILE=#LKBLK 5$: TST HISEG ;Is this the first segment? BNE 6$ ;Branch if not MOV DH.HI(R5),HISEG ;Else get the highest segment open MOV DH.AVL(R5),AVAIL ; and the highest available BLE 4$ ;If <= 0, illegal directory CMP #37,AVAIL ;Too many directory segments? BLO 4$ ;Branch if so 6$: TST EOSFLG ;Was the last entry end of a segment? BEQ 1$ ;Branch if so 7$: MOV NXTFIL,R5 ;Point R5 at the next entry BIT #DS.EOS,@R5 ;Are we pointing to end of the segment? BEQ 8$ ;Branch if not CLR EOSFLG ;Set the flag 8$: ADD #DE.SIZ,NXTFIL ;Point to next file entry for next loop ADD XTRABY,NXTFIL ;Don't forget extra bytes CLC ;Clear the carry bit 9$: RETURN .SBTTL MTDIR-Get next magtape filename ;+ ; MTDIR ; This is the main magtape directory routine. It is JMP'ed to ; from WCDIR ; INPUTS: ; An HDR label starting at the address in MBUF. ; OUTPUTS: ; R5 -> a pseudo-directory entry at the address in MBUF+1000 ; CHARS contains the filename ; SBLOCK contains the file sequence number ; All registers modified. ; ;The C bit is set when there are no more files ;- MTDIR:: TST EOSFLG ;Have we encountered EOT or LEOT? BEQ 1$ ;Branch if not JSR R5,SPFUN ;Start a rewind .BYTE 377,SF.MRE SEC ; say we're done BR 17$ ; and return with done. 1$: MOV MBUF,R4 ;Point to input buffer MOV R4,R5 ;001 ADD #1000,R5 ;Put fake directory entry here. ;001 MOV R4,R0 ;Point to filename ADD #MT.FID,R0 ; MOV #CHARS,R1 ;Store the filename here MOV R1,R3 ;Save it. CMPB #377,@R0 ;Deleted file? BNE 3$ ;Branch if not 2$: CLR DE.LEN(R5) ;Length is zero MOV #DS.EMP,@R5 ;Empty file BR 9$ ;Go get positioned for next file 3$: MOV #DS.PRM,@R5 ;Make it a permanent entry MOV #13,R2 ;Blank file the filename area 4$: MOVB #BLANK,(R1)+ ; DEC R2 ; BNE 4$ ;Branch if not MOV #6,R2 ;Filenames are 6 characters long 5$: CMPB @R0,#DOT ; or until the '.' is found BEQ 6$ ;Branch if found MOVB (R0)+,(R3)+ ;Move in the character DEC R2 ;Done? BNE 5$ ;Branch if not 6$: CMPB @R0,#DOT ;Was the last character a '.'? BNE 7$ ;Branch if not TSTB (R0)+ ;Else get rid of it SUB #4,R1 ;Point R1 at the filetype area 7$: MOV #3,R2 ;Move 3 characters 75$: CMPB @R0,#DOT ;Is it a dot? BEQ 8$ ;Branch if so. Done. MOVB (R0)+,(R1)+ ;Move in the character DEC R2 ;Done? BNE 75$ ;Branch if not 8$: MOV R4,R1 ;Point to the file sequence number ADD #MT.SEQ,R1 ; CLRB 4(R1) ;Mark the end CALL GETNUM ;Convert it to binary MOV R3,SBLOCK ;Save it BEQ 2$ ;If it's equal, it's an empty file. CALL GETNAM ;Convert the name to RAD50 9$: JSR R5,SPFUN1 ;Space forward to tapemark .BYTE 377,SF.MFS 10$: JSR R5,SPFUN1 ;Again... .BYTE 377,SF.MFS 11$: CALL READMT ;Read a label (we hope) BCC 12$ ;Branch if no error CALL CHCKSB ;Check for a 'short block read' BEQ 12$ ;Branch if so... may be a good label CMP LKBLK,#EM.EOT ;End-of-tape w/o EOF? BEQ 115$ ;Yep... CMP LKBLK,#EM.EFT ;End-of-tape w/EOF? BNE 11$ ;Nope... 115$: CLR DE.LEN(R5) ;We hit EOT without a label. Zero length BR 15$ ;Finish up 12$: MOV MBUF,R4 ;Get buffer address CMP @R4,#MT.HDR ;Did we get a header label? BNE 13$ ;Branch if not JSR R5,SPFUN1 ;Else do 2 backspaces to tapemark .BYTE 377,SF.MBS ; followed by a space forward JSR R5,SPFUN1 ; and a read .BYTE 377,SF.MBS ; to get to the EOF label BR 10$ ; 13$: CMP @R4,#MT.EOF ;Did we get the EOF label? BNE 11$ ;Branch if not. Try reading another block BIT #DS.PRM,@R5 ;Is this file there? BEQ 14$ ;Branch if not MOV R4,R1 ;Point to record count ADD #MT.FSZ,R1 ; CLRB 6(R1) ;Mark the end of the field CALL GETNUM ;Go make it binary MOV R3,DE.LEN(R5) ;Save it 14$: JSR R5,SPFUN1 ;Space forward tapemark .BYTE 377,SF.MFS CALL READMT ;Read the next label (we hope) BCC 17$ ;Branch if no error CALL CHCKSB ;Short block check. CLC ;Clear carry, just in case BEQ 17$ ;Branch if it was... Ignore error 15$: MOV SP,EOSFLG ;Else assume EOT or LEOT 17$: RETURN .SBTTL CHCKSB- Check for a 'short block' read ;+ ; CHCKSB ; This routine checks to see if a magtape read error was caused ; by the record containing less data than requested. If so, ; the Z bit is returned = 1. ;- CHCKSB:: TSTB @#$ERRBY ;Is it a hard error? BNE 10$ ;Yes, check for short read CLZ ;Nope... BR 20$ 10$: CMP LKBLK,#EM.SML ;Short block read? 20$: RETURN ;*Z* .SBTTL READMT- Read a magtape record ;+ ; READMT ; This routine is called to read magtape records. A .SPFUN is used ; so that the extra information can be obtained. ;- READMT:: .SPFUN #IOAREA,ICHAN,#SF.MRD,MBUF,#LABSIZ,#LKBLK RETURN .SBTTL SPFUN and SPFUN1- Issue .SPFUN request ;+ ; SPFUN, SPFUN1 ; SPFUN is used to do single block spacing on magtapes. ; SPFUN1 is used to space to tapemarks on magtapes. ; Both assume that a magtape is open on channel ICHAN. ; CALL: ; JSR R5,SPFUN(1) ; .BYTE 377,code ;code is the .SPFUN code to execute ; OUTPUTS: ; R0 is modified. ;- .ENABL LSB SPFUN1:: MOV #-1,-(SP) ;Space to tapemark entry BR 1$ ; SPFUN:: CLR -(SP) ;Single MT block spacing entry 1$: MOV #IOAREA,R0 ;Point to the EMT area block MOV ICHAN,@R0 ;Move in channel ADD #32*400,@R0 ;Add in function MOV #LKBLK,2(R0) ;Error reporting block for magtapes MOV (SP)+,6(R0) ;Word count MOV (R5)+,10(R0) ;.SPFUN code EMT 375 ;Execute it RTS R5 ;And return to caller. .DSABL LSB .SBTTL MATCH1- Filename match driver ;+ ; MATCH1 ; This is the driver for matching input filenames against the directory ; entries. ; INPUTS: ; R5 -> directory entry ; R3 -> ASCII input string ; OUTPUTS: ; R0 <> 0 if any of the input files matched the current file ; R0-R4 modified ; CHARS contains the ASCII of the current filename ;- MATCH1:: MOV R5,R0 ;Point to the directory entry ADD #DE.FN1,R0 ;Point to the 1st word of the filename MOV #CHARS,R1 ;Point to storage area for ASCII of the name CALL RTOA ;Convert the filename to ASCII BIT #DS.PRM,@R5 ;Is it a permanent file? BNE 2$ ;Branch if so 1$: CLR R0 ;Signal no match BR 9$ ; and return 2$: MOV R3,R1 ;Point to the input string MOV #CHARS,R2 ;Point to the filename (from directory) CALL MATCH2 ;Go see if the filenames match TST R0 ;Did they match? BEQ 9$ ;Branch if not. We're done MOV R3,R1 ;Point to the test string again ADD #7,R1 ;Point to the extension MOV #CHARS,R2 ;Point to the filename (from directory) ADD #7,R2 ;Point to the extension CALL MATCH2 ;Go see if the filetypes match TST R0 ;Did they match? BNE 9$ ;Branch if so 9$: RETURN .SBTTL MATCH2 - Pattern match routine ;+ ; MATCH2 ; This routine does a wildcard pattern match against an ASCII pattern string ; pointed to by R1 and a test string pointed to by R2. The matchable ; wildcards are: ; "%" => match any non-null, non-blank character ; "*" => match any string ; Both strings must end in an ASCII blank. ; If there is a match, R0 returns as <> 0. ; R1 is modified. ;- MATCH2:: .SAVRG CLR R0 ;Assume failure MOV #BLANK,R4 ;An ASCII blank is often used 1$: MOVB (R1)+,R3 ;Get the next pattern character CMPB #ASTERK,R3 ;Is it a "*"? BNE 2$ ;Branch if not CMPB @R1,R4 ;Are we at the end of the string? BEQ 3$ ;Branch if so. We have a match 2$: CMPB @R2,R4 ;Is this the end of the test string? BNE 4$ ;Branch if not CMPB R3,R4 ;At the end of the pattern string? BNE 6$ ;Branch if not. Return a level 3$: INC R0 ;Else it matched!!! BR 6$ ;Return a level 4$: CMPB R3,R4 ;Is this the end of the pattern string? BEQ 6$ ;Branch if so CMPB #ASTERK,R3 ;Is the pattern character a "*"? BEQ 5$ ;Branch if so CMPB (R2)+,R3 ;Does test char match pattern char? BEQ 1$ ;Branch if yes CMPB #PRCENT,R3 ;Is the pattern char a "%"? BEQ 1$ ;Branch if so. It matches. BR 6$ ;Else return to caller 5$: MOV R1,-(SP) ;Save R1 MOV R2,-(SP) ; and R2 JSR PC,1$ ;And call self!!!! MOV (SP)+,R2 ;Restore R2 MOV (SP)+,R1 ; and R1 TST R0 ;Did the strings match? BNE 6$ ;Branch if so CMPB (R2)+,R4 ;At the end of the test string yet? BNE 5$ ;Branch if not 6$: RETURN ;Return a level .SBTTL WCDMAT - FIND FILES FOR WILDCARD COMPARISON ;+ ; WCDMAT ; ; WCDMAT WILL DETERMINE WHICH FILES IN THE TWO SAVE AREAS ; WILL ACTUALLY BE COMPARED ; ; ONEFIL PROCESSES WILDCARDING ON ONE SPEC ; ; TWOFIL PROCESSES WILDCARDING ON BOTH SPECS ; ; IF A FILENAME IN THE SAVE AREA MATCHES, IT WILL BE RETAINED. ;- WCDMAT:: BOTSPC ;WILDCARDING ON BOTH SPECS? BEQ TWOFIL ;IF YES, BRANCH .SBTTL ONEFIL - WILDCARDING ON ONE INPUT SPEC ;+ ; ONEFIL ; ; SRCCOM WILL COMPARE ALL FILES THAT MATCH THE ; WILDCARDING TO THE FIXED SPEC (SPEC WITH NO WILDCARDING). ; ;- ONEFIL:: MOV WCSAV1,WC1PTR ;POINT TO START OF SAVE AREA RETURN .SBTTL TWOFIL - WILDCARDING ON BOTH INPUT SPECS ;+ ; TWOFIL ; ; A FILENAME IS SELECTED FROM WCSAV1. IT IS COMPARED ; TO EVERY AVAILABLE FILENAME IN WCSAV2. ; ; THE FILES MUST MATCH EXACTLY WHERE WILDCARDING EXISTS. ; ; IF THERE IS NO MATCH, THE FILENAME IN WCSAV1 IS ; BLANKED OUT ; ; IF THERE IS A MATCH, THE FILENAME IN WCSAV2 IS MOVED TO ; THE SLOT AFTER THE LAST MATCH IN WCSAV2 ; ; A FILENAME IN WCSAV1 CAN MATCH ONLY ONE FILENAME IN ; WCSAV2. ONCE A FILE IN WCSAV2 HAS BEEN MATCHED, IT ; CANNOT BE A MATCH FOR ANY OTHER FILES IN WCSAV1. ;- TWOFIL:: CLR MATFND ;CLEAR MATCH FOUND FLAG MOV WCSAV1,WC1PTR ;POINT TO START OF SAVE AREA 1 MOV WCSAV2,SAVPT2 ;POINT TO START OF SAVE AREA 2 10$: MOV WC1PTR,FIXSPC ;SAVE THE FIXED SPEC MOV #STR1A,R4 ;GET SAVE AREA FOR FILNAM MOV #IN1ASC,R1 ;GET INPUT SPEC MOV WC1PTR,R5 ;GET FILENAME 1 CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR1B,R4 ;GET SAVE AREA FOR FILTYP MOV #IN1ASC,R1 ;GET INPUT SPEC ADD #7,R1 ;POINT TO FILTYP MOV WC1PTR,R5 ;GET FILENAME 1 ADD #7,R5 ;POINT TO FILTYP CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV SAVPT2,WC2PTR ;POINT TO START OF VARIABLE SPECS MOV WC2PTR,R5 ;SAVE IT BIC #MATPAS,MATFND ;CLEAR THE MATCH FOUND FLAG 20$: MOV #STR2A,R4 ;GET SAVE AREA FOR FILNAM MOV #IN2ASC,R1 ;GET INPUT SPEC CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR2B,R4 ;GET SAVE AREA FOR FILTYP MOV #IN2ASC,R1 ;GET INPUT SPEC ADD #7,R1 ;POINT TO FILTYP MOV WC2PTR,R5 ;GET FILENAME 2 ADD #7,R5 ;POINT TO FILTYP CALL MAT2 ;FIND WHICH CHARS MATCH THE WILDCARDING MOV #STR1A,R1 ;GET FILE 1 STRING MOV #STR2A,R2 ;GET FILE 2 STRING CALL WMATCH ;SEE IF THE TWO MATCH TST R0 ;DO THEY MATCH? BEQ 80$ ;IF NOT, BRANCH 30$: MOV #STR1B,R1 ;GET FILE 1 TYP MOV #STR2B,R2 ;GET FILE 2 TYP CALL WMATCH ;SEE IF THE TWO MATCH TST R0 ;DO THEY MATCH? BEQ 80$ ;IF NOT, BRANCH 40$: BIS #MAT,MATFND ;MATCH FOUND CLRB MATTMP ;CLEAR TEMP SAVE AREA MOV SAVPT2,R4 ;GET CURRENT START OF BUFFER 2 CMP R4,WC2PTR ;ALREADY IN CORRECT SLOT? BEQ 75$ ;IF YES, BRANCH MOV #FILLEN,R3 ;MOVE OCCUPANT OF SLOT MOV #MATTMP,R5 ;TO TEMP SAVE AREA 50$: MOVB (R4)+,(R5)+ ;MOVE CHARS INTO MATTMP SOB R3,50$ 60$: MOV #FILLEN,R3 MOV WC2PTR,R4 ;GET MATCH IN WCSAV2 MOV SAVPT2,R5 ;GET DESTINATION SLOT 65$: MOVB (R4)+,(R5)+ ;MOVE MATCH TO DESTINATION SOB R3,65$ MOV #FILLEN,R3 ;IF YES, MOVE CONTENTS MOV #MATTMP,R4 ;TO WHERE THE MATCH MOV WC2PTR,R5 ;CAME FROM IN WCSAV2 70$: MOVB (R4)+,(R5)+ SOB R3,70$ ;CONTINUE UNTIL END 75$: ADD #FILLEN,SAVPT2 ;GET NEW START OF WCSAV2 MOV SAVPT2,R2 TSTB @R2 ;AT END OF WCSAV2? BNE 110$ ;IF NOT, CONTINUE BR 120$ ;YES, GO OUT 80$: ADD #FILLEN,WC2PTR ;POINT TO THE NEXT VARIABLE SPEC MOV WC2PTR,R5 TSTB @R5 ;AT END OF BUFFER? BNE 20$ ;IF NOT, BRANCH BIT #MATPAS,MATFND ;ANY MATCHES ON THIS PASS? BNE 110$ ;IF YES, BRANCH MOV FIXSPC,R2 ;NO, BLANK OUT MOV #FILLEN,R3 ;FILENAME IN 90$: MOVB #BLANK,(R2)+ ;WCSAV1 SOB R3,90$ 110$: ADD #FILLEN,WC1PTR ;GET NEXT FIXED SPEC MOV WC1PTR,R2 TSTB @R2 ;AT END OF FIXED SPECS? BEQ 120$ ;IF YES, GO OUT JMP 10$ ;IF NO, GET ANOTHER FILENAME 120$: BIT #ONEMAT,MATFND ;AT LEAST ONE MATCH FOUND? BNE 100$ ;IF YES, BRANCH .ERR #ERAREA,#ILC,LEVEL=FATAL,RETURN=NO 100$: MOV SAVPT2,R5 ;GET END OF WCSAV2 CLRB @R5 ;FLAG IT WITH A ZERO MOV WCSAV1,WC1PTR ;GET START OF SAVE AREA 1 MOV WCSAV2,WC2PTR ;GET START OF SAVE AREA 2 RETURN .SBTTL MATCH ROUTINES FOR WILDCARDING ON BOTH SPECS ;+ ; WILDCARDING ON BOTH SPECS USES TWO ROUTINES TO ; DETERMINE IF THERE IS A MATCH ; ; 1. MAT2 WILL PRODUCE A STRING CONTAINING THE CHARACTERS ; THAT MATCH THE WILDCARDING FOR EACH PAIR OF FILENAMES. ; 2. WMATCH WILL DETERMINE IF THE TWO STRINGS PRODUCED ; BY MAT2 ARE THE SAME. ; ; This algorithm allows for special interpretation when two ; filespecs contain similar wildcards. In a sense, it must ; invert the sense of the wildcard string, allowing a match ; wherever fixed characters exist, and demanding equivalence ; for any wildcard. ; ; For example, ; ; DIFFERENCES A*.TXT B*.TXT ; ; means "let A match B and find files where the '*' represents ; the same character(s) in both specs. In other words, the ; traditional wildcard comparison would never match A* and B* ; because A and B are different. But MAT2 tries to isolate those ; characters that are represented by '*'s and '%'s, and places ; those characters in a 'save' area for later comparison. ; ; MAT2 is called four times for each potential comparison; ; once for each filename, and once for each filetype. Then MATCH ; is used to see if the respective save areas match. ; ; Consider the example above, and the following list of directory ; files: ; ; ALPHA.TXT BETA.TXT ; A1.TXT B1.TXT ; A2.TXT B3.TXT ; A4.TXT B2.TXT ; ALL.TXT BLL.TXT ; ; Characters that aren't to be checked are the initial 'A's and 'B's. ; MAT2 will place 'LPHA' and 'ETA' in the save area for comparison. ; Because they don't compare, it will be called again on the second ; filename with '1', '3', '2', and 'LL'. No match will occur. ; Then, looking at the second spec in the first column, MAT2 will be ; called upon to isolate '1' from 'A1', and 'ETA' from 'BETA', then ; '1' from 'B1', and MATCH will detect a match. ;- .SBTTL MAT2 - Find characters that correspond to wildcards ;+ ; MAT2 ; ; MAT2 finds those characters in the input files that ; correspond to the wildcard characters in the supplied pattern ; string. Those characters will be placed in a special save area. ; A blank flags the end of the matching characters. If there are ; no matches, the save area will contain one blank. ; ; INPUTS: ; R1 = ADDRESS OF WILDCARDING SPEC (PATTERN STRING) ; R4 = ADDRESS OF SAVE AREA FOR MATCHING CHARS ; R5 = ADDRESS OF FILENAME TO BE TESTED (TEST STRING) ; OUTPUTS: ; SAVE AREA CONTAINS THE MATCHING CHARACTERS ;- .ENABL LSB MAT2:: MOV R5,SAVPTR ;SAVE FILENAME START 10$: MOVB (R1)+,R2 ;GET PATTERN CHARACTER CMPB R2,#ASTERK ;IS IT AN *? BEQ 20$ ;IF YES, BRANCH CMPB R2,#PRCENT ;IS IT A %? BEQ 20$ ;IF YES, BRANCH CMPB R2,#BLANK ;AT THE END? BEQ 50$ ;IF YES, BRANCH ; Character is a "FIXED" character. INC R5 ;POINT TO NEXT CHAR IN TEST STRING CMPB #ASTERK,-2(R4) ; Is there already an '*' in string ? BEQ 10$ ; Yes, don't add redundant '*' MOVB #ASTERK,(R4)+ ; No, translate to match any string BR 10$ ;GET NEXT PATTERN CHAR ; Character is '%' or '*'. 20$: CMPB @R5,#BLANK ;end of TEST string? BEQ 50$ ;if YES, done. MOVB (R5)+,(R4)+ ;put TEST character into save area. CMPB R2,#PRCENT ;was PATTERN char a '%'? BEQ 10$ ;if YES, get next PATTERN character ; Finish processing '*' in pattern. One test character is already ; stored for it. 30$: CMPB @R1,#ASTERK ;redundant stars? BNE 40$ INC R1 BR 30$ ; eat them up. 40$: CALL MAT2A ;Test for fixed substring equality BCC 10$ ; if equal, continue scanning. BR 20$ ; if not, keep getting TEST chars. ; Finished 50$: MOVB ASCB,@R4 ;PUT IN TERMINATOR 60$: RETURN .DSABL LSB .SBTTL MAT2A - TEST FOR FIXED SUB-STRING EQUALITY ;+ ; Test for fixed sub-string equality ; ; Compare strings, accepting BLANK, ASTERK or PRCENT as legitimate ; terminators on the PATTERN string, and BLANK as a legitimate ; terminator on the TEST string. This can be used to check whether ; the next fixed portion of a wildcard substring is equivalent to ; the corresponding portion of a test string. ; ; R1 -> PATTERN sub-string ; R5 -> TEST sub-string ; ; Examples: ; ; 1) in "a*bc" let R1 -> a*bc ; in "a123bc" let R5 -> a123bc (match) ; ; 2) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> 23bc (no match) ; ; 3) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> 3bc (no match) ; ; 4) in "a*bc" let R1 -> bc ; in "a123bc" let R5 -> bc (match) ; ; NO registers are altered ; ; Upon return, the C-bit ON indicates NOT_EQUAL; use BCC or BCS ; immediately after call. ;- .ENABL LSB MAT2A: MOV R1,-(SP) ; Save working registers MOV R5,-(SP) 10$: CMPB @R1,@R5 ; Are the characters equal? BNE 20$ ; find out why not. CMPB @R1,#BLANK ; End of BOTH strings? BEQ 30$ ; That's Equality. BITB (R1)+,(R5)+ ; Yes. bump the pointers, BR 10$ ; and check again. 20$: CMPB @R1,#BLANK ; End of just PATTERN string? BEQ 40$ ; That's not equality. CMPB @R1,#PRCENT ; allow '%' for terminating PATTERN BEQ 30$ ; also CMPB @R1,#ASTERK ; allow '*' to terminate BNE 40$ 30$: TST (PC)+ ; EQUAL 40$: SEC ; NOT_EQUAL MOV (SP)+,R5 ;*C* Restore registers MOV (SP)+,R1 ;*C* RETURN .DSABL LSB .SBTTL WMATCH - GENERAL MATCH ROUTINE ;+ ; WMATCH ; ; WMATCH DETERMINES IF TWO INPUT STRINGS ARE EXACTLY ALIKE. ; ; TWOFIL USES WMATCH TO DETERMINE IF THE TWO STRINGS ; CONTAINING THE CHARACTERS MATCHING THE WILDCARDING ARE ; THE SAME. IF THEY ARE, THERE IS A MATCH. ; ; INPUTS: ; R1 = ADDRESS OF STRING 1 ; R2 = ADDRESS OF STRING 2 ; OUTPUTS: ; R0 <> 0 IF THERE IS A MATCH ;- WMATCH:: .SAVRG CLR R0 ;ASSUME FAILURE MOVB #BLANK,R4 ;END OF SPEC = BLANK 10$: MOVB (R1)+,R3 ;GET FIXED SPEC CHAR CMPB @R2,R4 ;END OF VARIABLE SPEC? BNE 20$ ;IF NOT, BRANCH CMPB R3,R4 ;END OF FIXED SPEC? BNE 100$ ;IF NOT, BRANCH INC R0 ;THEY MATCHED BR 100$ ;RETURN 20$: CMPB R3,R4 ;END OF FIXED SPEC? BEQ 100$ ;BRANCH IF SO CMPB (R2)+,R3 ;TEST CHAR MATCH FIXED SPEC? BEQ 10$ ;IF YES, BRANCH 100$: RETURN .SBTTL WCDLKI - LOOKUP INPUT FILES ;+ ; WCDLKI ; ; WCDLKI DOES THE LOOKUPS ON THE INPUT FILES. ; EACH TIME THROUGH IT SELECTS THE NEXT FILENAME(S) ; FROM WCSAV1 (AND WCSAV2) AND OPENS THE FILES ; ; WHEN THE END OF WCSAV1 IS FOUND, THE WILDCARDING FLAG ; WC.FLG IS SET TO ZERO. ;- WCDLKI:: MOV WC1PTR,R1 ;POINT TO NEXT INPUT FILENAME 10$: CMPB @R1,#BLANK ;GET RID OF LEADING BNE 20$ ;BLANKS TSTB (R1)+ BR 10$ 20$: .CLOSE #ICHAN1 ;CLOSE CHANNELS AFTER .CLOSE #ICHAN2 ;PREVIOUS LOOKUPS TSTB @R1 ;AT END OF BUFFER? BNE 25$ ;IF NO, BRANCH BIC #FL.WCD,$FLAGS ;WCD ENDED BR 70$ 25$: MOV R1,WC1PTR ;PUSH PAST ANY BLANKS CALL CONR50 ;CONVERT NEXT SPEC TO RAD50 BOTSPC ;WILDCARDING ON BOTH SPECS? BEQ 50$ ;IF YES, BRANCH BIT #WC.1FL,WC.FLG ;WILDCARDING ON FIRST INPUT SPEC? BEQ 30$ ;NO, BRANCH MOV #INFILE,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;INFILE FOR LOOKUP 30$: BIT #WC.2FL,WC.FLG ;WILDCARDING ON INPUT FILE 2? BEQ 40$ ;IF NOT, BRANCH MOV #,R0 ;YES, MOV RAD50 SPEC TO CALL MOVR50 ;INPUT FILE 2 FOR LOOKUP 40$: BIT #WC.NXT,WC.FLG ;1ST TIME THROUGH WC? BEQ 60$ ;IF YES, BRANCH CALL LOOK1 ;LOOKUP INPUT FILE 1 CALL LOOK2 ;LOOKUP INPUT FILE 2 BR 60$ ;GO BUMP FILE POINTER 50$: MOV WC2PTR,R0 ;GET NEXT FILE2 TSTB @R0 ;AT THE END? BNE 55$ ;IF NOT, BRANCH BIC #FL.WCD,$FLAGS ;WCD ENDED BR 70$ 55$: MOV #INFILE,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;INFILE 1 FOR LOOKUP MOV WC2PTR,R1 ;GET INPUT FILE 2 NAME CALL CONR50 ;CONVERT NAME TO RAD50 MOV #,R0 ;MOV RAD50 SPEC TO CALL MOVR50 ;INFILE 2 FOR LOOKUP BIT #WC.NXT,WC.FLG ;1ST TIME THROUGH WC? BEQ 60$ ;IF YES, BRANCH CALL LOOK1 ;LOOKUP INPUT FILE 1 CALL LOOK2 ;LOOKUP INPUT FILE 2 60$: ADD #FILLEN,WC2PTR ;POINT TO NEXT FILE 2 ADD #FILLEN,WC1PTR ;POINT TO NEXT FILESPEC MOV WC1PTR,R0 TSTB @R0 ;AT END? BNE 100$ ;IF NOT, BRANCH 70$: CLR WC.FLG ;YES, END WILDCARDING 100$: RETURN .SBTTL LOOK1 ;+ ; LOOK1 ; ; LOOK1 DOES THE LOOKUP FOR THE FIRST INPUT SPEC ; THE TYPE OF LOOKUP DEPENDS ON WHETHER THE ; FILE IS ON A MAGTAPE OR A DISK ;- LOOK1:: BIT #DEVMT,WDEV1 ;DEV 1 A MAGTAPE? BNE 20$ ;IF YES, BRANCH .LOOKUP #IOAREA,#ICHAN1,#INFILE ;LOOKUP INPUT FILE 1 (DISK) BCC 100$ ;IF NO ERROR, BRANCH 10$: .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,RETURN=NO,FILE=F.OPNM(R2) 20$: .LOOKUP #IOAREA,#ICHAN1,#INFILE,#0 ;LOOKUP INPUT FILE 1 (TAPE) BCS 10$ ;IF ERROR, BRANCH 100$: RETURN .SBTTL LOOK2 ;+ ; LOOK2 ; ; LOOK2 DOES THE LOOKUP FOR THE SECOND INPUT SPEC ; ; THE TYPE OF LOOKUP DEPENDS ON WHETHER THE ; FILE IS ON A MAGTAPE OR A DISK ;- LOOK2:: BIT #DEVMT,WDEV2 ;DEV 2 A MAGTAPE? BNE 20$ ;IF YES, BRANCH .LOOKUP #IOAREA,#ICHAN2,# ;LOOKUP INPUT FILE 2 (DISK) BCC 100$ ;IF NO ERROR, BRANCH 10$: .ERR #ERAREA,F.ERR(R2),LEVEL=FATAL,RETURN=NO,FILE=F.OPNM(R2) 20$: .LOOKUP #IOAREA,#ICHAN2,#,#0 ;LOOKUP INPUT FILE 2 (TAPE) BCS 10$ ;BRANCH ON ERROR 100$: RETURN .SBTTL CONR50 ;+ ; CONR50 CONVERTS AN ASCII FILENAME TO RAD50 FOR LOOKUP ; ; INPUTS: ; R1 = START OF ASCII FILENAME ; OUTPUTS: ; SAVR50 = RAD50 FILENAME ; ; THE ASCII FILENAME IS IN THE FORM ; XXXXXXbXXXb WHERE b IS AN ASCII BLANK ;- CONR50:: MOV #SAVR50,R2 ;SAVE AREA FOR RAD50 CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT TSTB (R1)+ ;SKIP THE BLANK CALL $ASCR50 ;CALL ULBLIB TO CONVERT 1 WORD MOV R0,(R2)+ ;SAVE IT RETURN .SBTTL MOVR50 ;+ ; MOVR50 MOVES A RAD50 FILESPEC PLACED IN AREA SAVR50 BY ; CONR50 TO EITHER INFILE OR INFILE+10 FOR THE .ENTER ; IN WCDLKI ; ; INPUTS: ; R0 = START OF RAD50 FILESPEC AREA ; (INFILE OR INFILE+10) ;- MOVR50:: MOV #SAVR50,R1 ;RAD50 WAS STORED IN SAVR50 ADD #2,R0 ;POINT TO START OF FILENAME MOV (R1)+,(R0)+ ;MOVE IN THE MOV (R1)+,(R0)+ ;THREE RAD50 MOV (R1)+,(R0)+ ;WORDS RETURN .SBTTL WCDPRT - PRINT COMPARING MESSAGE ;+ ; WCDPRT SENDS THE COMPARING MESSAGE TO THE TT WHEN ; THE USER HAS SPECIFIED A PRINT FILE OR THAT ; DIFFERENCES ARE NOT TO BE PRINTED ;- WCDPRT:: MOV #$SDB1,R2 ;Point to the SDB for file #1 CALL $IDLIN ;Convert file ID to ASCII MOV #$LSTBF,R0 ;Get list buffer start ADD R1,R0 ;Add string length CLRB @R0 ;Put in a zero for .PRINT .PRINT #$LSTBF ;Print filename 1 MOV #$SDB2,R2 ;Same for file #2 CALL $IDLIN ; MOV #$LSTBF,R0 ;Get list buffer start ADD R1,R0 ;Add string length CLRB @R0 ;Put in a zero for .PRINT .PRINT #$LSTBF ;Print filename 2 RETURN .SBTTL WCDPUT - PUT FILENAMES INTO PRINT BUFFER ;+ ; WCDPUT PUTS THE FILENAMES INTO THE PRINT BUFFER ; WHEN CHANGEBARS WERE SPECIFIED AND ON THE SECOND ; AND LATER WILDCARDING PASSES ;- WCDPUT:: MOV #$SDB1,R2 ;Point to the SDB for file #1 CALL $IDLIN ;Convert file ID to ASCII MOV #$LSTFD,SAVFDB ;Get FDB for printing PUTLIN R3,R1 ;Output the file ID MOV #$SDB2,R2 ;Same for file #2 CALL $IDLIN ; MOV #$LSTFD,SAVFDB ;Get FDB for printing PUTLIN R3,R1 ; RETURN .SBTTL RTOA- Convert 3 RAD50 words to ASCII ;+ ; RTOA ; This routine converts 3 RAD50 words to ASCII. It assumes that the 3 ; words to convert is a filename block, and inserts blanks accordingly. ; INPUTS: ; R0 -> 3 word block ; R1 -> 11 byte block to store the ASCII ; OUTPUTS: ; R1 updated past the end of the ASCII ; ; For a filespec AAAA.XXX in RAD50, RTOA returns ; AAAAbbbXXXb in ASCII, where b = ASCII blank ; ; RTOA always returns 11. bytes ;- RTOA:: MOV R0,-(SP) ;Save R0 MOV R2,-(SP) ; and R2 MOV R0,R2 ;Point to the RAD50 to convert MOV (R2)+,R0 ;Get the first word CALL $R50ASC ;Convert it MOV (R2)+,R0 ;Get next word CALL $R50ASC ; and convert it MOVB #BLANK,(R1)+ ;Move in a blank MOV @R2,R0 ;Get the next word CALL $R50ASC ;Convert it MOVB #BLANK,(R1)+ ;Store the final blank MOV (SP)+,R2 ;Restore the registers MOV (SP)+,R0 ; RETURN .SBTTL GETNAM- Convert filename to RAD50 ;+ ; GETNAM ; This routine converts the ASCII stored at CHARS to 3 words of RAD50. ; Called from the magtape routine to produce pseudo-directory entries. ; ; INPUTS: ; R5 -> to a pseudo-directory entry ; OUTPUTS: ; R0 is modified ; RAD50 is stored in the filename/filetype locations of the ; pseudo-entry. ;- GETNAM:: MOV R1,-(SP) ;Save R1 MOV #CHARS,R1 ;R1 -> ASCII CALL $ASCR50 ;Convert it to RAD50 MOV R0,DE.FN1(R5) ;Store it CALL $ASCR50 ;Convert the next 3 characters MOV R0,DE.FN2(R5) ; and store the RAD50 TSTB (R1)+ ;Skip the blank CALL $ASCR50 ;Convert the filetype MOV R0,DE.TYP(R5) ;Save it MOV (SP)+,R1 ;Restore R1 RETURN .SBTTL GETNUM - Convert ASCII to binary, decimal ;+ ; GETNUM ; ; INPUTS: ; R1 -> buffer holding an ASCII character string ; OUTPUTS: ; R3 contains the binary number ;- GETNUM:: CLR R3 ;R3 will hold the binary result 10$: MOVB (R1)+,R0 ;Move char to R0 SUB #'0,R0 ;Subtract ASCII zero BMI 100$ ;If MI, char is not a number CMP #9.,R0 ;Is it a 9? BLO 100$ ;If not, branch ASL R3 ;Multiply previous result by 2 MOV R3,-(SP) ;Save it ASL R3 ;R3 * 4 ASL R3 ;R3 * 8 ADD (SP)+,R3 ;(R3 * 2) + (R3 * 8) = R3 * 10 ADD R0,R3 ;Add new digit to previous result BR 10$ ;Keep going until end 100$: RETURN .SBTTL MOVASC ; ; THIS SUBROUTINE SAVES THE ASCII OF THE INPUT FILENAME ; ; INPUTS: ; R3 = ADDRESS OF THE BUFFER IN WHICH TO PLACE ; THE SPEC ; MOVASC: MOV #FILLEN,R0 ;NUMBER OF BYTES TO MOVE MOV #CHARS,R1 ;START OF ASCII SPEC 10$: MOVB (R1)+,(R3)+ ;MOVE A BYTE INTO THE BUFFER DEC R0 ;DEC COUNTER BGT 10$ ;IF NOT FINISHED, BRANCH RETURN ;RETURN .DSABL GBL .END WILCRD