DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦eea024bed⟧ TextFile

    Length: 86016 (0x15000)
    Types: TextFile
    Names: »ttramos«

Derivation

└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ.
    └─⟦b2ec5d50f⟧ 
        └─⟦this⟧ »ttramos« 

TextFile

begin

  <* variables for claiming (accumulating) basic entities *>
  integer maxsem, maxsemch, maxop, maxcoru, maxmessext, maxprocext, maxnettoop;

  <* fields defining current position in pools af basic entities
     during initialization *>
  integer array field firstsem, firstsim, firstcoru, firstop, optop;

  <* variables used as pointers to 'current object' (work variables) *>
  integer messext, procext, timeinterval, testbuffering;
  integer array field timermessage, coru, sem, op, receiver, currevent,
    baseevent, prevevent;

  <* variables defining the size of basic entities (descriptors) *>
  integer corusize, semsize, simsize, opheadsize;
  integer array clockmess(1:2);
  real array clock(1:3);
  boolean eventqueueempty;

message  trim variables;
  algol list.on;
  integer no_of_terminals,max_children,cur_children,
          child_base_address,childrencreated,termdisconnect,
          oscommunication,osparentmess,
          length_user_cat_entry,
          length_user_cat_entry0,size_user_cat,
          user_cat_users,
          con_desc_size,
          no_of_drums,no_of_discs,no_of_bs,
          core_block_size,no_of_core_blocks,
          first_user_core,
          reader,punch,console1,console2,firstmt,lastmt,firstterminal,
          lastterminal,lastdevice,
          sysconpda,
          ownbuf,ownarea,owninternal,
          freebuf,freearea,freeinternal,
          user_cat_lower,user_cat_upper,
          cat_sem,z_sem;
  integer field base_ref;
  integer array field cat_base_ref,std_base_ref,max_base_ref,
                      core_address_ref,own_ref,
          first_bs_ref,size_bs_ref;
  long field run_time_ref,start_time_ref;
  integer field buf_area_ref,int_func_ref,parent_ref;
  boolean field state_ref;
  integer bit_0,bit_batch,bit_abs_size,bit_std_base,
          bit_evening,bit_maxclaim,bit_auto,bit_waiting,
          bit_c1,bit_priv,tw_mask; 
  boolean bit_mess,bit_answer,bit_wait,
          bit_run ,bit_stop  ,bit_start,
          bit_proc,bit_not_run,mon_list,mon_change;
  integer std_buf,std_area,std_int,std_func,std_size,
          std_temp_entries,
          std_entries,std_segm_disc,std_segm_disc1,
          std_entry_disc,std_entry_disc1;
  integer std_max_buf,std_max_area,std_max_int,std_max_size,
          std_max_entries,std_max_segm_disc,std_max_segm_disc1,
          std_max_entry_disc,std_max_entry_disc1,
          own_entries,own_entry_disc,own_segm_disc,
          own_entry_disc1,own_segm_disc1;
  long array drum_name,std_disc_name,std_disc1_name,
       user_cat_name,own_drum,own_disc,own_disc1,
       std_program,
       own_name,name1,name(1:3);
  long array field laf;
  integer array field iaf;
  real array field raf;
  integer i,j,k;
  integer field con_access,con_prio_and_commands,
       con_first_address,con_top_address,con_buf_and_area,
       con_job_id,
       con_int_and_func,con_mode,
       con_lower_max,con_upper_max,con_lower_std,con_upper_std,
       con_size,con_lower_user,con_upper_user,con_projno,
       con_usercat_no,con_job_state,
       con_term_pda,
       con_cur_child,con_cur_child_pda,
       con_term_no,con_ref,con_proc_in,con_proc_out,
       con_job;
  integer array field cur_con_desc,con_first_bs,fi;
  long array field con_proc_name,con_program,
    con_des_term,
    con_in_name,con_out_name,con_term_name,con_job_name;
  integer maxpmess,maxmess;
  boolean array testop(1:12);
  long array sysconsole,logconsole,monitorconsole(1:3);
  integer array tail(1:10);
  long array field doc;
  array field f;
  boolean lock;
  algol list.off;
  algol copy.tmonpr;
message  error messages: trim variable;
  integer size_error_message;
message  batch queue: trim variables and fields;
  algol list.on;
  integer qdescsize,qdes,b_max_jobs,b_curjob,
          b_child_first,b_child_last,
          b_max_time,
          b_max_time_day,  b_max_size_day,
          b_max_time_night,b_max_size_night,
          b_day_to_night,  b_night_to_day,
          b_upd_time,b_interval,b_time_slice,b_std_time,
          b_max_children,b_cur_children,b_job_number,
          b_run_children,b_stop_begin,b_stop_end,
          swop_segm,
          b_max_prio_day;
  real    b_time_fac,b_job_fac;
  integer field q_jobmask,
                q_job_no,q_job_state,q_job_seq,q_max_time,
                q_start_time,
                q_remove_job_file,q_lref;
  long array field q_job_name,q_printer,q_wrk_o,
                   d_job_name;
  integer field q0_max_time_day,q0_max_size_day,
                q0_max_time_night,q0_max_size_night,
                q0_day_to_night,q0_night_to_day,
                q0_upd_time;
  long array qname,swop,swopdoc(1:3);
  algol list.off;
message  primary input: global definitions;
  integer array field l_line_buf;
  integer field l_next,l_type;
  long array field l_procname,l_jobname,l_outname,l_printer,l_last;

  maxsem:= maxsemch:= maxop:= maxcoru:= maxnettoop:= 0;
  maxmessext:= maxprocext:= 1;
  corusize:= 20;
  simsize:= 6;
  semsize:= 8;
  opheadsize:= 8;
  testbuffering:= 1;
  timeinterval:= 5;

message  trimming;
  algol list.on;
  lock:=true;
  bit_0       :=(1 shift 0);
  bit_batch   :=(1 shift 1);
  bit_abs_size:=(1 shift 2);
  bit_std_base:=(1 shift 3);
  bit_evening :=(1 shift 4);
  bit_maxclaim:=(1 shift 5);
  bit_auto    :=(1 shift 6);
  bit_waiting :=(1 shift 7);
  bit_c1      :=(1 shift 8);
  bit_priv    :=(1 shift 9);
  twmask:=-1; <*mask for typewriters in call of open*>
  <*bits for process state*>
  bit_mess   :=false add (1 shift 0);
  bit_answer :=false add (1 shift 1);
  bit_wait   :=false add (1 shift 2);
  bit_run    :=false add (1 shift 3);
  bit_stop   :=false add (1 shift 4);
  bit_start  :=false add (1 shift 5);
  bit_proc   :=false add (1 shift 6);
  bit_not_run:=false add (1 shift 7);
  state_ref   :=12; <*process state*>
  buf_area_ref:=28;
  int_func_ref:=30;
  parent_ref:=52;
  std_base_ref:=76;
  max_base_ref:=72;
  cat_base_ref:=68;
  core_address_ref:=22;
  start_time_ref:=60+2;
  run_time_ref:=56+2;
  base_ref:=100; <*base register*>
  firstbs_ref:=86;
  size_bs_ref:=18;
  i:=0;
  i:=con_access:=i+2;
  i:=con_prio_and_commands:=i+2;
  i:=con_proc_name:=i;
  i:=con_first_address:=i+2+8;
  i:=con_top_address:=i+2;
  i:=con_buf_and_area:=i+2;
  i:=con_int_and_func:=i+2;
  i:=con_mode:=i+2;
  i:=con_lower_max:=i+2;
  i:=con_upper_max:=i+2;
  i:=con_lower_std:=i+2;
  i:=con_upper_std:=i+2;
  i:=con_size:=i+2;
  i:=con_program:=i;
  i:=con_lower_user:=i+2+8;
  i:=con_upper_user:=i+2;
  i:=con_projno:=i+2;
  i:=con_user_cat_no:=i+2;
  i:=con_in_name:=i;
  i:=con_out_name:=i+8;
  i:=con_term_name:=i+8;
  i:=con_jobstate:=i+10;
  i:=con_job_id:=i+2;
  con_first_bs:=con_desc_size:=i+10;
  doc:=2;
  fi:=f:=0; readsfp(<:c:>,logconsole.f,<:c:>);
  for i:=1 step 1 until 12 do testop(i):=false;
  connectlso;
  for i:=1 step 1 until 11 do
  begin
    if testop(i) then write(out,"nl",1,<:*test :>,case i of (
     <:init:>,<:create:>,<:verify:>,<:usercat:>,
     <:communication:>,<:error:>,<:batch:>,<:submit:>,
     <:job:>,<:primary in:>,<:queue selection:>));
  end;
  outendcur(10);
  readsfp(<:cat:>,usercatname.f,<:osusercat:>);
  std_program(1):=long <:fp:>;
  std_program(2):=
  sysconsole(2):=logconsole(2):=monitorconsole(2):=
  drumname(2):=stddiscname(2):=stddisc1name(2):=0;
  curchildren:=0;
  maxmess:=5;
  maxpmess:=5;
  console1:=2;
  ownbuf:=2;
  ownarea:=2;
  owninternal:=1;
  child_base_address:=128*1024;
  algol list.on copy.tramoption;
  ownbuf:=ownbuf+noofterminals;
  readifp(<:children:>,maxchildren,maxchildren);
  readifp(<:blocks:>,noofcoreblocks,noofcoreblocks);
  if maxchildren<noofcoreblocks then maxchildren:=noofcoreblocks;
  readifp(<:size:>,coreblocksize,coreblocksize);
  readifp(<:terminals:>,no_of_terminals,no_of_terminals);
  i:=lookupentry(logconsole,tail);
  if i<>0 then alarm("nl",1,logconsole,<: does not exist:>,i);
  for i:=1,2 do logconsole(i):=tail.doc(i);
  write(out,<:log console is :>,logconsole);
  if readsfp(<:monitor:>,name.f,<::>) then
     readsfp(<:monitor:>,monitorconsole.f,<::>);
  write(out,"nl",1,<:monitor console :>,monitorconsole);
  name(1):=0;
  set_cat_base(name,usercatlower,usercatupper);
  i:=connectcuri(usercatname);
  if i<>0 then alarm("*",3,usercatname,<: connect error :>,i);
  setposition(in,0,0);
  inrec6(in,512);
  length_user_cat_entry:=in.fi(2);
  length_user_cat_entry0:=in.fi(3);
  size_user_cat:=in.fi(4);
  user_cat_users:=in.fi(5);
  unstackcuri;
  no_of_bs:=no_of_drums+no_of_discs;
  if no_of_bs*12+14<>lengthusercatentry0 then alarm("nl",1,
      <:***number of bs devices inconsistent:>,no_of_bs);
  i:=condescsize:=condescsize+size_bs_ref*(no_of_drums+no_of_discs);
  i:=con_proc_in:=i+4;
  i:=con_proc_out:=i+2;
  i:=con_term_pda:=i+2;
  i:=con_des_term:=i;
  i:=con_job_name:=i+8;
  i:=con_cur_child:=i+2+8;
  i:=con_cur_child_pda:=i+2;
  i:=con_term_no:=i+2;
  i:=con_ref:=i+2;
  i:=con_job:=i+2;
  condescsize:=i;
  algol list.off;
