Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-01 - decus/20-0003/paslnx.not-quite-finished
There is 1 other file named paslnx.not-quite-finished in the archive. Click here to see a list.
{$m-,d-,c-}
program pasprm;
{  this is a replacement for pasprm in paslnk.mac, for use when you do
	not want to interface to the EXEC.  It calls a COMND jsys scanner}

{This program works in the following passes:
  1) scan all commands, set a few global switches saying what kind of
	command, and prepare filelist, listing all files
  2) scan all files, once for each language, putting out the command files,
	and building up a link command string.
  3) now execute the Pascal command list
  4) call the next step.
}

{A comment with %%%% in it will be used where edits are needed to add a
 language}

include 'pascmd.pas','string.pas';

const
	noswitch=0;
	zero=1;
	stack=2;
	objectlist=3;
	nomain=4;
	nodebug=5;
	nocheck=6;
	nobinary=7;
	list=8;
	heap=9;
	debug=10;
	cref=11;
	version=12;
	compile=13;
	load=14;
	noload=15;
	arithcheck=16;
	noarithcheck=17;
	pascal=18;
	macro=19;
	fortran=20;
{%%%%}
	lastswitch=20;

type retblk=record
	relnam:alfa;
	stkval:integer;
	heaval:integer;
	verval:integer;
	rpgsw:Boolean;
	crsw:Boolean;
	dsw:Boolean;
	csw:Boolean;
	msw:Boolean;
	tsw:Boolean;
	lsw:Boolean;
	zsw:Boolean;
	asw:Boolean
	end;

     retptr = ^ retblk;


  char3=packed array[1..3]of char;

  fileblock=record
	filename:packed array[1:200]of char;
	namefield:packed array[1:40]of char;
	switches:set of noswitch..lastswitch;
	stackval,heapval,versionval:integer;
	nextfile:^fileblock;
	language:integer;
	end;	
  fileptr = ^fileblock;

var
	firstrun:integer;  {the language Pascal will call, -1 for LINK}
{%%%%}
	macrolist,fortranlist,pascallist:^fileblock;
	first:Boolean;
	infile,relfile,linkfile:text;
	curfile,filelist:^fileblock;
	defaults:^fileblock;
	dodeb,noexec,nolink,ccl:Boolean;
	i,which,ptr,key:integer;
	switchtable:table;
	buf:packed array[1:200]of char;
	r:retptr;
	idate,odate:array[1:1]of integer;
	xwd:packed record case Boolean of
		true:(full:integer);
		false:(lh:0..777777B;rh:0..777777B)
		end;

initprocedure;
	begin
	first := true;
	end;

procedure quit; extern;

procedure pascmp; extern;

procedure run(prog:alfa); extern;

procedure linkcommand;
		var jobno:array[1:1]of integer;
		    tempname:packed array[1:12] of char;
		    i,j:integer;
	begin
	writeln(buf:findnull(buf)-1);
	if noexec
		then writeln('/G')
		else writeln('/G/E');
	close(output);
	end;

function getoct:integer;
		var x:packed record case Boolean of
			true:(word:integer);
			false:(junk:0..777777B;page:0..777B;addr:0..777B)
			end;
	begin
	x.word := cmnum8;
	with x do
		begin
		if (junk <> 0) or (page = 0)
			then begin
			writeln(tty); 
			writeln(tty,'?  Must be between 1000 and 777777');
			cmagain
			end;
		if addr = 0
			then page := page-1;
		addr := 777B;
		getoct := word;
		end;
	end;

procedure parseswitch;
	begin
	with curfile^ do
	case cmint of
		zero: switches := switches + [zero];
		-version: begin
			switches := switches + [version];
			versionval := cmnum8;
			end;
		-stack: begin
			switches := switches + [stack];
			stackval := getoct;
			end;
		objectlist: switches := switches + [objectlist];
		nomain: switches := switches + [nomain];
		nodebug: switches := switches + [nodebug];
		arithcheck: switches := switches + [arithcheck];
		noarithcheck: switches := switches + [noarithcheck];
		nocheck: switches := switches + [nocheck];
		nobinary: switches := switches + [nobinary];
		list: switches := switches + [list];
		-heap: begin
			switches := switches + [heap];
			heapval := getoct
			end;
		debug: dodeb := true;
		cref: switches := switches + [cref];
		compile: switches := switches + [compile];
		load: noexec := true;
		noload: nolink := true;
		fortran: switches := switches + [fortran];
		pascal: switches := switches + [pascal];
		macro: switches := switches + [macro];
{%%%%}
		end;
	end;

