*
*    TFilter                                           Rev: 26 Dec 88
*
*    Program to filter out non-text bytes from a file
*
*    This program will filter out everything except printable ASCII or CR,
*     LF, FF, HT, or VT.
*
*    This program is pure, and may be made resident.
*
*
     NOPAGE

     INCLUDE "AsMac:CoreMacros.i"

     INCLUDE "AsMac:AllocMem.i"
     INCLUDE "AsMac:AllocUDS.i"
     INCLUDE "AsMac:Close.i"
     INCLUDE "AsMac:DeleteFile.i"
     INCLUDE "AsMac:Exist.i"
     INCLUDE "AsMac:FreeMem.i"
     INCLUDE "AsMac:FreeUDS.i"
     INCLUDE "AsMac:Open.i"
     INCLUDE "AsMac:Read.i"
     INCLUDE "AsMac:Write.i"


     DefineSections TFilter

BufferSize     EQU  10240


TFilter:
     AllocUDS UDS_Size        ; Allocate memory for uninitialized data
     BEQ TFilter_19           ;  storage.
     OpenLib exec.library     ; Open the exec library.
     BEQ TFilter_18
     OpenLib dos.library      ; Open the dos library.
     BEQ TFilter_17
                              ; Allocate memory for the source and
                              ;    destination buffers.
     AllocMem SourceBuf,D,BufferSize
     BEQ TFilter_16
     AllocMem DestBuf,D,BufferSize
     BEQ TFilter_15
     MOVE.L #AskFNSpec,D1     ; Open a window to ask for file names.
     Open R,D1,AskFileName,new
     BEQ TFilter_14
TFilter_1:                    ; Ask for the filename for the SOURCE file.
     Write D,AskSourceName,AskFileName
     BEQ TFilter_13
                              ; Get the response.
     Read AskFileName,D,Response
     BEQ TFilter_13
                              ; Adjust response length to get rid of the LF.
     SUBQ.L #1,Response.Len(A5)

                              ; IF no file name was given,
     MOVE.L Response.Len(A5),D0
     BEQ TFilter_13           ; THEN pass to TFilter_13 to abort.
                              ; ENDIF

     MOVEA.L #SourceName,A1   ; Put the source file name string at
     MOVEA.L #Response,A0     ;    SourceName with null termination.
     ADDA.L A5,A0
     ADDA.L A5,A1
TFilter_2:
     MOVE.B (A0)+,(A1)+
     SUBQ.L #1,D0
     BNE.S TFilter_2
     MOVE.B #0,(A1)+          ;    (Terminate it with an ASCII null.)

     Exist I,SourceName       ; Find out if the file exists.
     BNE.S TFilter_3          ; IF it does not exist,
                              ; THEN tell the operator that the file does
                              ;    not exist.
     Write D,FileNotExist,AskFileName
     BRA TFilter_1            ;    Loop back to TFilter_1 to get the
                              ;    correct file name.
TFilter_3:                    ; ENDIF

                              ; Ask for the filename for the DESTINATION
                              ;    file.
     Write D,AskDestName,AskFileName
     BEQ TFilter_13
                              ; Get the response.
     Read AskFileName,D,Response
     BEQ TFilter_13
                              ; Adjust response length to get rid of the LF.
     SUBQ.L #1,Response.Len(A5)

                              ; IF no file name was given,
     MOVE.L Response.Len(A5),D0
     BEQ TFilter_13           ; THEN pass to TFilter_13 to abort.
                              ; ENDIF

     MOVEA.L #DestName,A1     ; Put the destination file name string at
     MOVEA.L #Response,A0     ;    DestName with null termination.
     ADDA.L A5,A0
     ADDA.L A5,A1
TFilter_4:
     MOVE.B (A0)+,(A1)+
     SUBQ.L #1,D0
     BNE.S TFilter_4
     MOVE.B #0,(A1)+          ;    (Terminate it with an ASCII null.)

     Exist I,DestName         ; Find out if the file exists.

     BEQ.S TFilter_5          ; IF it does exist,
     DeleteFile I,DestName    ; THEN delete it.
     BEQ TFilter_13
