               INCLUDE  flp1_pipe_definitions




               SECTION   text

               xdef      io.doit
               xref      geef.terug


* the actual I/O  is performed here:
* if (pipe ->ready)
*    if (pipe ->EOF)
*         return EOF
*    else
*         if((c = do_I/O) == EOF)    {           /* vector IO.SERQ */
*              throw_away (pipe -> partner)
*              pipe -> EOF = TRUE
*              return EOF
*         } else
*              return c
*  else
*    return NOT_COMPLETE      
                  
               dc.b      'I/O'
io.doit        cmpi.b    #5,d0              ; in- or output?
               bge.s     io.output          ; if input: 
               tst.b     pi.ready(a0)       ; ready?
               beq.l     q.nc
               tst.b     pi.eof(a0)         ;     EOF?
               beq.s     queueIO
               bra.l     q.eof2

io.output      cmpi.b    #7,d0
               bgt.s     io.rest


queueIO        add.w     d0,d0
               move.w    branchtable(pc,d0.w),d0
wissel         jmp       *(pc,d0.w)

*************************** BRANCHTABLE **************************************


branchtable    dc.w      q.pend-wissel               ; IO.PEND    0
               dc.w      q.fbyte-wissel              ; IO.FBYTE   1
               dc.w      q.fline-wissel              ; IO.FLINE   2
               dc.w      q.fstrg-wissel              ; IO.FSTRG   3
               dc.w      q.bp-wissel                 ; IO.EDLIN   4
               dc.w      q.sbyte-wissel              ; IO.SBYTE   5
               dc.w      q.bp-wissel                 ;            6
               dc.w      q.sstrg-wissel              ; IO.SSTRG   7



io.rest        cmpi.b    #sd.clear,d0
               beq.l     io.cls
               cmpi.b    #fs.posre,d0
               beq.l     io.posre
               cmpi.b    #fs.posab,d0
               beq.l     io.posab
               bra.l     q.bp




*************************** I/O ROUTINES ************************************

****** IO.PEND ***** 

q.pend         move.l    ch.qin(a0),d0       ; get queue
               beq.l     q.no.input          ; no queue?
               move.l    d0,a2
               vector    io.qtest   a5
               bra.l     q.testeof

****** IO.FBYTE *****

q.fbyte        move.l    ch.qin(a0),d0       ; get queue
               beq.l     q.no.input          ; no queue?
               move.l    d0,a2
               vector    io.qout   a5
               tst.l     d0
               bne.l     q.testeof
               addq.l    #1,pi.filepos(a0)
qb.ready       rts  


****** IO.FLINE ******

q.fline        move.l    ch.qin(a0),d5       ; get queue
               beq.l     q.no.input          ; no queue?
               move.l    d5,a5               ; a5 -> queue
               bsr.l     q.inspace           ; find space
               clr.l     d6                  ; d6 = 0 (byte counter) 
               tst.w     d4
               beq.s     qf.noread           ; nothing to read

* first stretch (from nxtout to q.end) 

               move.l    q.nxtout(a5),a2      ; a2 -> next byte to read
               bra.s     qf.s1
qf.a1          cmp.w     d1,d2                ; bytes read = buflength?
               beq.s     qf.bf                ; buffer full
               move.b    (a2)+,d0
               move.b    d0,(a1)+
               addq.w    #1,d1
               addq.w    #1,d6
               cmpi.b    #10,d0
qf.s1          dbeq      d4,qf.a1
               beq.s     qf.ready              ; was d0 = 10 indeed? 
               tst.w     d5
               beq.s     qf.ready

* second stretch (from q.queue to q.nextin)

               lea.l     q.queue(a5),a2
               bra.s     qf.s2
qf.a2          cmp.w     d1,d2
               beq.s     qf.bf                ; buffer full
               move.b    (a2)+,d0
               move.b    d0,(a1)+
               addq.w    #1,d1
               addq.w    #1,d6
               cmpi.b    #10,d0
qf.s2          dbeq      d5,qf.a2

qf.ready       add.l     d6,pi.filepos(a0)
               cmpa.l    q.end(a5),a2
               blt.s     qf.noworries
               lea.l     q.queue(a5),a2
qf.noworries   move.l    a2,q.nxtout(a5)
               cmpi.b    #10,d0
               bne.l     qf.noread
               bra.l     q.ok
qf.bf          add.l     d6,pi.filepos(a0)
               move.l    a2,q.nxtout(a5)
               bra.l     q.bf

qf.noread      tst.b     (a5)
               blt.l     q.eof
               bra.l     q.nc

