Z3ENV DEFL 0FE00H VERS EQU 10 ; 5/31/86 ; Adapted for ZCPR3 by Bruce Morgen, with display ; enhancements, now requires a REL-capable assembler ; W C . Z 8 0 (word counter) ; David Coons (cis [72435,136]) ; V1.0 February 1984 ; ; Abstract ; -------- ; Counts words in any file and displays ; count on con: in the form "FILE CONTAINS ; 00000 WORDS.". A word is defined as any ; character sequence ended by spaces, tabs, ; a carriage return, or line feed. ignores ; high order bit in any character. ; Uses word count algorithm from "THE C ; PROGRAMMING LANGUAGE" (BW Kernighan and DM ; Ritchie, Englewood Cliffs, NJ: Prentice- ; Hall, 1978), page 18. ; written in Z80 assembly language ; (assemble with Z80ASM, zas or zasm) ; ; usage: ; zwc [du: or dir:]filename.ext ; (ambiguous file names not allowed) ; execution timing: ; a 3200-word file was counted in ; approximately seven seconds on a ; floppy-based system. ; -------------------------------------------------- EXTRN FENV,PRNDU ;separate modules EXTRN Z3INIT,Z3LOG,GETMDISK,GETMUSER,GETCRT,DUTDIR EXTRN EPRINT,RETUD,PFN2,SETDMA,CRLF,COUT,PHLFDC ; YES EQU -1 NO EQU NOT YES ZERO EQU 0 BDOS EQU 0005H ; Bdos entry addr FOPEN EQU 15 ; Open file FREAD EQU 20 ; Sequential read FCB EQU 005CH ; Fcb addr DRIVE EQU FCB ; Drive FILNAM EQU FCB+01H ; File name EXTENT EQU FCB+0CH ; Extent number CURREC EQU FCB+20H ; Current record BUFFER EQU 0080H ; Disk i/o buffer TAB EQU 09H ; Horizontal tab CR EQU 0DH ; Carriage return LF EQU 0AH ; Line feed SPACE EQU ' ' ; Space MASK EQU 01111111B ; Saves 7 bits ; -------------------------------------------------- START: ; verify a file name is present in command tail LD HL,ZERO ; Zero out HL LD (NW),HL ; Initialize word count ADD HL,SP ; Acquire system stack LD (STACK),HL ; Store its address LD SP,STACK ; Set local stack LD HL,BUFFER+80H ; Initial buffer address LD (BUFADR),HL ; into its data area XOR A ; Zero out A LD (INWORD),A ; Init in-the-word flag CALL FENV ; Acquire ENV address JP NZ,ENVOK ; Give up if not found CALL EPRINT DB 'Apparently this is not a ZCPR3 system: Aborting!'0 JP FINIS ENVOK: CALL Z3INIT ; Pass to Z3LIB CALL EPRINT DB 'ZWC, Version ' DB [VERS/10]+'0','.',[VERS MOD 10]+'0',2CH DB ' a ZCPR3 word counter',CR,LF,LF,0 LD A,(FCB+1) CP '/' JP Z,ZHELP CP ' ' JP NZ,CHKDRV ; CALL EPRINT DB CR,LF,'No file specified,',CR,LF,LF,0 JP ZHELP CHKDRV: ; verify specified drive with the ZCPR3 environment. LD A,(DRIVE) ; Get drive # LD B,A CALL GETMDISK CP B JP NC,CHKUSR CALL EPRINT DB 'Drive code is not valid',CR,LF,LF,0 JP FINIS ; End program CHKUSR: ; does Z3 approve of user area? LD A,(FCB+13) LD B,A CALL GETMUSER CP B JP NC,CHKNAM CALL EPRINT DB 'User code is not valid',CR,LF,LF,0 JP FINIS CHKNAM: ; verify that file name includes no '?' LD HL,FILNAM-1 ; Load addr of name LD B,11 ; Chk name(8)+ext(3) LD A,'?' ; Search argument LOOP1: INC HL ; Point to next char CP (HL) ; '?' present? JP Z,NOAMB ; Yes; print err msg DEC B ; Decrement counter JP NZ,LOOP1 ; Jmp if more chars JP NAMOK ; Check done and ok NOAMB: CALL EPRINT DB 'Ambiguous file names not allowed' DB CR,LF,LF,0 JP ZHELP ; End program NAMOK: ; open file XOR A ; Zero accumulator LD (EXTENT),A ; Set extent to zero LD (CURREC),A ; Set curr rec to 0 LD DE,FCB ; Load fcb addr CALL Z3LOG CALL RETUD CALL PRNDU INC DE CALL PFN2 CALL DUTDIR JP Z,OPENIT CALL EPRINT DB 2CH,' in the ',0 LD B,8 NDRLOP: LD A,(HL) CP SPACE JP Z,NDRMSG CALL COUT INC HL DEC B JP NZ,NDRLOP NDRMSG: CALL EPRINT DB ' directory',2CH,0 CALL GETCRT LD A,(HL) CP 52 CALL C,CRLF OPENIT: DEC DE LD C,FOPEN ; Bdos function 15 CALL BDOS ; Attempt to open CP 0FFH ; Open ok? JP NZ,PREP ; Yes ; CALL EPRINT DB ' does not exist.' DB CR,LF,LF,0 JP FINIS ; End program PREP: LD HL,BUFFER ; Load buffer addr CALL SETDMA ; Set buffer addr MLOOP: ; main program loop LD HL,(BUFADR) ; Get pointer LD A,L ; Get lsb of pointer OR A ; End of buffer? JP NZ,GETBYT ; No, process byte ; LD HL,BUFFER ; Load buffer start LD (BUFADR),HL ; Reset buffer ptr LD DE,FCB ; Load fcb addr LD C,FREAD ; Bdos function 20 CALL BDOS ; Get next record OR A ; More of file? JP NZ,RESULT ; No, end GETBYT: LD A,(HL) ; Get curr byte AND MASK ; Mask off 8th bit LD HL,(BUFADR) ; Load pointer INC HL ; Point to next byte LD (BUFADR),HL ; Save pointer ; check for white space CP SPACE ; Space? JP Z,ENDWRD ; Yes, check word CP CR ; Carriage return? JP Z,ENDWRD ; Yes, check word CP LF ; Line feed? JP Z,ENDWRD ; Yes, check word CP TAB ; Tab? JP Z,ENDWRD ; Yes, check word ; check indicator; if no, set and count LD A,(INWORD) ; Get indicator CP NO ; Is it reset? JP NZ,MLOOP ; No, repeat loop ; LD BC,YES ; Load 'yes' LD A,B ; Move to accum LD (INWORD),A ; Store in indicator ; increment counter and repeat loop LD HL,(NW) ; Load counter INC HL ; Increment LD (NW),HL ; Save counter JP MLOOP ; ENDWRD: ; at end of word; reset indicator LD BC,NO ; Load 'no' LD A,B ; Move to accum LD (INWORD),A ; Reset indicator JP MLOOP ; Repeat loop ; RESULT: ; display first half of results message CALL EPRINT DB ' contains ',0 ; display number of words LD HL,(NW) ; Load word count CALL PHLFDC ; display second half of results message CALL EPRINT DB ' words.',CR,LF,0 FINIS: LD HL,(STACK) LD SP,HL RET ; -------------------------------------------------- ZHELP: CALL EPRINT DB 'Syntax:' DB CR,LF,TAB DB 'ZWC [du: or dir:]ufn',CR,LF,0 JP FINIS ; -------------------------------------------------- ; storage areas BUFADR: DS 2 ; Buffer pointer INWORD: DS 1 ; Yes = curr in word ; No = between words NW: DS 2 ; Word count ; DS 32 STACK: DS 2 END