home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advmsdos / chap15 / clean.asm next >
Encoding:
Assembly Source File  |  1988-10-01  |  9.1 KB  |  265 lines

  1.         title   CLEAN - Text file filter 
  2.         page    55,132
  3. ;
  4. ; CLEAN.ASM     Filter to turn document files into
  5. ;               normal text files.
  6. ;
  7. ; Copyright 1988 Ray Duncan
  8. ;
  9. ; Build:        C>MASM CLEAN;
  10. ;               C>LINK CLEAN;
  11. ;                       
  12. ; Usage:        C>CLEAN  <infile  >outfile
  13. ;
  14. ; All text characters are passed through with high 
  15. ; bit stripped off.  Form feeds, carriage returns, 
  16. ; and line feeds are passed through.  Tabs are expanded 
  17. ; to spaces.  All other control codes are discarded.
  18. ;
  19.  
  20. tab     equ     09h             ; ASCII tab code
  21. lf      equ     0ah             ; ASCII line feed
  22. ff      equ     0ch             ; ASCII form feed
  23. cr      equ     0dh             ; ASCII carriage return
  24. blank   equ     020h            ; ASCII space code
  25. eof     equ     01ah            ; Ctrl-Z End-of-file 
  26.  
  27. tabsiz  equ     8               ; width of tab stop
  28.  
  29. bufsiz  equ     128             ; size of input and
  30.                                 ; output buffers
  31.  
  32. stdin   equ     0000            ; standard input handle
  33. stdout  equ     0001            ; standard output handle
  34. stderr  equ     0002            ; standard error handle
  35.  
  36.  
  37. _TEXT   segment word public 'CODE'
  38.  
  39.         assume  cs:_TEXT,ds:_DATA,es:_DATA,ss:STACK 
  40.  
  41. clean   proc    far             ; entry point from MS-DOS.
  42.  
  43.         push    ds              ; save DS:0000 for final
  44.         xor     ax,ax           ; return to MS-DOS, in case
  45.         push    ax              ; Function 4CH can't be used.   
  46.  
  47.         mov     ax,_DATA        ; make data segment addressable
  48.         mov     ds,ax
  49.         mov     es,ax
  50.  
  51.         mov     ah,30h          ; check version of MS-DOS
  52.         int     21h
  53.         cmp     al,2            ; MS-DOS 2.0 or later?
  54.         jae     clean1          ; jump if version OK
  55.  
  56.                                 ; MS-DOS 1.x, display error
  57.                                 ; message and exit...
  58.         mov     dx,offset msg1  ; DS:DX = message address
  59.         mov     ah,9            ; Fxn 9 = display string
  60.         int     21h             ; transfer to MS-DOS
  61.         ret                     ; then exit the old way
  62.  
  63. clean1: call    init            ; initialize input buffer
  64.  
  65. clean2: call    getc            ; get character from input
  66.         jc      clean9          ; exit if end of stream
  67.  
  68.         and     al,07fh         ; strip off high bit
  69.  
  70.         cmp     al,blank        ; is it a control char?
  71.         jae     clean4          ; no, write it
  72.  
  73.         cmp     al,eof          ; is it end of file?
  74.         je      clean8          ; yes, write EOF and exit
  75.  
  76.         cmp     al,tab          ; is it a tab?
  77.         je      clean6          ; yes, expand it to spaces
  78.  
  79.         cmp     al,cr           ; is it a carriage return?
  80.         je      clean3          ; yes, go process it.
  81.  
  82.         cmp     al,lf           ; is it a line feed?
  83.         je      clean3          ; yes, go process it.
  84.  
  85.         cmp     al,ff           ; is it a form feed?
  86.         jne     clean2          ; no, discard it  
  87.  
  88. clean3: mov     column,0        ; if CR, LF, or FF
  89.         jmp     clean5          ; reset column to zero
  90.  
  91. clean4: inc     column          ; if non-control char.
  92.                                 ; increment column counter
  93.                                 
  94. clean5: call    putc            ; write char. to stdout
  95.         jnc     clean2          ; if disk not full,
  96.                                 ; get another character
  97.  
  98.                                 ; write failed...
  99.         mov     dx,offset msg2  ; DS:DX = error message
  100.         mov     cx,msg2_len     ; CX = message length
  101.         mov     bx,stderr       ; BX = standard error handle
  102.         mov     ah,40h          ; Fxn 40H = write
  103.         int     21h             ; transfer to MS-DOS
  104.  
  105.         mov     ax,4c01h        ; Fxn 4CH = terminate
  106.                                 ; return code = 1
  107.         int     21h             ; transfer to MS-DOS
  108.  
  109. clean6: mov     ax,column       ; tab code detected
  110.         cwd                     ; tabsiz - (column MOD tabsiz)
  111.         mov     cx,tabsiz       ; is number of spaces needed
  112.         idiv    cx              ; to move to next tab stop
  113.         sub     cx,dx
  114.  
  115.         add     column,cx       ; also update column counter
  116.  
  117. clean7: push    cx              ; save spaces counter
  118.  
  119.         mov     al,blank        ; write an ASCII space
  120.         call    putc
  121.  
  122.         pop     cx              ; restore spaces counter
  123.         loop    clean7          ; loop until tab stop 
  124.  
  125.         jmp     clean2          ; get another character
  126.                                 
  127. clean8: call    putc            ; write EOF mark
  128.  
  129. clean9: call    flush           ; write last output buffer
  130.         mov     ax,4c00h        ; Fxn 4CH = terminate
  131.                                 ; return code =0
  132.         int     21h             ; transfer to MS-DOS
  133.  
  134. clean   endp
  135.  
  136.  
  137. getc    proc    near            ; get char. from stdin
  138.                                 ; returns Carry = 1 if
  139.                                 ; end of input, else
  140.                                 ; AL = char, Carry = 0
  141.  
  142.         mov     bx,iptr         ; get input buffer pointer
  143.         cmp     bx,ilen         ; end of buffer reached?
  144.         jne     getc1           ; not yet, jump
  145.  
  146.                                 ; more data is needed...
  147.         mov     bx,stdin        ; BX = standard input handle
  148.         mov     cx,bufsiz       ; CX = length to read
  149.         mov     dx,offset ibuff ; DS:DX = buffer address
  150.         mov     ah,3fh          ; Fxn 3FH = read
  151.         int     21h             ; transfer to MS-DOS
  152.         jc      getc2           ; jump if read failed
  153.         
  154.         or      ax,ax           ; was anything read?
  155.         jz      getc2           ; jump if end of input
  156.  
  157.         mov     ilen,ax         ; save length of data
  158.         xor     bx,bx           ; reset buffer pointer
  159.  
  160. getc1:  mov     al,[ibuff+bx]   ; get char. from buffer
  161.         inc     bx              ; bump buffer pointer
  162.  
  163.         mov     iptr,bx         ; save updated pointer
  164.         clc                     ; return char in AL
  165.         ret                     ; and Carry = 0 (clear)
  166.  
  167. getc2:  stc                     ; end of input stream
  168.         ret                     ; return Carry = 1 (set)
  169.  
  170. getc    endp
  171.  
  172.  
  173. putc    proc    near            ; send char. to stdout
  174.                                 ; returns Carry = 1 if
  175.                                 ; error, else Carry = 0
  176.  
  177.         mov     bx,optr         ; store character into
  178.         mov     [obuff+bx],al   ; output buffer
  179.  
  180.         inc     bx              ; bump buffer pointer
  181.         cmp     bx,bufsiz       ; buffer full?
  182.         jne     putc1           ; no, jump
  183.  
  184.         mov     bx,stdout       ; BX = standard output handle
  185.         mov     cx,bufsiz       ; CX = length to write
  186.         mov     dx,offset obuff ; DS:DX = buffer address
  187.         mov     ah,40h          ; Fxn 40H = write
  188.         int     21h             ; transfer to MS-DOS
  189.         jc      putc2           ; jump if write failed
  190.  
  191.         cmp     ax,cx           ; was write complete?
  192.         jne     putc2           ; jump if disk full
  193.  
  194.         xor     bx,bx           ; reset buffer pointer
  195.  
  196. putc1:  mov     optr,bx         ; save buffer pointer
  197.         clc                     ; write successful,
  198.         ret                     ; return Carry = 0 (clear)
  199.  
  200. putc2:  stc                     ; write failed or disk full,
  201.         ret                     ; return Carry = 1 (set)
  202.  
  203. putc    endp
  204.  
  205.  
  206. init    proc    near            ; initialize input buffer
  207.  
  208.         mov     bx,stdin        ; BX = standard input handle
  209.         mov     cx,bufsiz       ; CX = length to read
  210.         mov     dx,offset ibuff ; DS:DX = buffer address
  211.         mov     ah,3fh          ; Fxn 3FH = read
  212.         int     21h             ; transfer to MS-DOS
  213.         jc      init1           ; jump if read failed
  214.         mov     ilen,ax         ; save actual bytes read
  215. init1:  ret
  216.  
  217. init    endp
  218.  
  219.  
  220. flush   proc    near            ; flush output buffer
  221.  
  222.         mov     cx,optr         ; CX = bytes to write
  223.         jcxz    flush1          ; exit if buffer empty
  224.         mov     dx,offset obuff ; DS:DX = buffer address
  225.         mov     bx,stdout       ; BX = standard output handle
  226.         mov     ah,40h          ; Fxn 40H = write
  227.         int     21h             ; transfer to MS-DOS
  228. flush1: ret
  229.  
  230. flush   endp
  231.  
  232. _TEXT   ends
  233.  
  234.  
  235. _DATA   segment word public 'DATA'
  236.  
  237. ibuff   db      bufsiz dup (0)  ; input buffer
  238. obuff   db      bufsiz dup (0)  ; output buffer
  239.  
  240. iptr    dw      0               ; ibuff pointer
  241. ilen    dw      0               ; bytes in ibuff
  242. optr    dw      0               ; obuff pointer 
  243.  
  244. column  dw      0               ; current column counter
  245.  
  246. msg1    db      cr,lf
  247.         db      'clean: need MS-DOS version 2 or greater.'
  248.         db      cr,lf,'$'
  249.  
  250. msg2    db      cr,lf
  251.         db      'clean: disk is full.'
  252.         db      cr,lf
  253. msg2_len equ    $-msg2
  254.  
  255. _DATA   ends
  256.  
  257.  
  258. STACK   segment para stack 'STACK'
  259.  
  260.         dw      64 dup (?)
  261.  
  262. STACK   ends
  263.  
  264.         end     clean
  265.