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

⟦139ddcae6⟧ TextFile

    Length: 92160 (0x16800)
    Types: TextFile
    Names: »tcatupdate«

Derivation

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

TextFile


(boptions = set 100 disc
boptions = slang lister.no
scope user boptions
print boptions words.2 integer 0.2)
s. a20 w.
77 11 02, 57 ; version id:
     a0, a1     ; top of devices, number devices
     a2         ; max number of private disc kits
     a3         ; no of free disc drives
p. <:options:>  ;  ...include boss 2 options...

a0 = e24+e17    ; define top of devicelist
a1 = e17        ; no of devices
a2 = i30        ; max no of private disc kits
a3 = i29-1      ; no of free disc drives.........
c.i27,a3=a3-1 z.; ..........
e.e.


(catupdate = set 100 disc
catupdate = algol spill.yes list.no xref.no
scope user catupdate
)
\f


<*  bbj   9 9 76                                               catupdate  ...1...  *>

begin
comment this program is intended to create and update
   the usercat, nescessary for the boss2-operating-system.

   there are several comments throughout the program, in
   order to facilitate the understanding of the text, but
   for certain of the actions, the reader is kindly
   requested to confer with the actual boss2-program-text.
   (this is especially recommended for reading the option-
   actions (because they are - more or less - directly translated
   from slang into algol6).)

   apart from this, i have used long variable-names, instead
   of having comments...;
\f


<*  bbj   9 9 76                    description of catalog     catupdate  ...2...  *>

<*

                                                               bbj 15-1-76

                     The usercatalog in Boss

The usercatalog is built as an hierarchical structure of subcatalogs with
each subcatalog consisting of records of varying length. These records
describe all the information available in the catalog.
The catalog is placed on the system disc with the name USERCAT and is re-
served by the operating system BOSS. The catalog is terminated by a re-
cord of type 0 and with a project number 2**23-1 (described later).
The first segment(s) is (are) used as an index to gain faster access to
the catalog.
The first word of the index table is the maximum number of permanent ca-
talog entries which are promised to the projects in the usercatalog (in
negative representation). If there exist more than one index segment the
next word will contain -1. The number of words with -1 is the number of 
index segments -1. The following words contain the number of the project 
with the highest number on that segment. The address of the segment is 
the number of the index word (absolute segment addressing).
The following figure illustrates how the indextable and the catalog en-
tries work


                            Usercat
                !                              !
                !------------------------------! --
             0  ! - no. of catalog entries     !   !
                !------------------------------!   !
             2  !                       -1     !   !
                !------------------------------!   !
segment 1    4  !   (project number)     0     !   !
                !------------------------------!   !
             6  !         do             0     !   !
                !------------------------------!   !
             8  !         do             1     !   !
                !------------------------------!   !
                !                              !   !
       ---------!         .                    !   >    index table
segment 2       !         .                    !   !
                !         .                    !   !
                !------------------------------!   !
                !                    2**23-1   !   !
                !------------------------------!   !
                !                    2**23-1   !   !
       ---------!------------------------------!---!
                !                              !
segment 3       !                              !
                !------------------------------!
                !  inf. about project 0        !
       ---------!------------------------------!
                !                              !
                !                              !
segment 4       !------------------------------!
                !  inf. about project 0        !
       ---------!------------------------------!
                !                              !
                !                              !
segment 5       !------------------------------!
                !  inf. about project 1        !
       ---------!------------------------------!
                !                              !
                !                              !


Each record describes a piece of information for a project or a user. The
records have the common feature that the two first bytes describe the 
type and the length of the record.
Type 0 and type 2 are special records. Type 0 describes the projects and
type 2 the users within the projects. All common information and resour-
ces are gathered under a type 0 record and all information for each user
is gathered under a type 2 record.
All information about projects and users are necessary in the catalog, 
all other types of records are optional.
The following is a list of all the record types and for each type the 
meaning of each byte (word) of the record.
Many of the records are concerned with different claims (for instance
disc or drum) with both a standard value and a maximum value, therefore
the record types can assume two values an even integer if standard va-
lues are used and an odd integer if maximum values are used. If only one
of the two types can be used the record is marked with a *.
More information about the catalog can be found in ref1 ch4 p2-3, ref2 
ch1 p1-3 and ref3 ch7.
\f


    bbj   9 9 76                    records in the catalog     catupdate  ...3...    

 

        
                    Record-types in the catalog

* type 0         project

   - 0 -         0, 12
   - 2 -         project number
   - 4 -         max-interval
   - 8 -         rest entries,  rest slices on disc
  - 10 -         total entries, total slices on disc

* type 2         user

   - 0 -         2, 16
   - 2 -         user name (8 bytes)
  - 10 -         user interval start
  - 12 -         standard interval length
  - 14 -         number of user indices

* type 4
 
   - 0 -         4, 6
   - 2 -         standard value of priority
   - 4 -         minimum value of late

* type 6         private disc kits

   - 0 -         6, 12
   - 2 -         device name
  - 10 -         rest entries,  rest slices
  - 12 -         total entries, total slices


  type 8
 
   - 0 -         8 , 6
   - 2 -         first word with device bits
   - 4 -         second word  -    -      -

  type 10        accounts               (ref1, ch2, p2)

   - 0 -         10, 4
   - 2 -         number of account buffers

  type 12        area processes         (ref1, ch2, p2)

   - 0 -         12, 4
   - 2 -         area claim

  type 14        mess. buffer         (ref1, ch2, p3)

   - 0 -         14, 4
   - 2 -         buffer claim

  type 16        convert operations     (ref1, ch2, p3)

   - 0 -         16, 4
   - 2 -         cbuf claim
\f


    bbj   9 9 76                    records in the catalog     catupdate  ...4...    

  type 18        internal processes     (ref1, ch2, p3)

   - 0 -         18, 4
   - 2 -         internal claim

  type 20        keys                   (ref1, ch2, p4)

   - 0 -         20, 4
   - 2 -         number of protection keys

  type 22        mounts                 (ref1, ch2, p5)

   - 0 -         22, 4
   - 2 -         number of mounts

  type 24        output                 (ref1, ch2, p6)

   - 0 -         24, 4
   - 2 -         number of output characters

  type 26        size                   (ref1, ch2, p7)

   - 0 -         26, 4
   - 2 -         number of bytes in core store

  type 28        stations               (ref1, ch2, p7)

   - 0 -         28, 4
   - 2 -         number of standard tape stations


  type 30         tapes                 (ref1, ch2, p4)

   - 0 -          30, 4
   - 2 -          number of papertapes to be loaded

  type 32         time                  (ref1, ch2, p8)

   - 0 -          32, 4
   - 2 -          net run time

* type 34         user with userpool
  
   - 0 -          34, 10
   - 2 -          user max interval
   - 6 -          rest entries, rest slices
   - 8 -          total entries, total slices

* type 36         drum, key 1

   - 0 -          36, 4
   - 2 -          entries, slices

* type 38         disc, key 1
 
   - 0 -          38, 4
   - 2 -          entries, slices
\f


    bbj   9 9 76                    records in the catalog     catupdate  ...5...    

* type 40         disc, key 3

   - 0 -          40, 4
   - 2 -          entries, slices

* type 42         output identification
 
   - 0 -          42 , variable length
   - 2 -          user name and address

* type 44         drum, key 3

   - 0 -          44, 6
   - 2 -          rest entries,  rest slices
   - 4 -          total entries, total slices

* type 46         drum, key 3

   - 0 -          46, 4
   - 2 -          user entries, slices

* type 48         special device, key 3

   - 0 -          48, 12
   - 2 -          device name
  - 10 -          user entries, slices

* type 50         max turn around time  (ref1, ch2, p4)

   - 0 -          50, 4
   - 2 -          maximum wait


  type 52         information for accountjob
 
   - 0 -          52, 16
   - 2 -          
                  project identification in textform
  - 14 -

* type 54         program

   - 0 -          54, 4
   - 2 -          name of program to be loaded

  type 56         available suspend buffers (ref1, ch2, p7)

   - 0 -          56, 4
   - 2 -          suspendings

  type 58         online
 
   - 0 -          58, 4
   - 2 -          conversational jobs allowed (0) / not allowed (1)

  type 60         corelock              (ref1, ch2, p3)

   - 0 -          60, 4
   - 2 -          corelock time
\f


    bbj   9 9 76                    records in the catalog     catupdate  ...6...    

  type 62         degree of information (ref1, ch2, p5)

   - 0 -          62, 4
   - 2 -          minimal yes (1) / no (0)

  type 64         priority

   - 0 -          64, 4
   - 2 -          start priority factor

  type 66         deliberate waiting    (ref1, ch2, p8)

   - 0 -          66, 4
   - 2 -          maximum wait time

  type 68         catalog preservation  (ref1, ch2, p6)

   - 0 -          68, 4
   - 2 -          preserve yes (1) / no (0)

  
  type 70         terminal user rights (privileges)

   - 0 -          70, 4
   - 2 -          privilege-bits
 
   type 72         link

    - 0 -         72,4
    - 2 -         no. of simultaneous used links


               References

(1)  Boss 2 Users Manual
(2)  Monitor 3
(3)  Boss 2 Installation and Maintenance
  
  
*>
\f


<*  bbj   9 9 76                    declarations               catupdate  ...7...  *>


real array     transname, vartransname, newcatname (1:2);
integer        max_devicenumber, max_option, max_record_type,
               worksize,
               std_usercat_index, max_no_of_disckits,
               intervaltable_size, varlength, maxlength,
               no_of_trans, no_of_vartrans, no_of_privkits,
               no_of_priv_discdrives;
boolean        nooldcat, leftside, updatetest;

comment definitions of standard-values ... may be changed;

max_devicenumber := 44;  comment length of devicelist;
max_option       := 26;  comment length of option-table;
max_record_type  := 72;
worksize        :=  8;  comment size of workareas;
std_usercat_index:=  2;  comment no of index segments in usercat;
max_no_of_disckits:=50;  comment length of kittable;
intervaltable_size := 200;
  comment i.e. max number of projects + greatest no of users in
          single project;
varlength        := 512//2;
  comment maxlength of username - 10 (in bytes...);
updatetest       := true;
  comment  testoutput is selected by the edit-command:
               g b/comment iiff updatetest/if updatetest/
  ;

begin
integer        print, no_of_devices;
integer array  devicenumber(1:max_devicenumber);
long    array  devicename(1:5);


begin

integer        projno, updateinf, usercatsegm,
               state, neutralstate, projectstate, userstate,
               linetype, inlinetype, linelength, freeparam, rectypelgth, typeofrec,valueofpar,
               paramno, number_of_params,
               first_paramno,
               first_free_proj, last,
                permanent_disc;

long           username1, username2, name,
               deviceword, maxdeviceword;

boolean        nosource,  list, userpool,
               device, maxdevice, project;

integer field  i, j, if2, if4, if12, basis, int1, int2, int3, int4,
               int5, int6, int7;

long field     lg6, lg10, long1, long2, lastoption, nameptr;

boolean field  p1;

