home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / chasm2.zip / DETAB.ASM < prev    next >
Assembly Source File  |  1986-05-12  |  9KB  |  262 lines

  1. ;===================================================
  2. ; PROGRAM DETAB    Version 1.0 by Dave Whitman
  3. ;
  4. ; Filter to expand tabs.
  5. ; System standard tab stops every 8 columns are assumed.
  6. ;
  7. ; Syntax:  DETAB [?] [<infile] [>outfile]
  8. ;
  9. ; The ? option prints a help message.
  10. ;
  11. ; Requires DOS 2.0, will abort under earlier versions.
  12. ;====================================================
  13.  
  14. ;============
  15. ; Equates
  16. ;============
  17.  
  18. @read   equ    3FH                ;read file/device
  19. @write  equ    40H                ;write file/device
  20. @dosver equ    30H                ;get dos version
  21. @prnstr equ    09H                ;print string
  22.  
  23. cr      equ    0DH                ;carriage return character
  24. lf      equ    0AH                ;line feed character
  25. tab     equ    09H                ;horizontal tab character
  26.  
  27. stdin   equ    0000H              ;standard input
  28. stdout  equ    0001H              ;standard output
  29.  
  30. buf_size       equ     8192       ;size of input and output buffers
  31. max_line       equ     255        ;maximum input line length
  32. yes            equ     0FFH       ;boolean true
  33. no             equ     00H        ;boolean false
  34.  
  35. param_count    equ     [80H]
  36. param_area     equ     [81H]
  37. mem_avail      equ     [06H]      ;PSP field: memory available in segment
  38.  
  39. main   proc    far
  40.        call    setup           ;check dos, parse options
  41.        call    stops           ;fill tab stop array
  42.        call    process         ;expand tabs
  43.        int     20H             ;and return to dos
  44.        endp
  45.  
  46. ;======================================
  47. ; SUBROUTINE SETUP
  48. ; Checks for proper DOS, parses options
  49. ;======================================
  50. setup  proc    near
  51.  
  52.        mov     ah, @dosver     ;what dos are we under?
  53.        int     21H
  54.        cmp     al, 2           ;2.0 or over?
  55.        jae     a_mem           ;yes, skip
  56.  
  57.        mov     ah, @prnstr     ;no, bitch
  58.        mov     dx, offset(baddos)
  59.        int     21H
  60.        pop     ax              ;reset stack
  61.        int     20H             ;and exit
  62.  
  63. a_mem  mov     ax, mem_avail   ;do we have room for the buffers and array?
  64.        cmp     ax, buf_size*2+max_line
  65.        jae     a_help          ;yes
  66.        mov     ah, @prnstr     ;no, bitch
  67.        mov     dx, offset(nomem)
  68.        int     21H
  69.        pop     ax              ;reset stack
  70.        int     20H             ;and exit
  71.  
  72. a_help xor     ch,ch           ;cx <== param count
  73.        mov     cl, param_count ;  "
  74.        cmp     cl, 00H         ;any params?
  75.        je      a_exit          ;return if none
  76.  
  77.        mov     di, offset(param_area)   ;scan for help request
  78.        mov     al, '?'
  79.        repnz                   ;repeat until matched or end
  80.        scasb
  81.        jnz     a_exit          ;reached end, no match? skip
  82.        mov     ah, @prnstr     ;found ?, so print help
  83.        mov     dx, offset(help)
  84.        int     21H
  85.        pop     ax              ;pop stack
  86.        int     20H             ;and exit
  87.  
  88. a_exit ret
  89.  
  90. baddos db      cr lf 'This program requires DOS 2.0!' cr, lf, '$'
  91.  
  92. nomem  db      cr lf 'Insufficient memory, program aborted' cr lf '$'
  93.  
  94.  
  95. help   db      cr lf
  96.        db      'DETAB version 1.0 by D. Whitman' cr lf
  97.        db      cr lf
  98.        db      'Syntax:  DETAB [?] [<infile] [>outfile]' cr lf
  99.        db      cr lf
  100.        db      'Reads stdin, expands tab characters, '
  101.        db      'and writes to stdout.' cr lf
  102.        db      'Tab stops are set every 8 columns.' cr lf
  103.        db      cr lf
  104.        db      'Option:' cr lf
  105.        db      '    ?  = print this help message' cr lf
  106.        db      cr lf
  107.        db      'This program is in the public domain.' cr lf
  108.        db      cr lf '$'
  109.        endp
  110.  
  111. ;=========================================
  112. ; SUBROUTINE STOPS
  113. ;
  114. ; Set tab stops in array.  Following the system
  115. ; standard, stops are set every 8 columns.
  116. ;=========================================
  117.  
  118. stops  proc  near
  119.        mov   di, offset(tabstops)      ;point to array
  120.        mov   cx, 1                     ;count columns
  121.        mov   dl, 8                     ;stops every 8 columns
  122. s1     cmp   cx, max_line              ;are we done?
  123.        jg    s_exit                    ;yes, exit
  124.        mov   ax, cx                    ;no, continue: get count
  125.        div   dl                        ;ah gets remainder
  126.        cmp   ah, 0                     ;multiple of eight?
  127.        jne   s2                        ;branch if not
  128.        movb  [di], yes                 ;yes, so mark tab
  129.        jmps  s3                        ;and skip
  130. s2     movb  [di], no                  ;no, mark no tab
  131. s3     inc   cx                        ;bump counts
  132.        inc   di                        ; "     "
  133.        jmps  s1                        ;and loop till done
  134. s_exit ret
  135.        endp
  136.  
  137. ;=========================================
  138. ; SUBROUTINE PROCESS
  139. ;
  140. ;   1. load input buffer
  141. ;   2. convert each char, pass to output buffer
  142. ;   3. dump output buffer
  143. ;   4. repeat until EOF
  144. ;==========================================
  145.  
  146. process proc    near
  147.  
  148.        mov     di, offset(buf_out) ;point to output buffer
  149.        movw    outnum, 0           ;output buffer is empty
  150.        movw    column, 0           ;start in column 0
  151.  
  152. bu1    mov     ah, @read           ;read
  153.        mov     bx, stdin           ;from stdin
  154.        mov     cx, buf_size        ;one buffer's worth
  155.        mov     dx, offset(buf_in)
  156.        int     21H
  157.        cmp     ax, 00H             ;test for EOF
  158.        jz      budone              ;if so, done
  159.  
  160.        mov     cx, ax              ;cx <== number of chars read
  161.        mov     si, offset(buf_in)  ;source is input buffer
  162.  
  163.  
  164. bu2    lodsb                       ;al <== next char from buffer
  165.        mov     bx, column          ;bx <== current column
  166.        cmp     al, tab             ;test if tab character
  167.        jne     bu3                 ;nope, skip
  168.        mov     al, ' '             ;yes, replace with spaces
  169. bu2a   call    putchar             ;send blank to StdOut
  170.        inc     bx                  ;bump column count
  171.        cmp     bx, max_line        ;line overflowing?
  172.        jge     bu2b                ;yes, so assume we're at a stop
  173.        cmpb    offset(tabstops)[bx], yes    ;are we at a stop?
  174.        jne     bu2a                ;no, keep emitting spaces
  175. bu2b   jmps    bu5                 ;yes, so done expanding
  176.  
  177. bu3    cmp     al, lf              ;EOL?
  178.        jne     bu4                 ;nope, skip
  179.        mov     bx, 0               ;reset column counter
  180.        call    putchar             ;print char
  181.        jmps    bu5                 ;and skip
  182.  
  183. bu4    call    putchar             ;otherwise, just send char to StdOut
  184.        inc     bx                  ;and bump column count
  185.  
  186. bu5    mov     column, bx          ;save column count
  187.        loop    bu2                 ;loop until buffer processed
  188.        jmps    bu1                 ;and loop until EOF
  189.  
  190. budone cmpw    outnum, 0           ;input done.  Any outstanding output?
  191.        jle     buexit              ;no, exit
  192.        call    dumpbuf             ;yes, empty buffer
  193. buexit ret
  194.        endp
  195.  
  196. ;===================================================
  197. ; SUBROUTINE PUTCHAR
  198. ;
  199. ; Moves the character in AL into the output buffer.
  200. ; If the buffer is now full, it is dumped to disk.
  201. ;===================================================
  202.  
  203. putchar proc near
  204.         stosb                   ;move character into buffer
  205.         incw  outnum            ;bump count of chars in buffer
  206.         cmpw  outnum, buf_size  ;if buffer full?
  207.         jl  p_exit              ;no, skip
  208.         call dumpbuf            ;yes, dump buffer to disk
  209. p_exit  ret
  210.         endp
  211.  
  212. ;==================================================
  213. ; SUBROUTINE DUMPBUF
  214. ;
  215. ; Dumps the output buffer to StdOut.
  216. ;==================================================
  217. dumpbuf proc near
  218.         push    ax             ;save active registers
  219.         push    bx             ; "      "      "
  220.         push    cx             ; "      "      "
  221.         mov     ah, @write     ;write
  222.         mov     bx, stdout     ;to stdout
  223.         mov     cx, outnum     ;number of chars for output
  224.         mov     dx, offset(buf_out)
  225.         int     21H
  226.         movw    outnum, 0            ;reset buffer
  227.         mov     di, offset(buf_out)  ;  "     "
  228.         pop     cx             ;restore active registers
  229.         pop     bx             ;   "       "       "
  230.         pop     ax             ;   "       "       "
  231.         ret
  232.         endp
  233. ;==================
  234. ; GLOBAL VARIABLES
  235. ;==================
  236.  
  237. innum  dw 0000H      ;number of characters in input buffer
  238. outnum dw 0000H      ;number of characters in output buffer
  239. column dw 0000H      ;current column in line
  240.  
  241. ;=====================================================
  242. ;BUFFERS
  243. ;
  244. ; No space is actually allocated for the buffers.
  245. ; At run time, the program checks to ensure there
  246. ; is suffcient free memory, then uses the memory
  247. ; immediately after itself for buffers.
  248. ;
  249. ; This stratagy minimizes the size of the object file,
  250. ; and lets the program load quicker.
  251. ;======================================================
  252.  
  253. tabstops               ;tab stop array
  254.  
  255.          org offset(tabstops+max_line)
  256.  
  257. buf_in                 ;input buffer
  258.  
  259.          org offset(buf_in+buf_size)
  260.  
  261. buf_out                ;output buffer
  262.