home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
trs80model4.tar.gz
/
trs80model4.tar
/
m4wild.asm
< prev
next >
Wrap
Assembly Source File
|
1986-10-22
|
13KB
|
449 lines
; 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