message  error message: initialize trim;
  size_error_message:=200;
message  batch queue: initialization;
  algol list.on;
  d_job_name:=4;
  i:=qdescsize:=condescsize;
  i:=q_jobno:=i+2;
  i:=q_jobmask:=i+2;
  i:=q_job_state:=i+2;
  i:=q_job_seq:=i+2;
  i:=q_max_time:=i+2;
  i:=q_start_time:=i+2;
  i:=q_remove_job_file:=i+2;
  i:=q_lref:=i+2;
  i:=q_job_name:=i;
  i:=q_printer:=i+8;
  i:=q_wrk_o:=i+8;
  i:=qdescsize:=i+8;
  <*global information*>
  i:=q0_max_time_day:=con_desc_size+2;
  i:=q0_max_size_day:=i+2;
  i:=q0_max_time_night:=i+2;
  i:=q0_max_size_night:=i+2;
  i:=q0_night_to_day:=i+2;
  i:=q0_day_to_night:=i+2;
  i:=q0_upd_time:=i+2;
  qname(1):=long <:bqueu:> add 'e';
  qname(2):=0;
  b_max_time_day:=20*60; <*sec*>
  b_max_time_night:=8*60*60;
  b_max_size_day:=512*coreblocksize;
  b_cur_job:=0;
  b_maxjobs:=250;
  b_max_children:=1;
  b_std_time:=5*60;
  b_time_slice:=30;
  b_interval:=5;
  swop(1):=long <:bswop:>; swop(2):=0;
  for i:=1,2 do swopdoc(i):=owndisc(i);
  b_time_fac:=0.5;
  b_job_fac :=1.0;
  algol copy.batchtrim;
  readifp(<:btimeslice:>,b_time_slice,b_time_slice);
  b_max_prio_day:=2*b_max_time_day;
  readifp(<:bprio:>,b_max_prio_day,b_max_prio_day);
  readrfp(<:btimefac:>,btimefac,btimefac);
  readrfp(<:bjobfac:>,bjobfac,bjobfac);
  readifp(<:bchildren:>,bmaxchildren,bmaxchildren);
  readifp(<:bjobs:>,bmaxjobs,bmaxjobs);
  readifp(<:bstdtime:>,bstdtime,bstdtime);
  readifp(<:time:>,b_max_time_day,b_max_time_day);
  laf:=2;
  swopsegm:=bmaxchildren*bmaxsizenight//512+1;
  b_curchildren:=0;
  qdes:=b_maxchildren+1;
  b_job_number:=0;
  if readifp(<:bsize:>,bmaxsizeday,bmaxsizeday) then
    bmaxsizeday:=bmaxsizeday*1024; <*halfwords*>
  algol list.off;
message  primary input: initialization of globals;
  i:=l_next:=2;
  i:=l_type:=i+2;
  i:=l_procname:=i;
  i:=l_jobname:=i+8;
  i:=l_outname:=i+8;
  i:=l_printer:=i+8;
  i:=l_last:=i+8;

message  tramos trim: claiming basic;
    maxsem:=maxsem+3+maxchildren;
message  readcommand: claiming basic;
    maxcoru:=maxcoru+noofterminals+maxmess;
    maxsem:=maxsem+no_of_terminals;
    maxsemch:=maxsemch+1;
    maxop:=maxop+noofterminals+1;
    maxnettoop:=maxnettoop+8*(noofterminals+1);
    maxprocext:=maxprocext+1;
    maxmessext:=maxmessext+noofterminals;
message  parent message: claiming basic;
    maxcoru:=maxcoru+1;
    maxsemch:=maxsemch+1;
    maxop:=maxop+maxpmess;
    maxnettoop:=maxnettoop+8*maxpmess;
message  batch que: claiming basic;
    maxcoru:=maxcoru+4;
    maxsemch:=maxsemch+2;
    maxop:=maxop+qdes+b_max_jobs+4;
    maxnettoop:=maxnettoop+12*qdes+6*(bmaxjobs+4);
    maxsem:=maxsem+qdes+1;
    maxmessext:=maxmessext+1;
message  primary input: claiming basic;
    maxcoru:=maxcoru+1;
    maxprocext:=maxprocext+1;

  begin

    <* work variables - primarily used during initialization *>
    integer array field simref, semref, coruref, opref;
    integer proccount, corucount, messcount, cmi, cmj;
    integer array zoneia(1:20);

    <* field variables describing the format of basic entities *>
    integer field
      <* chain head *>
      next, prev,
      <* simple semaphore *>
      simvalue, simcoru,
      <* chained semaphore *>
      semop, semcoru,
      <* coroutine *>
      coruop, corutimerchain, corutimer, corupriority, coruident,
      <* operation head *>
      opnext, opsize;


    boolean field
      corutypeset, corutestmask, optype;
    real starttime;
    long corustate;

    <* field variables used as queue identifiers (addresses) *>
    integer array field current, readyqueue, idlequeue, timerqueue;

    <* extensions (message- and process- extensions) *>
    integer array messref, messcode, messop (1:maxmessext);
    integer array procref, proccode, procop (1:maxprocext);

    <* core array used for accessing the core using addresses as field 
       variables (as delivered by the monitor functions)
    -  descriptor array 'd' in which all basic entities are allocated
       (except for extensions) *>
    integer array core (1:1), d (1:(4 <* readyqueue *> +
                                    4 <* idlequeue *> +
                                    4 <* timerqueue *> +
                                    maxcoru * corusize +
                                    maxsem * simsize +
                                    maxsemch * semsize +
                                    maxop * opheadsize +
                                    maxnettoop)/2);



      <*************** initialization procedures ***************>


  
      procedure initchain (chainref);
      value chainref;
      integer array field chainref;
      begin
        integer array field cref;
        cref:= chainref;
        d.cref.next:= d.cref.prev:= cref;
      end;


      <***** nextsem *****

      this procedure allocates and initializes the next simple semaphore in the
      pool of claimed semaphores.
      the procedure returns the identification (the address) of the semaphore to
      be used when calling 'signal', 'wait' and 'inspect'. *>
  
      integer procedure nextsem;
      begin
        nextsem:= simref;
        if simref >= firstsem then initerror(1, true);
        initchain(simref + simcoru);
        d.simref.simvalue:= 0;
        simref:= simref + simsize;
      end;


      <***** nextsemch *****
   
      this procedure allocates and initializes the next simple semaphore in the
      pool of claimed semaphores.
      the procedure returns the identification (the address) of the semaphore to
      be used when calling 'signalch', 'waitch' and 'inspectch'. *>
  
      integer procedure nextsemch;
      begin
        nextsemch:= semref;
        if semref >= firstop-4 then initerror(2, true);
        initchain(semref + semcoru);
        initchain(semref + semop);
        semref:= semref + semsize;
      end;


      <***** nextcoru *****

      this procedure initializes the next coroutine description in the pool of
      claimed coroutine descriptions.
      at initialization is defined the priority (an integer value), an identi-
      fication (an integer value 0..8000) and a test pattern (a boolean). *>
  
      integer procedure nextcoru(ident, priority, testmask);
      value ident, priority, testmask;
      integer ident, priority;
      boolean testmask;
      begin
        corucount:= corucount + 1;
        if corucount > maxcoru then initerror(3, true);
        nextcoru:= corucount;
        initchain(coruref + next);
        initchain(coruref + corutimerchain);
        initchain(coruref + coruop);
        d.coruref.corupriority:= priority;
        d.coruref.coruident:= ident * 1000 + corucount;
        d.coruref.corutypeset:= false;
        d.coruref.corutimer:= 0;
        d.coruref.corutestmask:= testmask;
        linkprio(coruref, readyqueue);
        current:= coruref;
        coruref:= coruref + corusize;
      end;


      <***** nextop *****

      this procedure initializes the next operation in the pool of claimed ope-
      rations (heads and buffers).
      the head is allocated and immediately following the head is allocated 'size'
      halfwords forming the operation buffer.
      the procedure returns an identification of the operation (an address) and
      in case this address is held in a field variable 'op', the buffer area may
      be accessed as:  d.op(1), d.op(2), d.op(3) ...  *>
  
      integer procedure nextop (size);
      value size;
      integer size;
      begin
        nextop:= opref;
        if opref >= optop then initerror(4, true);
        initchain(opref + next);
        d.opref.opsize:= size;
        opref:= opref + size + opheadsize;
      end;


      <***** nextprocext *****

      this procedure initializes the next process extension in the series of
      claimed process extensions.
      the process description address is put into the process extension and the
      state of the extension is initialized to be closed. *>
  
      integer procedure nextprocext (processref);
      value processref;
      integer processref;
      begin
        proccount:= proccount + 1;
        if proccount >= maxprocext then initerror(5, true);
        nextprocext:= proccount;
        procref(proccount):= processref;
        proccode(proccount):= 1 shift 12;
      end;


      <***** initerror *****

      this procedure is activated in case the initialized set of resources does
      not match the claimed set.
      in case more resources are claimed than used, a warning is written,
      in case too few resources are claimed, an error message is written and
      the execution is terminated. *>

      procedure initerror (resource, exceeded);
      value resource, exceeded;
      integer resource; boolean exceeded;
      begin
        write(out, false add 10, 1,
           if exceeded then <:more :> else <:less :>,
           case resource of (
             <:simple semaphores:>,
             <:chained semaphores:>,
             <:coroutines:>,
             <:operations:>, 
             <:process extensions:>),
             <: initialized than claimed:>,
           false add 10, 1);
        if exceeded then goto dump;
      end;


      <***** stackclaim *****

      this procedure is used by a coroutine from its first activation to it
      arrives its first waiting point. the procedure is used to claim an addi-
      tional amount of stack space. this must be done because the maximum
      stack space for a coroutine is set to be the max amount used during its
      very first activation. *>


      procedure stackclaim (size);
      value size; integer size;
      begin
        boolean array stackspace (1:size);
      end;
  
