CNC Programming

CNC | C | C++ | Assembly | Python | R | Rust | Arduino | Solidworks | Embedded Systems

This program removes all control codes except for line feeds

; CLEAN --- a utility to filter text files.
; This program removes all control codes except
; for line feeds, carriage returns, and form
; feeds, strips off the high bit of all characters,
; and expands tabs.  Can be used to make a Wordstar
; file acceptable for other screen or line editors,
; and vice versa.

cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
ff equ 0ch ;ASCII form feed
eof equ 01ah ;End of file marker
tab equ 09h ;ASCII tab character

command equ 80h ;buffer for command tail

blksize equ 1024 ;blocking/deblocking size

cseg segment para public 'CODE'

assume cs:cseg,ds:data,es:data,ss:stack

clean proc far ;entry point from PC-DOS

push ds ;save DS:0000 for final
xor ax,ax ;return to PC-DOS
push ax
mov ax,data ;make our data segment
mov es,ax ;addressable via ES register
call infile ;get path and file spec.
;for input file
mov ax,es ;set DS=ES for remainder
mov ds,ax ;of program
jnc clean1 ;jump, got acceptable name
mov dx,offset msg4 ;missing or illegal filespec,
jmp clean9 ;print error message and exit.

clean1: call outfile ;set up output file name
call open_input ;now try to open input file
jnc clean2 ;jump,opened input ok
mov dx,offset msg1 ;open of input file failed,
jmp clean9 ;print error msg and exit.

call open_output ;try to open output file.
jnc clean25 ;jump,opened ok
mov dx,offset msg2 ;open of output file failed,
jmp clean9 ;print error message and exit.

clean25: ;set up buffers
call init_buffs
call sign_on ;print ident and file names

;files successfully opened,
clean3: ;now filter the file.
call get_char ;read 1 character from input.
and al,07fh ;strip off the high bit
cmp al,20h ;is it a control code?
jae clean4 ;no,write it to new file
;yes it is control code,
cmp al,eof ;is it end of file marker?
je clean6 ;yes,jump to close files.
cmp al,tab ;is it a tab command?
jz clean5 ;yes,jump to special processing.
cmp al,cr ;if control code other than
je clean35 ;tab or end-of-file mark, throw
cmp al,ff ;it away unless it is a
je clean35 ;form feed, carriage return,
cmp al,lf ;or line feed.
jne clean3
clean35: ;If it is one of those three,
mov column,0 ;incidentally initialize
jmp clean45 ;column count for tab processor.

clean4: ;count alphanumeric chars. sent.
inc column

clean45: ;write this character to
call put_char ;output file,
jnc clean3 ;if CY not set, write was
;ok so go get next char.
call close_input ;if CY set, disk is full
call close_output ;so close files and exit
mov dx,offset msg5  ;with error message.
jmp clean9

clean5: ;process tab character
mov ax,column ;let DX:AX=column count
mov cx,8 ;divide it by eight...
idiv cx
sub cx,dx ;remainder is in DX.
add column,cx ;update column pointer.
clean55: ;8 minus the remainder
push cx ;gives us the number of
mov al,20h ;spaces to send out to
call put_char ;move to the next tab position
pop cx ;restore space count
jc clean47 ;jump if disk is full
loop clean55
jmp short clean3 ;get next character

clean6: ;end of file detected,
call put_char ;write end-of-file marker,
jc clean47 ;jump if disk was full
call flush_buffs ;write remaining data to disk
jc clean47 ;if CY set,disk was full
;otherwise file was written ok
call close_input ;close input and output
call close_output ;files.
mov dx,offset msg3 ;addr of success message,

clean9: ;print message and return
mov ah,9 ;control to PC-DOS
int 21h

clean endp

infile proc near ;process name of input file
;DS:SI <- addr command line
mov si,offset command
;ES:DI <- addr filespec buffer
mov di,offset input_name
lodsb ;any command line present?
or al,al ;return error status if not.
jz infile4
infile1:          ;scan over leading blanks
lodsb ;to file name
cmp al,cr ;if we hit carriage return
jz infile4 ;filename is missing.
cmp al,20h ;is this a blank?
jz infile1 ;if so keep scanning.

infile2: ;found first char of name,
stosb ;move last char. to output
;file name buffer.
lodsb ;check next character, found
cmp al,cr ;carriage return yet? 
je infile3 ;yes,exit with success code
cmp al,20h ;is this a blank?
jne infile2 ;if not keep moving chars.

infile3: ;exit with carry =0
clc ;for success flag

infile4: ;exit with carry =1
stc ;for error flag
infile  endp

outfile proc near ;set up path and file
cld ;name for output file.
mov cx,64 ;length to move
mov si,offset input_name  ;source addr
mov di,offset output_name ;dest addr
rep movsb ;transfer the string
mov di,offset output_name
outfile1: ;scan string looking for
mov al,[di] ;"." marking start of extension
or al,al ;or zero byte marking name end.
jz outfile2 ;if either is found,jump.
cmp al,'.'
je outfile2 ;bump string pointer, loop
inc di ;if neither '.' or zero found.
jmp outfile1
outfile2: ;found zero or '.',force the
;extension of the output file
;to '.CLN'
mov si,offset outfile_ext
mov cx,5
rep movsb
ret ;back to caller
outfile endp

