;
;       Sorry for the total lack of comments, but I'm too busy studying
;       for my finals to spend the time.
;
;       This program was assembled with Gibbs A68K 2.42, and linked
;       using BLink.
;
        INCLUDE "exec/types.i"

        STRUCTURE Main,0                ; uninitialized data area (BSS)

        APTR    dosBase                 ; dos.library
        STRUCT  FileList,384
        STRUCT  Buffer,260
        STRUCT  PrintableB,260
        LABEL   Tee_Size

CALLSYS MACRO
        XREF    _LVO\1
        jsr     _LVO\1(A6)
        ENDM

LINKSYS MACRO
        MOVE.L  \2Base(a5),A6
        CALLSYS \1
        move.l  D7,A6
        ENDM

OPENLIBA MACRO
        lea     \1Name(pc),A1
        moveq.l  #0,D0
        CALLSYS OpenLibrary
        move.l  D0,\1Base(a5)
        beq     No\1
        ENDM

CLOSELIB MACRO
        move.l  \1Base(a5),A1
        move.l  A1,D0
        beq     No\1
        CALLSYS CloseLibrary
No\1:
        ENDM


_AbsExecBase(A5)    EQU     4

FLAG_Protect        EQU     1
FLAG_Append         EQU     2
FLAG_Filter         EQU     3
FLAG_NoClose        EQU     4

FLAG_ScreenUsed     EQU     8
FLAG_OpenedFile     EQU     9
FLAG_InterOut       EQU    10
FLAG_InterIn        EQU    11
FLAG_NoOut          EQU    12

MODE_OLDFILE        EQU  1005
MODE_NEWFILE        EQU  1006
ACCESS_WRITE        EQU    -1
OFFSET_END          EQU     1

TEE:
        move.l  $4,a6           ;get execbase
        move.l  A0,A4
        clr.b   -1(A0,D0.l)
        cmp.b   #10,-2(a0,d0.l)
        bne.s   DontZero
        clr.b   -2(A0,D0.l)
DontZero:
        move.w  #(Tee_Size/4)-1,D0
        move.l  A6,D7
ClrStk:
        clr.l   -(a7)
        dbra    D0,ClrStk
        move.l  A7,A5
        OPENLIBA dos
        clr.l   D6
        LINKSYS Input,dos
        move.l  D0,D5
        move.l  D5,D1
        LINKSYS IsInteractive,dos
        tst.l   D0
        beq.s   NotInputInter
        bset    #FLAG_ScreenUsed,D6
        bset    #FLAG_InterIn,D6
NotInputInter:
        LINKSYS Output,dos
        lea     FileList(A5),A0
        move.l  A0,A3
        addq.l  #6,A3
        move.l  D0,(A0)
        move.l  D0,D1
        bset    #FLAG_NoClose,4(A0)
        LINKSYS IsInteractive,dos
        tst.l   D0
        beq.s   NotOutputInter
        btst    #FLAG_InterIn,D6
        beq.s   O.K.IO
        subq.l  #6,A3
        clr.l   (A3)
        bset    #FLAG_NoOut,D6
O.K.IO:
        bset    #FLAG_ScreenUsed,D6
        bset    #FLAG_InterOut,D6
NotOutputInter:
        clr.l   D3
Parse:
        bsr     SkipSpace
        tst.b   (A4)
        beq     ParseDone
ParseNonSpace:
        cmp.b   #'-',(A4)
        bne.s   NotFlag
        addq.l  #1,A4
ParseFlags:
        move.b  (a4)+,D0
        beq     ParseDone
        cmp.b   #' ',D0
        beq     Parse
        cmp.b   #'A',D0
        bne.s   NotGlobApp
        bset    #FLAG_Append,D6
NotGlobApp:
        cmp.b   #'a',D0
        bne.s   NotLocApp
        bset    #FLAG_Append,D3
NotLocApp:
        cmp.b   #'F',D0
        bne.s   NotGlobFilt
        bset    #FLAG_Filter,D6
NotGlobFilt:
        cmp.b   #'f',D0
        bne.s   NotLocFilt
        bset    #FLAG_Filter,D3
NotLocFilt:
        cmp.b   #'P',D0
        bne.s   NotGlobProt
        bset    #FLAG_Protect,D6
NotGlobProt:
        cmp.b   #'p',D0
        bne.s   NotLocProt
        bset    #FLAG_Protect,D3
NotLocProt:
        cmp.b   #'?',D0
        bne     ParseFlags
        bra     Help
NotFlag:
        bsr     SkipSpace
        or.l    D6,D3
        move.l  A4,A2
        moveq.b #' ',D0
        cmp.b   #'"',(A4)+
        bne.s   UnQuoted
        move.b  #'"',D0
        move.l  A4,A2
UnQuoted:
        cmp.b   (A4),D0
        beq.s   Terminator
        tst.b   (A4)+
        bne     UnQuoted
        subq.l  #1,A4
        bra.s   Terminated
Terminator:
        clr.b   (A4)+
Terminated:
        cmp.b   #'*',(A2)
        bne.s   NotScreen
        bsr     OpenScreen
        bra     Parse
