home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / chasm2.zip / DUP.ASM < prev    next >
Assembly Source File  |  1986-05-27  |  15KB  |  444 lines

  1. ;===================================================
  2. ; PROGRAM DUP   Version 1.0 by Dave Whitman
  3. ;
  4. ; Filter to remove adjacent duplicate lines.
  5. ; Reads StdIn and writes non-duplicated lines to StdOut.
  6. ; Duplicate lines must be adjacent to be detected.
  7. ;
  8. ; Syntax:  DUP [?] [/nn] [<infile] [>outfile]
  9. ;
  10. ; The ? option prints a help message.
  11. ; If option /nn is used, comparision is based on
  12. ; the first nn characters only.
  13. ;
  14. ; Requires DOS 2.0, will abort under earlier versions.
  15. ;====================================================
  16.  
  17. ;============
  18. ; Equates
  19. ;============
  20.  
  21. @read   equ    3FH                ;read file/device
  22. @write  equ    40H                ;write file/device
  23. @dosver equ    30H                ;get dos version
  24. @prnstr equ    09H                ;print string
  25.  
  26. cr      equ    0DH                ;carriage return character
  27. lf      equ    0AH                ;line feed character
  28.  
  29. stdin   equ    0000H              ;standard input
  30. stdout  equ    0001H              ;standard output
  31. u       equ    01H                ;upper case option selected
  32.  
  33. buf_size       equ     8192       ;size of input and output buffers
  34.  
  35. param_count    equ     [80H]
  36. param_area     equ     [81H]
  37. mem_avail      equ     [06H]      ;PSP field: memory available in segment
  38.  
  39. up_mask        equ     11011111B  ;mask for lowercase conversion (with AND)
  40. low_mask       equ     00100000B  ;mask for uppercase conversion (with OR)
  41.  
  42. main   proc    far
  43.        call    setup           ;check dos, parse options
  44.        call    process         ;count w, l, c from std i/o
  45.        int     20H             ;and return to dos
  46.        endp
  47.  
  48. ;======================================
  49. ; SUBROUTINE SETUP
  50. ; Checks for proper DOS, parses options
  51. ;======================================
  52. setup  proc    near
  53.  
  54.        mov     ah, @dosver     ;what dos are we under?
  55.        int     21H
  56.        cmp     al, 2           ;2.0 or over?
  57.        jae     a_mem           ;yes, skip
  58.  
  59.        mov     ah, @write      ;no, bitch
  60.        mov     bx, 2           ;on stderror
  61.        mov     cx, dosend-baddos
  62.        mov     dx, offset(baddos)
  63.        int     21H
  64.  
  65.        pop     ax              ;reset stack
  66.        int     20H             ;and exit
  67.  
  68. a_mem  mov     ax, mem_avail   ;do we have room for the buffers?
  69.        cmp     ax, (buf_size*2)+200H
  70.        jae     a_help          ;yes
  71.        mov     ah, @write      ;no, bitch
  72.        mov     bx, 2           ;on stderror
  73.        mov     cx, memend-nomem
  74.        mov     dx, offset(nomem)
  75.        int     21H
  76.        pop     ax              ;reset stack
  77.        int     20H             ;and exit
  78.  
  79. a_help xor     ch,ch           ;cx <== param count
  80.        mov     cl, param_count ;  "
  81.        cmp     cl, 00H         ;any params?
  82.        je      aexit           ;return if none
  83.  
  84.        mov     di, offset(param_area)   ;scan for help request
  85.        mov     al, '?'
  86.        repnz                   ;repeat until matched or end
  87.        scasb
  88.        jnz     a_par           ;reached end, no match? skip
  89.        mov     ah, @write      ;founc ?, so print help
  90.        mov     bx, 2           ;on stderror
  91.        mov     cx, helpend-help
  92.        mov     dx, offset(help)
  93.        int     21H
  94.        pop     ax              ;pop stack
  95.        int     20H             ;and exit
  96.  
  97. a_par  xor     ch, ch                   ;cx <== param count
  98.        mov     cl, param_count          ;  "
  99.        mov     di, offset(param_area)   ;scan for options
  100. a_loop mov     al, '/'                  ;will be marked with /
  101.        repnz                   ;repeat until matched or end
  102.        scasb
  103.        jnz     aexit           ;reached end, no match? skip
  104.  
  105.        xor     ax,ax           ;will hold building number
  106.        jmps    enter           ;convert string to binary
  107.  
  108. s2bin  mov     bl, 10          ;multiply running total by 10
  109.        mul     al,bl
  110.        jo      bad_num         ;overflow?  error exit
  111. enter  xor     bx,bx           ;clear out top half
  112.        mov     bl, [di]        ;get a digit into al
  113.        inc     di              ;bump pointer
  114.        cmp     bl, ' '         ;if space, done
  115.        je      aexit
  116.        cmp     bl, '0'         ;must be between 0
  117.        jb      bad_num
  118.        cmp     bl, '9'         ;and 9
  119.        ja      bad_num
  120.        sub     bl, '0'         ;convert to binary
  121.        add     ax, bx          ;add to running total
  122.        jo      bad_num         ;overflow? error exit
  123.        loop    s2bin
  124.  
  125.        cmp     ax, 0FFH        ;too long?
  126.        jg      bad_num         ;abort
  127.        mov     comp_length, al ;else store converted number
  128. aexit
  129.        ret                     ;normal return
  130.  
  131. bad_num        mov     ah, @write      ;print error message
  132.                mov     bx, 2           ;on stderror
  133.                mov     cx, numend-nummsg
  134.                mov     dx, offset(nummsg)
  135.                int     21H             ;and use default
  136.                ret
  137.  
  138. baddos db      cr lf 'This program requires DOS 2.0!' cr, lf
  139. dosend
  140.  
  141. nomem  db      cr lf 'Insufficient memory, program aborted' cr lf
  142. memend
  143.  
  144. nummsg db      cr lf 'Length parameter non-numeric or greater than 255'
  145.        db      cr lf
  146. numend
  147.  
  148. help   db      cr lf
  149.        db      'DUP version 1.0 by D. Whitman' cr lf
  150.        db      cr lf
  151.        db      'Reads stdin and writes all non-duplicated lines to stdout.'
  152.        db      cr lf
  153.        db      'Duplicates must be adjacent to be detected.' cr lf
  154.        db      'DUP will normally be used in a pipeline, following SORT.'
  155.        db      cr lf cr lf
  156.        db      'Syntax:  DUP [?] [/nn] [<infile] [>outfile]' cr lf
  157.        db      cr lf
  158.        db      'Options:' cr lf
  159.        db      '    ?   = print this help message' cr lf
  160.        db      '    /nn = base comparision on first nn chars only' cr lf
  161.        db      cr lf
  162.        db      'This program is in the public domain.' cr lf
  163.        db      cr lf
  164. helpend
  165.        endp
  166.  
  167. ;=========================================
  168. ; SUBROUTINE PROCESS
  169. ;
  170. ;   while not(EOF) do
  171. ;     begin
  172. ;       get next line
  173. ;       if curr_line <> last_line
  174. ;          then begin
  175. ;             write(curr_line)
  176. ;             last_line := curr_line
  177. ;          end
  178. ;      end
  179. ;==========================================
  180.  
  181. ;==================
  182. ; Register assignments:
  183. ;
  184. ; SI  ^buf_in
  185. ; DI  ^buf_out
  186. ; CX  # of chars left in buf_in
  187. ;===================
  188.  
  189. process proc near
  190.         movw outnum, 0000H      ;output buffer is empty
  191.         mov  si, offset(buf_in)
  192.         mov  di, offset(buf_out)
  193.  
  194.         call fillbuf            ;get 1st buffer's worth
  195.         cmp  cx, 0000H          ;any chars?
  196.         je   p_done             ;if not, quit
  197.         call read_line          ;read 1st line
  198.         call save_line          ;save as "old_line"
  199.         call put_line           ;and output it
  200.         ;===========
  201.         ; Main loop
  202.         ;===========
  203. p_loop  call read_line          ;get next line
  204.         jc   p_done             ;none available? done
  205.         call compare            ;is it unique?
  206.         jc   p_loop             ;if not, bit bucket, and try again
  207.         call put_line           ;if so, output it
  208.         call save_line          ;and save as new template
  209.         jmps p_loop             ;and continue til EOF
  210.  
  211. p_done  call dumpbuf            ;flush output buffer
  212.         ret
  213.         endp
  214. ;=======================================================
  215. ; SUBROUTINE READLINE
  216. ;
  217. ; Reads the next line from the input buffer into string
  218. ; CURR_LINE.  If sucessful, clears the carry flag.
  219. ; If not sucessful, sets the carry flag
  220. ;=======================================================
  221. read_line proc near
  222.           push bx
  223.           push dx
  224.           xor  dx, dx
  225.  
  226.           mov  bx, offset(curr_line)
  227.           call getchar
  228.           jc   r_fail
  229.  
  230. r_loop    mov  [bx], al           ;put char in string
  231.           inc  bx                 ;bump string pointer
  232.           inc  dl                 ;bump char count
  233.           cmp  al, lf             ;newline?
  234.           je   r_exit             ;done if so
  235.           cmp  dl, 0FFH           ;string too long?
  236.           je   r_exit             ;abort if so
  237.           call getchar            ;get next character
  238.           jc   r_exit             ;none available? exit
  239.           jmps r_loop             ;otherwise continue
  240.  
  241. r_exit    mov  [offset(curr_length)], dl    ;save length
  242.           pop  dx
  243.           pop  bx
  244.           clc
  245.           ret
  246.  
  247. r_fail    pop  dx
  248.           pop  bx
  249.           stc
  250.           ret
  251.           endp
  252.  
  253. ;==================================
  254. ; SUBROUTINE SAVE_LINE
  255. ;
  256. ; Copies CURR_LINE into LAST_LINE.
  257. ;==================================
  258. save_line proc  near
  259.           push  si
  260.           push  di
  261.           push  cx
  262.           mov   si, offset(curr_line)
  263.           mov   di, offset(last_line)
  264.           xor   cx, cx
  265.           mov   cl, [offset(curr_length)]
  266.           mov   [offset(last_length)], cl
  267.           cld       ;autoincrement mode
  268.           rep
  269.           movsb
  270.           pop   cx
  271.           pop   di
  272.           pop   si
  273.           ret
  274.           endp
  275.  
  276. ;==================================================
  277. ; SUBROUTINE COMPARE
  278. ;
  279. ; Compares CURR_LINE and LAST_LINE.  If identical,
  280. ; sets carry flag, otherwise carry is cleared.
  281. ;==================================================
  282. compare  proc  near
  283.          push  si
  284.          push  di
  285.          push  cx
  286.  
  287.          xor   cx, cx
  288.          mov   cl, [offset(curr_length)]   ;set comparison length
  289.          cmp   cl, comp_length
  290.          ja    c_trunc           ;longer than compare length? truncate
  291.          jmps  c_doit
  292. c_trunc  mov   cl, comp_length
  293.  
  294. c_doit   mov   di, offset(curr_line)
  295.          mov   si, offset(last_line)
  296.          repe                    ;repeat until different or end
  297.          cmpsb
  298.          je c_match              ;matched
  299.          clc                     ;not identical
  300.          jmps c_exit
  301. c_match  stc
  302. c_exit   pop  cx
  303.          pop  di
  304.          pop  si
  305.          ret
  306.          endp
  307.  
  308. ;================================================
  309. ; SUBROUTINE PUT_LINE
  310. ;
  311. ; Moves the current line into the output buffer.
  312. ;================================================
  313. put_line proc  near
  314.          push  bx
  315.          push  dx
  316.  
  317.          mov   bx, offset(curr_line)
  318.          xor   dx, dx
  319.          mov   dl, [offset(curr_length)]
  320.          cmp   dl, 0
  321.          je    pl_done
  322.  
  323. pl_loop  mov   al, [bx]     ;get char
  324.          call  putchar      ;output it
  325.          inc   bx           ;bump string pointer
  326.          dec   dl           ;used one char
  327.          jnz   pl_loop      ;loop til done
  328.  
  329. pl_done  pop   dx
  330.          pop   bx
  331.          ret
  332.          endp
  333.  
  334. ;======================================================
  335. ; SUBROUTINE GETCHAR
  336. ;
  337. ; Trys to get a character from the input buffer.
  338. ; If sucessful, returns with character in AL, and carry
  339. ; flag clear.  If unsucessful, sets carry flag.
  340. ;======================================================
  341. getchar proc   near
  342.         cmp    cx, 0000           ;is the buffer empty?
  343.         jne    g1                 ;nope, skip
  344.         call   fillbuf            ;if so, try to refill it
  345.         cmp    cx, 0000           ;still empty?
  346.         je     g_abort            ;then return failure
  347.  
  348. g1      lodsb                     ;get character from [si]
  349.         dec    cx                 ;used up one char
  350.         clc                       ;clear flag to indicate sucess
  351.         ret                       ;and return
  352.  
  353. g_abort stc                       ;set flag for failure
  354.         ret
  355.         endp
  356.  
  357. ;======================================================
  358. ; SUBROUTINE FILLBUF
  359. ;
  360. ; Fills the input buffer from StdIn.  The number of
  361. ; available characters is stored in CX, and SI is reset
  362. ; to the beginning of the buffer.
  363. ;======================================================
  364. fillbuf proc   near
  365.         push    bx
  366.         push    dx
  367.         mov     ah, @read           ;read
  368.         mov     bx, stdin           ;from stdin
  369.         mov     cx, buf_size        ;one buffer's worth
  370.         mov     dx, offset(buf_in)  ;into the input buffer
  371.         int     21H
  372.         mov     cx, ax              ;save number of chars read
  373.         mov     si, offset(buf_in)  ;reset buffer
  374.         pop     dx
  375.         pop     bx
  376.         ret
  377.         endp
  378.  
  379. ;===================================================
  380. ; SUBROUTINE PUTCHAR
  381. ;
  382. ; Moves the character in AL into the output buffer.
  383. ; If the buffer is now full, it is dumped to disk.
  384. ;===================================================
  385.  
  386. putchar proc near
  387.         stosb                   ;move character into buffer
  388.         incw  outnum            ;bump count of chars in buffer
  389.         cmpw  outnum, buf_size  ;is buffer full?
  390.         jl    pu_exit           ;no, skip
  391.         call  dumpbuf           ;yes, dump buffer to disk
  392. pu_exit ret
  393.         endp
  394.  
  395. ;==================================================
  396. ; SUBROUTINE DUMPBUF
  397. ;
  398. ; Dumps the output buffer to StdOut.
  399. ;==================================================
  400. dumpbuf proc near
  401.         push    ax                   ;save active registers
  402.         push    bx                   ; "      "      "
  403.         push    cx                   ; "      "      "
  404.         push    dx                   ; "      "      "
  405.         mov     ah, @write           ;write
  406.         mov     bx, stdout           ;to stdout
  407.         mov     cx, outnum           ;number of chars for output
  408.         mov     dx, offset(buf_out)  ;from output buffer
  409.         int     21H
  410.         movw    outnum, 0            ;reset buffer
  411.         mov     di, offset(buf_out)  ;  "     "
  412.         pop     dx                   ;restore active registers
  413.         pop     cx                   ;   "       "       "
  414.         pop     bx                  ;   "       "       "
  415.         pop     ax                   ;   "       "       "
  416.         ret
  417.         endp
  418. ;=====================================================
  419. ;BUFFERS
  420. ;
  421. ; No space is actually allocated for the buffers.
  422. ; At run time, the program checks to ensure there
  423. ; is suffcient free memory, then uses the memory
  424. ; immediately after itself for buffers.
  425. ;
  426. ; This stratagy minimizes the size of the object file,
  427. ; and lets the program load quicker.
  428. ;======================================================
  429.  
  430. outnum      dw 0000H
  431. comp_length db 0FFH
  432.  
  433. last_length
  434.             org offset($+1)
  435. last_line
  436.             org offset($+0FFH)
  437. curr_length
  438.             org offset($+1)
  439. curr_line
  440.             org offset($+0FFH)
  441. buf_in
  442.             org offset($+buf_size)
  443. buf_out
  444.