1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; UrForth level
1: self
-hosting
32-bit Forth compiler
3 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 code: getdents ( dentaddr dentsize fd -- errcode // bytesread // 0 )
20 2 cells
2+ 256 + constant #dent
24 8 constant dent
-reclen
;; 2 bytes
25 10 constant dent
-namez
31 : open
-dir
( c
-addr u
-- dirfd wior
)
32 [ os
:O
-RDONLY os
:O
-DIRECTORY or
] literal
0 os
:open dup
-if err
-file
-not
-found
else 0 endif
35 : close
-dir
( dirfd
-- wior
)
36 os
:close
if err
-file
-read-error
else 0 endif
39 \ calls xt
for each directory entry except
"." and
".."
40 \ xt
: ( nameaddr namecount inode
-- stopflag
)
41 \ name buffer is temporary
, you should not store its address anywhere
42 : foreach
-dir
( dirfd xt
-- eflag wior
)
43 over
-if 2drop
0 err
-file
-read-error exit
endif
44 os
:#dent ralloca nrot
>r
2>r
( xt buf
-dirfd
)
46 2r@ os
:#dent swap os
:getdents
47 dup
-if drop
2rdrop rdrop
0 err
-file
-read-error os
:#dent rdealloca exit
endif
48 dup ifnot
2rdrop rdrop
0 os
:#dent rdealloca exit
endif
49 2r@ drop swap
( buf bleft | xt buf
-dirfd
)
50 2r
> r@ nrot
2>r
>r
( buf bleft | xt buf
-dirfd xt
)
52 over dup os
:dent
-ino
+ @ swap os
:dent
-namez
+ zcount
( buf bleft uno addr count | xt buf
-dirfd xt
)
53 2dup
2dup
" ." s
= nrot
" .." s
= or
if 2drop drop
54 else ( buf bleft uno addr count | xt buf
-dirfd xt
)
55 \ rot r@ execute
( buf bleft stopflag | xt buf
-dirfd xt
)
56 rot r@
2rot
2>r execute
2r
> rot
57 ?dup
if nrot
2drop
2rdrop
2rdrop
0 os
:#dent rdealloca exit
endif
59 over os
:dent
-reclen
+ w@
/string
60 dup
1- -until
2drop rdrop
64 \ inode is zero when we hit
end-of
-dir
(and the name is empty
, i
.e
. count is
0)
65 : (read-dir
) ( addr maxcount dirfd
-- addr count inode wior
)
66 dup
-if 2drop
0 0 err
-file
-read-error exit
endif
68 os
:dent
-namez
1+ 0 begin
( addr maxcount dirfd curlen dummy | buf
)
69 drop
2dup r@ swap rot os
:getdents dup
-22 ( EINVAL
) =
71 swap
1+ swap over os
:#dent
>
73 dup
-if nip
0 swap err
-file
-read-error exit
endif
74 if 0 max over swap r@ os
:dent
-namez
+ zcount rot min dup
>r rot swap move r
>
75 r@ os
:dent
-ino
+ @
1 umax
0
76 else drop
0 0 0 endif ;; no more
77 rdrop os
:#dent rdealloca
80 ;; this ignores
"." and
".."
81 \ inode is zero when we hit
end-of
-dir
(and the name is empty
, i
.e
. count is
0)
82 : read-dir
( addr maxcount dirfd
-- addr count inode wior
)
83 >r begin
2dup r@
(read-dir
) dup not
-while
84 2over
2dup
" ." s
= nrot
" .." s
= or
while