;**********************************************************************
;                                                                     *
;    PROGRAM       LPRFILTER                                          *
;                                                                     *
;    FUNCTIONS     1. STRIPS TEXT LINES OF TRAILING BLANKS            *
;                  2. CHANGES FROM <NL> TO <CR><NL>                   *
;                  3. CONVERTS FROM SWEDISH 7-BITS ASCII TO ANSI      *
;                     8-BIT ASCII.                                    *
;                  4. CONVERTS NULLS TO BLANKS                        *
;                  5. ADDS A FORM FEED TO THE END OF THE FILE         *
;                                                                     *
;    INPUT         TEXT FILE, UNIX TYPE DELIMITERS                    *
;                                                                     *
;    OUTPUT        TEXT FILE, PC TYPE DELIMITERS                      *
;                                                                     *
;    CREATED       1999-12-06                                         *
;                                                                     *
;    CREATED BY    ROBERT DE MANDER, ROBDEM SOFT AB                   *
;                                                                     *
;    MODIFIED                                                         *
;**********************************************************************
;
           .TITLE  LPRFILTER
           .REV    1,0,1
           .ENT    LPRFILTER
;
;**********************************************************************
;          MACROS
;**********************************************************************
;
;          1. PACKET DEFINITION
;
           .MACRO  DEFPKT              ; SYNTAX: DEFPKT NAME, SIZE
           .PUSH   ^2                  ; REMEMBER NO OF WORDS
           .PUSH   .                   ; REMEMBER THE ADRESS
^1:        .BLK    ^2                  ; RESERVE SPACE
%
;
;          2. INIT A 16-BIT WORD
;
           .MACRO  SINIT               ; SYNTAX: SINIT OFFSET, VALUE
           .LOC    .TOP+^1             ; LOCATION
           .WORD   ^2                  ; VALUE
%
;
;          3. INIT A 32-BIT WORD
;
           .MACRO  DINIT               ; SYNTAX: DINIT OFFSET, VALUE
           .LOC    .TOP+^1             ; LOCATION
           .DWORD  ^2                  ; VALUE
%
;
;          4. END PACKET DEFINITION
;
           .MACRO  ENDPKT              ; SYNTAX: ENDPKT
           .LOC    .POP+.POP+1         ; LOCATION AFTER PACKET
%
;
;          5. ZERO OUT AC:S BEFORE CERTAIN SYSTEM CALLS
;
           .MACRO  NOLLAK              ; SYNTAX: NOLLAK
           WSUB    0,0                 ; AC0, RESERVED SET TO 0
           WSUB    1,1                 ; AC1, RESERVED SET TO 0
%
;**********************************************************************
;          PROGRAM VARIABLES
;**********************************************************************

            .NREL 0
FLAGS:     ?RFCF+?RFEC+?RFAB           ; CLI FORMAT, AC0=CODE, ABORT
COUNT:     .WORD 0                     ; COUNTER FOR VARIOUS ITERATIONS
TMP:       .TXT    ".TMP<0>"           ; TAIL END OF INPUT FILENAME
SPACE:     .TXT    "<0><40>"           ; <NULL><SPACE>
NEWLINE:   .TXT    "<0><12>"           ; <NULL><NL>
CRETURN:   .TXT    "<0><15>"           ; <NULL><CR>
FORMFEED:  .TXT    "<0><14>"           ; <NULL><FF>

           .RDX 16
