* QL WORLD DIY TOOLKIT - PIPE routines
* Ver. 0.4, Copyright 1988 Simon N Goodwin.
*
start      lea.l    define,a1
           move.w   $110,a2         BP.INIT vector
           jmp      (a2)
*
define     dc.w  1                One procedure
           dc.w  qlink-*
           dc.b  5,'QLINK'
           dc.w  0,3              3 functions
           dc.w  qspace-*
           dc.b  7,'QSPACE%'
           dc.w  qsize-*
           dc.b  6,'QSIZE%'
           dc.w  qcount-*
           dc.b  7,'QCOUNT%'
           dc.w  0                End of functions
*
pipe_name  dc.w  6                Input pipe name string
           dc.b  'PIPE_0'
*
qlink      move.w   $112,a2       Vector to get integers
           jsr      (a2)          CA.GTINT
           bne.s    bad_exit
           subq.w   #2,d3         Check for two channels
           bne.s    bad_param
           bsr.s    get_channel
           bmi.s    not_open
           addq.l   #2,a1         Discard first integer
           move.l   d3,d5         Save first channel ID
*
* Process second channel No. & close channel if need be
*
           bsr.s    get_channel
           bmi.s    closed
           move.l   d3,a0
           moveq    #2,d0         IO.CLOSE
           trap     #2
*
* Connect input channel to existing pipe 
*
closed     moveq    #-1,d1        Owner is this task
           move.l   d5,d3         Output pipe ID
           lea.l    pipe_name,a0
           moveq    #1,d0         IO.OPEN
           trap     #2
           tst.l    d0            Did the OPEN fail?
           bmi.s    bad_exit
           move.l   a0,0(a6,d7.l) Store channel ID
           rts                    Return no error
*
* Check channel number; set D3 to ID and D7 to offset
*
get_channel move.w  0(a1,a6.l),d7 Get BASIC channel No.
           mulu     #40,d7        Channel table size
           add.l    $30(a6),d7    Add base offset
           cmp.l    $34(a6),d7 
           bge.s    what_chan     Past end of table?
           move.l   0(a6,d7.l),d3 Grab channel ID
           rts
*
what_chan  addq.l   #4,a7         Return to old caller
not_open   moveq    #-6,d0        Error, Channel not open
           rts
bad_param  moveq    #-15,d0       Error, Bad parameter
bad_exit   rts
*
qspace     moveq    #-1,d5        D5<0 for QSPACE%
           bra.s    get_param
qsize      moveq    #0,d5         D5=0 for QSIZE%
           bra.s    get_param
qcount     moveq    #1,d5         D5>0 for QCOUNT%
*
get_param  move.w   $112,a2       Vector to get integers
           jsr      (a2)          CA.GTINT
           bne.s    bad_exit
           subq.w   #1,d3         Check there's only one
           bne.s    bad_param
           bsr.s    get_channel   Locate channel
           bmi.s    not_open      Channel must be open
*
           moveq    #0,d0         MT.INF to find queue
           trap     #1            Find system variables
           move.l   120(a0),a0    Base of QDOS channels
           lsl.w    #2,d3         Convert D3.W to offset
           move.l   0(a0,d3.w),a0 Base of channel details
           move.l   24(a0),d0     Check input queue base
           beq.s    try_output    It's zero, try output
           bmi.s    bad_param     Not a pipe!
           tst.l    28(a0)        Check output is closed
           bne.s    bad_param     Not a pipe!
           bra.s    got_queue
*
try_output move.l   28(a0),d0     Try output queue base
           ble.s    bad_param     Not a pipe!
got_queue  btst     #0,d0         Queue base must be even
           bne.s    bad_param     Not a pipe!
           move.l   d0,a2         Assume it's a queue
*
* Compute total space available in D7
* 
           move.l   4(a2),d7      Get end pointer
           lea.l    17(a2),a3     Point 1 beyond start
           sub.l    a3,d7         D7 is queue size
           tst.l    d5            For QSIZE% the
           beq.s    return_int    result is in D7
*
           move.w   222,a0        IO.QTEST vector
           jsr      (a0)
*
* Ignore EOF and NOT COMPLETE (i.e. empty) reports
*
           tst.l    d5              
           bpl.s    find_used
           move.l   d2,d7         Return QSPACE%
           bra.s    return_int           
find_used  sub.l    d2,d7         Return QCOUNT%       
*
return_int move.w   d7,0(a1,a6.l) Put result in space
           moveq    #3,d4         Indicate type is INT
           moveq    #0,d0         No error
           rts                     
*
           end
