; move comments over 1 tab	C/;/	;/
; move back 1 tab        	C/	;/;/
; find leading spaces and convert to tabs	4y5y6y
; put 24 leading	1,$c/^                        /			/4p
;      16        	1,$c/^                /		/5p
;       8         	1,$c/^        /	/6p
;
$MACRO callr here (use this for co-routine call - won't use stack)
        jmp #@1
$ENDM
$MACRO moveb from to nbytes
?? 4
        mov #@1,r0
        mov #@2,r1
        mov #@3,r2
#@4=.
        movb (r0)+,(r1)+
        sob r2,#@4
$ENDM
/
        PROGRAM trn
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;   This program monitors the lines and spawns the receiver and sender
;   (its active on both ends) when it detects either a send data (to send)
;   or inputs a char (to be receiver).
;
;       The following are the handshake codes between this program
;       and the ones the sender/receiver send back and forth.
;
;       sender          receiver
;       4 S's           4 R's           these are sync codes
;                       A               ack
;                       null            nack
;                       F               fatal, next 2 bytes are error code
;
;          G            S               Sender starts receiver with a G
;                       X               after a send completes, receiver sends
;                                       an S if it wants to become next sender
;                                       or an X if it does not.
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;       The xmt program (or whatever it is called) does a send data to this
;       this task with the following format:
;               word 1      -      default uic
;               word 2      -      protection uic (login uic)
;               word 3-13   -      rest of file name (22 chars max)
;       This task passes on the default uic, and spawns with the prot uic.
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



        .title tran

        .enabl lc
        .enabl ama
	.nlist sym

        .psect tran

        .mcall qiow$,dir$,alun$,srda$s,astx$s,ustp$
        .mcall rcvd$,spwn$,wtse$,qiow$s,exit$s,stop$s

        cr      =       15             ;ascii return
        esc     =       33             ;ascii escape key
        blank   =       40             ;ascii space bar
        lun     =       1              ;lun for communications
        ef      =       1              ;ef for    "      "
        ugc     =       0              ;uic group code - non priv'd
        umc     =       0              ;    member
        ugcp    =       1              ;uic group code - priveled (receiv)
        umcp    =       1              ;    member
        efs     =       20.            ;spawn event flag



begin:   
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
outch:  qiow$ io.wal,lun,ef ,,ios,, <char,1,0>          ;output 1 char
inch:   qiow$ io.ral,lun,ef ,,ios,, <char,1>            ;input  1 char
att:    qiow$ io.ata,lun,ef ,, ,, <cast>                ;char ast
det:    qiow$ io.det,lun,ef                             ;detach terminal
assign: alun$ lun,CM,0                                  ;assign lun
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
recdat:  rcvd$   ,rtask                 ;receive
rtask:  .word 0,0                       ;received data task name
uic:    .word 0                         ;default uic
puic:   .word 0                         ;protection uic
rbuf:   .blkw 11.                       ;receive buffer
;spawnr: spwn$ MCR...,,,ugcp,umcp,efs,,status,rcmdln,rcmd,0,CO  ;spawn receiver
spawnr: spwn$ RECEIV,,,ugcp,umcp,efs,,status,,,0,CO            ;spawn receiver
spawns: spwn$ SENDER,,,ugcp,umcp,efs,,status,scmdln,scmd ;spawn sender
wait:    wtse$ efs              ;wait for spawn (can't stop in an ast)
unstop: ustp$  tasknm           ;to be filled in later
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;rcmdln: .ascii 'ins $receive/TASK=RECEIV/uic=[1,1]/run=rem' ;CO: MUST be priv'd
;rcmd=.-rcmdln
scmdln: .byte 1,0,0,40                  ;encode uic here
scmd=.-scmdln
sbuf:   .blkb 90.-scmd                  ;allocate remainder
        .even
ios:    .word 0,0
char:   .byte 0,0
ch:     .byte 0,0                       ;save the c ast char
status: .blkw 8.
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

start:     
        srda$s #rast            ;spec receive ast
        dir$ #assign            ;assign lun to communications line
        dir$ #att               ;attach and specify ast on comm line
        stop$s                  ;stop, do all work in asts
        exit$s
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rast:                           ;receive ast
	mov r0,-(sp)
	mov r1,-(sp)
	mov r2,-(sp)
	mov r3,-(sp)
	mov r4,-(sp)
	mov r5,-(sp)
        dir$ #det                  ;detach comm line
        DO FOREVER
           dir$ #recdat            ;then receive data

           IF $dsw NE #is.suc      ;rsx won't work correctly so we must
              BREAK                ;propogate ourselves and exit only
           FI                      ;when nothing in receive queue.
                                   ;what happens if we receive right here ???
                                   ;do we lose an ast, I don't know.

           mov #'G,char            ;send the Go signal
           dir$ #outch             ;by outputing a char G

           call snd                ;spawn the snd program

        OD
        dir$ #att                  ;re-attach here

	mov (sp)+,r5
	mov (sp)+,r4
	mov (sp)+,r3
	mov (sp)+,r2
	mov (sp)+,r1
	mov (sp)+,r0

        astx$s                     ;exit (no data need be clear from stack)
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cast:                           ;input char ast
        mov (sp)+,ch            ;save the char

	mov r0,-(sp)
	mov r1,-(sp)
	mov r2,-(sp)
	mov r3,-(sp)
	mov r4,-(sp)
	mov r5,-(sp)

        dir$ #det               ;detach comm line

        IFB ch = #'G            ;check for garbage, only a G is ok
        call rcv                ;spawn the receiving end
        FI

        dir$ #att               ;re-attach here

	mov (sp)+,r5
	mov (sp)+,r4
	mov (sp)+,r3
	mov (sp)+,r2
	mov (sp)+,r1
	mov (sp)+,r0

        astx$s                  ;exit

;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rcv:                            ;get receiver going
        dir$ #spawnr            ;spawn receiver
        dir$ #wait              ;and wait for it
 
        dir$ #recdat            ;see if any thing queued up here
        IF $dsw = #is.suc       ;if yes, then we will be sender
            mov #'S,char        ; for a while
            dir$ #outch         ; so, send an 'S back
            callr snd           ; and shift to snd routine
        ELSE
            mov #'X,char        ;otherwise just return an 'X
            dir$ #outch         ;to indicate were done
        FI
        rts pc

;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
snd:                            ;get the sender going
        movb #blank,sbuf
        moveb #sbuf,#sbuf+1,#80. ;blank out remainder of buffer
        moveb #rbuf,#sbuf,#22.  ;copy it all in

        call spwns              ;spawn sender with file name
        call restart            ;restart the sender
        dir$ #inch              ;get other sides response
        IFB char = #'S          ;if he wants to send, then
           callr rcv            ;we will receive
        FI                      ;for a while
        rts pc
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
restart:                                   ;restart the sender
           mov rtask,unstop+u.sttn         ;first part of name
           mov rtask+2,unstop+u.sttn+2     ;second part of name
           dir$ #unstop                    ;do it
           rts pc
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
spwns:
        LOOP for r0 = #sbuf+24. DOWNTHRU #sbuf step #-1
        BREAK IFB (r0) NE #blank
        NEXT r0

        inc r0
        movb #cr,(r0)
        sub #sbuf,r0
        add #4,r0

        mov r0,spawns+s.pwcl
        movb puic,spawns+s.pwum                 ;member
        movb puic+1,spawns+s.pwug               ;group

        movb #1,scmdln                          ;stuff
        movb uic,scmdln+1                       ;the command line to include
        movb uic+1,scmdln+2                     ;the default uic

        dir$ #spawns            ;spawn sender
        dir$ #wait              ;and wait for it
        rts pc


        .end start