DTABLE:    .WORD 2001,0203,0405,0607,0809,0A0B,0C0D,0E0F
           .WORD 1011,1213,1415,1617,1819,1A1B,1C1D,1E1F
           .WORD 2021,2223,2425,2627,2829,2A2B,2C2D,2E2F
           .WORD 3031,3233,3435,3637,3839,3A3B,3C3D,3E3F
           .WORD 0C941,4243,4445,4647,4849,4A4B,4C4D,4E4F
           .WORD 5051,5253,5455,5657,5859,5AC4,0D6C5,0DC5F
           .WORD 0E961,6263,6465,6667,6869,6A6B,6C6D,6E6F
           .WORD 7071,7273,7475,7677,7879,7AE4,0F6E5,0FC7F

           .WORD 8081,8283,8485,8687,8889,8A8B,8C8D,8E8F
           .WORD 9091,9293,9495,9697,9899,9A9B,9C9D,9E9F
           .WORD 0A0A1,0A2A3,0A4A5,0A6A7,0A8A9,0AAAB,0ACAD,0AEAF
           .WORD 0B0B1,0B2B3,0B4B5,0B6B7,0B8B9,0BABB,0BCBD,0BEBF
           .WORD 0C0C1,0C2C3,0C4C5,0C6C7,0C8C9,0CACB,0CCCD,0CECF
           .WORD 0D0D1,0D2D3,0D4D5,0D6D7,0D8D9,0DADB,0DCDD,0DEDF
           .WORD 0E0E1,0E2E3,0E4E5,0E6E7,0E8E9,0EAEB,0ECED,0EEEF
           .WORD 0F0F1,0F2F3,0F4F5,0F6F7,0F8F9,0FAFB,0FCFD,0FEFF
           .RDX 8
DTABADR:   .DWORD DTABLE*2

INBUFF:    .BLK    128.                ; I/O BUFFER INFIL MAX 256 CHARS
UTBUFF:    .BLK    128.                ; I/O BUFFER UTFIL MAX 256 CHARS

ISOURCE:   .BLK 128.                   ; PATHNAME TO INPUT SOURCE
OSOURCE:   .BLK 128.                   ; PATHNAME TO OUTPUT SOURCE

ARG1VAL:   .BLK 128.                   ; VALUE OF ARGUMENT 1

           .NOMAC 1                    ; DON'T EXPAND MACROS

           DEFPKT FARG1,?GTLN          ; START OF ?GTMES PACKET

           SINIT  ?GREQ,?GARG          ; WE WANT AN ARGUMENT
           SINIT  ?GNUM, 1             ; AND IT'S THE FIRST ONE
           DINIT  ?GSW,0               ; NOT IN USE
           DINIT  ?GRES,ARG1VAL*2      ; BP TO RESULT BUFFER

           ENDPKT                      ; END OF ?GTMES PACKET

           DEFPKT SFILE1,?IBLT         ; START OF ?OPEN PACKET 1

           SINIT  ?ISTI,?ICRF+?OFIN+?RTDS; DATA-SENSITIVE & INPUT
           SINIT  ?ISTO,0                ; FILE TYPE
           SINIT  ?IMRS,-1               ; BLOCK SIZE
           DINIT  ?IBAD,INBUFF*2         ; BP TO I/O BUFFER
           SINIT  ?IRES,0                ; DENSITY
           SINIT  ?IRCL,256.             ; MAX RECORD LENGTH
           SINIT  ?IRLR,0                ; NO OF TRANSFERED BYTES (R/W ONLY)
           SINIT  ?IRNW,0                ; RESERVED
           DINIT  ?IRNH,0                ; RECORD #
           DINIT  ?IFNP,ISOURCE*2        ; BP TO FILENAME
           DINIT  ?IDEL,-1               ; DELIMITER TABLE

           ENDPKT                      ; END OF ?OPEN PACKET 1

           DEFPKT SFILE2,?IBLT         ; START OF ?OPEN PACKET 2

           SINIT  ?ISTI,?ICRF+?OFOT+?RTDS+?OFCR ; DATA-SENSITIVE & OUTPUT
                                         ; CREATE THE FILE
           SINIT  ?ISTO,0                ; FILE TYPY
           SINIT  ?IMRS,-1               ; BLOCK SIZE
           DINIT  ?IBAD,UTBUFF*2         ; BP TO I/O BUFFER
           SINIT  ?IRES,0                ; DENSITY
           SINIT  ?IRCL,256.             ; MAX RECORD LENGTH
           SINIT  ?IRLR,0                ; NO OF TRANSFERED BYTES (R/W) ONLY
           SINIT  ?IRNW,0                ; RESERVED
           DINIT  ?IRNH,0                ; RECORD #
           DINIT  ?IFNP,OSOURCE*2        ; BP TO FILENAME
           DINIT  ?IDEL,-1               ; DELIMITER TABLE

           ENDPKT                      ; END OF ?OPEN PACKET 2
