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

⟦595b1a034⟧ TextFile

    Length: 100608 (0x18900)
    Types: TextFile
    Names: »disccopy5tx «

Derivation

└─⟦01e83a425⟧ Bits:30008166 Bånd med SW8010 og SW8500 source code
    └─⟦75ff9bef3⟧ 
        └─⟦this⟧ »disccopy5tx « 

TextFile

begin
  
  integer array kind(0:100),alphabet(0:127),zdescr,ia(1:21),shdescr(1:12),
                entrybase,ownbase(1:2);
 
  real array    ra(0:100),par,auxname,docname,name,toname,fromname,
                act_auxname,act_docname,maincatname(1:2);
  
  long array    program(1:2);
  
  integer       sep,space_name,point_name,space_integer,point_integer,i,j,
                type,paramno,firstentryname,no_of_entries,devno,todevno,
                fromdevno,scopetype,blocklen,tosegm,fromsegm,number_of_segments,
                firstbuffer,topbuffer,topinbuf,curfirstbuf,curtopbuf,
                curbufsize,base_lower,base_upper,permkey,start_pos,list,last,
                slicelength,slices,segments,entries,bytes,basetype,totalsegments,
                chain_addr;
  
  long          maximum,topfromsegm,toptosegm;
  
  boolean       maincatrem,output,ok,fp_mode,scope,base,
                area,morelines, checkread, olddisk;
  
  integer array field iaf;
  
  real array field areaname;
   
  zone          zhelp(1,1,stderror),zdisc(5*128,1,ownerror);

\f


  procedure result (no, text, name, res, exit);
  integer           no,             res       ;
  string                text                  ;
  real    array               name            ;
  boolean                                exit ;

  begin
    integer i;
    real    mon_name, mon_res;

    errorbits := 1; <*warning.no, ok.no*>

    write (out,
    "nl", 1, "*", 3, <: monitor result ::>);
    
    i := 1;
    if no < 0 then
      <*result from operation sent*>

      write (out,
      "nl", 1, text, <: : :>, string name (increase (i)),
      "nl", 1, "sp", 1, <:result : :>, case res of (
      <::>,
      <:process not reserver of disc process:>,
      <:receiver logical disc or physical disc with logical discs connected:>),
      "nl", 1)
    else
    begin <*monitor procedure result*>
      if no = 40 then
      begin
        mon_name := real <:create entry:>;
        mon_res  := real ( case res of (
        <::>,
        <:catalog i/o error, 
          document not mounted or not ready:>,
        <:name conflict:>,
        <:claims exceeded:>,
        <:cat base outside std base:>,
        <:name format of entry or document illegal:>,
        <:main catalog not present:>     ));
      end 

\f


      else
      if no = 54 then
      begin
        mon_name := real <:create peripheral process:>;
        mon_res  := real ( case res of (
        <:function forbidden in calling process:>,
        <:calling process not user, 
          catalog i/o error:>,
        <:name conflict, 
          not same disc:>,
        <:device number does not exist:>,
        <:device is reserved by another user:>,
        <:name format illegal:>,
        <::>));
      end else
      if no = 90 then
      begin
        mon_name := real <:permanent entry into aux cat:>;
        mon_res  := real ( case res of (
        <::>,
        <:document not ready,
          document does not exist, 
          catalog i/o error:>,
        <:name conflict in aux cat, 
          entry not found:>,
        <:entry protected, i.e. outside maxbases,
          permkey illegal:>,
        <:area used by another process, 
          entry already permanent in another auxcat:>,
        <:name format illegal, 
          claims exceeded:>,
        <:main catalog not present:>      ));
      end 
      
\f


      else
      if no = 102 then
      begin
        mon_name := real <:prepare backing storage:>;
        mon_res  := real ( case res of (
        <:area claims exceeded, 
          function forbidden in calling process:>,
        <:catalog i/o error:>,
        <:auxcat name overlap,
          auxcat name exists already:>,
        <:document device does not exist,
          document device is not a bs device,
          document device not reserved:>,
        <:auxcat size <= 0 or auxcat size too large,
          chainhead chain inconsistent,
          auxcat chain inconsistent,
          illegal kind of chaintable,
          permkey of auxcat illegal,
          too many slices,
          claims exceeded (too few slices for chaintable),
          -,-             (auxcat too large),
          -,-             (no room in maincat):>,
        <:auxcat name format illegal,
          doc    name format illegal:>,
        <:no chains idle:>               ));
      end else
      if no = 104 then
      begin
        mon_name := real <:insert entry:>;
        mon_res  := real ( case res of (
        <:function forbidden in calling process:>,
        <:catalog i/o error,
          document not found,
          state of document does not permit the call:>,
        <:name overlap,
          name exists already:>,
        <:calling process not user of the device:>,
        <:permkey  illegal,
          interval illegal,
          chain overlap,
          chain outside limits:>,
        <:name    format illegal,
          docname format illegal,
          claims  exceeded:>,
        <:main catalog not present:>     ));
      end 


\f

      else
      if no = 106 then
      begin
        mon_name := real <:insert backing storage:>;
        mon_res  := real (case res of (
        <:function forbidden in calling process:>,
        <:document not found,
          state of document does not permit call:>,
        <::>,
        <:calling process not user of device:>,
        <::>,
        <:docname format illegal:>,
        <::>));
      end else
      if no = 108 then
      begin
        mon_name := real <:delete backing storage:>;
        mon_res  := real (case res of (
        <:function forbidden in calling process:>,
        <:document not found,
          catalog i/o error:>,
        <::>,
        <:calling process not user of device:>,
        <:area processes exist for the document:>,
        <:docname format illegal,
          main catalog on the document:>,
        <::>));
      end else
      if no = 110 then
      begin
        mon_name := real <:delete entries:>;
        mon_res  := real (case res of (
        <:function forbidden in calling process:>,
        <:document not found,
          catalog i/o error,
          state of document does not permit call:>,
        <:not all entries deleted yet:>,
        <:calling process not user of device:>,
        <::>,
        <:docname format illegal:>,
        <::>));
      end 

\f


      else
      if no = 120 then
      begin
        mon_name := real <:create aux entry and area process:>;
        mon_res  := real (case res of (
        <:function forbidden in calling process,
          area claims exceeded:>,
        <:catalog i/o error,
          document not found,
          state of document does not permit the call:>,
        <:procname  overlap,
          procname  exists already,
          entryname overlap        (in auxcat),
          entryname exists already (in auxcat):>,
        <:calling process not user of the device,
          claims exceeded:>,
        <:key      illegal,
          interval illegal:>,
        <:entry name format illegal,
          proc  name format illegal,
          doc   name format illegal:>,
        <::>                             ));
      end;

      write (out,
      "nl", 1, string mon_name,
      <: : :>, string name (increase (i)),
      "nl", 1, "sp", 1, <:result : :>, string mon_res,
      "nl", 1);

    end <*monitor procedure result*>;
 
    if not fpmode then
      stopzone (out, false);

    if exit then
    begin
      close (zdisc, true);
      reset_catbase;
      if fp_mode then
        goto aftererror
      else
        goto next_line;
    end <*exit*>;

  end procedure result;

\f



  procedure maybe_device_status (z);
  zone                           z ;
  
  <***********************************************************>
  <*                                                         *>
  <* The procedure writes on the zone z a device status mes- *>
  <* sage with document name and status bit names the same   *>
  <* way fp does if the program was to terminate with a give *>
  <* up alarm instead of having trapped one.                 *>
  <*                                                         *>
  <***********************************************************>

  begin
    integer             status, cause, param, bit;
    long    array       text (1:4);
    long    array field docname;

    docname := 8; <*fields possible docname in text*>

    status := getalarm (text);
    cause  := alarmcause extract  24 ;
    param  := alarmcause shift  (-24);

    if cause = -11 then
    begin <*give up*>
      write (z, "nl", 1, 
      <:device status :>, text.docname);

      for bit := 0 step 1 until 23 do
      if status shift bit < 0 then
        write (z, "nl", 1, case (bit + 1) of (
        <:intervention:>,
        <:parity error:>,
        <:timer:>,
        <:data overrun:>,
        <:block length error:>,
        <:end of document:>,
        <:load point:>,
        <:tape mark or attention:>,
        <:writing enabled:>,
        <:mode error:>,
        <:read error:>,
        <:card rejected or disk error:>,
        <:checksum error:>,
        <:bit 13:>,
        <:bit 14:>,
        <:stopped:>,
        <:word defect:>,
        <:position error:>,
        <:process does not exist:>,
        <:disconnected:>,
        <:unintelligible:>,
        <:rejected:>,
        <:normal:>,
        <:hard error:>));

      write (z, "nl", 1);
    end;

  end rs_alarm;

\f




  integer procedure process_description (devno, proc_area);
  value                                  devno            ;
  integer                                devno            ;
  integer array                                 proc_area ;
  begin
    integer i;
    system (5, 74, proc_area);
    i:= proc_area(1)+devno*2;
    if i>=proc_area(2) then writeerror (<:devno outside limits:>);
    system(5, i, proc_area);
    process_description:= proc_area(1);
    system(5,proc_area(1), proc_area);
  end process_description;

\f




  integer procedure device_number (proc_address);
  value                            proc_address ;
  integer                          proc_address ;
  begin
    integer array ia (1:2);
    integer i, max_device;

    system (5, 74, ia);
    max_device:= (ia(2)-ia(1))//2;
    begin
      integer array       name_table (0:max_device);
      integer array field iff;

      iff := -2;

      system(5, ia(1), name_table.iff);
      for i:= 0 step 1 until max_device do
      begin
        if proc_address=name_table(i) then
        begin
          device_number:= i;
          i:= max_device;
        end;
      end;
    end;
  end device_number;





    procedure typetext(text);
    string text;
    begin
    write(out, text); if -,fp_mode then setposition(out,0,0);
    end;


  
    procedure typein(number);
    integer number;
    begin
    setposition(in, 0, 0); read(in, number);
    end;

\f






    procedure alarm(text);
    string text;
    begin
    typetext(text);
    typetext(<:<10>:>);
    goto after_error;
    end;
  
  
    procedure caterror(z,s,b);
    zone               z     ;
    integer              s,b ;
      if s shift (-18) extract 1 = 1 then b:= 34 else
      if s shift (-2) extract 1 = 1 then stderror(z,s,b);
   
    
      
    procedure end_of_document(z);
    zone                      z ;
    begin
      getshare6(z,shdescr,1);
      write(out,<:<10>:>,if shdescr(4) shift (-12) = 3 then
                <:input from segment : :> else
                <:output to segment  : :>,<<ddddddd>,shdescr(7),
                <: - end of document:>);
      typetext(<:<10>:>);
    end;



procedure status (z, s, b);
zone z; integer s, b;
begin
integer bit;
integer array zdescr(1:20), shdescr(1:12);
long array field zname;

zname := 2;
getzone6 (z, zdescr);
getshare6 (z, shdescr, 1);

write (out, <:<10>:>, if shdescr(4) shift (-12) = 3 then
               <:input from: :>           else
               <:output to : :>);
write (out, false add 32, 12 - write (out, zdescr.zname));
write (out, <<dddddd>, <:   segm::>, shdescr(7),
            <:   status=:>);
for bit := 0 step 1 until 23 do
  write (out, if s shift bit < 0 then <:1:> else <:.:>);
typetext (<:<10>:>);

end procedure status;

\f



procedure ownerror (z, s, b);
zone z; integer s, b;
  begin
  status (z, s, b);
  stderror (z, s, b);
  end;



