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. 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 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, but 32 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 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%)+""" ret%=0 :REM Return value idx%=0 :REM Directory index, starts at zero REPEAT f$=FNgbpb8(idx%):idx%=X%!9:IF f$<>"" THEN PROCname UNTIL f$="" 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 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 and FNs() from the String library. DIM ctrl% 31,name% 31 DEFPROCScan LOCAL idx%,f$ REPEAT:f$=FNs(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 : DEFFNs(A$):IFLEFT$(A$,1)=" ":REPEATA$=MID$(A$,2):UNTILLEFT$(A$,1)<>" " IFRIGHT$(A$,1)=" ":REPEATA$=LEFT$(A$,LENA$-1):UNTILRIGHT$(A$,1)<>" " =A$ 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.