; FILTEX.ASM ver 1.1 ; by Keith Petersen, W8SDZ ; (revised 6/10/81) ; ;-->NOTE: Requires MAC and SEQIO.LIB to assemble. ; ;This program copies any ASCII file and filters out (ignores) ;all control characters except CR and TAB. When a CR is ;encountered, a LF is automatically appended to make the file ;compatible with CP/M editors. If an "orphan" LF is encountered, ;a CR and LF are written to the output. The program also resets ;the high order bit of all characters to zero so that files ;created with WordStar or other text processing programs can ;be read by MBASIC. The filtered copy of the of the file is ;created as 'FILTEX.FIL' on the default drive. The source ;file is left intact. If the original file's EOF (1AH) is ;not at the physical end of the last sector, this program ;will pad the last sector with EOF's. This is useful for ;'cleaning up' a file which was originally created by MBASIC ;or text editors which do not pad the last sector with EOF's. ; ;FILTEX is also useful for fixing files which contain only ;CRs at the end of each line. ; ;NOTE: FILTEX should not be used on MBASIC source code which ;contains lines which are "continued on next line". This is ;because MBASIC uses a special end-of-line sequence (LF then CR) ;which will be altered by this program. Use FILTER.COM for these ;kinds of files. ; ;Command: FILTEX [drive:] ; ;---------------------------------------------------------- ;Fixes/updates (in reverse order to minimize reading time): ; ;06/10/81 Add routines to count and report number of ; high-order bits deleted and number of input ; and output lines. (KBP) ; ;NOTE: If you add improvements or otherwise update ;this program, please modem a copy of the new file ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone ;313-846-6127 (110, 300, 450 or 600 baud). Use the ;filename FILTEXXX.NEW. (KBP) ;---------------------------------------------------------- ; ;Define write buffer size ; BSIZE EQU 1024*16 ;<--NOW SET FOR 16k ; ;BDOS equates ; WBOOT EQU 0 ;WARM BOOT ENTRY ADRS WRCON EQU 2 ;WRITE CHARACTER TO CONSOLE BDOS EQU 5 ;CP/M BDOS ENTRY ADRS PRINT EQU 9 ;PRINT STRING (DE) UNTIL '$' OPEN EQU 15 ;OPEN DISK FILE READ EQU 20 ;READ SEQUENTIAL FILE STDMA EQU 26 ;SET DMA ADDRESS FCB EQU 5CH ;DEFAULT FILE CONTROL BLOCK ; ;Program starts here ; ORG 100H ; MACLIB SEQIO ;NAME OF MACRO LIBRARY USED ; START: LXI SP,STACK ;SET STACK POINTER CALL ILPRT ;PRINT: DB CR,LF,'FILTEX ver 1.1 - ' DB 'ASCII file filter utility',CR,LF,CR,LF,0 LDA FCB+1 CPI ' ' ;FILENAME THERE? JNZ OPENIT ;YES, GO OPEN IT CALL EXIT ;PRINT MSG THEN EXIT DB 'Usage: FILTEX [drive:]',CR,LF DB CR,LF,' [ ] = optional, < > = required$' ; ;Open source file ; OPENIT: LXI D,FCB MVI C,OPEN CALL BDOS INR A ;CHECK FOR NO OPEN JNZ DECFIL ;NO ERROR, CONTINUE CALL EXIT DB '++SOURCE FILE NOT FOUND++$' ; ;'Declare' output file ; DECFIL: FILE OUTFILE,OUTPUT,,FILTEX,FIL,BSIZE CALL ILPRT ;PRINT: DB 'Input and output files open',CR,LF,CR,LF,0 ; ;Read sector from source file ; READLP: LXI D,80H MVI C,STDMA CALL BDOS LXI D,FCB MVI C,READ CALL BDOS ORA A ;READ OK? JZ WRDISK ;YES, SEND IT TO OUTPUT CPI 1 ;END-OF-FILE? JZ TDONE ;TRANSFER DONE, CLOSE, EXIT CALL ERXIT DB '++SOURCE FILE READ ERROR++$' ; ;Write sector to output file (with buffering) ; WRDISK: LXI H,80H ;READ BUFFER ADRS ; WRDLOP: MOV A,M ;GET BYTE FROM READ BUFFER CPI 1AH ;END OF FILE MARKER ? JZ TDONE ;TRANSFER DONE, CLOSE, EXIT ANI 80H ;HI-BIT TURNED ON? JZ WRDLP2 ;NO, DON'T COUNT IT PUSH H ;SAVE INPUT BUFFER ADRS LHLD HCOUNT ;GET DELETED HI-BIT COUNT INX H ;ADD ONE SHLD HCOUNT ;SAVE NEW COUNT POP H ;GET INPUT BUFFER ADRS BACK ; WRDLP2: MOV A,M ;GET BYTE AGAIN ANI 7FH ;STRIP PARITY BIT CPI 7FH ;DEL (RUBOUT) ? JZ IGNORE ;YES, IGNORE IT CPI ' ' ;SPACE OR ABOVE? JNC PUTCHR ;YES GO WRITE IT CPI CR ;CARRIAGE RETURN ? JNZ WRDLP3 ;SKIP LINE COUNT PUSH H ;SAVE INPUT BUFFER ADRS LHLD ICOUNT ;GET INPUT LINE COUNT INX H ;ADD ONE SHLD ICOUNT ;SAVE NEW COUNT POP H ;GET INPUT BUFFER ADRS BACK JMP WRCRLF ;YES GO WRITE CR AND A LF ; WRDLP3: CPI LF ;LINE FEED ? JZ WRLF ;YES PROCESS IT CPI TAB ;TAB CHARACTER ? JZ PUTCHR ;YES, GO WRITE IT ; ;Ignore character and add one to ignore count ; IGNORE: PUSH H ;SAVE INPUT BUFFER ADRS LHLD DCOUNT ;GET DELETE COUNTER INX H ;ADD ONE SHLD DCOUNT ;SAVE NEW COUNT POP H ;GET INPUT BUFFER ADRS BACK JMP TSTEND ;IGNORE CHARACTER AND CONTINUE ; ;This routine checks to see if the last character was a LF. ;If not, the current character is an "orphan" LF and we need ;to add a CR before it in the output file. ; WRLF: LDA LSTCHR ;GET LAST CHARACTER CPI LF ;WAS IT A LINE FEED? JZ TSTEND ;YES, IGNORE THIS ONE PUSH H ;SAVE INPUT BUFFER ADRS LHLD OLFCNT ;GET ORPHAN LF COUNT INX H ;ADD ONE SHLD OLFCNT ;SAVE NEW COUNT POP H ;GET INPUT BUFFER ADRS BACK ; ;Write a CR and LF to the file. ; WRCRLF: PUSH H ;SAVE INPUT BUFFER ADRS LHLD OCOUNT ;GET OUTPUT LINE COUNT INX H ;ADD ONE SHLD OCOUNT ;SAVE NEW COUNT MVI A,CR ;GET A CR PUT OUTPUT ;WRITE CR TO FILE POP H ;GET INPUT BUFFER ADRS BACK MVI A,LF ;GET A LINE FEED, DROP INTO PUTCHR ; ;Write character to output buffer ; PUTCHR: STA LSTCHR ;SAVE CHAR FOR LATER PUSH H ;SAVE INPUT BUFFER ADRS PUT OUTPUT ;SEND TO DISK WRITE BUFFER POP H ;GET INPUT BUFFER ADRS BACK ; TSTEND: INR L ;DONE WITH SECTOR? JNZ WRDLOP ;NO, GET ANOTHER BYTE JMP READLP ;GO GET ANOTHER SECTOR ; ;Transfer is done - close destination file ; TDONE: FINIS OUTPUT ;FLUSH BUFFERS, CLOSE CALL ILPRT ;PRINT: DB 'Function complete.',CR,LF,CR,LF,0 LHLD ICOUNT ;GET INPUT LINE COUNT CALL DECOUT ;PRINT IT CALL ILPRT ;PRINT: DB ' lines read from input file.' DB CR,LF,0 LHLD OCOUNT ;GET OUTPUT LINE COUNT CALL DECOUT ;PRINT IT CALL ILPRT ;PRINT: DB ' lines written to FILTEX.FIL with:' DB CR,LF,TAB,0 LHLD DCOUNT ;GET DELETED CHAR COUNT CALL DECOUT ;PRINT IT CALL ILPRT ;PRINT: DB ' ctl. characters deleted.' DB CR,LF,TAB,0 LHLD HCOUNT ;GET DELETED HI-ORDER BIT COUNT CALL DECOUT ;PRINT IT CALL ILPRT ;PRINT: DB ' high-order bits deleted.' DB CR,LF,TAB,0 LHLD OLFCNT ;GET ORPHAN LF COUNT CALL DECOUT ;PRINT IT CALL EXIT ;PRINT MSG THEN EXIT DB ' orphan LFs fixed.$' ; ;Erase the incomplete output file, then exit ; ERXIT: FINIS OUTPUT ;CLOSE INCOMPLETE FILE ERASE OUTPUT ;THEN ERASE IT ; ;Print message then exit to CP/M warm boot ; EXIT: POP D ;GET MSG ADRS MVI C,PRINT ;PRINT MESSAGE CALL BDOS CALL ILPRT ;PRINT CRLF DB CR,LF,0 JMP WBOOT ;ASSURES UPDATE OF BIT MAP ; ;Inline print routine - prints string pointed to ;by stack until a zero is found. Returns to caller ;at next address after the zero terminator. ; ILPRT: XTHL ;SAVE HL, GET MSG ADRS ; ILPLP: MOV A,M ;GET CHAR CALL TYPE ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; ;Send character in A register to console ; TYPE: PUSH B PUSH D PUSH H MOV E,A ;CHAR TO E FOR CP/M MVI C,WRCON ;WRITE TO CONSOLE CALL BDOS POP H POP D POP B RET ; ;Decimal output - print HL as decimal ;number with leading zero suppression ; DECOUT: PUSH B PUSH D PUSH H LXI B,-10 LXI D,-1 ; DECOU2: DAD B INX D JC DECOU2 LXI B,10 DAD B XCHG MOV A,H ORA L CNZ DECOUT MOV A,E ADI '0' CALL TYPE POP H POP D POP B RET ; LSTCHR: DB 0 ;LAST CHARACTER REMINDER ICOUNT: DW 0 ;INPUT LINE COUNTER OCOUNT: DW 0 ;OUTPUT LINE COUNTER DCOUNT: DW 0 ;DELETED CHARACTER COUNTER OLFCNT: DW 0 ;ORPHAN LINE FEED COUNTER HCOUNT: DW 0 ;HI-ORDER BITS ZEROED COUNTER DS 100 ;ROOM FOR 50-LEVEL STACK STACK EQU $ ;STACK POINTER SET HERE ; ;Org write buffer to even page boundry ORG ($+255) AND 0FF00H BUFFERS EQU $ ;WRITE BUFFER STARTS HERE ; END