home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
vol229
/
wc86.lbr
/
WC5.A86
next >
Wrap
Text File
|
1986-02-10
|
8KB
|
375 lines
TITLE 'Word Count for CP/M 86'
; by Charlie Godet-Ceraolo
; 2610 Glenwood Road
; Brooklyn, NY 11210
;
; based on MuchText.A86 with input file buffering
; and count accurate to about 8 digits.
; 5 March 1985
;
FALSE EQU 0
TRUE EQU NOT FALSE
Release EQU 1
Version EQU 05
;
; User definable equates
;
Buf_Sectors EQU 256 ; 32k buffer
Precision EQU 8 ; maximum bcd digits
;
; CP/M Equates
;
Sector_Size EQU 128
Console EQU 2
OPEN EQU 15 ;OPEN FUNCTION CODE
READ EQU 20 ;READ FUNCTION CODE
STDMA EQU 26 ; set buffer address
CPM_EOF EQU 1AH
;
; Ascii Equates
;
TAB EQU 09H
LF EQU 0AH ; Line Feed
CR EQU 0DH ; Carriage Return
SPACE EQU 20H ; Blank
Ascii_Zero EQU '0'
EOS EQU 0
;
CSEG
;
WC:
MOV DX,DS
MOV SS,DX ; set up our stack
MOV SP,OFFSET LOCAL_STACK
MOV ES,DX ; make sure ES -> our data area
CLD ; and we're going the right way
;
MOV SI,Offset SignOn
CALL P_String
MOV AL,.CMD_TAIL ; test cmdline
OR AL,AL ; anything?
JNZ got_cmd ; yes, continue
;
MOV SI,OFFSET MsgUse ; no args, send help
CALL P_String
JMP MAIN_EXIT ; and leave
;
; try to OPEN FILE
;
got_cmd:
MOV DX,TFCB
MOV CL,OPEN
CALL BDOS
CMP AL,0FFH ; found?
JNE MAIN ; yes, proceed
;
MOV SI,OFFSET MsgNoFile ; nope, tell 'em
CALL P_String
JMP MAIN_EXIT ; and leave
;
MAIN:
MOV AL,Space ; initialize variables
MOV CX,Precision * 3
MOV DI,Offset Counters
REP STOSB
MOV InWord,FALSE
MOV BUF_PTR,Offset BUF_END ; force first read
CALL P_Name
;
;
MAIN_LOOP:
CALL GET_CHAR ;GET A BYTE
CMP AL,CPM_EOF ; eof?
JE send_report ; leave
AND AL,7FH ; strip hi-bit for WS files
MOV SI,Offset Char_Count
CALL Inc_Ascii ; bump char count
CMP AL,LF ; eoln?
JNE not_lf ; nope
MOV SI,Offset Line_Count
CALL Inc_Ascii ; yes, bump line count
not_lf:
MOV DI,Offset WhiteSpace
MOV CX,Length WhiteSpace
REPNE SCASB
JNE not_white ; nope
MOV InWord,FALSE ; yes, end of a word
JMPS Main_Loop ; and back for more
not_white:
CMP InWord,TRUE ; are we in a word?
JE Main_Loop ; yes, back for more
MOV InWord,TRUE ; we are now,
MOV SI,Offset Word_Count
CALL Inc_Ascii ; bump word count
JMPS MAIN_LOOP ; and back for more
;
; FINAL PROCESSING
;
send_report:
MOV SI,Offset MsgDoc
CALL P_String
MOV SI,Offset MsgChar
CALL P_String
MOV SI,Offset Char_Count
CALL P_Number
MOV SI,Offset MsgLine
CALL P_String
MOV SI,Offset Line_Count
CALL P_Number
MOV SI,Offset MsgWords
CALL P_String
MOV SI,Offset Word_Count
CALL P_Number
CALL P_CrLf
MAIN_EXIT:
MOV CL,0 ;EXIT TO CP/M
MOV DL,0
INT 224
;
; SUBROUTINES
;
P_CrLf:
PUSH AX
MOV AL,CR
CALL P_Char
MOV AL,LF
CALL P_Char
POP AX
RET
;
P_Char:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DL,AL
MOV CL,Console
CALL BDOS
POP DX
POP CX
POP BX
POP AX
RET
;
; Print null-terminated string pointed to by SI. Preserves all.
;
P_String:
PUSH SI
ps_loop:
LODSB ; get char
OR AL,AL ; string end?
JZ ps_exit ; yes
CALL P_Char ; no, print it
JMPS ps_loop ; get another
ps_exit:
POP SI
RET
;
; Increment an unpacked BCD number, up to Precision places
;
Inc_Ascii:
PUSH SI
PUSH DI
PUSH AX
PUSH CX
STD ; set to decrement
ADD SI,Precision-1 ; start from LSB
MOV DI,SI ; point di there too
MOV CX,Precision ; max bytes to do
incloop:
LODSB ; get byte
INC AL ; bump it
AAA ; ascii adjust
STOSB ; save it
JNC incexit ; no carry, we're done
LOOP incloop ; else go to next byte
; if we get here,
; we have overflow
incexit:
POP CX
POP AX
POP DI
POP SI
CLD ; restore regs and direction
RET
;
; Display an unpacked BCD number with leading zeros replaced
; by leading blanks. Up to Precision digits
;
P_Number:
MOV CX,Precision - 1 ; all but last digit
ploop:
LODSB ; get a byte
CMP AL,Space ; if it's a space
JE p_it ; print it
ADD AL,Ascii_Zero ; else make it ascii
p_it:
CALL P_Char
LOOP ploop ; get another
LODSB ; get last digit
OR AL,30H ; make ascii, no matter
CALL P_Char ; and print
RET
;
; Gets char from buffer, reads file, if necessary.
; Updates buffer pointer and returns char in AL.
; Preserves all.
;
GET_CHAR:
PUSH SI
MOV SI,BUF_PTR ; get buffer position
CMP SI,Offset BUF_END ; are we at end?
JNE get_byte ; no, get char
;
CALL INIT_BUFFER ; yes, do a read
CALL FILL_BUFFER
MOV SI,OFFSET BUF_START ; reset the pointer
get_byte:
LODSB
MOV BUF_PTR,SI
POP SI
RET
;
; Fill buffer with CPM_EOF, so getchar will find one.
; Preserves all
;
INIT_BUFFER:
PUSH CX
PUSH DI
PUSH AX
MOV CX,Buf_Sectors*Sector_Size ; bytes to fill
MOV DI,Offset BUF_START
MOV AL,CPM_EOF
REP STOSB
POP AX
POP DI
POP CX
RET
;
; Fills the buffer from the start to either EOF or Buf_Sectors.
; preserves all. BDOS return code in AL.
;
FILL_BUFFER:
PUSH BX
PUSH CX
PUSH DX
MOV DX,(Offset BUF_START) ;load start of disk buffer
MOV CX,Buf_Sectors ;number of sectors to read
fil_buf1:
CALL READ_SECTOR
OR AL,AL ;read OK?
JNZ fill_exit ;no, end of file, exit
ADD DX,Sector_Size ;else, add 128 to dma address
LOOP fil_buf1
fill_exit:
POP DX
POP CX
POP BX
RET
;
; Reads a sector into the address in DX. Preserves all,
; bdos return code in al
;
READ_SECTOR:
PUSH BX
PUSH CX
PUSH DX
MOV CL,STDMA
CALL BDOS
MOV DX,TFCB
MOV CL,READ
CALL BDOS
POP DX
POP CX
POP BX
RET
;
; Calls bdos, saves ES from bdos clobber. Don't use for
; system calls that return values in ES!!! (eg GetDMABase etc.)
;
BDOS:
PUSH ES
INT 224
POP ES
RET
;
; Move filename from fcb to heading, put in standard form
;
P_Name:
MOV SI,TFCB+1 ; SOURCE: name in fcb
MOV DI,Offset FName
MOV CX,8
name1:
LODSB
CMP AL,SPACE ; blank?
JE ext1 ; yes, get the extension
STOSB
LOOP name1 ; get another, if less than 8
ext1:
MOV AL,'.' ; place a dot
STOSB
MOV SI,TFCB+9 ; point to extension
MOV CX,3
REP MOVSB
RET
IF ((Offset $ - Offset WC) MOD 10H) EQ 0
NOP
ENDIF
;
DSEG
Data_Start EQU $
ORG 100H ; for the base page
;
TFCB EQU 005CH ;TRANSIENT PROGRAM FCB
CMD_TAIL EQU 0080H ; CP/M command line image
;
DB '(c) 1984 Charlie Godet-Ceraolo'
SignOn DB 'WordCount (CP/M86) v'
DB (Release MOD 10) + Ascii_Zero,'.'
DB (Version / 10) + Ascii_Zero
DB (Version MOD 10) + Ascii_Zero
DB CR,LF,EOS
MsgNoFile DB 'File not found',CR,LF,EOS
MsgDoc DB CR,LF,TAB,'Name: '
FName DB ' '
DB CR,LF,EOS
MsgChar DB CR,LF,TAB,'Characters: ',EOS
MsgLine DB CR,LF,TAB,'Lines: ',EOS
MsgWords DB CR,LF,TAB,'Words: ',EOS
MsgUse DB CR,LF,'Usage:',TAB,'WC Filespec'
DB CR,LF,EOS
;
WhiteSpace DB CR,LF,TAB,Space,0CH,08H
IF (Offset $ - Offset Data_Start ) MOD 2 NE 0 ; make even
RB 1
ENDIF
RS 128
LOCAL_STACK EQU $
InWord RW 1 ; word flag
Counters EQU $
Line_Count RS Precision
Word_Count RS Precision
Char_Count RS Precision
BUF_PTR RW 1
BUF_START RS (Buf_Sectors*Sector_Size)
BUF_END EQU $
Min_Data EQU (Offset $ - Offset Data_Start) / 16 ; for gencmd
;
END
;
SingleQuote EQU 27H
DoubleQuote EQU 22H
Legals DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DB '0123456789'
DB '_'
; DB SingleQuote,DoubleQuote
NumberLegals EQU (Offset $ - Offset Legals)
To_Upper:
CMP AL,'a'
JB no_change
CMP AL,'z'
JA no_change
SUB AL,'a'-'A'
no_change:
RET