;  PROGRAM:  ERASE
;  VERSION:  5.0
;  DATE:  18 MAY 84
;  AUTHOR:  RICHARD CONN
;  PREVIOUS VERSION:  4.0 (16 JAN 83)
;  PREVIOUS VERSION:  3.3 (6 JAN 83), 3.2 (7 DEC 82)
;  PREVIOUS VERSION:  3.1 (9 NOV 82), 3.0 (18 OCT 82), 2.0 (18 NOV 81)
;  PREVIOUS VERSION:  1.2 (12 APR 81), 1.3 (25 OCT 81), 1.4 (26 OCT 81)
;  PREVIOUS VERSION:  1.0 (14 JUN 80), 1.1 (19 OCT 80)
VERS    equ     50
z3env   SET     0f400h

;
;  ERASE COMMAND --
;       Erase files specified in command line.  Command is of the form --
;               ERASE DIR:FILENAME.TYP,... ISR
;       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.  Drive specification
; is optional.  If R option is given, R/O files are erased without prompting.
;

FALSE   EQU     0
TRUE    EQU     NOT FALSE

ESIZE   EQU     16      ; SIZE OF DIR ENTRY (FROM SYSLIB DIRQ ROUTINE)

       EXT     DIRQ    ; DIRECTORY PROCESSOR

       EXT     Z3INIT  ; INIT Z3 ENV
       EXT     ZFNAME  ; FILE NAME PARSER
       EXT     Z3LOG   ; LOG INTO Z3 FCB SPEC

       EXT     PUTUD   ; SAVE CURRENT DU
       EXT     GETUD   ; GET CURRENT DU
       EXT     PHLDC   ; PRINT HL AS DECIMAL CHARS
       EXT     EPRINT  ; PRINT ROUTINE
       EXT     COUT    ; CONSOLE OUTPUT ROUTINE
       EXT     CIN     ; CONSOLE INPUT ROUTINE
       EXT     CAPS    ; CAPITALIZE ROUTINE
       EXT     CRLF    ; NEW LINE ROUTINE
       EXT     FILLB   ; FILL ROUTINE
       EXT     CODEND  ; CODE END COMPUTATION ROUTINE

;
;  CP/M EQUATES
;
CPM     EQU     0       ; WARM BOOT
BDOS    EQU     5       ; BDOS ENTRY
FCB     EQU     5CH     ; FCB
BUFF    EQU     80H     ; INPUT LINE BUFFER
CR      EQU     13      ; <CR>
LF      EQU     10      ; <LF>

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3init  ;initialize the ZCPR3 Env and the VLIB Env
;
       LXI     H,0     ; GET STACK PTR
       DAD     SP
       SHLD    STACK   ; SAVE IT
;
; Compute Buffer Locations
;
       CALL    CODEND  ; DETERMINE FREE SPACE
       SHLD    CMDLNE  ; SET PTR TO COMMAND LINE
       LXI     D,100H  ; BUFFER SIZE
       DAD     D       ; COMMAND LINE
       SHLD    ERAFCB  ; FCB FOR ERASE
       DAD     D
       SHLD    DIRBUF  ; SET PTR TO DIRECTORY BUFFER
       SPHL            ; SET STACK PTR
;
; Save Location
;
       CALL    PUTUD   ; SAVE AWAY CURRENT DU

;
; Print Banner
;
       CALL    EPRINT
       DB      'ERASE  Version '
       DB      VERS/10+'0','.',(VERS MOD 10)+'0',0
       LDA     FCB+1   ; GET FIRST CHAR OF FILE NAME
       CPI     '/'     ; OPTION CAUGHT?
       JNZ     ECONT

;  PRINT HELP INFORMATION
HELP:
       CALL    EPRINT
       DB      CR,LF,'  ERASE dir:filename.typ,dir:fn.ft,... o...'
       DB      CR,LF,'Options:'
       DB      CR,LF,'   I -- Inspect Mode'
       DB      CR,LF,'   R -- Erase R/O Files without prompting user'
       DB      CR,LF,'   S -- Include System Files'
       DB      0
       JMP     RETURN

;  RETURN TO OS
RETURN:
       CALL    GETUD   ; RESET USER IF NECESSARY
RETX:
       LHLD    STACK   ; GET OLD STACK
       SPHL            ; SET IT
       RET

