include  "inc:util.imp"
include  "inc:fs.imp"
begin 

integerfn  EtherPacketStatus(integer  port)
   integer  bit

   bit = 1<<port
   if  ack & bit # 0 start 
      result  = -1 if  nak & bit # 0
      result  = 1
   finish 
   result  = 0
end 

predicate  EtherPacketPending(integer  port)
   integer  bit
   bit = 1<<port
   true  if  dtx & bit # 0
   false 
end 

integerfn  gotack(integer  port, deadline)
   !Wait for an ether ACK or NAK for DEADLINE milliseconds.
   !Return -1 for a NAK, 1 for an ACK and 0 if the deadline expired.
   integer  es
   deadline = cputime + deadline
   cycle 
      es = EtherPacketStatus(port)
      nak = nak!!(1<<port) if  es < 0
      result  = es if  es # 0
   repeatuntil  cputime>deadline
   result  = 0
end 

predicate  gotdtx(integer  port, deadline)
   ! Wait for DTX and TRUE.  FALSE when fed up
   deadline = cputime+deadline
   cycle 
     trueif  EtherPacketPending(port)
   repeatuntil  cputime>deadline
   false 
end 

!These reduced * 10 for testing
constinteger  ack deadline      = 200 ;!milliseconds
constinteger  response deadline = 1500 ;!milliseconds

constinteger  vax = 16_7200

recordformat  ntmf(byte  dummy,unit,command,seqflags,string (248)s)

constinteger  start process =  0
constinteger  readrequest   =  1
constinteger  read data     =  2
constinteger  write done    =  3
constinteger  write data    =  4
constinteger  disconnect    =  5
constinteger  ctrlc         =  6
constinteger  ctrly         =  7
constinteger  setmode       =  8
constinteger  cancel        =  9
constinteger  broadcast     = 10
constinteger  typeahead     = 11

constinteger  cr=13,lf=10,esc=27

routine  dropout(string  (127) text)
   !Stop the program. If text is non-null print a diagnostic message first.

   if  text # "" start 
      printstring("Vax ".text." timeout")
   finish 
   newline
   stop 
end 


string (255)dummy
record (ntmf)ntm
bytename  u,c,sf,l
string (248)name  s
integer  lport,rport,x,i,j

  dummy = cliparam
  lport = 1; lport = 2 if  lport=fsport
  u == ntm_unit
  c == ntm_command
  sf == ntm_seqflags
  s == ntm_s
  l == length(s)
  ntm = 0

! Connect to vax

  etheropen(lport,vax+0)
  u = 1
  etherwrite(lport,u,1)

  dropout("Initial Write") unless  c 
  gotack(lport, ack deadline) >= 0 and  gotdtx(lport, response deadline)

  l = etherread(lport,charno(s,1),248)

  dropout(s) unless  c 
  l=2 and  charno(s,2)=nl and  1<=charno(s,1)-'0'<=31

  rport = charno(s,1)-'0'; u = rport
  etheropen(lport,vax+rport)
  prompt(""); set terminal mode(nopage)

! Start Process

  c = start process
  etherwrite(lport,u,4)

! Main Loop

routine  main

integer  pendlf=0

routine  outstring(string (*)name  s)
integer  i,k
  for  i=1,1,length(s) cycle 
    k = charno(s,i)
    if  k=nl start 
      pendlf = 0 unless  i<=2
      if  pendlf=0 start 
        newline
      finish 
      pendlf = 0
    elseif  k=cr
      printsymbol(cr)
    else 
      printsymbol(k)
    finish 
  repeat 
  if  k=cr start 
    newline
    pendlf = 1
  finish 
end 
  
routine  diagnose(integer  x)
integer  i,j
  printsymbol('['); phex2(c)
  printsymbol(','); phex2(sf)
  printsymbol(','); phex2(l)
  printsymbol(',')
  for  i=1,1,x-4 cycle 
    j = charno(s,i)
    if  ' '<=j<=126 then  printsymbol(j) elsestart 
      printsymbol('_'); phex2(j)
    finish 
  repeat 
  printsymbol(']'); newline
end 

routine  keyboard
  onevent  0,3,9 start 
    if  event_event=9 start 
      printstring("^Z")
      x = 'Z'-64; ->eof
    finish 
    printstring("^Y")
    c = 7; return 
  finish 
  c = 2; s = ""
  set terminal mode(nopage{+notermecho}+noecho) if  sf&noecho#0
  cycle 
    readsymbol(x)
    if  x=cr or  x=lf start ; !Bloody stupid idea his swopping
      x = x!!(cr!!lf)
      pendlf = 1
    finish 
    s = s.tostring(x)
    if  x<32 start 
      if  x='C'-64 start 
        printstring("^C")
        c = 6; return 
      finish 
      returnunless  x=esc
      readsymbol(x)
      if  x='?' start 
        s = s.tostring('?')
        readsymbol(x)
      finish 
eof:  s = s.tostring(x)
      return 
    finish 
  repeatuntil  length(s)>=245
end 

switch  sw(0:15)
onevent  0 start 
  printstring("^Y")
  c = 7; ->cy
finish 
  cycle 
    set terminalmode(nopage{+notermecho})
    x = etherread(lport,u,252)
    ->sw(c) if  c&15=c
sw(start process): printstring("Start Process"); ->bum
sw(read data):     printstring("Read Data");     ->bum
sw(write done):    printstring("Write Done");    ->bum
sw(ctrlc):         printstring("^C");            ->bum
sw(ctrly):         printstring("^Y");            ->bum
sw(typeahead):     printstring("Typeahead");     ->bum
sw(cancel):        printstring("Cancel");        ->bum
sw(12):            printstring("Number 12");     ->bum
sw(13):            printstring("Number 13");     ->bum
sw(14):            printstring("Number 14");     ->bum
sw(15):            printstring("Number 15")
bum:               printstring(" message received"); newline
    diagnose(x)
sw(setmode):
    continue 
sw(broadcast):
    outstring(s)
    continue 
sw(write data):
    pendlf = 0 if  sf&1#0
    outstring(s); l = 0; c = write done
    dropout("Write") if  gotack(lport, ack deadline) < 0
    etherwrite(lport,u,4)
    continue 
sw(read request):
    outstring(s)
    keyboard
cy: dropout("Write") if  gotack(lport, ack deadline) < 0
    etherwrite(lport,u,l+4)
  repeat 

sw(disconnect): dropout("")
end 

main

endofprogram