open_input proc near ;open input file
;DS:DX=addr filename
mov dx,offset input_name
mov al,0 ;AL=0 for read only
mov ah,3dh ;function 3dh=open
int     21h ;handle returned in AX,
mov input_handle,ax ;save it for later.
ret ;CY is set if error
open_input endp

open_output proc near ;open output file
;DS:DX=addr filename
mov dx,offset output_name
mov al,1 ;AL=1 for write only
mov ah,3ch ;function 3ch=MAKE or
int 21h ;truncate existing file
;handle returned in AX
mov output_handle,ax;save it for later.
ret ;return CY=true if error
open_output endp

close_input proc near ;close input file
mov bx,input_handle ;BX=handle
mov ah,3eh
int 21h
close_input endp

close_output proc near ;close output file
mov bx,output_handle;BX=handle
mov ah,3eh
int 21h
close_output endp

get_char proc near ;get one character from input buffer
mov bx,input_ptr
cmp bx,blksize
jne get_char1
call read_block
mov bx,0
mov al,[input_buffer+bx]
inc bx
mov input_ptr,bx
get_char endp

put_char proc near ;put one character into output buffer
mov bx,output_ptr
mov [output_buffer+bx],al
inc bx
mov output_ptr,bx
cmp bx,blksize ;buffer full yet?
jne put_char1 ;no,jump
call write_block ;yes,write the block
ret ;return CY as status code
clc ;return CY clear for OK status
put_char endp

read_block proc near
mov bx,input_handle ;read first block of input
mov cx,blksize
mov dx,offset input_buffer
mov ah,3fh
int 21h
jnc read_block1 ;jump if no error status
mov ax,0 ;simulate a zero length read if error
cmp ax,blksize ;was full buffer read in?
je read_block2 ;yes,jump
mov bx,ax ;no, store End-of-File mark
mov byte ptr [input_buffer+bx],eof
xor ax,ax ;initialize input buffer pointer
mov input_ptr,ax
read_block endp

write_block proc near ;write blocked output (blksize bytes)
mov dx,offset output_buffer
mov cx,blksize
mov bx,output_handle
mov ah,40h
int 21h
xor bx,bx ;initialize pointer to blocking buffer
mov output_ptr,bx
cmp ax,blksize ;was correct length written?
jne write_block1 ;no,disk must be full
clc ;yes,return CY=0 indicating all OK
write_block1: ;disk is full, return CY =1
stc ;as error code
write_block endp

init_buffs proc near
call read_block ;read 1st block of input
xor ax,ax ;initialize pointer to output
mov output_ptr,ax ;output blocking buffer
init_buffs endp

flush_buffs proc near ;write any data in output buffer to disk
mov cx,output_ptr
or cx,cx
jz flush_buffs1 ;jump,buffer is empty
mov bx,output_handle
mov dx,offset output_buffer
mov ah,40h
int 21h
cmp ax,output_ptr ;was write successful?
jnz flush_buffs2 ;no,jump
clc ;yes,return CY=0 for
ret ;success flag
flush_buffs2: ;disk was full so write failed,
stc ;return CY=1 as error flag
flush_buffs endp

sign_on proc near ;print sign-on message
mov dx,offset msg6 ;title...
mov ah,9
int 21h
mov dx,offset msg7 ;input file:
mov ah,9
int 21h
mov dx,offset input_name
call pasciiz
mov dx,offset msg8 ;output file:
mov ah,9
int 21h
mov dx,offset output_name
call pasciiz
mov dx,offset msg9
mov ah,9
int 21h
sign_on endp

pasciiz proc near ;call DX=offset of ASCIIZ string
mov bx,dx ;which will be printed on standard output
mov dl,[bx]
or dl,dl
jz pasciiz9
cmp dl,'A'
jb pasciiz2
cmp dl,'Z'
ja pasciiz2
or dl,20h
mov ah,2
int 21h
inc bx
jmp pasciiz1
pasciiz endp

cseg ends

data segment para public 'DATA'

input_name db 64 dup (0) ;buffer for input filespec
output_name db 64 dup (0) ;buffer for output filespec

input_handle dw 0 ;token returned by PCDOS
output_handle dw 0 ;token returned by PCDOS

input_ptr dw 0 ;pointer to input blocking buffer
output_ptr dw 0 ;pointer to output blocking buffer

outfile_ext db '.CLN',0 ;extension for filtered file

column dw 0 ;column count for tab processing

msg1 db cr,lf
db 'Cannot find input file.'
db cr,lf,'$'

msg2 db cr,lf
db 'Failed to open output file.'
db cr,lf,'$'

msg3 db cr,lf
db 'File processing completed'
db cr,lf,'$'

msg4 db cr,lf
db 'Missing file name.'
db cr,lf,'$'

msg5 db cr,lf
db 'Disk is full.'
db cr,lf,'$'

msg6 db cr,lf
db 'Clean Word Processing File'
db cr,lf
db 'WWW.'
db cr,lf,'$'

msg7 db cr,lf,'Input file:   $'

msg8 db cr,lf,'Output file:  $'

msg9 db cr,lf,'$'

input_buffer db blksize dup (?) ;buffer for deblocking of data
;from input file

output_buffer db blksize dup (?) ;buffer for blocking of data
;sent to output file

data ends

stack segment para stack 'STACK'
db 64 dup (?)
stack ends

end clean



No comments:

Post a Comment