NotScreen:
        cmp.b   #'?',(A2)
        beq     Help
        bsr     Exists
        beq.s   NewMode
        btst    #FLAG_Protect,D3
        bne     FileError
        btst    #FLAG_Append,D3
        beq.s   NewMode
        move.l  #MODE_OLDFILE,D2
        bra.s   OpenFile
NewMode:
        move.l  #MODE_NEWFILE,D2
OpenFile:
        move.l  A2,D1
        LINKSYS Open,dos
        tst.l   D0
        beq     FileError
        move.l  D0,(A3)
        move.b  D3,4(A3)
        addq.l  #6,A3
        btst    #FLAG_Append,D3
        beq.s   NotAppendFile
        move.l  D0,D1
        moveq.l #0,D2
        moveq.l #OFFSET_END,D3
        LINKSYS Seek,dos
NotAppendFile:
        move.l  D6,D3
        bra     Parse
;
ParseDone:
        btst    #FLAG_NoOut,D6
        bne.s   IgnoreFlags
        bset    #FLAG_NoClose,D3
        move.b  D3,8(A5)
        move.l  D6,D3
IgnoreFlags:
        lea     10(a5),A4
        cmp.l   A4,A3
        bne.s   ChkNoOut
        bsr     OpenScreen
ChkNoOut:
        subq.l  #6,A4
        cmp.l   A4,A3
        beq     Help
        lea     Buffer(A5),A2
        lea     PrintableB(A5),A3
TheLoop:
        move.l  D5,D1
        move.l  A2,D2
        move.l #256,D3
        LINKSYS Read,dos
        move.l  D0,D4
        ble     Abort
        move.l  A2,A0
        move.l  A3,A1
        clr.l   D6
        add.l   A0,D0
PrintLoop:
        move.b  (A0)+,D1
        cmp.b   #10,D1
        beq.s   Printable
        cmp.b   #32,D1
        bmi.s   NotPrintable
        cmp.b   #127,D1
        bpl.s   NotPrintable
Printable:
        move.b  D1,(A1)+
        addq.l  #1,D6
NotPrintable:
        cmp.l   D0,A0
        bne     PrintLoop
        lea     FileList(A5),A4
OutputLoop:
        tst.l   (A4)
        beq     TheLoop
        move.l  A2,D2
        move.l  D4,D3
        btst    #FLAG_Filter,4(A4)
        beq.s   OutPut
        move.l  A3,D2
        move.l  D6,D3
OutPut:
        move.l  (A4),D1
        LINKSYS Write,dos
        cmp.l   #-1,D0
        beq     Abort
NextOut:
        addq.l  #6,A4
        bra     OutputLoop
;
Abort:
        lea     FileList(A5),A3
CloseAll:
        move.l  (A3),D1
        beq.s   CloseDone
        btst    #FLAG_NoClose,4(A3)
        bne.s   DontClose
        LINKSYS Close,dos
DontClose:
        addq.l  #6,A3
        bra     CloseAll
CloseDone:
        CLOSELIB dos
        lea      Tee_Size(A5),A7
        rts

SkipSpace:
        cmp.b   #' ',(A4)+
        beq     SkipSpace
NonSpace:
        subq.l  #1,A4
        rts

OpenScreen:
        btst    #FLAG_ScreenUsed,D6
        bne.s   OpenSDone
        lea     Screen(PC),A0
        move.l  A0,D1
        move.l  #MODE_OLDFILE,D2
        LINKSYS Open,dos
        tst.l   D0
        beq.s   OpenSDone
        move.l  D0,(A3)
        move.b  D3,4(A3)
        bset    #FLAG_ScreenUsed,D6
        addq.l  #6,A3
OpenSDone:
        move.l  D6,D3
        rts

Help:
        lea     Helpmsg(PC),A0
        bsr     PrintMsg
        bra     Abort

Exists:
        move.l  A2,D1
        move.l  #ACCESS_WRITE,D2
        LINKSYS Lock,dos
        move.l  D0,D1
        beq     NoExist
        LINKSYS UnLock,dos
        moveq.b #-1,D0
NoExist:
        rts

PrintMsg:
        movem.l D0-D4/A0-A1,-(SP)
        move.l  A0,D3
        lea     Screen(PC),A0
        move.l  A0,D1
        move.l  #MODE_OLDFILE,D2
        LINKSYS Open,dos
        tst.l   D0
        beq.s   NoWin
        move.l  D0,D4
        move.l  D0,D1
        move.l  D3,D2
        move.l  D3,A0
        clr.l   D3
FindEnd:
        tst.b   0(A0,D3.l)
        beq.s   FoundEnd
        addq.l  #1,D3
        bra     FindEnd
FoundEnd:
        LINKSYS Write,dos
        move.l  D4,D1
        LINKSYS Close,dos
NoWin:
        movem.l (SP)+,D0-D4/A0-A1
        rts

FileError:
        lea     FileErr(PC),A0
        bsr     PrintMsg
        move.l  A2,A0
        bsr     PrintMsg
        lea     LineFd(PC),A0
        bsr     PrintMsg
        bra     Abort

        EVEN
dosName dc.b    "dos.library",0
FileErr dc.b    "tee: Can't open ",0
Helpmsg dc.b    "Usage:  tee [[-A|a|F|f|P|p] [filename]]...",10,0
LineFd  dc.b    10,0
        EVEN
Screen  dc.b    "*",0
        END