message  tramos trim global variables and procedures;
    algol list.on;
    integer logsem;
    boolean free,stopsystem;
    zone log(128,1,noerror),cat(768,2,stderror),z(128,1,stderror);
    long array basestack(1:25);
    long array field basep,maxbasep;
    integer array con_pda_table(1:no_of_terminals),
       con_desc(1:no_of_terminals*con_desc_size//2),
       chartable(0:255),user_core(1:256*coreblocksize*noofcoreblocks),
       usercatbs(1:6*no_of_bs),ownbs,freebs(1:8*no_of_bs),
       perm_bs_claimed(1:usercatusers+10,1:noofbs,1:4),
       <*+10 to allow some updating of the usercatalog
         while running*>
       includelist(0:lastdevice),
       coretable(1:no_of_core_blocks+1,1:2),
       childtable(1:(maxchildren+1)*20);
    boolean array bs_exist(1:no_of_bs+1);
    
    <*use of childtable
    1:  childpda
    2:  destermpda
    3:  state (1 created, 2 running, 3 stopped, 4 breaked, 5 swopped
    4:  ref to descriptor
    5:  jobname
    6:   -
    7:   -
    8:   -
    9:  batch or online (0=online, 1=batch)
    10: first address
    11: last  address
    12: job number
    13: segment number swop
    14: segment number batch queue
    15: buffer ref finis or break
    16: childno
    17: usercatno
    18: process description in
    20: access semaphore
    19: process description out
    *>
    integer field ct_child_pda, ct_term_pda, ct_state,
                  ct_ref, ct_batch, ct_first, ct_last,
                  ct_jobno, ct_segm_swop, ct_segm_queue,
                  ct_bufref,ct_childno,ct_usercatno,
                  ct_procin,ct_procout,ct_sem;
    integer state_created,state_running,state_stopped,
            state_breaked,state_swopped,state_removed,
            ct_size;
    long array field ct_job_name;
    
    procedure set_base(lower,upper);
    value lower,upper; integer lower,upper;
    begin
    integer res;
    long array name(1:2);
    integer array field lu;
    name(1):=0;
    lu:=0;
    if basep>=maxbasep then  alarm("nl",1,<:base pointer:>) else
    begin
      res:=set_cat_base(name,lower,upper);
      if res>0 then alarm("nl",1,<:base interval:>,res,lower,upper,basep) else
      begin
        basestack.basep.lu(1):=lower;
        basestack.basep.lu(2):=upper;
        basep:=basep+4;
      end set cat base;
    end no stack over flow;
    end set base;
    
    procedure resetbase;
    begin
    integer res;
    long array name(1:2);
    integer array field lu;
    name(1):=0;
    lu:=0;
    if basep=0 then set_base_std else
    begin
      basep:=basep-4;
      res:=set_cat_base(name,basestack.basep.lu(1),basestack.basep.lu(2));
      if res<>0 then alarm("nl",1,<:reset base :>,res,basep);
    end basep>0;
    end reset_base;
    
    procedure set_base_std;
    begin
    setbase(core.ownref.stdbaseref(1),core.ownref.stdbaseref(2));
    end;
    
    procedure set_base_user_cat;
    begin
    setbase(usercatlower,usercatupper);
    end;
    
    procedure set_own_bs(doc,claim,owndoc,ownsegm,ownentry);
    value ownsegm,ownentry; integer ownsegm,ownentry;
    long array doc,owndoc;
    integer array claim;
    if doc(1)<>owndoc(1) or doc(2)<>owndoc(2) then
    begin
    integer i; for i:=1 step 1 until 8 do claim(i):=0;
    end else
    begin
    integer i;
    for i:=2 step 2 until 8 do
    begin
      claim(i-1):=ownentry;
      claim(i  ):=ownsegm;
    end
    end setownbs;
    
    integer procedure find_term(pda);
    value pda; integer pda;
    if pda=0 then findterm:=-1 else
    begin
    integer i,j;
      findterm:=i:=0;
      j:=no_of_terminals+1;
      for i:=i+1 while i<=no_of_terminals and j=no_of_terminals+1 do
         if con_pda_table(i)=pda then j:=findterm:=i;
      cur_con_desc:=(j-1)*con_desc_size;
    end findterm;
    
    integer procedure next_free_term(pda);
    value pda; integer pda;
    if pda=0 then next_free_term:=-1 else
    begin
    integer i,j,k;
    long array field name;
    i:=next_free_term:=0;
    j:=no_of_terminals+1;
    for i:=i+1 while i<=no_of_terminals and j=no_of_terminals+1 do
      if con_pda_table(i)=0 or con_pda_table(i)=pda then
        begin
          j:=nextfreeterm:=i;
          con_pda_table(j):=pda;
          cur_con_desc:=(j-1)*con_desc_size;
          condesc.curcondesc.contermpda:=pda;
          name:=pda+2;
          for k:=1,2 do condesc.curcondesc.condesterm(k):=core.name(k);
          condesc.curcondesc.contermno:=i;
      end found;
    end next free term;
    
    procedure noerror(z,s,b);
    zone z; integer s,b;
    begin
    comment no action;
    end;
    
    procedure writelog(t1,i,t2);
    string t1,t2; integer i;
    begin
      wait(logsem);
      write(log,t1,i,"sp",1,t2,"nl",1);
      setposition(log,0,0);
      signal(logsem);
    end;
    algol list.off;
message  readcommand global variables and procedures;
    algol list.on;
    integer ownpda,tpspda;
    integer messaddress,attline;
    boolean att,verify;
    zone array c_buf(no_of_terminals,17,1,no_error);
    algol copy.tchildpr;
    algol copy.treaduscat;
    algol copy.treadclist;
    
    algol copy.tnextparam;
    
    procedure readcommand(cno);
    value cno; integer cno;
    begin
    integer rem,pda,termno,el;
    integer array field cur;
    boolean stop,waitc;
    integer array field attref;
      stackclaim(850);
      stop:=false;
      repeat
      waitc:=waitch(attline,attref,att or stopsystem,0);
      if (stopsystem and waitc) extract 12 =0 then
      begin
        pda:=d.attref(1);
        termno:=findterm(pda);
        if termno=0 then termno:=nextfreeterm(pda);
        cur:=curcondesc;
       inspect(condesc.cur.conaccess,el);
        wait(condesc.cur.conaccess);
        readcommandlist(c_buf(termno),condesc.curcondesc,false);
        signal(condesc.cur.conaccess);
        signalch(attline,attref,free);
      end else stop:=true;
      until stop;
    writelog(<:readcommand:>,cno,<:stopped:>);
    end readcommand;
    
    procedure receivemess(no);
    value no; integer no;
    begin
    boolean stop;
    integer array M,A(1:8);
    integer array field taddress;
    integer array field bufref,attref,pmessref;
    
    stackclaim(350);
    stop:=false;
    repeat
      cwaitmessage(messaddress,M,bufref,0);
      taddress:=core.bufref(4);
      if taddress<0 then sendanswer(1,bufref,A) else
      if core.taddress(1)=0 then
      begin
        <*parent message*>
        waitch(pmessline,pmessref,free,0);
        d.pmessref(1):=taddress;
        d.pmessref(2):=bufref;
        signalch(pmessline,pmessref,pmess);
        osparentmess:=osparentmess+1;
      end else
      begin
       sendanswer(1,bufref,A);
       waitch(attline,attref,free,0);
       d.attref(1):=taddress;
       signalch(attline,attref,att or (stop and stopsystem));
       oscommunication:=oscommunication+1;
      end terminal;
    until stop;
    writelog(<:receivemess:>,0,<:finis:>);
    end receivemess;
    algol list.off;
message  parent message global variables and procedures;
    algol list.on;
    boolean pmess;
    integer pmessline;
    algol list.on copy.treadjob;
    
    procedure receive_parent_message;
    begin
    integer i,j,res,cbn,op,mode,word,job;
    integer array M,A(1:8);
    integer array field bufref,parentref,child_pda,cur,fi,
            bufd,reg,ct,bref;
    long array field nf;
    integer field interrupt_address;
    long array name,text(1:3);
    boolean pause,batch;
    zone pz(17,1,noerror);
    
    stackclaim(750);
    interruptaddress:=38;
    for i:=1 step 1 until 8 do A(i):=0;
    fi:=0;
    repeat
      waitch(pmessline,parentref,pmess,0);
      bufref:=d.parentref(2);
      child_pda:=core.bufref(4);
      if childpda<0 then send_answer(1,bufref,A) else
      begin
        cbn:=0;
        ct:=-ct_size;
        repeat cbn:=cbn+1;
        ct:=ct+ct_size;
        until cbn>maxchildren or childpda=childtable.ct.ct_childpda;
        if cbn<=maxchildren then wait(childtable.ct.ct_sem);
        if cbn>maxchildren or childtable.ct.ct_childpda<>childpda then
          sendanswer(2,bufref,A) else
        begin
         <*it was a child*>
         op:=core.bufref(5) shift (-12) extract 12;
         mode:=core.bufref(5) extract 12;
         pause:=mode extract 1=1;
         if op mod 2=1 or op>42 then sendanswer(3,bufref,A) else
         if op=0 then sendanswer(1,bufref,A) else
         begin
           nf:=childpda+2;
           for i:=1,2 do name(i):=core.nf(i);
           cur:=childtable.ct.ct_ref; <*console description*>
           batch:=childtable.ct.ct_batch>0;
           if op//2<3 then childtable.ct.ct_bufref:=bufref;
           if batch then
           begin
             open(pz,8,q.cur.condesterm,tw_mask);
             if pause then
             begin
             waitch(bmessline,bref,free,0);
             d.bref(1):=1; <*signal to clock driver*>
             d.bref(2):=-1; <*stop*>
             d.bref(3):=ct;
             signalch(bmessline,bref,cmess);
             end pause;
           end else
           begin
             wait(condesc.cur.conaccess);
             if condesc.cur.concurchildpda<>childpda then
             begin
               for i:=1,2 do condesc.cur.conprocname(i):=name(i);
               condesc.cur.concurchildpda:=childpda;
               condesc.cur.concurchild:=childtable.ct.ct_childno;
             end;
             open(pz,8,condesc.cur.condesterm,tw_mask);
             if pause then res:=stopchild(condesc.cur);
           end;
           write(pz,"nl",1,if pause then <:pause:> else <:message:>,
             "sp",1,name,"sp",1);
          op:=op//2;
          mode:=mode shift (-5);
          text(2):=0;
          bufd:=bufref+10;
          for i:=1 step 1 until 7 do
          begin
            word:=core.bufd(i);
            if mode shift  (i-7)=1 then
              write(pz,word) else
            begin
              text.fi(1):=word; text.fi(2):=0;
              write(pz,text);
              if word=0 then write(pz,"sp",1);
            end text;
           end write buffer content;
           if op<3 then childtable.ct.ct_bufref:=bufref;
           case op of
           begin
             begin <*finis*>
             if batch then
             begin
               waitch(bmessline,bref,free,0);
               d.bref(1):=1; <*clock*>
               d.bref(2):=-5; <*finis*>
               d.bref(3):=ct;
               signalch(bmessline,bref,cmess);
             end batch else
             begin
               res:=stopchild(condesc.cur);
               if res<>0 then disable
               write(pz,<:**stop int :>,condesc.cur.conprocname,res);
               res:=removechild(condesc.cur,pz);
               if res<>0 then write(pz,<:**remove error :>,name,res,
               childtable.ct.ct_state);
             end online;
             end finis;
             begin <*break*>
               if core.childpda(40+7)>0 and core.childpda(40+7)<18 then
               write(pz,core.childpda(40+7),<: ic :>,core.childpda(40+6),
                 <: w0 :>,core.childpda(41),
                 <: w1 :>,core.childpda(42),
                 <: w2 :>,core.childpda(43),
                 <: w3 :>,core.childpda(44));
                if batch then
                begin
                  waitch(bmessline,bref,free,0);
                  d.bref(1):=1;
                  d.bref(2):=-4;
                  d.bref(3):=ct;
                   signalch(bmessline,bref,cmess);
                end else
                begin
                  res:=stopchild(condesc.cur);
                  childtable.ct.ct_state:=state_breaked;
                end;
             end break;
             begin <*hard error*>
             end hard error;
             begin <*account*>
             end account;
             begin <*replace*>
             end replace;
             begin <*new job*>
               read_job_file(ct,bufref,A,pz);
             end newjob;
             begin <*mount tape*>
             end mount;
             begin <*print*>
             end print;
             begin <*mount ring*>
             end ring;
             begin <*suspend tape*>
             end suspend;
             begin <*release tape*>
             end release;
             begin <*load*>
             end load;
             begin <*change paper*>
             end change;
             begin <*timer*>
             end timer;
             begin <*convert*>
             end convert;
             begin <*mount special*>
             end mount special;
             begin <*mount kit*>
             end kit;
             begin <*lock*>
             lock:=true;
             end lock;
             begin <*open*>
             lock:=false;
             end open;
             begin <*remove*>
             end remove;
             begin <*swop and wait*>
             end swop and wait;
          end case;
          if op>=3 then sendanswer(1,bufref,A);
           if -,batch then signal(condesc.cur.conaccess);
           close(pz,true);
         end legal operation;
        end it was a child;
      if cbn<=maxchildren then signal(childtable.ct.ctsem);
      end  childpda>0;
    signalch(pmessline,parentref,free);
    until false;
    end parent message;
    algol list.off;
message  error message: global variables and procedures,;
    algol list.on;
    long array error_texts(1:sizeerrormessage);
    long array field error_ready,error_syntax,error_not_allowed,
         error_no_core,
         error_no_buffers,error_no_areas,error_no_internals,
         error_process_unknown,error_process_exists,
         error_catalog_error,error_area_unknown,
         error_area_reserved,error_program_too_big,
         error_area_error,error_device_unknown,
         error_device_reserved,error_not_implemented,
         error_bs_claims_exceeded,error_bs_device_unknown,
         error_name_unknown,error_no_entries_in_maincat,
         error_illegal_priority,error_program_name_unknown,
         error_name_conflict,
         error_result_impossible,error_job_file_unknown,
         error_job_number_not_found;
    
    procedure init_error_text(e);
    long array e;
    begin
    integer array field p,max_error;
    integer i,j;
    integer array f(1:sizeerrormessage);
    array field t;
    long array field lf;
    <* an error record lookup like this:
       +0 param(1)
       +2 param(2)
       +4 param(3)
       +6 error text
    
    where the value of param indicates:
     param(i)=<=0 dummy
              1 integer
              >1 reference to a text
    *>
    
    for i:=1 step 1 until size_error_message do e(i):=0;
    
    j:=1;
    i:=t:=f(j):=error_ready:=6;                   j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:ready:>);
    i:=t:=f(j):=error_syntax:=12+i;              j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:***syntax:>);
    i:=t:=f(j):=error_not_allowed:=16+i;         j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:not allowed:>);
    i:=t:=f(j):=error_no_core:=16+i;             j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:no core:>);
    i:=t:=f(j):=error_no_buffers:=16+i;          j:=j+1; p:=i-6; 
      e.p(1):=1;e.p(2):=e.p(3):=-1; movestring(e.t,1,<:no buffers:>);
    i:=t:=f(j):=error_no_areas:=16+i;            j:=j+1; p:=i-6;
      e.p(1):=-1;e.p(2):=1;e.p(3):=-1; movestring(e.t,1,<:no areas:>);
    i:=t:=f(j):=error_no_internals:=16+i;        j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=-1;e.p(3):=1; movestring(e.t,1,<:no internals:>);
    i:=t:=f(j):=error_process_unknown:=16+i;      j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:process unknown:>);
    i:=t:=f(j):=error_process_exists:=20+i;       j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:process exists:>);
    i:=t:=f(j):=error_catalog_error:=20+i;        j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:catalog error:>);
    i:=t:=f(j):=error_area_unknown:=20+i;         j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:area unknown:>);
    i:=t:=f(j):=error_area_reserved:=16+i;        j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:area reserved:>);
    i:=t:=f(j):=error_program_too_big:=20+i;      j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:program too big:>);
    i:=t:=f(j):=error_area_error:=20+i;           j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:area error:>);
    i:=t:=f(j):=error_device_unknown:=16+i;       j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:device unknown:>);
    i:=t:=f(j):=error_device_reserved:=20+i;      j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:device reserved:>);
    i:=t:=f(j):=error_not_implemented:=20+i;      j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:not implemented:>);
    i:=t:=f(j):=error_bs_claims_exceeded:=20+i;   j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:bs claims exceded:>);
    i:=t:=f(j):=error_bs_device_unknown:=20+i;    j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:bs device unknown:>);
    i:=t:=f(j):=error_name_unknown:=20+i;         j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:name unknown:>);
    i:=t:=f(j):=error_no_entries_in_maincat:=20+i;j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:no entries in main catalog:>);
    i:=t:=f(j):=error_illegal_priority:=32+i;     j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:illegal priority:>);
    i:=t:=f(j):=error_program_name_unknown:=20+i; j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:progran name unknown:>);
    i:=t:=f(j):=error_name_conflict:=i+28;        j:=j+1; p:=i-6;
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:name conflict:>);
    i:=t:=f(j):=error_result_impossible:=i+24;    j:=j+1; p:=i-6; 
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:result impossible:>);
    i:=t:=f(j):=error_job_file_unknown:=i+20;     j:=j+1; p:=i-6;
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:job file unknown:>);
    i:=t:=f(j):=error_job_number_not_found:=i+20; j:=j+1; p:=i-6;
      e.p(1):=e.p(2):=e.p(3):=-1; movestring(e.t,1,<:job number not found:>);
    end init error;
    
    procedure writeerror(z,error,auxerror);
    long array field error;
    zone z;
    integer array auxerror;
    begin
    long array field lf;
    integer array field p;
    p:=error-6;
    write(z,errortexts.error);
    if error=error_bs_claims_exceeded then
    begin
      for i:=1 step 1 until no_of_bs do
      begin
      if auxerror(i)>0 then
      begin
        lf:=i*12-12;
        write(z,"nl",1,"sp",2,true,7,usercatbs.lf);
      end;
      end for;
    end error=bsclaim else
    begin
    for i:=1,2,3 do
    begin
    if errortexts.p(i)>0 then
    begin
      if errortexts.p(i)=1 then write(z,auxerror(i)) else
      begin
        lf:=errortexts.p(i);
        write(z,"sp",1,auxerror.lf);
      end text;
    end param;
    end for;
    end error<>bs;
    end write error;
    algol list.off;