****** IO.FSTRG ******

q.fstrg        move.l    ch.qin(a0),d0       ; get queue
               beq.l     q.no.input          ; no queue?
               move.l    d0,a5               ; a5 -> queue
               bsr.l     q.inspace           ; find space
               clr.l     d6                  ; d6 = 0 (byte counter) 
               tst.w     d4
               beq.l     qs.noread           ; nothing to read

* first stretch (from nxtout to q.end)
 
               move.l    q.nxtout(a5),a2      ; a2 -> next byte to read
               bra.s     qs.s1
qs.a1          cmp.w     d1,d2                ; bytes read = buflength?
               beq.s     qs.ready             ; ready
               move.b    (a2)+,(a1)+
               addq.w    #1,d1
               addq.w    #1,d6
qs.s1          dbra      d4,qs.a1
               tst.w     d5
               beq.s     qs.ready

* second stretch (from q.queue to q.nextin)

               lea.l     q.queue(a5),a2
               bra.s     qs.s2
qs.a2          cmp.w     d1,d2
               beq.s     qs.ready              ; ready
               move.b    (a2)+,(a1)+
               addq.w    #1,d1
               addq.w    #1,d6
qs.s2          dbra      d5,qs.a2
               

qs.ready       add.l     d6,pi.filepos(a0)
               cmpa.l    q.end(a5),a2
               blt.s     qs.noworries
               lea.l     q.queue(a5),a2
qs.noworries   move.l    a2,q.nxtout(a5)
               cmp.w     d1,d2 
               bne.l     qs.noread
               bra.l     q.ok

******************** IO.SBYTE *****************************************

q.sbyte        move.l    ch.qout(a0),d5
               beq.l     q.bp
               move.l    d5,a2
               vector    io.qin    a5
               tst.l     d0
               bne.s     qsb.ready
               addq.l    #1,pi.filepos(a0)
qsb.ready      rts  


********************* IO.SSTRG *****************************************

q.sstrg        move.l    ch.qout(a0),d5      ; is there a queue?
               beq.l     q.bp                ; arrgh!
               move.l    d5,a5               ; a5 -> queue
               bsr.l     q.outspace          ; find distances
               clr.l     d6                  ; clear byte counter
               tst.w     d4
               beq.l     q.nc                ; nothing to write

* first stretch

               move.l    q.nextin(a5),a2
               bra.s     qss.s1
qss.a1         cmp.w     d1,d2               ; bytes sent == buflen?
               beq.s     qss.ready
               move.b    (a1)+,(a2)+
               addq.w    #1,d1
               addq.w    #1,d6
qss.s1         dbra      d4,qss.a1
               tst.w     d5
               beq.s     qss.ready

* second stretch

               lea.l     q.queue(a5),a2 
               bra.s     qss.s2
qss.a2         cmp.w     d1,d2
               beq.s     qss.ready
               move.b    (a1)+,(a2)+
               addq.w    #1,d1
               addq.w    #1,d6
qss.s2         dbra      d5,qss.a2

qss.ready      cmpa.l    q.end(a5),a2
               blt.s     qss.noworries
               lea.l     q.queue(a5),a2
qss.noworries  move.l    a2,q.nextin(a5)
               add.l     d6,pi.filepos(a0)
               cmp.w     d1,d2
               bne.l     q.nc
               bra.l     q.ok

qs.noread      tst.b     (a5)
               blt.l     q.eof
               bra.l     q.nc



io.cls         tst.b     pi.eof(a0)
               beq.s     io.not.eof
               clr.b     pi.eof(a0)
               clr.b     pi.ready(a0)
               clr.l     pi.filepos(a0)
               clr.l     d0
               rts
io.not.eof     moveq     #err.bp,d0
               rts

               dc.b      'WHAM!'

io.posab       sub.l     pi.filepos(a0),d1
io.posre       move.l    ch.qin(a0),d0
               bne.s     ip.inpipe
               move.l    ch.qout(a0),d0
               bne.s     ip.outpipe
               tst.b     pi.eof(a0)
               bne.l     q.eof2
               clr.l     d1
               bra.l     q.ok

ip.inpipe      move.l    d0,a5
               bsr.s     find.length
               move.l    q.nextin(a5),d3       ; d3 = maximal virtual pos
               move.l    q.nxtout(a5),d4
               bsr.s     find.pos
               move.l    d4,q.nxtout(a5)
               bra.s     ip.ready

ip.outpipe     move.l    d0,a5
               bsr.s     find.length
               move.l    q.nxtout(a5),d3
               subq.l    #1,d3
               move.l    q.nextin(a5),d4
               bsr.s     find.pos
               move.l    d4,q.nextin(a5)