boolean procedure transfer (z, cursegment, topsegment);
zone z; integer cursegment; long topsegment;
begin
  integer mode;
  long remaining_bytes;
  integer logstatus, segments, repcount;
  integer array answer(1:8);

  repcount := 0;

  curfirstbuf := firstbuffer;
  curbufsize  := curtopbuf - firstbuffer;
  remaining_bytes := (topsegment - cursegment) shift 9;
  if remaining_bytes < curbufsize then
    begin
    curbufsize := remaining_bytes;
    curtopbuf  := curfirstbuf + curbufsize;
    end;

 next_block:

  if curfirstbuf = curtopbuf then
    goto exit;

  mode :=         if checkread   and
                     not olddisk and
                     output      then 1 else 0;
  <*if checkread and not old disk and output then read after write*>

<*write (out,
  "nl", 2, <:***********  mode = :>, mode, <:  **************:>);
*>
  shdescr (4) := (if output      then 5 else 3) shift 12 + mode;

  shdescr (5) := curfirstbuf;
  shdescr (6) := curfirstbuf + curbufsize - 2;
  shdescr (7) := cursegment;

  setshare6 (z, shdescr, 1);
  monitor (16) send message :( z, 1, shdescr);
  logstatus := 1 shift monitor (18) wait answer :( z, 1, answer);
  bytes := if logstatus = 2 <* normal answer *> then
              answer (2)
           else
              0;
\f


 
 
  if logstatus = 2 <* normal answer *> then
    logstatus := logstatus + answer (1);
  if (logstatus shift(-18) extract 1 = 1  and
      logstatus shift(-1)  extract 1 = 1  and
      curbufsize = 512                    and
      -,area                                  )   or
      logstatus = 1 shift 18 + 1 shift 1 <* end document *> 
      then curtopbuf:= curfirstbuf + bytes
  else
  if logstatus <> 1 shift 1 then
    begin <* transfer not ok *>
    if curbufsize <> 512 then
      begin <* repeat same transfer, but with size = 512 bytes *>
      bytes := 0;
      curbufsize := 512;
      end
    else
      begin <*single segment transfer was not ok*>
        repcount := repcount + 1;
        if repcount < 6 then
          bytes := 0 <*retry*>
        else
        begin <*give up*>
          repcount := 0;
          errorbits := 3;
          status (z, logstatus, bytes);
          bytes := 512; <*simulate transfer of one segment*>
          if logstatus extract 6 <> 2 <*normal answer*> and
             logstatus extract 6 <> 1 shift 4 <*malfnct, i.e. bus parity*> then
          begin <*simulate end of document*>
            curtopbuf := firstbuffer;
            goto exit;
          end <*simulate*>;

        end <*give up*>;

      end <*single transfer not ok*>;
    end
  else
  begin <*transfer ok*>
    repcount := 0;
    if curbufsize <> 512 then
     curbufsize := curbufsize - bytes;
  end <*transfer ok*>;

  curfirstbuf := curfirstbuf + bytes;
  segments := bytes shift (-9);
  cursegment := cursegment + segments;
  goto next_block;

  exit:

  transfer := curtopbuf <> firstbuffer;