integer array  p(0:10), line, kind(1:(varlength-10)//2), alphabettable(0:5*128-1),
               option(1:5*max_option+2);

real array     fpparam, fpparam1(1:2);

integer array field rec;

zone           in, trans, vartrans(128, 1, stderror);
\f


<*  bbj   9 9 76                   help procedures            catupdate  ...8...  *>

procedure output(z, length);
   zone z; integer length;
   comment the procedure initializes the next transaction-
      record, with project-number, username and recordtype
      and -length, and information whether creation, changing
      or deleting.
      furthermore the two special cases are handled:
       l. only checking of transactions (i.e. no leftside
          in program call)
       2. the transactions are allready sorted and may
          be used directly to form a new usercat.
      ;
   begin
   no_of_trans:= no_of_trans + 1;
      outrec6(z, length);
      z.if2:= projno;
      z.lg6:= username1;
   z.lg10:= username2;
   z.if12:= rectypelgth shift 4 add (if inlinetype<-1 then 0 else updateinf);
   z.basis:= rectypelgth;
   end;

procedure move_username(z, length);
   value length; zone z; integer length;
   comment the procedure moves the first parameter on the
      input line (i.e. the username) to the zone;
   begin
   j:= p(0) * 2;     comment start of text;
   last := p(1) * 2;  comment last of text;
   rectypelgth := rectypelgth + last - j + 2;
   output(z,length);

   i:= int1 - 2;
   for i:= i+2 while j <> last do
      begin comment move...;
      z.i := line.j;
      j := j+2;
      end;

   end move_username;

procedure checkparam(min, max, number, type);
   integer min, max, number, type;
   comment the procedure checks, that the number_of_params
      is within the limits min,max (incl.) and that all
      parameters are of legal type. (notice the jensen-device...).
      if any inconsistency is found the alarm-procedure
      is called;
   if number_of_params < min or number_of_params > max then
      alarm(<:number of params:>)
   else
   for number := 0 step 1 until number_of_params-1 do
      if type shift (-kind(p(number))) extract 1 = 0 then
         alarm(<:illegal type:>);
   comment notice: if the actual type contains ..1 shift m..
      it means, that an actual parameter with kind=m is
      legal...;

procedure alarm(text);
   string text;
   begin
   write(out, <:***:>, text, <:<10>:>);
   goto alarmprint;
   end;
\f


<*  bbj   9 9 76                    proc parameter error      catupdate  ...9...  *>

procedure parameter_error;
   comment if any parameter error is found in the fp-command, this procedure
      is called. it writes the faulty parameters on current
      output, and returns to ...next_source... with paramno
      pointing at the next parameter;
   begin
   write(out, <:  <10>***parameter error:  :>);
   for i:= system(4, paramno, fpparam),
           system(4, paramno, fpparam) while i shift (-12) = 8 do
      begin
      write(out, if i shift (-12) = 8 then <:.:> else <: :>);
      j := 1;
      if i extract 12 = 10 then
         write(out, string fpparam(increase(j)))
      else
         write(out, <<d>, fpparam(1));
      paramno := paramno + 1;
      end;
   write(out, <:<10>:>);
   goto next_source;
   end parameter_error;

  procedure testvalues(rectype,val1);
  value rectype,val1; integer rectype,val1;
  <* the routine checks the parametervalues for byte/word 
     overflow/underflow where it is possible
  *>
  begin integer i,j;
    j:=rectype//2;
    if j>max_record_type then
    begin write(out,<:<10>case out of range in testvalues<10>:>); goto exittest;
    end;
    i := case j of
         (3,3,3,3,1,1,1,1,1,1,
          1,2,2,1,1,2,3,3,3,3,
          3,3,3,3,2,3,3,1,3,2,
          3,1,2,3,3,1
         );
    <* i-value :
       1- the parameter must be within a byte
       2-  -    -        -    -    -   a word
       3-  no check
    *>

    case i of
    begin
      <*1*> if (val1<0) or (val1>=4095) then
            write(out,<: ***value should not exceed a byte:>);

      <*2*> if (val1<0) or (val1>=8388607) then
            write(out,<: ***value should not exceed a word:>);

      <*3 - nothing *> ;
    end case i;
  exittest:
  end proc testvalues;
\f


<*  bbj   9 9 76                    initialization             catupdate  ...10...  *>




comment initialization of fields in transaction-records;
   if2 := 2; if4 := 4; lg6 := 6; lg10 := 10;  if12 := 12;

comment standard values of program options;
   nooldcat:= false;
   list   := false;

   nosource :=  true;
   print := 0;  comment no listing of usercatalog;

comment initialize state-values;
   neutralstate := 1 - (-1) * 3;  comment (=1-(smallest type)*3);
   projectstate := 1 + neutralstate;
   userstate    := 1 + projectstate;
   state        := neutralstate;

comment initialize the primitive interval-routine, in case
   of newcat-mode;
   first_free_proj := 1 shift 23 + 2;
   usercatsegm := std_usercat_index;   comment number of indexsegments;


comment initialize the charactertable for reading of username;
   for i := 0 step 1 until 5*128-1 do alphabettable(i) := 0;
   for i := 33 step 1 until 125 do
      alphabettable(i) := 1 shift 12 + 128; comment shift-chars;
   for i := 12, 25, 59 do
      alphabettable(i) := 1 shift 12 + 256;   comment shift back;
   for i := 32 step 1 until 125 do
      alphabettable(i+128) := 6 shift 12 + i;   comment normal chars;
   alphabettable(10) := 6 shift 12 + 10;
   for i := 10+128, 12+128, 25+128, 59+128 do
      alphabettable(i) := 1 shift 12 + 0;   comment shift chars;
   alphabettable(95) := 6 shift 12 + 32;    comment underline is space;

comment initialize the charactertable for reading of normal lines;
   for i := 97 step 1 until 125 do
      alphabettable(i+256) := 6 shift 12 + i; comment letters;
   for i := 9, 14 step 1 until 94,
             96, 126 do
      alphabettable(i+256) := 7 shift 12 + i; comment delimiters;
   for i := 9, 32 step 1 until 125 do
      alphabettable(i+384) :=
      alphabettable(i+512) := 7 shift 12 + i;
   for i := 48 step 1 until 57 do
      alphabettable(i+256) := 2 shift 12 + i; comment digits;
   for i := 43, 45 do
      alphabettable(i+256) := 3 shift 12 + i; comment sign;
   for i := 10, 12, 25 do
      alphabettable(i+256) := 8 shift 12 + i; comment terminators;
   alphabettable(40+256) := 1 shift 12 + 384; comment shift-char;
   alphabettable(59+256) := 1 shift 12 + 512; comment shift-char;
   for i := 10, 12, 25 do
      alphabettable(i+384) :=
      alphabettable(i+512) := 1 shift 12 + 256; comment shift back;
   alphabettable(41+384) := 1 shift 12 + 256; comment shift back;
   for i := 0 step 128 until 512 do
      alphabettable(26+i) := 7 shift 12 + 38; comment sub char;

   intable(alphabettable);  tableindex := 256;
\f


<*  bbj    9 9 76                    initialization of optiontable  catupdate  ...11...  *>


comment initialization of the option table:
   each entry contains:
    1. option name
    2. action number
    3. legal parametertypes for this option (3 bytes)
       (notice: 1 shift m means that parameters, whose
        readall-kind (-value) is m, are legal)
    4. recordtype in usercat
    5. recordlength in usercat
   ;

   begin
   integer type_2, type_6, type_8, type_2_6, type_2_8;
   boolean field byte;

   procedure pack(optionname, actionno, partype1,
                  partype2, partype3, rectype, reclength);
      string optionname;
      integer actionno, partype1, partype2, partype3,
              rectype, reclength;

      begin comment the procedure packs the parameters
               in the next free elements of the option table;
      option.lastoption := long optionname;
      byte := lastoption;
      for i := actionno, partype1, partype2, partype3,
               rectype, reclength do
         begin
         byte := byte + 1;
         option.byte := false add i;
         end;
      lastoption := lastoption + 10;
      end pack;

   type_2   := 1 shift 2;       comment integer parameter;
   type_6   := 1 shift 6;       comment text parameter;
   type_8   := 1 shift 8;       comment end of line;
   type_2_6 := type_2 + type_6; comment integer or text parameter;
   type_2_8 := type_2 + type_8; comment integer param or end of line;

   lastoption := 4;
   pack(<:acco:>, 1, type_2, type_8, type_8, 10, 4);
   pack(<:area:>, 1, type_2, type_8, type_8, 12, 4);
   pack(<:buf:> , 1, type_2, type_8, type_8, 14, 4);
   pack(<:cbuf:>, 1, type_2, type_8, type_8, 16, 4);
   pack(<:core:>, 1, type_2, type_8, type_8, 60, 4);
   pack(<:devi:>, 2, type_2_6, type_8, type_8, 8,6);
   pack(<:inte:>, 1, type_2, type_8, type_8, 18, 4);
   pack(<:key:> , 1, type_2, type_8, type_8, 20, 4);
   pack(<:late:>, 3, type_2, type_2_8, type_8,50,4);
   pack(<:mini:>, 9, type_6, type_8, type_8, 62, 4);
   pack(<:moun:>, 1, type_2, type_8, type_8, 22, 4);
   pack(<:onli:>, 9, type_6, type_8, type_8, 58, 4);
   pack(<:outp:>, 1, type_2, type_8, type_8, 24, 4);
   pack(<:perm:>, 7, type_6, type_2, type_2, 40, 4);
   pack(<:pres:>, 9, type_6, type_8, type_8, 68, 4);
   pack(<:prio:>, 1, type_2, type_8, type_8, 64, 4);
   pack(<:priv:>, 4, type_2, type_8, type_8, 70, 4);
   pack(<:prog:>, 5, type_6, type_8, type_8, 54,10);
   pack(<:link:>, 1, type_2, type_8, type_8, 72, 4);
   pack(<:size:>, 1, type_2, type_8, type_8, 26, 4);
   pack(<:stat:>, 1, type_2, type_8, type_8, 28, 4);
   pack(<:susp:>, 1, type_2, type_8, type_8, 56, 4);
   pack(<:tape:>, 1, type_2, type_8, type_8, 30, 4);
   pack(<:temp:>, 8, type_6, type_2, type_2_8,36,4);
   pack(<:time:>, 6, type_2, type_2_8, type_2_8, 32, 4);
   pack(<:wait:>, 1, type_2, type_8, type_8, 66, 4);

   comment now lastoption points at a place just after the
           the option names;

   end initialize option table;

\f


<*  bbj   9 9 76                    initialization                 catupdate  ...12...  *>


comment initialize the tables of system devices,
   to be used by the action ..device..;

   for i := 1 step 1 until 5 do
      devicename(i) := long (case i of
      (<:    :>, <:prin:>, <:card:>, <:punc:>, <:plot:>));
   open(trans, 4, <:boptions:>, 0);
   inrec6(trans, 4);
   write(out, <:<12><10>; catupdate version:>, trans.if2, trans.if4, <:<10><10>:>);
   inrec6(trans, 508);
   no_of_devices := trans.if4;
   p1 := trans.if2-4;  comment top of devicelist...;
   rec:= 0;
   no_of_privkits:= trans.rec(3);
   no_of_priv_discdrives:= trans.rec(4);
   for i:=1 step 1 until no_of_devices do
      begin
      devicenumber(i) := trans.p1 extract 11 - trans.p1 shift(-11) extract 1 shift 11;
      p1 := p1 - 1;
      end;
   close(trans, true);


comment initialize the transaction-zone and update
   the newcat-option...;

   for i:= 3 step 1 until 10 do line(i):= 0;
   open(trans, 4, <::>, 0);
   line(1) := worksize;
   line(2) := 1;  comment pref. disc;
   monitor(40) create entry:(trans, 0, line);
   open(vartrans, 4, <::>, 0);
   line(1):= line(2):= 1;
   monitor(40) create entry:(vartrans, 0, line);
   getzone6(trans, line);
   for i:= 1, 2 do 
      transname(i):= real<::> add line(i*2) shift 24 add line(i*2+1);
   getzone6(vartrans, line);
   for i:= 1,2 do
      vartransname(i):= real<::> add line(i*2) shift 24 add line(i*2+1);
\f


<*  bbj   9 9 76                    fp-command                    catupdate  ...13...  *>

<*  examination of the fp-command *>
<*  ----------------------------- *>


comment examine the parameter list:
   1. if there is a leftside parameter, the transaction
      zone is connected to the specified area
      (and the option ..leftside.. is set to true)
   2. if the first parameter group is  cat.yes  the
      transactions are not merged with the old usercat
      (and the option ..newcat.. is set to true)
   ;

paramno := 1;  comment point at a possible programname;

i := system(4, paramno, fpparam);  comment get parameter 1 ;

leftside := false;

if i = 6 shift 12 + 10 <* = followed by a name *> then
   begin
   leftside:= true;
   system(4, 0, newcatname); <*leftside := newcatname *>
   paramno:= paramno + 1;
   i:= system(4, paramno, fpparam); <* fpparam := catupdate *>
   end;

   first_paramno := paramno + 1;

comment now paramno is the number of the first real parameter,
   and fpparam contains the parameter, while  i  contains the
   parameterhead...;

comment test if the first parameter group is  cat.yes...;

if if i = 4 shift 12 + 10 <* . followed by a name *> then fpparam(1) = real <:cat:> else false then
   begin comment the parameter group may be  cat.yes  ;
   if system(4, paramno + 1, fpparam) = 8 shift 12 + 10
      and fpparam(1) = real <:yes:>
      and system(4, paramno + 2, fpparam) shift (-12) <> 8 then
      begin
      paramno := paramno + 2;
      nooldcat:= true;
      end cat.yes;
   end first parameter = <:cat:>;

comment initialize fields in transaction records;
   basis := 14;
   int1 := 2 + basis;
   int2 := 4 + basis;  long1 := int2;
   int3 := 6 + basis;
   int4 := 8 + basis;  long2 := int4;
   int5 := 10+ basis;
   int6 := 12+ basis;
   int7 := 14+ basis;

   maxlength := int7;  comment last byte of longest record;
   maxlength := ((maxlength + 3) // 4) * 4; comment must be a
      multiple of 4 bytes;
   no_of_trans:= no_of_vartrans:= 0;
\f


<*  bbj   9 9 76                    fp-command                    catupdate  ...14...  *>


comment initialize the input zone, and update the list-option...;

next_source:      ; comment
***************   ;

comment paramno is the number of the next fpparameter;

i := system(4, paramno, fpparam);  comment get the parameter;

if i = 0 then
   begin comment the list is empty;
   if nosource then
      print := 1 shift 3;  comment print all catalog...;
   linetype := -1;  comment simulate a finis-record;
   goto select;
   end;

if i <> 4 shift 12 + 10 <* space followed by name *> then parameter_error;

i := system(4, paramno + 1, fpparam1);  comment examine the following
   parameter...;

if i shift (-12) = 8 then
   begin comment parameter group ... must be  list.on  or  list.off;
   if i = 8 shift 12 + 10 <* . and name follows *>
      and fpparam(1) = real <:list:>
      and system(4, paramno + 2, fpparam) shift (-12) <> 8 then
      begin
      list := fpparam1(1) = real <:on:>;
      paramno := paramno + 2;
      goto next_source;
      end list.on or list.off
   else
      parameter_error;
   end parameter group;

comment the parameter is the name of the next source;

paramno := paramno + 1;

nosource :=  false;
if paramno = first_paramno then
   system(9, 0, <:<10>***call :>);
close(in, true);

i := 1; open(in, 4, string fpparam(increase(i)), 0);

comment examine if it is something else than a backing store area;

i := monitor(42, in, 1, line);  comment lookup entry;

if i = 0 and line(1) < 0 then
   begin comment it is a filedescriptor...;
   close(in, true); comment i.e. regret the open...;
   i := 2;
   open(in, line(1) extract 23, string (real <::> add
        line(increase(i)) shift 24 add line(increase(i))), 0);
   end;

comment position the input, according to the catalog entry...;

if line(1) > 0 or line(1) extract 12 = 4 or line(1) extract 12 = 18 then
setposition(in, line(7), line(8));
comment ... only in case of backing store area or mag.tape...;

goto first_line;

<* end fp-command *>
<* -------------- *>

\f


<*  bbj   9 9 76                    input                         catupdate  ...15...  *>


print_line:      ; comment
***************  ;

if list then
   begin

alarmprint:      ; comment
***************  ;

   write(out, <<d>, inlinetype);
   for i := 1 step 1 until (abs linelength)-1 do
      case kind(i) of
         begin
         comment kind 1; write(out, <:***number out of range:>);
         comment kind 2; write(out, <<d>, line(i));
         comment kind 3,4,5; ;;;
         comment kind 6;
            begin
            write(out, string (real <::> add
                  line(increase(i)) shift 24 add
                  line(increase(i))));
            i := i-1;
            end;
         comment kind 7; write(out, false add line(i), 1);
         end case kind;
   write(out, <:<10>:>);
  if inlinetype = 5 then testvalues(typeofrec,valueofpar);
   end print line;

comment reading of input ;
comment ---------------- ;

tableindex := 256;  comment select std alfabet;
for i := readchar(in, i) while i <> 8 do ;
   comment skip any possible line-rest;

first_line:      ; comment
***************  ;

if list then
   begin comment copy input until sign, digits or endline;
   for i:=readchar(in, j) while i<>3 and i<>2 and j<>25 do
      write(out, false add j, 1);
   repeatchar(in);
   end;

if read(in, inlinetype) = 0 then goto next_source;
repeatchar(in);
linetype := inlinetype;
if inlinetype = -1 then goto select;  comment finis-record;
linetype := abs linetype;
if linetype = 3 or linetype=12 then tableindex := 0; <* name and add or accounting *>
   comment this special alfabet skips the preceding
   spaces on a line, and terminates reading when
   a semicolon or end_medium char occurs;

linelength := readall(in, line, kind, 1);
repeatchar(in);
freeparam := linelength + 1;
if linetype > 12 or inlinetype < -1 then  alarm(<:illegal linetype:>);

if linelength < 0 then alarm(<:line too long:>);
if linetype = 0 then goto select;  comment end-record;
if linetype <> 3 and linetype <> 12 and linelength < 3 and linelength <> 0 then
   alarm(<:too few parameters on line:>);

comment check the type of the line;
\f


<*  bbj   9 9 76                    search kind                   catupdate  ...16...  *>


comment search the kind-array and find the start of the parameters ;
i := 1;
number_of_params := -1;

comment i is the element in ...kind... to be checked, while
   number_of_params is the corresponding parameter number in
   the line (notice: parameters are counted from 0...);

for number_of_params := number_of_params + 1 while kind(i) <> 8 do
   begin
   if number_of_params > 6 then alarm(<:too many parameters:>);
   if (1 shift 1 + 1 shift 2 + 1 shift 6) shift (-kind(i))
      extract 1 = 0 then
         number_of_params := number_of_params - 1
      else
         p(number_of_params) := i;
   comment if the kind of the element is not integer or text
      then skip the element, else indicate the start of the
      current parameter in the array ..p..
      in this way p(J) is the start index of parameter j of
      the current line;

   for i:= i+1 while kind(i) = kind(i-1) do ;
   comment skip the following elements with the same kind;
   end;
p(number_of_params) := i; comment the end_of_line element;


select:          ; comment
***************  ;

comment dependent of the type of the line, rectypelgth is
   initialized with the standard value. (each input line normally
   produces one record in the usercat). some of the special
   action may however set another rectypelgth;

comment:  linetype is in the range from -1 to 12 (both incl.)
    -1   0   1   2   3   4   5   6   7   8   9  10  11  12   ;

rectypelgth := case linetype+2 of
   (-1, -1,  0,  2, 42,  6, -1, -1,  4, 44, 34,  0,  2, 52)
      shift 12 add (case linetype+2 of
   (-1, -1, 12, 16,  0, 16,  0,  0,  6,  6,  0, 12, 16,  0) );

comment ... notice that the rectypelgth of linetype 0 is explicitly
   used at ...initsort... ;


comment select the corresponding action, depending on line type
   and state;

goto case linetype*3 + state of
   (initsort  , termproj  , termuser  ,
    print_line, termproj  , termuser  ,
    linetype1 , termproj  , termuser  ,
    linetype2 , termproj  , termuser  ,
    illegal   , linetype3 , linetype3,
    illegal   , linetype4 , linetype4,
    illegal   , linetype5 , linetype5,
    illegal   , linetype6 , linetype6,
    illegal   , linetype7 , linetype7,
    illegal   , linetype8 , linetype8,
    illegal   , illegal   , linetype9,
    linetype10, termproj  , termuser ,
    linetype11, termproj  , termuser ,
    illegal   , linetype12, linetype12);
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...17...  *>



linetype1:       ; comment  create project
***************            **************** ;

   checkparam(4, 5, 0, 1 shift 2); comment 4 or 5 integer parameters;
   if number_of_params = 4 and line(p(1)) = 0 then
      alarm(<:number of params:>);

   comment convert project width into primitive project
      interval...;
   p(5) := increase(freeparam);
   line(p(5)) := first_free_proj + line(p(4)) - 1;
   p(4) := increase(freeparam);
   line(p(4))  := first_free_proj;
   comment now: p(4) points at lower proj-interval,
                p(5) points at upper proj-interval;
   goto initproj;


linetype2:       ; comment  create user
***************            ************* ;

   checkparam(3, 5, i, if i=0 then 1 shift 6 else 1 shift 2);
      comment 3, 4 or 5 parameters, first is name, rest are integers;

   comment initialize standard values;
   if number_of_params = 3 then
      begin comment insert std job-interval-width;
      p(3) := increase(freeparam);
      line(p(3)) := 1;
      end;
   if number_of_params < 5 then
      begin comment insert std number of sim. jobs;
      p(4) := increase(freeparam);
      line(p(4)) := 10;
      end;

   comment compute primitive user interval;
   p(5) := increase(freeparam);
   line(p(5)) := first_free_proj;
   comment now: p(3) points at job-interval-width.
                p(4) points at number of simult. jobs,
                p(5) points at lower user interval;
   goto inituser;


linetype3:       ; comment  username record
***************            ***************** ;

   checkparam(1, 1, i, 1 shift 6);
      comment exactly one text parameter;

   comment:  the record is copied to a
      special file, vartrans, in order to facilitate the
      sorting of the transactions (because the sorting then
      may concentrate on fixlength records...);
   no_of_trans:= no_of_trans - 1;
   no_of_vartrans:= no_of_vartrans + 1;
      move_username(vartrans, varlength);
   goto print_line;
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...18...  *>


linetype4:       ; comment  resources on special disc-kits
***************            ******************************** ;

   checkparam(4, 4, i, if i=0 then 1 shift 6 else 1 shift 2);
      comment 4 parameters, the first is text, the rest integers;
   if -, project then userpool:= true;
   nameptr := p(0) * 2 + 2;  comment point at kit-name;
   if line.nameptr = long <:disc:> or
      line.nameptr = long <:drum:> then
      alarm(<:illegal devicename:>);
   output(trans, maxlength);
   trans.long1 := line.nameptr;
   nameptr := nameptr + 4;
   trans.long2 := if kind(p(0)+2) <> 6 then extend 0
                  else line.nameptr;
   trans.int5 :=
   trans.int6 := line(p(2)) shift 12 add line(p(1));
   trans.int7 := line(p(3));
   goto print_line;


linetype5:       ; comment  standard values for options
***************            ***************************** ;

linetype6:       ; comment  maximum values for options
***************            **************************** ;

   checkparam(2, 4, i, if i=0 then 1 shift 6 else -1);
      comment 2 to 4 parameters, the first is text,
         the rest may be anything;

   nameptr := p(0) * 2 + 2;  comment point at option name;
   name := line.nameptr shift (-16) shift 16;
      comment extract the first four letters...;
   option.lastoption := name;  comment insert last in table...;

   comment scan the option table to find the proper option...;
   nameptr := -6;
   for nameptr := nameptr + 10 while option.nameptr <> name do ;
   if nameptr = lastoption then
      alarm(<:option unknown:>);

   p1 := nameptr + 2;  comment point at first parameter type...;
   for i := 1 step 1 until 3 do
      begin comment check the parameters in the option line...;
      if kind(p(i)) = 8 then
         begin
         p(i+1) := p(i) + 1;
         kind(p(i+1)) := 8;
         end
      else
      if -, option.p1 shift (-kind(p(i))) then
         alarm(<:parameter kind:>);
      p1 := p1 + 1;
      end;
      i:= nameptr+5; <*point at recordtype*>
      typeofrec:= option.i shift (-12);

   i := nameptr + 6;  comment point at rectypelgth element;
   rectypelgth := option.i;
   if linetype = 6 then
      rectypelgth := 1 shift 12 + rectypelgth;
      comment maximum-value-records have an odd recordtype...;

   p1 := nameptr + 1; comment point at action-number byte;
   goto case option.p1 extract 12 of
      (action1, action2, action3, action4, action5,
       action6, action7, action8, action9);
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...19...  *>


linetype7:       ;  comment  jobpriority and respite
***************             ************************* ;
   <* used by older versions, does not exist in newer versions *>

   checkparam(2, 2, 0, 1 shift 2);
      comment 2 integer parameters;

   output(trans, maxlength);
   trans.int1 := line(p(0));  comment jobpriority;
   trans.int2 := (line(p(1)) * (extend 10000)) shift (-13);;  comment respite;
   goto print_line;


linetype8:       ;  comment  permanent drum
***************             **************** ;

   checkparam(2, 2, 0, 1 shift 2);
      comment 2 integer parameters;

   output(trans, maxlength);
   trans.int1 :=
   trans.int2 := line(p(1)) shift 12 add line(p(0));
   goto print_line;


linetype9:       ;  comment  userpool
***************             ********** ;

   checkparam(2, 2, 0, 1 shift 2);
      comment 2 integer parameters;

   permanent_disc :=
      permanent_disc + line(p(1)) shift 12 add line(p(0));
   userpool := true;
   goto print_line;


linetype10:      ;  comment  abs create proj
***************             ***************** ;

   checkparam(6, 6, 0, 1 shift 2);
      comment 6 integer parameters;

   goto initproj;
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...20...  *>


linetype11:      ;  comment  abs create user
***************             ***************** ;

   checkparam(6, 6, i, if i=0 then 1 shift 6 else 1 shift 2);
      comment 6 parameters, the first is text, the rest
         are integers;

   goto inituser;

linetype12:      ;  comment  project id (account inf.)
***************             *************************** ;

   checkparam(1, 1, 0, 1 shift 6);
      comment 1 text parameter;

   for i := p(1), i+1 while p(0)+7 > i do line(i) := 0;
   p(1) := p(0) + 7;
      comment extend the text into 21 chars...;
   move_username(trans, maxlength);
   goto print_line;


initproj:        ;  comment
***************  ;
   <* the parameter pointed at by p(1) is :
      0 - new project or user
      1 - change  -   -   -
      2 - delete  -   -  -
   *>

   projno := line(p(0));
   if projno < 0 or projno > 999999 then
      alarm(<:illegal projno:>);
   if line(p(1)) < 0 or line(p(1)) > 2 then
      alarm(<:illegal update identification:>);
   updateinf := (if line(p(1)) = 2 then 0 else line(p(1)) + 1) shift 1
                add (if linetype=1 then 1 else 0);
   if updateinf = 1 then alarm(<:illegal update information:>);
   project := true;
   username1 := username2 := 0;

   output(trans, maxlength);
   maxdeviceword := -1;  comment no devices allowed;
   deviceword    :=  0;  comment no devices requested;
   maxdevice     :=
   device        := false;

   trans.int1 := projno;
   trans.int2 := line(p(4));  comment lower proj interv.;
   trans.int3 := line(p(5));  comment upper proj interv.;
   trans.int4 :=
   trans.int5 := line(p(3)) shift 12 add line(p(2));

   state := if updateinf = 0 then neutralstate else projectstate;

   goto print_line;
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...21...  *>


inituser:        ;  comment
***************  ;

   projno := line(p(1));
   if line(p(2)) < 0 or line(p(2)) > 2 then
      alarm(<:illegal update identification:>);
   updateinf := (if line(p(2)) = 2 then 0 else line(p(2)) + 1) shift 1
                add (if linetype=2 then 1 else 0);
   if updateinf = 1 then alarm(<:illegal update information:>);
   project := false;
   nameptr := p(0) * 2 + 2;  comment point at username...;
   username1 := line.nameptr;
   nameptr := nameptr + 4;
   username2 := if kind(p(0) + 2) <> 6 then extend 0
                else line.nameptr shift (-24) shift 24;
      comment if the username is shorter than 7 characters,
         the name is extended with null-chars, otherwise
         the name allways is cut down to at most 9 chars;

   output(trans, maxlength);
   maxdeviceword := -1;  comment no devices allowed;
   deviceword    :=  0;  comment no devices requested;
   maxdevice     :=
   device        := false;
   userpool      := false;
   permanent_disc:= 0;

   trans.long1:= username1;
   trans.long2:= username2;
   trans.int5 := line(p(5));  comment user interval start;
   trans.int6 := line(p(3));  comment job-interval-width;
   trans.int7 := line(p(4));  comment number of simult. jobs;

   state := if updateinf = 0 then neutralstate else userstate;

   goto print_line;
\f


<*  bbj   9 9 76                    linetypes                     catupdate  ...22...  *>


termuser:        ;  comment
***************  ;

   if userpool then
      begin comment output the max-interval record;
      rectypelgth := 34 shift 12 add 10;
      output(trans, maxlength);
      trans.int3 :=
      trans.int4 := permanent_disc;
      end;


termproj:        ;  comment
***************  ;

   if device then
      begin comment output the device record;
      rectypelgth := 8 shift 12 add 6;
      output(trans, maxlength);
      trans.long1 := deviceword;
      end;

   if maxdevice then
      begin comment output the max-device record;
      rectypelgth := 9 shift 12 add 6;
      output(trans, maxlength);
      trans.long1 := maxdeviceword;
      end;

   state := neutralstate;

   goto select;


illegal:         ;  comment
***************  ;

   alarm(<:out of sequence:>);
\f


<*  bbj   9 9 76                    special actions               catupdate  ...23...  *>



comment the following contains the different
   special actions to be taken with the different
   options, called by linetype 5 and linetype 6...

   notice: some of the action require a certain linetype
   ***************************************************** ;

action1:         ;  comment
***************  ;
comment joboptions which consist of <keyword> <int parameter> ;

comment acco, area, buf, cbuf, core, inte, key, outp,
        moun, wait, size, stat, susp, tape, prio, link;

   output(trans, maxlength);
   valueofpar:=trans.int1 := line(p(1));
   goto print_line;

action2:         ;  comment
***************  ;

comment devi;

   if kind(p(1)) = 6 then
      begin comment text parameter;
      nameptr := p(1) * 2 + 2;  comment point at device name;
      name := line.nameptr shift (-16) shift 16;
         comment extract the first four letters of device name;
      for i := 2 step 1 until 5 do
         if devicename(i) = name and devicenumber(i) > 0 then
            goto device_found;
      if name = long <:no:> then
         begin
         i := 50;  comment devicebit out of range...;
         if linetype = 5 then deviceword    := 0
                         else maxdeviceword := -1;
         end
      else
      alarm(<:device unknown:>);
      end
   else
      begin comment integer parameter;
      for i := no_of_devices step -1 until 4 do
         if line(p(1)) = devicenumber(i) then
            goto device_found;
      alarm(<:device unknown:>);
      end;

device_found:
   if linetype = 5 then
      begin
      if deviceword shift (-47+i) extract 1 = 0 then
         deviceword := deviceword + (extend 1) shift (47-i);
      device := true;
      end
   else
      begin
      if maxdeviceword shift (-47+i) extract 1 = 1 then
         maxdeviceword := maxdeviceword - (extend 1) shift (47-i);
      maxdevice := true;
      end;

   goto print_line;
\f


<*  bbj   9 9 76                    special actions               catupdate  ...24...  *>

action3:         ;  comment
***************  ;

comment late;

   output(trans, maxlength);
   valueofpar:=trans.int1 := extend 0
      + ((line(p(1)) * 60
          + (if kind(p(2))=2 then line(p(2)) else 0))
         * (extend 600000))
        shift (-13);

   goto print_line;

action4:         ;  comment
***************  ;

comment priv;
   if linetype <> 5 then
      alarm(<:max value not allowed:>);

   output(trans, maxlength);
   i:=line(p(1));
   if i>9 or i<=0 then alarm(<:privilege illegal:>);
   trans.int1:=case i of (4081, 4080, 4064, 4032, 3968, 3840, 3584, 3072, 2048);
   goto print_line;

action5:         ;  comment
***************  ;

comment prog;

   if linetype <> 5 then
      alarm(<:max value not allowed:>);

   output(trans, maxlength);
   nameptr := p(1) * 2 + 2;  comment point at programname;
   trans.long1 := line.nameptr;
   nameptr := nameptr + 4;
   trans.long2 := if kind(p(1) + 2) = 6 then line.nameptr shift (-8) shift 8
                  else extend 0;
   goto print_line;

action6:         ;  comment
***************  ;

comment time;

   output(trans, maxlength);
   j := 0;  comment compute time from up to three params;
   for i := 1 step 1 until 3 do
      if kind(p(i)) <> 2 then i := 3
      else j := j * 60 + line(p(i));
   valueofpar:=trans.int1 := ((extend 10000) * j) shift (-13);
   goto print_line;
\f


<*  bbj   9 9 76                    special actions               catupdate  ...25...  *>

action7:         ;  comment
***************  ;

comment perm;

   if linetype <> 5 then
      alarm(<:max value not allowed:>);

   nameptr := p(1) * 2 + 2;  comment point at device name;
   name := line.nameptr;
   if name = long <:drum:> then rectypelgth := 46 shift 12 add 4
   else if name <> long <:disc:> then goto special;

   output(trans, maxlength);
   trans.int1 := line(p(3)) shift 12 + line(p(2));
   goto print_line;

special:
   rectypelgth := 48 shift 12 add 12;
   output(trans, maxlength);
   trans.long1 := line.nameptr;
      nameptr := nameptr + 4;
   trans.long2 := if kind(p(1) + 2) <> 6 then extend 0
                  else line.nameptr shift (-8) shift 8;
   trans.int5  := line(p(3)) shift 12 + line(p(2));
   goto print_line;

action8:         ;  comment
***************  ;

comment temp;

   if linetype <> 5 then
      alarm(<:max value not allowed:>);

   nameptr := p(1) * 2 + 2;  comment point at devicename;
   name := line.nameptr;
   if name = long <:disc:> then rectypelgth := 38 shift 12 add 4
   else if name <> long <:drum:> then
      alarm(<:temp not allowed on specified device:>);
   output(trans, maxlength);
   trans.int1 := line(p(2)) + (if kind(p(3)) = 2 then line(p(3)) shift 12
                               else 0);
   goto print_line;

action9:         ;  comment
***************  ;

comment onli  , pres or  mini;

   nameptr := p(1) * 2 + 2;  comment point at answer;
   name := line.nameptr;
   if name = long <:no:> then i := 0
   else if name = long <:yes:> then i := 1
   else alarm(<:illegal parameter:>);
   output(trans, maxlength);
   trans.int1 := i;
   goto print_line;
\f


<*  bbj   9 9 76                    end of input                  catupdate  ...26...  *>



initsort:         ;  comment
****************  ;

comment now all input has been processed, and has been
   changed into transaction records;

   rectypelgth := 0 shift 12 add 12;  comment produce a end-catalog-record;
   projno := (-1) shift (-1);
   username1 := username2 := 0;
   updateinf := 0;
   output(trans, maxlength);
   output(vartrans, varlength);
   no_of_trans := no_of_trans - 1;  comment compensate the counting;
   no_of_vartrans := no_of_vartrans + 1;
   close(in, true);
   close(trans, true);
   close(vartrans, true);

end; <* end of input *>
\f


<*  bbj   9 9 76                    sorting of records            catupdate  ...27...  *>

begin comment sorting block;

procedure discsort(filnavn,læ,antalindiv,segmprblok,ngl,levls);
value segmprblok; string filnavn;
integer læ,antalindiv,segmprblok,levls;
integer array ngl;

begin integer fysisksubbloklængde, fysiskbloklængde, b;
      integer array ia(1:20); array ra(1:2);
      fysisksubbloklængde := 512 * segmprblok;
      b:= (system(2,b,ra)-8*512)//(2*fysisksubbloklængde);
      fysiskbloklængde := b * fysisksubbloklængde;
      segmprblok := b * segmprblok;
comment iiff updatest then write(out, <:<10>antalindiv = :>, antalindiv);

begin integer diff, fa, indivlæ2, logiskbloklængde,
      logisksubbloklængde, nedbasis, nedplads, nedslut, opbasis,
      opplads, opslut, slut2, start2, subblokstart, transporter;
      long array field m, ned, op; integer array nuvblok(0:1);
      zone z(fysiskbloklængde//2,1,blproc);

      long array mid, nøgle(1:levls);
      long r;
      long field i;
      integer j, levels, level; integer field indivlæ;

procedure blproc(z,s,b); zone z; integer s, b;
if s extract 19 < 1 shift 18 or ia(4)<>5 shift 12 then
stderror(z,s,b);

procedure io(plads,operation); integer plads, operation;
begin b:=nuvblok(plads)*segmprblok;
      if b>=0 then
      begin ia(4):= operation shift 12;
            ia(7):= b;
            ia(5):= b:= fa + plads*fysiskbloklængde;
            ia(6):= b + fysiskbloklængde - 2;
            setshare(z,ia,1);
            monitor(16,z,1,ia); check(z);
      end
end io;
\f


<*  bbj   9 9 76                    quicksort                      catupdate  ...28...  *>
                                                                         
procedure quicksort(start,slut,enblok); value start, slut, enblok;
integer start, slut; boolean enblok;
begin

for m:=(start+slut)//indivlæ2*indivlæ while start<slut-indivlæ2 do
begin op:= start-opbasis; ned:= slut-nedbasis;
      if enblok then m:=m-opbasis else
      begin transporter:=0;
            transport(m,0,opplads,nedplads);
            nedslut:=ned; opslut:=op;
      end;
      for level:= 1 step 1 until levels do
         mid(level):= z.m(nøgle(level));

søgned:  ned:= ned-indivlæ; if ned < nedslut then
      begin transport(ned,nedbasis,nedplads,opplads);
            nedslut:= subblokstart;
      end;
      for level:= 1 step 1 until levels do
         if z.ned(nøgle(level)) > mid(level) then goto søgned else
         if z.ned(nøgle(level)) < mid(level) then level:= levels;

søgop:   op:= op+indivlæ; if op >= opslut then
      begin transport(op,opbasis,opplads,nedplads);
            opslut:= subblokstart + logisksubbloklængde;
            if transporter=3 then enblok:= nedslut=subblokstart;
      end;
      for level:= 1 step 1 until levels do
         if z.op(nøgle(level)) < mid(level) then goto søgop else
         if z.op(nøgle(level)) > mid(level) then level:= levels;

      if op+opbasis < ned+nedbasis then
      begin for i:=4 step 4 until indivlæ do
            begin r:=z.op.i; z.op.i:=z.ned.i; z.ned.i:=r end;
            if indivlæ extract 2 = 2 then
             begin j:=z.op.indivlæ; z.op.indivlæ:=z.ned.indivlæ; z.ned.indivlæ:=j end;
            goto søgned;
      end;

      slut2:= op+opbasis; start2:= start; start:= ned+nedbasis;
      if slut-start < slut2-start2 then
      begin i:=slut; slut:=slut2; slut2:=i;
            i:=start; start:=start2; start2:=i;
      end;
      if start2<slut2-indivlæ2 then quicksort(start2,slut2,enblok);
end for m;
end quicksort;
\f


\f


<*  bbj   9 9 76                    transport                    catupdate  ...29...  *>
                                                                     
procedure transport(fysisk,basis,plads,andenplads);
integer fysisk, basis, plads, andenplads;
begin integer logisk, blok, blokrel, subbloknr, blokbasis;

      logisk:= fysisk+basis;
      blok:= logisk//logiskbloklængde; blokrel:= logisk mod logiskbloklængde;

      if blok = nuvblok(0) then plads := 0 else
      if blok = nuvblok(1) then plads := 1 else
      begin plads := 1-andenplads; io(plads,5);
            nuvblok(plads):= blok; io(plads,3);
      end;

      subbloknr := blokrel//logisksubbloklængde;
      blokbasis := plads * fysiskbloklængde;
      fysisk := blokrel + subbloknr * diff + blokbasis;
      subblokstart := subbloknr * fysisksubbloklængde + blokbasis;
      basis := logisk - fysisk;
      transporter := transporter + 1;
end transport;


      open(z,4,filnavn,1 shift 18); close(z,false);
      getzone(z,ia); fa:=ia(19)+1; getshare(z,ia,1);

      indivlæ:= læ;
      indivlæ2:= 2*indivlæ;
      levels:= levls;
      for level:= 1 step 1 until levels do
         nøgle(level):= ngl(level);

      diff:= fysisksubbloklængde mod indivlæ;
      logisksubbloklængde := fysisksubbloklængde - diff;
      logiskbloklængde := b * logisksubbloklængde;

      nuvblok(0) := nuvblok(1) := -1;
      opbasis:= nedbasis:= nedplads:= 0;
      quicksort(-indivlæ, indivlæ*antalindiv, false);
      io(0,5); io(1,5);
end zone blok;
end disksort;

integer array keyfield(1:6); integer i;
      for i:= 1 step 1 until 6 do keyfield(i):= case i of(1,2,3,4,5,6);
      i:= 1; discsort(string transname(increase(i)), maxlength, no_of_trans, 1, keyfield, 6);
      i:= 1; discsort(string vartransname(increase(i)), varlength, no_of_vartrans, 1, keyfield, 3);
end sorting block;
\f


\f


<*  bbj   9 9 76                    declarations                 catupdate  ...30...  *>



begin

integer        projlower, projupper, lowerint, upperint,
               minimum, maximum,
               nextnew, nextold,
               level, copytype,
               firstsegm, projsegm, projrel,
               projstart, userstart, nil;

long           tproj, tuser1, tuser2, ttype,
               cproj, cuser1, cuser2, ctype, ckit1, ckit2,
               width, catno, transno;

boolean        absint, warning, delete, nodelete, create, after_delete,
               firsttime, bool, record_in_inbuf,
               newproj, firstproj, projlist, userlist;

integer field  proj, cupper, clower, cstart, cwidth, cjobs,
               maxlower, maxupper,
               ptr, oldptr, firstfree, i, j, if2, if12, basis;

long field     kitname1, kitname2, username1, username2,
               lg6, lg10;

integer array  xinf(1:2),
               intervals(1:3*intervaltable_size),
               special_action(0:max_record_type//2);

long array     comp(1:2,1:4);

boolean array  change(0:max_record_type//2);

integer array field old, new, rec, cat, upper, lower;

zone           trans, vartrans, oldcat, newcat(128, 1, stderror);
\f


<*  bbj   9 9 76                    proc initialize              catupdate  ...31...  *>


procedure initialize(start, project, lowint, upint);
   value project, lowint, upint;
   integer start, lowint, upint;
   boolean project;
   comment the procedure initializes the intervaltable, and
           returns the start-address of the list in ..start..;

   begin
   integer lowerint, upperint, segm;
   integer field minptr, stepptr, searchptr;

comment iiff updatest then write(out, <:<10>initialize :>, if project then <:proj:> else <:user:>, lowint, upint);

   if firstfree > intervaltable_size then
      interval_alarm;
   start := oldptr := firstfree;
   firstfree := firstfree + 6;

   comment initialize list-head, containing top- and base-interval
           of the ..owner.. of the list (i.e. the surrounding
           interval to be obeyed);
   intervals.lower.oldptr := upint + 1;
   intervals.upper.oldptr := lowint - 1;
   intervals.oldptr        := nil;
   comment notice the funny exchange of lower- and upper...;

   if newproj or firstproj then goto exit;
      comment i.e. there are no proper records in oldcat;

   comment the oldcat is searched, extracting the information
           concerning the intervals of all projects (or all
           users belonging to the current project);
   getposition(oldcat, 0, segm);
   setposition(oldcat, 0, if project then firstsegm else projsegm);
   cat := if project then 0 else projrel;
\f


<*  bbj   9 9 76                    proc initialize              catupdate  ...32...  *>

next_block:
   inrec6(oldcat, 512);
   for i := oldcat.cat.if2 extract 12 + cat while oldcat.cat.if2 <> 0 do
      begin

      if oldcat.cat.if2 < 2 shift 12 then
         begin
         comment project record;
         if -, project or oldcat.cat.proj = maximum then
            goto updated;
         if firstfree > intervaltable_size then
            interval_alarm;
         intervals.lower.firstfree := lowerint := oldcat.cat.clower;
         intervals.upper.firstfree :=             oldcat.cat.cupper;
         if lowerint <> minimum then
            firstfree := firstfree + 6;
            comment maintenance-project and account-project are
                    not included in interval-list;
         end proj-record
      else
      if if project then false else oldcat.cat.if2 < 4 shift 12 then
         begin
         comment user-record (skipped if only extracting projects...);
         if firstfree > intervaltable_size then
            interval_alarm;
         intervals.lower.firstfree := lowerint := oldcat.cat.cstart;
         intervals.upper.firstfree :=
            oldcat.cat.cwidth * oldcat.cat.cjobs + lowerint - 1;
         if lowerint <> minimum then
            firstfree := firstfree + 6;
         end user-record;

      cat := i;  comment increase to next record...;
      end;

   cat := 0;
   goto next_block;
\f


<*  bbj   9 9 76                    proc initialize              catupdate  ...33...  *>

updated:;
   comment restore the oldcat-zone...;
   setposition(oldcat, 0, segm);
   inrec6(oldcat, 512);

   comment the intervals must be sorted:
           primary: lower interval ascending,
           sec.ary: upper interval descending;

   for stepptr := start+6 step 6 until firstfree-6 do
      begin
      minptr := stepptr;  comment point at current winner;
      lowerint := intervals.lower.minptr;

      for searchptr := stepptr+6 step 6 until firstfree-6 do
         if if extend intervals.lower.searchptr < lowerint then true else
               intervals.lower.searchptr = lowerint and
               extend intervals.upper.searchptr < intervals.upper.minptr then
            begin
            minptr := searchptr;
            lowerint := intervals.lower.minptr;
            end;

      comment exchange the challenger and the winner;
      intervals.lower.minptr := intervals.lower.stepptr;
      intervals.lower.stepptr:= lowerint;
      upperint := intervals.upper.minptr;
      intervals.upper.minptr := intervals.upper.stepptr;
      intervals.upper.stepptr:= upperint;

      comment insert in list of intervals;
      intervals.oldptr := oldptr := stepptr;
      intervals.stepptr := nil;
      end sorting;

exit:
   end initialize_procedure;
\f


<*  bbj   9 9 76                    proc getinterval             catupdate  ...34...  *>


procedure get_interval(start, lowint, upint);
   value start;
   integer start, lowint, upint;
   comment the procedure searches the interval-list, starting
           at start, until a hole with the width upint-lowint+1
           is found. special actions are made with abs-intervals;

   begin
   long oldupper, maxupper, low;
   width := extend upint - lowint + 1;
   ptr := start;
   maxupper := intervals.upper.ptr;

comment iiff updatest then
   write(out, <:<10>get interval :>, start, lowint, upint, 
   intervals.upper.ptr, intervals.lower.ptr);

   if absint then
      begin
      if extend lowint <= intervals.upper.ptr or
         extend upint >= intervals.lower.ptr then
            update_alarm(<:illegal abs interval:>);
      end;

rep:
   oldptr   := ptr;
   oldupper := intervals.upper.oldptr;
   ptr      := intervals.oldptr;
   if oldupper > maxupper then maxupper := oldupper;

   if ptr <> nil then
      begin
      low := intervals.lower.ptr;
      if absint then
         begin
         comment search until low has passed lowint...;
         if low < lowint then goto rep;
         comment if low has not yet passed upint then overlap...;
         if low <= upint then
            begin
            warning := true;
            update_alarm(<:overlapping intervals:>);
            end;
         comment search until the sorting demands are fulfilled...;
         if low = lowint and
            intervals.upper.ptr > upint then goto rep;
         end
      else
         begin
         comment search until a hole is found big enough...;
         if low - oldupper <= width then goto rep;
         end
      end ptr <> nil
   else
   ptr := start; comment notice: lower.start is top of legal interv.;
\f


<*  bbj   9 9 76                    proc getinterval             catupdate  ...35...  *>

comment now oldptr points at element just before, while
   intervals.lower.ptr contains the start of the next interval
   (used to chech ..no room..);

   if absint then
      oldupper := lowint - 1
   else

   if intervals.lower.ptr - oldupper <= width then
      update_alarm(<:no room:>);

   if firstfree > intervaltable_size then
      interval_alarm;
   intervals.lower.firstfree := lowint := oldupper + 1;
   intervals.upper.firstfree := upint  := oldupper + width;
   if maxupper >= lowint then
      begin
      warning := true;
      update_alarm(<:overlapping intervals:>);
      end;

   intervals.firstfree := intervals.oldptr;
   intervals.oldptr    := firstfree;
   firstfree           := firstfree + 6;

   end get_interval...;
\f


<*  bbj   9 9 76                    proc output                  catupdate  ...36...  *>


procedure output(from, iaf);
   zone from;
   integer array field iaf;

   begin
   integer length;
   length := from.iaf.if2 extract 12;
comment iiff updatest then write(out, <:<10>output :>, from.iaf.if2 shift (-12), length, nextnew);
   if nextnew+length > 510 then
      begin
      if leftside then outrec6(newcat, 512);
      nextnew := 0;
      end;
   new := nextnew;
   nextnew := nextnew + length;  comment point at next record;

   for i := 2 step 2 until length do
      newcat.new.i := from.iaf.i;
   newcat.new.i := 0;
      comment insert a dummy zero (in case of block-change...);
   end output_procedure;


procedure interval_alarm;
   begin
   write(out, <:***the catupdate program must be corrected and
recompiled, with a greater intervaltable_size<10>:>);
   system(9, intervaltable_size//6, <:<10>size    :>);
   end;


procedure update_alarm(text);
   string text;
   begin
   write(out, <:projno= :>, <<dddddd>, tproj, <:  user= :>);
   i := 1;
   write(out, false add 32,
         13 - write(out, string( case increase(i) of (tuser1, tuser2))),
         <:*** :>,text,<: ***:>, <:<10><10>  ; :>);
   if ttype=42 then printrec(vartrans.rec, tproj)
               else printrec(trans.rec   , tproj);
   write(out, <:<10><10>:>);
   if warning then warning := false else
   goto next_trans;
   end;
\f


<*  bbj   9 9 76                    proc printrec                catupdate  ...37...  *>

procedure printrec(record, projno);
   integer array record;
   long    projno;

   comment the procedure prints the current record in such a way,
           that it later may be used again as input for the program...;

   begin
   integer i, typ, type, length;
   long    longwork;
   boolean newline;

   procedure slices(n); integer n;
      write(out, <<d>, record(n) shift 12 // 4096, <:,:>, record(n)  // 4096);

   procedure claim(n); integer n;
      begin
      write(out, <: (slices, entries=) :>);
      slices(n);
      end;

   procedure restclaim(n); integer n;
      begin
      write(out, <: (restclaim= :>);
      slices(n);
      write(out, <:):>);
      end;

   procedure temp_or_perm(device, n); string device; integer n;
      begin
      write(out, <:  5 :>, if type < 40 then <:temp :> else <:perm :>, device);
      claim(n);
      end;

   long procedure name;
      name := case increase(i) of (record.username1, record.username2);

   long procedure longtext;
      longtext := long <::> add (if i < length then record(increase(i)+1) else 0) shift 24
                            add (if i < length then record(increase(i)+1) else 0);

   procedure standard(text); string text;
      write(out, <<ddd>, typ, <: :>, text, << d>, record(2));
\f


<*  bbj   9 9 76                    proc printrec                catupdate  ...38...  *>

   type := record(1) shift (-12);
   length := record(1) extract 12;
   typ := if type extract 1 = 0 then 5 else 6;
   i := 1;  comment used in printing text a.o.;

   case type shift (-1)  + 1 of
   begin

   comment type=0, project-record;
      begin
      write(out, <: 10 (new projno =):>, <<dddddd>, projno, <: 0:>);
      claim(6);
      restclaim(5);
      write(out, <: (interval=):>, record.clower, record.cupper);
      end;

   comment type=2, user-record;
      write(out, <: 11 (new user =) :>, string name,
                 <: (projno =):>, projno, <: 0 (width,jobs,start =):>,
                 record.cwidth, record.cjobs, record.cstart);

   comment type=4, priority and respite;
      write(out, <:  7 (priority, respite =):>, record(2),
                 (extend record(3)) shift 13 // 10000);

   comment type=6, claims on private kits;
      begin
      write(out, <:  4 (private kit =) :>, string name);
      claim(7);
      restclaim(6);
      write(out, <: (slicelength =):>, if length = 14 then 8 else record(8));
      end;

   comment type=8/9 , device-mask record;
      begin
      longwork := record.username1;
      if type extract 1 = 1 then longwork := -1 - longwork;
         comment ones-complement...;

      if longwork = 0 then
         write(out, <<ddd>, typ, <: device no:>)
      else
         begin
         newline := false;
         for i := 2 step 1 until 5 do
            if longwork shift (-47+i) extract 1 = 1 then
               begin write(out, newline, 1);
               newline := false add 10;
               write(out, <<ddd>, typ, <: device :>, string devicename(i));
               end;
         for i := 6 step 1 until no_of_devices do
            if longwork shift (-47+i) extract 1 = 1 then
               begin write(out, newline, 1);
               newline := false add 10;
               write(out, <<ddd>, typ, <: device :>, devicenumber(i));
               end;
         end;
      end;
\f


<*  bbj   9 9 76                    print rec types              catupdate  ...39...  *>

   comment type=10/11;
      standard(<:acco:>);

   comment type=12/13;
      standard(<:area:>);

   comment type=14/15;
      standard(<:buf:>);

   comment type=16/17;
      standard(<:cbuf:>);

   comment type=18/19;
      standard(<:inte:>);

   comment type=20/21;
      standard(<:key:>);

   comment type=22/23;
      standard(<:moun:>);

   comment type=24/25;
      write(out, <<ddd>, typ, <: outp:>, << d>, record(2), <: (slices):>);

   comment type=26/27;
      standard(<:size:>);

   comment type=28/29;
      standard(<:stat:>);

   comment type=30/31;
      standard(<:tape:>);

   comment type=32/33;
      begin
      write(out, <<ddd>, typ, <: time:>);
      longwork := (extend record(2)) shift 13 // 10000;
      if longwork >= 3600 then write(out, longwork // 3600);
      if longwork >= 60   then write(out, longwork mod 3600 // 60);
      write(out, longwork mod 60);
      end;

   comment type=34;
      begin
      write(out, <:  9 (userpool):>);
      claim(5);
      restclaim(4);
      end;

   comment type=36, temp drum;
      temp_or_perm(<:drum:>, 2);

   comment type=38, temp disc;
      temp_or_perm(<:disc:>, 2);

   comment type=40, perm disc;
      temp_or_perm(<:disc:>, 2);

   comment type=42, username and address;
      write(out, <:  3 :>, string longtext);
\f


<*  bbj    9 9 76                   print rec types              catupdate  ...40...  *>

   comment type=44, permanent resources on drum;
      begin
      write(out, <:  8 (permanent drum):>);
      claim(3);
      restclaim(2);
      end;

   comment type=46, perm drum;
      temp_or_perm(<:drum:>, 2);

   comment type=48, perm <private kit>;
      temp_or_perm(string name, 6);

   comment type=50/51 the latest finishing time for the job;
      begin
      longwork := (extend record(2)) shift 13 // 600000;
      write(out,<<ddd>, typ, <: late:>, longwork // 60, longwork mod 60);
      end;

   comment type=52, project id;
      write(out, <: 12 :>, string longtext);

   comment type=54;
      write(out, <:  5 program= :>, string name);

   comment type=56;
      standard(<:susp:>);

   comment type=58/59;
      write(out, <<ddd>, typ, <: onli:>, if record(2) = 0 then <: no:> else <: yes:>);

   comment type=60/61;
      standard(<:core:>);

   comment type=62/63;
      write(out,<<ddd>, typ, <: mini:>, if record(2) = 0 then <: no:> else <: yes:>);

   comment type=64/65;
      standard(<:prio:>);

   comment type=66/67;
      standard(<:wait:>);

   comment type=68/69;
      write(out, <<ddd>, typ, <: pres:>, if record(2) = 0 then <: no:> else <: yes:>);
\f


<*  bbj   9 9 76                    print rec types              catupdate  ...41...  *>
   
   comment type=70;
      begin
         write(out,<<ddd>, typ,<: priv:>);
         longwork:=record(2);
         if longwork extract 1=1 then i:=1 else
         begin
           longwork:=longwork shift (-3);
           i:=2;
           for longwork:=longwork shift (-1) while longwork extract 1=0 do
              i:=i+1;
         end;
         write(out,i,<:  (bit pattern: :>);
         longwork:=record(2);
         write(out,<< d>, longwork shift (-11) extract 1,
                          longwork shift (-10) extract 1,
                          longwork shift (-9) extract 1,
                          longwork shift (-8) extract 1,
                          longwork shift (-7) extract 1,
                          longwork shift (-6) extract 1,
                          longwork shift (-5) extract 1,
                          longwork shift (-4) extract 1,
                          longwork shift (-3) extract 1,
                          longwork shift (-2) extract 1,
                          longwork shift (-1) extract 1,
                          longwork extract 1,<:):>);
      end;
 
   comment type=72  link ;
   standard(<:link:>);
 

   end case type...;

   write(out, <:;:>);

   end procedure printrec;
\f


<*  bbj   9 9 76                    initialization               catupdate  ...42...  *>


comment initialize field-variables;

comment project record (type = 0);
proj   := 4;
clower := 6;
cupper := 8;

comment user record (type = 2);
username1 := 6;
username2 := 10;
cstart    := 12;
cwidth    := 14;
cjobs     := 16;

comment special bs-device record (type = 6);
kitname1  := 6;
kitname2  := 10;

comment userpool record(type = 34);
maxlower  := 4;
maxupper  := 6;

comment sorting fields in transactions;
if2       := 2;  comment projectnumber of transaction, rectype of usercat;
lg6       := 6;  comment username1 of transactions;
lg10      := 10; comment username2 of transactions;
if12      := 12; comment contains updateinf...;
basis     := 14; comment recordtype and -length of transactions;
rec       := basis-if2;

comment interval-list;
intervaltable_size := intervaltable_size * 6;
userstart := firstfree := 2;
upper := 2;
lower := upper + 2;
warning := false;

comment std-variables;
maximum := (-1) shift (-1);
minimum := 1 shift 23 + 1;
nil     := -1;


comment initialize update-tables;

for i := 0 step 2 until max_record_type do
   begin

   change(i//2) := false add
      (if i=0  then (1 + 1 shift 4 + 1 shift 5) else
       if i=2  then  1                          else
       if i=6  then (1 + 1 shift 5 + 1 shift 6) else
       if i=34 then (1 + 1 shift 3 + 1 shift 4) else
       if i=44 then (1 + 1 shift 1 + 1 shift 2) else
       if i=46 then (1 + 1 shift 1            ) else
       if i=48 then (1 + 1 shift 5            ) else
       0 );
   comment this means, that in f.ex. the record of type 6,
           updating is made by increasing the contents of
           word 5 (i.e. 1 shift 5) and word 6 in the usercat-
           record by the corresponding words in the trans-
           action-record.  *****  only bs claims  *****
           (the bit 1 shift 0 indicates whether the record is 
           to be updated or simply exchanged by a new record);

   special_action(i//2) :=
      if i=0 then 1 else
      if i=2 then 2 else
      if i=6 or i=48 then 3 else
      if i=34 then 4 else
                   5    ;

   end initialize update-tables;
\f


<*  bbj   9 9 76                    mix  catalogs                catupdate  ...43...  *>


if nooldcat  then  <* the parameter cat.yes is set *>
   begin comment no old usercat present, simulate end-record;
   oldcat.if2    := 0 shift 12 + 12;   comment rectype of proj-record;
   oldcat.proj   := maximum;           comment projno of end-record;
   cproj         := maximum;
   cuser1  := cuser2 := ctype := 0;
   firstsegm     := std_usercat_index;
   old           := 0;
   record_in_inbuf := true;
   end
else
   begin
   open(oldcat, 4, <:usercat:>, 0);
   firstsegm := 0;
   for i:= inrec6(oldcat, 2), inrec6(oldcat, 2) while oldcat.if2 < 0 do
      firstsegm := firstsegm + 1;
   setposition(oldcat, 0, firstsegm);
   cproj := -1;
   nextold := 0;
   inrec6(oldcat, 512);
   record_in_inbuf := false;
   end;

i := 1; open(trans, 4, string(transname(increase(i))), 0);
i := 1; open(vartrans, 4, string(vartransname(increase(i))), 0);

nextnew := 512;
if leftside then
   begin
   i := 1; open(newcat, 4, string(newcatname(increase(i))), 0);
   setposition(newcat, 0, std_usercat_index);
   end;

projlist := false;  comment the interval-list of projs is not created yet;
firstproj := true;
firsttime := true;
ttype := 0       ;  comment serves to initialize the trans-zones...;
\f


<*  bbj   9 9 76                    mix catalogs                catupdate   ...44...  *>


next_trans:      ;  comment
***************  ;

comment select the next transaction from either the
trans-zone or the vartrans-zone. initialize the merging
variables;

if first_time or ttype=42 then
   begin
   first_time := false;
   inrec6(vartrans, varlength);
   comp(1,1) := vartrans.if2;  comment project number;
   comp(1,2) := vartrans.lg6;  comment username...;
   comp(1,3) := vartrans.lg10;
   xinf(1)   := vartrans.if12 extract 4;  comment updateinf;
   comp(1,4) := vartrans.basis shift (-12); comment recordtype;
   end;

if ttype <> 42 then
   begin
   inrec6(trans, maxlength);
   comp(2,1) := trans.if2;  comment project number;
   comp(2,2) := trans.lg6;  comment username...;
   comp(2,3) := trans.lg10;
   xinf(2)   := trans.if12 extract 4;  comment updateinf;
   comp(2,4) := trans.basis shift (-12);  comment recordtype;
   end;

i := 1;  comment suppose vartrans wins...;

for level := 1 step 1 until 4 do
   if comp(1,level) < comp(2,level) then goto winner else
   if comp(1,level) > comp(2,level) then level := 5;

i := 2;  comment vartrans lost the competition...;

winner:  ; comment
******;

tproj := comp(i,1);  comment project number;
tuser1:= comp(i,2);  comment username...;
tuser2:= comp(i,3);  comment .... ;
ttype := comp(i,4);  comment recordtype;

absint:= xinf(i) extract 1 = 0;
delete:= xinf(i) shift (-1) = 0;
create:= xinf(i) shift (-1) = 1;

nodelete := true;
after_delete := false;
  comment no deleting is in progress...;
comment iiff updatest then write(out, case i of (<:<10>var:>, <:<10>tr :>), tproj, ttype, xinf(i));
\f


<*  bbj   9 9 76                    mix catalogs               catupdate  ...45...  *>

compare_start:   ;  comment
***************  ;

level := 1;  comment start the comparison at project-level;

compare:         ;  comment
***************  ;

comment proceed the comparison at the current level...;

catno    := case level of (cproj, cuser1, cuser2, ctype, ckit1, ckit2); <* current record-variables *>
transno  := case level of (tproj, tuser1, tuser2, ttype,
                           trans.rec.kitname1, trans.rec.kitname2); <* record from trans or vartrans *>
copytype := case level of (2, 4, 4, 1000, 1000, 1000);

comment iiff updatest then write(out, <:<10>cat:>, level, catno, transno);




if catno < transno then
   begin
   comment the current record is completely updated.
           copy the usercat, until a record with recordtype
           less than ..copytype.. is met;

copy:
   if nodelete and record_in_inbuf then output(oldcat, old);
   if nextnew < 512 and print > 0 then
      begin comment print the current record...;
      if nodelete then
         begin
         printrec(newcat.new, cproj);
         if print extract 1 = 1 then write(out, <: --- updated ---:>);
         end
      else
         begin
         printrec(oldcat.old, cproj);
         write(out, <: --- deleted ---:>);
         end;
      write(out, <:<10>:>);
      print := print shift (-1) shift 1;
         comment remove the update-bit;
      end;
   for old := nextold while oldcat.old.if2 = 0 do
      begin
      nextold := 0;
      inrec6(oldcat, 512);
      end;
   nextold := oldcat.old.if2 extract 12 + old;
      comment step nextold up pointing at next record...;
   ctype   := oldcat.old.if2 shift (-12);
   record_in_inbuf := true;

   if ctype >= copytype then goto copy;


comment the present record is to be seperatly considered;
\f


<*  bbj   9 9 76                    mix catalogs               catupdate   ...46...  *>

   if ctype < (case level of ( 0, 2, 2, 4, 4, 4)) then
      goto possibly_new_record;
      comment this means, that the next project-record or
              next user-record is met (i.e. a sort of
              end-situation has come up...);


   case level of
   begin

level1: begin comment projectno was not ok, try this one;
        cproj := oldcat.old.proj;
        cuser1 := cuser2 := ctype := 0;
        firstproj := false;

        comment initialize interval-procedures...;
        getposition(oldcat, 0, projsegm);
        projrel := nextold;
        firstfree := userstart;
        projlower := oldcat.old.clower;
        projupper := oldcat.old.cupper;
        newproj := userlist := false;

        end level1;

level2: begin comment project ok, user not ok, try this user;
        cuser1 := oldcat.old.username1;
        cuser2 := oldcat.old.username2;
        lowerint := oldcat.old.cstart;
        upperint := oldcat.old.cwidth * oldcat.old.cjobs + lowerint - 1;
        end;

level3: begin comment second part of username not ok, try this user;
        level := 2;
        goto level2;
        end;

level4: begin comment project and user ok, recordtype not ok.
                      try this record;
        end;

level5: begin comment first part of kitname in record concerning
                      private kit is not ok, try this record;
        level := 4;
        end;

level6: begin comment second part of kitname not ok, try this record;
        level := 4;
        end;

   end level_case;

   goto compare; comment i.e. test with the current level...;

   end catno<transno;



if catno = transno then
   begin
   comment proceed the comparison in all levels...;

   level := level + 1;
   if level <= 4 then goto compare;

comment at this point projectnumber, username and recordtype is ok; 
\f


<*  bbj   9 9 76                    mix catalogs               catupdate  ...47...  *>


   case special_action(ctype//2) of
      begin

acti1:  begin comment ctype = 0... project-record;
        if cproj = maximum then
           begin
           output(oldcat, old);  comment end-record...;
           goto finisupdate;
           end;
        goto testcreate;
        end;

acti2:  begin comment ctype = 2... user-record;

testcreate: if create then update_alarm(<:existing:>);

        if delete then
           begin
           if cuser1 = 0 then
              begin comment delete project until next proj-record;

              comment check proper interval...;
              if trans.rec.clower <> projlower or
                 trans.rec.cupper <> projupper then
                   update_alarm(<:delete wrong interval:>);
              tproj := tproj + 1; comment to skip rest of project;

              end
           else
              begin comment delete user...;

              comment check proper interval...;
              if lowerint <> trans.rec.cstart or
                upperint <> trans.rec.cwidth * trans.rec.cjobs
                   + lowerint - 1 then
                 update_alarm(<:delete wrong interval:>);
              tuser2 := tuser2 + 1; comment to skip rest of user...;

              end;


           comment the project (or user) is not removed from the internal list;

start_delete:
           after_delete := true;  comment i.e. remember the forgery...;
           nodelete     := false; comment i.e. skip rest of proj or user;
           delete       := false;
           print        := print shift (-1) shift 1 add 1;
           goto compare_start;

           end delete-action;

        if after_delete then
stop_delete:
           begin comment forget about the simulated transaction...;
           nodelete := true;
           ttype := ttype - 1;  comment in case of deleting username-record...;
           goto next_trans;
           end;

        end action 2, delete user or project;
\f


<*  bbj   9 9 76                    mix catalogs               catupdate  ...48...  *>

acti3:  begin comment special bs-devices, ctype = 6 or ctype = 48;
        comment proceed the comparison to check the devicename...;
        if record_in_inbuf then
           begin
           ckit1 := oldcat.old.kitname1;
           ckit2 := oldcat.old.kitname2;
           end
        else
           begin
           ckit1 := newcat.new.kitname1;
           ckit2 := newcat.new.kitname2;
           end;
        if level < 7 then goto compare;
        if delete then
           begin
           trans.rec.kitname2 := trans.rec.kitname2 + 1;
           goto start_delete;
           end;
        end action 3;

acti4:  begin comment ctype = 34, userpool record;
        if delete then update_alarm(<:delete not allowed:>);
        end;

acti5:  begin comment other records, no action to be done...;
        if delete then
           begin comment skip record...;
           ttype := ttype + 1;
           goto start_delete;
           end;
        end;

      end special_action_case;


comment at this point the proper record is found

        update it...;
\f


<*  bbj   9 9 76                    mix catalogs               catupdate   ...49...  *>


   bool := change(ctype//2);

   if bool then
      begin comment the variable bool contains information about
                    which elements in the record to update;
      if record_in_inbuf then output(oldcat, old);
      for i := -1 step -1 until -11 do
         if bool shift i then
            begin
            j:=newcat.new(1-i) + trans.rec(1-i);
            if j<0 or j shift 12 < 0 then
               begin comment claims would get negative;
               warning:=true;
               update_alarm(<:illegal claims:>);
               end
            else newcat.new(1-i):=j;
            end;
      end
   else
      begin comment forget about the old version of the record...;
      if -, record_in_inbuf then nextnew := new;
new_record:
      if ttype = 42 then output(vartrans, rec)
                    else output(trans   , rec);
      end;

   ctype := ttype;
   record_in_inbuf := false;
   print := print shift (-1) shift 1 add 1;
      comment indicate the updating;

   goto next_trans;

   end catno = transno;
\f


<*  bbj   9 9 76                    mix catalogs               catupdate  ...50...  *>



comment catno > transno;

possibly_new_record:

   nextold := old;  comment regret input, i.e. repeat next time...;
   record_in_inbuf := false;
   if afterdelete then goto stop_delete;

   case special_action(ttype//2) of
   begin

act1:   begin comment ttype = 0, new project;
        if -, create then update_alarm(<:project unknown:>);
        firstfree := userstart;
        if -, projlist then
           initialize(projstart, true, minimum+2, maximum-2);
        projlist := true;
        userlist := false; newproj := true;

        comment the intervals of the project must be inserted in
           the interval-list (except the maintenance-proj and
           the account-project);

        if trans.rec.clower <> minimum then
           get_interval(projstart, trans.rec.clower, trans.rec.cupper);
        userstart  := firstfree;

        projlower := trans.rec.clower;
        projupper := trans.rec.cupper;
        cproj     := tproj;
        cuser1 := cuser2 := ctype := 0;
        end action 1;

act2:   begin comment ttype = 2, new user;
        if level = 1 then
           update_alarm(<:project unknown:>);
        if -, create then update_alarm(<:user unknown:>);
        if -, userlist then
           initialize(userstart, false, projlower, projupper);
        userlist := true;

        comment the intervals of the user must be inserted in the
           interval list;
        lowerint:= trans.rec.cstart;
        upperint := trans.rec.cwidth * trans.rec.cjobs
                      + lowerint - 1;
        get_interval(userstart, lowerint, upperint);
        trans.rec.cstart := lowerint;
        cuser1 := tuser1;
        cuser2 := tuser2;
        end action 2;

act3:   begin comment special bs-devices, ttype = 6;
        goto act5;
        end;

act4:   begin comment userpool record, ttype = 34;
        if level < 4 then goto act5;
        trans.rec.maxlower:= lowerint;
        trans.rec.maxupper:= upperint;
        end;

act5:   begin comment other records;
        if level < 4 then update_alarm(<:out of sequence:>);
        end;

   end special-action_case with new record...;
   if delete then updatealarm(<:record unknown:>);
   
   bool:=change(ttype//2);
   if bool then
      for i:=-1 step -1 until -11 do
         if bool shift i then
            begin
            if trans.rec(1-i)<0 or trans.rec(1-i) shift 12 < 0 then
               update_alarm(<:illegal claims:>);
            end;

   goto new_record;

finis_update:   ; comment
****************;

if print shift(-3) extract 1=1 then
write(out,<:-1 ; end of catalog<10>:>);
close(vartrans, true);  monitor(48) remove entry:(vartrans, 0, xinf);
close(trans, true);     monitor(48) remove entry:(trans, 0, xinf);
close(oldcat, true);
close(newcat, false);

end update_block;

end device-number block;
\f


<*  bbj   9 9 76                    index segment              catupdate   ...51...  *>

if leftside then
begin comment update the index segments...;

zone           index(128, 1, stderror),
               newcat(128, 1, stderror);
integer array  entr, slicelength(1:max_no_of_disckits);
long    array  kittable(2:2*max_no_of_disckits+1);
integer array field new;
integer field  if2, proj, slicelgth, disc_entr, priv_entr, userdisc_entr, drum_entr;
long    field  kit1, kit2, user1, user2;
integer        i, j, projno, type, entries, max, maxindex, no_of_disckits, kitcount;
long           name1, name2;

procedure warn(text);
   string text;
   begin
   integer i;
   write(out, <:projno= :>, <<dddddd>, projno, <:  user= :>);
   i := 1;
   write(out, false add 32,
         13 - write(out, string (case increase(i) of (name1, name2))),
         text, <:<10>:>);
   end;

   i := 1; open(index , 4, string newcatname(increase(i)), 0);
   i := 1; open(newcat, 4, string newcatname(increase(i)), 0);
   setposition(newcat, 0, std_usercat_index);

   if2 := 2;
   proj      := 4;
   disc_entr := 12;
   priv_entr := 14;
   userdisc_entr := 10;
   drum_entr :=  6;
   kit1      :=  6;
   kit2      := 10;
   slicelgth:= 16;
   user1     :=  6;
   user2     := 10;
   projno    := -1;

   for i := 1 step 1 until std_usercat_index do
      begin
      outrec6(index, 2);
      index.if2 := projno;
      end;

comment scan the new usercat and count the maximum-number
        of pre-promissed entries;

   entries := 0;
   no_of_disckits := 0;

next_block:

   inrec6(newcat, 512);
   index.if2 := projno;
   new := 0;
   outrec6(index, 2);
\f


<*  bbj   9 9 76                    count entries              catupdate  ...52...  *>

next_record:

   type := newcat.new.if2 shift (-12);

   if type < 2 then
      begin comment project-record or end-of-segment;
      if newcat.new.if2 = 0 then goto next_block;
      projno := newcat.new.proj;
      if projno = (-1) shift (-1) then goto finished;
      entries := newcat.new.disc_entr shift (-12) + entries;
      kitcount := 0;
      name1 := name2 := long <::>;
      end

   else

   if type < 4 then
      begin comment user-record;
      kitcount := 0;
      name1 := newcat.new.user1;
      name2 := newcat.new.user2;
      end

   else

   if type = 6 then
      begin comment private disckit, search kitname in kittable;
      for i := 2 step 2 until no_of_disckits do
         if if newcat.new.kit1 <> kittable(i) then false
          else newcat.new.kit2 =  kittable(i+1) then goto found;
      comment kitname was not in kittable, include it now...;
      if i > 2* max_no_of_disckits then
         begin
         warn(<::>);
         system(9, i//2, <:<10>disckits:>);
         end;
      no_of_disckits := i;
      kittable(i)    := newcat.new.kit1;
      kittable(i+1)  := newcat.new.kit2;
      slicelength(i//2) := newcat.new.slicelgth;
      entr(i//2)     := 0;

   found:
      kitcount       := kitcount + 1;
      if kitcount = no_of_privkits + 1 then 
         warn(<:too many privkits:>);
      entr(i//2)     := entr(i//2) + newcat.new.priv_entr shift (-12);
      if slicelength(i//2) <> newcat.new.slicelgth then
         warn(<:different slice-length on same kit:>);
      slicelength(i//2) := newcat.new.slicelgth;
      end type=6

   else

   if type = 34 then
      begin comment userpool-record;
      entries := newcat.new.userdisc_entr shift (-12) + entries;
      end

   else

   if type = 44 then
      begin comment permanent drum-record;
      entries := newcat.new.drum_entr shift (-12) + entries;
      end;

   new := newcat.new.if2 extract 12 + new;
   goto next_record;

\f


<*  bbj   9 9 76                    private kits               catupdate  ...53...  *>

finished:

   getposition(index, 0, new);
   if new >= std_usercat_index then
      write(out, <:<10>***std_usercat_index too small***<10>:>);
   index.if2 := projno;

   for i := 1 step 1 until no_of_priv_discdrives do
      begin
      max := 0;
      maxindex := 1;
      for j := no_of_disckits//2 step -1 until 1 do
         if entr(j) > max then
            begin
            max := entr(j);
            maxindex := j;
            end;
      entries := entries + max;
      entr(maxindex) := 0;  comment i.e. clear in the kittable...;
      end;
   setposition(index, 0, 0);
   swoprec6(index, 2);
   index.if2 := - entries;

   close(index, true);
   close(newcat,true);

end index-update block;

end

▶EOF◀