;************************************************************************
;          ARGUMENT ERROR HANDLING ROUTINE
;************************************************************************
ARGERR:    WLDAI   ERNAG,0             ; AC0 = ERROR CODE
           WSUB    1,1                 ; AC1 = 0, NO MESSAGE
ARROR:     XWLDA   2,FLAGS             ; LOAD ERROR FLAGS
           ?RETURN                     ; GO BACK WITH ERROR
           WBR     ARROR               ; FAILED WHILE FAILING

;**********************************************************************
;          PROGRAM ENTRY POINT
;**********************************************************************

LPRFILTER:                             ; PROGRAM ENTRY POINT

           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?GTMES  FARG1               ; FETCH ARG-1 FROM INITIAL IPC MESS
           JMP     B300                ; WHAT'S THIS THEN?

           WSEQI   -1,1                ; ARG-1 SHOULDN'T BE NUMERIC
           JMP     ARGERR              ; SORRY IT WAS - LET'S DIE

           XNSTA   0,COUNT             ; SAVE THE LENGTH OF ARG 1

           XLEFB   0,ARG1VAL*2         ; BP TO ARGUMENT 1 IN AC0
           XLEFB   1,OSOURCE*2         ; BP TO OUTPUT FILENAME IN AC1
           NLDAI   256.,2              ; LENGTH OF OSOURCE FILENAME BUFFER
           ?GNAME                      ; GET THE COMPLETE PATHNAME
           JMP     B300                ; WHY ME?

           XLEFB   2,ISOURCE*2         ; BP TO INPUT FILENAME IN AC2
           XLEFB   3,ARG1VAL*2         ; BP TO ARGUMENT 1 IN AC3

B100:      WLDB    3,0                 ; GET THE FIRST BYTE OF ARG-1
           WSTB    2,0                 ; STUFF IT IN THE INPUT FILENAME

           WINC    3,3                 ; BUMP THE BP FOR ARG-1
           WINC    2,2                 ; BUMP THE BP FOR INPUT FILENAME

           XNDSZ   COUNT               ; CONTINUE UNTIL COUNT IS ZERO
           JMP     B100

           NLDAI   5,0                 ; PUT 5 IN AC0
           XNSTA   0,COUNT             ; SAVE IT IN  COUNT
           XLEFB   3,TMP*2             ; BP TO INPUT FILENAME'S TAIL END

B200:      WLDB    3,0                 ; GET THE FIRST BYTE OF TAIL END
           WSTB    2,0                 ; STUFF IT IN THE INPUT FILENAME

           WINC    2,2                 ; BUMP THE BP FOR INPUT FILENAME
           WINC    3,3                 ; BUMP THE BP FOR TAIL END

           XNDSZ   COUNT               ; CONTINUE UNTIL COUNT IS ZERO
           JMP     B200

           XLEFB   0,OSOURCE*2         ; BP TO OUTPUT FILENAME (ORIGINAL)
           XLEFB   1,ISOURCE*2         ; BP TO INPUT FILENAME (NEW)
           WSUB    2,2                 ; ZERO OUT BEFORE SYSCALL
           ?RENAME                     ; RENAME ORIGINAL SOURCE FILE
B300:      JMP     B450                ; JEEEZ...

           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?OPEN   SFILE1              ; OPEN INPUT FILE
           JMP     B450                ; OOPS!!

           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?OPEN   SFILE2              ; OPEN OUTPUT FILE
B450:      JMP     ERROR               ; OH NOO!!
;
;**********************************************************************
;          PROCESSING CONTINUES UNTIL INPUT FILE REACHES EOF
;**********************************************************************
C100:
           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?READ   SFILE1              ; READ A RECORD/LINE
           JMP     C400                ; EOF OR AN ERROR?

           XLEFB   1,INBUFF*2          ; BP TO I/O BUFFER
           XNLDA   2,SFILE1+?IRLR      ; LOAD NO-OF-BYTES TRANSFERED
           WSBI    1,2                 ; LOWER IT BY 1 (IGNORE DELIMITER)
           WSGTI   0,2                 ; SKIP IF AC > ZERO
           JMP     C280                ; ONLY  A DELIMITER

           XNSTA   2,COUNT             ; SAVE NO-OF-BYTES
           WSBI    1,2                 ; I/O BUFFER BP + NO-OF-BYTES - 1 =
           WADD    2,1                 ; NEXT TO LAST BYTE TRANSFERED
           XNLDA   2,SPACE             ; LOAD <NULL><SPACE> IN AC2