end procedure transfer;
\f







        procedure copyarea(tosegm, fromsegm, size);
        value tosegm, fromsegm, size;
        integer tosegm, fromsegm;
        long size;
        <* this procedure will perform the actual copying*>
        begin

        if fpmode then
        begin
          <*the segments involved in copyarea must be transferred*>
          <*to core and locked before data buffer is allocated   *>

          integer oldtrapmode;

          oldtrapmode :=trapmode;
          trapmode := 1 shift 1; <*stack alarm masked off*>
          trap (maybe_stack);

          lock (
          transfer, getdevorname,
          setshare6, 1 ,
          monitor  , 3 );

          maybe_stack:
          if alarmcause extract 24 = -1 then
          alarm ( <:process too small:> ) else
          if alarmcause extract 24 <  0 then
          alarm ( <:alarm:> );

          trapmode := old_trapmode;
        end;

        blocklen := system(2 <*free core*>, 0, name)
                  -1624 <* space for local variables and procedure calls *>;
        blocklen := blocklen shift (-9) shift 9;
        if blocklen < 512 then alarm (<:process too small:>);
        begin
          integer       i;
          integer array todesc, fromdesc(1:20), procdescr (1:1);
          zone          z(blocklen//4, 1, status);



          procedure prepout;
          begin
            getzone6(z,fromdesc);
            setzone6(z,todesc);
            output:=true;
          end prepout;



          procedure prepin;
          begin
            getzone6(z,todesc);
            setzone6(z,fromdesc);
            output:=false;
          end prepin;

\f


          i:=1;
          getzone6(z,todesc);
          open(z,0,string fromname(increase(i)),-1 shift 2 - 1 shift 8);
                   <* all except normal answer and stopped *>
          if area then
          monitor(52,z,0,ia);
          monitor(6)initialize:(z,0,ia);
          prepout;
          i:=1;
          open(z,0,string toname(increase(i)),-1 shift 2 - 1 shift 8);
                   <* all except normal answer and stopped *>
          if area then
            monitor(52,z,0,ia);
          monitor(8)reserve:(z,0,ia);

          procdescr (1) := monitor (4, z, 0, procdescr);
          if procdescr (1) <> 0 then
          begin <*process exists*>
            if area then
              system (5, procdescr (1) + 10, procdescr); <*main disc*>
            system (5, procdescr (1), procdescr); <*procdescr (1) = kind*>
          end;
          olddisk := procdescr (1) <> 6; <*not exist or kind <> 6*>

          prepin;
          firstbuffer := fromdesc (19) + 1;
          topbuffer   := fromdesc (20) * 4 <* buffersize in bytes *>
                       + firstbuffer;
          getshare6 (z, shdescr, 1);
        
          topfromsegm := size + fromsegm;
          toptosegm   := size + tosegm;

nextblock:
          curtopbuf := topbuffer;
          if transfer (z, fromsegm, topfromsegm) then
            begin
            topinbuf := curtopbuf;
            prepout;
            transfer (z, tosegm, toptosegm);
            prepin;
            if topinbuf = curtopbuf then
              goto nextblock;
            prepout;
            end_of_document(z);
            prepin;
            end;
          getshare6(z,shdescr,1);
          totalsegments:= shdescr(7) + bytes shift (-9); <* no. of last segment copied *>
          close(z,true);
          monitor(64)remove process:(z,0,ia);
          prepout;
          close(z,true);
          monitor(64)remove process:(z,0,ia);
          prepin;
        end;
        end copyarea;
\f




        boolean procedure getdevorname(getdevice,devno,name,auxname,chain_addr);
        boolean getdevice;
        integer devno,chain_addr;
        real array name,auxname;
        begin
        integer chainentry, firstdeviceinnametable, device;
        integer array coreword(1:1), bspointers(1:3), chainhead(1:17);
        real field docname1, docname2, auxcatname1, auxcatname2;
        integer field documentnametableaddress;

        docname1 := 20; docname2 := docname1 + 4;
        documentnametableaddress := docname1 + 6;
        auxcatname1:= 10; auxcatname2:= 14;

        <* get nametable address of first,top chain *>
        system(5, 92, bspointers);

        <* get nametable address of first device *>
        system(5, 74, coreword);
        firstdeviceinnametable := coreword(1);

        <* scan all chaintables to find the rigth one *>
        for chainentry := bspointers(3) - 2   <* last chaintable *>
                 step     - 2                 <* size of nametable entry *>
                 until    bspointers(1)       <* first chaintable *>
                 do
          begin
          <* get chaintable address *>
          system(5, chainentry, coreword);

          <* get chainhead from chaintable *>
          system(5, coreword(1) - 34, chainhead);

          <* compute devicenumber of discdrive *>
          device := (chainhead.documentnametableaddress
                    - firstdeviceinnametable
                    ) // 2;

          if chainhead.docname1 shift (-24) extract 24 <> 0 and
             (if -, getdevice then
                 device = devno
              else
                (name(1) = chainhead.docname1 and
                 name(2) = chainhead.docname2
                )
             )
          then
            goto chaintablefound;
 
          <* this chaintable was not the rigth one *>
          end;

        <* no chaintables was found good enough *>
        getdevorname := true;
        goto exit;

chaintablefound:

        devno := device;
        name(1) := chainhead.docname1;
        name(2) := chainhead.docname2;
        auxname(1):= chainhead.auxcatname1;
        auxname(2):= chainhead.auxcatname2;
        chain_addr:= coreword(1);

        getdevorname := false;
 exit:
        end procedure getdevorname;

\f



        boolean procedure connect(devno, name);
        integer devno;
        real array name;
        begin
        integer repcount;
        integer array zdescr(1:20);
        real array field zname;

        procedure repeatproc(z, s, b);
        zone z;
        integer s, b;
          begin
          repcount := repcount + 1;

          if repcount < 3 and s = 1 shift 5 then
            goto try_once_more;
          b := 512;
          connect := true;
          write (out, <:intervention on :>, <<zdd>, devno);
          typetext (<:<10>:>);
          end procedure repeatproc;

        repcount := 0;
        connect := false;
try_once_more:
        begin
        zone device(128, 1, repeatproc);
        zname := 2;
        i := 1; open(device, 0, string name(increase(i)), 1 shift 5);
        i := monitor(54 <*create peripheral proc*>, device, devno, zdescr);
        if i <> 0 then
          begin
          result(54, <::>,  name, i,false);

          connect := true;
          end
        else
          begin
          inrec6(device, 0);  <*try to read a block *>
          getzone6(device, zdescr);
          name(1) := zdescr.zname(1);
          name(2) := zdescr.zname(2);
          end;
        end;
        end procedure connect;
\f




        boolean procedure kitoff(docname);
        real array docname;
        begin
          integer array tail (1:10);
          long array field dname;
          integer i,k;
          zone z (512,1,stderror);
          long array progname(1:2);
      
          dname := 2; <*fields docname in tail*>
          kitoff := false;  <*assume succes in removal*>
          for i := 1 step 1 until 4 do
          ia(17+i) := docname.iaf(i);
          k:=monitor(108)delete bs:(z,0,ia);

          if k=5 <* area processes exists for same document *> then
          begin <*remove area process*>

            <*maybe remove program area proc*>
            system (2, 0, progname);
            open (z, 4, progname, 0);
            tail.dname (1) := tail.dname (2) := long <::>;
            if monitor (42) lookup tail :(z, i, tail) = 0 and
               tail.dname (1) = long docname (1)               and
               tail.dname (2) = long docname (2)              then
            begin <*lock all program segments and remove proc*>
              if fp_mode then
                lockall;

              close (z, true);
              typetext (<:notice : disc with program file is removed<10>:>);
            end else
              close (z, false);

            <*maybe remove fp area process*>
            open (z, 4, <:fp:>, 0);
            tail.dname (1) := tail.dname (2) := long <::>;
            if monitor (42) lookup tail :(z, i, tail) = 0 and
               tail.dname (1) = long docname (1)               and
               tail.dname (2) = long docname (2)              then
            begin
              close (z, true);
             
              typetext (<:notice : disc with fp prog file is removed<10>:>);
              end_action := 1; <*end prog condition := finis*>
            end else
              close (z, false);

            k := monitor (108) delete bs :(z, 0, ia);

          end <*remove area processes*>;
 

          if k=6 <* maincat on same document*> then
            begin
            maincatrem := 0 = monitor(114)remove main catalog:(z,0,ia);
            if maincatrem then
              typetext (<:notice : disc with main catalog is removed<10>:>);
            k:=monitor(108)delete bs:(z,0,ia);
            end;
\f


 
          if k<>0  and  k<>2 then 
            begin
            kitoff := true;
            result(108, <::>,  docname, k,true);
            end
          else
            begin
            for k:=monitor(110)delete entries:(z,0,ia) while k=3 do;
            if k<>0 and k<>7 then
              begin
              kitoff := true;
              result(110, <::>,  docname, k,true);
              end;
            end;

        end procedure kitoff;


\f


      procedure list_entry(entry,k);
      integer                    k ;
      real array           entry   ;
      begin
        boolean sp;
        long array field entryname;
        sp:= false add 32;
        entryname:= 6;
        outchar(out,10);
        write(out,sp,18-write(out,entry.entryname));
        if entry.iaf(8) >= 0
           then write(out,<<dddddd>,entry.iaf(8))
           else write(out,sp,6);
        write(out,<<-ddddddd>,sp,5,entry.iaf(2),sp,5,entry.iaf(3));
        if k <> 0
           then write(out,<: -   not ok:>, "nl", 1, <:result = :>,
                case k of (
                <:function forbidden in calling process:>,
                <:catalog i/o error, document not found, state illegal:>,
                <:name overlap/exists already:>,
                <:calling process not user of the device:>,
                <:permkey/interval illegal, chain overlap/outside limits:>,
                <:name/docname format illegal, claims exceeded:>,
                <:main catalog not present:>     ),
                "nl", 1);
        if -,fp_mode then setposition(out,0,0);
      end listentry;

\f

        procedure kiton(devno,docname,list,insert_entry_incl,wrkname);
        boolean insert__entry_incl,wrkname;
        integer devno,list;
        real array docname;
        begin
          long array field auxcat,document;
          zone zcat(128,1,ownerror);
          integer k,i,catsize, first_slice_chain, last_slice_doc, no_of_slices, chain_length;
          integer array shdescr (1:12);
          long array field laf;
          boolean head_listed;

          document:= 16; auxcat:= 6;
          laf:=6;
          docname(1) := 0;
          if connect(devno, docname) then
          goto if fp_mode then aftererror else nextline;
          i := 1; open (zdisc, 6, string docname (increase (i)), 0);
          <*read chain*>
          inrec6(zdisc,34);
          
          first_slice_chain := zdisc.iaf (15)             extract 12;
          last__slice_doc   := zdisc.iaf (15) shift (-12) extract 12;
          no_of_slices      := last_slice_doc - first_slice_chain + 1;

          chain_length      := ((34 + no_of_slices + 511) // 512) * 512;

          setposition (zdisc, 0, 0);

          getshare6 (zdisc, shdescr, 1);
          shdescr (3) := shdescr (2) + chain_length - 1; <*last sh := first sh + ...*>
          setshare6 (zdisc, shdescr, 1);

          inrec6 (zdisc, chainlength); <*just the necessary no of segments*>
  
          if -,wrkname then
          begin <* create ph. proc. with correct documentname *>
            getzone6(zdisc,ia);
            for i:= 2 step 1 until 5 do
            docname.iaf(i-1):= ia(i):= zdisc.iaf(i+7);
            setzone6(zdisc,ia);
            monitor(54)create ph proc:(zdisc,devno,ia);
          end
          else
          begin <* insert wrkname for document and auxcat in chainhead *>
            for i:= 1 step 1 until 4 do
            begin <* save actual names before insertion of wrknames *>
              act_auxname.iaf(i):= zdisc.iaf(i+3); <* save auxname *>
              act_docname.iaf(i)   := zdisc.iaf(i+8); <* save docname *>
            end;
            monitor(68)generate wrkname:(zcat,0,ia);
            getzone6(zcat,ia);
            for i:= 1 step 1 until 4 do
            begin
              zdisc.iaf(i+8):= docname.iaf(i); <* document *>
              zdisc.iaf(i+3):= ia(i+1);        <* auxcat *>
            end;
            close(zcat,false);
          end;
  
          slicelength:= zdisc.iaf(14);
   
          monitor(8)reserve:(zdisc,i,ia);
          k := monitor(102)prepare bs:(zdisc,i,ia);
          if k <> 0 then
            result(102, <::>,  docname, k, true);
 
          if maincatrem then
          begin <* connect maincat if possible *>
            i:= 1;
            open(zcat,4,string zdisc.laf(increase(i)),0);
            close(zcat,true); <* remove area process for auxcat *>
            maincatname(1):= real<:catal:> add 111;
            maincatname(2):= real<:g:>;
            maincatrem:= monitor(112)connect maincat:(zdisc,0,maincatname.iaf) <> 0;

            write (out,
              "nl", 1, <:main catalog :>,
              if maincatrem then <:not :> else <: :>, <:reconnected:>);
              typetext (<:<10>:>);
          end;
 
          if insert_entry_incl then
          begin <* insert entries in maincatalog *>
          head_listed := false;
          i:=1;
          open(zcat,4,string zdisc.laf(increase(i)),0);
          catsize:=zdisc.iaf(8)*15;

          for i:=1 step 1 until catsize do
          begin
            inrec6(zcat,34);
            <*if entry used then insert entry*>
            if zcat.iaf(1)<>-1 then
            begin
            k:= monitor(104)insert entry:(zdisc,0,zcat.iaf);

            if not head_listed                         and
              (list =  2       
            or list =  3                               and
              (extend zcat.iaf (2) > extend (-8388607)
            or extend zcat.iaf (3) < extend   8388605)
            or list =  4                               and
               k     > 0                               and
               k    <> 3
            or list =  5                               and
               k    =  3)                             then
            begin
              write(out,<:<10>*kiton, :>,case list of
                   (<::>,
                    <:entries inserted::>,
                    <:non system entries inserted::>,
                    <:errors during insertion::>,
                    <:entries not inserted due to name overlap::>),
                    <:<10><10>:>,
                    <:entry name          size   :>,
                    <:lower base   upper base:>, "nl", 1);
              head_listed := true;
            end;

            case list of
            begin
                                                   ; <* list.no *>
              list_entry(zcat,k)                   ; <* list.yes *>
              if extend zcat.iaf(2) > extend (-8388607) or
                 extend zcat.iaf(3) < extend  8388605
                 then list_entry(zcat,k)           ; <* list.nonsys *>
              if k <> 0 and k <> 3
                 then list_entry(zcat,k)           ; <* list.error *>
              if k = 3 then list_entry(zcat,0)     ; <* list.warning *>
            end;
            end;
          end;
          close(zcat,true);
          if -,wrkname then close(zdisc,true);
          open  (zcat, 4, <:fp:>, 0);
          if monitor (52) create area proc :(zcat, 1, ia) = 0 then
            endaction := 0; <*fp area proc intact*>
          close (zcat, false);
          end;
 
        end procedure kiton;
\f



      procedure lockall;

        lock (0, progsize - 1); <*lock all upper part of prog in core*>
\f


  
  boolean procedure next_param(arr,no,type,optional);
  value                                    optional ;
  boolean                                  optional ;
  integer                          no,type          ;
  array                        arr                  ;
 
  begin comment this procedure returns call-parameter number
                'no' in array 'arr'. type-checking is performed
                as follows:
       
                type = 1: space-name is demanded
                type = 2: point-name is demanded
                type = 3: space-integer is demanded
                type = 4: point-integer is demanded
                type = 5: point-integer or point-name is demanded
 
                'optional' indicates whether the next parameter is
                optional or not.
  
                the procedure operates in fp-mode or in
                conversational mode.                 ;
  
     
    procedure conv_error(number,i,type,delim);
    value                number,i,type,delim ;
    integer              number,i,type,delim ;
    begin <* error-messages in conversational mode *>
       write(out,<:<10>illegal parameter no. :>,no,
                <:,must be :>,case type of (<:<sp><name>:>,
                <:.<name>:>,<:<sp><integer>:>,
                <:.<integer>:>,<:.<integer> or .<name>:>),
                <:     read: :>);
      if delim = 0
         then write(out,<:<integer>:>)
         else outchar(out,delim);
      if kind(i) = 6 <* text *> 
         then write(out,string ra(increase(i)))
         else
           if kind(i) = 2 <* legal number *>
              then write(out,round ra(i))
              else write(out,<: illegal number :>);
      write(out,<:<10>:>);
      if -,fp_mode then setposition(out,0,0);
      goto next_line;
    end conv_error;
  
    
    boolean ok,continue;
    real array op_name(1:2);
    integer sep,action,number,delim,separator;
    if optional then
    begin
      op_name(1):= arr(1);
      op_name(2):= arr(2);
    end;
    continue:= true;
  
    if fp_mode then
    begin <* fp_mode *>
      sep:= system(4,no,arr);
      if sep <> 0 then
      begin
        if optional then
        begin
          if sep = (case type of (space_name,point_name,space_integer,
                                  point_integer))  then

          begin
            if op_name(1) <> arr(1) or
               op_name(2) <> arr(2) then
            begin
               i:= 1;
               write(out,<:<10>illegal parameter no. :>,no,
                     <:,must be: :>,string op_name(increase(i)));
               i:= 1;
               write(out,<:    read: :>,string arr(increase(i)));
               goto endprogram;
            end;
          end
          else
            continue:= false;
        end optional;
        if continue then
        begin
          case type of
          begin
            ok:= sep = space_name;
            ok:= sep = point_name;
            ok:= sep = space_integer;
            ok:= sep = point_integer;
            begin
              type:= if sep = point_name then 2 else 4; <* return-value *>
              ok:= sep = point_name or sep = point_integer;
            end;
          end;
          if -,ok then
          begin
            separator:= 5;
            for i:= 1 step 1 until 4 do
            if sep = ( case i of (space_name,point_name,space_integer,
                                  point_integer)) then separator:= i ;
            write(out,<:<10>***:>,program,<:: illegal fpparameter no. :>,
                  no,<:,must be :>,case type of (<:<sp><name>:>,
                  <:.<name>:>,<:<sp><integer>:>,<:.<integer>:>),
                  <:     read::>,case separator of (<:<sp>:>,<:.:>,
                  <:<sp>:>,<:.:>,<::>));
            if separator < 3 <* name *> then
            begin
              i:= 1;
              write(out,string arr(increase(i)));
            end
            else
              write(out,round arr(1));
            goto endprogram;
          end -, ok;
        end;
      end;
      next_param:= if optional
                      then continue and sep <> 0
                      else sep <> 0;
    end
    else
    begin <* conversational mode *>
      delim:= 0;
      number:= -1;
      <* search item *>
      for i:= 0,i + 1 while kind(i) <> 8 and number < no do
      begin
        action:= case ((kind(i)-1)*8 + kind(i+1)) of
  
                        <* kind(i+1) *>
                 ( 3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 ,
                   3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 ,
                   3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
   <* kind(i) *>   3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
                   3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
                   3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 ,
                   1 , 1 , 3 , 3 , 3 , 1 , 2 , 2  ) ;
  
  

        case action of
        begin
          number:= number + 1; <* text or integer found *>
                             ; <* skip *>
          begin <* error *>
            write(out,<:<10>action-table in error:>);
            goto endprogram;
          end;
        end;
      end for-loop;
  
      if number = no then
      begin <* now 'i' points at the first element of the
               item in array 'ra' . get the item and check it .       *>
  
        if optional then
        begin
          if round ra(i-1) = (case type of (32,46,32,46)) then
          begin
            if op_name(1) <> ra(i) then
            begin
               j:= 1;
               write(out,<:<10>illegal parameter no. :>,no,
                     <:,must be: :>,string op_name(increase(j)),
                     <:    read: :>,string ra(increase(i)),<:<10>:>);
               if -,fp_mode then setposition(out,0,0);
               goto next_line;
            end;
          end
          else
            continue:= false;
        end optional;
        if continue then
        begin
          if kind(i-1) = 7 then delim:= round ra(i-1);
 
          case type of
          begin
       
            <* space-name *> if delim <> 32 or kind(i) <> 6
                                then conv_error(number,i,1,delim);
  
            <* point-name *> if delim <> 46 or kind(i) <> 6
                                then converror(number,i,2,delim);
  
            <* space-int. *> if delim <> 32 or kind(i) <> 2
                                then conv_error(number,i,3,delim);
  
            <* point-int. *> if delim <> 46 or kind(i) <> 2
                                then conv_error(number,i,4,delim);
            <* point-int. or
               point-name *> begin
                                 if delim=46 and kind(i)=6 then type:= 2 else
                                 if delim=46 and kind(i)=2 then type:= 4 else
                                 conv_error(number,i,5,delim);
                             end;
  
          end case;
  
          <* return item in 'arr' *>
 
          if type < 3 then
          begin <* text *>
            arr(1):= ra(i);
            arr(2):= if kind(i+1) <> 6 then real <::> else
                        ra(i+1) shift(-8) shift 8; <* max 11 chars *>
          end
          else
            arr(1):= ra(i);
        end;
      end;
      next_param:= if optional
                      then continue and number = no <* optional param. present *>
                      else number = no;
    end conversational mode;
    if continue then no:= no + 1;
  end next_param;
\f

 
   
    
  procedure dump_actual_names(devno);
  integer                     devno         ;
  begin <* dumps actual names of auxcat and document in chainhead. *>
    zone zdisc (128, 1, ownerror);

    docname(1):= 0;
    connect(devno,docname); <* create ph. proc with wrkname *>
    i:= 1; open(zdisc,6,string docname(increase(i)),0);
    swoprec6(zdisc,34); <* get chainhead *>
    for i:= 1 step 1 until 4 do
    begin
      zdisc.iaf(i+3):= act_auxname.iaf(i); <* reestablish auxname *>
      zdisc.iaf(i+8):= act_docname.iaf(i); <* reestablish docname *>
    end;
    close(zdisc,true);
    monitor(64)remove process:(zdisc,0,ia);
  end;
\f

  
  
  integer procedure convert_to_number(arr);
  array                               arr ;
  begin
    integer i;
    convert_to_number:= 13;
    for i:= 1 step 1 until 12 do
    begin
      if arr(1) = ( case i of ( real<:discc:> add 'o',
                                real<:kitna:> add 'm',
                                real<:kiton:>        ,
                                real<:kitof:> add 'f',
                                real<:packo:> add 'n',
                                real<:packo:> add 'f',
                                real<:kitla:> add 'b',
                                real<:end:>          ,
                                real<:save:>         ,
                                real<:load:>         ,
                                real<:bin:>          ,
                                real<:typei:> add 'n' )) and
   
         arr(2) = ( case i of ( real<:py:>           ,
                                real<:e:>            ,
                                real<::>             ,
                                real<::>             ,
                                real<::>             ,
                                real<:f:>            ,
                                real<:el:>           ,
                                real<::>             ,
                                real<::>             ,
                                real<::>             ,
                                real<::>             ,
                                real<::>              ))
  
         then convert_to_number:= i;
    end;
  end convert_to_number;
  
\f

 
  procedure outtable(alphabet,length);
  value                       length ;
  integer                     length ;
  integer array      alphabet        ;
  begin
  
    zone alpha(25,1,blockproc);
    integer class,char,i;
  
    procedure blockproc(z,s,b);
    zone                z     ;
    integer               s,b ;
      if (s shift (-5)) extract 1 <> 1 then stderror(z,s,b) else b:= 25*4;
  
    if length < 0 or length > 127 then length:= 127;
    open(alpha,0,<::>,1 shift 5);
    for i:= 0 step 1 until length do write(alpha,false add i,1);
    write(alpha,false add 10,1);
    setposition(alpha,0,0);
    for i:= 0 step 1 until length do
    begin
      class:= readchar(alpha,char);
      if char <> i then
      begin
        class:= 0;
        repeatchar(alpha);
      end;
      alphabet(i):= class shift 12 + i;
    end;
  end outtable;
  
  
  integer procedure convert_param(arr);
  array                           arr ;
  begin
    integer i;
    convert_param:= 7;
    for i:= 1 step 1 until 6 do
      if arr (1) = ( case i of (
        real<:from:>          ,
        real<:to:>            ,
        real<:scope:>         ,
        real<:base:>          ,
        real<:list:>          ,
        real<:check:> add 'r' )) then
          convert_param := i;
  end;
  
\f

 
  procedure write_error(cause);
  string                cause ;
  begin
    write (out, "nl", 1);
    if fp_mode then
      write (out, <:***:>, program, <:, :>);
    write (out, cause, "nl", 1);
    if fp_mode
       then goto after_error
       else
       begin
         setposition(out,0,0);
         goto next_line;
       end;
  end;
  
   
  procedure check_scope;
  begin
    for i:= 1 step 1 until 3 do
        if par(1) = (case i of ( real<:syste:> add 109,
                                 real<:proje:> add 99 ,
                                 real<:user:>         )) and
           par(2) = (case i of ( real<::>             ,
                                 real<:t:>            ,
                                 real<::>             ))
           then scopetype:= i;
  
    if scopetype = 0
       then writeerror(<:scope must be 'system','project' or 'user':>);
  end;
  
\f

  
  
  boolean procedure entry_ok(entry,names,entry_found);
  real array                 entry,names             ;
  boolean array                          entry_found ;
  begin <* this procedure checks a catalogentry according to
           the call-parameters.                             *>
  
    integer i;
    boolean ok;
    real array entryname(1:2);
    <* check base *>
    entrybase(1):= entry.iaf(2);
    entrybase(2):= entry.iaf(3);
    if base
       then ok:= extend entrybase(1) >= extend base_lower and
                 extend entrybase(2) <= extend base_upper and
                 entry.iaf(1) extract 3 >= 2 <* min auxcat permkey *>
       else ok:= extend entrybase(1)  = extend base_lower and
                 extend entrybase(2)  = extend base_upper and
                 entry.iaf(1) extract 3 = 3; <* permkey *>
    if ok then
    begin
      <* check if entryname match with entrynames in call - if any *>
      if firstentryname > 0 then
      begin
        for i:= 1 step 1 until 4 do
        entryname.iaf(i):= entry.iaf(i+3); <* get entryname *>
        ok:= false;
        for i:= 1,i+1 while i <= no_of_entries and -,ok do
            if entryname(1) = names(i,1) and
               entryname(2) = names(i,2) then 
               ok:= entry_found(i):= true;
      end;
    end;
    entry_ok:= ok;
  end entry_ok;
\f

 
  
  procedure initbases;
  begin
    integer array iarr(1:8);
    system(11)catalog bases:(i,iarr);
    ownbase(1):= iarr(1);
    ownbase(2):= iarr(2);
    if -,base then
    begin
    base_lower:= (case scopetype of (-8388607,iarr(7),iarr(5)));
    base_upper:= (case scopetype of (8388605 ,iarr(8),iarr(6)));
    end;
  end;
\f



    procedure set_catbase (base);
    integer array          base ;

    <***********************************************************>
    <*                                                         *>
    <* The procedure changes the catalog base of own process   *>
    <* to the base given.                                      *>
    <* If the result becomes 4 : new base illegal, it is sup-  *>
    <* posed that the new base is outside the max base of the  *>
    <* process and the procedure will set cat base to max base.*>
    <*                                                         *>
    <* Call : set_catbase (entry);                             *>
    <*                                                         *>
    <* base         (call value, integer array). The new base  *>
    <*              in base (1:2).                             *>
    <*                                                         *>
    <***********************************************************>


    begin
      own
      boolean             called_before;

      integer             i;
      integer array       own_bases (1:8);
      integer             result;
      integer array field max;

      zone                z (1, 1, stderror);

      if -,called_before then
      begin
        called_before := true;
        reset_catbase; <*init reset catbase*>
      end;

      open  (z, 0, <::>, 0); <*own process*>
      close (z, true);

      for i := 1, 2 do own_bases (i) := base (i);
      <*to avoid fielding in call of system*>

      result := monitor (72, z, 0, own_bases);

      if result = 4 then
      begin <*outside max*>
        max := 12; <*fields max base in own_bases (7:8)*>

        system (11 )bases:( 0, own_bases);
        set_catbase (own_bases.max);
      end <*outside max*> else
      if result <> 0 then
        system (9, result, <:<10>cat base:>);

    end set_catbase;

\f




    procedure reset_catbase;

    <***********************************************************>
    <*                                                         *>
    <* The procedure resets the catbase of own process         *>
    <* to the original catbase before the first change         *>
    <* of catbase by a call of set_catbase.                    *>
    <*                                                         *>
    <***********************************************************>

    begin
      own
      boolean             called_before;

      own
      integer             catbase_lower, catbase_upper;

      if -,called_before then
      begin <*save catbase and init branch*>
        called_before := true;

        catbase_lower := ownbase (1);
        catbase_upper := ownbase (2);

        reset_catbase;
      end else
      begin <*set catbase*>
        integer array catbase (1:2);

        catbase (1) := catbase_lower;
        catbase (2) := catbase_upper;

        set_catbase (catbase);
      end <*set catbase*>;

    end reset_catbase;

\f

 
  procedure read_base_params;
  begin
    integer array iarr(1:8);
    integer type;
    type:= 5; <* name or integer *>
    if next_param(par,paramno,type,false) then
    begin
      if type = 4 <* returnvalue - integer *> then
      begin
        base_lower:= round par(1);
        if next_param(par,paramno,4,false)
           then base_upper:= round par(1)
           else writeerror(<:upper base is missing:>);
        if base_upper < base_lower then
        writeerror(<:'upper-base' is less than 'lower-base':>);
      end
      else
      begin <* returnvalue - text *>
        basetype:= if par(1) = real<:syste:> add 109   then 1 else
                   if par(1) = real<:proje:> add 99    and
                      par(2) = real<:t:>               then 2 else
                   if par(1) = real<:user:>            then 3 else 0;

        if basetype = 0 then
        writeerror(<:'base' must be 'system','project' or 'user':>)
        else
        begin
          system(11)process bases:(i,iarr);
          base_lower:= (case basetype of (-8388607,iarr(7),iarr(5)) );
          base_upper:= (case basetype of (8388605 ,iarr(8),iarr(6)) );
        end;
      end
    end
    else
      writeerror(<:'base-params' are incomplete:>);
  end read_base_params;
\f

  
  procedure call_save(displ);
  value               displ ;
  integer             displ ;
  begin
    zone zcat(128,1,caterror);
    integer k,i,first_slice;
    integer array core,chain_start(1:1);
    long array entryname(1:2);
    real array from_docname(1:2);
    boolean anywhere,listing,found,head;

    area:= found:= true;
    base:= scope:= head:= listing:= checkread:= false;
    basetype:= firstentryname:= scopetype:=  segments:= slices:= entries:= 0;
    no_of_entries:= 1;
    paramno:= 1+displ;
    docname(1):= docname(2):= 0;
    todevno:= -1;
    while next_param(par,paramno,1,false) do
    begin
      case convert_param(par) of
      begin
  
        begin <* from *>
          if next_param(par,paramno,2,false) then
          begin
            from_docname(1):= docname(1):=  par(1);
            from_docname(2):= docname(2):=  par(2);
          end
          else
            write_error(<:no document-name :>);
        end;
        
   
        begin <* to *>
          if next_param(par,paramno,4,false)
             then todevno:= round par(1)
             else write_error(<:no device-number:>);
        end;
  
  
        begin <* scope *>
          scope:= true;
          if todevno < 0 then
          writeerror(<:to.<devno> must be specified before scope:>);
          if next_param(par,paramno,2,false)
             then check_scope
             else writeerror(<:'scope'-parameters are incomplete:>);
        end;
  
   
        begin <* base *>
           base:= true;
           if todevno < 0 then
           writeerror(<:to.<devno> must be specified before base:>);
           read_base_params;
        end;
  
  
        begin <* list *>
             if next_param(par,paramno,2,false) then
             begin
               if par(1) <> real<:no:> and
                  par(1) <> real<:yes:>
                  then writeerror(<:listoption must be 'yes' or 'no':>)
                  else listing:= par(1) = real<:yes:>;
             end
             else
               writeerror(<:no listoption:>);
        end;
  
  
        begin <* checkread *>
          set_checkread;
        end;


        begin <* entrynames *>
          if todevno < 0 then
          writeerror(<:to.<devno> must be specified before entrynames:>)
          else
          begin
            firstentryname:= paramno-1;
            no_of_entries:= 1;
            while next_param(par,paramno,1,false) do no_of_entries:= no_of_entries+1;
          end
        end entrynames;
  
      end case;
    end while-loop;
  
    begin
    real array names(1:no_of_entries,1:2);
    boolean array entry_found(1:no_of_entries);
    if todevno < 0 then
    writeerror(<:to.<devno> must be specified :>);
    if firstentryname > 0 then
    begin
      paramno:= firstentryname;
      for i:= 1 step 1 until no_of_entries do
      begin
        next_param(par,paramno,1,false);
        names(i,1):=  par(1);
        names(i,2):=  par(2);
        entry_found(i):= false;
      end;
    end;
    if -,base and -,scope then scopetype:= 1; <* default scope.system *>
    anywhere:= docname(1) = 0;
    if -,anywhere then
    begin
      if get_dev_or_name(true,devno,docname,auxname,chain_addr)
          then writeerror(<:source disc does not exist:>);
    end;
    kiton(todevno,docname,1,true,true); <* include to-device *>
    for i:= 1 step 1 until 4 do ia(17+i):= docname.iaf(i);
    initbases;
    i:= 1;
    if listing then write(out,<:<12><10>entries saved on :>,
                              string act_docname(increase(i)),<::<10><10>:>,
                              <:entryname           :>,
                              <:size   lower-base   upper-base:>);
    i:= 1;
    open(zcat,4,if anywhere then <:catalog:> else string auxname(increase(i)),1 shift 18);
    comment scan catalog ( auxiliary or maincat );
 
    for i:= inrec6(zcat,34) while i > 0 do
    begin <* check entry *>
      if zcat.iaf(1) <> -1 <* used catalog entry *> then
        begin
        fromname(1):= zcat.areaname(1);
        fromname(2):= zcat.areaname(2);
        if entry_ok(zcat,names,entry_found) then
        begin <* entry ok - try to save it *>
          zone z(1,1,stderror);

          set_catbase (entry_base);
          i:= 1;
          open(z,0,string fromname(increase(i)),0);
          monitor(76)head and tail:(z,0,ia);
          close(z,false);
          reset_catbase;
          if -,anywhere then
          begin <* the entry is checked to be ok so far - check if  *>
                <* correct document                                 *>
        
            first_slice:= ia(1) shift (-12) extract 12;
            if first_slice >= 2048 <* non area entry *> then
            begin <* compute chain table address *>
              system(5,92,core);
              system(5,core(1) + (first_slice - 2048),chain_start);
              found:= chain_start(1) = chain_addr;
            end
            else
              found:= from_docname.iaf(1) = ia(9)  and
                      from_docname.iaf(2) = ia(10) and
                      from_docname.iaf(3) = ia(11) and
                      from_docname.iaf(4) = ia(12);
          end;
          if found then
          begin
              open(z,0,<::>,0);
              set_catbase (entry_base);
              k:= monitor(120)create aux entry:(z,0,ia);
              reset_catbase;
              if k <> 0 then
              begin
                if k = 3 <* nameoverlap *> then
                begin
                  i:= 1;
                  write(out,<:<10>entry already exists in auxcat ::>,
                            string fromname(increase(i)) );
                  if -,fp_mode then setposition(out,0,0) else
                    errorbits := 1 shift 1; <*warning.yes ok.yes*>
                end
                else
                begin
                  close (zcat, true);
                  kitoff (docname);
                  dump_actual_names (to_devno);
                  result(120, <::>, fromname,k,true);
                end;
              end
              else
              begin
                entries:= entries+1;
                if listing then list_entry(zcat,0);
                set_catbase (entry_base);
                if ia(8) > 0 <* area describing entry *> then
                begin
                  close(z,false);
                  getzone(z,zdescr);
                  for i:= 2 step 1 until 5 do toname.iaf(i-1):=zdescr(i);
                  copyarea(0,0,maximum);
                  segments := segments +  ia (8); <*size*>
                  slices   := slices   + (ia (8) - 1) // slicelength + 1;
                end
                else
                begin <* remove area process *>
                  close(z,true);
                  monitor(64)remove process:(z,0,ia);
                end;
                reset_catbase;
              end;
          end;
        end;
      end;
    end while_loop;
  
    close(zdisc,true);
    close(zcat,true);
    kitoff(docname);
    dump_actual_names(todevno);
 
    if entries > 0 then
    begin
      write(out,<:<10><10>:>,<<dddd>,entries,<: entries,   :>,
                <<dddddddd>,segments,<: segments<10>:>,<<dddd>,
                slices,<: slices *:>,slicelength,<: =:>,<<ddddd>,
                slices*slicelength,<: segments<10><10>:>);
      if -,fp_mode then setposition(out,0,0);
    end;
 
    if firstentryname > 0 then
    begin <* check if all entries are saved *>
      for i:= 1 step 1 until no_of_entries do
      if -,entry_found(i) then
      begin
        if -,head then
        begin
          write(out,<:<10>***entries not found :<10>:>);
          errorbits := 1 shift 1; <*warning.yes, ok.yes*>
          head:= true;
          j:= 0;
        end;
        entryname(1):= long names(i,1);
        entryname(2):= long names(i,2);
        j:= j + write(out,false add 32,2,entryname);
        if j > 65 then begin j:= 0; typetext(<:<10>:>) end;
      end;
      typetext(<:<10>:>);
    end;
   end;
   
  end call_save;
\f

 
  
  procedure call_load(displ);
  value               displ ;
  integer             displ ;
  begin
    integer array tail(1:10),core,chain_start(1:1);
    long array entryname(1:2);
    real array wrkname,name,fromkitname,old_docname(1:2);
    integer i,k,pos1,pos2,first_slice,act_chain_addr;
    boolean listing,head,ok;
    zone zwrk,z(1,1,stderror),zcat(128,1,caterror);
    basetype:= scopetype:= segments:= slices:= entries:= 0;
    area:= true;
    base:= scope:= head:= listing:= checkread:= false;
    firstentryname:= 0;
    no_of_entries:= 1;
    paramno:= 1+displ;
    docname(1):= docname(2):= 0;
    fromdevno:= -1;
    while next_param(par,paramno,1,false) do
    begin
      case convert_param(par) of
      begin
  
        begin <* from *>
          if next_param(par,paramno,4,false)
             then fromdevno:= round par(1)
             else writeerror(<:no 'from'-devicenumber:>);
        end;
  
        begin <* to *>
          if next_param(par,paramno,2,false) then
          begin
            docname(1):=  par(1);
            docname(2):= par(2);
          end
          else
            writeerror(<:no 'to'-documentname:>);
        end;
  
        begin <* scope *>
          scope:= true;
          if docname(1) = 0 then
          writeerror(<:to.<docname> must be specified before scope:>)
          else
          if fromdevno < 0 then
          writeerror(<:from.<devno> must be specified before scope:>)
          else
          begin
            if next_param(par,paramno,2,false)
               then check_scope
               else writeerror(<:'scope'_parameters are incomplete:>);
          end;
        end;
  
        begin <* base *>
          base:= true;
          if docname(1) = 0 then
          writeerror(<:to.<docname> must be specified before base :>)
          else
          if fromdevno < 0 then
          writeerror(<:from.<devno> must be specified before base :>)
          else
          read_base_params;
        end;
  
        begin <* list *>
          if next_param(par,paramno,2,false) then
          begin
            if par(1) <> real<:no:> and
               par(1) <> real<:yes:> 
               then writeerror(<:listoption must be 'yes' or 'no':>)
               else listing:= par(1) = real<:yes:>;
          end
          else
            writeerror(<:no listoption :>);
        end;

        begin <* checkread *>
          set_checkread;
        end;

        begin <* entrynames *>
          if docname(1) = 0 then
          writeerror(<:to.<docname> must be specified before entrynames:>)
          else
          if fromdevno < 0 then
          writeerror(<:from.<devno> must be specified before entrynames:>)
          else
          begin
            firstentryname:= paramno-1;
            no_of_entries:= 1;
            while next_param(par,paramno,1,false) do
                  no_of_entries:= no_of_entries+1;
          end
        end entrynames;
  
      end case;
    end while-loop;
  
    begin
      real array names(1:no_of_entries,1:2);
      boolean array entry_found(1:no_of_entries);
      for i:= 1 step 1 until no_of_entries do entry_found(i):= false;
      if docname(1) = 0 or fromdevno < 0 then
      writeerror(<:from.<devno> and to.<docname> must be specified:>);
      if firstentryname > 0 then
      begin
        paramno:= firstentryname;
        for i:= 1 step 1 until no_of_entries do
        begin
          next_param(par,paramno,1,false);
          names(i,1):=  par(1);
          names(i,2):=  par(2);
        end;
      end;
    if -,base and -,scope then scopetype:= 1; <* default scope.system *>
    if get_dev_or_name(true,devno,docname,auxname,act_chain_addr) then
    writeerror(<:object disc not included in bs-system:>);
    initbases;
    kiton(fromdevno,fromkitname,1,false,true); <* entries are not inserted *>
    <* get name of auxcat *>
    get_dev_or_name(true,fromdevno,fromkitname,auxname,chain_addr);
    i:= 1;
    if listing then write(out,<:<12><10>entries loaded to :>,
                              string docname(increase(i)),<::<10><10>:>,
                              <:entryname           :>,
                              <:size   lower-base   upper-base:>);
    i:= 1;
    open(zcat,4,string auxname(increase(i)),1 shift 18);
    comment scan auxiliary catalog;
 
inrec_entry:
  
    for i:= inrec6(zcat,34) while i > 0 do
    begin
      if zcat.iaf(1) <> -1 then
      begin
        if entry_ok(zcat,names,entry_found) then
        begin <* entry ok - load it *>
          toname(1):= zcat.areaname(1);
          toname(2):= zcat.areaname(2);
          set_catbase (entry_base);
          monitor(68)generate wrkname:(zwrk,0,entrybase);
          getzone(zwrk,zdescr);
          for j:= 2 step 1 until 5 do
          begin <* insert wrknames *>
            old_docname.iaf(j-1):= zcat.iaf(j+7);
            zcat.areaname.iaf(j-1):= fromname.iaf(j-1):= zdescr(j);
            zcat.iaf(j+7):= fromkitname.iaf(j-1);
          end;
          <* insert entry with workname *>
          k:= monitor(104)insert entry:(zdisc,0,zcat.iaf);
          reset_catbase;
          if k <> 0 then
          begin
            if k = 6 <* claims exceeded *> then
            begin <* remove entries inserted with wrknames *>
              getposition(zcat,pos1,pos2);
              close(zcat,true);
              close(zdisc,true);
              kitoff(fromkitname);
              kiton(fromdevno,fromkitname,1,false,true);
              get_dev_or_name(true,fromdevno,fromkitname,auxname,chain_addr);
              j:= 1; open(zcat,4,string auxname(increase(j)),1 shift 18);
              setposition(zcat,pos1,pos2);
              goto inrec_entry;
            end
            else
            begin
              close (zcat, true);
              kitoff (from_kitname);
              result(104, <::>, toname,k,true);
            end;
          end;
          for j:= 1 step 1 until 10 do tail(j):= zcat.iaf(j+7);
          j:= 1;
          open(z,0,string toname(increase(j)),0);
          set_catbase (entry_base);
          if monitor(76)head and tail:(z,0,ia) = 0 and
             extend ia(2) = extend entrybase(1)    and
             extend ia(3) = extend entrybase(2)    then
          begin <* entry included - change it if correct document *>
                reset_catbase;
               first_slice:= ia(1) shift (-12) extract 12;
               if first_slice >= 2048 <* non area entry *> then
               begin <* compute chain table address *>
                 system(5,92,core);
                 system(5,core(1) + (first_slice-2048),chain_start);
                 ok:= chain_start(1) = act_chain_addr;
                 if ok then
                 for j:= 1 step 1 until 4 do
                 tail(j+1):= old_docname.iaf(j); <* insert correct document *>
               end
               else
                 ok:= ia(9)  = docname.iaf(1) and
                      ia(10) = docname.iaf(2) and
                      ia(11) = docname.iaf(3) and
                      ia(12) = docname.iaf(4);
  
               if ok then
               begin
                 set_catbase (entry_base);
                 monitor (44) change entry :(z, 0, tail);
                 reset_catbase;
               end else
               begin
                 close (z, false);
                 j:= 1;
                 write(out,<:<10>entry already included from another document : :>,
                           string toname(increase(j)) );
                 if -,fp_mode then setposition(out,0,0) else
                   errorbits := 1 shift 1; <*warning.yes, ok.yes*>
                 goto inrec_entry;
               end;
          end
          else
          begin <* entry does not exist - create on document specified *>
            reset_catbase;
            for j:= 1 step 1 until 4 do
            tail(j+1):= if zcat.iaf(8) < 0 then old_docname.iaf(j)
                                            else docname.iaf(j);
            set_catbase (entry_base);
            j:= monitor(40)create entry:(z,0,tail);
            reset_catbase;
            if j <> 0 then
            begin
              close (zcat, true);
              kitoff (from_kitname);
              result(40, <::>, toname,j,true);
            end;
            set_catbase (entry_base);
            j:= monitor(90)perm into auxcat:(z,3,docname.iaf);
            reset_catbase;
            if j <> 0 then
            begin
              close (zcat, true);
              kitoff (from_kitname);
              result(90, <::>, toname,j,true);
            end;
          end;
          if listing then
          begin
            for j:= 1 step 1 until 4 do
              zcat.areaname.iaf(j):= toname.iaf(j);
            listentry(zcat,0);
          end;
          set_catbase (entry_base);
          if zcat.iaf(8) > 0 <* area describing entry *> then
          begin
            copyarea(0,0,maximum);
            segments := segments + zcat.iaf (8);
          end;
          entries := entries + 1;
           close(z,true);
           reset_catbase;
         end;
       end;
     end while_loop;
  
     close(zdisc,true);
     close (zcat,true);
     kitoff(fromkitname);
     
     if entries > 0 then
     begin
       write(out,<:<10><10>:>,<<dddd>,entries,<: entries,   :>,
                 <<dddddddd>,segments,<: segments<10>:>);
       if -,fp_mode then setposition(out,0,0);
     end;
  
  
     if firstentryname > 0 then
     begin <* check if all entries are loaded *>
       for i:= 1 step 1 until no_of_entries do
       if -,entry_found(i) then
       begin
         if -,head then
         begin
           write(out,<:<10>***entries not found:<10>:>);
           errorbits := 1 shift 1; <*warning.yes, ok.yes*>
           head:= true;
           j:= 0;
         end;
         entryname(1):= long names(i,1);
         entryname(2):= long names(i,2);
         j:= j + write(out,false add 32,2,entryname);
         if j > 65 then begin j:= 0; typetext(<:<10>:>) end;
       end;
       typetext(<:<10>:>);
     end;
    end;
  end call_load;
  
\f

 
  procedure call_bin(displ);
  value              displ ;
  integer            displ ;
  begin
    boolean all,all_from,all_to;
    integer no_of_devices,physical_disc__addr,i, maincatdev, mainautodev;
    integer array core(1:2), main (1:1), proc (1:30);
    real array       main_name, mainautoname (1:2);
    long array field laf;

    all_from:= all_to:= all:= area:= checkread:= false;
    todevno:= fromdevno:= -1;
    laf := 0;
    paramno:= displ + 1;
    if -,next_param(par,paramno,1,false) then
    begin <* no parameters - copy specified parts of discpacks *>
      call_spec;
      goto if fp_mode then endprogram else nextline;
    end
    else paramno:= paramno-1;
    while next_param(par,paramno,1,false) do
    begin
      case convert_param(par) of
      begin
      
       begin <* from *>
          next_param(par,paramno,4,false);
          fromdevno:= round par(1);
          par(1):= real<:all:>;
          par(2):= real<::>;
          <* all-param is optional *>
          if next_param(par,paramno,2,true) then all:= all_from:= true;
       end;
  
       begin <* to *>
         next_param(par,paramno,4,false);
         todevno:= round par(1);
         par(1):= real <:all:>; <* all-param is optional *>
         par(2):= real<::>;
         if next_param(par,paramno,2,true) then all:= all_to:= true;
       end;;;;
   
        begin <* checkread *>
          set_checkread;
        end;

       begin
         i:= 1;
         write(out,<:illegal parameter : :>,string par(increase(i)));
         if fp_mode 
            then goto after_error
            else
            begin
               setposition(out,0,0);
              goto nextline;
            end;
       end;
      end case;
    end while-loop;
  
    if todevno < 0 or fromdevno < 0 
       then writeerror(<:to.<devno> and from.<devno> must be specified:>);

    system (5) move core :(           98, core); <*chaintable maincatdev*>
    system (5) move core :(core (1) - 10, core); <*name table address   *>
    system (5) move core :(core (1)     , core); <*proc descr address   *>
    system (5) move core :(core (1) +  2, main_name); <*proc name       *>
    system (5) move core :(core (1) + 10, main     ); <*main process    *>

    maincatdev := device_number (core (1)); <*device number*>

    system(5)move core area:(74,core);
    no_of_devices:= (core(2) - core(1))//2 ;
    begin
      integer array       device_addr(0:no_of_devices - 1);
      boolean array       remember (0 : no_of_devices - 1);
      boolean             error, maincatdev_wr_enabled;
      integer array field iff;

      iff := -2;

      for i := 0 step 1 until no_of_devices - 1 do
      begin
        remember (i) := false;

        j := process_description (i, proc);

        if (proc ( 1) = 62
        or  proc ( 1) =  6)                  and
            proc ( 6) = main (1)             and
            proc (15) =  0 <*first segment*> then
        begin <*autoload disc on same physical as maincat disc*>
          main_auto_dev := i;
          system (5) move core :(j + 2, main_auto_name);
        end;
      end;

      error := maincatdev_wr_enabled := false;
 
      <*decide whether or not to be copied from or to physical disc *>
      system(5)move core area:(core(1),device_addr.iff);

      <*get physical source disc*>
      physical_disc_addr := deviceaddr (fromdevno);

      system (5) move core :(deviceaddr (fromdevno), ia);

      if ia   (1) =  6 then
        system (5) move core :(ia (6), main); <*get main*>

      if ia   (1) = 62 <*disc not ida*>  and
         ia   (6) =  0 <*no     main *>
      or ia   (1) =  6 <*disc     ida*>  and
         main (1) = 20 <*main is  ida*> then
      begin <*from device is itself a physical disc*>
        physical_disc_addr := device_addr (fromdevno);
        all := all_from := true;
      end else
      if ia   (1) = 62 <*disc not ida*>  and
         ia   (6) >  0 <*has  a main *>
      or ia   (1) =  6 <*disc     ida*>  and
         main (1) =  6 <*main is  ida*> then
        physical_disc_addr := ia (6); <*main*>

      if all_from then
      begin <*get dev no of physical disc*>
        for devno := 0 step 1 until no_of_devices - 1 do
          if device_addr (devno) = physical_disc_addr then
          begin
            from_devno := devno;
            devno      := noofdevices;
          end;

        system (5) move core :(physical_disc_addr, ia);
        if ia (1) = 6 then
        begin <*ida, pack it off*>
          trap (on_again);
          packoff (fromdevno, false) <*no power down*>
        end else
        begin <*not ida*>

          for devno := 0 step 1 until no_of_devices - 1 do
          begin <*kitoff logical discs on the physical*>
            system (5) move core :(deviceaddr (devno), ia);
        
            if (ia (1) = 62 <*disc not ida*>
            or  ia (1) =  6 <*disc     ida*>) and
                ia (6) = physical_disc_addr  then
            begin
              if -,getdevorname (false, devno, docname, auxname,
                                                        chainaddr) then
              begin
                if -,kitoff ( docname) then
                begin
                  write (out,
                  "nl", 1, true, 12, docname.laf, <: dismounted from :>,
                  <<ddd>, devno);
                  typetext (<:<10>:>);
        
                  trap (on_again);
                  remember (devno) := true;
                end;
              end;
            end;
          end <*kitoff*>;
        end <*not ida*>;

      end <*get device number of physical source disc*>;

      <*get physical object disc*>
      system (5) move core :(deviceaddr (todevno), ia);

      if ia (1) =  6 then
        system (5) move core :(ia (6), main);

      if ia   (1) = 62 <*disc not ida*>  and
         ia   (6) =  0 <*has  no main*>
      or ia   (1) =  6 <*disc     ida*>  and
         main (1) = 20 <*main is  ida*> then
      begin <*to device is itselt a physical disc*>
        physical_disc_addr := device_addr (todevno);
        all := all_to := true;
      end else
      if ia   (1) = 62 <*disc not ida*>  and
         ia   (6) >  0 <*has a main  *>
      or ia   (1) =  6 <*disc     ida*>  and
         main (1) =  6 <*has a main  *>  then
        physical_disc_addr := ia (6);

      if all_to then
      begin <*get device no of physical disc*>
        for devno := 0 step 1 until no_of_devices - 1 do
          if deviceaddr (devno) = physical_disc_addr then
          begin todevno := devno; devno := noofdevices; end;
      end <*get*>;

      if all then
      begin
        write(out,<:<10>source disc: :>,fromdevno,
                  <:<10>object disc: :>,todevno,<:<10>:>);
        if -,fp_mode then setposition(out,0,0);
      end;

      toname (1) := 0;
      if connect (todevno, toname) then
        type_text (<:<10>object disc not connected<10>:>)
      else
      begin <*todev connected*>
        if -,get_dev_or_name (false, fromdevno, docname, auxname, chainaddr) then
        begin
          if -,kitoff (docname) then
          begin
            write (out,
            "nl", 1, true, 12, docname.laf, <: dismounted from :>,
            <<ddd>, fromdevno);
            typetext (<:<10>:>);

            trap (on_again);
            remember (fromdevno) := true;
          end;
        end;

        fromname (1) := 0;
        if connect (fromdevno, fromname) then
          type_text (<:<10>source disc not connected<10>:>)
        else
        begin <*fromdev connected*>
          copyarea (0, 0, maximum);

          write (out,
          "nl", 1, <:copying terminated:>,
          "nl", 1, <:number of segments copied : :>,
          <<ddddddd>, totalsegments);

          typetext (<:<10>:>);
        end <*fromdev connected*>;
      end <*todev connected*>;

      on_again:

      trap (0);

      <*check if disc with maincat is wr enabled*>

      maincatdev_wr_enabled :=
        if mainautoname (1) shift (-24) extract 24 = 0 then
          -,connect (mainautodev, mainautoname)
        else
          true;
      
      if maincatdev_wr_enabled then
      begin <*connectable*>
        zone z (128, 1, check_malfnc);
      
        procedure check_malfnc (z, s, b);
        zone                    z       ;
        integer                    s, b ;
        begin
          if s extract 1 = 1 then
            stderror (z, s, b)
          else
          begin
            maincatdev_wr_enabled := false;
            b := 512;
            s :=   0;
          end;
      
        end check_malfnc;
      
        laf := 0;
        open (z, 6, main_auto_name.laf, 60); <*dummy answer*>
        monitor (8) reserve :(z, 1, core);
      
        maincatdev_wr_enabled := true;
        inrec_6 (z, 512);
        setposition (z, 0, 0);
        outrec6 (z, 512);
        close (z, true); <*release process*>
      
      end <*connectable*>;
      
      if -,maincatdev_wr_enabled then
        write (out,
        "nl", 1,
        <:notice : disc with main catalog disconnected or write protected:>)
      else
      if all_from then
      begin <*if ida then packon again*>
        system (5) move core :(device_addr (from_devno), ia);
      
        if ia (1) = 6 <*ida disc*> then
          pack_on (from_devno, false, 5); <*no power up, list.warning*>
      end;
      
      if remember (maincatdev) or main_cat_rem then
      begin <*write enabled and dismounted*>
        kiton (maincatdev, docname, 4 <*list error*>, true <*insert bs*>,
               false <*wrk name*>);
      
        for i := 1 step 1 until 4 do
          ia (17 + i) := docname.iaf (i);
      
        i := monitor (106) insert bs :(out, 0, ia);
      
        if i <> 0 then
          result (106, <::>,  docname, i, false);
      
        remember (maincatdev) := false;
        write (out,
        "nl", 1, true, 12, docname.laf,
        if i <> 0 then <: not:> else <::>,
        <: mounted on :>, <<ddd>, maincatdev);
      end <*write enabled and dismounted*>;
      
      typetext (<:<10>:>);

      if maincatdev_wr_enabled then
      begin <*kit on discs previously kitted of*>

        for devno := 0 step 1 until no_of_devices - 1 do
        if remember (devno) then
        begin
          kiton (devno, docname, 4 <*list error*>, true <*insert entries*>,
                                                false <*wrk name*>);

          for i := 1 step 1 until 4 do
            ia (17 + i) := docname.iaf (i);

          i := monitor (106) insert bs :(out, 0, ia);

          if i <> 0 then
            result (106, <::>,  docname, i, false);

          remember (devno) := false;

          write (out,
          "nl", 1, true, 12, docname.laf,
          if i <> 0 then <: not:> else <::>, <: mounted on :>, <<ddd>, devno);
          typetext (<:<10>:>);
        end;

      end <*kit on discs previously kitted off*>;

      if error then
        goto if fpmode then aftererror else nextline;
    end;
  
  end call_bin;
\f

  
  
  procedure call_kiton;
  begin
    integer list,k;
    long array field laf;
    zone z(1,1,stderror);
    list:= 5; <*list.warning as default*>
    laf := 0;

    paramno:= 1;
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real <:devno:> then
      begin
        if next_param(par,paramno,4,false)
           then devno:= round par(1)
           else writeerror(<:device-number is missing:>);
      end
      else
        writeerror(<:first parameter must be devno.<devno> :>);
    end
    else
      writeerror(<:no parameters:>);
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real<:list:> then
      begin
        if next_param(par,paramno,2,false) then
        begin
          if par(1) = real<:no:>            then            else
          if par(1) = real<:yes:>           then list:= 2   else
          if par(1) = real<:nonsy:> add 115 then list:= 3   else
          if par(1) = real<:error:>         then list:= 4   else
          if par(1) = real<:warni:> add 110 and
             par(2) = real<:g:>             then list:= 5   else
          writeerror(<:illegal list-option :>);
        end
        else
          writeerror(<:listoption is missing:>);
      end
      else
      begin
        i:= 1;
        write(out,<:unknown parameter : :>,string par(increase(i)));
        if fp_mode
           then goto after_error
           else
           begin
              setposition(out,0,0);
             goto next_line;
           end;
      end;
    end;
    kiton(devno,fromname,list,true,false);
    for i:= 1 step 1 until 4 do ia(17+i):= fromname.iaf(i);
    k:= monitor(106)insert bs:(z,0,ia);
    if k <> 0 then result(106, <::>, fromname,k, false);
    write(out,"nl", 2, true, 12, fromname.laf,
    if k <> 0 then <: not:> else <::>, <: mounted on :>,<<ddd>,devno,<:<10>:>);
    if -,fp_mode then setposition(out,0,0);
  
  end call_kiton;
  
\f

   
  procedure call_kitoff;
  begin

    long array field laf;

    laf := 0;

    paramno:= 1;
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real<:devno:> then
      begin
        if next_param(par,paramno,4,false)
           then devno:= round par(1)
           else writeerror(<:device-number is missing:>);
      end
      else
        writeerror(<:first parameter must be devno.<devno>:>);
    end
    else
      writeerror(<:no parameters:>);
  
    if -,get_dev_or_name(false,devno,docname,auxname,chain_addr) then
    begin
      if -,kitoff (docname) then
      begin
        write (out,
        "nl", 1, true, 12, docname.laf, <: dismounted from :>,
        <<ddd>, devno);
        typetext (<:<10>:>);
      end;
    end;
  
  end call_kitoff;

\f


  procedure mount_disc;
  begin
    integer list;

    list:= 5; <*list.warning as default*>
    paramno:= 1;
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real <:devno:> then
      begin
        if next_param(par,paramno,4,false)
           then devno:= round par(1)
           else writeerror(<:device-number is missing:>);
      end
      else
        writeerror(<:first parameter must be devno.<devno> :>);
    end
    else
      writeerror(<:no parameters:>);
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real<:list:> then
      begin
        if next_param(par,paramno,2,false) then
        begin
          if par(1) = real<:no:>            then            else
          if par(1) = real<:yes:>           then list:= 2   else
          if par(1) = real<:nonsy:> add 115 then list:= 3   else
          if par(1) = real<:error:>         then list:= 4   else
          if par(1) = real<:warni:> add 110 and
             par(2) = real<:g:>             then list:= 5   else
          writeerror(<:illegal list-option :>);
        end
        else
          writeerror(<:listoption is missing:>);
      end
      else
      begin
        i:= 1;
        write(out,<:unknown parameter : :>,string par(increase(i)));
        if fp_mode
           then goto after_error
           else
           begin
              setposition(out,0,0);
             goto next_line;
           end;
      end;
    end;

    pack_on (devno, true, list); <*power up*>

  end procedure mount_disc;

  procedure pack_on (devno, power_up, list);
  value              devno                 ;
  integer            devno,           list ;
  boolean                   power_up       ;
  begin
    
    integer k, disc_count, disc_descr_size, disc;
    integer first_segment, segments, type, log_devno;
    integer array field log_entry;
    long    array field laf;
    integer field count_f;
    integer array field iaf;
    real array field raf;
    real array za (1:128);

    zone z(128,1,stderror);

    laf := 0;

    process_description (devno, ia);

    if ia(1)<>6 then
    begin
      writeerror (<:not connected or not ida disc:>);
    end;
    raf:= 2; iaf:= 0;
    tofrom (docname, ia.raf, 8);
    if ia(8) shift (-12) <> 0 then
    write_error (<:not physical disc:>);
    if docname.iaf(1) = 0 then
    begin
      if connect (devno, docname) then
      begin
        if fp_mode then goto after_error
        else goto next_line;
      end;
    end;

    open (z, 0, docname, 0);

    if power_up then
    begin
      monitor (8, z, i, ia);
      getshare6 (z, shdescr, 1);
      for i:= 4 step 1 until 7 do shdescr(i):= 0;
      shdescr(4):= 10 shift 12 + 0; <* power up spindle *>
      setshare6 (z, shdescr, 1);
      i:= 1;
      monitor (16, z, i, ia); <* send message *>
      i :=
      monitor (18, z, i, shdescr); <* wait answer *>
      monitor (10, z, 0, ia);
      if i<>1 then result(-1, <:power up spindle:>, docname, i, true);
    end;

    setposition (z, 0, 0);
    inrec6 (z, 512);
    tofrom (za, z, 512);
    close (z, false);
    process_description (devno, ia);
    system (5, ia(6), ia);
    tofrom (docname, ia.raf, 8);
    open (z, 0, docname, 0);

    count_f := 2; <* files in autoload description *>
    count_f := (za.count_f*4) + 4; <* logical disc files *>
    disc_descr_size := za.count_f shift (-12) extract 12;
    disc_count      := za.count_f             extract 12;

    log_entry:= count_f;

    for disc:= 1 step 1 until disc_count do
    begin comment linkup logical discs;
      first_segment:= za.log_entry(1);
      segments:= za.log_entry(2);
      type:= za.log_entry(3) shift (-12);
      log_devno:= za.log_entry(3) extract 12;
      getshare6 (z, shdescr, 1);
      shdescr(4):= 16 shift 12 + (type extract 1); <* link logical disc *>
      shdescr(5):= log_devno;
      shdescr(6):= devno;
      shdescr(7):= first_segment;
      shdescr(8):= segments;
      setshare6 (z, shdescr, 1);
      i:= 1;
      monitor(16, z, i, ia);
      i:= monitor(18, z, i, ia);
      if i<>1 then
      begin
        write (out, <:<10>linkup logical disc, devno=:>, << dd>, log_devno,
                    <:, on device=:>, devno,
                    <:, result=:>, i);
        if fp_mode then goto after_error else
        begin
          setposition (out, 0, 0);
          goto next_line;
        end;
      end;
      log_devno:= ia(2);
      if type shift (-1) = 1 then
      begin comment catalog on disc;
        kiton(log_devno,fromname,list,true,false);
        for i:= 1 step 1 until 4 do ia(17+i):= fromname.iaf(i);
        k:= monitor(106)insert bs:(z,0,ia);
        if k <> 0 then result(106, <::>, fromname,k, false);

        write (out,
        "nl", 2, true, 12, fromname.laf,
        if k <> 0 then <: not:> else <::>, <: mounted on :>, <<ddd>, logdevno);
        typetext (<:<10>:>);
      end else
      begin comment disc has no katalog;
        real array docname (1:2);
        docname(1):= real<::>;
        if connect (log_devno, docname) then
        begin
          if fp_mode then goto after_error else
          begin
            setposition (out, 0, 0);
            goto next_line;
          end;
        end;

        write (out,
        "nl", 1, true, 12, docname.laf, <: mounted on :>, <<ddd>, logdevno); 
        typetext (<: - no auxcat -<10>:>);
        if -, fp_mode then setposition (out, 0, 0);
      end;
      log_entry:= log_entry + disc_descr_size;
    end;
    close (z, false);
    if -,fp_mode then setposition(out,0,0);
  end pack_on;
  
\f

   
  procedure remove_disc;
  begin

    paramno:= 1;
    if next_param(par,paramno,1,false) then
    begin
      if par(1) = real<:devno:> then
      begin
        if next_param(par,paramno,4,false)
           then devno:= round par(1)
           else writeerror(<:device-number is missing:>);
      end
      else
        writeerror(<:first parameter must be devno.<devno>:>);
    end
    else
      writeerror(<:no parameters:>);
  
    pack_off (devno, true); <*power down*>

  end procedure remove_disc;

  procedure pack_off (devno, power_down);
  value               devno             ;
  integer             devno             ;
  boolean                    power_down ;
  begin
    integer log_devno, next_logical, log_disc;
    long    array field laf;
    integer array field iaf;
    real array field raf;

    zone z (1, 1, stderror);

    laf := 0;

    next_logical:= process_description (devno, ia)+22;
    if ia(1)<>6 then write_error (<:not connected or not ida disc:>);
    if ia(8) shift (-12)<>0 then write_error (<:not physical disc:>);
    system (5, ia(6), ia);
    raf:= 2;iaf:= 0;
    tofrom (docname, ia.raf, 8);
    open (z, 0, docname, 0);
    system (5, next_logical, ia);
    log_disc:= ia(1);
      close (z, false);
    while log_disc > 0 do
    begin
      system (5, log_disc, ia);
      tofrom (docname, ia.raf, 8);
      log_devno:= device_number (log_disc);
      if ia(8) shift (-13) extract 11 = 1 then
      begin
        if -,kitoff (docname) then
        begin
          write (out,
          "nl", 1, true, 12, docname.laf, <: dismounted from :>, 
          <<ddd>, logdevno);
          typetext (<:<10>:>);
        end;
      end;
      getshare6 (z, shdescr, 1);
      for i:= 4 step 1 until 8 do shdescr(i):= 0;
      shdescr(4):= 18 shift 12 + 0; <* unlink logical disc *>
      shdescr(5):= log_devno;
      setshare6 (z, shdescr, 1);
      i:=1;
      monitor (16, z, i, shdescr);
      i:= monitor (18, z, i, ia);
      if i<>1 then
      begin
        result (-1, <:unlink logical disc:>, docname, i, false);
      end;
      system (5, next_logical, ia);
      log_disc:= ia(1);
    end;
    process_description (devno, ia);
    tofrom (docname, ia.raf, 8);
    if docname.iaf(1)=0 then connect (devno, docname);

    if power_down then
    begin
      open (z, 0, docname, 0);
      close (z, false);
      monitor (8, z, i, ia);
      getshare6 (z, shdescr, 1);
      for i:= 4 step 1 until 5 do shdescr(i):= 0;
      shdescr(4):= 12 shift 12 + 0; <* power down spindle *>
      setshare6 (z, shdescr, 1);
      i:= 1;
      monitor (16, z, i, ia);
      i:= monitor (18, z, i, ia);
      if i<>1 then result (-1, <:power down spindle:>, docname, i, false);
      monitor (10, z, 1, ia);
    end <*power down*>;
  
  end pack_off;
\f

   
  
  procedure call_kitlabel;
  begin
    integer field devno,catsize,slicelength,size,catfirst,catlast,
                  lastslice,i,segm;
    boolean field slicerel;
    integer kind;
    integer array ia(1:1);
    long array    name,auxname(1:2);
    zone          disc(128,1,stderror);
  
    procedure discerror(z,s,b);
    zone z; integer s,b;
    begin
      own boolean aftererror;
      if aftererror then stderror(z,s,b);
      aftererror:= true;
      goto again;
    end;
 
    paramno:= 1;
    if next_param(par,paramno,3,false) then
    begin
      devno:= round par(1); <* devicenumber *>
      if next_param(par,paramno,1,false) then
      begin
        name(1):= long par(1);
        name(2):= long par(2) shift (-8) shift 8; <* max 11 chars *>
      end
      else
        writeerror(<:no documentname:>);
        if next_param(par,paramno,1,false) then
        begin
          auxname(1):= long par(1);
          auxname(2):= long par(2) shift (-8) shift 8 ; <* max 11 chars *>
        end
        else
          writeerror(<:no auxcat-name:>);
    end
    else
      writeerror(<:no device-number:>);
    next_param(par,paramno,1,false);
    if par(1) = real<:slow:> then kind:= 1 else
    if par(1) = real<:fast:> then kind:= 0 else
    writeerror(<:kind must be 'slow' or 'fast':>);
    for i:= 1 step 1 until 3 do
    begin
      if next_param(par,paramno,3,false) then
      begin
        case i of
        begin
          catsize:= round par(1);
          slicelength:= round par(1);
          size:= round par(1);
        end;
      end
      else
        case i of
        begin
          writeerror(<:catsize-param is missing:>);
          writeerror(<:slicelength-param is missing:>);
          writeerror(<:size-param is missing:>);
        end;
    end for-loop;
 
 
again:
  
 

    <* compute first, last slice of aux cat *>
    catfirst := (( 34                  <* size of chainhead *>
                 + size                <* size of chaintable *>
                 + 511) // 512         <* counted in segments *>
                + slicelength - 1      <* round up *>
                ) // slicelength;
    catlast  := catfirst + (catsize - 1) // slicelength;
    <* compute last slicenumber of disc *>
    lastslice:= size - 1;
    open(disc, 0, <::>, 0);
    <* create peripheral process, wrk-name *>
    monitor(54, disc, devno, ia);
    <* reserve process *>
    monitor(8 , disc, 0    , ia);
    <* prepare chainhead *>
    outrec6(disc, 34);
    for i := 2 step 2 until 34 do
       disc.i := case i shift (-1) of
               (catfirst shift 12 +kind shift 3 + 3<*1st catslice,kind*8+key*>
               , -8388607                        <* lower catalog interval *>
               ,  8388606                        <* upper catalog interval *>
               , auxname.iaf(1)                  <* auxcat name *>
               , auxname.iaf(2)
               , auxname.iaf(3)
               , auxname.iaf(4)
               , catsize                         <* size of auxcat *>
               , name.iaf(1)                     <* document name *>
               , name.iaf(2)
               , name.iaf(3)
               , name.iaf(4)
               , 0                               <* not used *>
               , slicelength
               , lastslice shift 12 + 0          <* last slice of disc, 
                                                    first of chain*>
               , (-1) shift 12 + 0               <* auxcat, zero *>
               , 0                               <* zero, zero *>
               );
   
    <* initialize chain for chaintable + auxcat *>
    outrec6(disc, outrec6(disc, 0));
    for slicerel := 1 step 1 until catlast do
       disc.slicerel := false add 1;
       disc.slicerel := false;

    <* clear space between cahintable and catalog *>
    outrec6(disc, 0);  <* change buffer *>
    getposition(disc, 0, segm);
    for segm := segm step 1 until catfirst * slicelength - 1 do
      outrec6(disc, 512);

    <* write empty auxcat *>
    setposition(disc, 0, catfirst * slicelength);
    for segm := 1 step 1 until catsize do
    begin
       outrec6(disc, 512);
       for i := 2 step 2 until 510 do
          disc.i := -1;    <* unused catalog entries *>
          disc.i := 0;     <* entry count *>
       end;

    <* terminate last block and release disc *>
    close(disc, true);


    goto if fp_mode then endprogram else nextline;
  end call_kitlabel;
\f

  
  
  
  
  procedure call_kitname;
  begin <* rename document and auxiliary catalog *>
    paramno := 1;
    if next_param(par,paramno,3,false) then
    devno:= round par(1)
    else writeerror(<: devicenumber is missing :>);
  
    if next_param(par,paramno,1,false) then
    begin
      actdocname(1):= par(1);
      actdocname(2):= par(2);
    end
    else writeerror(<:documentname is missing:>);
  
    if next_param(par,paramno,1,false) then
    begin
      actauxname(1):= par(1);
      actauxname(2):= par(2);
    end
    else writeerror(<:auxcatname is missing:>);
 
    if -,get_dev_or_name(false,devno,docname,auxname,chain_addr) then kitoff(docname);
    dump_actual_names(devno);
  
  end call_name;
\f

 
  procedure call_spec;
  begin <* used for copying specified parts of devices *>
    
    typetext(<:to device: :>);               typein(todevno);
    typetext(<:start segment: :>);           typein(tosegm);
    typetext(<:from device: :>);             typein(fromdevno);
    typetext(<:start segment: :>);           typein(fromsegm);
    typetext(<:number of segments: :>);      typein(number_of_segments);
    if -,get_dev_or_name(false,todevno,toname,auxname,chain_addr) then kitoff(toname);
    if -,get_dev_or_name(false,fromdevno,fromname,auxname,chain_addr) then kitoff(fromname);
    toname(1):= 0;         connect(todevno,toname);
    fromname(1):= 0;       connect(fromdevno,fromname);
    copyarea(tosegm,fromsegm,extend number_of_segments);
    write(out,<:<10>copying terminated<10>:>,
              <:number of segments copied: :>,<<ddddddd>,
              totalsegments-(if shdescr(4) shift (-12) = 3 <* input *>
              then fromsegm else tosegm) );
    typetext(<:<10>:>);
  
  end;

  procedure set_checkread;
  begin

    if next_param (par, paramno, 2, false) then
    begin
      if par (1) = real <:yes:>
      or par (1) = real <:no:>  then
        checkread := par (1) = real <:yes:>
      else
        write_error (<:checkread option must be 'yes' or 'no':>)
    end else
      write_error (<:checkread.yes or checkread.no:>);

  end set_checkread;
\f

   
  
                             <* m a i n  p r o g r a m *>
  
   
  open(zhelp,0,<::>,0);
  trapmode:= 0; <* write all alarms *>
  trap(after_error);
  maximum:= 10 000 000;
  maincat_rem:= false;
  area:= false;
  areaname:= 6;
  ok:= false;
  iaf:= 0;
  permkey:= 3;
  scopetype:= 0;
  scope:= base:= false;
  space_name:= 4 shift 12 + 10;
  point_name:= 8 shift 12 + 10;
  space_integer:= 4 shift 12 + 4;
  point_integer:= 8 shift 12 + 4;
  fp_mode:= true;
  checkread := false;
  kind(0):= 7; <* delimiter *>
  ra(0):= 32 ; <* space *>

  base := true;
  init_bases;
  base := false;

  reset_catbase; <*to initialize reset catbase*>
  
  <* decide name of program *>
  system(4,0,par);
  tofrom(program,par,8);
  case convert_to_number(par) of
  begin
  
    begin <* disccopy *>
      paramno:= 1;
      next_param(par,paramno,1,false);
      <* decide action *>
      type:= convert_to_number(par);
      if type < 9 then type:= 13;
      case type-8 of
      begin
        call_save(1);
        call_load(1);
        call_bin(1) ;
        begin <* enter conversational mode *>
          fp_mode:= false;
          lockall;
          <* modify standardalphabet *>
          outtable(alphabet,127);
          for i:= 39,43,46 do alphabet(i):= 7 shift 12 + i;
          intable(alphabet);
          tableindex:= 0;
nextline: morelines:= true;
          start_pos:= 1;
 
          while morelines do
          begin <* read lines of command *>
            setposition(in,0,0);
            i:= readall(in,ra,kind,start_pos);
            if i < 0 then
            begin <* array bounds exceeded *>
              write(out,<:<10>command too long - last line skipped<10>:>);
              if -,fp_mode then setposition(out,0,0);
              kind(start_pos):= 8; <* terminates inf. in 'ra' and 'kind'*>
              morelines:= false;
            end
            else
            begin <* check if current line terminates command *>
              for i:= 0,i+1 while round ra(i) = 32 do;
              if kind(i) = 8 then goto nextline; <* skip if no command *>
              for i:= startpos,i+1 while kind(i) <> 8 do;
              last:= i;
              ra(last):= 32;
              kind(last):= 7;
              for i:= i,i-1 while kind(i) = 7 and round ra(i) = 32 do;
              if (kind(i) = 7 and round ra(i) = 44) <* comma *> then
              begin
                ra(i):= ra(i+1):= 32; <* space *>
                kind(i):= kind(i+1):= 7;
                startpos:= i+1;
              end
              else
              begin
                morelines:= false;
                kind(last):= 8;
              end;
            end;
          end while_loop;
  
          <* start execution of command *>
            paramno:= 0;
            next_param(par,paramno,1,false);
            case convert_to_number(par) of
            begin
              <* disccopy ignored *> ;
              call_kitname;
              call_kiton;
              call_kitoff;
              mount_disc;
              remove_disc;
              call_kitlabel;
              goto endprogram; <* end *>
              call_save(0);
              call_load(0);
              call_bin(0);
              <* typein ignored *> ;
              begin <* unknown command *>
                i:= 1;
                write(out,<:<10>illegal command : :>,
                      string par(increase(i)),<:<10>:>);
                if -,fp_mode then setposition(out,0,0);
              end;
            end case;
          close(zdisc,true);
          goto nextline;
        end conv_mode;
 
        begin <* unknown fpparameter *>
          i:= 1;
          write(out,<:<10>***disccopy: unknown fpparameter : :>,
                string par(increase(i)));
          goto endprogram;
        end;
      end case;
    end disccopy;
 
    call_kitname;
  
    call_kiton;
  
    call_kitoff;

    mount_disc;

    remove_disc;
  
    call_kitlabel;

    <*8*>;

    <*9*>;

    <*10*>;

    <*11*>;

    <*12*>;

    write(out,<:<10>unknown program name: :>,program);
 
  end case;
  
  goto end_program;
  
 
after_error: errorbits:= 3; <*warning.yes, ok.no*>

  may_be_device_status (out);
 
endprogram:
 
end;
▶EOF◀