DelDir

1 rem --------------------- cut  here ---------------------|
rem

1 CLS:DELETE_DIRECTORY 'ram1_','temp_', 1
2 :

rem NB! WARNING! ACHTUNG! VARSKU I SKAUEN! VARNING! LET OP! VIVA!;>
rem
rem                  Careless use of this program
rem
rem may have   A   D E V A S T A T I N G    E F F E C T
rem
rem                          on your life
rem for all I know. I could list reams of possible ways things could
rem go wrong, and the consequences subsequent thereunto, as a result
rem of using this potentially HAZARDOUS software; whether used as
rem intended, or in error. Please take this WARNING seriously,
rem because you see, whatever happens, that'll be ENTIRELY
rem YOUR OWN FAULT. I accept NO responsibility WHATSOEVERNONOTI!
rem for YOUR ACTIONS - or your rotten luck, for that matter.
rem However, if you like it, if it improves your understanding or
rem inspires you if, in a funny sort of way, it leads to your
rem promotion, or saves your marriage, teaches your kids to break
rem the bank, or.. Then REMEMEBER ME. That's MY doing. That shows I
rem got it right, and that YOU took good note of this warning!

10 REMark        DELETE_DIRECTORY
11 REMark S*BASIC PROCedure to delete an
12 REMark     entire directory tree
13 REMark   Requires tk2 or equivalent
14 REMark          ©PWitte 1998
15 REMark Use at own risk! No warranties!
16 REMark Parameters:
17 REMark  dev$ = device; eg win1_, ram2_
18 REMark  dir$ = directory; eg temp_
19 REMark  tree:  0 => files only
20 REMark       <>0 => dirs and files
21 :

rem For the benefit of qlers (of all ages) who, like myself,
rem enjoy reading (short snippets!) of other people's commented
rem code. I enjoy a small, well-defined problem - like
rem traversing the directory tree - much as others might like a
rem crossword puzzle. Except this is fun!
rem
rem If you just want to get on and try it:
rem cut out the bit between the two --- cut here --- lines.
rem Save it as a file named say, flp1_DelDir.txt.
rem LOAD 'flp1_deldir.txt' into BASIC.
rem SAVE 'win1_temp_DelDir_bas', for example.
rem Re-LOAD it and check if any lines start with MIStake.
rem
rem Genuine bug or incompatibility reports (and comments)
rem welcomed - and where appropriate, may be dealt with.
rem NB         No other support provided!
rem NB These rem lines may miraclulously disappear!

1000 DEFine PROCedure DELETE_DIRECTORY(dev$, dir$, tree)

rem To remind the user what s/he's about to do, an awkward name
rem has been chosen.
rem
rem The selection of parameters has been made to avoid parsing.
rem                  ----------
rem The dir$ parameter seeds the name variable n$. The reason for
rem for not re-using the dir$ parameter and dispensing with n$
rem altogether is that n$ changes, and if dir$ were used as a
rem variable an unintended change would be passed all the way
rem back to the calling code's variables! In S*BASIC all
rem parameters are passed by Reference ie, the parameter passes
rem an actual copy of the calling variable - a very nice feature.
rem But in this instance it would be safer to pass the variable
rem by Value ie, only the value is passed, completely disociated
rem from the variable. (I'll have a bit more to say on that
rem subject in an upcomming QHJ article (if my contribution is
rem deemed acceptable)).
rem
rem tree is simply a switch to enable the whole sub-directory
rem tree to be scanned. In SBASIC it defaults to off, as all
rem variables are pre-initialled to zero/nul. In SuperBASIC
rem a value must always be supplied.
rem
rem I've chosen a none-recursive tree traversal algorithm here
rem As traversing a tree structure is by nature a recursive
rem operation this entails the use of a stack. This stack only
rem explicitly needs to store the S*BASIC channel numbers; the
rem remaining information required - namely our current file
rem position in each open directory - is "remembered" by the
rem the file system itself.

1010 LOCal c%, t%, pos, ch%(17), n$(36)
1020 n$ = dir$: c% = 0