;  COPY BUFFER INTO TEMP BUFFER
ECONT:
       LHLD    CMDLNE  ; PT TO COMMAND LINE
       XCHG            ; ... IN DE
       LXI     H,BUFF+1        ; PT TO BUFFER
       MVI     B,80H   ; BUFFER SIZE (MAX)
       CALL    MOVEB   ; COPY INTO COMMAND LINE BUFFER

;  EXTRACT FLAGS IF PRESENT
       XRA     A       ; SET NO INSPECT, NO R/O, AND NO SYSTEM FILES
       STA     INSPECT
       STA     READONLY
       MVI     A,80H   ; SELECT NON-SYS
       STA     SYSTEM
       LXI     H,0     ; SET FILE COUNT
       SHLD    FILECNT
       LHLD    CMDLNE  ; PT TO BUFFER

;  SKIP TO FILE NAME STRING
SBLANK:
       MOV     A,M     ; SKIP TO NON-BLANK
       CPI     ' '     ; <SP>?
       JNZ     SBL1
       INX     H       ; PT TO NEXT CHAR
       JMP     SBLANK

;  SKIP TO END OF FILE NAME STRING
SBL1:
       MOV     A,M     ; SKIP TO <SP> OR EOL
       ORA     A       ; DONE?
       JZ      OPT
       CPI     ' '     ; <SP>
       JZ      OPT
       INX     H       ; PT TO NEXT
       JMP     SBL1

;  CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO
OPT:
       CPI     '/'     ; OPTION CHAR?
       JNZ     OPTION
       INX     H       ; SKIP SLASH

;  PROCESS LIST OF OPTIONS
OPTION:
       MOV     A,M     ; GET BYTE
       ORA     A       ; DONE?
       JZ      DSPEC
       INX     H       ; PT TO NEXT CHAR
       CPI     ' '     ; SKIP OVER SPACES
       JZ      OPTION
       CPI     '/'     ; IF OPTION LETTER, OBVIOUS ERROR, SO HELP
       JZ      HELP
       CPI     'I'     ; INSPECT?
       JZ      OPTINS
       CPI     'R'     ; READ/ONLY?
       JZ      OPTRO
       CPI     'S'     ; SYSTEM FILES?
       JNZ     HELP

;  SET SYS SELECTION
       MVI     A,0C0H  ; SET FOR SYS AND NON-SYS FILES
       STA     SYSTEM
       JMP     OPTION

;  SET INSPECT OPTION
OPTINS:
       MVI     A,0FFH  ; INSPECT
       STA     INSPECT
       JMP     OPTION

;  SET R/O OPTION
OPTRO:
       MVI     A,0FFH  ; SET R/O
       STA     READONLY
       JMP     OPTION

;  EXTRACT DISK, USER, AND FILE NAME INFORMATION
DSPEC:
       LHLD    CMDLNE  ; PT TO BEFORE FIRST BYTE
       DCX     H       ; PT TO BEFORE FIRST BYTE FOR FOLLOWING INX
DSPEC0:
       INX     H       ; PT TO BYTE
       MOV     A,M     ; GET BYTE
       ORA     A       ; DONE?
       JZ      HELP
       CPI     ' '     ; <SP>?
       JZ      DSPEC0
;
;  MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS
;    HL PTS TO FIRST BYTE OF NEXT FILE SPEC
;
DSPEC1:
       CALL    GETUD   ; RETURN HOME
       LXI     D,FCB   ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL
       MVI     A,0     ; SCAN FOR DIR FORM BEFORE DU
       CALL    ZFNAME  ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER
       SHLD    NEXTCH  ; SAVE PTR TO DELIMITER WHICH ENDED SCAN
       LXI     H,FCB+1 ; SEE IF FILE NAME IS ALL WILD
       MVI     B,11    ; 11 BYTES
WTEST:
       MOV     A,M     ; GET BYTE
       INX     H       ; PT TO NEXT
       CPI     '?'     ; WILD?
       JNZ     NOWILD
       DCR     B       ; COUNT DOWN
       JNZ     WTEST
       LDA     INSPECT ; INSPECT?
       ORA     A       ; 0=NO
       JNZ     NOWILD
       CALL    EPRINT
       DB      CR,LF,'Erase All Files? ',0
       CALL    CIN     ; GET RESPONSE
       CALL    CAPS    ; CAPITALIZE
       CALL    COUT    ; ECHO
       CPI     'Y'     ; YES?
       JZ      NOWILD
       CALL    EPRINT
       DB      CR,LF,'Aborting',0
       JMP     RETX
