; Program: ERASE ; Version: 5.0 ; Date: 18 May 84 ; Author: Richard Conn ; Previous Versions: 4.0 (16 Jan 83) ; Previous Versions: 3.3 (6 Jan 83), 3.2 (7 Dec 82) ; Previous Versions: 3.1 (9 Nov 82), 3.0 (18 Oct 82), 2.0 (18 Nov 81) ; Previous Versions: 1.2 (12 Apr 81), 1.3 (25 Oct 81), 1.4 (26 Oct 81) ; Previous Versions: 1.0 (14 Jun 80), 1.1 (19 Oct 80) ; vers equ 54 subvers equ ' ' ; ; Version 5.4 -- July 1, 1990 -- Gene Pizzetta ; Eliminated internal environment assembly option. Added ; configuration byte after ASCII string 'SYSFILES>' to chose ; whether to include system files by default (non-zero) or ; exclude them by default (0). S option now toggles the ; default meaning (it's current action is shown by the usage ; screen. Now filters high bit of filenames for terminals that ; display special characters that way. At the suggestion of ; Howard Goldstein, ERASE no longer signs on with its load ; address and version number; these are displayed only on the ; usage screen. Restored Q (quit) as a valid response to ; an erase query, but ^C still works. Display has been made ; even more compact than last version. Many of these changes ; are to make the ERASE interface very similar to the RCP ; version. Program error flag is now set to 10 if no files ; are erased, unless the program is aborted with a ^C or with ; a "Q" response to a prompt. If an invalid option is given ; the program error code is set to 19 and error handler is ; invoked. Added disk free space display. Now obeys ZCPR3 ; quiet flag, except when in inspect mode or when a prompt is ; necessary (when a read/only file is found, for instance). ; Removed Wheel byte protection for S and R options. ; ; Version 5.3 -- March 25, 1990 -- Gene Pizzetta ; Added "A" option to suppress "Erase all files?" question ; when "*.*" is given as a filespec. This option is primarily ; for use in alias scripts and batch files, where you might ; want to clear a directory without ERASE stopping to ask if ; you know what you're doing. Rick Charnes added some nice ; features in v5.2, but succeeded in badly messing up the display ; for all prompted erasures. That has been corrected and the ; Q (quit) option has been eliminated. Instead, ^C now aborts ; ERASE at any prompt. ; ; Version 5.2 -- January 24, 1989 -- Rick Charnes ; Three changes: ; (1) Now turns off ZEX input while program is running. ; This is important when ERASE.COM (a) is used in an alias inside ; a ZEX file under certain circumstances and (b) ERASE.COM requires ; user input, such as if its I)nspect option is used or if R/O files ; are encountered. Otherwise the ZEX script itself would be sent ; willy-nilly into the prompt rather than allowing the user to do so. ; (2) The ZCPR3 error flag is set if program did not erase ; any files. This can be useful in aliases when the correct ; execution of the remainder of an alias is dependent upon a ; successful erasure. The error flag is cleared if any files ; were successfully erased. ; (3) ZCPR3 register "0" is set to the number of files ; successfully erased. This can also be nice for aliases. I always ; liked this concept, for which my inspiration was Jay Sage's doing ; the same thing with FF.COM, which sets ZCPR3 register 0 to the ; number of files successfully found. ; ; Version 5.1A -- December 30, 1987 -- Bruce Morgen ; Fix option parser as per RENAME32, strip high bit ; when printing program's actual name for help screen, wheel byte ; checked before granting "S" or "R" option or help text on those ; options. ; ; Version 5.1 -- December 21, 1987 -- Bruce Morgen ; Z80 opcodes, Zilog mnemonics and ZCPR33 Type 3 format. ; Usage message gives correct COMfile name of program. Following ; Howard Goldstein's (LX17 & 18) lead, the ZCPR 3.3 parser is used ; if it's available. ; ; ERASE command -- Erases files specified in command line. Command is of ; the form: ; ERASE dir:filename.typ,... ISRA ; Drive specification is optional. If I option is given, Inspection of ; each file is performed and the user is given the option to erase the ; file or not. If S option is given, System files are included in erase ; procedure. If R option is given, R/O files are erased without prompting. ; If A option is given, user will not be prompted if All files (*.*) are ; selected. ; ext z33chk,z33fname,z3init,zfname,z3log ext stopzex,putreg,puter2,prtname ext inverror,dparams,dfree,getquiet ext dirq,fillb,cin,caps,bout,eprint,crlf,retud ext putud,getud,pafdc,phlfdc,phl4hc,codend ; public cout ; make SYSLIB use our COUT routine ; ; Equates ; bdos equ 5 ; BDOS entry fcb equ 5Ch ; file control block buff equ 80h ; input line buffer esize equ 16 ; size of dir entry (from SYSLIB DIRQ routine) z3env defl 0FE00h ; environment address ctrlc equ 03h ; ^C BEL equ 07h ; bell BS equ 08h ; backspace CR equ 0Dh ; carriage return LF equ 0Ah ; linefeed ; ; Type 3 Header -- Code modified as suggested by Charles Irvine to function ; correctly with interrupts enabled. Program will abort with an error message ; when not loaded to the correct address (attempt to run it under CP/M or Z30). ; entry: jr start0 ; must use relative jump nop ; filler db 'Z3ENV',3 ; type-3 environment z3eadr: dw z3env ; filled in by Z33 dw entry ; intended load address ; ; Configuration . . . ; db 'SYSFILES>' ; system files configuration byte sysflg: db 0 ; 0 = exclude, non-zero = include ; start0: ld hl,0 ; point to warmboot entry ld a,(hl) ; save the byte there di ; protect against interrupts ld (hl),0C9h ; replace warmboot with a return opcode rst 0 ; call address 0, pushing RETADDR ; onto stack retaddr: ld (hl),a ; restore byte at 0 dec sp ; get stack pointer to point dec sp ; to the value of RETADDR pop hl ; get it into HL and restore stack ei ; we can allow interrupts again ld de,retaddr ; this is where we should be xor a ; clear carry flag push hl ; save address again sbc hl,de ; subtract -- we should have 0 now pop hl ; restore value of RETADDR jr z,start ; if addresses matched, begin real code ; ld de,notz33msg-retaddr ; offset to message add hl,de ex de,hl ; switch pointer to message into DE ld c,9 jp bdos ; return via BDOS print string function notz33msg: db 'Not Z33+$' ; abort message if not Z33-compatible ; ; Start of program . . . ; start: ld hl,(z3eadr) ; point to ZCPR3 environment call z3init ; initialize the ZCPR3 env and the VLIB env ld (stack),sp ; get stack pointer & save it ; ; Compute buffer locations ; call codend ; determine free space ld (cmdlne),hl ; set pointer to command line ld de,100h ; buffer size add hl,de ; command line ld (erafcb),hl ; FCB for erase add hl,de ld (dirbuf),hl ; set pointer to directory buffer ld sp,hl ; set stack pointer ; ; Save our location and stop ZEX input ; call putud call stopzex ; ; Check for help request ; ld a,(fcb+1) ; get first char of filename cp '/' ; option caught? jr z,usage cp ' ' jp nz,econt ; ; Print usage information ; usage: call eprint db 'ERASE Version ' db vers/10+'0','.',vers MOD 10+'0',subvers db ' (loaded at ',0 ld hl,entry call phl4hc call eprint db 'h)',CR,LF db 'Usage:',CR,LF,' ',0 call prtname call eprint db ' {dir:}afn.aft{,{dir:}afn.aft{,...}} {{/}options}',CR,LF db 'Options:',CR,LF db ' A Erase all (*.*) files without asking.',CR,LF db ' I Inspect mode (get user approval).',CR,LF db ' R Erase read/only files without asking.',CR,LF db ' S ',0 ld a,(sysflg) or a jr nz,usage2 call eprint db 'Include',0 jr usage3 usage2: call eprint db 'Exclude',0 usage3: call eprint db ' system files.',0 ; ; Return to operating system ; exit: ld a,0 erexit: call puter2 ; set program error flag ld b,a ; move error code to B cp 19 ; invalid option error? call z,inverror ; (yes, invoke error handler) call getud ; reset user if necessary ld sp,(stack) ; get old stack & set it ret ; ; Copy buffer into temp buffer ; econt: ld hl,(cmdlne) ; point to command line ex de,hl ; ... in DE ld hl,buff+1 ; point to buffer ld bc,80h ; buffer size (max) ldir ; copy into command line buffer ; ; Extract flags if present ; xor a ; set no inspect, no r/o, and no system files ld (inspct),a ld (rdonly),a ld (noask),a ; NoAsk flag ld (quiet),a ld a,(sysflg) ; check system config byte or a jr z,xsys ld a,0C0h ld (system),a jr xsys2 xsys: ld a,80h ; select non-sys ld (system),a xsys2: ld hl,0 ; set file count ld (filcnt),hl ld hl,(cmdlne) ; point to buffer ; ; Skip to filename string ; sblank: ld a,(hl) ; skip to non-blank cp ' ' ; space? jr nz,sbl1 inc hl ; point to next char jr sblank ; ; Skip to end of filename string ; sbl1: ld a,(hl) ; skip to space or EOL or a ; done? jp z,chkqt cp ' ' ; space jr z,sbl2 inc hl ; point to next jr sbl1 ; ; Skip over trailing blanks ; sbl2: inc hl ; point to character after space ld a,(hl) or a ; end of command tail? jp z,chkqt cp ' ' ; another space jr z,sbl2 ; if so, continue skipping ; ; Check for leading slash on option and skip it if so ; opt: cp '/' ; option char? jr nz,option inc hl ; skip slash ; ; Process list of options ; option: ld a,(hl) ; get byte or a ; done? jp z,chkqt inc hl ; point to next char cp ' ' ; skip over spaces jr z,option cp '/' ; if option letter, obvious error, so help jp z,usage cp 'I' ; inspect? jr z,optins cp 'R' ; read/only? jr z,optro cp 'A' ; don't ask? jr z,optask cp 'S' ; system files? jp nz,invopt ; ; Set system file selection ; ld a,(system) ; check default cp 80h jr z,setsys ld a,80h ld (system),a jr option setsys: ld a,0C0h ; set for sys and non-sys files ld (system),a jr option ; ; We have an invalid option ; invopt: call eprint db ' Invalid option.',0 ld a,19 jp erexit ; ; Set inspect option ; optins: ld a,0FFh ; inspect ld (inspct),a jr option ; ; Set don't ask option ; optask: ld a,0FFh ; don't ask ld (noask),a jr option ; ; Set r/o option ; optro: ld a,0FFh ; set r/o ld (rdonly),a jr option ; ; Check quiet mode (not valid in Inspect mode) ; chkqt: ld a,(inspct) or a jr nz,dspec call getquiet jr z,dspec ld (quiet),a ; ; Extract disk, user, and filename information ; dspec: ld hl,(cmdlne) ; point to before first byte dec hl ; point to before first byte for following INC dspec0: inc hl ; point to byte ld a,(hl) ; get byte or a ; done? jp z,usage cp ' ' ; space? jr z,dspec0 jr dspec2 ; ; Major re-entry point when file specs are separated by commas. ; HL points to first byte of next file spec ; dspec1: ld a,(quiet) or a jr nz,dspec2 call crlf dspec2: call getud ; return home ld de,fcb ; point to FCB in DE, point to first char of filename IN HL call parsit ; extract filename into FCB, get disk and user ld (nextch),hl ; save pointer to delimiter which ended scan ld hl,fcb+1 ; see if filename is all wild ld b,11 ; 11 bytes wtest: ld a,(hl) ; get byte inc hl ; point to next cp '?' ; wild? jr nz,nowild djnz wtest ; count down ld a,(inspct) ; inspect? or a ; 0=no jr nz,nowild ld a,(noask) ; check don't ask flag or a ; 0=yes, ask jr nz,nowild call eprint db 'Erase all files on ',0 ld a,(fcb) or a jr nz,prtdu call retud ld a,b inc a prtdu: add '@' call bout ld a,(fcb+13) call pafdc call eprint db ': ? N',BS,0 call cin ; get response call caps ; capitalize cp 'Y' ; yes? call z,bout ; echo jr z,nowild jp eradone ; nowild: call z,crlf ld de,fcb ; point to FCB call z3log ; log into directory ; ; Load directory and erase files ; erase: ld hl,(dirbuf) ; point to dir buffer ld a,(system) ; get sys/non-sys flags ld de,fcb ; point to FCB call dirq ; load dir, select files, pack, and alphabetize ; ; Erase dir files; HL points to first file, BC=file count ; call erafiles ; ; Check for next file spec ; ld hl,(nextch) ; get pointer ld a,(hl) ; get delim cp ',' ; another file? jr nz,eradone inc hl ; point to char after comma jp dspec1 ; continue processing ; ; Erase complete: print count and exit ; eradone: call prcount ; print file count ld hl,(filcnt) ; get count ld a,l ; check for none or h jp nz,exit ld a,10 jp erexit ; ; Erase selected files ; erafiles: ld a,b ; check for any files loaded or c ret z jr erafl1 ; ; Print filename ; eraflp: ld a,(quiet) or a jr nz,erafl1 call crlf erafl1: push bc ; save entry count ld a,(inspct) ; inspect mode? or a jr nz,skipqt ; (yes, skip quiet mode) ld a,(quiet) or a jr nz,nofnam skipqt: push hl ; save pointer to FCB call prfn ; print filename pop hl ; get pointer ; ; Check for inspection and inspect if set ; nofnam: ld a,(inspct) ; get flag or a ; 0=no jr z,erait ; ; Prompt user for erase ; call eraq ; erase question cp ctrlc ; quit? jr z,quit cp 'Q' jr z,quit cp 'Y' ; yes? jr z,erait ; ; Don't erase file ; erano: jp eratest ; ; Prompt user for erase ; eraq: call eprint ; print prompt db ' Erase (Y/N/Q)? N',BS,0 call cin ; get response call caps ; capitalize cp 'Y' jr z,cout cp 'Q' ; quit? jr z,cout cp ctrlc ; quit? ret z ld a,'N' cout: jp bout ; echo ; ; Quit erase program -- Even if we've erased no files, we want to exit ; quit: cp ctrlc jr nz,quit1 call eprint db '^C',0 quit1: jp eradone ; ; Print filename ; prfn: ld a,' ' call bout inc hl ; point to filename ld b,8 ; print name call prnt ld a,'.' ; decimal call bout ld b,3 ; print type call prnt ret ; ; Erase file ; erait: push hl ld de,9 ; point to r/o attribute add hl,de ld a,(hl) ; get r/o attribute pop hl ; restore pointer and 80h ; r/o? jr z,erait1 ; r/w, proceed ld a,(rdonly) ; get r/o erase flag or a ; 0=query jr nz,erait0 ; erase without question if flag set ld a,(quiet) ; check quiet flag or a jr z,skipfn ; (filename already printed) call crlf push hl call prfn pop hl skipfn: call eprint ; notify user and prompt db BEL,' Read/Only,',0 call eraq ; ask question cp 'Q' ; quit? jr z,quit cp ctrlc jr z,quit cp 'Y' ; erase r/o jp nz,erano ; do not erase if not yes ; ; Erase R/O file ; erait0: push hl ; save pointer to file entry ld de,9 ; point to r/o attribute add hl,de ld A,(hl) ; get attribute and 7Fh ; make r/w ld (hl),a pop hl ; get pointer to FCB push hl ; save pointer again ex de,hl ; DE points to FCB xor a ; make sure current disk is selected ld (de),a ld c,30 ; set file attributes call bdos pop hl ; ; Erase R/W file ; erait1: push hl ; save pointer to filename to erase inc hl ; point to first byte of name push hl ; save HL ld hl,(erafcb) ; set up FCB ex de,hl ; ..in DE pop hl ; get HL push de ; save pointer xor a ; A=0 ld (de),a ; current disk inc de ; point to first char ld bc,11 ; copy 11 bytes ldir ; copy HL to DE for 11 bytes ex de,hl ; HL points to rest of FCB ld b,24 ; fill rest of FCB with zeroes xor a ; A=0 call fillb pop de ; get pointer ld c,19 ; delete file call bdos skpmsg: ld hl,(filcnt) ; increment count inc hl ld (filcnt),hl pop hl ; get pointer to directory entry ; ; Point to next entry ; eratest: ld de,esize ; point to next entry add hl,de pop bc ; get count dec bc ; count down ld a,b ; check for zero or c jp nz,eraflp ret ; ; Print chars pointed to by HL for B bytes ; prnt: ld a,(hl) ; get character and 07Fh call bout inc hl ; point to next djnz prnt ; count down ret ; ; Print count of number of files erased ; prcount: ld hl,(filcnt) ; get count ld b,0 ; we'll be setting ZCPR3 register "0" ld a,l ; check for none (and prepare for PUTREG) call putreg call getquiet ; (even for inspect mode) or a ret nz call crlf ld a,l or h jr z,prno call phlfdc ; print decimal count jr prms ; prno: call eprint db 'No Files Erased, ',0 jr fspace ; prms: ld hl,(filcnt) ; 1 file erased? ld a,h ; high zero? or a jr nz,prmult ld a,l ; low one? cp 1 jr z,prsing ; prmult: call eprint db ' Files Erased, ',0 jr fspace ; prsing: call eprint db ' File Erased, ',0 ; fspace: call dparams ; prints free space on last drive used call dfree ex de,hl call phlfdc call eprint db 'k Free',0 ret ; ; Parse filename ; parsit: call z33chk jp z,z33fname xor a jp zfname ; DSEG ; ; Uninitialized data . . . ; inspct: ds 1 ; inspect flag (0=no, 0FFh=yes) system: ds 1 ; system flag (80h=exclude, 0C0h=include) rdonly: ds 1 ; read/only flag (0=query for r/o, 0FFh=don't) noask: ds 1 ; don't ask flag (0=query *.*, 0FFh=don't) quiet: ds 1 ; quiet flag (non-zero=quiet) nextch: ds 2 ; pointer to next char in multifile command line filcnt: ds 2 ; count of number of files erased erafcb: ds 2 ; pointer to FCB for erase cmdlne: ds 2 ; pointer to command line dirbuf: ds 2 ; pointer to directory buffer stack: ds 2 ; old stack pointer END