home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / MURUTIL4.ZIP / DETAB.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-11-22  |  8.9 KB  |  299 lines

  1.     PAGE    57,132
  2.     TITLE    DETAB -- Expand Tab Codes Filter Routine.
  3.     NAME    DETAB
  4. ;
  5. ;    Usage:
  6. ;               DETAB <INPUT.FIL >OUTPUT.FIL
  7. ;               DETAB <AFILE.TXT | SORT >AFILE.SRT
  8. ;
  9. ;    This is a filter routine which converts tab  codes  to  spaces
  10. ;    while copying the input file to the output file and  filtering
  11. ;    out the FFH byte and all control bytes.   Each carriage-return
  12. ;    is followed by a line-feed code.  Trailing blanks are deleted.
  13. ;    An all-blank line is written simply as a CR/LF combination.
  14. ;
  15. ;    Ground rules:
  16. ;            (1)  All routines must  preserve  any  needed
  17. ;            registers before calling other routines.
  18. ;
  19. ;            (2)  Registers SI and DI index the input  and
  20. ;            the output buffers, respectively.
  21. ;
  22. ;    Program by Harry M. Murphy,  4 March 1987.
  23. ;
  24. ;
  25. ;                               NOTICE
  26. ;
  27. ;       Copyright 1987, Harry M. Murphy.
  28. ;
  29. ;       A general license is hereby  granted  for  non-commercial
  30. ;       use,  copying and free exchange of this  program  without
  31. ;       payment of any royalties,  provided that  this  copyright
  32. ;       notice is not altered nor deleted.   All other rights are
  33. ;       reserved.   This program is supplied as-is and the author
  34. ;       hereby disclaims all warranties,  expressed  or  implied,
  35. ;       including any and all warranties of  merchantability  and
  36. ;       any and all warranties of suitability  for  any  purpose.
  37. ;       Use of this program in  any  way  whatsoever  constitutes
  38. ;       acceptance of the terms of this license.
  39. ;
  40. ;       Harry M. Murphy, Consultant
  41. ;       3912 Hilton Avenue, NE
  42. ;       Albuquerque, NM  87110
  43. ;
  44. ;
  45. BEL    EQU    07H        ;Bell (beep) code.
  46. BUFLEN    EQU    1000H        ;Length of the I/O buffers.
  47. CTLZ    EQU    1AH        ;Control-Z (ASCII SUB) code.
  48. CR    EQU    0DH        ;Carriage Return code.
  49. DOS    EQU    21H        ;DOS interrupt code.
  50. HT    EQU    09H        ;Tab code.
  51. LF    EQU    0AH        ;Line Feed code.
  52. LINLEN    EQU    100H        ;Line length.
  53. STDIN    EQU    0        ;Standard input file handle.
  54. STDOUT    EQU    1        ;Standard output file handle.
  55. TABLEN    EQU    8        ;Tab spacing.
  56. ;
  57. ;
  58. DETAB SEGMENT 'CODE'
  59.     ORG    100H        ;This is a "COM" routine.
  60.     ASSUME    CS:DETAB,DS:DETAB
  61. ;
  62. MAIN    PROC    NEAR        ;DETAB starts here.
  63.     XOR    AX,AX        ;Zero AX and
  64.     MOV    EOF,AX        ;  clear end-of-file flag,
  65.     MOV    LINP,AX        ;    clear input buffer length,
  66.     MOV    LLIN,AX        ;      clear line length,
  67.     MOV    SI,AX        ;        clear input index and
  68.     MOV    DI,AX        ;          clear output index.
  69. ;
  70. MAIN1:    CALL    GETLIN        ;Get a line
  71.     CMP    EOF,0        ;  and skip
  72.     JNE    MAIN2        ;    if end-of file.
  73. ;
  74.     CALL    PUTLIN        ;Else, output the line and
  75.     JMP    MAIN1        ;  loop for another.
  76. ;
  77. MAIN2:    CMP    LLIN,0        ;If the line length is
  78.     JE    MAIN3        ;  zero, then skip to flush.
  79. ;
  80.     CALL    PUTLIN        ;Else, output the last line.
  81. ;
  82. MAIN3:    CALL    FLUSH        ;Flush the output buffer and
  83.     MOV    AX,4C00H    ;  exit with
  84.     INT    DOS        ;    ERRORLEVEL = 0.
  85. MAIN    ENDP
  86. ;
  87. ;
  88. ABORT    PROC    NEAR        ;Abort routine.  Jump to this routine
  89. ;                ;with DX containing the offset of  an
  90. ;                ;ASCIIZ error message.
  91. ;        
  92.     MOV    AH,0EH        ;Prepare for BIOS output text in
  93.     XOR    BX,BX        ;  teletype mode interrupt.
  94.     MOV    SI,DX        ;Copy ASCIIZ pointer to SI and
  95.     CLD            ;  clear direction flag.
  96. ;
  97. ABRT1:    LODSB            ;Get next byte of the message,
  98.     OR    AL,AL        ;  skip to
  99.     JZ    ABRT2        ;    exit on zero.
  100. ;
  101.     INT    10H        ;Else, display the byte and
  102.     JMP    ABRT1        ;  loop for next byte.
  103. ;
  104. ABRT2:    MOV    AX,4C07H    ;Exit with
  105.     INT    DOS        ;  ERRORLEVEL = 7.
  106. ABORT    ENDP
  107. ;
  108. ;
  109. FLUSH    PROC    NEAR        ;Subroutine to flush the output buffer.
  110. ;
  111.     MOV    AL,CTLZ        ;Output a final
  112.     CALL    PUTCH        ;  Control-Z.
  113.     OR    DI,DI        ;If the output buffer is empty,
  114.     JZ    FLUSH2        ;  skip to return.
  115. ;
  116.     MOV    AH,40H        ;Else
  117.     MOV    BX,STDOUT    ;  call DOS
  118.     MOV    CX,DI        ;    to flush
  119.     MOV    DX,OFFSET OUTPUT ;     the output
  120.     INT    DOS        ;        buffer.
  121.     JNC    FLUSH1        ;If no carry, OK.
  122. ;
  123.     MOV    DX,OFFSET WRMSG    ;Else, point to write-error message
  124.     JMP    ABORT        ;  and abort.
  125. ;
  126. FLUSH1:    INC    AX        ;If we wrote all the bytes, or all the
  127.     CMP    AX,DI        ;  bytes except for the CTLZ,
  128.     JAE    FLUSH2        ;    then OK.
  129. ;
  130.     MOV    DX,OFFSET WFMSG    ;Else, point to "full" message
  131.     JMP    ABORT        ;  and abort.
  132. ;
  133. FLUSH2:    XOR    DI,DI        ;Clear the output index and
  134.     RET            ;  return.
  135. FLUSH    ENDP
  136. ;
  137. ;
  138. GETCH    PROC    NEAR        ;Subroutine to get the next  input  byte
  139. ;                ;in AL.  If end-of-file, EOF is returned
  140. ;                ;set to -1, else it's set to 0.
  141. ;
  142.     CMP    SI,LINP        ;If we haven't read the last byte from
  143.     JNE    GETCH2        ;  the input buffer, skip to GETCH2.
  144. ;
  145.     MOV    EOF,0        ;Else, clear the end-of-file flag and
  146.     MOV    AH,3FH        ;  call DOS
  147.     MOV    BX,STDIN    ;    to read
  148.     MOV    CX,BUFLEN    ;      into the
  149.     MOV    DX,OFFSET INPUT    ;        input
  150.     INT    DOS        ;          buffer.
  151.     JNC    GETCH1        ;If no carry, OK.
  152. ;
  153.     MOV    DX,OFFSET RDMSG    ;Else, point to read-error message
  154.     JMP    ABORT        ;  and abort.
  155. ;
  156. GETCH1:    XOR    SI,SI        ;Clear the input index and
  157.     MOV    LINP,AX        ;  copy number of bytes read to LINP.
  158.     OR    AX,AX        ;If the number of bytes
  159.     JNZ    GETCH2        ;  is non-zero, OK.
  160. ;
  161.     DEC    EOF        ;Else, set the end-of-file flag.
  162. ;
  163. GETCH2:    MOV    AL,BYTE PTR INPUT[SI] ;Get byte in AL,
  164.     INC    SI        ;  increment input index and
  165.     RET            ;    return.
  166. GETCH    ENDP
  167. ;
  168. ;
  169. GETLIN    PROC    NEAR        ;Subroutine to get and filter an input
  170. ;                ;line.   If end-of-file,  then EOF is
  171. ;                ;returned set to -1, else it's set to 0.
  172. ;
  173.     MOV    LLIN,0        ;Start:  clear the line length.
  174. ;
  175. GETLN1:    CALL    GETCH        ;Get an input byte in AL,
  176.     CMP    EOF,0        ;  check for end-of-file and
  177.     JNE    GETLN6        ;    skip to return if EOF.
  178. ;
  179.     CMP    AL,0FFH        ;Reject
  180.     JE    GETLN1        ;  FFH bytes.
  181. ;
  182.     CMP    AL,' '        ;Else, accept all bytes equal to, or
  183.     JAE    GETLN3        ;  above, a blank code.
  184. ;
  185.     CMP    AL,CR        ;Else, skip to GETLN4 if it's a
  186.     JE    GETLN4        ;  carriage-return code.
  187. ;
  188.     CMP    AL,HT        ;Else, if it's NOT a tab code,
  189.     JNE    GETLN1        ;  reject it.
  190. ;
  191.     MOV    AX,LLIN        ;(It IS a tab code.)  Divide the
  192.     CWD            ;  current line
  193.     MOV    CX,TABLEN    ;    length by the
  194.     DIV    CX        ;      tab spacing.  (Remainder ==> DX.)
  195.     SUB    CX,DX        ;Spaces = Tab spacing - remainder.
  196.     MOV    AL,' '        ;Get blank in AL and
  197.     MOV    BX,LLIN        ;  current line length in BX.
  198.     MOV    DX,BX        ;Add LLIN and
  199.     ADD    DX,CX        ;  spaces in DX to get new LLIN.
  200.     CMP    DX,LINLEN    ;If the new LLIN >= LINLEN
  201.     JAE    GETLN3        ;  then simply convert HT to a space.
  202. ;
  203. GETLN2:    MOV    BYTE PTR LINE[BX],AL ;Else, expand the tab by
  204.     INC    BX        ;  copying CX blanks to the
  205.     LOOP    GETLN2        ;    line.
  206. ;
  207.     MOV    LLIN,BX        ;Update LLIN to new length and
  208.     JMP    GETLN1        ;  loop for next byte.
  209. ;
  210. GETLN3:    MOV    BX,LLIN        ;Get current line length in BX,
  211.     MOV    BYTE PTR LINE[BX],AL ;copy the byte to the line,
  212.     INC    BX        ;    increment the line length and
  213.     MOV    LLIN,BX        ;      re-store in LLIN.
  214.     CMP    BX,LINLEN    ;If the line isn't full,
  215.     JNE    GETLN1        ;  loop for another byte.
  216. ;
  217. GETLN4:    MOV    BX,LLIN        ;Get the line length in BX and
  218.     OR    BX,BX        ;  if it's zero,
  219.     JZ    GETLN6        ;    skip to return.
  220. ;
  221. GETLN5:    CMP    BYTE PTR LINE[BX-1],' ' ;Else, if the last byte isn't
  222.     JNE    GETLN6        ;  a blank, skip to return.
  223. ;
  224.     DEC    BX        ;Else, decrement the line count in BX
  225.     MOV    LLIN,BX        ;  and LLIN and
  226.     JNZ    GETLN5        ;    loop if BX isn't zero.
  227. ;
  228. GETLN6:    RET            ;Return with the line length in LLIN.
  229. GETLIN    ENDP
  230. ;
  231. ;
  232. PUTCH    PROC    NEAR        ;Subroutine to output the byte in AL.
  233. ;
  234.     MOV    BYTE PTR OUTPUT[DI],AL ;Copy AL to the output buffer,
  235.     INC    DI        ;  and increment the buffer index.
  236.     CMP    DI,BUFLEN    ;If the buffer isn't full,
  237.     JB    PUTCH2        ;  skip to return.
  238. ;
  239.     MOV    AH,40H        ;Else,
  240.     MOV    BX,STDOUT    ;  call DOS to
  241.     MOV    CX,BUFLEN    ;    write the
  242.     MOV    DX,OFFSET OUTPUT ;     output
  243.     INT    DOS        ;        buffer.
  244.     JNC    PUTCH1        ;If no carry, OK.
  245. ;
  246.     MOV    DX,OFFSET WRMSG    ;Else, point to write-error message
  247.     JMP    ABORT        ;  and abort.
  248. ;
  249. PUTCH1:    XOR    DI,DI        ;Clear the output index and
  250.     CMP    AX,BUFLEN    ;  check if all bytes were written.
  251.     JE    PUTCH2        ;    If so, skip to return.
  252. ;
  253.     MOV    DX,OFFSET WFMSG    ;Else, point to "full" message
  254.     JMP    ABORT        ;  and abort.
  255. ;
  256. PUTCH2:    RET            ;Return.
  257. PUTCH    ENDP
  258. ;
  259. ;
  260. PUTLIN    PROC    NEAR        ;Subroutine to output the line in LINE
  261. ;                ;whose length is LLIN.
  262. ;
  263.     MOV    CX,LLIN        ;Get line length in CX and
  264.     OR    CX,CX        ;  if it's zero,
  265.     JZ    PUTLN2        ;    skip to output CR/LF.
  266. ;
  267.     XOR    BX,BX        ;Else clear BX as a line index.
  268. ;
  269. PUTLN1:    MOV    AL,BYTE PTR LINE[BX] ;Get the next byte from LINE in AL
  270.     INC    BX        ;  increment the line index,
  271.     PUSH    BX        ;    save the line index
  272.     PUSH    CX        ;      save the byte count and
  273.     CALL    PUTCH        ;        call PUTCH to output it.
  274.     POP    CX        ;Restore the byte count,
  275.     POP    BX        ;  restore the line index and
  276.     LOOP    PUTLN1        ;    loop to output the next byte.
  277. ;
  278. PUTLN2:    MOV    AL,CR        ;Output a trailing
  279.     CALL    PUTCH        ;  carriage-return and
  280.     MOV    AL,LF        ;    a trailing
  281.     CALL    PUTCH        ;      line-feed and
  282.     RET            ;         return.
  283. PUTLIN    ENDP
  284. ;
  285. ;
  286. RDMSG    DB    CR,LF,'Read error!',CR,LF,BEL,0
  287. WRMSG    DB    CR,LF,'Write error!',CR,LF,BEL,0
  288. WFMSG    DB    CR,LF,'Disk full error!',CR,LF,BEL,0
  289.     EVEN
  290. EOF    DW    0        ;End-of-File flag.
  291. LINP    DW    0        ;Input buffer byte count.
  292. LLIN    DW    0        ;Line length.
  293. ;
  294. LINE    LABEL    BYTE        ;Start of LINE buffer.
  295. INPUT    EQU    LINE+LINLEN    ;Start of INPUT buffer.
  296. OUTPUT    EQU    INPUT+BUFLEN    ;Start of OUTPUT buffer.
  297. DETAB    ENDS
  298.     END    MAIN
  299.