NOWILD:
       LXI     D,FCB   ; PT TO FCB
       CALL    Z3LOG   ; LOG INTO DIRECTORY

;  LOAD DIRECTORY AND ERASE FILES
ERASE:
       LHLD    DIRBUF  ; PT TO DIR BUFFER
       LDA     SYSTEM  ; GET SYS/NON-SYS FLAGS
       LXI     D,FCB   ; PT TO FCB
       CALL    DIRQ    ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE

;  ERASE DIR FILES; HL PTS TO FIRST FILE, BC=FILE COUNT
       CALL    ERAFILES

;  CHECK FOR NEXT FILE SPEC
       LHLD    NEXTCH  ; GET PTR
       MOV     A,M     ; GET DELIM
       CPI     ','     ; ANOTHER FILE?
       JNZ     ERADONE
       INX     H       ; PT TO CHAR AFTER COMMA
       JMP     DSPEC1  ; CONTINUE PROCESSING

;  ERASE COMPLETE -- PRINT COUNT AND EXIT
ERADONE:
       CALL    PRCOUNT ; PRINT FILE COUNT
       JMP     RETURN

;  ERASE SELECTED FILES
ERAFILES:
       MOV     A,B     ; CHECK FOR ANY FILES LOADED
       ORA     C
       RZ

;  PRINT FILE NAME
ERAFLP:
       PUSH    B       ; SAVE ENTRY COUNT
       CALL    CRLF    ; NEW LINE
       PUSH    H       ; SAVE PTR TO FCB
       INX     H       ; PT TO FILE NAME
       MVI     B,8     ; PRINT NAME
       CALL    PRNT
       MVI     A,'.'   ; DECIMAL
       CALL    COUT
       MVI     B,3     ; PRINT TYPE
       CALL    PRNT
       POP     H       ; GET PTR

;  CHECK FOR INSPECTION AND INSPECT IF SET
       LDA     INSPECT ; GET FLAG
       ORA     A       ; 0=NO
       JZ      ERAIT

;  PROMPT USER FOR ERASE
       CALL    ERAQ    ; ERASE QUESTION
       CPI     'Q'     ; QUIT?
       JZ      QUIT
       CPI     'Y'     ; YES?
       JZ      ERAIT

;  DON'T ERASE FILE
ERANO:
       CALL    EPRINT
       DB      '  NOT Erased',0
       JMP     ERATEST

;  PROMPT USER FOR ERASE
ERAQ:
       CALL    EPRINT  ; PRINT PROMPT
       DB      ' -- Erase (Y/N/Q=Quit/other=N)? ',0
       CALL    CIN     ; GET RESPONSE
       CALL    CAPS    ; CAPITALIZE
       CALL    COUT    ; ECHO
       RET

;  QUIT ERASE PROGRAM
QUIT:
       CALL    PRCOUNT ; PRINT COUNT OF FILES ERASED
       JMP     RETURN

;  ERASE FILE
ERAIT:
       PUSH    H
       LXI     D,9     ; PT TO R/O ATTRIBUTE
       DAD     D
       MOV     A,M     ; GET R/O ATTRIBUTE
       POP     H       ; RESTORE PTR
       ANI     80H     ; R/O?
       JZ      ERAIT1  ; R/W - PROCEED
       LDA     READONLY        ; GET R/O ERASE FLAG
       ORA     A       ; 0=QUERY
       JNZ     ERAIT0  ; ERASE WITHOUT QUESTION IF FLAG SET
       CALL    EPRINT  ; NOTIFY USER AND PROMPT
       DB      CR,LF,' File is R/O',0
       CALL    ERAQ    ; ASK QUESTION
       CPI     'Q'     ; QUIT?
       JZ      QUIT
       CPI     'Y'     ; ERASE R/O
       JNZ     ERATEST ; DO NOT ERASE IF NOT YES

;  ERASE R/O FILE
ERAIT0:
       PUSH    H       ; SAVE PTR TO FILE ENTRY
       LXI     D,9     ; PT TO R/O ATTRIBUTE
       DAD     D
       MOV     A,M     ; GET ATTRIBUTE
       ANI     7FH     ; MAKE R/W
       MOV     M,A
       POP     H       ; GET PTR TO FCB
       PUSH    H       ; SAVE PTR AGAIN
       XCHG            ; DE PTS TO FCB
       XRA     A       ; MAKE SURE CURRENT DISK IS SELECTED
       STAX    D
       MVI     C,30    ; SET FILE ATTRIBUTES
       CALL    BDOS
       POP     H

