home *** CD-ROM | disk | FTP | other *** search
- PAGE 57,132
- TITLE DETAB -- Expand Tab Codes Filter Routine.
- NAME DETAB
- ;
- ; Usage:
- ; DETAB <INPUT.FIL >OUTPUT.FIL
- ; DETAB <AFILE.TXT | SORT >AFILE.SRT
- ;
- ; This is a filter routine which converts tab codes to spaces
- ; while copying the input file to the output file and filtering
- ; out the FFH byte and all control bytes. Each carriage-return
- ; is followed by a line-feed code. Trailing blanks are deleted.
- ; An all-blank line is written simply as a CR/LF combination.
- ;
- ; Ground rules:
- ; (1) All routines must preserve any needed
- ; registers before calling other routines.
- ;
- ; (2) Registers SI and DI index the input and
- ; the output buffers, respectively.
- ;
- ; Program by Harry M. Murphy, 4 March 1987.
- ;
- ;
- ; NOTICE
- ;
- ; Copyright 1987, Harry M. Murphy.
- ;
- ; A general license is hereby granted for non-commercial
- ; use, copying and free exchange of this program without
- ; payment of any royalties, provided that this copyright
- ; notice is not altered nor deleted. All other rights are
- ; reserved. This program is supplied as-is and the author
- ; hereby disclaims all warranties, expressed or implied,
- ; including any and all warranties of merchantability and
- ; any and all warranties of suitability for any purpose.
- ; Use of this program in any way whatsoever constitutes
- ; acceptance of the terms of this license.
- ;
- ; Harry M. Murphy, Consultant
- ; 3912 Hilton Avenue, NE
- ; Albuquerque, NM 87110
- ;
- ;
- BEL EQU 07H ;Bell (beep) code.
- BUFLEN EQU 1000H ;Length of the I/O buffers.
- CTLZ EQU 1AH ;Control-Z (ASCII SUB) code.
- CR EQU 0DH ;Carriage Return code.
- DOS EQU 21H ;DOS interrupt code.
- HT EQU 09H ;Tab code.
- LF EQU 0AH ;Line Feed code.
- LINLEN EQU 100H ;Line length.
- STDIN EQU 0 ;Standard input file handle.
- STDOUT EQU 1 ;Standard output file handle.
- TABLEN EQU 8 ;Tab spacing.
- ;
- ;
- DETAB SEGMENT 'CODE'
- ORG 100H ;This is a "COM" routine.
- ASSUME CS:DETAB,DS:DETAB
- ;
- MAIN PROC NEAR ;DETAB starts here.
- XOR AX,AX ;Zero AX and
- MOV EOF,AX ; clear end-of-file flag,
- MOV LINP,AX ; clear input buffer length,
- MOV LLIN,AX ; clear line length,
- MOV SI,AX ; clear input index and
- MOV DI,AX ; clear output index.
- ;
- MAIN1: CALL GETLIN ;Get a line
- CMP EOF,0 ; and skip
- JNE MAIN2 ; if end-of file.
- ;
- CALL PUTLIN ;Else, output the line and
- JMP MAIN1 ; loop for another.
- ;
- MAIN2: CMP LLIN,0 ;If the line length is
- JE MAIN3 ; zero, then skip to flush.
- ;
- CALL PUTLIN ;Else, output the last line.
- ;
- MAIN3: CALL FLUSH ;Flush the output buffer and
- MOV AX,4C00H ; exit with
- INT DOS ; ERRORLEVEL = 0.
- MAIN ENDP
- ;
- ;
- ABORT PROC NEAR ;Abort routine. Jump to this routine
- ; ;with DX containing the offset of an
- ; ;ASCIIZ error message.
- ;
- MOV AH,0EH ;Prepare for BIOS output text in
- XOR BX,BX ; teletype mode interrupt.
- MOV SI,DX ;Copy ASCIIZ pointer to SI and
- CLD ; clear direction flag.
- ;
- ABRT1: LODSB ;Get next byte of the message,
- OR AL,AL ; skip to
- JZ ABRT2 ; exit on zero.
- ;
- INT 10H ;Else, display the byte and
- JMP ABRT1 ; loop for next byte.
- ;
- ABRT2: MOV AX,4C07H ;Exit with
- INT DOS ; ERRORLEVEL = 7.
- ABORT ENDP
- ;
- ;
- FLUSH PROC NEAR ;Subroutine to flush the output buffer.
- ;
- MOV AL,CTLZ ;Output a final
- CALL PUTCH ; Control-Z.
- OR DI,DI ;If the output buffer is empty,
- JZ FLUSH2 ; skip to return.
- ;
- MOV AH,40H ;Else
- MOV BX,STDOUT ; call DOS
- MOV CX,DI ; to flush
- MOV DX,OFFSET OUTPUT ; the output
- INT DOS ; buffer.
- JNC FLUSH1 ;If no carry, OK.
- ;
- MOV DX,OFFSET WRMSG ;Else, point to write-error message
- JMP ABORT ; and abort.
- ;
- FLUSH1: INC AX ;If we wrote all the bytes, or all the
- CMP AX,DI ; bytes except for the CTLZ,
- JAE FLUSH2 ; then OK.
- ;
- MOV DX,OFFSET WFMSG ;Else, point to "full" message
- JMP ABORT ; and abort.
- ;
- FLUSH2: XOR DI,DI ;Clear the output index and
- RET ; return.
- FLUSH ENDP
- ;
- ;
- GETCH PROC NEAR ;Subroutine to get the next input byte
- ; ;in AL. If end-of-file, EOF is returned
- ; ;set to -1, else it's set to 0.
- ;
- CMP SI,LINP ;If we haven't read the last byte from
- JNE GETCH2 ; the input buffer, skip to GETCH2.
- ;
- MOV EOF,0 ;Else, clear the end-of-file flag and
- MOV AH,3FH ; call DOS
- MOV BX,STDIN ; to read
- MOV CX,BUFLEN ; into the
- MOV DX,OFFSET INPUT ; input
- INT DOS ; buffer.
- JNC GETCH1 ;If no carry, OK.
- ;
- MOV DX,OFFSET RDMSG ;Else, point to read-error message
- JMP ABORT ; and abort.
- ;
- GETCH1: XOR SI,SI ;Clear the input index and
- MOV LINP,AX ; copy number of bytes read to LINP.
- OR AX,AX ;If the number of bytes
- JNZ GETCH2 ; is non-zero, OK.
- ;
- DEC EOF ;Else, set the end-of-file flag.
- ;
- GETCH2: MOV AL,BYTE PTR INPUT[SI] ;Get byte in AL,
- INC SI ; increment input index and
- RET ; return.
- GETCH ENDP
- ;
- ;
- GETLIN PROC NEAR ;Subroutine to get and filter an input
- ; ;line. If end-of-file, then EOF is
- ; ;returned set to -1, else it's set to 0.
- ;
- MOV LLIN,0 ;Start: clear the line length.
- ;
- GETLN1: CALL GETCH ;Get an input byte in AL,
- CMP EOF,0 ; check for end-of-file and
- JNE GETLN6 ; skip to return if EOF.
- ;
- CMP AL,0FFH ;Reject
- JE GETLN1 ; FFH bytes.
- ;
- CMP AL,' ' ;Else, accept all bytes equal to, or
- JAE GETLN3 ; above, a blank code.
- ;
- CMP AL,CR ;Else, skip to GETLN4 if it's a
- JE GETLN4 ; carriage-return code.
- ;
- CMP AL,HT ;Else, if it's NOT a tab code,
- JNE GETLN1 ; reject it.
- ;
- MOV AX,LLIN ;(It IS a tab code.) Divide the
- CWD ; current line
- MOV CX,TABLEN ; length by the
- DIV CX ; tab spacing. (Remainder ==> DX.)
- SUB CX,DX ;Spaces = Tab spacing - remainder.
- MOV AL,' ' ;Get blank in AL and
- MOV BX,LLIN ; current line length in BX.
- MOV DX,BX ;Add LLIN and
- ADD DX,CX ; spaces in DX to get new LLIN.
- CMP DX,LINLEN ;If the new LLIN >= LINLEN
- JAE GETLN3 ; then simply convert HT to a space.
- ;
- GETLN2: MOV BYTE PTR LINE[BX],AL ;Else, expand the tab by
- INC BX ; copying CX blanks to the
- LOOP GETLN2 ; line.
- ;
- MOV LLIN,BX ;Update LLIN to new length and
- JMP GETLN1 ; loop for next byte.
- ;
- GETLN3: MOV BX,LLIN ;Get current line length in BX,
- MOV BYTE PTR LINE[BX],AL ;copy the byte to the line,
- INC BX ; increment the line length and
- MOV LLIN,BX ; re-store in LLIN.
- CMP BX,LINLEN ;If the line isn't full,
- JNE GETLN1 ; loop for another byte.
- ;
- GETLN4: MOV BX,LLIN ;Get the line length in BX and
- OR BX,BX ; if it's zero,
- JZ GETLN6 ; skip to return.
- ;
- GETLN5: CMP BYTE PTR LINE[BX-1],' ' ;Else, if the last byte isn't
- JNE GETLN6 ; a blank, skip to return.
- ;
- DEC BX ;Else, decrement the line count in BX
- MOV LLIN,BX ; and LLIN and
- JNZ GETLN5 ; loop if BX isn't zero.
- ;
- GETLN6: RET ;Return with the line length in LLIN.
- GETLIN ENDP
- ;
- ;
- PUTCH PROC NEAR ;Subroutine to output the byte in AL.
- ;
- MOV BYTE PTR OUTPUT[DI],AL ;Copy AL to the output buffer,
- INC DI ; and increment the buffer index.
- CMP DI,BUFLEN ;If the buffer isn't full,
- JB PUTCH2 ; skip to return.
- ;
- MOV AH,40H ;Else,
- MOV BX,STDOUT ; call DOS to
- MOV CX,BUFLEN ; write the
- MOV DX,OFFSET OUTPUT ; output
- INT DOS ; buffer.
- JNC PUTCH1 ;If no carry, OK.
- ;
- MOV DX,OFFSET WRMSG ;Else, point to write-error message
- JMP ABORT ; and abort.
- ;
- PUTCH1: XOR DI,DI ;Clear the output index and
- CMP AX,BUFLEN ; check if all bytes were written.
- JE PUTCH2 ; If so, skip to return.
- ;
- MOV DX,OFFSET WFMSG ;Else, point to "full" message
- JMP ABORT ; and abort.
- ;
- PUTCH2: RET ;Return.
- PUTCH ENDP
- ;
- ;
- PUTLIN PROC NEAR ;Subroutine to output the line in LINE
- ; ;whose length is LLIN.
- ;
- MOV CX,LLIN ;Get line length in CX and
- OR CX,CX ; if it's zero,
- JZ PUTLN2 ; skip to output CR/LF.
- ;
- XOR BX,BX ;Else clear BX as a line index.
- ;
- PUTLN1: MOV AL,BYTE PTR LINE[BX] ;Get the next byte from LINE in AL
- INC BX ; increment the line index,
- PUSH BX ; save the line index
- PUSH CX ; save the byte count and
- CALL PUTCH ; call PUTCH to output it.
- POP CX ;Restore the byte count,
- POP BX ; restore the line index and
- LOOP PUTLN1 ; loop to output the next byte.
- ;
- PUTLN2: MOV AL,CR ;Output a trailing
- CALL PUTCH ; carriage-return and
- MOV AL,LF ; a trailing
- CALL PUTCH ; line-feed and
- RET ; return.
- PUTLIN ENDP
- ;
- ;
- RDMSG DB CR,LF,'Read error!',CR,LF,BEL,0
- WRMSG DB CR,LF,'Write error!',CR,LF,BEL,0
- WFMSG DB CR,LF,'Disk full error!',CR,LF,BEL,0
- EVEN
- EOF DW 0 ;End-of-File flag.
- LINP DW 0 ;Input buffer byte count.
- LLIN DW 0 ;Line length.
- ;
- LINE LABEL BYTE ;Start of LINE buffer.
- INPUT EQU LINE+LINLEN ;Start of INPUT buffer.
- OUTPUT EQU INPUT+BUFLEN ;Start of OUTPUT buffer.
- DETAB ENDS
- END MAIN