TFilter_5:                    ; ENDIF

                              ; Open the SOURCE and DESTINATION files.
     Open I,SourceName,SourceFile,read
     BEQ TFilter_13
     Open I,DestName,DestFile,new
     BEQ TFilter_12
TFilter_6:                    ; REPEAT (Start of REPEAT UNTIL)

                              ;> Read the SOURCE file into the SourceBuffer.
     Read SourceFile,I,SourceBuf
     BEQ TFilter_11
     TST.L D0                 ;> IF all bytes have been read from the file,
     BEQ.S TFilter_10         ;> THEN pass to TFilter_10 to break out of
                              ;>    the REPEAT UNTIL loop.
                              ;> ENDIF

                              ;> Copy from the source buffer to the
                              ;>    destination buffer. Filter out non-text
                              ;>    bytes as it is copied.
     MOVE.L SourceBuf.Adr(A5),A0
     MOVE.L DestBuf.Adr(A5),A3
     CLR.L D3
TFilter_7:                    ;>    REPEAT (Start of REPEAT UNTIL)
     MOVE.B (A0)+,D2          ;>>    Get the byte from the source buffer.
     BLE.S TFilter_9          ;>>    IF the byte is printable ASCII or CR,
     CMPI.B #$7F,D2           ;>>       LF, FF, HT, or VT,
     BEQ.S TFilter_9
     CMPI.B #$20,D2
     BGE.S TFilter_8
     CMPI.B #$08,D2
     BLE.S TFilter_9
     CMPI.B #$0E,D2
     BGT.S TFilter_9
TFilter_8:
     MOVE.B D2,(A3)+          ;>>    THEN copy it to the destination buffer.
     ADDQ.L #1,D3
TFilter_9:                    ;>>    ENDIF
     SUBQ.L #1,D0             ;>    UNTIL all bytes have been read from the
     BNE TFilter_7            ;>       source buffer.

                              ;> Write from the DestBuffer to the DESTINATION
                              ;>  file.
     Write I,DestBuf,DestFile,D3
     BEQ TFilter_11
     BRA TFilter_6            ;> Loop back to TFilter_6 to get the rest
                              ;>  of the SOURCE file.

TFilter_10:                   ; UNTIL done copying data from the source to
                              ;    the destination file.

TFilter_11:                   ; Close the SOURCE and DESTINATION files.
     Close DestFile
TFilter_12:
     Close SourceFile
TFilter_13:                   ; Close the AskFileName window.
     Close AskFileName
TFilter_14:                   ; De-allocate memory.
     FreeMem DestBuf
TFilter_15:
     FreeMem SourceBuf
TFilter_16:
     CloseLib dos.library     ; Close the dos library.
TFilter_17:
     CloseLib exec.library    ; Close the exec library.
TFilter_18:
     FreeUDS UDS_Size         ; De-allocate the UDS memory.
TFilter_19:
     CLR.L D0                 ; Exit the program with return code of zero.
     RTS




*----------------------------------------------------------------------------

LF   SET $0A

     SECTION   DataSection,DATA

AskFNSpec:

  DC.B 'CON:40/15/600/52/TFilter',0

AskFNSpecEnd:

AskSourceName:

  DC.B LF,' Specify the source filename:      '

AskSourceNameEnd:

AskDestName:

  DC.B LF,' Specify the destination filename: '

AskDestNameEnd:

FileNotExist:

  DC.B LF,LF,'[33m ERROR: The specified file does not exist.[0m',LF,LF

FileNotExistEnd:


*----------------------------------------------------------------------------

     SECTION   CodeSection,CODE

     DefDS Response,20
     DefDS ResponseEnd,0
     DefDS SourceName,20
     DefDS DestName,20

UDS_Size       EQU  DefDSPointer


     END
