home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / assemutl.zip / TABS.ASM < prev    next >
Assembly Source File  |  1984-05-04  |  18KB  |  519 lines

  1. r
  2. Title   TABS - Align ASCII File
  3.         Page    82,132
  4.         Comment | Version 1.2, April 27, 1984
  5.  
  6. TABS Command
  7. -----------------
  8.  
  9. Purpose:   Replace blanks with TAB character(s).
  10.  
  11. Format:    TABS  d:input.ext  d:output.ext
  12.  
  13. Remarks:   Any TAB characters found are first expanded. Thus, if TABS
  14.         appear within quoted strings - out of context - they will
  15.         be expanded incorrectly.
  16.  
  17.         In replacing blanks with tabs, quoted strings are ignored.
  18.         The maximum logical record size is 255, see MAXREC equate.
  19.         Defacto tab columns are 9,17,25,...
  20.  
  21.         V. Buerg, March, 1984. For public domain use.
  22.  
  23. -----------------                                       |
  24.  
  25. Cseg    Segment Public Para 'CODE'
  26.         Assume  CS:Cseg,DS:Cseg,ES:Nothing
  27.  
  28. Tabs    Proc    Far
  29.         Push    DS                      ;DOS convention
  30.         Sub     AX,AX
  31.         Push    AX
  32.         Mov     CS:Stk_Top,SP           ;Save stack ptr to insure return
  33.         Mov     AH,30h
  34.         Int     21h                     ;Verify DOS 2.0 or later
  35.         Mov     DX,Offset Sorry
  36.         Cmp     AL,2
  37.         Jb      Error
  38.  
  39.         Call    GetFile                 ;Get file names
  40.  
  41.         Call    OpenIn                  ;Open input
  42.  
  43.         Call    OpenOut                 ;Open output
  44.  
  45.         Call    Inform                  ;Display "cooking" message
  46.  
  47.         Call    GenTab                  ;Generate tabs
  48.  
  49.         Call    Flush                   ;Empty the output buffer
  50.  
  51.         Mov     DX,Offset EofMsg        ;Say END-OF-FILE
  52. Error:  Mov     SP,Stk_Top              ;Insure proper return
  53.         Mov     AH,9                    ;Print any message
  54.         Int     21h
  55.  
  56.         Call    Close                   ;Close files
  57.  
  58.         Ret                             ;Return to DOS
  59.         Page
  60.  
  61. Buflen  Equ     16*1024                 ;I/O buffer size
  62. Maxrec  Equ     255                     ;Longest logical record
  63.  
  64. S_Quote Equ     34                      ;Single quote
  65. D_Quote Equ     39                      ;Double quote
  66. Tab     Equ     9
  67. Lf      Equ     10
  68. Cr      Equ     13
  69. Eof     Equ     1Ah
  70.  
  71. Rec     Db      Maxrec Dup (0)          ;Current record
  72. Rlen    Dw      0                       ;Current record length
  73. Sw      Db      0                       ;Number of blanks skipped
  74. Qsw     Db      0                       ;Quote switch
  75. Stk_Top Dw      0                       ;SP at entry
  76.  
  77. MsgIn   Db      Cr,Lf,'Enter INPUT file name>  $'
  78. Msg1    Db      Cr,Lf,'Input failed to open>'
  79. InKey   Db      32,32                   ;Keyboard buffer
  80. Input   Db      64 Dup (0),0,'$'        ;Drive:path\name.ext
  81. IHandle Dw      0                       ;Input file handle
  82. Ilen    Dw      0                       ;Input block length
  83. Iptr    Dw      0                       ;Offset to next char
  84.  
  85. MsgOut  Db      Cr,Lf,'Enter OUTPUT file name> $'
  86. Msg2    Db      Cr,Lf,'Output failed to open>'
  87. OutKey  Db      32,32
  88. Output  Db      64 Dup (0),0,'$'
  89. OHandle Dw      0                       ;Output file handle
  90. Olen    Dw      0                       ;Output block size
  91. Optr    Dw      0                       ;Offset to next char
  92.  
  93. Sorry   Db      Cr,Lf,'Sorry, PC DOS Version 2 required',Cr,Lf,'$'
  94. Msg3    Db      Cr,Lf,'I/O error reading',Cr,Lf,'$'
  95. Msg4    Db      Cr,Lf,'I/O error writing',Cr,Lf,'$'
  96. Cooking Db      Cr,Lf,'TABBING:  $'
  97. Mark    Db      ' => $'
  98. EofMsg  Db      Cr,Lf,'End of File',Cr,Lf,'$'
  99. NewLine Db      CR,LF,'-$'
  100.  
  101. Code2   Db      'File not found $'
  102. Code3   Db      'Path not found $'
  103. Code4   Db      'Too many files $'
  104. Code5   Db      'Access denied  $'
  105.         Page
  106.  
  107.         ;       Replace blanks with tabs
  108.  
  109. GenTab  Proc    Near
  110. Loop:   Call    GetRec                  ;Get a record
  111.         Mov     CX,Rlen                 ; its length
  112.         Sub     BX,BX                   ;Output column
  113.         Mov     Sw,0                    ;No blanks yet
  114.         Mov     Qsw,0                   ;No quotes yet
  115.         Or      CX,CX                   ;Any data in record?
  116.         Jnz     Set1
  117.         Jmp     Null                    ; no, just CR-LF
  118.  
  119. Set1:   Mov     SI,Offset Rec           ;Look for blanks and
  120. Wloop:  Lodsb                           ; replace strings of blanks
  121.         Inc     BX                      ; with tab characters
  122.         Cmp     AL,D_Quote              ;Don't count blanks
  123.         Jne     Chk1                    ; within single or double
  124.         Xor     Qsw,2                   ; quoted strings
  125.         Jmp     Chk2
  126.  
  127. Chk1:   Cmp     AL,S_Quote              ;Insert TABs for any
  128.         Jne     Chk3                    ; blanks skipped before
  129.         Xor     Qsw,1                   ; a quote
  130. Chk2:   Cmp     Sw,0                    ;Must re-insert
  131.         Je      Check                   ; any blanks skipped
  132.         Jmp     Insert                  ; if not enough for a TAB
  133.  
  134. Chk3:   Cmp     AL,' '                  ;Tis a blank?
  135. ;       Jmp     Check                   ;for DETAB
  136.         Jne     Check                   ; no, see if eof
  137.         Test    Qsw,3                   ;Within quotes?
  138.         Jnz     Check
  139.         Inc     Sw
  140.         Test    BL,07h                  ;Ready for a tab?
  141.         Jnz     Tloop                   ; no, keep going
  142.         Mov     AL,Tab                  ; yes, send one
  143.         Jmp     Copy
  144.  
  145. Check:  Cmp     AL,Eof                  ;End of file?
  146.         Je      Done                    ; yes, all done
  147. ;       Jmp     Copy                    ;for DETAB
  148.         Test    Qsw,3                   ;When a non-blank is
  149.         Jnz     Copy                    ; encountered, insert a TAB
  150.         Cmp     Sw,0                    ; if there were blanks
  151.         Je      Copy                    ; before it
  152.         Mov     DX,BX
  153.         Dec     DL
  154.         Test    DL,07h                  ;If the non-blank is not
  155.         Jnz     Insert                  ; in a TAB column, then
  156.         Push    AX                      ; keeps all the blanks
  157.         Mov     AL,Tab
  158.         Call    PutChar
  159.         Pop     AX
  160.         Jmp     Copy
  161.  
  162. Insert: Push    AX                      ;Insert any blanks that
  163.         Mov     DL,Sw                   ; didn't line up on
  164. Blanks: Cmp     DL,1                    ; a TAB column
  165.         Jb      None
  166.         Mov     AL,' '
  167.         Call    PutChar
  168.         Dec     DL                      ;Decr insert count
  169.         Jmp     Blanks                  ; and continue
  170.  
  171. None:   Pop     AX                      ;Get char back
  172. Copy:   Call    PutChar                 ; and write it
  173.         Mov     Sw,0                    ;Ind not blank
  174. Tloop:  Loop    Wloop
  175. Null:   Mov     AL,Cr                   ;Append CR
  176.         Call    PutChar
  177.         Mov     AL,Lf                   ; and LF
  178.         Call    PutChar
  179.         Jmp     Loop
  180. Done:   Ret
  181. GenTab  Endp
  182.         Page
  183.  
  184.         ;       Build a logical record
  185.  
  186. GetRec  Proc    Near
  187.         Push    DI
  188.         Sub     DI,DI                   ;Target record offset
  189.         Mov     Rlen,0                  ; and length
  190.         Mov     Qsw,0                   ;Quote indicator
  191.  
  192. Get1:   Call    GetChar                 ;Build up a logical record
  193.         Cmp     AL,Cr                   ; by looking for a CR or LF
  194.         Je      Get1                    ; as end-of-record
  195.         Cmp     AL,Lf
  196.         Je      Get7
  197.         Cmp     AL,S_Quote              ;Don't expand tabs
  198.         Jne     Get2                    ; found within a
  199.         Xor     Qsw,1                   ; quoted string
  200. Get2:   Cmp     AL,D_Quote
  201.         Jne     Get3
  202.         Xor     Qsw,2
  203. Get3:   Cmp     AL,Tab                  ;Is it TAB?
  204.         Jne     Get5                    ; no, pass it
  205.         Test    Qsw,3                   ;Within quotes?
  206.         Jnz     Get5                    ; yes, pass it
  207. Get4:   Mov     Rec[DI],' '             ;Expand embedded tabs
  208.         Inc     DI                      ; with blanks
  209.         Test    DI,0007h
  210.         Jz      Get1
  211.         Jmp     Get4
  212.  
  213. Get5:   Mov     Rec[DI],AL              ;Build the record by
  214.         Inc     DI                      ; copying each character
  215.         Cmp     DI,Maxrec               ; or TABs expanded to blanks
  216.         Jae     Get6
  217.         Cmp     AL,Eof                  ;Is it EOF?
  218.         Je      Get6                    ; yes, all done
  219.         Jmp     Get1                    ; no, continue
  220. Get6:   Mov     Rlen,DI                 ;Final record length
  221.         Pop     DI
  222.         Ret
  223.  
  224. Get7:   Cmp     Rec-1[DI],' '           ;Strip trailing blanks
  225.         Jne     Get6
  226.         Dec     DI
  227.         Jz      Get6
  228.         Jmp     Get7
  229.  
  230. GetRec  Endp
  231.         Page
  232.         ;       Extract one char from record
  233.  
  234. GetChar Proc    Near                    ;Read char into AL
  235.         Push    CX
  236.         Push    SI
  237. Read1:  Cmp     Ilen,0                  ;Any in buffer?
  238.         Je      Read                    ; no, read next block
  239.         Mov     SI,Iptr                 ; yes, get offset in buf
  240.         Push    DS
  241.         Mov     AX,Seg InBuf            ;Copy a char from the
  242.         Mov     DS,AX                   ; input (segment) buffer
  243.         Lodsb
  244.         Pop     DS
  245.         Mov     Iptr,SI                 ;Offset for next one
  246.         Dec     Ilen                    ;Decr buffer size left
  247.         Jmp     Read4                   ; and return with AL
  248.  
  249. Read:   Mov     BX,IHandle              ;Read a block of data
  250.         Mov     CX,BufLen               ; into Input (segment) buffer
  251.         Sub     DX,DX
  252.         Push    DS
  253.         Mov     AX,Seg InBuf
  254.         Mov     DS,AX
  255.         Mov     AH,3Fh
  256.         Int     21h
  257.         Pop     DS
  258.         Mov     Iptr,0                  ;Reset buffer ptr
  259.         Mov     Ilen,AX                 ; and length
  260.         Jc      Read2
  261.         Or      AX,AX                   ;Anything read?
  262.         Jnz     Read1                   ; yes, pick it up
  263.         Mov     AL,Eof                  ; no, return EOF
  264.         Jmp     Read4
  265.  
  266. Read2:  Mov     DX,Offset Msg3          ;Say I/O ERROR
  267.         Jmp     Error
  268.  
  269. Read4:  Pop     SI
  270.         Pop     CX
  271.         Ret
  272. GetChar Endp
  273.         Page
  274.  
  275.         ;       Block output records
  276.  
  277. PutChar Proc    Near                    ;Write from AL
  278.         Push    AX
  279.         Push    BP
  280.         Push    BX
  281.         Push    CX
  282.         Push    DI
  283.         Push    DX
  284.         Mov     DI,Optr                 ;Offset in buffer
  285.         Mov     DX,Seg OutBuf
  286.         Push    ES                      ;Get buffer segment
  287.         Mov     ES,DX
  288.         Stosb                           ;Place into buffer
  289.         Pop     ES
  290.         Inc     Olen                    ;Incr the length
  291.         Mov     Optr,DI                 ; and buffer ptr
  292.         Cmp     Olen,Buflen             ;Full block?
  293.         Jb      Write2                  ; no, return
  294.         Mov     CX,Buflen               ; yes,write it
  295.         Jmp     Write3
  296.  
  297. Flush:  Push    AX                      ;Write data left over
  298.         Push    BP                      ; in output buffer
  299.         Push    BX
  300.         Push    CX
  301.         Push    DI
  302.         Push    DX
  303.         Mov     CX,Olen                 ;Any left in output?
  304.         Or      CX,CX
  305.         Jz      Write2
  306.  
  307. Write3: Mov     BX,OHandle              ;Get file handle
  308.         Mov     BP,CX                   ;Save size requested
  309.         Sub     DX,DX
  310.         Push    DS                      ;Set up DS:DX
  311.         Mov     AX,Seg OutBuf           ; in buffer segment
  312.         Mov     DS,AX
  313.         Mov     AH,40h                  ;Write the block
  314.         Int     21h
  315.         Pop     DS
  316.         Mov     Optr,0                  ;Reset buffer ptr
  317.         Mov     Olen,0                  ; and size used
  318.         Jc      Writer                  ;Write OK?
  319.         Cmp     BP,AX                   ;Wrote all data?
  320.         Je      Write2                  ; yes, good
  321. Writer: Mov     DX,Offset Msg4          ; no, say I/O error
  322.         Jmp     Error
  323.  
  324. Write2: Pop     DX
  325.         Pop     DI
  326.         Pop     CX
  327.         Pop     BX
  328.         Pop     BP
  329.         Pop     AX
  330.         Ret
  331. PutChar Endp
  332.         Page
  333.  
  334.         ;       Open input file
  335.  
  336. OpenIn  Proc    Near
  337.         Mov     DX,Offset Input
  338.         Mov     AL,0                    ;For input
  339.         Mov     AH,3Dh                  ;Open a file
  340.         Int     21h
  341.         Jnc     Openi
  342.         Mov     DX,Offset Msg1
  343.         Jmp     OpenErr
  344.  
  345. Openi:  Mov     IHandle,AX
  346.         Ret
  347. OpenIn  Endp
  348.  
  349.         ;       Open output file
  350.  
  351. OpenOut Proc    Near
  352.         Mov     DX,Offset Output
  353.         Sub     CX,CX                   ;Normal file attribute
  354.         Mov     AH,3Ch                  ;Create a file
  355.         Int     21h
  356.         Jnc     Openo
  357.         Mov     DX,Offset Msg2
  358.         Jmp     OpenErr
  359.  
  360. Openo:  Mov     OHandle,AX
  361.         Ret
  362. OpenOut Endp
  363.  
  364.         ;       Determine why OPEN failed
  365.  
  366. OpenErr:Cmp     AL,2                    ;AL has reason code
  367.         Jb      Opene
  368.         Cmp     AL,5
  369.         Ja      Opene
  370.         Sub     BX,BX                   ;Get offset to reason
  371.         Mov     BL,AL                   ; text for open failure
  372.         Mov     CL,4
  373.         Shl     BX,CL
  374.         Mov     AH,9                    ;Say OPEN FAILED
  375.         Int     21h
  376.         Mov     DX,Offset NewLine
  377.         Mov     AH,9
  378.         Int     21h
  379.         Lea     DX,Code2-32[BX]
  380. Opene:  Jmp     Error
  381.  
  382.         ;       Close input/output
  383.  
  384. Close   Proc    Near                    ;Close files
  385.         Mov     BX,IHandle              ; input
  386.         Mov     AH,3Eh
  387.         Int     21h
  388.         Mov     BX,OHandle              ; output
  389.         Mov     AH,3Eh
  390.         Int     21h
  391.         Ret
  392. Close   Endp
  393.         Page
  394.  
  395.         ;       Get file names from command line
  396.  
  397. GetFile Proc    Near                    ;Get file name(s)
  398.         Push    CS                      ;DS points to PSB
  399.         Pop     ES                      ;Now ES points to data
  400.         Mov     SI,80h                  ;Point to command line
  401.         Sub     BP,BP                   ;Indicates first or second name
  402.         Sub     CH,CH                   ;The PSP may contain one or two
  403.         Or      CL,Byte Ptr DS:[SI]     ; filenames separated by blanks
  404.         Jz      GetF5
  405.         Lea     DI,ES:Input
  406.         Inc     SI
  407.  
  408. GetF1:  Lodsb                           ;Copy command line to file names
  409.         Cmp     AL,' '                  ; by skipping leading blanks
  410.         Jne     GetF2                   ; until a CR is found
  411.         Or      BP,BP                   ; or until the length is zero
  412.         Jz      GetF4                   ;If a second blank is found,
  413.         Mov     AX,2400h                ; append zero and dollar sign
  414.         Stosw
  415.         Lea     DI,ES:Output            ; and it starts the second file name
  416.         Jmp     GetF4
  417.  
  418. GetF2:  Cmp     AL,Cr                   ;Is it CR, end of line?
  419.         Je      GetF5                   ; yes, end of command
  420.         Stosb                           ; no, save in name
  421.         Mov     BP,DI                   ; and indicate data copied
  422. GetF4:  Loop    GetF1
  423.  
  424. GetF5:  Mov     AX,2400h                ;Append zero and dollar sign
  425.         Stosw
  426.         Mov     AX,CS                   ;When done, set up
  427.         Mov     DS,AX                   ; segment registers
  428.  
  429. GetF7:  Cmp     Input,0                 ;Any input name?
  430.         Jne     GetF8                   ; yes, try output name
  431.         Mov     DI,Offset MsgIn         ; no, ask for one
  432.         Mov     SI,Offset InKey
  433.         Call    AskName                 ;Get the input file name
  434.  
  435. GetF8:  Cmp     Output,0                ;Any output name?
  436.         Jne     GetF9                   ; yes, that was easy
  437.         Mov     DI,Offset MsgOut        ; no, ask for it
  438.         Mov     SI,Offset OutKey
  439.         Call    AskName                 ;Get the output name
  440.  
  441. GetF9:  Cmp     Word Ptr Output+1,003Ah ;If just a drive is given
  442.         Jne     GetFend                 ; for the output,
  443.         Mov     CX,64                   ; use the input filename
  444.         Mov     DI,Offset Output+2
  445.         Mov     SI,Offset Input
  446.         Cmp     Input+1,':'             ;If drive was given for
  447.         Jne     GetF10                  ; input, must skip over it
  448.         Dec     CL
  449.         Dec     CL                      ;Adjust pointers passed drive
  450.         Dec     SI
  451.         Dec     SI
  452. GetF10: Rep     Movsb
  453.  
  454. GetFend:Ret
  455. GetFile Endp
  456.         Page
  457.  
  458.         ;       Ask for file name(s)
  459.  
  460. AskName Proc    Near                    ;Ask for input file name
  461.         Push    DI                      ;Ptr to prompt msg
  462.         Push    SI                      ;Ptr to reply buffer
  463.         Mov     Byte Ptr [SI],64        ;Reply length
  464. Ask1:   Mov     DX,DI
  465.         Mov     AH,9                    ;Print the prompt msg
  466.         Int     21h
  467.         Mov     DX,SI                   ;Read console reply
  468.         Mov     AH,10
  469.         Int     21h
  470.         Sub     BX,BX                   ;If a reply is given,
  471.         Add     BL,1[SI]                ; append a zero as the
  472.         Jz      Ask1                    ; ASCIIZ name stopper
  473.         Mov     Word Ptr 2[SI][BX],2400h
  474.         Mov     Word Ptr 0[SI],'  '     ;Clear error message part
  475.         Pop     SI
  476.         Pop     DI
  477.         Ret
  478. AskName Endp
  479.  
  480.         ;       Display "cooking" message
  481.  
  482. Inform  Proc    Near
  483.         Mov     AH,9
  484.         Mov     DX,Offset Cooking
  485.         Int     21h
  486.         Mov     AH,9
  487.         Mov     DX,Offset Input
  488.         Int     21h
  489.         Mov     AH,9
  490.         Mov     DX,Offset Mark
  491.         Int     21h
  492.         Mov     AH,9
  493.         Mov     DX,Offset Output
  494.         Int     21h
  495.         Ret
  496. Inform  Endp
  497.  
  498. Tabs    Endp
  499.  
  500.  
  501. Cseg    Ends
  502.  
  503. Stk     Segment Byte Stack 'STACK'
  504.         Db      128 Dup (?)
  505. Stk     Ends
  506.  
  507. InBuf   Segment Public Byte 'DATA'
  508.         Db      Buflen Dup (?)
  509. InBuf   Ends
  510.  
  511. OutBuf  Segment Public Byte 'DATA'
  512.         Db      Buflen Dup (?)
  513. OutBuf  Ends
  514.  
  515.         End     Tabs
  516.  
  517.  
  518. Press ENTER to continue: Segment Public Byte 'DATA'
  519.         Db      Buflen Dup (?)