C200:      WLDB    1,0                 ; LOAD BYTE
           WSEQ    0,2                 ; SKIP IF SPACE
           JMP     C250

           WSBI    1,1                 ; LOWER I/O BUFFER BP BY ONE

           XNDSZ   COUNT               ; CONTINUE UNTIL COUNT IS ZERO
           WBR     C200

C250:      WINC    1,1                 ; BUMP I/O BUFFER BP

C280:      XNLDA   0,CRETURN           ; LOAD A CARRIAGE RETURN
           WSTB    1,0                 ; STORE IT IN I/O BUFFER

           XLEF    0,DTABADR           ; ADRESS TO DELIMITER TABLE
           XNLDA   1,SFILE1+?IRLR      ; BUFF LEN = NO-OF-BYTES TRANSFERED
           WNEG    1,1                 ; REQUIRED BY WCTR
           XLEFB   2,UTBUFF*2          ; BP TO I/O BUFFER 
           XLEFB   3,INBUFF*2          ; BP TO I/O BUFFER
           WCTR                        ; TRANSLATE

C300:      NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?WRITE  SFILE2              ; WRITE A RECORD/LINE
           JMP     ERROR               ; QUE?

           XNLDA   0,NEWLINE           ; LOAD A NEWLINE
           XLEFB   1,UTBUFF*2          ; BP TO I/O BUFFER
           WSTB    1,0                 ; STORE IT IN I/O BUFFER
           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?WRITE  SFILE2              ; WRITE A RECORD/LINE
           JMP     ERROR               ; QUE?

           JMP     C100                ; CONTINUE PROCESSING

C400:
           NLDAI   EREOF,2             ; LOAD EOF-CODE IN AC2
           WSEQ    0,2                 ; HAVE WE REACHED EOF?
           JMP     ERROR               ; NO, SOMETHING ELSE WENT WRONG

D100:                                  ; EOF, ADD FF, CLOSE FILES AND QUIT
           XNLDA   0,FORMFEED          ; LOAD A FORMFEED
           XLEFB   1,UTBUFF*2          ; BP TO I/O BUFFER
           WSTB    1,0                 ; STORE IT IN I/O BUFFER
           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?WRITE  SFILE2              ; WRITE A RECORD/LINE
           JMP     ERROR               ; QUE?

           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?CLOSE  SFILE1              ; CLOSE INPUT FILE
           JMP     ERROR               ; WHAT THE F...?

           NOLLAK                      ; ZERO AC:S BEFORE SYSCALL
           ?CLOSE  SFILE2              ; CLOSE OUTPUT FILE
           JMP     ERROR               ; SCHUCKS...

           XLEFB   0,ISOURCE*2         ; BP TO INPUT FILENAME
           XLEFB   1,ARG1VAL*2         ; BP TO RESULT BUFFER
           NLDAI   256.,2              ; LENGTH OF RESULT BUFFER
           ?GNAME                      ; GET THE COMPLETE PATHNAME
           JMP     ERROR               ; MIGHTY STRANGE

           XLEFB   0,ARG1VAL*2         ; BP TO FILENAME TO DELETE
           WSUB    1,1                 ; ZERO BEFORE SYSCALL
           WSUB    2,2                 ; ZERO BEFORE SYSCALL
           ?DELETE                     ; DELETE TEMPORARY FILE
           JMP     ERROR               ; BAD KARMA AGAIN!!

           WSUB    2,2                 ; NORMAL PROGRAM TERMINATION
           ?RETURN                     ; BACK TO DADDY

;************************************************************************
;          GENERAL PURPOSE ERROR HANDLING ROUTINE
;************************************************************************
ERROR:     XWLDA   2,FLAGS             ; LOAD ERROR FLAGS, AC0 = ERRCODE
           ?RETURN                     ; GO BACK WITH ERROR
           WBR     ERROR               ; THIS IS ANNOYING

           .END    LPRFILTER           ; THIS IS THE END