message  batch queue global variables and procedures;
    algol list.on;
    integer array q(1:qdes*qdescsize//2);
    integer array b_segm_table(1:b_maxchildren,1:2);
    integer array job_table(1:b_maxjobs,1:13);
    <* 1: segment number
       2: state (0: free, 1: enrolled, 2: running, 3: removed)
       3: unique job number
       4: current job priority
       5: run time
       6: rest time
       7: childno
       8: termpda
       9: jobprio
      10: projno
      11: cpu time
      12: sequence number
      13: job mask (0=normal, 1=released, 2=evening)
    *>
    zone qz,q_in(128,1,noerror);
    real timebase;
    boolean cmess,qmess,bmess,jobtimermess,newqueue,day;
    integer qmessline,bmessline,qsem;
    
    algol list.on copy.treadsub;
    
    procedure init_batch_queue;
    begin
    if -,newqueue then
    begin
    integer array field bref;
    integer segm;
      get_job_segm_0(false);
      for segm:=1 step 1 until b_max_jobs do
      begin
       if get_job_segm(q,segm,false) then
       begin
         <*old job found*>
         if q.q_job_state=staterunning then
         begin
           disable write(out,"nl",1,true,12,q.qjobname,q.qjobno,<: lost:>);
           q.q_job_state:=q.qjobno:=0;
           get_jobsegm(q,segm,true);
         end else
         begin
         b_cur_job:=b_cur_job+1;
         jobtable(segm,1):=segm;
         jobtable(segm,2):=q.q_job_state;
         jobtable(segm,3):=q.q_job_no;
         jobtable(segm,4):=q.q_maxtime;
         jobtable(segm,5):=q.qmaxtime;
         jobtable(segm,6):=q.qmaxtime;
         jobtable(segm,7):=0;
         jobtable(segm,8):=q.contermpda;
         jobtable(segm,9):=q.qmaxtime;
         jobtable(segm,10):=q.conprojno shift (-8) extract 16;
         jobtable(segm,11):=0;
         jobtable(segm,12):=0;
         jobtable(segm,13):=q.q_jobmask;
         if bjobnumber<q.fi.q_job_no then b_jobnumber:=
            q.fi.q_job_no;
          waitch(bmessline,bref,free,0);
          d.bref(1):=2;
          d.bref(2):=segm;
          signalch(bmessline,bref,bmess);
       end initjob;
       end old job;
      end scan segments;
    end -,newqueue;
    disable write(out,"nl",2,<:batch included :>,if newqueue then
         <:new:> else <:old:>,<: queue :>);
    disable writetime(out,b_upd_time);;
    disable write(out,<< dddddd>,
              "nl",1,<:current max time:>,bmaxtime,
                if day then <: day:> else <: night:>,
              "nl",1,<:max time day    :>,b_max_time_day//60,<: min:>,
              b_max_time_day mod 60,<: sec:>,
              "nl",1,<:max size day    :>,b_max_size_day//1024,<: k:>,
              "nl",1,<:max time night  :>,b_max_time_night//60//60,<: h:>,
              "nl",1,<:max size night  :>,b_max_size_night//1024,<: k:>,
              "nl",1,<:day to night    :>,<<_____dd.dd>,b_day_to_night//100,
              "nl",1,<:night to day    :>,b_night_to_day//100,
              "nl",1,<:parallel jobs   :>,<< dddddd>,b_max_children,
              "nl",1,<:jobs in queue   :>,b_cur_job,
              "nl",1,<:max job number  :>,b_job_number);
    outendcur(10);
    end initbatch;
    
    procedure batch_queue;
    begin
    integer i,j,res,cbn,op,mode,word,jobno,jobstate;
    long array field nf;
    integer array field qref,qcur,concur,bref,ct;
    long array name,text(1:3);
    zone pz(17,1,noerror);
    
    stackclaim(800);
    fi:=0;
    repeat
      waitch(qmessline,qref,qmess,0);
      concur:=d.qref(2);
      for i:=1,2 do name(i):=condesc.concur.condesterm(i);
      open(pz,8,name,1 shift 9);
      open(qin,8,name,1 shift 9);
      case d.qref(1) of
      begin
        begin
          <*submit*>
          qcur:=0;
          j:=condescsize//2;
          for i:=2 step 1 until j do
            q.qcur(i):=condesc.concur(i);
          j:=j+1;
          for i:=qdescsize//2 step -1 until j do
              q.qcur(i):=0;
          res:=0;
          if d.qref.d_job_name(1)<>0 then
          begin
            if readusercat(d.qref.d_jobname,q.qcur,testop(7),pz) then
            begin
              stdclaim(q.qcur);
              stdbs(q.qcur,pz);
            end else
            begin
              res:=4;
              writeerror(pz,errornameunknown,q.qcur);
            end;
          end jobname;
          if res=0 then read_submit(qin,pz,q.qcur,false);
        end submit;
        begin
        integer t;
          <*queue*>
          t:=condesc.concur.contermpda;
          list_job_table(pz,if t=sysconpda then 0 else t);
        end queue;
        begin
        integer i,jte,rest;
        boolean first;
          <*what*>
           first:=true;
           for i:=1 step 1 until maxchildren do
           begin
            ct:=(i-1)*ctsize;
            if childtable.ct.ct_batch>0 then
            begin
              if first then
              begin
                 write(pz,"nl"1,if day then <:day :> else <:night :>);
                 writecurtime(pz);
                 write(pz,"nl",1,<:user________:>,<:state____:>,
                   <:jobno__:>,<:time left:>);
                first:=false;
              end;
              jte:=childtable.ct.ct_segm_queue;
              rest:=jobtable(jte,6);
              write(pz,"nl",1,true,12,childtable.ct.ct_jobname,
                true,9,case childtable.ct.ctstate of
                 (<:created:>,<:running:>,<:stopped:>,<:breaked:>,
                  <:swopped:>),<< dddd>,childtable.ct.ctjobno);
              if rest>0 then write(pz,<< dd >,rest//3600,rest mod 3600 //60,
                   rest mod 60);
             end batch job;
           end childtable scan;
        end what;
        begin
          <*search*>
           i:=0;
           jobno:=d.qref(3);
           repeat i:=i+1;
           until i=bmaxjobs or jobno=jobtable(i,3);
           if jobno=jobtable(i,3) then
           begin
             write(pz,"nl",1,<:job number:>,jobno,<: :>,
               case jobtable(jobno,2)+1 of (
              <:impossible:>,<:enrolled:>,<:running:>,<:removed:>));
            end else writeerror(pz,errorjobnumbernotfound,q.qcur);
        end search;
        begin
          <*kill*>
          i:=0;
          jobno:=d.qref(3);
          repeat i:=i+1;
          until i=bmaxjobs or jobno=jobtable(i,3);
          if jobno=jobtable(i,3) then
          begin
            jobstate:=jobtable(i,2);
            b_cur_job:=b_cur_job-1;
            if jobstate=2 then
            begin
              waitch(bmessline,bref,free,0);
              d.bref(1):=1; <*clock*>
              d.bref(2):=-6; <* kill running job*>
              d.bref(3):=(jobtable(i,7)-1)*ctsize;
              signalch(bmessline,bref,cmess);
            end job running else
             for j:=2 step 1 until 15 do jobtable(i,j):=0;
          qcur:=0;
          q.qcur.qjobno:=0;
          get_job_segm(q.qcur,i,true);
          end else writeerror(pz,errorjobnumbernotfound,q.qcur);
        end kill;
        begin
          <*release*>
           i:=0;
           jobno:=d.qref(3);
           repeat i:=i+1;
           until i=bmaxjobs or jobno=jobtable(i,3);
           if jobno=jobtable(i,3) then
           begin
             <*job no found*>
             jobtable(i,13):=1; <*released*>
           end job found else
           writeerror(pz,errorjobnumbernotfound,q.qcur);
        end release;
        begin
          <*set prio*>
           i:=0;
           jobno:=d.qref(3);
           repeat i:=i+1;
           until i=bmaxjobs or jobno=jobtable(i,3);
           if jobno=jobtable(i,3) then
           begin
              jobtable(i,4):=0;
           end else writeerror(pz,errorjobnumbernotfound,q.qcur);
        end setprio;
      end case;
      close(pz,true);
      close(q_in,true);
    signalch(qmessline,qref,free);
    until false;
    end batch queue;
    
    procedure b_timer;
    begin
    integer array field bref;
    real r;
    stackclaim(250);
    repeat
      waitch(bmessline,bref,free,0);
      delay(b_time_slice);
      systime(5,0,r);
      d.bref(1):=1;
      d.bref(2):=r;
      signalch(bmessline,bref,cmess);
    until false;
    end b_timer;
    
    procedure run_job_timer;
    begin
    integer array field bref;
      stackclaim(150);
      repeat
      waitch(bmessline,bref,jobtimermess,0);
      d.bref(1):=2;
      d.bref(2):=-1;
      delay(b_time_slice);
      signalch(bmessline,bref,bmess);
      until false;
    end runjobtimer;
    algol list.on copy.trunbatch;
    
    procedure write_b_des(d,z);
    integer array d;
    zone z;
    begin
      writeentry(d,z,true);
      write(z,"nl",1,<:job number   :>,d.qjobno,
              "nl",1,<:job state    :>,d.qjobstate,
              "nl",1,<:job seq      :>,d.qjobseq,
              "nl",1,<:max time     :>,d.qmaxtime,
              "nl",1,<:start wanted :>,d.qstarttime,
              "nl",1,<:job file name:>,d.qjobname,
              "nl",1,<:printer      :>,d.qprinter);
    end writebdes;
    
    
    algol list.off;
message  primary input global variables and procedures;
    algol list.on;
    integer priminproc,primpda;
    long array primin(1:3);
    integer array line_buf(1:bmaxchildren*(l_last//2));
    
    procedure receive_input_message;
    begin
    integer i,j,res,cbn,op,mode,next,type,curline,
      hwreq;
    integer array M,A(1:8);
    integer array field bufref,inputref,child_pda,cur,fi,
            bufd,reg,ct;
    long array field nf,lref,address;
    array field f;
    integer array lrefs(1:8);
    long array name,text(1:3),line(1:60);
    zone mon(17,1,noerror);
    
    stackclaim(950);
    open(mon,8,monitorconsole,0);
    f:=0;
    address:=firstaddr(line);
    for i:=1 step 1 until 60 do line(i):=0;
    lref:=lrefs(1):=0;
    movestring(line.lref.f,1,<:mode list.yes<10>:>);
    lref:=lrefs(2):=lrefs(1)+28;
    movestring(line.lref.f,3,<: = set 50<10>:>);
    lref:=lrefs(3):=lrefs(2)+28;
    movestring(line.lref.f,1,<:scope day :>);
    lref:=lref+8+8;
    line.lref(1):=long <:<10>:>;
    lref:=lrefs(4):=lrefs(3)+28;
    movestring(line.lref.f,1,<:o :>);
    lref:=lref+4+8;
    line.lref(1):=long <:<10>:>;
    lref:=lrefs(5):=lrefs(4)+28;
    movestring(line.lref.f,1,<:i :>);
    lref:=lref+4+8;
    line.lref(1):=long <:<10>:>;
    lref:=lrefs(6):=lrefs(5)+28;
    movestring(line.lref.f,1,<:o c<10>:>);
    lref:=lrefs(7):=lrefs(6)+28;
    movestring(line.lref.f,3,<:=convert :>);
    lref:=lref+8+8+8;
    line.lref(1):=long <:<10>:>;
    lref:=lrefs(8):=lrefs(7)+28;
    movestring(line.lref.f,1,<:finis<10>:>);
    for i:=1 step 1 until 8 do A(i):=0;
    fi:=0;
    repeat
      c_wait_message(priminproc,M,bufref,0);
      child_pda:=core.bufref(4);
      if childpda<0 then send_answer(1,bufref,A) else
      begin
        cbn:=0;
        ct:=-ct_size;
        repeat cbn:=cbn+1;
        ct:=ct+ct_size;
        until cbn>maxchildren or childpda=childtable.ct.ct_childpda;
        if cbn>maxchildren then sendanswer(2,bufref,A) else
        if childtable.ct.ct_batch=0 then send_answer(2,bufref,A) else
        begin
         <*it was a child*>
         op:=core.bufref(5) shift (-12) extract 12;
         mode:=core.bufref(5) extract 12;
         if op=0 then sendanswer(1,bufref,A) else
         if op<>3 then send_answer(3,bufref,A) else
         begin
           nf:=childpda+2;
           hwreq:=core.bufref(7)-core.bufref(6)+2;
           for i:=1,2 do name(i):=core.nf(i);
           cur:=childtable.ct.ct_ref; <*console description*>
           bufd:=bufref+10;
           lref:=q.cur.q_lref;
           next:=line_buf.lref.l_next;
           type:=line_buf.lref.l_type;
           curline:=nf:=lrefs(next);
           if hwreq<28 then 
           begin
             for i:=1,2,3 do A(i):=0;
             sendanswer(1,bufref,A);
           end else
           begin
           case next of
           begin
             begin <*mode list.yes*>
                next:=if type=0 then 5 else 2;
             end 1;
             begin  <* <outname> = set 50*>
                for i:=1,2 do line.nf(i):=linebuf.lref.l_outname(i);
                next:=3;
             end 2;
             begin <* scope day <outname> *>
                nf:=nf+8;
                for i:=1,2 do line.nf(i):=linebuf.lref.l_outname(i);
                next:=4;
             end 3;
             begin <*o <outname> *>
                nf:=nf+2;
                for i:=1,2 do line.nf(i):=linebuf.lref.l_outname(i);
                next:=5;
             end 4;
             begin <*i <jobname> *>
                nf:=nf+2;
                for i:=1,2 do line.nf(i):=linebuf.lref.l_jobname(i);
                next:=if type=0 then 8 else 6;
             end 5;
             begin <* o c*>
                next:=7;
             end 6;
             begin <* <printer> = convert <outname>*>
                 for i:=1,2 do line.nf(i):=linebuf.lref.l_printer(i);
                 nf:=nf+8+8;
                 for i:=1,2 do line.nf(i):=linebuf.lref.l_outname(i);
                 next:=8;
             end 7;
             begin <*finis*>
                 next:=8;
             end 8;
          end case next;
           i:=address+curline;
           res:=copy(bufref,i,i+28-2);
           if res<>0 or monw1<28 then A(1):=A(2):=A(3):=0 else
           begin
             A(1):=0; A(2):=monw1; A(3):=monw3;
             linebuf.lref.l_next:=next;
           end;
           sendanswer(1,bufref,A);
           end halwords requested >=28;
         end legal operation;
        end it was a child;
      end  childpda>0;
    until false;
    end input message;
    algol list.off;
  

    <*************** coroutine monitor procedures ***************>


    <***** delay *****

    this procedure links the calling coroutine into the timerqueue and sets
    the timeout value to 'timeout'. *>


    procedure delay (timeout);
    value timeout;
    integer timeout;
    begin
      link(current, idlequeue);
      link(current + corutimerchain, timerqueue);
      d.current.corutimer:= timeout;


      passivate;
      d.current.corutimer:= 0;
    end;


    <***** pass *****

    this procedure moves the calling coroutine from the head of the ready 
    queue down below all coroutines of lower or equal priority. *>
  
  
    procedure pass;
    begin
      linkprio(current, readyqueue);


      passivate;
    end;


    <***** signal ****

    this procedure increases the value af 'semaphore' by 1.
    in case some coroutine is already waiting, it is linked into the ready 
    queue for activation. the calling coroutine continues execution. *>
  

    procedure signal (semaphore);
    value semaphore;
    integer semaphore;
    begin
      integer array field sem;
      sem:= semaphore;
      if d.sem.simvalue < 0 then linkprio(d.sem.simcoru, readyqueue);
      d.sem.simvalue:= d.sem.simvalue + 1;


    end;


    <***** wait *****

    this procedure decreases the value of 'semaphore' by 1.
    in case the value of the semaphore is negative after the decrease, the
    calling coroutine is linked into the semaphore queue waiting for a
    coroutine to signal this semaphore. *>
  
  
    procedure wait (semaphore);
    value semaphore;
    integer semaphore;
    begin
      integer array field sem;
      sem:= semaphore;
      d.sem.simvalue:= d.sem.simvalue - 1;


      linkprio(current, if d.sem.simvalue < 0 then sem+simcoru else readyqueue);
      passivate;
    end;


    <***** inspect ****

    this procedure inspects the value of the semaphore and returns it in
    'elements'.
    the semaphore is left unchanged. *>


    procedure inspect (semaphore, elements);
    value semaphore;
    integer semaphore, elements;
    begin
      integer array field sem;
      sem:= semaphore;
      elements:= d.sem.simvalue;


    end;


    <***** signalch *****

    this procedure delivers an operation at 'semaphore'.
    in case another coroutine is already waiting for an operation of the
    kind 'operationtype' this coroutine will get the operation and it will
    be put into the ready queue for activation.
    in case no coroutine is waiting for the actial kind of operation it is
    linked into the semaphore queue. 
    the calling coroutine continues execution. *>
  
  
    procedure signalch (semaphore, operation, operationtype);
    value semaphore, operation, operationtype;
    integer semaphore, operation;
    boolean operationtype;
    begin
      integer array field firstcoru, currcoru, op;
      op:= operation;
      d.op.optype:= operationtype;
      firstcoru:= semaphore + semcoru;
      currcoru:= d.firstcoru.next;
      while currcoru <> firstcoru do
      begin
        if (d.currcoru.corutypeset and operationtype) extract 12 <> 0 then
        begin
          link(operation, 0);
          d.currcoru.coruop:= operation;
          linkprio(currcoru, readyqueue);
          link(currcoru + corutimerchain, idlequeue);
          goto exit;
        end else currcoru:= d.currcoru.next;
      end;
      link(op, semaphore + semop);
  exit:


    end;


    <***** waitch *****

    this procedure fetches an operation from a semaphore.
    in case an operation matching 'operationtypeset' is already waiting at
    'semaphore' it is handed over to the calling coroutine.
    in case no matching operation is waiting, the calling coroutine is
    linked to the semaphore.
    in any case the calling coroutine will be stopped and all corouti-
    nes are rescheduled. *>
  
  
    boolean procedure waitch (semaphore, operation, operationtypeset, timeout);
    value semaphore, operationtypeset, timeout;
    integer semaphore, operation, timeout;
    boolean operationtypeset;
    begin
      integer array field firstop, currop;
waitch:=false;
      firstop:= semaphore + semop;
      currop:= d.firstop.next;


      while currop <> firstop do
      begin
        if (d.currop.optype and operationtypeset) extract 12 <> 0 then
        begin
      waitch:=d.currop.optype;
          link(currop, 0);
          d.current.coruop:= currop;
          operation:= currop;
          linkprio(current, readyqueue);
          passivate;
          goto exit;
        end else currop:= d.currop.next;
      end;
      linkprio(current, semaphore + semcoru);
      if timeout > 0 then
      begin
        link(current + corutimerchain, timerqueue);
        d.current.corutimer:= timeout;
      end else d.current.corutimer:= 0;
      d.current.corutypeset:= operationtypeset;
      passivate;
      if d.current.corutimer < 0 then operation:= 0
                                 else operation:= d.current.coruop;
      d.current.corutimer:= 0;
      currop:= operation;
      d.current.coruop:= currop;
      link(current+corutimerchain, idlequeue);
  exit:


    end;


    <***** inspectch *****

    this procedure inspects the queue of operations waiting at 'semaphore'.
    the number of matching operations are counted and delivered in 'elements'.
    the semaphore is left unchanged. *>
  
  
    procedure inspectch (semaphore, operationtypeset, elements);
    value semaphore, operationtypeset;
    integer semaphore, elements;
    boolean operationtypeset;
    begin
      integer array field firstop, currop;
      integer counter;
      counter:= 0;
      firstop:= semaphore + semop;
      currop:= d.firstop.next;
      while currop <> firstop do
      begin
        if (operationtypeset and d.currop.optype) extract 12 <> 0 then
          counter:= counter + 1;
        currop:= d.currop.next;
      end;
      elements:= counter;


    end;


    <***** csendmessage *****

    this procedure sends the message in 'mess' to the process defined by the name
    in 'receiver', and returns an identification of the message extension used
    for sending the message (this identification is to be used for calling 'cwait-
    answer' or 'cregretmessage'. *>
  
  
    procedure csendmessage (receiver, mess, messextension);
    real array receiver;
    integer array mess;
    integer messextension;
    begin
      integer bufref, messext;
      messref(maxmessext):= 0;
      messext:= 1;
      while messref(messext) <> 0 do messext:= messext + 1;
      if messext = maxmessext then <* no resources *> messext:= 0 else
      begin
        messcode(messext):= 1 shift 12 add 2;
        mon(16) send message :(0, mess, 0, receiver);
        messref(messext):= monw2;
        if monw2 > 0 then messextension:= messext else messextension:= 0;
      end;


    end;


    <***** cwaitanswer *****

    this procedure asks the coroutine monitor to get an answer to the message
    corresponding to 'messextension'. in case the answer has already arrived
    it stays in the eventqueue until 'cwaitanswer' is called.
    in case 'timeout' is positive, the coroutine is linked into the timer
    queue, and in case the answer does not arrive within 'timout' seconds the
    coroutine is restarted with result = 0. *>
  
  
    procedure cwaitanswer (messextension, answer, result, timeout);
    value messextension, timeout;
    integer messextension, result, timeout;
    integer array answer;
    begin
      integer messext;
      messext:= messextension;
      messcode(messext):= messcode(messext) extract 12;
      link(current, idlequeue);
      messop(messext):= current;
      if timeout > 0 then
      begin
        link(current + corutimerchain, timerqueue);
        d.current.corutimer:= timeout;
      end else d.current.corutimer:= 0;


      passivate;
      if d.current.corutimer < 0 then result:= 0 else
      begin
        mon(18) wait answer :(0, answer, messref(messextension), 0);
        result:= monw0;
        baseevent:= 0;
        messref(messextension):= 0;
      end;
      d.current.corutimer:= 0;
      link(current+corutimerchain, idlequeue);
    end;


    <***** cwaitmessage *****

    this procedure asks the coroutine monitor to give it a message, when some-
    one arrives. in case a message has arrived already it stays at the event queue
    until 'cwaitmessage' is called.
    in case 'timeout' is positive, the coroutine is linked into the timer queue,
    if no message arrives within 'timeout' seconds, the coroutine is restarted
    with messbufferref = 0. *>
  
  
    procedure cwaitmessage (processextension, mess, messbufferref, timeout);
    value timeout, processextension;
    integer processextension, messbufferref, timeout;
    integer array mess;
    begin
      integer i;
      integer array field messbuf;
      proccode(processextension):= 2;
      procop(processextension):= current;
      link(current, idlequeue);
      if timeout > 0 then
      begin
        link(current + corutimerchain, timerqueue);
        d.current.corutimer:= timeout;
      end else d.current.corutimer:= 0;


      passivate;
      if d.current.corutimer < 0 then messbufferref:= 0 else
      begin
        messbuf:= procop(processextension);
        for i:=1 step 1 until 8 do mess(i):= core.messbuf(4+i);
        proccode(procext):= 1 shift 12;
        messbufferref:= messbuf;
        baseevent:= 0;
      end;
      d.current.corutimer:= 0;
      link(current+corutimerchain, idlequeue);
    end;


    <***** cregretmessage *****

    this procedure regrets the message corresponding to messageexten-
    sion, to release message buffer and message extension.
    i/o messages are not regretable. *>

  
  
    procedure cregretmessage (messageextension);
    value messageextension;
    integer messageextension;
    begin
      integer array field messbuf;
      messbuf:= messref(messageextension);
      mon(82) regret message :(0, 0, messbuf, 0);
      messref(messageextension):= 0;


    end;


    <***** semsendmessage *****

    this procedure sends the message 'mess' to 'receiver' and at the same time it
    defines a 'signalch(semaphore, operation, operationtype)' to be performed
    by the monitor, when the answer arrives.
    in case there are too few resources to send the message, the operation is
    returned immediately with the result field set to zero. *>
  
  
    procedure semsendmessage (receiver, mess, semaphore, operation, operationtype);
    value semaphore, operation, operationtype;
    real array receiver;
    integer array mess;
    integer semaphore, operation;
    boolean operationtype;
    begin
      integer array field op;
      integer messext;
      op:= operation;
      messref(maxmessext):= 0;
      messext:= 1;
      while messref(messext) <> 0 do messext:= messext + 1;
      if messext < maxmessext then
      begin
        messop(messext):= op;
        messcode(messext):=1;
        d.op(1):= semaphore;
        d.op.optype:= operationtype;
        mon(16) send message :(0, mess, 0, receiver);
        messref(messext):= monw2;
      end;


      if messext = maxmessext or messref(messext) = 0 <* no resources *> then
      begin   <* return the operation immediately with result = 0 *>
        d.op(9):= 0;
        signalch(semaphore, op, operationtype);
      end;
    end;


    <***** semwaitmessage *****

    this procedure defines a 'signalch(semaphore, operation, operationtype)' to
    be performed by the coroutine monitor when a message arrives to the process
    corresponding to 'processextension'. *>
  
  
    procedure semwaitmessage (processextension, semaphore, operation, operationtype);
    value processextension, semaphore, operation, operationtype;
    integer processextension, semaphore, operation;
    boolean operationtype;
    begin
      integer array field op;
      op:= operation;
      procop(processextension):= operation;
      d.op(1):= semaphore;
      d.op.optype:= operationtype;
      proccode(processextension):= 1;


    end;


    <***** semregretmessage *****

    this procedure regrets a message sent by semsendmessage.
    the message is identified by the operation in which the answer should be
    returned.
    the procedure sets the result field of the operation to zero, and then
    returns it by performing a signalch. *>
  
  
    procedure semregretmessage (operation);
    value operation;
    integer operation;
    begin
      integer i, j;
      integer array field op, sem;
      op:= operation;
      i:= 1;
      while i < maxmessext do
      begin
        if messref(i) > 0 and (messcode(i) = 1 and messop(i) = op) then
        begin
          mon(82) regret message :(0, 0, messref(i), 0);
          messref(i):= 0;
          sem:= d.op(1);
          for j:=1 step 1 until 9 do d.op(j):= 0;
          signalch(sem, op, d.op.optype);
          i:= maxmessext;
        end;
        i:= i + 1;
      end;


    end;


    <***** link *****

    this procedure links an object (allocated in the descriptor array 'd') into
    a queue of alements (allocated in the descriptor array 'd'). the queues
    are all double chained, and the chainhead is of the same format as the chain
    fields of the objects.
    the procedure links the object immediately after the head. *>
  
  
    procedure link (object, chainhead);
    value object, chainhead;
    integer object, chainhead;
    begin
      integer array field prevelement, nextelement, chead, obj;
      obj:= object;
      chead:= chainhead;
      prevelement:= d.obj.prev;
      nextelement:= d.obj.next;
      d.prevelement.next:= nextelement;
      d.nextelement.prev:= prevelement;
      if chead > 0 then <* link into queue *>
      begin
        prevelement:= d.chead.prev;
        d.obj.prev:= prevelement;
        d.prevelement.next:= obj;
        d.obj.next:= chead;
        d.chead.prev:= obj;
      end else
      begin  <* link onto itself *>
        d.obj.prev:= obj;
        d.obj.next:= obj;
      end;
    end;


    <***** linkprio *****

    this procedure is used to link coroutines into queues corresponding to
    the priorities of the actual coroutine and the queue elements.
    the object is linked immediately before the first coroutine of lower prio-
    rity. *>
  
  
    procedure linkprio (object, chainhead);
    value object, chainhead;
    integer object, chainhead;
    begin
      integer array field currelement, chead, obj;
      obj:= object;
      chead:= chainhead;
      currelement:= d.chead.next;
      while currelement <> chead
            and d.currelement.corupriority <= d.obj.corupriority 
              do currelement:= d.currelement.next;
      link(obj, currelement);
    end;


    activity(maxcoru);

    goto initialization;



    <*************** event handling ***************>


  
  takeexternal:
    currevent:= baseevent;
    eventqueueempty:= false;
    repeat
      current:= 0;
      prevevent:= currevent;
      mon(66) test event :(0, 0, currevent, 0);
      currevent:= monw2;
      if monw0 < 0 <* no event *> then goto takeinternal;
      if monw0 = 1 and monw1 > 0 then cmi:= monw1 else
      cmi:= - monw0;

      if cmi > 0 then
        begin <* answer to activity zone *>
          current:= firstcoru + (cmi - 1) * corusize;
          linkprio(current, readyqueue);
          baseevent:= 0;
        end else
  
      if cmi = 0 then
        begin <* message arrived *>
          receiver:= core.currevent(3);
          if receiver < 0 then receiver:= - receiver;
          procref(maxprocext):= receiver;
          procext:= 1;
          while procref(procext) <> receiver do procext:= procext + 1;
          if procext = maxprocext then
          begin <* receiver unknown *>
            <* leave the message unchanged *>
          end else
          if proccode(procext) shift (-12) = 0 then
          begin  <* the receiver is ready for accepting messages *>
            mon(26) get event :(0, 0, currevent, 0);
            case proccode(procext) of
            begin
              begin <* message received by semwaitmessage *>
                op:= procop(procext);
                sem:= d.op(1);
                for cmj:=1 step 1 until 8 do d.op(cmj):= core.currevent(4+cmj);
                d.op(9):= currevent;
                signalch(sem, op, d.op.optype);
                proccode(procext):= 1 shift 12;
              end;
              begin <* message received by cwaitmessage *>
                current:= procop(procext);
                procop(procext):= currevent;
                linkprio(current, readyqueue);
                link(current + corutimerchain, idlequeue);


              end;
            end; <* case *>
            currevent:= baseevent;
            proccode(procext):= 1 shift 12;
          end;
        end <* message *> else
  
      if cmi = -1 then
        begin  <* answer arrived *>
          if currevent = timermessage then
          begin
            mon(26) get event :(0, 0, currevent, 0);
            coru:= d.timerqueue.next;
            while coru <> timerqueue do
            begin
              current:= coru - corutimerchain;
              d.current.corutimer:= d.current.corutimer - clockmess(2);
              coru:= d.coru.next;
              if d.current.corutimer <= 0 then
              begin <* timer perion expired *>
                d.current.corutimer:= -1;
                linkprio(current, readyqueue);
                link(current + corutimerchain, idlequeue);
              end;
            end;
            mon(16) send message :(0, clockmess, 0, clock);
            timermessage:= monw2;
            currevent:= baseevent;
          end <* timer answer *> else
          begin
            messref(maxmessext):= currevent;
            messext:= 1;
            while messref(messext) <> currevent do messext:= messext + 1;
            if messext = maxmessext then
            begin <* the answer is unknown *>
              <* leave the answer unchanged - it may belong to an activity *>
            end else
            if messcode(messext) shift (-12) = 0 then
            begin
              case messcode(messext) extract 12 of
              begin
                begin <* answer arrived after semsendmessage *>
                  op:= messop(messext);
                  sem:= d.op(1);
                  mon(18) wait answer :(0, d.op, currevent, 0);
                  d.op(9):= monw0;
                  signalch(sem, op, d.op.optype);
                  messref(messext):= 0;
                  baseevent:= 0;
                end;
                begin <* answer arrived after csendmessage *>
                  current:= messop(messext);
                  linkprio(current, readyqueue);
                  link(current + corutimerchain, idlequeue);


                end;
              end;
            end else baseevent:= currevent;
          end;
        end;
    until eventqueueempty;



    <*************** coroutine activation ***************>

takeinternal:
  
    current:= d.readyqueue.next;
    if current = readyqueue then
    begin
      mon(24) wait event :(0, 0, baseevent, 0);
      goto takeexternal;
    end;


    corustate:= activate(d.current.coruident mod 1000);
    cmi:= corustate extract 24;

    if cmi = 1 then
    begin  <* programmed passivate *>
      goto takeexternal;
    end;

    if cmi = 2 then
    begin <* implicit passivate in activity *>


      link(current, idlequeue);
      goto takeexternal;
    end;

    <* coroutine termination (normal or abnormal) *>


    link(current, idlequeue);
    goto takeexternal;



  initialization:


    <*************** initialization ***************>
  
    <* chain head *>
  
       prev:= -2;                         <* -2  prev *>
       next:= 0;                          <* +0  next *>
  
    <* corutine descriptor *>
  
                                          <* -2  prev *>
                                          <* +0  next *>
                                          <* +2  (link field) *>
       corutimerchain:= next + 4;         <* +4  corutimerchain *>
                                          <* +6  (link field) *>
       coruop:= corutimerchain + 4;       <* +8  coruop *>
       corutimer:= coruop + 2;            <*+10  corutimer *>
       coruident:= corutimer + 2;         <*+12  coruident *>
       corupriority:= coruident + 2;      <*+14  corupriority *>
       corutypeset:= corupriority + 1;    <*+15  corutypeset *>
       corutestmask:= corutypeset + 1;    <*+16  corutestmask *>
  
    <* simple semaphore *>
  
                                          <* -2  (link field) *>
       simcoru:= next;                    <* +0  simcoru *>
       simvalue:= simcoru + 2;            <* +2  simvalue *>
  
    <* chained semaphore *>
  
                                          <* -2  (link field) *>
       semcoru:= next;                    <* +0  semcoru *>
                                          <* +2  (link field) *>
       semop:= semcoru + 4;               <* +4  semop *>
  
    <* operation *>
  
       opsize:= next - 6;                 <* -6  opsize *>
       optype:= opsize + 1;               <* -5  optype *>
                                          <* -2  prev *>
                                          <* +0  next *>
                                          <* +2  operation(1) *>
                                          <* +4  operation(2) *>
                                          <* +6      -        *>
                                          <*  .      -        *>
                                          <*  .      -        *>
  
  
      trap(dump);
      systime(1, 0, starttime);
      for cmi:= 1 step 1 until maxmessext do messref(cmi):= 0;
      clockmess(1):= 0;
      clockmess(2):= timeinterval;  
      clock(1):= real <:clock:>;
      clock(2):= real <::>;
      mon(16) send message :(0, clockmess, 0, clock);
      timermessage:= monw2;
      readyqueue:= 4;
      initchain(readyqueue);
      idlequeue:= readyqueue + 4;
      initchain(idlequeue);
      timerqueue:= idlequeue + 4;
      initchain(timerqueue);
      current:= 0;
      corucount:= 0;
      proccount:= 0;
      baseevent:= 0;
      coruref:= timerqueue + 4;
      firstcoru:= coruref;
      simref:= coruref + maxcoru * corusize;
      firstsim:= simref;
      semref:= simref + maxsem * simsize;
      firstsem:= semref;
      opref:= semref + maxsemch * semsize + 4;
      firstop:= opref;
      optop:= opref + maxop * opheadsize + maxnettoop - 6;
      for cmi:= coruref step 2 until optop - 2 do d(cmi//2):= 0;
      reflectcore(core);

  
message  tramtrim program;
      algol list.on;
      i:=ct_child_pda:=2;
      i:=ct_term_pda:=i+2;
      i:=ct_state:=i+2;
      i:=ct_ref:=i+2;
      i:=ct_job_name:=i;
      i:=ct_batch:=i+10;
      i:=ct_first:=i+2;
      i:=ct_last:=i+2;
      i:=ct_jobno:=i+2;
      i:=ct_segm_swop:=i+2;
      i:=ct_segm_queue:=i+2;
      i:=ct_bufref:=i+2;
      i:=ct_childno:=i+2;
      i:=ct_usercatno:=i+2;
      i:=ct_procin:=i+2;
      i:=ct_procout:=i+2;
      i:=ct_sem:=i+2;
      ct_size:=i;
      state_created:=1;
      state_running:=2;
      state_stopped:=3;
      state_breaked:=4;
      state_swopped:=5;
      ownref:=owndescr;
      laf:=2;
      for i:=1,2 do ownname(i):=core.ownref.laf(i);
      basep:=0;
      maxbasep:=100;
      setbasestd;
      free:=false add (1 shift 1);
      sysconpda:=console;
      laf:=sysconpda+2;
      for i:=1,2 do sysconsole(i):=core.laf(i);
      stopsystem:= false add (1 shift 2);
      verify:=testop(3);
      catsem:=nextsem;
      signal(catsem);
      zsem:=nextsem;
      signal(zsem);
      logsem:=nextsem;
      signal(logsem);
      termdisconnect:=oscommunication:=osparentmess:=childrencreated:=0;
      initalf(chartable);
      for i:=1 step 1 until usercatusers do
      for j:=1 step 1 until noofbs do
      for k:=1,2 do perm_bs_claimed(i,j,k):=0;
      j:=0;
      for i:=reader,punch,console1,firstmt step 1 until lastmt,
         firstterminal step 1 until lastterminal do
      begin
        if j<=lastdevice then includelist(j):=i;
        j:=j+1;
      end include;
      lastdevice:=j-1;
      for i:=(maxchildren+1)*ct_size//2 step -1 until 1 do
          childtable(i):=0;
      for i:=1 step 1 until maxchildren do
      begin
        iaf:=(i-1)*ctsize;
        childtable.iaf.ct_childno:=i;
        childtable.iaf.ct_sem:=nextsem;
        signal(childtable.iaf.ct_sem);
      end;
      firstusercore:=firstaddr(usercore)-1;
      for i:=1 step 1 until no_of_core_blocks+1 do
      begin
        coretable(i,1):=firstusercore+(i-1)*coreblocksize*512;
        coretable(i,2):=0; <*free*>
      end;
      coretable(no_of_core_blocks+1,2):=100000;
      cleararray(condesc);
      for i:=1 step 1 until no_of_terminals do con_pda_table(i):=0;
      open(log,0,logconsole,tw_mask);
      name(1):=0;
      readusercat(name,usercatbs,testop(4),log);
      i:=core.ownref.bufarearef;
      freebuf:=(i shift (-12) extract 12)-ownbuf;
      freearea:=(i extract 12)-ownarea;
      i:=core.ownref.intfuncref;
      freeinternal:=(i shift (-12) extract 12)-owninternal;
      for i:=1 step 1 until noofbs do
      begin
        iaf:=(i-1)*16;
        laf:=(i-1)*12;
        setownbs(usercatbs.laf,ownbs.iaf,owndrum,0,ownentries);
        setownbs(usercatbs.laf,ownbs.iaf,owndisc,ownsegmdisc,ownentrydisc);
        setownbs(usercatbs.laf,ownbs.iaf,owndisc1,ownsegmdisc1,ownentrydisc1);
      end;
      for i:=1 step 1 until noofbs do
      begin
        iaf:=i*16-16;
        laf:=i*12-12;
        j:=lookup_bs_claims(ownname,usercatbs.laf,freebs.iaf);
        bs_exist(i):=j=0;
        ownbs.iaf(1):=ownbs.iaf(3):=0;
       if j>0 then write(out,"nl",1,true,12,usercatbs.laf,<: does not exist:>,j) else
        for j:=1 step 1 until 8 do freebs.iaf(j):=freebs.iaf(j)-ownbs.iaf(j);
      end;
      write(out,"nl",2,"#",12,<: TRAMOS started: name=:>,ownname,
         "sp",3,"#",12);
      writecurtime(out);
      write(out,"nl",1,
         <<      -ddd>,
         "nl",1,<:resource            free    total:>,
         "nl",1,<:internals     :>,freeinternal,freeinternal+owninternal,
         "nl",1,<:buffers       :>,freebuf,freebuf+ownbuf,
         "nl",1,<:areas         :>,freearea,freearea+ownarea,
         "nl",1,<:coreblocks    :>,noofcoreblocks,
         "nl",1,<:coreblocksize :>,coreblocksize);
        write(out,"nl",2,<:bs resources:>,
        "nl",1,true,11,<:doc:>);
        write(out,"sp",12,<:temp:>,"sp",12,"sp",12,<:perm:>);
        write(out,"nl",1,"sp",11);
        for i:=1,2 do write(out,<:______entry___:>,<:_____segm____:>);
        write(out,"nl",1,"sp",11);
        for i:=1 step 1 until 4 do write(out,<:___free__total:>);
        for i:=1 step 1 until noofbs do
        begin
          iaf:=(i-1)*16;
          laf:=(i-1)*12;
          write(out,"nl",1,true,11,usercatbs.laf);
          if -,bs_exist(i) then write(out,<:  ** does not exist:>) else
          for j:=1,2,7,8 do write(out,<< dddddd>,
             freebs.iaf(j),freebs.iaf(j)+ownbs.iaf(j));
        end for bs;
      outendcur(10);
      algol list.off;
message  readcommand program;
      algol list.on;
      att:=false add (1 shift 3);
      attline:=nextsemch;
      for i:=1 step 1 until noofterminals+1 do
      begin
        j:=nextop(8);
        signalch(attline,j,free);
      end;
      for i:=1 step 1 until noofterminals do
      begin
        fi:=(i-1)*condescsize;
        con_desc.fi.con_term_no:=i;
        condesc.fi.con_ref:=fi;
        condesc.fi.conaccess:=nextsem;
        signal(condesc.fi.conaccess);
      end;
      ownpda:=owndescr;
      messaddress:=nextprocext(ownpda);
      for i:=1 step 1 until maxmess do
      begin
      j:=nextcoru(1,100,true);
      newactivity(j,j,receivemess,i);
      end mess;
      for i:=1 step 1 until noofterminals do
      begin
        j:=nextcoru(2,100,true);
        newactivity(j,0,readcommand,i);
      end;
      algol list.off;
message  parent message: program;
      algol list.on;
      pmess:=false add (1 shift 4);
      pmessline:=nextsemch;
      for i:=1 step 1 until maxpmess do
      begin
        j:=nextop(8);
        signalch(pmessline,j,free);
      end;
      j:=nextcoru(3,300,true);
      newactivity(j,j,receive_parent_message);
      algol list.off;
message  error messages program;
      init_error_text(errortexts);
message  batch queue: program;
      algol list.on;
      setbasestd;
      tail(1):=swopsegm;
      laf:=2;
      for i:=1,2 do tail.laf(i):=swopdoc(i);
      for i:=6 step 1 until 10 do tail(i):=0;
      i:=createentry(swop,tail);
      if i=3 then
      begin
        removeentry(swop);
        i:=createentry(swop,tail);
      end;
      if i>0 then alarm(<:***swop area :>,swop,i);
      permentry(swop,3);
      resetbase;
      begin
      integer cs,cb,blocks;
        cs:=coreblocksize*512;
        blocks:=(bmaxsizeday+cs-2)//cs;
        if blocks<=noofcoreblocks then
        begin
         cb:=0;
         for cb:=1 step 1 until blocks do coretable(cb,2):=ownpda;
         bchildfirst:=coretable(1,1);
         bchildlast :=coretable(blocks+1,1)-2;
        end else
        begin
          write(out,"nl",1,<:batch inactive, no free core :>,
          bmaxsizeday,<: needed:>);
        bmaxchildren:=0;
        end;
      end local;
      qmess:=false add (1 shift 5);
      bmess:=false add (1 shift 6);
      cmess:=false add (1 shift 7);
      jobtimermess:=false add (1 shift 8);
      qsem:=nextsem;
      signal(qsem);
      qmessline:=nextsemch;
      for i:=1 step 1 until qdes do
      begin
        j:=nextop(12);
        signalch(qmessline,j,free);
      end;
      systime(5,0,timebase);
      timebase:=timebase/100;
      day:=(timebase>b_night_to_day and timebase<b_day_to_night);
      b_max_time:=if day then b_max_time_day else b_max_time_night;
      bmessline:=nextsemch;
      for i:=1 step 1 until bmaxchildren do
      begin
        bsegmtable(i,1):=0;
        bsegmtable(i,2):=(i-1)*bmaxsizenight//512;
      end;
      for i:=1 step 1 until b_maxjobs+4 do
      begin
        j:=nextop(6);
        signalch(bmessline,j,free);
      end;
      for i:=1 step 1 until b_max_jobs do
      for j:=1 step 1 until 10 do
      job_table(i,j):=0;
      setbaseusercat;
      readbfp(<:newq:>,newqueue,false);
      i:=lookupentry(qname,tail);
      if i>0 or tail(1)<=b_max_jobs  or newqueue then
      begin
        newqueue:=true;
        tail(1):=b_max_jobs+1;
        laf:=2;
        for i:=1,2 do tail.laf(i):=own_disc(i);
        for i:=7 step 1 until 10 do tail(i):=0;
        removeentry(qname);
        i:=createentry(qname,tail);
        if i>0 then alarm(<:Queue no resources :>,qname,i);
      end;
      permentry(qname,3);
      open(qz,4,qname,1 shift 9);
      if newqueue then
      begin
        outrec6(qz,512);
        fi:=0;
        for i:=1 step 1 until 256 do qz.fi(i):=0;
        qz.fi.q0_max_time_day:=b_max_time_day;
        qz.fi.q0_max_size_day:=b_max_size_day;
        qz.fi.q0_max_time_night:=b_max_time_night;
        qz.fi.q0_max_size_night:=b_max_size_night;
        qz.fi.q0_night_to_day:=b_night_to_day;
        qz.fi.q0_day_to_night:=b_day_to_night;
        qz.fi.q0_upd_time:=b_upd_time:=systime(7,0,0.0);
        outrec6(qz,512);
        for i:=1 step 1 until 256 do qz.fi(i):=0;
        for i:=3 step 1 until b_max_jobs+1 do outrec6(qz,512);
        setposition(qz,0,0);
      end newqueue;
      resetbase;
      for i:=1 step 1 until qdes do
      begin
        fi:=(i-1)*qdescsize;
        for j:=2 step 1 until qdescsize//2 do q.fi(j):=0;
        q.fi.conref:=fi;
        q.fi.conaccess:=nextsem;
        signal(q.fi.conaccess);
      end;
      j:=nextcoru(4,300,true);
      newactivity(j,j,batch_queue);
      j:=nextcoru(5,50,true);
      newactivity(j,j,run_batch);
      j:=nextcoru(6,25,true);
      newactivity(j,j,b_timer);
      j:=nextcoru(7,25,true);
      newactivity(j,j,run_job_timer);
      algol list.off;
message  primary input message: program;
      algol list.on;
      setbasestd;
      primin(1):=long <:primi:> add 'n';
      primin(2):=0;
      createpseudoprocess(primin);
      primpda:=process_description(primin);
      priminproc:=nextprocext(primpda);
      j:=nextcoru(8,40,true);
      newactivity(j,j,receive_input_message);
      algol list.off;
message  automatic upstart: program;
      <*start up processes*>
      algol list.on;
      setbaseusercat;
      name(1):=long <:osaut:>; name(2):=0;
      i:=lookup_entry(name,tail);
      if i=0 and tail(1)>0 then
      begin
        <*start up area present*>
        zone start(128,1,stderror);
        open(start,4,<:osaut:>,0);
        i:=nextfreeterm(sysconpda);
        write(out,"nl",1,<:start up area present:>);
        outendcur(0);
        readcommandlist(start,condesc.curcondesc,true);
      end else lock:=false;
      resetbase;
      write(out,"nl",1,<:ready:>,"nl",1);
      outendcur(10);
      if fpout then closeout;
      algol list.off;

      if simref <> firstsem then initerror(1, false);
      if semref <> firstop - 4 then initerror(2, false);
      if coruref <> firstsim then initerror(3, false);
      if opref <> optop + 6 then initerror(4, false);
      if proccount <> maxprocext -1 then initerror(5, false);
      goto takeexternal;

dump:


  end;
end
▶EOF◀