{ Card reader spooler interfacing to 5/16 front end. }

{Modified at PARMFM below to compile with new compiler}
%begin

%recordformat  parmfm(%shortinteger  dsno, dact, ssno, sact,  %c
                     (%bytearray  b(1:24)  %or %integer P1,P2,P3,P4,P5,P6) )

%constinteger line limit = 161
%string(161)  line
%record(parmfm)  p, fdr
%record(parmfm)   text
%integer  tp
%owninteger  binary = 0
%integer  job type
%string(23)  user process, file name, password
%string(23)  s
%integer  unit, user, pass
%byteintegerarray  buff(0:511);  %integer  bp

%integer  temp file, file key, error, skipping, delete flag
%integer  j, k, sym, term

%constinteger  LINK READ = 3;   ! input request to link demon
%constinteger  EOT = 4
%constinteger  INITIALISE = 1;   ! must be 1 for 'STARTUP' program (q.v.)
%constinteger  COMMAND  = 2
%constinteger  GET = 3
%switch  act(INITIALISE:GET)

! packed names:
%constinteger  BATCH = 2566987, SELF = 1253847, LP=604 , PP=608 , CR=669
%constinteger  OPER  = 1007883
! BEL control characters in strings
%conststring(1)  squeak = "";   ! one BEL
%conststring(3)  blast  = "";   ! three BEL's

%routine  report(%string(23) s)
%record(parmfm)  p
   string(addr(p_p1)) = s
   p_dsno = 0
   svc(120,p)
%end


%predicate  spooler(%integer  user name)
   %true %if user name = LP %or user name = PP
   %false
%end

%routine  pack(%string(31)  fd, %record(parmfm)%name  p)
   string(addr(p_sact)) = fd
   svc(17,p)
%end


%routine  transvest
%record(parmfm)  p
   p_p1 = unit
   p_p2 = user
   p_p3 = pass
   p_p6 = 0
   p_dact = 27;  svc(20,p);    ! become
   %if p_p6 < 0 %start
      report("tranvest:".string(addr(p_p1)))
      %signal 15,15
   %finish
%end

%routine  revert
%record(parmfm)  p
   p_dact = 27;  p_p2 = 0;  p_p6 = 0;  svc(20,p)
   %if p_p6 < 0 %start
      report("revert:".string(addr(p_p1)))
      %signal 15,15
   %finish
%end

%integerfn  opened output
%record(parmfm)  p
   p_dact = 25;  svc(20,p);   ! unique file
   temp file = p_p4
   p_p3 = 0;      ! packed CR
   p_dact = 5;  svc(20,p);      ! open output
   %if p_p6 < 0 %start
      report("open:".string(addr(p_p1)))
      p_p5 = 0
   %finish
   %result = p_p5
%end

%routine  write buffer
%record(parmfm)  p
   p_p4 = addr(buff(0))
   p_p5 = file key
   p_dact = 8;  svc(20,p);   ! sequential write
   %if p_p6 < 0 %start
      report("write:".string(addr(p_p1)))
      %signal 15,15
   %finish
%end

%routine  put(%integer  sym)
   buff(bp) = sym;  bp = (bp+1)&511
   write buffer %if bp = 0
%end

%routine  insert(%string(63)  s)
%integer  j
   put(charno(s,j)) %for j = 1,1,length(s)
   put(nl)
%end

%routine  close file
%record(parmfm) p
   put(EOT) %until bp = 0
   p_p5 = file key;  p_dact = 11;  svc(20,p);   ! close
   %if job type = 1 %and %not spooler(user) %start;   ! //FILE (to user file)
      %if delete flag # 0 %start
         p = fdr
         p_dact = 14;  svc(20,p);   ! delete
         delete flag = 0
      %finish
      p_p3 = 0;  p_p4 = temp file
      p_p5 = fdr_p3;  p_p6 = fdr_p4
      p_dact = 15;  svc(20,p);   ! rename
   %else
      p_dact = 1;                  ! normal offer
      p_p3 = fdr_p3;  p_p4 = fdr_p4
      p_p5 = 0;  p_p6 = temp file
      %if job type # 1 %start;      ! //JOB, //OS32
         p_p1 = BATCH
         %if user process # ":" %start
            p_dact = 14
            p_p1 = unit;  p_p2 = user;  p_p5 = pass
         %finish
      %else;                        ! //FILE (to output spooler)
         p_p1 = user
      %finish
      svc(22,p);                     ! offer
      %if p_p6 < 0 %start
         report("offer:".string(addr(p_p1)))
         %signal 15,15
      %finish
   %finish
   file key = 0;   ! to inhibit any further 'close' attempts
