home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Share Gallery 1
/
share_gal_1.zip
/
share_gal_1
/
LA
/
LA001.ZIP
/
CHASM.ARC
/
DETAB.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-12
|
9KB
|
262 lines
;===================================================
; PROGRAM DETAB Version 1.0 by Dave Whitman
;
; Filter to expand tabs.
; System standard tab stops every 8 columns are assumed.
;
; Syntax: DETAB [?] [<infile] [>outfile]
;
; The ? option prints a help message.
;
; Requires DOS 2.0, will abort under earlier versions.
;====================================================
;============
; Equates
;============
@read equ 3FH ;read file/device
@write equ 40H ;write file/device
@dosver equ 30H ;get dos version
@prnstr equ 09H ;print string
cr equ 0DH ;carriage return character
lf equ 0AH ;line feed character
tab equ 09H ;horizontal tab character
stdin equ 0000H ;standard input
stdout equ 0001H ;standard output
buf_size equ 8192 ;size of input and output buffers
max_line equ 255 ;maximum input line length
yes equ 0FFH ;boolean true
no equ 00H ;boolean false
param_count equ [80H]
param_area equ [81H]
mem_avail equ [06H] ;PSP field: memory available in segment
main proc far
call setup ;check dos, parse options
call stops ;fill tab stop array
call process ;expand tabs
int 20H ;and return to dos
endp
;======================================
; SUBROUTINE SETUP
; Checks for proper DOS, parses options
;======================================
setup proc near
mov ah, @dosver ;what dos are we under?
int 21H
cmp al, 2 ;2.0 or over?
jae a_mem ;yes, skip
mov ah, @prnstr ;no, bitch
mov dx, offset(baddos)
int 21H
pop ax ;reset stack
int 20H ;and exit
a_mem mov ax, mem_avail ;do we have room for the buffers and array?
cmp ax, buf_size*2+max_line
jae a_help ;yes
mov ah, @prnstr ;no, bitch
mov dx, offset(nomem)
int 21H
pop ax ;reset stack
int 20H ;and exit
a_help xor ch,ch ;cx <== param count
mov cl, param_count ; "
cmp cl, 00H ;any params?
je a_exit ;return if none
mov di, offset(param_area) ;scan for help request
mov al, '?'
repnz ;repeat until matched or end
scasb
jnz a_exit ;reached end, no match? skip
mov ah, @prnstr ;found ?, so print help
mov dx, offset(help)
int 21H
pop ax ;pop stack
int 20H ;and exit
a_exit ret
baddos db cr lf 'This program requires DOS 2.0!' cr, lf, '$'
nomem db cr lf 'Insufficient memory, program aborted' cr lf '$'
help db cr lf
db 'DETAB version 1.0 by D. Whitman' cr lf
db cr lf
db 'Syntax: DETAB [?] [<infile] [>outfile]' cr lf
db cr lf
db 'Reads stdin, expands tab characters, '
db 'and writes to stdout.' cr lf
db 'Tab stops are set every 8 columns.' cr lf
db cr lf
db 'Option:' cr lf
db ' ? = print this help message' cr lf
db cr lf
db 'This program is in the public domain.' cr lf
db cr lf '$'
endp
;=========================================
; SUBROUTINE STOPS
;
; Set tab stops in array. Following the system
; standard, stops are set every 8 columns.
;=========================================
stops proc near
mov di, offset(tabstops) ;point to array
mov cx, 1 ;count columns
mov dl, 8 ;stops every 8 columns
s1 cmp cx, max_line ;are we done?
jg s_exit ;yes, exit
mov ax, cx ;no, continue: get count
div dl ;ah gets remainder
cmp ah, 0 ;multiple of eight?
jne s2 ;branch if not
movb [di], yes ;yes, so mark tab
jmps s3 ;and skip
s2 movb [di], no ;no, mark no tab
s3 inc cx ;bump counts
inc di ; " "
jmps s1 ;and loop till done
s_exit ret
endp
;=========================================
; SUBROUTINE PROCESS
;
; 1. load input buffer
; 2. convert each char, pass to output buffer
; 3. dump output buffer
; 4. repeat until EOF
;==========================================
process proc near
mov di, offset(buf_out) ;point to output buffer
movw outnum, 0 ;output buffer is empty
movw column, 0 ;start in column 0
bu1 mov ah, @read ;read
mov bx, stdin ;from stdin
mov cx, buf_size ;one buffer's worth
mov dx, offset(buf_in)
int 21H
cmp ax, 00H ;test for EOF
jz budone ;if so, done
mov cx, ax ;cx <== number of chars read
mov si, offset(buf_in) ;source is input buffer
bu2 lodsb ;al <== next char from buffer
mov bx, column ;bx <== current column
cmp al, tab ;test if tab character
jne bu3 ;nope, skip
mov al, ' ' ;yes, replace with spaces
bu2a call putchar ;send blank to StdOut
inc bx ;bump column count
cmp bx, max_line ;line overflowing?
jge bu2b ;yes, so assume we're at a stop
cmpb offset(tabstops)[bx], yes ;are we at a stop?
jne bu2a ;no, keep emitting spaces
bu2b jmps bu5 ;yes, so done expanding
bu3 cmp al, lf ;EOL?
jne bu4 ;nope, skip
mov bx, 0 ;reset column counter
call putchar ;print char
jmps bu5 ;and skip
bu4 call putchar ;otherwise, just send char to StdOut
inc bx ;and bump column count
bu5 mov column, bx ;save column count
loop bu2 ;loop until buffer processed
jmps bu1 ;and loop until EOF
budone cmpw outnum, 0 ;input done. Any outstanding output?
jle buexit ;no, exit
call dumpbuf ;yes, empty buffer
buexit ret
endp
;===================================================
; SUBROUTINE PUTCHAR
;
; Moves the character in AL into the output buffer.
; If the buffer is now full, it is dumped to disk.
;===================================================
putchar proc near
stosb ;move character into buffer
incw outnum ;bump count of chars in buffer
cmpw outnum, buf_size ;if buffer full?
jl p_exit ;no, skip
call dumpbuf ;yes, dump buffer to disk
p_exit ret
endp
;==================================================
; SUBROUTINE DUMPBUF
;
; Dumps the output buffer to StdOut.
;==================================================
dumpbuf proc near
push ax ;save active registers
push bx ; " " "
push cx ; " " "
mov ah, @write ;write
mov bx, stdout ;to stdout
mov cx, outnum ;number of chars for output
mov dx, offset(buf_out)
int 21H
movw outnum, 0 ;reset buffer
mov di, offset(buf_out) ; " "
pop cx ;restore active registers
pop bx ; " " "
pop ax ; " " "
ret
endp
;==================
; GLOBAL VARIABLES
;==================
innum dw 0000H ;number of characters in input buffer
outnum dw 0000H ;number of characters in output buffer
column dw 0000H ;current column in line
;=====================================================
;BUFFERS
;
; No space is actually allocated for the buffers.
; At run time, the program checks to ensure there
; is suffcient free memory, then uses the memory
; immediately after itself for buffers.
;
; This stratagy minimizes the size of the object file,
; and lets the program load quicker.
;======================================================
tabstops ;tab stop array
org offset(tabstops+max_line)
buf_in ;input buffer
org offset(buf_in+buf_size)
buf_out ;output buffer