$BEGIN PARSFN,<29.0>, ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ; BE USED OR COPIED ONLY IN ACCORDANCE WITH THE TERMS ; OF SUCH LICENSE. ; ; COPYRIGHT (c) 1982 BY DIGITAL EQUIPMENT CORPORATION. ; ALL RIGHTS RESERVED. ; ; PETER H. LIPMAN ; ; PREVIOUSLY MODIFIED BY ; ; E. H. MARISON ; S. RUZICH ; LONI BROWN ; ; August 31, 1984 by Robin Miller. Edit (01). ; Allow parsing of new wildcard constructions (* and %). The ; ACP routine .LOCAT checks bit NB.WCH in the file name status ; word (N.STAT) and if set calls routine .MATNM to do special ; wildcard matching. ; ;+ ; PARSE FILE NAME DESCRIPTOR - CALLED BY PARSE TO ESTABLISH THE ; FILE NAME AND VERSION NUMBER ENTRIES OF FNB. ; ; INPUTS: ; R0=FDB ADDRESS ; R1=ADDRESS OF FILE NAME BLOCK ; R2=POINTER TO DEV, DIR, AND NAME DESCRIPTORS ; R3=DEFAULT FILE NAME BLOCK OR ZERO IF NONE SPECIFIED ; OUTPUTS: ; C=0 IF SUCCESSFUL, C=1 IF ERROR, F.ERR SET TO REASON ; ALL REGISTERS PRESERVED. ;- .PRSFN::.SAVR1 MOV #1,F.ERR(R0) ..PSFN::MOV R3,-(SP) TST R2 ;NO DESCRIPTOR POINTER? .IF EQ,R$RSTS BEQ 10$ ;BRANCH IF YES .IFF BEQ PRSDF1 ;BR IF YES .IFTF MOV N.FNPT(R2),R3 ;R3=ADDRESS OF STRING MOV N.FNSZ(R2),R2 ;R2=SIZE OF STRING .IFF BLE PRSDF1 ;IS NO STRING USE DEFAULT .IFT 10$: MOV R3,-(SP) ;SAVE STRING POINTER MOV R2,-(SP) ;SAVE STRING SIZE .IF GT,R$$ANI BEQ PARS1 ;DO DEFAULT PROCESSING IF NULL FILENAME CMPB (R3),#'" ;FILENAME BEGINS WITH QUOTE CHARACTER? BNE PARS2 ;NO - NORMAL FILENAME JMP QUOTE ;YES- ANSI MAG TAPE QUOTED STRING FILENAME .ENDC PARS1: BLE BRDEF ;BRANCH IF STRING IS NOW NULL (DO DEFAULTS) PARS2: MOVB (R3)+,R4 ;GET NEXT CHARACTER OF STRING CMP #'.,R4 ;IS IT A DOT? BEQ DOT ;BRANCH IF YES CMP #';,R4 ;IS IT A SEMICOLON? BEQ SEMI ;BRANCH IF IT IS SOB R2,PARS2 ;GO LOOK AT NEXT CHARACTER ; NO MORE CHARACTERS IN STRING. THE STRING PASSED OVER IS A ; FILE NAME IF WE HAVN'T ALREADY SEEN ONE; A FILE TYPE IF WE HAVN'T ; SEEN THAT, OR A VERSION. INC R3 ;POSITION POINTER AS IF THERE WERE ;A DELIMITER ON THE END. ; HAVE WE ALREADY PASSED THE FILE NAME? BIT #NB.NAM!NB.DOT!NB.SMI,N.STAT(R1) BEQ FNAME ;BRANCH IF NO. ; HAVE WE ALREADY PASSED THE FILE TYPE? BIT #NB.SMI,N.STAT(R1) ;ONLY SEMICOLON OR EOLN DELIMITS FILE TYPE BEQ FTYPE ;EQ - JUST PASSED FILE TYPE ; ; THE FIELD JUST SCANNED IS A VERSION NUMBER. ; THE ERROR IN A STRING LIKE "A";X WILL BE DETECTED BY .VRCVT BELOW. ; VERSN: MOV 2(SP),R5 ;R5=ADDRESS OF STRING MOV R3,R4 ;CALCULATE R4=SIZE OF STRING SUB R5,R4 DEC R4 CMPB #'*,@R5 ;WILD CARD VERSION? BEQ 10$ MOV R1,R3 ADD #N.FVER,R3 ;R3=ADDRESS TO RETURN NUMBER IN CALL .VRCVT ;CONVERT THE STRING TO A NUMBER ; EM001 BCS 15$ ;**-1 BR PRSDF ;ALL DONE WITH FILE NAME- ;FILL IN DEFAULTS 10$: CMP #1,R4 ;* SEEN, ONLY 1 CHAR? BEQ 20$ ;YES, IT'S OK 15$: JMP PRSBX ;SYNTAX ERROR 20$: BIS #NB.SVR,N.STAT(R1) BRDEF: BR PRSDF ; FOUND DOT, NAME IN FRONT, ALSO NOTE THAT A TYPE WAS FOUND. IF NULL ; THEN THAT'S DIFFERENT FROM NULL AND NO DOT. (I.E. NULL VS. NOT SPECIFIED) DOT: BIT #NB.SMI,N.STAT(R1) ;IS THIS DOT PART OF VERSION NO.? BEQ 10$ ;BRANCH IF NO INC R3 ;ASSUME DECIMAL VERSION NUMBER BR VERSN ;DOT IS PART OF THE STRING 10$: BIT #NB.DOT,N.STAT(R1) ;HAVE WE ALREADY SEEN A DOT? BNE PRSBX ;YES- THIS IS AN ERROR BIS #NB.DOT,N.STAT(R1) ;NOTE THAT DOT WAS SEEN FNAME: MOV R3,R4 ;CALCULATE SIZE OF STRING SUB 2(SP),R4 ;TO SEE IF IT'S NULL DEC R4 BEQ 10$ ;BRANCH IF IT IS NULL BIS #NB.NAM,N.STAT(R1) ;WE HAVE FOUND A FILE NAME ; ; The wildcard characters are checked for in routine CKWILD. ; ;*** CMPB #'*,@2(SP) ;WILD CARD IN FIRST CHARACTER? (01) ;*** BNE 10$ ; (01) ;*** BIS #NB.SNM,N.STAT(R1) ;INDICATE THAT A * WAS SEEN (01) 10$: MOV #N.FNAM,R4 ;R4=OFFSET FOR FILE NAME MOV #9.,R5 ;R5=MAX SIZE OF FILE NAME BR PRSMV ; ; FOUND A SEMICOLON, THE PRECEEDING STRING IS A FILE NAME ; IF NO FILE NAME WAS SEEN OR IT IS A FILE TYPE. SEMI: BIT #NB.SMI,N.STAT(R1) ;HAVE WE ALREADY SEEN A SEMI? BNE PRSBX ;YES- THIS IS AN ERROR BIS #NB.SMI!NB.VER,N.STAT(R1) ;INDICATE THAT SEMI WAS FOUND BIT #NB.NAM!NB.DOT,N.STAT(R1) ;PAST A FILE NAME YET? BEQ FNAME ;BRANCH IF NO,THIS IS A FILE NAME ; THIS IS A FILE TYPE STRING FTYPE: MOV R3,R4 ;CALCULATE STRING SIZE SUB 2(SP),R4 DEC R4 ;TO SEE IF IT'S NULL BEQ 10$ ;BRANCH IF IT IS .IF GT,R$$ANI BIT #NB.ANS,N.STAT(R1) ;HAVE WE PASSED A QUOTED STRING? BNE PRSBX ;YES- BAD NAME LIKE "A"X. OR "A"X; OR "A"3 .ENDC BIS #NB.TYP,N.STAT(R1) ;NOTE THAT WE SAW A FILE TYPE ;*** CMPB #'*,@2(SP) ; (01) ;*** BNE 10$ ; (01) ;*** BIS #NB.STP,N.STAT(R1) ;NOTE WILD CARD TYPE (01) 10$: MOV #N.FTYP,R4 ;R4=OFFSET FOR FILE TYPE STRING MOV #3,R5 ;R5=MAX SIZE STRING .PAGE ; MOVE FILE NAME OR TYPE INTO ITS PLACE IN THE FILE NAME BLOCK ; R1=FILE NAME BLOCK ADDRESS, R3=POINTER TO TERMINATING CHARACTER ; R4=OFFSET IN FILE NAME BLOCK TO STORE STRING, R5=MAX NO. OF BYTES IN ; STRING. 0(SP)=PREVIOUS SIZE OF STRING, 2(SP)=STRING POINTER TO ; BEGINNING OF NAME PRSMV: MOV 2(SP),R2 ;R2=PTR TO BEGINNING OF STRING MOV R3,2(SP) ;UPDATE STRING POINTER SUB R2,R3 ;R3=NEW POINTER-OLD POINTER SUB R3,@SP ;UPDATE BYTE REMAINING IN STRING DEC R3 ;R3=SIZE OF STRING,EXCLUDING DELIMITER BEQ 10$ ;BRANCH IF STRING IS NULL ; ; This following code must be commented so the "*" gets converted ; to "$" for special wildcard matching. This becomes important on ; file names like "*.MA%" or "V%L.*" since special matching is done. ; ;*** CMPB #'*,@R2 ;DOES NAME START WITH WILD CARD? (01) ;*** BNE 2$ ;BRANCH IF NO (01) ;*** CMP #1,R3 ;MUST BE THE ONLY CHAR (01) ;*** BEQ 10$ ;IT IS, IF NOT, ILL RAD50 CHAR (01) 2$: CALL CKWILD ; Check/convert special wild cards. (01) CMP R5,R3 ;SIZE LEGAL? BLT PRSBX ;BRANCH IF TOO BIG ADD R1,R4 ;R4=ADDRESS TO MOVE STRING TO CALL ..SGR5 ;CONVERT ASCII STRIN TO RAD50 BCS PRSBX ;BRANCH IF SYNTAX ERROR ; DONE PUTTING NAME IN NAME BLOCK, GO DO THE NEXT PART OF THE STRING 10$: MOV 2(SP),R3 ;R3=ADDRESS OF STRING MOV @SP,R2 ;R2=REMAINING SIZE OF STRING JMP PARS1 .IFF CALL ..FSS,R5,<273> ; CALL RSTS FILE STRING SCANNER BCS PRSBX ; EXIT IF ERROR MOV R1,R5 ADD #N.STAT,R5 ; POINT TO STATUS WORD IN FNB BIT #1,R2 ; WAS FILENAME FOUND BEQ 10$ ; BR IF NO BIS #NB.NAM,@R5 ; INDICATE FILENAME FOUND BIT #2,R2 ; CHECK FOR WILDCARD NAME BNE 9$ ; BR IF YES MOV FQNAM1(R3),N.FNAM(R1); COPY THE FILENAME MOV FQNAM1+2(R3),N.FNAM+2(R1) BR 10$ 9$: BIS #NB.SNM,@R5 ; INDICATE WILDCARD FOUND 10$: BIT #10,R2 ; WAS FILE TYPE FOUND? BEQ 20$ ; BR IF NO BIS #NB.TYP,@R5 ; INDICATE FILE TYPE FOUND BIT #20,R2 ; CHECK FOR NULL FILE TYPE BEQ 20$ ; BR IF NULL FILE TYPE BIT #40,R2 ; CHECK FOR WILD FILE TYPE BNE 19$ ; BR IF FOUND MOV FQEXT(R3),N.FTYP(R1); PUT FILE TYPE IN FNB BR 20$ 19$: BIS #NB.STP,@R5 ; INDICATE WILD FILE TYPE 20$: BIT #200,R2 ; CHECK FOR SPECIAL PPN BEQ PRSDF1 ; BR IF PPN NOT FOUND MOV FQPPN(R3),N.DID(R1); MOVE PPN TO FNB .IFT ; ; STRING PARSE IS COMPLETE-SET UP DEFAULT FIELDS. PRSDF: ADD #4,SP ;GET RID OF STRING PTR AND SIZE .IFTF PRSDF1: MOV N.STAT(R1),R3 ;R3 = STATUS BITS .IFT BIT #NB.DOT,R3 ;IF DOT WAS SEEN BEQ 2$ BIS #NB.TYP,N.STAT(R1) ;INDICATE EXPLICIT TYPE FOUND .IFTF 2$: MOV (SP)+,R2 ;R2=DEFAULT NAME BLOCK ADDRESS BEQ 8$ ;BRANCH IF NO DEFAULT NAME BLOCK BIT #NB.NAM,R3 ;WAS A FILE NAME SPECIFIED? BNE 4$ ;BRANCH IF YES-NO DEFAULT NEEDED MOV N.FNAM(R2),N.FNAM(R1) ;MOV DEFAULT NAME FIELD INTO MOV N.FNAM+2(R2),N.FNAM+2(R1) ;FILE NAME BLOCK MOV N.FNAM+4(R2),N.FNAM+4(R1) ; IF AN EXPLICIT FILE TYPE WAS FOUND OR IF A DOT WAS SEEN THEN ; ASSUME FILE TYPE WAS EXPLICIT AND DON'T USE DEFAULT. ; THIS ALLOWS FILE. TO MEAN AN EXPLICIT NULL TYPE. 4$: BIT #NB.TYP!NB.DOT,R3 ;WAS A FILE TYPE SPECIFIED? BNE 6$ ;BRANCH IF YES-NO DEFAULT NEEDED MOV N.FTYP(R2),N.FTYP(R1) ;MOVE THE DEFAULT FILE TYPE .IFT 6$: BIT #NB.VER!NB.SMI,R3 ;WAS A VERSION SPECIFIED? BNE 8$ ;BRANCH IF YES- MOV N.FVER(R2),N.FVER(R1) ;MOVE THE DEFAULT VERSION NUMBER .IFF 6$: .IFTF 8$: RETURN .PAGE ; ERROR EXIT .IFT PRSBX: ADD #6,SP .IFF PRSBX: TST (SP)+ .ENDC MOVB #IE.BNM,F.ERR(R0) SEC RETURN ;+ ; QUOTE - ANSI MAG TAPE QUOTED ASCII STRING FILENAME PROCESSING ; ; ENTERED BY JMP. ; ; FILENAME IS INDICATED BY INITIAL DOUBLE QUOTE IN DSPT FILENAME STRING. ; A PAIR OF DOUBLE QUOTES IN THE DSPT REDUCES TO A ONE DOUBLE QUOTE IN THE FNB. ; FINAL DOUBLE QUOTE IS OPTIONAL AT END OF STRING (IF NO VERSION NUMBER). ; VERSION NUMBER CAN FOLLOW FINAL QUOTE, AS IS CAN FOLLOW NORMAL FILENAME. ; ROUTINE WILL JMP TO PARS1 IF VERSION NUMBER MIGHT FOLLOW; BAD SYNTAX ; FOLLOWING QUOTED STRING WILL BE DETECTED THERE. ; ; THE FILENAME MAY BE BROKEN UP INTO TWO SEGMENTS IN ORDER TO FIT THE ; PROCRUSTIAN BED OF THE FNB. ; ; QUOTED FILENAME SETS STATUS BITS FOR ANSI FILENAME, EXPLICIT FILENAME, ; EXPLICIT FILETYPE (TO AVOID DFNB FILETYP BEING APPLIED), AND DOT FOUND. ; ; INPUT: R0 - FDB ADDRESS ; R1 - FNB ADDRESS ; R2 - INPUT FILENAME STRING SIZE ; R3 - INPUT FILENAME STRING ADDRESS ; (SP) - INPUT FILENAME STRING SIZE ; 2(SP) - INPUT FILENAME STRING ADDRESS ; 4(SP) - FNB ADDRESS ; ; OUTPUT, IF JMP TO PRSDF OR PRSBX: ; R0,R1,SP - PRESERVED ; R2-R5 - ALTERED ; ; OUTPUT, IF JMP TO PARS1: ; Z BIT - SET/CLEAR FROM TEST OF R2 (FILENAME STRING SIZE) ; R0,R1 - PRESERVED ; R2 - CURRENT FILENAME STRING SIZE ; R3 - CURRENT FILENAME STRING ADDRESS ; (SP) - CURRENT FILENAME STRING SIZE ; 2(SP) - CURRENT FILENAME STRING ADDRESS ; 4(SP) - PRESERVED ; R4,R5 - ALTERED ; ;- .IF GT,R$$ANI QUOTE: BITB #CH.AND,F.CHR(R0) ;ANSI MAG TAPE? BEQ PRSBX ;IF NOT, THEN ERROR BIS #NB.NAM!NB.TYP!NB.DOT!NB.ANS,N.STAT(R1) ;SET STATUS BITS MOV #S.ANM1,R4 ;MAX SIZE OF FIRST SEGMENT IN FNB MOV R1,R5 ;GET ADDRESS OF FNB ADD #N.ANM1,R5 ;CALCULATE ADDRESS OF FIRST FILENAME SEGMENT CLR -(SP) ;CLEAR FLAG TO INDICATE INPUT EXISTS CALL ANSMV1 ;MOVE CHARACTERS INTO FIRST SEGMENT MOV #S.ANM2,R4 ;NE - MORE INPUT - GET MAX 2ND FNB SEGMENT SIZE MOV R1,R5 ;GET ADDRESS OF FNB ADD #N.ANM2,R5 ;CALCULATE ADDRESS OF SECOND FILENAME SEGMENT CALL ANSMV2 ;MOVE CHARACTERS INTO SECOND SEGMENT TST (SP)+ ;TEST FLAG; RESTORE SP BGT PRSDF ;GT = NO MORE INPUT BLT 10$ ;LT = CLOSED QUOTES, MORE INPUT: LOOK FOR VERS ;EQ = NOT END OF INPUT CMPB #'",(R3)+ ;ONLY TERMINAL QUOTE CAN BE LEGAL HERE BNE PRSBX ;NO - BAD FILE NAME DEC R2 ;YES- TERMINAL QUOTE FOUND - CORRECT CHAR COUNT 10$: MOV R3,2(SP) ;UPDATE THE STACKED STRING ADDRESS MOV R2,(SP) ;UPDATE THE STACKED STRING SIZE JMP PARS1 ;SEARCH FOR VERSION NUMBER, OR END OF INPUT .PAGE ;+ ; ANSMV1 - MOVE INPUT STRING CHARACTERS INTO FNB SEGMENT; IGNORE INITIAL QUOTE. ; ANSMV2 - MOVE INPUT STRING CHARACTERS INTO FNB SEGMENT ; ; TERMINAL QUOTE CHARACTER IN INPUT STRING IS OPTIONAL. ; ANY UNUSED SPACE IN THE FNB NAME FIELD WILL BE PADDED WITH SPACES. ; ; ; INPUT: R2 - INPUT STRING SIZE ; R3 - INPUT STRING ADDRESS ; R4 - FNB SEGMENT SIZE ; R5 - FNB SEGMENT ADDRESS ; 2(SP) - FLAG: 0 = NOT END OF INPUT STRING, NOT CLOSED QUOTES ; 1 = END OF INPUT STRING ; -1 = CLOSED QUOTES, BUT NOT END OF INPUT STRING ; ; OUTPUT: R2 - UPDATED INPUT STRING SIZE ; R3 - UPDATED INPUT STRING ADDRESS ; R4,R5 - ALTERED ; 2(SP) - UPDATED; SAME CODES AS ON INPUT ; ;- .ENABL LSB ANSMV2: TST 2(SP) ;TEST FLAG BNE 50$ ;NE = NO MORE INPUT; PAD WITH SPACES 10$: CMPB #'",(R3) ;EXAMINE CURRENT CHAR - DOUBLE QUOTE? BNE 20$ ;NO - MOVE IT INTO FNB DEC R2 ;YES- IS IT THE LAST CHAR IN STRING? BEQ 30$ ;YES- IT IS TERMINAL QUOTE - CLEAN UP INC R3 ;NO - INCR INPUT STRING POINTER... CMPB #'",(R3) ;...TO LOOK FOR ANOTHER QUOTE BEQ 20$ ;PAIR OF QUOTES - MOVE ONE INTO FNB DEC 2(SP) ;NOTE TERMINAL QUOTE, BUT NOT END OF STRING BR 50$ ;PAD REMAINING FNB BYTES WITH SPACES 20$: MOVB (R3)+,(R5)+ ;MOVE THE CURRENT CHAR INTO THE FNB DEC R4 ;DECREMENT COUNT OF OUTPUT BYTES REMAINING DEC R2 ;ADJUST INPUT STRING CHAR COUNT BEQ 30$ ;EQ - END OF INPUT TST R4 ;LOOK AT COUNT OF OUTPUT BYTES REMAINING BNE 10$ ;NE - MORE SPACE LEFT, PROCESS NEXT CHARACTER BR 60$ ;EQ - RETURN 2(SP) = 0, SINCE MORE INPUT EXISTS ANSMV1: INC R3 ;BUMP INPUT STRING POINTER PAST THE QUOTE CHAR DEC R2 ;ADJUST INPUT STRING CHAR COUNT BNE 10$ ;IF NOT AT END OF STRING, GET ANOTHER CHAR 30$: INC 2(SP) ;NOTE END OF INPUT; NO VERSION NUMBER FOLLOWS BR 50$ ;SEE IF WE NEED TO PAD THE FNB WITH SPACES 40$: MOVB #40,(R5)+ ;PAD REST OF THIS FDB SEGMENT WITH SPACES 50$: DEC R4 ;DECREMENT COUNT OF OUTPUT BYTES REMAINING BGE 40$ ;GE - MORE ROOM TO FILL 60$: RETURN ; .DSABL LSB .ENDC ;+ ; ; CKWILD - Check for special wild card construction. ; ; This routine checks for the new wild card matching construction. It ; converts "*" into "$" and "%" into "." for the ACP routine .MATNM. ; ; Inputs: ; R1 = The FNB address. ; R2 = The string address. ; R3 = The string size. ; ; Outputs: ; All registers are preserved. ; ; *** This routine added for edit (01). *** ;- CKWILD: CALL $SAVAL ; Save all registers. CLR R0 ; Clear wildcard found flag. 10$: CMPB #'*,(R2) ; Wildcard many characters ? BNE 20$ ; If NE, no. MOVB #'$,(R2) ; Yes, convert to dollar sign. BR 30$ ; Set special wildcard match. 20$: CMPB #'%,(R2) ; Wildcard single character ? BNE 40$ ; If NE, no. MOVB #'.,(R2) ; Yes, convert it to period. 30$: BIS #NB.WCH,N.STAT(R1) ; Set wildcard character match. INC R0 ; Show wildcard character found. 40$: INC R2 ; Point to the next character. SOB R3,10$ ; Loop until no more count. ; Set wildcard flag for file name or type. TST R0 ; Special wildcard(s) found ? BEQ 100$ ; If EQ, no. BIT #NB.TYP,N.STAT(R1) ; Have we processed the type ? BNE 50$ ; If NE, yes. BIS #NB.SNM,N.STAT(R1) ; No, set wildcard file name. BR 100$ ; And return ... 50$: BIS #NB.STP,N.STAT(R1) ; Set for wildcard file type. 100$: RETURN ; ; $END PARSFN ; .END