program revert(exe_file);
 (* This program fixes up the directory of a tops-20 core image to be
    acceptable to tops-10.  We remove all pages outside the areas defined
    by .jbrel and .jbhrl, and make page 400 and above into a high segment.
        The following possibly dubious assumptions are made:
		- the high segment starts at page 400
    		- the directory is one page only
		- .jbrel and .jbhrl are set up by the loader
		- no entry section is needed, as .jbsa is set up
		- the only sections are 1776, pages, 1775, entries (which is
		   deleted), and 1777, end.  If
		- we assume that there is nothing in the core image 
		   except the low segment, high segment, and that the rest
		   is zero and unallocated.
	If there is something funny about the directory format, there is a
	good chance that we will detect it and give an error message, so
	long as the above assumptions are still good in the current
	monitor (they were as of when this was written).
  *)

type
  three=0..2;
  word=packed record case three of
		0:(LH:0..777777B;RH:0..777777B);
		1:(count:0..777B);
		2:(full:integer)
		end;

var
  exe_file:file of array[0:777B] of word;
  newdir:array[0:777B]of word;
  lastlo,lasthi,old,new,stpage,nextpage:integer;

procedure quit; extern;

procedure putpage(filepage,bits,mempage,rep:integer);
{note that rep and count are not a real count, but a "repetion factor",
 which is count-1}
  begin
  if filepage = 0 {See if we can extend an existing 0 block}
    then if new >= 3
      then if (newdir[new-2].rh = 0) and 
	      (newdir[new-1].rh + newdir[new-1].count + 1 = mempage) and
	      (newdir[new-2].count = bits)
        then begin
	newdir[new-1].count := newdir[new-1].count + rep + 1;
	goto 1
	end;
  newdir[new].full := filepage;
  newdir[new].count := bits;
  newdir[new+1].full := mempage;
  newdir[new+1].count := rep;
  new := new+2;
1:
  end;

begin

(* look at job data area and find boundaries of low and high segments *)

update(exe_file,'',true);
setpos(exe_file,1000B);
lastlo := exe_file^[44B].RH div 1000B;
(* now have to find vestigal job data area, page 400 *)
setpos(exe_file,0);
old := 1;
while not ((exe_file^[old].LH = 1775B) or (exe_file^[old].LH = 1777B)
	   or (exe_file^[old+1].RH = 400B)) do
  if exe_file^[old+1].RH > 400B
    then begin writeln(tty,'High segment doesn''t begin at 400000?'); quit end
  else if (old+2) > 777B
    then begin writeln(tty,'No end section in .EXE directory'); quit end
  else old := old+2;
if exe_file^[old+1].RH = 400B (* high seg. found *)
  then begin
  if exe_file^[old].RH = 0
    then begin writeln(tty,'Zero vestigial job data area'); quit end;
  setpos(exe_file,1000B*exe_file^[old].RH);
  lasthi := (exe_file^[3].LH - 1) div 1000B + 400B;
  end
 else lasthi := -1;  (* no high seg found *)

setpos(exe_file,0);

(* now we go through the page section of the directory recopying it to
   make it a legal tops-10 directory *)

old := 1; new := 1; nextpage := 0;

while not ((exe_file^[old].LH = 1775B) or (exe_file^[old].LH = 1777B)
	   or (exe_file^[old+1].RH > lastlo)) do
  begin {This loop processes the whole low seg}
  stpage := exe_file^[old+1].RH;  (* process page for this entry *)
{here we handle any gap between the last entry and this one}
  if stpage > nextpage  {gap between last entry and this}
  	then putpage(0,100B,nextpage,stpage-nextpage-1);
{now we process the entry itself}
  nextpage := stpage + exe_file^[old+1].count + 1;
     {if it ends above end of low seg, truncate it}
  if (stpage + exe_file^[new+1].count) > lastlo
    then putpage(exe_file^[old].RH,100B,exe_file^[old+1].RH,lastlo-stpage)
    else putpage(exe_file^[old].RH,100B,exe_file^[old+1].RH,exe_file^[old+1].count);
{finally, advance to next entry}
  old := old + 2;
  if old > 777B
    then begin writeln(tty,'No end section in .EXE directory');
	       quit end;
  end;

{now process high segment if any}
{find start of high seg - set old to point to it}
while not ((exe_file^[old].LH = 1775B) or (exe_file^[old].LH = 1777B)
	   or (exe_file^[old+1].RH = 400B)) do
  begin
  old := old + 2;
  if old > 777B
    then begin writeln(tty,'No end section in .EXE directory');
	       quit end;
  end;
nextpage := 400B;
{now process the pages}
while not ((exe_file^[old].LH = 1775B) or (exe_file^[old].LH = 1777B)
	   or (exe_file^[old+1].RH > lasthi)) do
  begin
{here we handle any gap between the last entry and this one}
  if stpage > nextpage  {gap between last entry and this}
  	then putpage(0,600B,nextpage,stpage-nextpage-1);
{now we process the entry itself}
  nextpage := stpage + exe_file^[old+1].count + 1;
     {if it ends above end of low seg, truncate it}
  if (stpage + exe_file^[new+1].count) > lasthi
    then putpage(exe_file^[old].RH,600B,exe_file^[old+1].RH,lasthi-stpage)
    else putpage(exe_file^[old].RH,600B,exe_file^[old+1].RH,exe_file^[old+1].count);
{finally, advance to next entry}
  old := old + 2;
  if old > 777B
    then begin writeln(tty,'No end section in .EXE directory');
	       quit end;
  end;

{now copy new data into the file}

for old := 1 to new-1 do
  exe_file^[old] := newdir[old];

{ update count in header}

exe_file^[0].RH := new;

(* now write an end section.  Note that we do not copy the entry section *)

exe_file^[new].full := 1777000001B;

(* now clear the rest of the page *)

for new := new+1 to 777B do
  exe_file^[new].full := 0;

(* now write out the new directory *)

putx(exe_file)

end.