%end;   ! close file

%integerfn  code for(%string(5)  s)
%conststring(5)%array job type(0:3) =
      "END ", "FILE", "JOB ", "OS32"
%integer  j
   %for j = 0,1,3 %cycle
      %result = j %if s = job type(j)
   %repeat
   %result = -1
%end

%routine  decode params
%integer  t
   %string(63)%fn  item
   %string(63)  s
      s = ""
      %cycle
         t = t+1
         %exit %if t >= length(line);   ! can ignore last character
         sym = charno(line,t)
         %exit %if sym = ':' %or sym = ','
         s = s.tostring(sym) %if sym # ' '
      %repeat
      %result = s
   %end
   user process = "";  filename = "";  password = ""
   error = 0
   t = 7-1;               ! past job type word
   user process = item.":";   ! **** the logic here needs checking ****
   %if sym = ',' %start
      file name = ""
   %else
      file name = item
   %finish
   error = 0
   password = item
   delete flag = 0;  delete flag = 1 %if item = "DELETE"
   pack(user process.filename,fdr)
   error = 1 %and %return %if fdr_p2 < 0
   pack(password.":",p);  pass = p_p2
   pack(user process.password,p);  unit = p_p1;  user = p_p2
   %return %if spooler(user)
   %if password # "" %start
      p_dact = 21;  svc(20,p);   ! find user
      %if p_p6 < 0 %or p_p3 # pass %start
         %if p_p6 < 0 %start
            report(blast."no user ".user process)
         %else
            report(blast."password for ".user process)
         %finish
         error = 1
      %finish
   %finish
%end

!      ======= start here ==========
act(INITIALISE):   ! ***** a frig up meantime *****
   p_p1 = 19;  svc(122,p);   ! uninhibit link
act(COMMAND):
      -> startup

WAIT:
   %cycle
      p_sact = 0;  svc(16,p);   ! poff(0,p)
      -> act(p_dact) %if 0 < p_dact <= GET
      report("bad dact")
   %repeat

STARTUP:
   skipping = 1
   file key = 0
   delete flag = 0
   job type = 0
   bp = 0
   tp = 25
   term = nl
   report("CR initialised")

   %cycle
      %cycle
         j = 0
         %cycle
            %if tp = 25 %start
               p_sact = GET; p_dact = link read; svc(127,p)
               -> wait
act(GET):
               text = p;  tp = 1
            %finish
            sym = text_b(tp);  tp = tp+1
            %if binary = 0 %and sym&x'80' # 0 %start
               k = sym&63;  sym = ' '
            %else
               k = 1
            %finish
            %cycle
               j = j+1 %if j # line limit
               charno(line,j) = sym
               k = k-1;  %exit %if k = 0
            %repeat
            %exit %if sym = term
         %repeat
         length(line) = j
         %exit %if charno(line,1) = '/' = charno(line,2)   %c
                                          %and charno(line,3) # nl
         %if skipping = 0 %start
            put(charno(line,j)) %for j = 1,1,length(line)
         %finish
      %repeat
      skipping = 1
      close file %if file key # 0
      revert;      ! N.B. may not actually do anything
      bp = 0;         !  --- initialise output buffer pointer ---
      charno(line,length(line)) = ' ';      ! splat NL
      line = line." " %while length(line) < 6
      report(squeak.line);   ! * for operator's edification
      job type = code for(substring(line,3,6))
      %if job type <= 0 %start;      ! error, //END
         report(blast.substring(line,1,6)) %if job type < 0
         %continue;      ! skip this job
      %finish
      decode params
      %continue %if error # 0
      skipping = 0
      %if job type # 1 %start;      ! //JOB, //OS32
         transvest %if user process # ":"
         file key = opened output
         insert("OS32MT") %if job type = 3
      %else;                        ! //FILE
         transvest %if %not spooler(user)
         file key = opened output
      %finish
   %repeat
%endofprogram