rem The maximum level of recursion can only be 19 deep (0..18)
rem DIM ch%(18), or rather LOCal ch%(18), sets it up.
rem (Remember we only need to store the S*BASIC channel
rem numbers, and they're integer.)
rem
rem c% is our stack pointer, and for SuperBASIC's sake, we
rem initialise it to 0.
rem
rem t% is just a help variable to store the type of the file
rem we're looking at.
rem
rem pos maintains our current-directory record position,
rem
rem n$(36) contains the current directory or file name.

1030 REPeat dir_loop

rem The outer loop is invoked each time a new directory
rem is to be opened ie, the first time, and then for every
rem recursive step down the sub-tree.

1040  ch%(c%) = FOP_DIR(dev$ & n$)

rem Here the current directory is opened and it's channel
rem number is stacked.
rem (The very first time through the loop c% = 0, and
rem n$ contains the value passed in dir$)

1050  IF ch%(c%) < 0: Action '', ch%(c%)

rem If an error occurs the channel number will be a negative
rem error code, thanks to FOP_DIR.
rem
rem The Action sub-routine is defined below. Taking the action
rem routine out of the main body of the code perhaps makes it
rem easyer to modify for other tasks. The action routine does
rem not return on an error parameter!

1060  pos = -64

rem Initialise pos (somewhere where we can see it!)

1070  REPeat file_loop

rem The inner loop goes through every entry in a directory file
rem once: If the current entry is a new directory file, it
rem temporarily postpones what it's doing and then does the whole
rem sub-tree (and any sub-trees of that again) before returning
rem to continue processing the next entry.

1080   pos = pos + 64

rem Each directory entry, or record, is 64 bytes long, starting
rem at position 0. The structure of the directory header table
rem looks like this (there doesn't appear to be an "official"
rem version, so here's mine (appended)):
rem

1090   IF pos >= FLEN(#ch%(c%)) THEN

rem here we're checking for End Of File

1100    n$ = FNAME$(#ch%(c%)): CLOSE#ch%(c%)

rem All subdirectories and files in Current Directory (CD) have
rem been deleted at this point. We lost the CD's name when we
rem start processing it, but it can be regained from its
rem Channel Definition Block with FNAME$. We're done with
rem this directory, all that's left to do now is to close it and

1110    IF tree: Action 'Deleting', 1

rem delete it (if appropriate).
rem
rem Here the tree switch is checked to see if all subdirectories
rem have been deleted (you can only DELETE an empty directory).

1120    c% = c% - 1: IF c% < 0: EXIT dir_loop

rem Pop the stack ie, proceed to a higher level. If the stack
rem "underflows" (c% < 0) then it's the end - we're done!

1130    pos = INT(FPOS(#ch%(c%)) / 64) * 64

rem At line 1130 we don't know exactly where the file pointer is!
rem Getting it is no problem: pos = FPOS(ch%(c%)). But it has to
rem be aligned to the record boundry, so amputate any bits
rem sticking out. (INT is word sized in SuperBASIC, so this could
rem error on a hard disk!)

1140   ELSE

rem This is the second main program block. The first block dealt
rem with rear-guard action; closing doors, turning off lights,
rem picking up new trails.. This part does most of the work. It
rem gets information from the file header, sorts directories from
rem files, and makes other decisions based on parameters and
rem data.

1150    GET#ch%(c%)\ pos + 14; n$

rem GET and BGET, both inluded in tk2 and similar toolkits has
rem the following syntax:
rem     GET #channel [\ position], items
rem At record base (ie, pos) + 14 is known to be the name of the
rem file (see end of listing). It's a string in the internal
rem format.

1160    IF LEN(n$) > 0 THEN
1170     BGET#ch%(c%)\ pos + 5; t%
1180     IF t% = 255 THEN
1190      IF tree THEN
1200       Action 'Checking', 2
1210       c% = c% + 1: EXIT file_loop
1220      END IF
1230     ELSE
1240      Action 'Deleting', 0
1250     END IF
1260    END IF
1270   END IF
1280  END REPeat file_loop
1290 END REPeat dir_loop
1300 END DEFine
1310 :
2000 DEFine PROCedure Action(tx$, type)
2010 IF CODE(INKEY$(#0; 0)) = 27: CLOSE: ERT -1
2020 IF type THEN
2030  IF type < 0: CLOSE: ERT type
2040  PRINT \ tx$! dev$; n$! '->'
2050  IF type = 1: DELETE dev$ & n$
2060 ELSE
2070  PRINT tx$! n$
2080  DELETE dev$ & n$
2090 END IF
2100 END DEFine
2110 :
rem
rem               File Header Definition

rem mnemonic  pos  size   description
rem
rem fht_len     0  long   file length
rem fht_acces   4  byte   file access key
rem fht_type    5  byte   file type:
rem
rem fht.bod          0    basic program or ordinary data files
rem fht.exe          1    executable program
rem fht.rel          2    relocatable object files
rem fht.thd          3    Thor directory files (ArgOS)
rem                       Others ?
rem fht.dir        255    directory files (standard)
rem
rem fht_finf    6         8 bytes of file type-dependent information
rem fht_data    6  long   default data space for executable files
rem
rem fht_name   14  qstr   name string
rem fht.nmln        36    max file name length
rem fht_updt   52  long   date of last update
rem fht_vers   56  word   version number
rem fht_filn   58  word   file number
rem fht_bkdt   60  long   date of last backup


rem -------------------------- cut here ---------------------------|

  
Generated with sb2htm on 2019 Mar 31
©pjwitte March 2oi9