ip.ready       move.l    d1,pi.filepos(a0)
               clr.l     d0
               rts


* find.length  : in a5 -> queue; out d0 = length, a1 corrupted, a5 preserved

find.length    move.l    q.end(a5),d0
               lea.l     q.queue(a5),a1
               sub.l     a1,d0
               rts

* find.pos
* a 'virtual pointer (vip)' to a queue is a pointer to an address space 
* which is seen when you imagine two mirrors at both ends of the queue 
* by adding or subtracting a suitable multiple (normally 1,0 or -1) of
* the queueue's length you get the actual byte pointed at  
* 
* in:     d0 = length,                  out:  d1 = actual new filepos
*         d1 = new rel filepos,               d4 = new queuepointer
*         d3 = max new virtual pointer,
*         d4 = actual virtual pointer
*         a5 -> queue


find.pos       move.l    pi.filepos(a0),d5
               add.l     d1,d5
               bge.s     fp.fpokee
               sub.l     d5,d1               ; d1 := d1 - (fp + d1) = - fp
fp.fpokee      cmp.l     d4,d3
               bge.s     fp.nochange
               sub.l     d0,d4               ; d4 = actual vip
fp.nochange    move.l    d4,d7
               move.l    d3,d5
               sub.l     d0,d5               ; d5 = min new vip
               add.l     d1,d4               ; d4 = new asked for vip
               cmp.l     d4,d5
               blt.s     fp.ok1
               move.l    d5,d4
               addq.l    #1,d4
fp.ok1         cmp.l     d4,d3
               bge.s     fp.ok2
               move.l    d3,d4
fp.ok2         sub.l     d4,d7
               neg.l     d7
               add.l     pi.filepos(a0),d7
               move.l    d7,d1
               lea.l     q.queue(a5),a4
               cmpa.l    d4,a4
               ble.s     fp.ok3
               add.l     d0,d4
fp.ok3         cmp.l     q.end(a5),d4
               blt.s     fp.ok4
               sub.l     d0,d4
fp.ok4         rts


************************* UTILITIES ***************************************
* q.inspace
* in:     a5 -> queue
* out:    d4 =  waiting input until q.end
*         d5 =  rest waiting from q.queue           
*         d6    corrupted

q.inspace      clr.l     d5
               move.l    q.nextin(a5),d4
               sub.l     q.nxtout(a5),d4
               bge.s     qw.ready
               move.l    q.end(a5),d4
               sub.l     q.nxtout(a5),d4
               move.l    q.nextin(a5),d5
               move.l    a5,d6
               add.l     #q.queue,d6
               sub.l     d6,d5
qw.ready       rts


* q.outspace
* in:     a5 -> queue
* out:    d4 = free space until q.end
*         d5 = free space from q.queue
*         d6 corrupted

q.outspace     clr.l     d5
               move.l    q.nxtout(a5),d4
               sub.l     q.nextin(a5),d4
               subq.l    #1,d4
               bge.s     qo.ready
               move.l    q.end(a5),d4
               sub.l     q.nextin(a5),d4
               move.l    q.nxtout(a5),d5
               move.l    a5,d6
               add.l     #q.queue+1,d6
               sub.l     d6,d5
               bge.s     qo.ready
               add.l     d5,d4
               clr.l     d5
qo.ready       rts

*************************** ERROR EXITS *************************************

q.ok           clr.l     d0
               rts

q.testeof      tst.l     d0
               bne.s     qt.oops
               rts
qt.oops        cmpi.l    #err.eof,d0
               beq.s     q.eof
               rts

q.no.input     tst.l     ch.qout(a0)              ; there is no input queue
               beq.s     q.nc                     ; nc if there is no output
               bra.s     q.bp                     ; bad parameter if there is

q.nc           moveq     #err.nc,d0
               rts


q.eof          tas       pi.eof(a0)        ; set EOF flag
               move.l    pi.partner(a0),d7 ; where is partner?
               beq.s     q.ff
               movem.l   d1-d3/a0-a3,-(a7) ; save regs
               move.l    d7,a0
               bsr.l     geef.terug
               movem.l   (a7)+,d1-d3/a0-a3
               clr.l     pi.partner(a0)    ; partner dead
q.eof2         moveq     #err.eof,d0
               rts


q.ff           moveq     #err.ff,d0
               rts
q.bf           moveq     #err.bf,d0
               rts
q.bp           moveq     #err.bp,d0
               rts


               END