procedure dodef(switch:integer);
  begin
  if switch in defaults^.switches
    then curfile^.switches := curfile^.switches + [switch]
  end;

procedure dodefi(switch:integer;var dval,lval:integer);
  begin
  if (switch in defaults^.switches) and not
     (switch in curfile^.switches)
    then begin
    curfile^.switches := curfile^.switches + [switch];
    lval := dval
    end
  end;

{The default for /ARITH is the setting of /CHECK}
if not aswseen
  then r^.asw := r^.csw;
end;

procedure checkextension(defext:char3;language:integer);
  begin
  if curfile^.language <> 0
    then if (buf[1]=defext[1]) and (buf[2]=defext[2]) and
            (buf[3]=defext[3]) and (buf[4]=chr(0))
	   then curfile^.language := language
  end;

procedure checkswitch(language);
  begin
  if language in curfile^.switches
    then if curfile^.language = 0
           then curfile^.language := language
	   else cmuerr('More than one language specified')
  end;


{*****
 PASS1
 *****}

procedure pass1;
begin


{Switchtable is table of compiler switches}
switchtable := tbmak(20);
{%%%%}
tbadd(switchtable,zero,'ZERO',0);
tbadd(switchtable,version,'VERSION:',0);
tbadd(switchtable,stack,'STACK:',0);
tbadd(switchtable,pascal,'PASCAL',0);
tbadd(switchtable,objectlist,'OBJECTLIST',0);
tbadd(switchtable,nomain,'NOMAIN',0);
tbadd(switchtable,noload,'NOLOAD',0);
tbadd(switchtable,nodebug,'NODEBUG',0);
tbadd(switchtable,nocheck,'NOCHECK',0);
tbadd(switchtable,nobinary,'NOBINARY',0);
tbadd(switchtable,noarithcheck,'NOARITHCHECK',0);
tbadd(switchtable,macro,'MACRO',0);
tbadd(switchtable,load,'LOAD',0);
tbadd(switchtable,list,'LIST',0);
tbadd(switchtable,heap,'HEAP:',0);
tbadd(switchtable,fortra,'FORTRAN',0);
tbadd(switchtable,debug,'DEBUG',0);
tbadd(switchtable,cref,'CREF',0);
tbadd(switchtable,compile,'COMPILE',0);
tbadd(switchtable,arithcheck,'ARITHCHECK',0);



cminir('PASCAL>');
ccl := cmmode = rescan;
{init global state variables only - must be done after cminir in case
 of recycle due to typo}
noexec := false;
nolink := false;
ccl := false;
dodeb := false;
filelist := nil;

newz(curfile);  {Get a pseudo-file for global defaults}

loop  {parse switches, stop when come to a file name}
  cmmult;  {multiple mode}
  i := cmswi(switchtable);  {global switches}
  gjgen(100000000000B);	{an input file}
  gjext('PAS');
  cmfil(infile);
 exit if cmdo = 2;    {stop on file name}
  parseswitch   {sets values into car filelist as sideeffect}
 end;

defaults := curfile;  {copy pseudofile as defaults}

loop  {over file names}
  newz(curfile);    {new file block}

  {we have seen a file name - put it in the block}
  jsys(30B{jfns};-1:curfile^.filename,0:infile,111111140001B);
  jsys(30B{jfns};-1:curfile^.namefield,0:infile,001000B:0);
  jsys(30B{jfns};-1:buf,000100B:0);  {get extension}
  
  jsys(23B{rljfn},2;0:infile);

  loop  {parse switches, stop when come to comma or eol}
    cmmult;  {multiple mode}
    i := cmswi(switchtable);  {file switches}
    cmcma;  {comma}
    cmcfm;
    which := cmdo;
   exit if which <> 1;    {stop if not switch}
    parseswitch   {sets values into car filelist as sideeffect}
   end;

  {Now make sure we know the language, and validate some switches}
{%%%%}
  checkswitch(pascal);
  checkswitch(fortran);
  checkswitch(macro);
  checkextension('FOR',fortran);
  checkextension('MAC',macro);
  if curfile^.language = 0   {still undefined}
    then curfile^.language := pascal;
  if curfile^.language <> pascal
    then if ([zero,stack,objectlist,nomain,nodebug,nocheck,heap,version,
	     arithcheck,noarithcheck] * curfile^.switches) <> []
	   then cmuerr('Pascal switch used with another language');



  curfile^.nextfile := filelist;  {link it into the list}
  filelist := curfile;

 exit if which = 3;

  gjgen(100000000000B);	{an input file}
  gjext('PAS');
  cmfil(infile);
 
 end;
