home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
asm_kit
/
tabs.asm
< prev
next >
Wrap
Assembly Source File
|
1984-05-04
|
18KB
|
519 lines
r
Title TABS - Align ASCII File
Page 82,132
Comment | Version 1.2, April 27, 1984
TABS Command
-----------------
Purpose: Replace blanks with TAB character(s).
Format: TABS d:input.ext d:output.ext
Remarks: Any TAB characters found are first expanded. Thus, if TABS
appear within quoted strings - out of context - they will
be expanded incorrectly.
In replacing blanks with tabs, quoted strings are ignored.
The maximum logical record size is 255, see MAXREC equate.
Defacto tab columns are 9,17,25,...
V. Buerg, March, 1984. For public domain use.
----------------- |
Cseg Segment Public Para 'CODE'
Assume CS:Cseg,DS:Cseg,ES:Nothing
Tabs Proc Far
Push DS ;DOS convention
Sub AX,AX
Push AX
Mov CS:Stk_Top,SP ;Save stack ptr to insure return
Mov AH,30h
Int 21h ;Verify DOS 2.0 or later
Mov DX,Offset Sorry
Cmp AL,2
Jb Error
Call GetFile ;Get file names
Call OpenIn ;Open input
Call OpenOut ;Open output
Call Inform ;Display "cooking" message
Call GenTab ;Generate tabs
Call Flush ;Empty the output buffer
Mov DX,Offset EofMsg ;Say END-OF-FILE
Error: Mov SP,Stk_Top ;Insure proper return
Mov AH,9 ;Print any message
Int 21h
Call Close ;Close files
Ret ;Return to DOS
Page
Buflen Equ 16*1024 ;I/O buffer size
Maxrec Equ 255 ;Longest logical record
S_Quote Equ 34 ;Single quote
D_Quote Equ 39 ;Double quote
Tab Equ 9
Lf Equ 10
Cr Equ 13
Eof Equ 1Ah
Rec Db Maxrec Dup (0) ;Current record
Rlen Dw 0 ;Current record length
Sw Db 0 ;Number of blanks skipped
Qsw Db 0 ;Quote switch
Stk_Top Dw 0 ;SP at entry
MsgIn Db Cr,Lf,'Enter INPUT file name> $'
Msg1 Db Cr,Lf,'Input failed to open>'
InKey Db 32,32 ;Keyboard buffer
Input Db 64 Dup (0),0,'$' ;Drive:path\name.ext
IHandle Dw 0 ;Input file handle
Ilen Dw 0 ;Input block length
Iptr Dw 0 ;Offset to next char
MsgOut Db Cr,Lf,'Enter OUTPUT file name> $'
Msg2 Db Cr,Lf,'Output failed to open>'
OutKey Db 32,32
Output Db 64 Dup (0),0,'$'
OHandle Dw 0 ;Output file handle
Olen Dw 0 ;Output block size
Optr Dw 0 ;Offset to next char
Sorry Db Cr,Lf,'Sorry, PC DOS Version 2 required',Cr,Lf,'$'
Msg3 Db Cr,Lf,'I/O error reading',Cr,Lf,'$'
Msg4 Db Cr,Lf,'I/O error writing',Cr,Lf,'$'
Cooking Db Cr,Lf,'TABBING: $'
Mark Db ' => $'
EofMsg Db Cr,Lf,'End of File',Cr,Lf,'$'
NewLine Db CR,LF,'-$'
Code2 Db 'File not found $'
Code3 Db 'Path not found $'
Code4 Db 'Too many files $'
Code5 Db 'Access denied $'
Page
; Replace blanks with tabs
GenTab Proc Near
Loop: Call GetRec ;Get a record
Mov CX,Rlen ; its length
Sub BX,BX ;Output column
Mov Sw,0 ;No blanks yet
Mov Qsw,0 ;No quotes yet
Or CX,CX ;Any data in record?
Jnz Set1
Jmp Null ; no, just CR-LF
Set1: Mov SI,Offset Rec ;Look for blanks and
Wloop: Lodsb ; replace strings of blanks
Inc BX ; with tab characters
Cmp AL,D_Quote ;Don't count blanks
Jne Chk1 ; within single or double
Xor Qsw,2 ; quoted strings
Jmp Chk2
Chk1: Cmp AL,S_Quote ;Insert TABs for any
Jne Chk3 ; blanks skipped before
Xor Qsw,1 ; a quote
Chk2: Cmp Sw,0 ;Must re-insert
Je Check ; any blanks skipped
Jmp Insert ; if not enough for a TAB
Chk3: Cmp AL,' ' ;Tis a blank?
; Jmp Check ;for DETAB
Jne Check ; no, see if eof
Test Qsw,3 ;Within quotes?
Jnz Check
Inc Sw
Test BL,07h ;Ready for a tab?
Jnz Tloop ; no, keep going
Mov AL,Tab ; yes, send one
Jmp Copy
Check: Cmp AL,Eof ;End of file?
Je Done ; yes, all done
; Jmp Copy ;for DETAB
Test Qsw,3 ;When a non-blank is
Jnz Copy ; encountered, insert a TAB
Cmp Sw,0 ; if there were blanks
Je Copy ; before it
Mov DX,BX
Dec DL
Test DL,07h ;If the non-blank is not
Jnz Insert ; in a TAB column, then
Push AX ; keeps all the blanks
Mov AL,Tab
Call PutChar
Pop AX
Jmp Copy
Insert: Push AX ;Insert any blanks that
Mov DL,Sw ; didn't line up on
Blanks: Cmp DL,1 ; a TAB column
Jb None
Mov AL,' '
Call PutChar
Dec DL ;Decr insert count
Jmp Blanks ; and continue
None: Pop AX ;Get char back
Copy: Call PutChar ; and write it
Mov Sw,0 ;Ind not blank
Tloop: Loop Wloop
Null: Mov AL,Cr ;Append CR
Call PutChar
Mov AL,Lf ; and LF
Call PutChar
Jmp Loop
Done: Ret
GenTab Endp
Page
; Build a logical record
GetRec Proc Near
Push DI
Sub DI,DI ;Target record offset
Mov Rlen,0 ; and length
Mov Qsw,0 ;Quote indicator
Get1: Call GetChar ;Build up a logical record
Cmp AL,Cr ; by looking for a CR or LF
Je Get1 ; as end-of-record
Cmp AL,Lf
Je Get7
Cmp AL,S_Quote ;Don't expand tabs
Jne Get2 ; found within a
Xor Qsw,1 ; quoted string
Get2: Cmp AL,D_Quote
Jne Get3
Xor Qsw,2
Get3: Cmp AL,Tab ;Is it TAB?
Jne Get5 ; no, pass it
Test Qsw,3 ;Within quotes?
Jnz Get5 ; yes, pass it
Get4: Mov Rec[DI],' ' ;Expand embedded tabs
Inc DI ; with blanks
Test DI,0007h
Jz Get1
Jmp Get4
Get5: Mov Rec[DI],AL ;Build the record by
Inc DI ; copying each character
Cmp DI,Maxrec ; or TABs expanded to blanks
Jae Get6
Cmp AL,Eof ;Is it EOF?
Je Get6 ; yes, all done
Jmp Get1 ; no, continue
Get6: Mov Rlen,DI ;Final record length
Pop DI
Ret
Get7: Cmp Rec-1[DI],' ' ;Strip trailing blanks
Jne Get6
Dec DI
Jz Get6
Jmp Get7
GetRec Endp
Page
; Extract one char from record
GetChar Proc Near ;Read char into AL
Push CX
Push SI
Read1: Cmp Ilen,0 ;Any in buffer?
Je Read ; no, read next block
Mov SI,Iptr ; yes, get offset in buf
Push DS
Mov AX,Seg InBuf ;Copy a char from the
Mov DS,AX ; input (segment) buffer
Lodsb
Pop DS
Mov Iptr,SI ;Offset for next one
Dec Ilen ;Decr buffer size left
Jmp Read4 ; and return with AL
Read: Mov BX,IHandle ;Read a block of data
Mov CX,BufLen ; into Input (segment) buffer
Sub DX,DX
Push DS
Mov AX,Seg InBuf
Mov DS,AX
Mov AH,3Fh
Int 21h
Pop DS
Mov Iptr,0 ;Reset buffer ptr
Mov Ilen,AX ; and length
Jc Read2
Or AX,AX ;Anything read?
Jnz Read1 ; yes, pick it up
Mov AL,Eof ; no, return EOF
Jmp Read4
Read2: Mov DX,Offset Msg3 ;Say I/O ERROR
Jmp Error
Read4: Pop SI
Pop CX
Ret
GetChar Endp
Page
; Block output records
PutChar Proc Near ;Write from AL
Push AX
Push BP
Push BX
Push CX
Push DI
Push DX
Mov DI,Optr ;Offset in buffer
Mov DX,Seg OutBuf
Push ES ;Get buffer segment
Mov ES,DX
Stosb ;Place into buffer
Pop ES
Inc Olen ;Incr the length
Mov Optr,DI ; and buffer ptr
Cmp Olen,Buflen ;Full block?
Jb Write2 ; no, return
Mov CX,Buflen ; yes,write it
Jmp Write3
Flush: Push AX ;Write data left over
Push BP ; in output buffer
Push BX
Push CX
Push DI
Push DX
Mov CX,Olen ;Any left in output?
Or CX,CX
Jz Write2
Write3: Mov BX,OHandle ;Get file handle
Mov BP,CX ;Save size requested
Sub DX,DX
Push DS ;Set up DS:DX
Mov AX,Seg OutBuf ; in buffer segment
Mov DS,AX
Mov AH,40h ;Write the block
Int 21h
Pop DS
Mov Optr,0 ;Reset buffer ptr
Mov Olen,0 ; and size used
Jc Writer ;Write OK?
Cmp BP,AX ;Wrote all data?
Je Write2 ; yes, good
Writer: Mov DX,Offset Msg4 ; no, say I/O error
Jmp Error
Write2: Pop DX
Pop DI
Pop CX
Pop BX
Pop BP
Pop AX
Ret
PutChar Endp
Page
; Open input file
OpenIn Proc Near
Mov DX,Offset Input
Mov AL,0 ;For input
Mov AH,3Dh ;Open a file
Int 21h
Jnc Openi
Mov DX,Offset Msg1
Jmp OpenErr
Openi: Mov IHandle,AX
Ret
OpenIn Endp
; Open output file
OpenOut Proc Near
Mov DX,Offset Output
Sub CX,CX ;Normal file attribute
Mov AH,3Ch ;Create a file
Int 21h
Jnc Openo
Mov DX,Offset Msg2
Jmp OpenErr
Openo: Mov OHandle,AX
Ret
OpenOut Endp
; Determine why OPEN failed
OpenErr:Cmp AL,2 ;AL has reason code
Jb Opene
Cmp AL,5
Ja Opene
Sub BX,BX ;Get offset to reason
Mov BL,AL ; text for open failure
Mov CL,4
Shl BX,CL
Mov AH,9 ;Say OPEN FAILED
Int 21h
Mov DX,Offset NewLine
Mov AH,9
Int 21h
Lea DX,Code2-32[BX]
Opene: Jmp Error
; Close input/output
Close Proc Near ;Close files
Mov BX,IHandle ; input
Mov AH,3Eh
Int 21h
Mov BX,OHandle ; output
Mov AH,3Eh
Int 21h
Ret
Close Endp
Page
; Get file names from command line
GetFile Proc Near ;Get file name(s)
Push CS ;DS points to PSB
Pop ES ;Now ES points to data
Mov SI,80h ;Point to command line
Sub BP,BP ;Indicates first or second name
Sub CH,CH ;The PSP may contain one or two
Or CL,Byte Ptr DS:[SI] ; filenames separated by blanks
Jz GetF5
Lea DI,ES:Input
Inc SI
GetF1: Lodsb ;Copy command line to file names
Cmp AL,' ' ; by skipping leading blanks
Jne GetF2 ; until a CR is found
Or BP,BP ; or until the length is zero
Jz GetF4 ;If a second blank is found,
Mov AX,2400h ; append zero and dollar sign
Stosw
Lea DI,ES:Output ; and it starts the second file name
Jmp GetF4
GetF2: Cmp AL,Cr ;Is it CR, end of line?
Je GetF5 ; yes, end of command
Stosb ; no, save in name
Mov BP,DI ; and indicate data copied
GetF4: Loop GetF1
GetF5: Mov AX,2400h ;Append zero and dollar sign
Stosw
Mov AX,CS ;When done, set up
Mov DS,AX ; segment registers
GetF7: Cmp Input,0 ;Any input name?
Jne GetF8 ; yes, try output name
Mov DI,Offset MsgIn ; no, ask for one
Mov SI,Offset InKey
Call AskName ;Get the input file name
GetF8: Cmp Output,0 ;Any output name?
Jne GetF9 ; yes, that was easy
Mov DI,Offset MsgOut ; no, ask for it
Mov SI,Offset OutKey
Call AskName ;Get the output name
GetF9: Cmp Word Ptr Output+1,003Ah ;If just a drive is given
Jne GetFend ; for the output,
Mov CX,64 ; use the input filename
Mov DI,Offset Output+2
Mov SI,Offset Input
Cmp Input+1,':' ;If drive was given for
Jne GetF10 ; input, must skip over it
Dec CL
Dec CL ;Adjust pointers passed drive
Dec SI
Dec SI
GetF10: Rep Movsb
GetFend:Ret
GetFile Endp
Page
; Ask for file name(s)
AskName Proc Near ;Ask for input file name
Push DI ;Ptr to prompt msg
Push SI ;Ptr to reply buffer
Mov Byte Ptr [SI],64 ;Reply length
Ask1: Mov DX,DI
Mov AH,9 ;Print the prompt msg
Int 21h
Mov DX,SI ;Read console reply
Mov AH,10
Int 21h
Sub BX,BX ;If a reply is given,
Add BL,1[SI] ; append a zero as the
Jz Ask1 ; ASCIIZ name stopper
Mov Word Ptr 2[SI][BX],2400h
Mov Word Ptr 0[SI],' ' ;Clear error message part
Pop SI
Pop DI
Ret
AskName Endp
; Display "cooking" message
Inform Proc Near
Mov AH,9
Mov DX,Offset Cooking
Int 21h
Mov AH,9
Mov DX,Offset Input
Int 21h
Mov AH,9
Mov DX,Offset Mark
Int 21h
Mov AH,9
Mov DX,Offset Output
Int 21h
Ret
Inform Endp
Tabs Endp
Cseg Ends
Stk Segment Byte Stack 'STACK'
Db 128 Dup (?)
Stk Ends
InBuf Segment Public Byte 'DATA'
Db Buflen Dup (?)
InBuf Ends
OutBuf Segment Public Byte 'DATA'
Db Buflen Dup (?)
OutBuf Ends
End Tabs
Press ENTER to continue: Segment Public Byte 'DATA'
Db Buflen Dup (?)