;  ERASE R/W FILE
ERAIT1:
       PUSH    H       ; SAVE PTR TO FILE NAME TO ERASE
       INX     H       ; PT TO FIRST BYTE OF NAME
       PUSH    H       ; SAVE HL
       LHLD    ERAFCB  ; SET UP FCB
       XCHG            ; ... IN DE
       POP     H       ; GET HL
       PUSH    D       ; SAVE PTR
       XRA     A       ; A=0
       STAX    D       ; CURRENT DISK
       INX     D       ; PT TO FIRST CHAR
       MVI     B,11    ; COPY 11 BYTES
       CALL    MOVEB   ; COPY HL TO DE FOR 11 BYTES
       XCHG            ; HL PTS TO REST OF FCB
       MVI     B,24    ; FILL REST OF FCB WITH ZEROES
       XRA     A       ; A=0
       CALL    FILLB
       POP     D       ; GET PTR
       MVI     C,19    ; DELETE FILE
       CALL    BDOS
       CALL    EPRINT
       DB      '      Erased',0
       LHLD    FILECNT ; INCREMENT COUNT
       INX     H
       SHLD    FILECNT
       POP     H       ; GET PTR TO DIRECTORY ENTRY

;  PT TO NEXT ENTRY
ERATEST:
       LXI     D,ESIZE ; PT TO NEXT ENTRY
       DAD     D
       POP     B       ; GET COUNT
       DCX     B       ; COUNT DOWN
       MOV     A,B     ; CHECK FOR ZERO
       ORA     C
       JNZ     ERAFLP

;  RETURN TO CALLER
       RET

;
;  COPY HL TO DE FOR B BYTES
;
MOVEB:
       MOV     A,M     ; GET BYTE
       STAX    D       ; PUT BYTE
       INX     H       ; PT TO NEXT
       INX     D
       DCR     B       ; COUNT DOWN
       JNZ     MOVEB
       RET

;
;  PRINT CHARS PTED TO BY HL FOR B BYTES
;
PRNT:
       MOV     A,M     ; GET CHAR
       CALL    COUT
       INX     H       ; PT TO NEXT
       DCR     B       ; COUNT DOWN
       JNZ     PRNT
       RET

;
;  PRINT COUNT OF NUMBER OF FILES ERASED
;
PRCOUNT:
       CALL    CRLF    ; NEW LINE
       LHLD    FILECNT ; GET COUNT
       MOV     A,L     ; CHECK FOR NONE
       ORA     H
       JZ      PRNO
       CALL    PHLDC   ; PRINT DECIMAL COUNT
       JMP     PRMS
PRNO:
       CALL    EPRINT
       DB      'No',0
PRMS:
       LHLD    FILECNT ; 1 FILE ERASED?
       MOV     A,H     ; HIGH ZERO?
       ORA     A
       JNZ     PRMULT
       MOV     A,L     ; LOW ONE?
       CPI     1
       JZ      PRSING
PRMULT:
       CALL    EPRINT
       DB      ' Files Erased',0
       RET
PRSING:
       CALL    EPRINT
       DB      ' File  Erased',0
       RET

;
;  BUFFERS
;
INSPECT:
       DS      1       ; INSPECT FLAG (0=NO, 0FFH=YES)
SYSTEM:
       DS      1       ; SYSTEM FLAG (0=NO, 80H=YES)
READONLY:
       DS      1       ; READ/ONLY FLAG (0=QUERY FOR R/O, 0FFH=DON'T)
USER:
       DS      1       ; NEW USER, OR 0FFH IF NO CHANGE
CURUSER:
       DS      1       ; CURRENT USER NUMBER
NEXTCH:
       DS      2       ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE
FILECNT:
       DS      2       ; COUNT OF NUMBER OF FILES ERASED
ERAFCB:
       DS      2       ; PTR TO FCB FOR ERASE
CMDLNE:
       DS      2       ; PTR TO COMMAND LINE
DIRBUF:
       DS      2       ; PTR TO DIRECTORY BUFFER
STACK:
       DS      2       ; OLD STACK PTR

       END