externalroutine  tidyijob(string (255) s)

   ! This routine examines file T#SPIJOB, which it first creates as a copy
   ! of JJ#SPIJOB.  It first sets the _user sub-field of each cell in
   ! the freelist to "<FREE>", and prints out the number of freelist cells.
   ! It then goes through each of the 128 lists in turn: if any contains a cell
   ! so marked then the list is terminated before it, since clearly it should
   ! not be pointing at part of the freelist.
   ! If the structure gets into a twist it is probably best to destroy
   ! JSPIJOB and start again.  However, such a corruption should be
   ! investigated.

  recordformat  rf(integer  conad, filetype, datastart, dataend)
  record  (rf) r
  externalroutinespec  copy(string (255) s)
  systemroutinespec  connect(string (31) file, integer  mode, hole,
          project, record (rf)name  r, integername  flag)
  recordformat  ijob head f( c 
     integer  end, start, size, filetype,
     checksum, date time, format, sp0,
     maxcells, freep, freen, sp1,
     halfintegerarray  list head(0:127))
  record (ijob head f)name  ijob head
  recordformat  cell f(string (6) user, string (16) device, integer  size,
    halfinteger  last, next, integer  time q, time unq, string (6) jname)
  ! This requires 48 bytes.
  record (cell f)arrayname  cell
  record (cell f)arrayformat  caf(1:50000)
  integer  i, flag, j, k, l, maxcells
  longinteger  li
  integerfn  s to i(string (255) s)
    integer  j, z
    z = 0
    z = 10*z + charno(s,j)-'0' for  j=1,1,length(s)
    result  = z
  end 
  integerfn  getcell {from freelist}
     integer  i
     i = ijob head_freep
     ijob head_freep = cell(ijob head_freep)_next
     cell(ijob head_freep)_last = 0 unless  ijob head_freep=0
     ijob head_freen = ijob head_freen-1
     cell(i) = 0
     result  = i
  end ; ! Of %integerfn getcell.

   copy("JJ#SPIJOB,T#SPIJOB")
   connect("T#SPIJOB",3,0,0,r,flag)
   monitor  and  stop  if  flag#0
   ijob head == record(r_conad)
   cell == array(r_conad+ijob head_start,caf)

   maxcells = ijob head_maxcells

   begin 
      halfintegerarray  in list(1:maxcells)

      in list(i) = 129 for  i=1,1,maxcells; ! Marks all cells as unused.
      ! First mark all freelist cells.
      j = 0
      i = ijob head_freep
      while  i#0 cycle 
         cell(i)_user = "<FREE>"
         in list(i) = 128; ! Code for freelist cell.
         j = j+1
         i = cell(i)_next
      repeat 
      printstring("No. of freelist cells:
1) by counting the list:"); write(j,3); newline
      printstring("2) according to head_freen")
      write(ijob head_freen,2); newline
      ijob head_freen = j


      ! Now remove any freelist cells within proper lists.
      l = 0; ! To hold total number in all lists.
      for  i=0,1,127 cycle 
         j = ijob head_listhead(i)
         continue  if  j=0
         if  cell(j)_user="<FREE>" start 
            ijob head_listhead(i) = 0
            printstring("List"); write(i,2)
            printstring(" faulty: contains freelist cells.")
            newline
            continue 
         finish 
         while  j#0 cycle 
            k = cell(j)_next
            if  k#0 and  cell(k)_user="<FREE>" start 
               cell(j)_next = 0
               printstring("List"); write(i,2)
               printstring(" faulty: contains freelist cells.")
               newline
               exit 
            finish 
            in list(j) = i; ! Cell is in list i.
            l = l+1
            j = k
         repeat 
      repeat 

      ! Now check 'in list' array, to see if the structure is self-consistent.
      for  i = 0,1,127 cycle 
         j = ijob head_list head(i)
         while  j#0 cycle 
            if  in list(j)#i start 
               printstring("Cell"); write(j,1)
               printstring(" is in list no."); write(i,1)
               printstring(", but 'in list' value is")
               write(in list(j),2); newline
            finish 
            j = cell(j)_next
         repeat 
      repeat 

      j = 0; ! free list count
      k = 0; ! unassigned count
      for  i = 1,1,maxcells cycle 
         j = j+1 if  in list(i)=128
         k = k+1 if  in list(i)=129
      repeat 
      printstring("3) according to 'in list' array")
      write(j,2); newlines(2)
      printstring("Total number of cells"); write(maxcells,2); newline
      printstring("Cells in use in (0-127) lists:")
      write(l,2); newlines(2)
      if  k#0 start 
         newline
         printstring("No. of cells unaccounted for (i.e. not in freelist and
not in any of the (0-127) lists:")
         write(k,2); newline
      finish 

      while  ijob head_freen>300 cycle 
         ! We can reduce file by 3 epages = 256 48-byte cells.
         ! First move any cells in use within the last 3 epages of the file.
         for  i=ijob head_maxcells,-1,ijob head_maxcells-255 cycle 
            continue  if  cell(i)_user="<FREE>"
            j = getcell; ! This cell will not be on the last 3 epages of the file.
             ijob head_freen = ijob head_freen+1; ! Reverse getcell's decrement of total.
            cell(j) = cell(i)
            if  cell(j)_last=0 start 
               li = s to i(cell(j)_jname)
               l =  ((li<<1!1)¬¬2>>13)&127
               ijob head_listhead(l) = j
            finishelsestart 
               cell(cell(j)_last)_next = j
            finish 
            cell(cell(j)_next)_last = j if  cell(j)_next#0
         repeat 

         ijob head_freen = ijob head_freen-256
         ijob head_maxcells = ijob head_maxcells-256
         ijob head_size = ijob head_size-256*48
         ijob head_end = ijob head_size
         i = ijob head_maxcells
         i = i-1 while  cell(i)_user#"<FREE>"
         ! i now gives end of freelist.
         cell(i)_next = 0
      repeat 
   end 
   printstring("Tidied file left in T#SPIJOB."); newline
end 
endoffile