home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / chasm2.zip / WC.ASM < prev    next >
Assembly Source File  |  1986-02-04  |  12KB  |  366 lines

  1. ;================================================
  2. ; PROGRAM WC    Version 1.1 by Dave Whitman
  3. ;
  4. ; Filter to count words, lines and characters.
  5. ; Based loosely on Kernighan and Ritchie, page 18.
  6. ;
  7. ; Syntax:  WC [?] [/w] [/l] [/c]
  8. ;
  9. ;           ? = print help message
  10. ;          /w = unlabeled word count
  11. ;          /l = unlabeled line count
  12. ;          /c = unlabeled character count
  13. ;        none = combined counts, with labels
  14. ;
  15. ; The three options may be present in any combination.
  16. ; Regardless of option order, the selected counts will
  17. ; be in the following order:
  18. ;    words
  19. ;    lines
  20. ;    characters
  21. ;
  22. ; Requires DOS 2.0, will abort under earlier versions.
  23. ;====================================================
  24.  
  25. ;============
  26. ; Equates
  27. ;============
  28.  
  29. @read   equ    3FH             ;read file/device
  30. @chrin  equ    06H             ;get char from stdin
  31. @chrout equ    02H             ;send char to stdout
  32. @dosver equ    30H             ;get dos version
  33. @prnstr equ    09H             ;print string
  34.  
  35. stdin   equ    0000H           ;standard input
  36.  
  37. w       equ    01H             ;flag value for word option
  38. l       equ    02H             ;flag value for line option
  39. c       equ    04H             ;flag value for char option
  40.  
  41. yes     equ    0FFH            ;boolean value
  42. no      equ    00H             ;    "
  43. cr      equ    0DH             ;carriage return
  44. lf      equ    0AH             ;line feed
  45. \n      equ    0DH             ;newline char
  46. \t      equ    09H             ;tab char
  47. \l      equ    0AH             ;linefeed char
  48.  
  49. buf_size       equ     8192
  50. mem_avail      equ     [06H]
  51. param_count    equ     [80H]
  52. param_area     equ     [81H]
  53.  
  54. main   proc    far
  55.        call    setup           ;check dos, parse options
  56.        call    buf_in          ;count w, l, c from std i/o
  57.        call    output          ;send requested output
  58.        int     20H             ;and return to dos
  59.        endp
  60.  
  61. ;======================================
  62. ; SUBROUTINE SETUP
  63. ; Checks for proper DOS, parses options
  64. ;======================================
  65. setup  proc    near
  66.  
  67.        mov     ah, @dosver     ;what dos are we under?
  68.        int     21H
  69.        cmp     al, 2           ;2.0 or over?
  70.        jae     a0              ;yes, skip
  71.  
  72.        mov     ah, @prnstr     ;no, bitch
  73.        mov     dx, offset(baddos)
  74.        int     21H
  75.        pop     ax              ;reset stack
  76.        int     20H             ;and exit
  77.  
  78. a0     mov     ax, mem_avail   ;do we have room for the buffer?
  79.        cmp     ax, buf_size
  80.        jae     a1              ;yes, skip
  81.        mov     ah, @prnstr     ;no, bitch
  82.        mov     dx, offset(nomem)
  83.        int     21H
  84.        pop     ax              ;reset stack
  85.        int     20H             ;and exit
  86.  
  87. a1     xor     ch,ch           ;cx <== param count
  88.        mov     cl, param_count ;  "
  89.        cmp     cl, 00H         ;any params?
  90.        je      aexit           ;exit if none
  91.  
  92.        mov     di, offset(param_area)  ;scan for help request
  93.        mov     al, '?'                 ;marked with ?
  94.        repnz                           ;scan until match or end
  95.        scasb
  96.        jnz     a_par                   ;reached end, no match? skip
  97.        mov     ah, @prnstr             ;matched? print help
  98.        mov     dx, offset(help)
  99.        int     21H
  100.        pop     ax                      ;pop stack and exit
  101.        int     20H
  102.  
  103. a_par  xor     ch, ch                   ;get number of param chars again
  104.        mov     cl, param_count
  105.        mov     di, offset(param_area)   ;scan for options
  106. a2     mov     al, '/'                  ;will be marked with /
  107.        repnz
  108.        scasb
  109.        jnz     aexit           ;reached end
  110.  
  111.        mov     al, [di]        ;get option char
  112.        and     al, 0DFH        ;guarantees upper case
  113.  
  114.        cmp     al, 'W'         ;words?
  115.        jne     a3              ;nope
  116.        orb     options, w      ;yes, set flag
  117.        jmps    a2              ;and loop
  118.  
  119. a3     cmp     al, 'L'         ;lines?
  120.        jne     a4              ;nope
  121.        orb     options, l      ;yes, set flag
  122.        jmps    a2              ;and loop
  123.  
  124. a4     cmp     al, 'C'         ;characters?
  125.        jne     a2              ;nope, just loop
  126.        orb     options, c      ;yes, set flag
  127.        jmps    a2              ;and loop
  128.  
  129. aexit  ret
  130.  
  131. baddos db      cr lf 'This program requires DOS 2.0!' cr, lf, '$'
  132.  
  133. nomem  db      cr lf 'Insufficient memory, program aborted' cr lf '$'
  134. help   db       cr lf
  135.        db      'WC  version 1.2 by D. Whitman' cr lf
  136.        db       cr lf
  137.        db      'Reads StdIn, and writes count of words, lines,' cr lf
  138.        db      'and characters to StdOut.' cr lf
  139.        db       cr lf
  140.        db      'Syntax:' cr lf
  141.        db       cr lf
  142.        db      '   WC [?] [/W] [/L] [/C] [<infile] [>outfile]' cr lf
  143.        db       cr lf
  144.        db      '   Options:' cr lf
  145.        db      '        ? = print this help message' cr lf
  146.        db      '       /W = print unlabeled word count' cr lf
  147.        db      '       /L = print unlabeled line count' cr lf
  148.        db      '       /C = print unlabeled character count' cr lf
  149.        db      '     none = combined counts, with labels' cr lf
  150.        db       cr lf
  151.        db      'Multiple options can be selected.' cr lf
  152.        db       cr lf
  153.        db      'This program is in the public domain.' cr lf '$'
  154.        endp
  155.  
  156. ;=========================================
  157. ; SUBROUTINE BUF_INPUT
  158. ; Inputs data by sector, sends it one char
  159. ; at a time for counting.
  160. ;==========================================
  161.  
  162.  
  163. buf_in proc    near
  164.  
  165.        movb    inword, no      ;not currently in a word
  166.  
  167. bu1    mov     ah, @read       ;read
  168.        mov     bx, stdin       ;from stdin
  169.        mov     cx, buf_size    ;one buffer's worth
  170.        mov     dx, offset(buffer)
  171.        int     21H
  172.        cmp     ax, 00H         ;test for EOF
  173.        jz      buexit          ;if so, done
  174.  
  175.        mov     cx,ax           ;cx <== number chars read
  176.        mov     si, offset(buffer)
  177. bu2    lodsb                   ;al <== next char from buffer
  178.        call    count           ;update totals
  179.        loop    bu2
  180.        jmps    bu1
  181. buexit ret
  182.        endp
  183.  
  184. ;=============================================
  185. ;SUBROUTINE COUNT
  186. ;Counts words, lines and characters as per K&R
  187. ;=============================================
  188. count  proc    near
  189.        addw    clow,0001H      ;bump # of chars
  190.        jae     b1              ;no carry? skip
  191.        incw    chigh           ;handle carry
  192.  
  193.        ;in the following, note use of ADD to increment
  194.        ;doublewords.  INC does not affect Carry Flag.
  195.  
  196. b1     cmp     al, \n          ;is it a newline?
  197.        jne     b2              ;no, skip
  198.        addw    llow,0001H      ;bump # of lines
  199.        jae     b2              ;no carry? skip
  200.        incw    lhigh           ;handle carry
  201.  
  202. b2     cmp     al, \n          ;newline or
  203.        je      b3
  204.        cmp     al, \t          ;tab or
  205.        je      b3
  206.        cmp     al, \l          ;linefeed or
  207.        je      b3
  208.        cmp     al, ' '         ;blank,
  209.        je      b3              ;then skip
  210.  
  211.       ;none of the above
  212.        cmpb    inword, yes     ;already in a word?
  213.        je      b4              ;yes, return
  214.        movb    inword, yes     ;if not, we are now.
  215.        addw    wlow,0001H      ;bump word count
  216.        jae     b4              ;no carry? return
  217.        incw    whigh           ;handle carry
  218.        jmps    b4              ;return
  219.  
  220.       ;any of the above
  221. b3     movb    inword, no
  222. b4     ret
  223.        endp
  224.  
  225. ;=====================================
  226. ; SUBROUTINE OUTPUT
  227. ; Prints results, modified by options.
  228. ;=====================================
  229. output proc    near
  230.  
  231.        cmpb    options, 00H    ;any options?
  232.        jne     c1              ;yes, skip label
  233.        mov     ah, @prnstr     ;print label for word count
  234.        mov     dx, offset(word_label)
  235.        int     21H
  236.        jmps    c1a             ;print count
  237.  
  238. c1     testb   options, W      ;/w option?
  239.        jz      c2              ;nope, skip
  240. c1a    mov     di, whigh       ;get doubleword word count
  241.        mov     si, wlow        ; in di:si
  242.        call    printdd         ;convert and print it.
  243.        call    newline
  244.  
  245. c2     cmpb    options, 00H    ;any options?
  246.        jne     c3              ;yes, skip label
  247.        mov     ah, @prnstr     ;print label for line count
  248.        mov     dx, offset(line_label)
  249.        int     21H
  250.        jmps    c3a             ;print count
  251.  
  252. c3     testb   options, L      ;/l option?
  253.        jz      c4              ;nope, skip
  254. c3a    mov     di, lhigh       ;get doubleword line count
  255.        mov     si, llow        ; in di:si
  256.        call    printdd         ;convert and print it
  257.        call    newline
  258.  
  259. c4     cmpb    options, 00H    ;any options?
  260.        jne     c5              ;yes, skip label
  261.        mov     ah, @prnstr     ;print label for char count
  262.        mov     dx, offset(char_label)
  263.        int     21H
  264.        jmps    c5a             ;print count
  265.  
  266. c5     testb   options, C      ;/c option?
  267.        jz      c6              ;nope, skip
  268. c5a    mov     di, chigh       ;get doubleword char count
  269.        mov     si, clow        ; in di:si
  270.        call    printdd         ;convert and print it
  271.        call    newline
  272.  
  273. c6     ret
  274.  
  275. word_label db 'Words:  $'
  276. line_label db 'Lines:  $'
  277. char_label db 'Chars:  $'
  278.       endp
  279.  
  280. ;=========================
  281. ; SUBROUTINE NEWLINE
  282. ; Prints a CR/LF to stdout
  283. ;=========================
  284. newline proc   near
  285.        mov     ah, @prnstr
  286.        mov     dx, offset(crlf)
  287.        int     21H
  288.        ret
  289. crlf   db      0DH, 0AH, '$'
  290.        endp
  291.  
  292. ;=========================================================
  293. ; SUBROUTINE PRINTDD
  294. ; This less-than-comprehensible routine was swiped verbatim
  295. ; from Ted Reuss's disassembly of John Chapman's sorted
  296. ; disk directory program.  The routine converts a 32 bit
  297. ; integer in DI:SI to ASCII digits and sends them to STDOUT.
  298. ;==========================================================
  299.  
  300. PRINTDD PROC    NEAR    ;Prints a 32 bit integer in DI:SI
  301.         XOR     AX,AX           ;Zero out the
  302.         MOV     BX,AX           ; working
  303.         MOV     BP,AX           ; registers.
  304.         MOV     CX,32           ;# bits of precision
  305. J1      SHL     SI
  306.         RCL     DI
  307.         XCHG    BP,AX
  308.         CALL    J6
  309.         XCHG    BP,AX
  310.         XCHG    BX,AX
  311.         CALL    J6
  312.         XCHG    BX,AX
  313.         ADC     AL,0
  314.         LOOP    J1
  315.         MOV     CX,1710H        ;5904 ?
  316.         MOV     AX,BX
  317.         CALL    J2
  318.         MOV     AX,BP
  319. J2      PUSH    AX
  320.         MOV     DL,AH
  321.         CALL    J3
  322.         POP     DX
  323. J3      MOV     DH,DL
  324.         SHR     DL              ;Move high
  325.         SHR     DL              ; nibble to
  326.         SHR     DL              ; the low
  327.         SHR     DL              ; position.
  328.         CALL    J4
  329.         MOV     DL,DH
  330. J4      AND     DL,0FH          ;Mask low nibble
  331.         JZ      J5              ;If not zero
  332.         MOV     CL,0
  333. J5      DEC     CH
  334.         AND     CL,CH
  335.         OR      DL,'0'          ;Fold in ASCII zero
  336.         SUB     DL,CL
  337.  
  338.         MOV     AH, @CHROUT     ;Print next digit
  339.         INT     21H
  340.  
  341.         RET                     ;Exit to caller
  342.         ENDP
  343.  
  344. J6     PROC    NEAR
  345.         ADC     AL,AL
  346.         DAA
  347.         XCHG    AL,AH
  348.         ADC     AL,AL
  349.         DAA
  350.         XCHG    AL,AH
  351.         RET
  352.         ENDP
  353.  
  354. ;=================
  355. ;GLOBAL VARIABLES
  356. ;=================
  357. options  db  00H       ;byte of option flags
  358. inword   db  00H       ;flag: yes indicates scan is within a word
  359. wlow     db  00H, 00H  ;low part of doubleword word count
  360. whigh    db  00H, 00H  ;high "   "      "       "     "
  361. llow     db  00H, 00H  ;low part of doubleword line count
  362. lhigh    db  00H, 00H  ;high "   "      "       "     "
  363. clow     db  00H, 00H  ;low part of doubleword char count
  364. chigh    db  00H, 00H  ;high "   "      "       "     "
  365. buffer                 ;input buffer
  366.