change in pattern arguments of diskio.list_files() and lf_start_list(): you can now use a simple pattern with ? and * wildcards

This commit is contained in:
Irmen de Jong 2020-12-30 23:34:00 +01:00
parent b4931c9a1f
commit 89230ade7a
6 changed files with 96 additions and 28 deletions

View File

@ -60,8 +60,6 @@ io_error:
; internal variables for the iterative file lister / loader
ubyte list_suffixmatch
ubyte list_pattern_size
ubyte list_skip_disk_name
uword list_pattern
uword list_blocks
@ -71,12 +69,12 @@ io_error:
; ----- get a list of files (uses iteration functions internally -----
sub list_files(ubyte drivenumber, uword pattern, ubyte suffixmatch, uword name_ptrs, ubyte max_names) -> ubyte {
sub list_files(ubyte drivenumber, uword pattern_ptr, uword name_ptrs, ubyte max_names) -> ubyte {
; -- fill the array 'name_ptrs' with (pointers to) the names of the files requested.
uword names_buffer = memory("filenames", 512)
uword buffer_start = names_buffer
ubyte files_found = 0
if lf_start_list(drivenumber, pattern, suffixmatch) {
if lf_start_list(drivenumber, pattern_ptr) {
while lf_next_entry() {
@(name_ptrs) = lsb(names_buffer)
name_ptrs++
@ -96,18 +94,13 @@ io_error:
; ----- iterative file lister functions -----
sub lf_start_list(ubyte drivenumber, uword pattern, ubyte suffixmatch) -> ubyte {
; -- start an iterative file listing with optional prefix or suffix name matching.
sub lf_start_list(ubyte drivenumber, uword pattern_ptr) -> ubyte {
; -- start an iterative file listing with optional pattern matching.
; note: only a single iteration loop can be active at a time!
lf_end_list()
list_pattern = pattern
list_suffixmatch = suffixmatch
list_pattern = pattern_ptr
list_skip_disk_name = true
iteration_in_progress = true
if pattern==0
list_pattern_size = 0
else
list_pattern_size = strlen(pattern)
c64.SETNAM(1, "$")
c64.SETLFS(12, drivenumber, 0)
@ -177,15 +170,9 @@ io_error:
void c64.CHRIN()
if not list_skip_disk_name {
if list_pattern_size {
; do filename matching
if list_suffixmatch
rightstr(list_filename, filename, list_pattern_size)
else
leftstr(list_filename, filename, list_pattern_size)
if strcmp(filename, list_pattern)==0
return true
} else
if not list_pattern
return true
if prog8_lib.pattern_match(list_filename, list_pattern)
return true
}
list_skip_disk_name = false

View File

@ -7,4 +7,76 @@
prog8_lib {
%asminclude "library:prog8_lib.asm", ""
%asminclude "library:prog8_funcs.asm", ""
asmsub pattern_match(str string @AY, str pattern @R0) clobbers(Y) -> ubyte @A {
%asm {{
; pattern matching of a string.
; Input: cx16.r0: A NUL-terminated, <255-length pattern
; AY: A NUL-terminated, <255-length string
;
; Output: A = 1 if the string matches the pattern, A = 0 if not.
;
; Notes: Clobbers A, X, Y. Each * in the pattern uses 4 bytes of stack.
;
; see http://6502.org/source/strings/patmatch.htm
str = P8ZP_SCRATCH_W1
stx P8ZP_SCRATCH_REG
sta str
sty str+1
lda cx16.r0
sta modify_pattern1+1
sta modify_pattern2+1
lda cx16.r0+1
sta modify_pattern1+2
sta modify_pattern2+2
jsr _match
lda #0
adc #0
ldx P8ZP_SCRATCH_REG
rts
_match
ldx #$00 ; x is an index in the pattern
ldy #$ff ; y is an index in the string
modify_pattern1
next lda $ffff,x ; look at next pattern character MODIFIED
cmp #'*' ; is it a star?
beq star ; yes, do the complicated stuff
iny ; no, let's look at the string
cmp #'?' ; is the pattern caracter a ques?
bne reg ; no, it's a regular character
lda (str),y ; yes, so it will match anything
beq fail ; except the end of string
reg cmp (str),y ; are both characters the same?
bne fail ; no, so no match
inx ; yes, keep checking
cmp #0 ; are we at end of string?
bne next ; not yet, loop
found rts ; success, return with c=1
star inx ; skip star in pattern
modify_pattern2
cmp $ffff,x ; string of stars equals one star MODIFIED
beq star ; so skip them also
stloop txa ; we first try to match with * = ""
pha ; and grow it by 1 character every
tya ; time we loop
pha ; save x and y on stack
jsr next ; recursive call
pla ; restore x and y
tay
pla
tax
bcs found ; we found a match, return with c=1
iny ; no match yet, try to grow * string
lda (str),y ; are we at the end of string?
bne stloop ; not yet, add a character
fail clc ; yes, no match found, return with c=0
rts
}}
}
}

View File

@ -58,7 +58,7 @@ diskio
------
Provides several routines that deal with disk drive I/O, such as:
- list files on disk, optionally filtering by prefix or suffix
- list files on disk, optionally filtering by a simple pattern with ? and *
- show disk directory as-is
- display disk drive status
- load and save data from and to the disk

View File

@ -38,7 +38,7 @@ main {
; this only works in the emulator V38 with an sd-card image with the files on it.
str[40] filename_ptrs
ubyte num_files = diskio.list_files(8, 0, false, &filename_ptrs, len(filename_ptrs))
ubyte num_files = diskio.list_files(8, 0, &filename_ptrs, len(filename_ptrs))
if num_files {
while num_files {
num_files--

View File

@ -10,8 +10,8 @@ main {
void diskio.directory(8)
txt.chrout('\n')
if diskio.lf_start_list(8, "nier", false) {
txt.print("\nfiles starting with 'nier':\n")
if diskio.lf_start_list(8, "cub*") {
txt.print("\nfiles starting with 'cub':\n")
while diskio.lf_next_entry() {
txt.print(diskio.list_filename)
txt.print(" ")
@ -23,8 +23,8 @@ main {
txt.print("error\n")
}
if diskio.lf_start_list(8, "pcx", true) {
txt.print("\nfiles ending with 'pcx':\n")
if diskio.lf_start_list(8, "*gfx") {
txt.print("\nfiles ending with 'gfx':\n")
while diskio.lf_next_entry() {
txt.print(diskio.list_filename)
txt.print(" ")
@ -36,7 +36,7 @@ main {
txt.print("error\n")
}
if diskio.lf_start_list(8, 0, false) {
if diskio.lf_start_list(8, 0) {
txt.print("\nfirst 10 files:\n")
ubyte counter=0
while counter < 10 and diskio.lf_next_entry() {

View File

@ -10,6 +10,7 @@ main {
draw_lines()
draw_circles()
draw_rects()
; graphics.disable_bitmap_mode()
; test_stack.test()
@ -18,6 +19,14 @@ main {
}
}
sub draw_rects() {
graphics.rect(220,10,80,10)
graphics.rect(20,180,80,10)
graphics.fillrect(220,30,80,10)
graphics.fillrect(20,160,80,10)
}
sub draw_circles() {
ubyte xx
for xx in 3 to 7 {