commit d167bdaa7aa3d2ff0398c5dd10b4cd4bb81f6225
parent f966805f2daffa8b6c7d5902a354125778090f1c
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 24 Aug 2022 14:00:41 -0400
Make Filesystem :iter take a callback word and remove :next
The previous system didn't allow recursion, which is needed in many cases.
Adding recursion support to a :iter/:next system would make it heavier than it
should. A callback word works fine. I hope...
Diffstat:
6 files changed, 46 insertions(+), 67 deletions(-)
diff --git a/fs/fs/fat.fs b/fs/fs/fat.fs
@@ -185,8 +185,8 @@ $e5 const DIRFREE
r@ FATLO :getdirentry ( dirent ) DIRFREE swap c! r> writecursector ;
: _patchFS ( fs -- )
- ['] fatinfo over 12 + ! ['] fatopen over 16 + ! ['] fatnewfile over 28 + !
- ['] fatnewdir over 32 + ! ['] fatremove over 36 + ! 1 swap to FATLO flags ;
+ ['] fatinfo over 12 + ! ['] fatopen over 16 + ! ['] fatnewfile over 24 + !
+ ['] fatnewdir over 28 + ! ['] fatremove over 32 + ! 1 swap to FATLO flags ;
: :mountvolume ( drv -- fs ) FATLO :mountvolume dup _patchFS ;
bootfs 12 + @ ' abort = [if] bootfs _patchFS [then]
diff --git a/fs/fs/fatlo.fs b/fs/fs/fatlo.fs
@@ -241,20 +241,15 @@ extends File struct[ FATFile
]struct
extends _FAT struct[ FATLO
- 0 value _dirent
- : :next ( self -- id-or-0 )
- _dirent not if abort" invalid iterator" then >r
- DirEntry SZ to+ _dirent _dirent r@ _FAT :)buf = if
- r@ _FAT :nextsector? not if
- rootdirentry( to _dirent else \ parses as "lastentry"
- r@ _FAT :buf( to _dirent then then
- _dirent DirEntry :lastentry? if rdrop 0 to _dirent 0 else
- _dirent DirEntry :iterable? if _dirent r> _FAT :getid else r> :next then
- then ;
-
- : :iter ( dirid self -- id-or-0 ) >r
- r@ _FAT :getdirentry r@ _FAT :readdir
- r@ _FAT :buf( DirEntry SZ - to _dirent r> :next ;
+ : :iter ( w dirid self -- id-or-0 ) >r \ V1=self
+ V1 _FAT :getdirentry V1 _FAT :readdir >r ( ) \ V2=w
+ V1 _FAT :buf( begin ( a )
+ dup DirEntry :lastentry? not while ( a )
+ dup DirEntry :iterable? if dup V1 _FAT :getid V1 V2 execute then ( a )
+ DirEntry SZ + dup V1 _FAT :)buf = if
+ drop V1 _FAT :nextsector? not if
+ rootdirentry( ( parses as "lastentry" ) else V1 _FAT :buf( then then
+ repeat ( a ) drop rdrop rdrop ;
: :child ( dirid name self -- id-or-0 ) >r
fnbuf! r@ _FAT :getdirentry r@ _FAT :readdir r@ _FAT :findindir
@@ -273,8 +268,8 @@ extends _FAT struct[ FATLO
: :mountvolume ( drv -- fs )
align4 here >r dup , ( drv R:fs ) 0 ( flags ) ,
- ['] :child , ['] abort , ['] :fatopen , ['] :iter , ['] :next , ['] abort ,
- ['] abort , ['] abort ,
+ ['] :child , ['] abort , ['] :fatopen , ['] :iter , ['] abort , ['] abort ,
+ ['] abort ,
0 , 0 , 0 , 0 , ( drv )
\ At this point, "here" points to the FAT-header-to-be. Read the first sector
\ directly in "here": we'll have the header right here!
diff --git a/fs/sys/file.fs b/fs/sys/file.fs
@@ -35,11 +35,8 @@ struct[ Path
r@ id swap r@ fs Filesystem :newfile ( id ) r> fs swap :new ;
: :newdir ( name self -- path ) >r
r@ id swap r@ fs Filesystem :newdir ( id ) r> fs swap :new ;
- : :iter ( self -- path ) >r
- r@ id r@ fs Filesystem :iter ( id ) r> fs swap :new ;
- : :next ( self -- path-or-0 ) >r
- r@ fs Filesystem :next ( id )
- dup if r> fs swap :new else rdrop then ;
+ : :iter ( w self -- ) >r
+ r@ id r> fs Filesystem :iter ( id ) ;
: :remove ( self -- ) dup id swap fs Filesystem :remove ;
: :root ( self -- path ) fs 0 :new ;
@@ -82,11 +79,8 @@ struct[ Path
_src size _src :readbuf ?dup while ( a n ) _dst :self IO :write repeat
_dst :close _src :close ;
- : :listdir ( self -- ) >r
- r@ :iter begin ( path-or-0 ) ?dup while
- :info FSInfo name stype nl>
- r@ :next repeat
- rdrop ;
+ : _ ( id fs -- ) Filesystem :info FSInfo name stype nl> ;
+ : :listdir ( self -- ) ['] _ swap :iter ;
]struct
Path _curpath structbind Path curpath
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -258,7 +258,6 @@ struct[ Filesystem
smethod :info
smethod :open
smethod :iter
- smethod :next
smethod :newfile
smethod :newdir
smethod :remove
diff --git a/posix/glue.fs b/posix/glue.fs
@@ -1,13 +1,11 @@
: _ doer ' , does> nip @ execute ;
_ _:child _fchild _ _:open _fopen _ _:info _finfo
-_ _:iter _fiter _ _:next _fnext
create _POSIXFS
0 , 0 ,
' _:child ,
' _:info ,
' _:open ,
- ' _:iter ,
- ' _:next ,
+ ' _fiter ,
' abort ,
' abort ,
' abort ,
diff --git a/posix/vm.c b/posix/vm.c
@@ -872,43 +872,36 @@ static void FINFO() { // op: 64
memcpy(&vm.mem[dst+13], name, strlen(name));
}
-static dword iterid = 0;
-static DIR *dirp = NULL;
-
-static void FNEXT() { // op: 65
+// ( w id self -- )
+static void FITER() { // op: 65
+ DIR *dirp;
struct dirent *d;
+ dword self = ppop();
+ dword fsid = ppop();
+ dword w = ppop();
+ int baselen;
char path[MAXPATHSZ] = {0};
- dword res;
- if (!dirp) {
- printf("Calling next without an iter first!");
- vm.PC = gd(ABORT);
- return;
- }
- do {
- d = readdir(dirp);
- } while (d && ((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0)));
- if (!d) {
- ppush(0);
- return;
- }
- strcpy(path, getpathfromid(iterid));
- strcat(path, "/");
- strcat(path, d->d_name);
- res = findpath(path);
- if (!res) {
- while (fsids[++res][0]);
- strcpy(fsids[res], path);
- }
- ppush(res);
-}
-
-static void FITER() { // op: 66
- iterid = ppop();
- char *path = getpathfromid(iterid);
- if (dirp) closedir(dirp);
+ strcpy(path, getpathfromid(fsid));
dirp = opendir(path);
if (dirp) {
- FNEXT();
+ strcat(path, "/");
+ baselen = strlen(path);
+ while(1) {
+ do {
+ d = readdir(dirp);
+ } while (d && ((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0)));
+ if (!d) break;
+ strcpy(&path[baselen], d->d_name);
+ fsid = findpath(path);
+ if (!fsid) {
+ while (fsids[++fsid][0]);
+ strcpy(fsids[fsid], path);
+ }
+ ppush(fsid);
+ ppush(self);
+ callword(w);
+ }
+ closedir(dirp);
} else {
printf("Couldn't open dir %s\n", path);
vm.PC = gd(ABORT);
@@ -965,7 +958,7 @@ static void (*ops[OPCNT])() = {
RSHIFT, LITN, EXECUTEWR, EXITWR, MOVE, MOVEWR, RTYPE, WNF,
STACKCHK, MAYBEWORD, WORD, PARSE, REQ, FIND, APOS, COMPILING,
SWR, STARTCOMP, STOPCOMP, RUNWORD, NULL, NULL, NULL, NULL,
- FCHILD, FOPEN, FREADBUF, FCLOSE, FINFO, FNEXT, FITER, NULL,
+ FCHILD, FOPEN, FREADBUF, FCLOSE, FINFO, FITER, NULL, NULL,
MOUNTDRV, DRVRD, DRVWR};
static char *opnames[OPCNT] = {
@@ -981,7 +974,7 @@ static char *opnames[OPCNT] = {
"rshift", "litn", "execute,", "exit,", "move", "move,", "rtype", "(wnf)",
"stack?", "maybeword", "word", "parse", "[]=", "find", "'", "compiling",
",\"", "]", "[", "runword", NULL, NULL, NULL, NULL,
- "_fchild", "_fopen", "_freadbuf", "_fclose", "_finfo", "_fnext", "_fiter", NULL,
+ "_fchild", "_fopen", "_freadbuf", "_fclose", "_finfo", "_fiter", NULL, NULL,
"_mountdrv", "_drv@", "_drv!"};
static void oprun1() { // run next op