home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol229 / wc86.lbr / WC5.A86 next >
Text File  |  1986-02-10  |  8KB  |  375 lines

  1.         TITLE    'Word Count for CP/M 86'
  2. ;        by Charlie Godet-Ceraolo
  3. ;           2610 Glenwood Road
  4. ;           Brooklyn, NY  11210
  5. ;
  6. ;        based on MuchText.A86 with input file buffering
  7. ;        and count accurate to about 8 digits.
  8. ;        5 March 1985
  9. ;
  10. FALSE        EQU    0
  11. TRUE        EQU    NOT FALSE
  12. Release        EQU    1
  13. Version        EQU    05
  14. ;
  15. ;    User definable equates
  16. ;
  17. Buf_Sectors    EQU    256        ; 32k buffer
  18. Precision    EQU    8        ; maximum bcd digits
  19. ;
  20. ;    CP/M Equates
  21. ;
  22. Sector_Size    EQU    128
  23. Console        EQU    2
  24. OPEN        EQU    15        ;OPEN FUNCTION CODE
  25. READ        EQU    20        ;READ FUNCTION CODE
  26. STDMA        EQU    26        ; set buffer address
  27. CPM_EOF        EQU    1AH
  28. ;
  29. ;    Ascii Equates
  30. ;
  31. TAB        EQU    09H
  32. LF        EQU    0AH         ; Line Feed
  33. CR        EQU    0DH         ; Carriage Return
  34. SPACE        EQU    20H         ; Blank
  35. Ascii_Zero    EQU    '0'
  36. EOS        EQU    0
  37. ;
  38.         CSEG
  39. ;
  40. WC:
  41.         MOV    DX,DS
  42.         MOV    SS,DX            ; set up our stack
  43.         MOV    SP,OFFSET LOCAL_STACK
  44.         MOV    ES,DX            ; make sure ES -> our data area
  45.         CLD                ; and we're going the right way
  46. ;
  47.         MOV    SI,Offset SignOn
  48.         CALL    P_String
  49.         MOV    AL,.CMD_TAIL        ; test cmdline
  50.         OR    AL,AL            ; anything?
  51.         JNZ    got_cmd            ; yes, continue
  52. ;
  53.         MOV    SI,OFFSET MsgUse    ; no args, send help
  54.         CALL    P_String
  55.         JMP    MAIN_EXIT        ; and leave
  56. ;                
  57. ;        try to OPEN FILE
  58. ;                
  59. got_cmd:
  60.         MOV    DX,TFCB
  61.         MOV    CL,OPEN
  62.         CALL    BDOS
  63.         CMP    AL,0FFH            ; found?
  64.         JNE    MAIN            ; yes, proceed
  65. ;
  66.         MOV    SI,OFFSET MsgNoFile    ; nope, tell 'em
  67.         CALL    P_String
  68.         JMP    MAIN_EXIT        ; and leave
  69. ;
  70. MAIN:
  71.         MOV    AL,Space        ; initialize variables
  72.         MOV    CX,Precision * 3
  73.         MOV    DI,Offset Counters
  74.         REP    STOSB
  75.         MOV    InWord,FALSE
  76.         MOV    BUF_PTR,Offset BUF_END    ; force first read
  77.         CALL    P_Name
  78. ;
  79. ;            
  80. MAIN_LOOP:
  81.         CALL    GET_CHAR        ;GET A BYTE
  82.         CMP    AL,CPM_EOF        ; eof?
  83.         JE    send_report        ; leave
  84.         AND    AL,7FH            ; strip hi-bit for WS files
  85.         MOV    SI,Offset Char_Count
  86.         CALL    Inc_Ascii        ; bump char count
  87.         CMP    AL,LF            ; eoln?
  88.         JNE    not_lf            ; nope
  89.         MOV    SI,Offset Line_Count
  90.         CALL    Inc_Ascii        ; yes, bump line count
  91. not_lf:
  92.         MOV    DI,Offset WhiteSpace
  93.         MOV    CX,Length WhiteSpace
  94.         REPNE    SCASB
  95.         JNE    not_white        ; nope
  96.         MOV    InWord,FALSE        ; yes, end of a word
  97.         JMPS    Main_Loop        ; and back for more
  98. not_white:
  99.         CMP    InWord,TRUE        ; are we in a word?
  100.         JE    Main_Loop        ; yes, back for more
  101.         MOV    InWord,TRUE        ; we are now,
  102.         MOV    SI,Offset Word_Count
  103.         CALL    Inc_Ascii        ; bump word count
  104.         JMPS    MAIN_LOOP        ; and back for more
  105. ;                
  106. ;        FINAL PROCESSING
  107. ;
  108. send_report:
  109.         MOV    SI,Offset MsgDoc
  110.         CALL    P_String
  111.         MOV    SI,Offset MsgChar
  112.         CALL    P_String
  113.         MOV    SI,Offset Char_Count
  114.         CALL    P_Number
  115.         MOV    SI,Offset MsgLine
  116.         CALL    P_String
  117.         MOV    SI,Offset Line_Count
  118.         CALL    P_Number
  119.         MOV    SI,Offset MsgWords
  120.         CALL    P_String
  121.         MOV    SI,Offset Word_Count
  122.         CALL    P_Number
  123.         CALL    P_CrLf
  124. MAIN_EXIT:
  125.         MOV    CL,0        ;EXIT TO CP/M
  126.         MOV    DL,0
  127.         INT    224
  128. ;                
  129. ;        SUBROUTINES
  130. ;                
  131. P_CrLf:
  132.         PUSH    AX
  133.         MOV    AL,CR
  134.         CALL    P_Char
  135.         MOV    AL,LF
  136.         CALL    P_Char
  137.         POP    AX
  138.         RET
  139. ;                
  140. P_Char:
  141.         PUSH    AX
  142.         PUSH    BX
  143.         PUSH    CX
  144.         PUSH    DX
  145.         MOV    DL,AL
  146.         MOV    CL,Console
  147.         CALL    BDOS
  148.         POP    DX
  149.         POP    CX
  150.         POP    BX
  151.         POP    AX
  152.         RET
  153. ;                
  154. ;    Print null-terminated string pointed to by SI. Preserves all.
  155. ;                
  156. P_String:
  157.         PUSH    SI
  158. ps_loop:
  159.         LODSB            ; get char
  160.         OR    AL,AL        ; string end?
  161.         JZ    ps_exit        ; yes
  162.         CALL    P_Char        ; no, print it
  163.         JMPS    ps_loop        ; get another
  164. ps_exit:
  165.         POP    SI
  166.         RET
  167. ;
  168. ;    Increment an unpacked BCD number, up to Precision places
  169. ;
  170. Inc_Ascii:
  171.         PUSH    SI
  172.         PUSH    DI
  173.         PUSH    AX
  174.         PUSH    CX
  175.         STD                ; set to decrement
  176.         ADD    SI,Precision-1        ; start from LSB
  177.         MOV    DI,SI            ; point di there too
  178.         MOV    CX,Precision        ; max bytes to do
  179. incloop:
  180.         LODSB                ; get byte
  181.         INC    AL            ; bump it
  182.         AAA                ; ascii adjust
  183.         STOSB                ; save it
  184.         JNC    incexit            ; no carry, we're done
  185.         LOOP    incloop            ; else go to next byte
  186.                         ; if we get here,
  187.                         ; we have overflow
  188. incexit:
  189.         POP    CX
  190.         POP    AX
  191.         POP    DI
  192.         POP    SI
  193.         CLD                ; restore regs and direction
  194.         RET
  195. ;
  196. ;    Display an unpacked BCD number with leading zeros replaced
  197. ;    by leading blanks.  Up to Precision digits
  198. ;
  199. P_Number:
  200.         MOV    CX,Precision - 1    ; all but last digit
  201. ploop:
  202.         LODSB                ; get a byte
  203.         CMP    AL,Space        ; if it's a space
  204.         JE    p_it            ; print it
  205.         ADD    AL,Ascii_Zero        ; else make it ascii
  206. p_it:
  207.         CALL    P_Char
  208.         LOOP    ploop            ; get another
  209.         LODSB                ; get last digit
  210.         OR    AL,30H            ; make ascii, no matter
  211.         CALL    P_Char            ; and print
  212.         RET
  213. ;
  214. ;    Gets char from buffer, reads file, if necessary.
  215. ;    Updates buffer pointer and returns char in AL.
  216. ;    Preserves all.
  217. ;                    
  218. GET_CHAR:
  219.         PUSH    SI
  220.         MOV    SI,BUF_PTR        ; get buffer position
  221.         CMP    SI,Offset BUF_END    ; are we at end?
  222.         JNE    get_byte        ; no, get char
  223. ;
  224.         CALL    INIT_BUFFER        ; yes, do a read
  225.         CALL    FILL_BUFFER
  226.         MOV    SI,OFFSET BUF_START    ; reset the pointer
  227. get_byte:
  228.         LODSB
  229.         MOV    BUF_PTR,SI
  230.         POP    SI
  231.         RET
  232. ;
  233. ;    Fill buffer with CPM_EOF, so getchar will find one.
  234. ;    Preserves all
  235. ;
  236. INIT_BUFFER:
  237.         PUSH    CX
  238.         PUSH    DI
  239.         PUSH    AX
  240.         MOV    CX,Buf_Sectors*Sector_Size    ; bytes to fill
  241.         MOV    DI,Offset BUF_START
  242.         MOV    AL,CPM_EOF
  243.         REP    STOSB
  244.         POP    AX
  245.         POP    DI
  246.         POP    CX
  247.         RET
  248. ;
  249. ;    Fills the buffer from the start to either EOF or Buf_Sectors.
  250. ;    preserves all.  BDOS return code in AL.
  251. ;
  252. FILL_BUFFER:
  253.         PUSH    BX
  254.         PUSH    CX
  255.         PUSH    DX
  256.         MOV    DX,(Offset BUF_START)    ;load start of disk buffer
  257.         MOV    CX,Buf_Sectors        ;number of sectors to read
  258. fil_buf1:
  259.         CALL    READ_SECTOR
  260.         OR    AL,AL            ;read OK?
  261.         JNZ    fill_exit        ;no, end of file, exit
  262.         ADD    DX,Sector_Size        ;else, add 128 to dma address
  263.         LOOP    fil_buf1
  264. fill_exit:
  265.         POP    DX
  266.         POP    CX
  267.         POP    BX
  268.         RET
  269. ;
  270. ;    Reads a sector into the address in DX. Preserves all,
  271. ;    bdos return code in al
  272. ;
  273. READ_SECTOR:
  274.         PUSH    BX
  275.         PUSH    CX
  276.         PUSH    DX
  277.         MOV    CL,STDMA
  278.         CALL    BDOS
  279.         MOV    DX,TFCB
  280.         MOV    CL,READ
  281.         CALL    BDOS
  282.         POP    DX
  283.         POP    CX
  284.         POP    BX
  285.         RET
  286. ;
  287. ;    Calls bdos, saves ES from bdos clobber. Don't use for
  288. ;    system calls that return values in ES!!! (eg GetDMABase etc.)
  289. ;
  290. BDOS:
  291.         PUSH    ES
  292.         INT    224
  293.         POP    ES
  294.         RET
  295. ;                    
  296. ;    Move filename from fcb to heading, put in standard form
  297. ;
  298. P_Name:
  299.         MOV    SI,TFCB+1        ; SOURCE: name in fcb
  300.         MOV    DI,Offset FName
  301.         MOV    CX,8
  302. name1:
  303.         LODSB
  304.         CMP    AL,SPACE    ; blank?
  305.         JE    ext1        ; yes, get the extension
  306.         STOSB
  307.         LOOP    name1        ; get another, if less than 8
  308. ext1:
  309.         MOV    AL,'.'        ; place a dot
  310.         STOSB
  311.         MOV    SI,TFCB+9    ; point to extension
  312.         MOV    CX,3
  313.         REP    MOVSB
  314.         RET
  315.     IF ((Offset $ - Offset WC) MOD 10H) EQ 0
  316.         NOP
  317.     ENDIF
  318. ;                
  319.         DSEG
  320. Data_Start    EQU    $
  321.         ORG    100H        ; for the base page
  322. ;
  323. TFCB        EQU    005CH        ;TRANSIENT PROGRAM FCB
  324. CMD_TAIL    EQU    0080H        ; CP/M command line image
  325. ;                
  326.     DB    '(c) 1984 Charlie Godet-Ceraolo'
  327. SignOn        DB    'WordCount (CP/M86) v'
  328.         DB    (Release MOD 10) + Ascii_Zero,'.'
  329.         DB    (Version / 10) + Ascii_Zero
  330.         DB    (Version MOD 10) + Ascii_Zero
  331.         DB    CR,LF,EOS
  332. MsgNoFile    DB    'File not found',CR,LF,EOS
  333. MsgDoc        DB    CR,LF,TAB,'Name: '
  334. FName        DB    '            '
  335.         DB    CR,LF,EOS
  336. MsgChar        DB    CR,LF,TAB,'Characters: ',EOS
  337. MsgLine        DB    CR,LF,TAB,'Lines:      ',EOS
  338. MsgWords    DB    CR,LF,TAB,'Words:      ',EOS
  339. MsgUse        DB    CR,LF,'Usage:',TAB,'WC Filespec'
  340.         DB    CR,LF,EOS
  341. ;
  342. WhiteSpace    DB    CR,LF,TAB,Space,0CH,08H
  343.     IF (Offset $ - Offset Data_Start ) MOD 2 NE 0    ; make even
  344.         RB    1
  345.     ENDIF
  346.         RS    128
  347. LOCAL_STACK    EQU    $
  348. InWord        RW    1        ; word flag
  349. Counters    EQU    $
  350. Line_Count    RS    Precision
  351. Word_Count    RS    Precision
  352. Char_Count    RS    Precision
  353. BUF_PTR        RW    1
  354. BUF_START    RS    (Buf_Sectors*Sector_Size)
  355. BUF_END        EQU    $
  356. Min_Data    EQU    (Offset $ - Offset Data_Start) / 16    ; for gencmd
  357. ;
  358.         END
  359. ;
  360. SingleQuote    EQU    27H
  361. DoubleQuote    EQU    22H
  362. Legals        DB    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  363.         DB    '0123456789'
  364.         DB    '_'
  365. ;        DB    SingleQuote,DoubleQuote
  366. NumberLegals    EQU    (Offset $ - Offset Legals)
  367. To_Upper:
  368.         CMP    AL,'a'
  369.         JB    no_change
  370.         CMP    AL,'z'
  371.         JA    no_change
  372.         SUB    AL,'a'-'A'
  373. no_change:
  374.         RET
  375.