end;  {of PASS1}



procedure addtolist(var whichlist:fileptr);
  begin
  curfile^.nextfile := whichlist;
  whichlist := curfile
  end;

procedure opentemp(var f:file;lang:char3);
	begin
	jsys(507B{getji},2;-1,-1:jobno,0);
	tempname := '000LNK.TMP;T';
	i := jobno[1];
	for ptr := 3 downto 1 do	    {convert jobnumber to char's}
		begin
		tempname[ptr] := chr((i mod 10) + 60B);
		i := i div 10;
		end;
	for ptr := 1 to 3 do
		tempname[ptr+3] := lang[ptr];	
	rewrite(f,tempname);
	end;

procedure dolang(lang:integer;langlist:fileptr;langname:char3);
	var opened,doit:boolean;rellen:integer;
  begin
  opened := false;
  curfile := langlist;
  while curfile <> nil do
    begin
{process one file}

{first set up switch values}

    dodef(nobinary);
    dodef(list);
    dodef(cref);    
    dodef(compile);

{always put rel file name in link command}
    rellen := findnull(curfile^.namefield)+3
    putstr(curfile^.namefield,rellen-4,buf,1);
    buf[rellen-3] := '.';
    putstr('REL',3,buf,rellen-2);
    buf[rellen+1] := chr(0);
    writeln(linkfile,buf:rellen);
    
{Here we see if a compilation is really needed, by checking creation dates}
    doit := false;
{check for forced}
    if compile in curfile^.switches
      then doit := true;
{check for no rel file}
    if not doit
      then begin
      jsys(20B{gtjfn},2,i;100001B:0,-1:buf;relfile);
      if i = 1  {no rel file}
        then doit := true;
      end;
{check dates}
    if not doit
      then begin
      jsys(20B{gtjfn},2,i;100011B:0,-1:curfile^.filename;infile);
      if i <> 2
        then begin
        writeln(tty,'? Can''t get back input file: ',curfile^.filename:
  			findnull(curfile^.filename)-1);
        quit
        end;
      jsys(63B{gtfdb};infile,1:5,idate);
      jsys(63B{gtfdb};relfile,1:5,odate);
      if (odate[1] <= idate[1])
        then doit := true;
      jsys(23B{rljfn},2;0:infile);
      jsys(23B{rljfn},2;0:relfile);
      end;
{Now the code for actually doing a compilation}
    if doit
      then begin
      if not opened
	then begin
	opentemp(output,langname);
	opened := true
	end;
      if not (nobin in curfile^.switches)
	then write(buf:rellen);
      if list in curfile^.switches
	then write(',',curfile^.namefield:rellen-4,'.LST');
      writeln('=',curfile^.filename:findnull(curfile^.filename)-1);
      end;
    curfile := curfile^.nextfile;
    end;
  if opened {we wrote something}
    then begin
    if firstrun <> 0  {there is something to run after us}
      then begin
      if lang = fortran
	then write('/RUN:');
      case firstrun of
	-1: write('SYS:LINK');
	fortran: write('SYS:FORTRA');
	macro: write('SYS:MACRO');
	end;
      if lang <> fortran
	then write('!');
      writeln;
      end;
    close(output);
    end
  end;



{*****
 PASS2
 *****}

procedure pass2;
begin

if not nolink	{initialize for link}
	then begin
	opentemp(linkfile,'LNK');
	if dodeb
		then writeln(linkfile,'SYS:PASDDT');
	end;

{sort into lists by language}

{%%%%}
pascallist := nil;
fortranlist := nil;
macrolist := nil;

curfile := filelist;
while curfile <> nil do
  begin
  case curfile^.language of
{%%%%}
    pascal: addtolist(pascallist);
    fortran: addtolist(fortranlist);
    macro: addtolist(macro)
    end;
  curfile := curfile^.nextfile
  end;

if nolink
  then firstrun := 0
  else firstrun := -1;
  
{%%%%}
if fortranlist <> nil
  then dolang(fortran,fortranlist,'FOR');
if macrolist <> nil
  then dolang(macro,macrolist,'MAC');

if not nolink
  then begin

{do the part of dolang applying to pascal}
  curfile := pascallist;
  while curfile <> nil do
    begin
    writeln(linkfile,curfile^.namefield:findnull(curfile^.namefield)-1);
    curfile := curfile^.nextfile
    end;

{Closing stuff for link}
  if noexec
    then writeln(linkfile,'/G')
    else writeln(linkfile,'/E/G')
    end
  end;

end;  {of pass2}





{Pasprm is a coroutine with the Pascal compiler.  The first time
it is called we do the early passes.  The last time it is called,
we do the late passes}
function pasprm(var infile,outfile,relfile:text):retptr;
begin
if firsttime
  then begin
  pass1;
  pass2;
  pass3;
  if pascallist = nil
    then lastpasses  {never returns}
  end;  

firsttime := false;

newz(r);

while pascallist <> nil do
    begin

    curfile := pascallist;

    dodef(nobinary);
    dodef(list);
    dodef(cref);    
    dodef(compile);
    dodef(zero);
    dodefi(stack,defaults^.stackval,curfile^.stackval);
    dodef(objectlist);
    dodef(nomain);
    dodef(nodebug);
    dodef(nocheck);
    dodefi(heap,defaults^.heapval,curfile^.heapval);
    dodefi(version,defaults^.versionval,curfile^.versionval);
{/ARITH is the complex one}
    aswseen := false;
    if	(arithcheck in curfile^.switches) or
	(noarithcheck in curfile^.switches)
      then aswseen := true;
    if  not aswseen and
        ((arithcheck in defaults^.switches) or
	 (noarithcheck in defaults^.switches))
      then begin
      dodef(arithcheck);
      dodef(noarithcheck);
      aswseen := true;
      end;
    if not aswseen then
      if not (nocheck in curfile^.switches)
        then curfile^.switches := curfile^.switches + [arithcheck];

{And make the rel file be the input name.REL.  also copy name
 as output module name.}
    putstr(curfile^.namefield,40,buf,1);
    if buf[1] = chr(0)
	then begin
	putstr('MAIN',4,buf,1);
	buf[5] := chr(0);
	end;
    with r^ do
	begin
	ptr := findnull(buf);
	buf[ptr] := ' ';
	putstr(buf,10,relnam,1);
	end;
    putstr('.REL',4,buf,ptr);
    buf[ptr+4] := chr(0);

{Here we see if a compilation is really needed, by checking creation dates}
    jsys(20B{gtjfn},2,i;100001B:0,-1:buf;relfile);
if i = 2
  then begin
  jsys(63B{gtfdb};infile,1:5,idate);
  jsys(63B{gtfdb};relfile,1:5,odate);
  if (odate[1] > idate[1]) and not force\\\
    then begin  {not needed - call link now}
    jsys(23B{rljfn},2;0:infile);
    jsys(30B{jfns};-1:buf,0:relfile,201100B:1);
    jsys(23B{rljfn},2;0:relfile);
    calllink;
    end
  end;
jsys(23B{rljfn},2;0:relfile);
end;

if nobin\\\
  then jsys(20B{gtjfn},2;400011B:0,-1:'NUL:';relfile)
  else jsys(20B{gtjfn},2;400001B:0,-1:buf;relfile);
if dolist\\\ or r^.crsw or r^.lsw
  then begin
  if r^.crsw
    then putstr('CRF',3,buf,ptr+1)
    else putstr('LST',3,buf,ptr+1);
  jsys(20B{gtjfn},2;400001B:0,-1:buf;outfile);
  end
  else jsys(20B{gtjfn},2;400011B:0,-1:'NUL:';outfile);




with r^ do
	begin
r^.rpgsw := ccl;
	dsw := true;
	csw := true;
	msw := true;
	tsw := true;
	end;

pasprm := r
end;

procedure pasxit(var infile,outfile,relfile:text);
	begin
	close(infile);
	if ccl
		then jsys(30B{jfns};-1:buf,0:relfile,201100B:1);
	close(outfile);
	close(relfile);
	if ccl
		then calllink
		else pascmp
	end
.