; ; This program reads text from the standard input device and writes ; filtered and transformed text to the standard output device. ; ; 1. High bit of all characters is stripped off. ; 2. Tabs are expanded. ; 3. Removes all control codes except for line ; feeds, carriage returns, and form feeds. ; 4. Appends an end-of-file mark to the text, if ; none was present in the input stream. ; ; 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 code command equ 80h ; buffer for command tail ; DOS 2.0 Pre-Defined Handles stdin equ 0000 ; standard input file stdout equ 0001 ; standard output file stderr equ 0002 ; standard error file stdaux equ 0003 ; standard auxilliary file stdprn equ 0004 ; standard printer file cseg segment para public 'CODE' assume cs:cseg,ds:cseg org 100H ; start .COM at 100H clean proc far ; entry point from PC-DOS. push ds ; push a long return back xor ax,ax ; to DOS onto the stack. push ax clean3: call get_char ; get a character from input. and al,7fh ; turn off the high bit. cmp al,20h ; is it a control char? jae clean4 ; no. write it to output. cmp al,eof ; is it end of file? je clean6 ; yes, go write EOF mark and exit. cmp al,tab ; is it a tab? je clean5 ; yes, go expand it to spaces. cmp al,cr ; is it a carriage return? je clean35 ; yes, go process it. cmp al,lf ; is it a line feed? je clean35 ; yes, go process it. cmp al,ff ; is it a form feed? jne clean3 ; no. discard it. clean35: mov column,0 ; if it's a legit ctrl char, jmp clean45 ; we should be back at column 0. clean4: inc column ; if it's a non-ctrl char, clean45: ; col = col + 1. call put_char ; write the char to output. jnc clean3 ; if OK, go back for another char. mov bx,stderr ; not OK. Set up to show error. mov dx,offset err_msg mov cx,err_msg_len ; error = Disk full. mov ah,40h ; write the error message int 21h ; to the standard error device. (CON:) ret ; back to DOS. clean5: mov ax,column ; tab code detected, must expand cwd ; expand tabs to spaces. mov cx,8 ; divide the current column counter idiv cx ; by eight... sub cx,dx ; eight minus the remainder is the add column,cx ; number of spaces to send out to clean55: ; move to the next tab position. push cx mov al,20h call put_char ; send an ASCII blank pop cx loop clean55 jmp clean3 clean6: call put_char ; write out the EOF mark, ret ; and return to DOS. clean endp get_char proc near mov bx,stdin ; get chars from std. input mov cx,1 ; # of chars to get = 1 mov dx,offset input_buffer ; location = input_buffer mov ah,3fh int 21h ; do the function call or ax,ax ; test # of chars returned jz get_char1 ; if none, return EOF mov al,input_buffer ; else, return the char in AL ret get_char1: mov al,eof ; no chars read, return ret ; an End-of-File (EOF) mark. get_char endp put_char proc near mov output_buffer,al ; put char to write in buffer. mov bx,stdout ; write to std. output mov cx,1 ; # of chars = 1 mov dx,offset output_buffer ; location = output_buffer mov ah,40h int 21h ; do the function call cmp ax,1 ; check to see it was really done. jne put_char1 clc ; really done. return carry = 0 ret ; as success signal. put_char1: stc ; not really done. return carry = 1 ret ; as error signal (device is full). put_char endp input_buffer db 0 output_buffer db 0 column dw 0 err_msg db cr,lf db 'clean: Disk is full.' db cr,lf err_msg_len equ (this byte)-(offset err_msg) cseg ends end clean