Scanning a Directory (Reading Directory Entries) OSGBPB 8 ========================================================= OSGBPB 8 (often known as OS HeebieJeebie) scans the current directory and returns the entries. It 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. 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 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 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. Realistically there should be at least 256 bytes available at the address pointed to by X%!1. 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. DIM ctrl% 31:REM Need at least 13 bytes for OSGBPB DIM name% 31:REM Need at least 12 bytes for directory entries dfs_all%=TRUE :REM TRUE to do all DFS directories dir%=0 IF dfs_all% THEN IF FNfs=4 THEN dir%=ASC"!":REM Start at dir "!" REPEAT IF dir% THEN OSCLI "Dir """+STRING$(1+(dir%=34),CHR$dir%)+""" 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 IF dir%=95:dir%=0 :REM Loop for all directories IF dir% THEN dir%=dir%+1:IF dir%=ASC":" THEN dir%=dir%+1:REM Skip ':' UNTIL dir%=0 ...etc DEFPROCname name%?(1+?name%)=13 :REM Put terminator in f$=$(name%+1) :REM Fetch object name IFdir%:IFdir%<>36:f$=CHR$dir%+"."+f$ :REM Prepend with non-"$" dir. char ...etc This code requires the following function to find the current filing system: DEFFNfs:LOCAL A%,X%,Y%,E%:=(USR&FFDA)AND&FF Tree Walking ------------ OSGBPB 8 can 'walk' a directory tree, descending subdirectories and returning from them with the following code, written using the BASIC FileIO library. DIM ctrl% 31,name% 31 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$ IFtype%=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.