; m4wild/asm ; ; Build a list of filenames given a list of arbitrary names ; pointed to by HL. Wild card processing is done here. ; ; The resulting blank separated list is returned in HL. The ; number of names put into the buffer is indicated by the ; count in FILECNT. This is a byte valued count, so 255 is ; the maximum number possible. ; BUILDF EQU $ LD (SRCPTR),HL ;Save the source input pointer LD HL,FILEBUFF ;Set the pointer to the matches LD (FBPTR),HL ;buffer where all matches go XOR A ;Set number of files found to 0 LD (FILECNT),A BF_0 EQU $ LD HL,(SRCPTR) ;Get the input string LD BC,0 ;Get zero LD (SYSFLAG),BC ;No system files LD (INVFLAG),BC ;No invisible files XOR A ;Reset response values LD (INVRESP),A LD (SYSRESP),A LD A,' ' BF_A IFANOT (HL),BF_B INC HL JR BF_A ; BF_B LD DE,PARMS ;Get the parse table CALL XPARAM ;Do @PARAM SVC JR Z,BF_D ;Jump if parse ok BF_C STROUT BADPARM ;Print error message JP KERMIT ;Abort! ; BF_D LD A,(SYSRESP) ;Get the system response AND 0A0H ;Valid? JR NZ,BF_C ;Jump if not LD A,(INVRESP) ;Check invisble flag AND 0A0H ;Valid? JR NZ,BF_C ;Jump if not LD A,' ' ;Get a space to compare with BF_E IFANOT (HL),BF_F ;Jump if not space INC HL JR BF_E ; BF_F LD B,32 ;Move 32 characters, MAX LD DE,TFBUF ;Get the temporary buffer BF_1 LD A,(HL) ;Get a character IFALT ' '+1,BF_2 ;Jump if at end of this filename CALL CPTAL ;Capitalize it LD (DE),A ;Save the new character INC DE ;Increment the pointers INC HL DJNZ BF_1 ;Loop until done BF_2 XOR A ;Terminate the string with a zero LD (DE),A ;Put in a terminator BF_3 LD A,(HL) ;Get the next character IFAGE ' '+1,BF_4 ;Jump if not separator IFA CR,BF_4 ;Jump if end of string INC HL ;Skip the separator JR BF_3 ;Loop on ; BF_4 LD (SRCPTR),HL ;Save the next string pointer LD A,32 ;Get the max length SUB B ;Compute length LD (FNLEN),A ;Save it JP Z,BF_18 ;Exit if no more names LD A,1 ;Initially check all drives LD (MOREDRV),A ;Set the flag DEC DE ;Check if '/' last character EX DE,HL ;Put it in HL LD A,(HL) ;Get the character IFANOT '/',BF_5 ;Is it a '/' LD (HL),0 ;Remove the trailing slash BF_5 LD HL,TFBUF ;Look for a drive specification LD A,(FNLEN) ;Get the length LD C,A ;Make BC a 16 bit copy of A LD B,0 ADD HL,BC ;Compute end of name plus one DEC HL ;Backup to possible drive number DEC C ;Decrement the counter JR Z,BF_7 ;Jump if no characters left DEC HL ;Backup to possible ':' separator DEC C ;Decrement counter JR Z,BF_7 ;Jump no characters left LD A,(HL) ;Get a possible ':' IFANOT ':',BF_7 ;Jump if not drive spec LD (HL),0 ;Terminate with no drive number INC HL ;Point back at drive number LD A,(HL) ;Get the drive number LD HL,FNLEN ;Change the length DEC (HL) DEC (HL) SUB '0' ;Make the drive number binary LD C,A ;Save the drive to check XOR A LD (MOREDRV),A ;No more drives to check JR BF_8 ; BF_7 EQU $ XOR A ;Zero A LD C,A ;Set drive number to zero BF_8 EQU $ PUSH BC ;Save the current drive number CALL XCHKDRV ;Check this drive JP NZ,BF_17 ;Jump if drive not ready LD HL,DIRSPEC ;Get the source of 'DIR/SYS' LD DE,DIRFCB ;Put it here LD BC,DLEN ;Move this many characters LDIR ;Copy the name POP BC ;Get the drive number PUSH BC ;Put it back LD A,C ;Put it into A ADD A,'0' ;Make it printable LD (DIRDRV),A ;Set the drive number LD (SDIRDRV),A ;Save the current drive LD A,CR ;Get a EOL marker LD (DIRDRV+1),A ;Put in a terminator LD HL,DIRBUFF ;Get the buffer LD B,0 ;LRECL = 256 LD DE,DIRFCB ;Get the FCB CALL XOPEN ;Try to open the directory JP NZ,BF_19 ;Jump on open error LD DE,DIRFCB ;Get the FCB CALL XSKIP ;Skip HIT and GAT CALL XSKIP BF_9 EQU $ LD HL,DIRBUFF ;Get the data buffer LD DE,DIRFCB ;Get the FCB CALL XREAD ;Read a record JP NZ,BF_15 ;Jump if can't read anymore LD B,8 ;Number of dir entries LD HL,DIRBUFF ;Get the starting data BF_10 PUSH BC ;Save the counter BIT 4,(HL) ;Check for used directory record JR Z,BF_12 ;Jump entry not in use BIT 7,(HL) ;Check if FPDE JR NZ,BF_12 ;Jump if extent or other LD A,(SYSFLAG) ;Check is system file valid IFNZ BF_10A ;Jump if system OK BIT 6,(HL) ;Is it a system file JR NZ,BF_12 ;Skip it if it is BF_10A LD A,(INVFLAG) ;Is invisible file valid? IFNZ BF_10B ;Jump if invisble ok (no check) BIT 3,(HL) ;Is the file invisible? JR NZ,BF_12 ;Skip it if it is BF_10B LD DE,TFBUF ;Get the pattern to match LD A,1 LD (HASWILD),A ;Set wild cards present flag CALL ISWILD ;Check if it really is JR Z,BF_11 ;Jump if there are wild cards XOR A LD (HASWILD),A ;Reset has wild cards flag BF_11 EQU $ CALL MATCH ;See if it matches JR NZ,BF_12 CALL COPYFILE ;Copy it if it matches LD A,(HASWILD) ;Check if should check others IFNZ BF_12 ;Jump if wild, might be more POP BC ;Otherwise, no wild, so keep only POP BC ;the first match as in TRSDOS's JP BF_0 ;normal drive search algorithm ; BF_12 LD BC,32 ;Get the length of a DIR record ADD HL,BC ;Point to next POP BC ;Restore the number of entries DJNZ BF_10 ;Decrement and loop if not end JR BF_9 ;Try next drive ; ; Control comes to here on an error in the call to @READ. Check ; to make sure it is EOF, and print an error message if not. ; BF_15 EQU $ CP 28 ;Check for end of file JR Z,BF_16 ;Jump if end of file CALL XERROR0 ;Print the error message LD DE,DIRFCB ;Close the open file CALL XCLOSE JP KERMIT ;Abort completely ; BF_16 EQU $ LD DE,DIRFCB ;Close the directory CALL XCLOSE ;Closed JP NZ,BFCLSERR ;Jump if close error BF_17 EQU $ POP BC ;Restore drive number INC C ;Next drive LD A,8 ;Get max drive number (plus 1) CP C ;Get next name if no more drvs JP Z,BF_0 ;Go get next name if end LD A,(MOREDRV) ;See if should check other drvs OR A ;Check for zero JP NZ,BF_8 ;If set, then no drive spec so go JP BF_0 ;Get the next filename in list ; ; At the end of processing, we update the end of the list of names, ; and return the pointer to the start of the list in HL. ; BF_18 EQU $ LD HL,(FBPTR) ;Get the pointer LD (HL),CR ;Terminate the string LD HL,FILEBUFF ;Return the start of the list RET ; ; Control comes to here on a directory open error. Print the error ; message, and then go check next drive. ; BF_19 EQU $ CALL XERROR0 JR BF_17 ; ; Control comes to here if CLOSE on DIR/SYS fails. ; BFCLSERR EQU $ CALL XERROR0 ;Print the error message JP KERMIT ;Return to command level ; ; Do a wild card match on the 2 strings pointed to by ; HL, and DE. DE points at the pattern containing possible ; wild card characters. HL points at the start of a TRSDOS ; complete directory record. HL must be moved to the start ; of the filename. The filename HL points to has up to 11 ; characters in it. The first 8 are the filename, the last ; 3 are the extension. Both are left justified within their ; respective fields, with blanks as fill. ; MATCH EQU $ PUSH BC ;Save BC PUSH HL ;Save HL PUSH DE ;Save DE LD BC,5 ;Move HL to filename field ADD HL,BC ;Move the pointer ; ; We must now convert the filename in the directory record ; to have the '/' in it. I.E. the entry may look like: ; ; DIR+5 DIR+15 ; +-+-+-+-+-+-+-+-+-+-+-+ ; |F|I|L|E| | | | |C| | | ; +-+-+-+-+-+-+-+-+-+-+-+ ; ; So we must make the name be FILE/C ; LD DE,COMPNAME ;Get the destination LD BC,0B30H ;Number of characters to move ; ; Note that C has a big enough value in it to keep the LDI ; below from changing B which is the loop counter. ; MATCH_1 LD A,(HL) ;See if at the end of name INC HL ;Point a head in case ' ' is next IFA ' ',MATCH_3 ;Skip spaces if at one DEC HL ;Move back, valid character LD A,B ;Check if time for '/' IFANOT 3,MATCH_2 ;If B is 3, then put in a '/' LD A,'/' ;Get the '/' LD (DE),A ;Put it in the destination INC DE ;Point to next position MATCH_2 LDI ;Move the current character MATCH_3 DJNZ MATCH_1 ;Loop until all moved XOR A ;Put in a terminating NULL LD (DE),A POP DE ;Get the wild card pattern back PUSH DE ;Save it again LD HL,COMPNAME ;Get the name to compare against ; ; Now the matching process starts ; ; From C-Kermit's wild carding, this is the function match() ; HL is string, DE is pattern. There are some things different ; here, but this is mostly a line by line translation. ; ; LD A,(HL) ;Check for null strings IFZ NOMATCH ;Return if no match LD A,(DE) ;Check for null pattern IFZ NOMATCH ;Return if no match ; LD (SPAT),DE ;Save current pattern spot LD (SSTR),HL ;Save current string spot LD HL,0 ;Reset the 2 pointers LD (PSAVE),HL LD (SSAVE),HL ; MATCH_6 EQU $ LD HL,(SSTR) ;Get the pointer LD A,(HL) ;Check for end of str IFZ MATCH_9 ;Jump if at the end ; LD DE,(SPAT) ;Ge&t the pattern pointer LD A,(DE) ;Get the character CP (HL) ;Do the characters match JR NZ,MATCH_9 INC HL ;Increment the pointers INC DE LD (SPAT),DE ;Save the new values LD (SSTR),HL JR MATCH_6 ;Loop until done ; MATCH_9 EQU $ LD A,(HL) ;Check if a match was found IFNZ MATCH_10 ;Jump if not at end LD DE,(SPAT) ;Get the pattern pointer LD A,(DE) ;Check if at end of pattern IFNZ MATCH_10 ;Jump if not at end MATCHED CP A ;Set Z status POP DE ;Restore the saved registers POP HL POP BC RET ;Return the matched status ; MATCH_10 EQU $ LD DE,(SPAT) ;Get the pattern pointer LD A,(DE) ;Get the pattern character IFANOT '$',MATCH_12 ;Jump if not '$' INC HL ;++sstr INC DE ;++spat LD (SSTR),HL LD (SPAT),DE JR MATCH_20 ;Skip else case ; MATCH_12 EQU $ IFANOT '*',MATCH_15 ;Jump if not '*' INC DE ;Move pattern forward LD (SPAT),DE ;Save the new value LD (PSAVE),DE LD (SSAVE),HL ;Match Zero characters JR MATCH_20 ; MATCH_15 EQU $ LD HL,(SSAVE) ;Get the saved position LD A,H ;Check if null pointer OR L JR Z,MATCH_17 ;Jump if pointer NULL LD A,(HL) ;Check if end of string IFZ MATCH_17 ;Jump if at the end INC HL LD (SSTR),HL ;sstr = ++ssave; LD (SSAVE),HL ;Save new value LD HL,(PSAVE) LD (SPAT),HL ;spat = psave; JR MATCH_20 ; MATCH_17 EQU $ NOMATCH LD A,1 ;Set NZ status CP 0 POP DE ;Restore the saved registers POP HL POP BC RET ;Return to caller ; MATCH_20 EQU $ JP MATCH_6 ;Loop ; ; This function takes the string in the COMPNAME data area, and ; appends it to the list of filenames already collected. ; COPYFILE EQU $ PUSH DE ;Save the regs PUSH HL PUSH BC LD HL,COMPNAME ;Get name matched LD DE,(FBPTR) ;Get the current position PUSH DE ;Save address to print from COPYF_1 EQU $ LD A,(HL) ;Check for end of string IFZ COPYF_3 ;Jump if at the end LDI ;Move a character PUSH HL ;Save HL PUSH DE ;Copy DE to HL POP HL LD BC,FILEBUFF+BUFFSIZE ;Get the end of buffer OR A ;Reset the carry SBC HL,BC ;Check for too far POP HL ;Restore HL back JR NZ,COPYF_1 ;Loop if not too far STROUT OUTOFSTR ;Print a message JP KERMIT ; COPYF_3 EQU $ PUSH DE POP HL ;Copy DE to HL LD BC,FILEBUFF+BUFFSIZE-4 ;Get max for following OR A SBC HL,BC ;Compute remaining JR NZ,COPYF_5 COPYF_4 STROUT OUTOFSTR ;Print message JP KERMIT ;Abort ; COPYF_5 LD A,':' ;Put in the drive delimiter LD (DE),A ;Store it INC DE ;Point ahead one LD A,(SDIRDRV) ;Get the drive number LD (DE),A ;Store it INC DE ;Point ahead one more LD A,' ' ;Add a space at the end LD (DE),A ;Store it INC DE ;Point ahead LD A,EOS ;Get the end of string character LD (DE),A ;Put in a terminator LD (FBPTR),DE ;Save the new pointer LD HL,FILECNT ;Increment the number of files LD A,(HL) ;Get the current count PUSH AF ;Save the count INC (HL) ;Add one to counter IFNZ COPYF_6 ;Jump if not first LD A,(LOGNAMES) ;Check if should print anything IFZ COPYF_6 ;Jump if not STROUT FILESFND ;Print the message only once COPYF_6 EQU $ POP AF IFA 255,COPYF_4 ;Jump if not too many names POP DE ;Get the string LD A,(LOGNAMES) ;Check if should print anything IFZ COPYF_7 ;Jump if not CALL PRTSTR ;Print the string CALL NEWLIN ;Get a new line COPYF_7 EQU $ POP BC ;Restore the registers POP HL POP DE RET ;Return to caller ; ; Check if any wild card characters are in the string pointed ; to by HL. Return Z status if there are, NZ if there are not ; ISWILD EQU $ PUSH HL ;Save the strings address PUSH DE EX DE,HL ISWILD_1 LD A,(HL) ;Get a character IFZ ISWILD_2 ;End of string? Jump if so IFA '$',ISWILD_4 ;Jump if it is a wild card IFA '*',ISWILD_4 ;Jump if it is a wild card INC HL ;Point to next character JR ISWILD_1 ;Loop until there ; ISWILD_2 EQU $ INC A ;Set NZ ISWILD_3 POP DE ;Restore the registers POP HL RET ;Return to caller ; ISWILD_4 EQU $ CP A ;Set Z status JR ISWILD_3 ;Return ; end of file