Scanning Directories (Reading Directory Entries)
OSGBPB 8 (often known as OS HeebieJeebie) scans the current directory and returns the entries.
Contents
OSGBPB 8 has the following entry and exit conditions. To call from BASIC you should
point X%
to a control block and set Y%=X%DIV256
.
On entry at &FFD1: A% 8 X%!1 Data address X%!5 Number of object names to read X%!9 Directory index, 0 to start On exit: X%?0 Directory cycle number X%!1 Updated data address X%!5 Number of object names /not/ read X%!9 Directory index for next call. The data block will hold the following information: &00 length of object name 1 (n) &01 object name 1 in ASCII characters &01+n length of object name 2 (m) &02+n object name 2 in ASCII characters &02+n+m etc...
Note that the directory index is an opaque value with only the value zero defined. You cannot and must not assume that it follows any particular sequence, for instance incrementing by one after each call. The only thing you can do with a nonzero value is pass it to another OSGBPB call. Some filing systems return the object names padded with trailing spaces, so you will need to strip those spaces if you want to append the names, such as when descending into a directory tree.
Reading directory entries
The following code will scan through a directory on any filing system and return the directory entries.
DIM ctrl% 31:REM Need at least 13 bytes for OSGBPB DIM name% 31:REM Need at least 12 bytes for directory entries X%=ctrl%:Y%=X%DIV256 :REM Point to control block ret%=0 :REM Return value idx%=0 :REM Directory index, starts at zero REPEAT X%!1=name% :REM Address in memory to read names to X%!5=1 :REM Fetch one directory entry X%!9=idx% :REM Directory index A%=8:CALL &FFD1 :REM OSGBPB call to read directory entries ret%=X%!5 :REM Number of entries not read idx%=X%!9 :REM Get directory index back IF ret%<>1 THEN PROCname :REM Directory entry returned UNTIL ret%=1 ...etc DEFPROCname :REM Extract object name name%?(1+?name%)=13 :REM Put <cr> terminator in f$=$(name%+1) :REM Fetch object name ...etc
Using the FileIO BASIC Library this can be considerably compressed to the following:
idx%=0:REPEAT:f$=FNgbpb8(idx%):idx%=X%!9:IF f$<>"" THEN .... UNTIL f$=""
The data block passed in X%!1
needs to be long enough to
receive the filenames read. Most filenames encountered on BBC systems are a
maximum of 10 characters long, so name%
needs to point to
at least 12 bytes - ten characters for the filename, one byte for the name
length and one byte for the <cr> terminator.
However, there is nothing that specifies that filenames are a maximum of ten
characters. Filenames can be anything up to 255 bytes long and it is
entirely down the the filing system what length names it can use. For
instance, DOSFS uses up to twelve character filenames, viz
"Filename.txt", and Win95FS can use almost unlimited filename lengths.
Strictly speaking, there should be 257 bytes available at the address
pointed to by X%!1
, but 32 bytes is a realistic
compromise.
Reading entries from all DFS directories
OSGBPB 8 reads the directory entries from the current directory. DFS implements single-character 'sideways' directories. The following code will run on all filing systems, and on DFS will scan through all the DFS directories. It uses the FileIO BASIC Library.
DIM ctrl% 31:REM Need at least 13 bytes for OSGBPB DIM name% 31:REM Need at least 12 bytes for directory entries X%=ctrl%:Y%=X%DIV256 :REM Point to control block dfs_all%=TRUE :REM TRUE to do all DFS directories dfs%=FNfile("$",5)<>2 :REM Test for DFS-like filing system dir%=0 IF dfs_all% THEN IF dfs% THEN dir%=ASC"!" :REM Start at dir "!" REPEAT IF dir% THEN OSCLI "Dir """+STRING$(1+(dir%=34),CHR$dir%)+""" idx%=0 :REM Directory index, starts at zero REPEAT f$=FNgbpb8(idx%):idx%=X%!9:IF f$<>"" THEN PROCname UNTIL f$="" IF dir%=97:dir%=0 :REM Loop for all directories IF dir% THEN dir%=dir%+1:IF dir%=ASC"""" OR dir%=ASC":" THEN dir%=dir%+1:REM Skip '"', ':' UNTIL dir%=0 IF dfs_all% THEN IF dfs% THEN OSCLI "Dir $" :REM Return to dir '$' ...etc DEFPROCname IFdir%:IFdir%<>36:f$=CHR$dir%+"."+f$ :REM Prepend with non-"$" dir. char ...etc
Tree Walking (Recursive Directory Scanning)
OSGBPB 8 can 'walk' a directory tree, descending subdirectories and returning from them with the following code, written using the FileIO BASIC library.
DIM ctrl% 31,name% 31:X%=ctrl%:Y%=X%DIV256 DEFPROCScan LOCAL idx%,f$ REPEAT:f$=FNgbpb8(idx%):idx%=X%!9:IF f$<>"":PROCObject UNTIL f$="" ENDPROC : DEFPROCObject LOCAL type% type%=FNfile(f$,5) REM Process object f$ IF type%=2:OSCLI "Dir "+f$:PROCScan:OSCLI "Dir ^" ENDPROC
Note that as 6502 BASIC only implements a 20-deep REPEAT stack, this will only descend to a maximum depth of 20 subdirectories before getting a "Too many REPEATs" error. To avoid this a program would have to maintain its own recursion stack.
See Also
Jgharston 14:34, 4 January 2008 (UTC)