[comp.sources.unix] v10i073: Pascal to C translator, Part09/12

rs@uunet.UU.NET (Rich Salz) (07/28/87)

Submitted-by: Per Bergsten <mcvax!enea!chalmers!holtec!perb>
Posting-number: Volume 10, Issue 73
Archive-name: ptoc/Part09


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 9 (of 12)."
# Contents:  ptc.p.3
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ptc.p.3' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ptc.p.3'\"
else
echo shar: Extracting \"'ptc.p.3'\" \(50280 characters\)
sed "s/^X//" >'ptc.p.3' <<'END_OF_FILE'
X					tx^.tto := ty^.thi
X				    end
X				else if ty^.tt = nscalar then
X				    begin
X					ty := ty^.tscalid;
X					tx^.tfrom := ty;
X					while ty^.tnext <> nil do
X						ty := ty^.tnext;
X					tx^.tto := ty
X				    end
X				else if ty = typnods[tchar] then
X				    begin
X					currsym.st := schar;
X					currsym.vchr := chr(minchar);
X					tx^.tfrom := mklit;
X					currsym.st := schar;
X					currsym.vchr := chr(maxchar);
X					tx^.tto := mklit
X				    end
X				else if ty = typnods[tinteger] then
X				    begin
X					currsym.st := sinteger;
X					currsym.vint := -maxint;
X					tx^.tfrom := mklit;
X					currsym.st := sinteger;
X					currsym.vint := maxint;
X					tx^.tto := mklit
X				    end
X				else
X					fatal(etree);
X				tx^.tforstmt := tz;
X				tx^.tincr := true
X			    end;
X			  npredef,
X			  nfileof:
X				if opn then
X				    begin
X					(* create file-struct initialization *)
X					ty := mknode(nselect);
X					ty^.trecord := ti;
X					ty^.tfield :=
X						oldid(defnams[dzinit]^.lid,
X								lforward);
X					tx := mknode(nassign);
X					tx^.tlhs := ty;
X					currsym.st := sinteger;
X					currsym.vint := 0;
X					tx^.trhs := mklit
X				    end
X				else begin
X					(* create file-struct wrapup *)
X					tx := mknode(ncall);
X					tx^.tcall := 
X						oldid(defnams[dclose]^.lid,
X								lidentifier);
X					tx^.taparm := ti
X				     end;
X			  nrecord:
X			    begin
X				ty := nil;
X				tq := tq^.tflist;
X				while tq <> nil do
X				    begin
X					if filevar(typeof(tq^.tbind)) then
X					    begin
X						tz := tq^.tidl;
X						while tz <> nil do
X						    begin
X							tx := mknode(nselect);
X							tx^.trecord := ti;
X							tx^.tfield := tz;
X							tx := fileinit(tx,
X							    typeof(tq^.tbind),
X								opn);
X							tx^.tnext := ty;
X							ty := tx;
X							tz := tz^.tnext
X						    end
X					    end;
X					tq := tq^.tnext
X				    end;
X				tx := mknode(nbegin);
X				tx^.tbegin := ty
X			    end;
X			end;(* case *)
X			fileinit := tx
X		end;
X
X	begin	(* initcode *)
X		while tp <> nil do
X		    begin
X			initcode(tp^.tsubsub);
X			tv := tp^.tsubvar;
X			while tv <> nil do
X			    begin
X				tq := typeof(tv^.tbind);
X				if filevar(tq) then
X				    begin
X					ti := tv^.tidl;
X					while ti <> nil do
X					    begin
X						tu := fileinit(ti, tq, true);
X						linkup(tp, tu);
X						tu^.tnext := tp^.tsubstmt;
X						tp^.tsubstmt := tu;
X						while tu^.tnext <> nil do
X							tu := tu^.tnext;
X						tu^.tnext := fileinit(ti, tq,
X									false);
X						linkup(tp, tu^.tnext);
X						ti := ti^.tnext
X					    end
X				    end;
X				tv := tv^.tnext;
X			    end;
X			tp := tp^.tnext
X		    end
X	end;	(* initcode *)
X
Xbegin	(* transform *)
X	renamc;
X	renamp(top^.tsubsub, false);
X	extract(top);
X	renamf(top);
X	initcode(top^.tsubsub);
X	global(top, top, false)
Xend;	(* transform *)
X
X(*	Emit C-code for program or module.				*)
Xprocedure emit;
X
Xconst	include	= '# include ';
X	define	= '# define ';
X	ifdef	= '# ifdef ';
X	ifndef	= '# ifndef ';
X	elsif	= '# else';
X	endif	= '# endif';
X	static	= 'static ';
X	xtern	= 'extern ';
X	typdef	= 'typedef ';
X	registr	= 'register ';
X	usigned	= 'unsigned ';
X	indstep	= 8;
X
Xvar	conflag,
X	setused,
X	dropset,
X	donearr	: boolean;
X	doarrow,
X	indnt	: integer;
X
X	procedure increment;
X	begin
X		indnt := indnt + indstep
X	end;
X
X	procedure decrement;
X	begin
X		indnt := indnt - indstep
X	end;
X
X	(*	Write tabs/blanks to properly (?) indent C-code.	*) 
X	procedure indent;
X
X	var	i	: integer;
X
X	begin
X		i := indnt;
X		(* limit indent to an integral number of tabs *)
X		if i > 60 then
X			i := i div tabwidth * tabwidth;
X		while i >= tabwidth do
X		    begin
X			write(tab1);
X			i := i - tabwidth
X		    end;
X		while i > 0 do
X		    begin
X			write(space);
X			i := i - 1
X		    end;
X	end;
X
X	(*	Determine if tp must be cast to an integer before being	*)
X	(*	used in an arithmetic expression.			*)
X	function arithexpr(tp : treeptr) : boolean;
X
X	begin
X		tp := typeof(tp);
X		if tp^.tt = nsubrange then
X			if tp^.tup^.tt = nconfarr then
X				tp := typeof(tp^.tup^.tindtyp)
X			else
X				tp := typeof(tp^.tlo);
X		arithexpr := (tp = typnods[tinteger]) or
X				(tp = typnods[tchar]) or
X					(tp = typnods[treal])
X	end;
X
X	procedure eexpr(tp : treeptr);				forward;
X	procedure etypedef(tp : treeptr);			forward;
X
X	(*	Emit code to select a record member.	*)
X	procedure eselect(tp : treeptr);
X
X	begin
X		doarrow := doarrow + 1;
X		eexpr(tp);
X		doarrow := doarrow - 1;
X		if donearr then
X			donearr := false
X		else
X			write('.')
X	end;
X
X	(*	Emit code for call to a predefined function/procedure.	*)
X	procedure epredef(ts, tp : treeptr);
X
X	label	444, 555;
X
X	var	tq,
X		tv, tx	: treeptr;
X		td	: predefs;
X		nelems	: integer;
X		ch	: char;
X		txtfile	: boolean;
X
X		(*	Determine a format-code for fprintf.		*)
X		(*	Update nelems as a sideeffect.			*)
X		function typeletter(tp : treeptr) : char;
X
X		label	999;
X
X		var	tq	: treeptr;
X
X		begin
X			tq := tp;
X			if tq^.tt = nformat then
X			    begin
X				if tq^.texpl^.tt = nformat then
X				    begin
X					typeletter := 'f';
X					goto 999
X				    end;
X				tq := tp^.texpl
X			    end;
X			tq := typeof(tq);
X			if tq^.tt = nsubrange then
X				tq := typeof(tq^.tlo);
X			if tq = typnods[tstring] then
X				typeletter := 's'
X			else if tq = typnods[tinteger] then
X				typeletter := 'd'
X			else if tq = typnods[tchar] then
X				typeletter := 'c'
X			else if tq = typnods[treal] then
X				if tp^.tt = nformat then
X					typeletter := 'e'
X				else
X					typeletter := 'g'
X			else if tq = typnods[tboolean] then
X			    begin
X				typeletter := 'b';
X				nelems := 6
X			    end
X			else if tq^.tt = narray then
X			    begin
X				typeletter := 'a';
X				nelems := crange(tq^.taindx)
X			    end
X			else if tq^.tt = nconfarr then
X			    begin
X				typeletter := 'v';
X				nelems := 0
X			    end
X			else
X				fatal(etree);
X		999:
X		end;	(* typeletter *)
X
X		procedure etxt(tp : treeptr);
X
X		var	w	: toknbuf;
X			c	: char;
X			i	: toknidx;
X
X		begin
X			case tp^.tt of
X			  nid:
X			    begin
X				tp := idup(tp);
X				if tp^.tt = nconst then
X					etxt(tp^.tbind)
X				else
X					fatal(etree)
X			    end;
X			  nstring:
X			    begin
X				(* printf format string *)
X				gettokn(tp^.tsym^.lstr, w);
X				i := 1;
X				while w[i] <> chr(null) do
X				    begin
X					c := w[i];
X					if (c = cite) or (c = bslash) then
X						write(bslash)
X					else if c = percent then
X						write(percent);
X					write(c);
X					i := i + 1
X				    end
X			    end;
X			  nchar:
X			    begin
X				(* single character in printf format *)
X				c := tp^.tsym^.lchar;
X				if (c = cite) or (c = bslash) then
X					write(bslash)
X				else if c = percent then
X					write(percent);
X				write(c)
X			    end;
X			end;(* case *)
X		end;	(* etxt *)
X
X		(*	Emit format for fprintf.			*)
X		procedure eformat(tq : treeptr);
X
X		var	tx	: treeptr;
X			i	: integer;
X
X		begin
X			case typeletter(tq) of
X			  'a':
X			    begin
X				write(percent);
X				if tq^.tt = nformat then
X					if tq^.texpr^.tt = ninteger then
X						eexpr(tq^.texpr)
X					else
X						write('*');
X				write('.', nelems:1, 's')
X			    end;
X			  'b':
X			    begin
X				write(percent);
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt = ninteger then
X						eexpr(tq^.texpr)
X					else
X						write('*')
X				    end;
X				write('s')
X			    end;
X			  'c':
X				if tq^.tt = nchar then
X					etxt(tq)
X				else begin
X					write(percent);
X					if tq^.tt = nformat then
X						if tq^.texpr^.tt = ninteger then
X							eexpr(tq^.texpr)
X						else
X							write('*');
X					write('c')
X				     end;
X			  'd':
X			    begin
X				write(percent);
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt = ninteger then
X						eexpr(tq^.texpr)
X					else
X						write('*')
X				    end
X				else
X					write(intlen:1);
X				write('d')
X			    end;
X			  'e':
X			    begin
X				write(percent, space);
X				tx := tq^.texpr;
X				if tx^.tt = ninteger then
X				    begin
X					i := cvalof(tx);
X					write(i:1, '.');
X					i := i - 7;
X					if i < 1 then
X						write('1')
X					else
X						write(i:1)
X				    end
X				else
X					write('*.*');
X				write('e')
X			    end;
X			  'f':
X			    begin
X				write(percent);
X				tx := tq^.texpl;
X				if tx^.texpr^.tt = ninteger then
X				    begin
X					eexpr(tx^.texpr);
X					write('.');
X					tx := tq^.texpr;
X					if tx^.tt = ninteger then
X					    begin
X						i := cvalof(tx);
X						tx := tq^.texpl^.texpr;
X						if i > cvalof(tx) - 1 then
X							write('1')
X						else
X							write(i:1)
X					    end
X					else
X						write('*');
X				    end
X				else
X					write('*.*');
X				write('f')
X			    end;
X			  'g':
X				write(percent, fixlen:1, 'e');
X			  's':
X				if tq^.tt = nstring then
X					etxt(tq)
X				else begin
X					write(percent);
X					if tq^.tt = nformat then
X						if tq^.texpr^.tt = ninteger then
X							eexpr(tq^.texpr)
X						else
X							write('*.*');
X					write('s')
X				     end
X			end (* case *)
X		end;	(* eformat *)
X
X		(*	Emit parameters to fprintf except format.	*)
X		procedure ewrite(tq : treeptr);
X
X		var	tx	: treeptr;
X
X		begin
X			case typeletter(tq) of
X			  'a':
X			    begin
X				write(', ');
X				tx := tq;
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt <> ninteger then
X					    begin
X					      eexpr(tq^.texpr);
X					      write(', ')
X					    end;
X					tx := tq^.texpl
X				    end;
X				eexpr(tx);
X				write('.A')
X			    end;
X			  'b':
X			    begin
X				write(', ');
X				tx := tq;
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt <> ninteger then
X					    begin
X					      eexpr(tq^.texpr);
X					      write(', ')
X					    end;
X					tx := tq^.texpl
X				    end;
X				usebool := true;
X				write('Bools[(int)(');
X				eexpr(tx);
X				write(')]')
X			    end;
X			  'c':
X			    begin
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt <> ninteger then
X					    begin
X						write(', ');
X						eexpr(tq^.texpr)
X					    end;
X					write(', ');
X					eexpr(tq^.texpl)
X				    end
X				else if tq^.tt <> nchar then
X				    begin
X					write(', ');
X					eexpr(tq)
X				    end
X			    end;
X			  'd':
X			    begin
X				write(', ');
X				tx := tq;
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt <> ninteger then
X					    begin
X						eexpr(tq^.texpr);
X						write(', ')
X					    end;
X					tx := tq^.texpl
X				    end;
X				eexpr(tx)
X			    end;
X			  'e':
X			    begin
X				write(', ');
X				tx := tq^.texpr;
X				if tx^.tt <> ninteger then
X				    begin
X					usemax := true;
X					eexpr(tx);
X					write(', Max(');
X					eexpr(tx);
X					write(' - 7, 1), ')
X				    end;
X				eexpr(tq^.texpl)
X			    end;
X			  'f':
X			    begin
X				write(', ');
X				tx := tq^.texpl;
X				if tx^.texpr^.tt <> ninteger then
X				    begin
X					eexpr(tx^.texpr);
X					write(', ')
X				    end;
X				if (tx^.texpr^.tt <> ninteger) or
X					(tq^.texpr^.tt <> ninteger) then
X				    begin
X					usemax := true;
X					write('Max((');
X					eexpr(tx^.texpr);
X					write(') - (');
X					eexpr(tq^.texpr);
X					write(') - 1, 1), ')
X				    end;
X				eexpr(tq^.texpl^.texpl)
X			    end;
X			  'g':
X			    begin
X				write(', ');
X				eexpr(tq)
X			    end;
X			  's':
X			    begin
X				if tq^.tt = nformat then
X				    begin
X					if tq^.texpr^.tt <> ninteger then
X					   begin
X						write(', ');
X						eexpr(tq^.texpr);
X						write(', ');
X						eexpr(tq^.texpr)
X					   end;
X					write(', ');
X					eexpr(tq^.texpl)
X				    end
X				else if tq^.tt <> nstring then
X				    begin
X					write(', ');
X					eexpr(tq)
X				    end
X			    end
X			end (* case *)
X		end;	(* ewrite *)
X
X		(*	Emit size of *tp for call to malloc. CPU	*)
X		(*	There is no safe way to compute the size of a	*)
X		(*	particular variant of a C-union, we assume that	*)
X		(*	the size can be computed by taking the address	*)
X		(*	of the first member and subracting the address	*)
X		(*	of the record and then adding the size of the	*)
X		(*	variant containing the record.			*)
X		procedure enewsize(tp : treeptr);
X
X		label	555;
X
X		var	tq, tx, ty	: treeptr;
X			v		: integer;
X
X			(*	Emit size of union member tq.		*)
X			procedure esubsize(tp, tq : treeptr);
X
X			label	555, 666;
X
X			var	tx, ty	: treeptr;
X				addsize	: boolean;
X
X			begin
X				tx := tq^.tvrnt;
X				ty := tx^.tflist;
X				if ty = nil then
X				    begin
X					ty := tx^.tvlist;
X					while ty <> nil do
X					    begin
X						if ty^.tvrnt^.tflist <> nil then
X						    begin
X							ty := ty^.tvrnt^.tflist;
X							goto 555
X						    end;
X						ty := ty^.tnext
X					    end;
X				555:
X				    end;
X				addsize := true;
X				if ty = nil then
X				    begin
X					(* empty variant, try using another *)
X					addsize := false;
X					ty := tx^.tup^.tup^.tvlist;
X					while ty <> nil do
X					    begin
X						if ty^.tvrnt^.tflist <> nil then
X						    begin
X							ty := ty^.tvrnt^.tflist;
X							goto 666
X						    end;
X						ty := ty^.tnext
X					    end;
X				666:
X				    end;
X				if ty = nil then
X				    begin
X					(* its getting too complicated,
X						ignore tag value *)
X					write('sizeof(*');
X					eexpr(tp);
X					write(')')
X				    end
X				else begin
X					(* compute offset to first member of
X					   the selected union variant *)
X					write('Unionoffs(');
X					eexpr(tp);
X					write(', ');
X					printid(ty^.tidl^.tsym^.lid);
X					if addsize then
X					    begin
X						(* add the size of the selected
X						   union variant *)
X						write(') + sizeof(');
X						eexpr(tp);
X						write('->');
X						printid(tx^.tuid)
X					    end;
X					write(')')
X				     end
X			end;
X
X		begin	(* newsize *)
X			if (tp^.tnext <> nil) and unionnew then
X			    begin
X				(* tnext points to a tag-value, evaluate it *)
X				v := cvalof(tp^.tnext);
X				(* find union type *)
X				tq := typeof(tp);
X				tq := typeof(tq^.tptrid);
X				if tq^.tt <> nrecord then
X					fatal(etree);
X				(* find corresponding variant *)
X				tx := tq^.tvlist;
X				while tx <> nil do
X				    begin
X					ty := tx^.tselct;
X					while ty <> nil do
X					    begin
X						if v = cvalof(ty) then
X							goto 555;
X						ty := ty^.tnext
X					    end;
X					tx := tx^.tnext
X				    end;
X				fatal(etag);
X			555:
X				(* emit size for that variant *)
X				esubsize(tp, tx)
X			    end
X			else begin
X				write('sizeof(*');
X				eexpr(tp);
X				write(')')
X			     end
X		end;	(* newsize *)
X
X	begin	(* epredef *)
X		td := ts^.tsubstmt^.tdef;
X		case td of
X		  dabs:
X		    begin
X			tq := typeof(tp^.taparm);
X			if (tq = typnods[tinteger]) or (tq^.tt = nsubrange) then
X				write('abs(')			(* LIB *)
X			else
X				write('fabs(');			(* LIB *)
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dargv:
X		    begin
X			write('Argvgt(');
X			eexpr(tp^.taparm);
X			write(', ');
X			eexpr(tp^.taparm^.tnext);
X			write('.A, sizeof(');
X			eexpr(tp^.taparm^.tnext);
X			writeln('.A));')
X		    end;
X		  dchr:
X		    begin
X			tq := typeof(tp^.taparm);
X			if tq^.tt = nsubrange then
X				if tq^.tup^.tt = nconfarr then
X					tq := typeof(tq^.tup^.tindtyp)
X				else
X					tq := typeof(tq^.tlo);
X			if (tq = typnods[tinteger]) or
X						(tq = typnods[tchar]) then
X				eexpr(tp^.taparm)
X			else begin
X				write('(char)(');
X				eexpr(tp^.taparm);
X				write(')')
X			     end
X		    end;
X		  ddispose:
X		    begin
X			write('free(');				(* LIB *)
X			eexpr(tp^.taparm);
X			writeln(');')
X		    end;
X		  deof:
X		    begin
X			write('Eof(');
X			if tp^.taparm = nil then
X			    begin
X				defnams[dinput]^.lused := true;
X				printid(defnams[dinput]^.lid)
X			    end
X			else
X				eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  deoln:
X		    begin
X			write('Eoln(');
X			if tp^.taparm = nil then
X			    begin
X				defnams[dinput]^.lused := true;
X				printid(defnams[dinput]^.lid)
X			    end
X			else
X				eexpr(tp^.taparm);
X			write(')');
X		    end;
X		  dexit:
X		    begin
X			write('exit(');				(* OS *)
X			if tp^.taparm = nil then
X				write('0')
X			else
X				eexpr(tp^.taparm);
X			writeln(');');
X		    end;
X		  dflush:
X		    begin
X			write('fflush(');			(* LIB *)
X			if tp^.taparm = nil then
X			    begin
X				defnams[doutput]^.lused := true;
X				printid(defnams[doutput]^.lid)
X			    end
X			else
X				eexpr(tp^.taparm);
X			writeln('.fp);')
X		    end;
X		  dpage:
X		    begin
X			(* write form-feed character *)
X			write('Putchr(', ffchr, ', '); (* CHAR *)
X			if tp^.taparm = nil then
X			    begin
X				defnams[doutput]^.lused := true;
X				printid(defnams[doutput]^.lid)
X			    end
X			else
X				eexpr(tp^.taparm);
X			writeln(');');
X		    end;
X		  dput,
X		  dget:
X		    begin
X			if typeof(tp^.taparm) = typnods[ttext] then
X				if td = dget then
X					write('Getx')
X				else
X					write('Putx')
X			else begin
X				write(voidcast);
X				if td = dget then
X					write('Get')
X				else
X					write('Put')
X			     end;
X			write('(');
X			eexpr(tp^.taparm);
X			writeln(');')
X		    end;
X		  dhalt:
X			writeln('abort();');			(* OS *)
X		  dnew:
X		    begin
X			eexpr(tp^.taparm);
X			write(' = (');
X			etypedef(typeof(tp^.taparm));
X			write(')malloc((unsigned)(');	(* LIB *)
X			enewsize(tp^.taparm);
X			writeln('));')
X		    end;
X		  dord:
X		    begin
X			write('(unsigned)(');
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dread,
X		  dreadln:
X		    begin
X			txtfile := false;
X			tq := tp^.taparm;
X			if tq <> nil then
X			    begin
X				tv := typeof(tq);
X				if tv = typnods[ttext] then
X				    begin
X					(* reading from textfile *)
X					txtfile := true;
X					tv := tq;
X					tq := tq^.tnext
X				    end
X				else if tv^.tt = nfileof then
X				    begin
X					(* reading from other file *)
X					txtfile := typeof(tv^.tof) =
X							typnods[tchar];
X					tv := tq;
X					tq := tq^.tnext
X				    end
X				else begin
X					(* reading from std-input *)
X					txtfile := true;
X					tv := nil
X				     end
X			    end
X			else begin
X				tv := nil;
X				txtfile := true
X			     end;
X			if txtfile then
X			    begin
X				(* check for special case *)
X				if tq = nil then
X					goto 444;
X				if (tq^.tt <> nformat) and
X						(tq^.tnext = nil) and
X						(typeletter(tq) = 'c') then
X				    begin
X					(* read single char *)
X					eexpr(tq);
X					write(' = ');
X					write('Getchr(');
X					if tv = nil then
X						printid(defnams[dinput]^.lid)
X					else
X						eexpr(tv);
X					write(')');
X					if td = dreadln then
X						write(',');
X					goto 444
X				    end;
X				usescan := true;
X				write('Fscan(');
X				if tv = nil then
X					printid(defnams[dinput]^.lid)
X				else
X					eexpr(tv);
X				write('), ');
X				(* first pass, emit format string *)
X				while tq <> nil do
X				    begin
X					write('Scan(', cite);
X					ch := typeletter(tq);
X					case ch of
X					  'a':
X						write(percent, 's');
X					  'c':
X						write(percent, 'c');
X					  'd':
X						write(percent, 'ld');
X					  'g':
X						write(percent, 'le')
X					end;(* case *)
X					write(cite, ', ');
X					case ch of
X					  'a':
X					    begin
X						eexpr(tq);
X						write('.A')
X					    end;
X					  'c':
X					    begin
X						write('&');
X						eexpr(tq)
X					    end;
X					  'd':
X						write('&Tmplng');
X					  'g':
X						write('&Tmpdbl')
X					end;(* case *)
X					write(')');
X					case ch of
X					  'd':
X					    begin
X						write(', ');
X						eexpr(tq);
X						write(' = Tmplng')
X					    end;
X					  'g':
X					    begin
X						write(', ');
X						eexpr(tq);
X						write(' = Tmpdbl')
X					    end;
X					  'a',
X					  'c':
X						(* no op *)
X					end;(* case *)
X					tq := tq^.tnext;
X					if tq <> nil then
X					    begin
X						writeln(',');
X						indent;
X						write(tab1)
X					    end
X				    end;
X				write(', Getx(');
X				if tv = nil then
X					printid(defnams[dinput]^.lid)
X				else
X					eexpr(tv);
X				write(')');
X				if td = dreadln then
X					write(',');
X			444:
X				if td = dreadln then
X				    begin
X					usegetl := true;
X					write('Getl(&');
X					if tv = nil then
X						printid(defnams[dinput]^.lid)
X					else
X						eexpr(tv);
X					write(')')
X				    end
X			    end
X			else begin
X				increment;
X				while tq <> nil do
X				    begin
X					write(voidcast, 'Fread(');
X					eexpr(tq);
X					write(', ');
X					eexpr(tv);
X					write('.fp)');
X					tq := tq^.tnext;
X					if tq <> nil then
X					    begin
X						writeln(',');
X						indent
X					    end
X				    end;
X				decrement
X			     end;
X			writeln(';')
X		    end;
X		  dwrite,
X		  dwriteln,
X		  dmessage:
X		    begin
X			txtfile := false;
X			tq := tp^.taparm;
X			if tq <> nil then
X			    begin
X				tv := typeof(tq);
X				if tv = typnods[ttext] then
X				    begin
X					(* writing to textfile *)
X					txtfile := true;
X					tv := tq;
X					tq := tq^.tnext
X				    end
X				else if tv^.tt = nfileof then
X				    begin
X					(* writing to other file *)
X					txtfile := typeof(tv^.tof) =
X							typnods[tchar];
X					tv := tq;
X					tq := tq^.tnext
X				    end
X				else begin
X					(* writing to std-output *)
X					txtfile := true;
X					tv := nil
X				     end
X			    end
X			else begin
X				tv := nil;
X				txtfile := true
X			     end;
X			if txtfile then
X			    begin
X				(* check for special case *)
X				if tq = nil then
X				    begin
X					(* writeln whithout parameters *)
X					if td in [dwriteln, dmessage] then
X					    begin
X						write('Putchr(', nlchr, ', ');
X						if tv = nil then
X							printid(
X							  defnams[doutput]^.lid)
X						else
X							eexpr(tv);
X						write(')')
X					    end;
X					writeln(';');
X					goto 555
X				    end
X				else if (tq^.tt <> nformat) and
X						(tq^.tnext = nil) then
X					if typeletter(tq) = 'c' then
X					    begin
X						(* print single char *)
X						write('Putchr(');
X						eexpr(tq);
X						write(', ');
X						if tv = nil then
X							printid(
X							  defnams[doutput]^.lid)
X						else
X							eexpr(tv);
X						write(')');
X						if td = dwriteln then
X						    begin
X							write(',Putchr(',
X							    nlchr, ', ');
X							if tv = nil then
X							 printid(
X							  defnams[doutput]^.lid)
X							else
X								eexpr(tv);
X							write(')');
X						    end;
X						writeln(';');
X						goto 555
X					    end;
X				tx := nil;
X				write(voidcast, 'fprintf(');	(* LIB *)
X				if td = dmessage then
X					write('stderr, ')
X				else begin
X					if tv = nil then
X						printid(defnams[doutput]^.lid)
X					else
X						eexpr(tv);
X					write('.fp, ')
X				     end;
X				write(cite);
X				tx := tq;	(* remember 1:st parm *)
X				(* first pass, emit format string *)
X				while tq <> nil do
X				    begin
X					eformat(tq);
X					tq := tq^.tnext
X				    end;
X				if (td = dmessage) or (td = dwriteln) then
X					write('\n');
X				write(cite);
X				(* second pass, add parameters *)
X				tq := tx;
X				while tq <> nil do
X				    begin
X					ewrite(tq);
X					tq := tq^.tnext
X				    end;
X				write('), Putl(');
X				if tv = nil then
X					printid(defnams[doutput]^.lid)
X				else
X					eexpr(tv);
X				if td = dwrite then
X					write(', 0)')
X				else
X					write(', 1)')
X			    end
X			else begin
X				increment;
X				tx := typeof(tv);
X				if tx = typnods[ttext] then
X					tx := typnods[tchar]
X				else if tx^.tt = nfileof then
X					tx := typeof(tx^.tof)
X				else
X					fatal(etree);
X				while tq <> nil do
X				    begin
X					if (tq^.tt in [nid, nindex, nselect,
X							nderef]) and
X						(tx = typeof(tq)) then
X					    begin
X						write(voidcast, 'Fwrite(');
X						eexpr(tq)
X					    end
X					else begin
X						if tx^.tt = nsetof then
X						    begin
X							usescpy := true;
X							write('Setncpy(');
X							eselect(tv);
X							write('buf.S, ');
X							eexpr(tq);
X							if typeof(tp^.trhs) =
X							   typnods[tset] then
X								eexpr(tq)
X							else begin
X								eselect(tq);
X								write('S')
X							     end;
X							write(', sizeof(');
X							eexpr(tv);
X							write('.buf))');
X						    end
X						else begin
X							eexpr(tv);
X							write('.buf = ');
X							eexpr(tq)
X						     end;
X						write(', Fwrite(');
X						eexpr(tv);
X						write('.buf');
X					     end;
X					write(', ');
X					eexpr(tv);
X					write('.fp)');
X					tq := tq^.tnext;
X					if tq <> nil then
X					    begin
X						writeln(',');
X						indent
X					    end
X				    end;
X				decrement
X			     end;
X			writeln(';');
X		555:
X		    end;
X		  dclose:
X		    begin
X			tq := typeof(tp^.taparm);
X			txtfile := tq = typnods[ttext];
X			if (not txtfile) and (tq^.tt = nfileof) then
X				if typeof(tq^.tof) = typnods[tchar] then
X					txtfile := true;
X			if txtfile then
X				write('Closex(')
X			else
X				write('Close(');
X			eexpr(tp^.taparm);
X			writeln(');');
X		    end;
X		  dreset,
X		  drewrite:
X		    begin
X			tq := typeof(tp^.taparm);
X			txtfile := tq = typnods[ttext];
X			if (not txtfile) and (tq^.tt = nfileof) then
X				if typeof(tq^.tof) = typnods[tchar] then
X					txtfile := true;
X			if txtfile then
X				if td = dreset then
X					write('Resetx(')
X				else
X					write('Rewritex(')
X			else
X				if td = dreset then
X					write('Reset(')
X				else
X					write('Rewrite(');
X			eexpr(tp^.taparm);
X			write(', ');
X			tq := tp^.taparm^.tnext;
X			if tq = nil then
X				write('NULL')
X			else begin
X				tq := typeof(tq);
X				if tq = typnods[tchar] then
X				    begin
X					write(cite);
X					ch := chr(cvalof(tp^.taparm^.tnext));
X					if (ch = bslash) or (ch = cite) then
X						write(bslash);
X					write(ch, cite)
X				    end
X				else if tq = typnods[tstring] then
X					eexpr(tp^.taparm^.tnext)
X				else  if tq^.tt in [narray, nconfarr] then
X				     begin
X					eexpr(tp^.taparm^.tnext);
X					write('.A')
X				     end
X				else
X					fatal(etree)
X			     end;
X			writeln(');')
X		    end;
X		  darctan:
X		    begin
X			write('atan(');	(* LIB *)
X			if typeof(tp^.taparm) <> typnods[treal] then
X				write(dblcast);
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dln:
X		    begin
X			write('log(');	(* LIB *)
X			if typeof(tp^.taparm) <> typnods[treal] then
X				write(dblcast);
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dexp:
X		    begin
X			write('exp(');	(* LIB *)
X			if typeof(tp^.taparm) <> typnods[treal] then
X				write(dblcast);
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dcos,
X		  dsin,
X		  dsqrt:
X		    begin
X			eexpr(tp^.tcall);	(* LIB *)
X			write('(');
X			if typeof(tp^.taparm) <> typnods[treal] then
X				write(dblcast);
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dtan:
X		    begin
X			write('atan(');		(* LIB *)
X			if typeof(tp^.taparm) <> typnods[treal] then
X				write(dblcast);
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dsucc,
X		  dpred:
X		    begin
X			tq := typeof(tp^.taparm);
X			if tq^.tt = nsubrange then
X				if tq^.tup^.tt = nconfarr then
X					tq := typeof(tq^.tup^.tindtyp)
X				else
X					tq := typeof(tq^.tlo);
X			if (tq = typnods[tinteger]) or
X						(tq = typnods[tchar]) then
X			    begin
X				write('((');
X				eexpr(tp^.taparm);
X				if td = dpred then
X					write(')-1)')
X				else
X					write(')+1)')
X			    end
X			else begin
X				(* some sort of scalar type, casting needed *)
X				write('(');
X				tq := tq^.tup;
X				if tq^.tt = ntype then
X				    begin
X					(* cast only if it is a named type *)
X					write('(');
X					printid(tq^.tidl^.tsym^.lid);
X					write(')')
X				    end;
X				write('((int)(');
X				eexpr(tp^.taparm);
X				if td = dpred then
X					write(')-1))')
X				else
X					write(')+1))')
X			     end
X		    end;
X		  dodd:
X		    begin
X			write('(');
X			printid(defnams[dboolean]^.lid);
X			write(')((');
X			eexpr(tp^.taparm);
X			write(') & 1)')
X		    end;
X		  dsqr:
X		    begin
X			tq := typeof(tp^.taparm);
X			if (tq = typnods[tinteger]) or (tq^.tt = nsubrange) then
X			    begin
X				write('((');
X				eexpr(tp^.taparm);
X				write(') * (');
X				eexpr(tp^.taparm);
X				write('))')
X			    end
X			else begin
X				write('pow(');	(* LIB *)
X				if typeof(tp^.taparm) <> typnods[treal] then
X					write(dblcast);
X				eexpr(tp^.taparm);
X				write(', 2.0)')
X			     end
X		    end;
X		  dround:
X		    begin
X			write('Round(');
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dtrunc:
X		    begin
X			write('Trunc(');
X			eexpr(tp^.taparm);
X			write(')')
X		    end;
X		  dpack:
X		    begin
X			tq := typeof(tp^.taparm);
X			tx := typeof(tp^.taparm^.tnext^.tnext);
X			write('{    ', registr, inttyp, tab1, '_j, _i = ');
X			if not arithexpr(tp^.taparm^.tnext) then
X				write('(int)');
X			eexpr(tp^.taparm^.tnext);
X			if tx^.tt = narray then
X				write(' - ', clower(tq^.taindx):1);
X			writeln(';');
X			indent;
X			write('    for (_j = 0; _j < ');
X			if tq^.tt = nconfarr then
X			    begin
X				write('(int)(');
X				printid(tx^.tcindx^.thi^.tsym^.lid);
X				write(')')
X			    end
X			else
X				write(crange(tx^.taindx):1);
X			writeln('; )');
X			indent;
X			write(tab1);
X			eexpr(tp^.taparm^.tnext^.tnext);
X			write('.A[_j++] = ');
X			eexpr(tp^.taparm);
X			writeln('.A[_i++];');
X			indent;
X			writeln('}')
X		    end;
X		  dunpack:
X		    begin
X			tq := typeof(tp^.taparm);
X			tx := typeof(tp^.taparm^.tnext);
X			write('{   ', registr, inttyp, tab1, '_j, _i = ');
X			if not arithexpr(tp^.taparm^.tnext^.tnext) then
X				write('(int)');
X			eexpr(tp^.taparm^.tnext^.tnext);
X			if tx^.tt <> nconfarr then
X				write(' - ', clower(tx^.taindx):1);
X			writeln(';');
X			indent;
X			write('    for (_j = 0; _j < ');
X			if tq^.tt = nconfarr then
X			    begin
X				write('(int)(');
X				printid(tq^.tcindx^.thi^.tsym^.lid);
X				write(')')
X			    end
X			else
X				write(crange(tq^.taindx):1);
X			writeln('; )');
X			indent;
X			write(tab1);
X			eexpr(tp^.taparm^.tnext);
X			write('.A[_i++] = ');
X			eexpr(tp^.taparm);
X			writeln('.A[_j++];');
X			indent;
X			writeln('}')
X		    end;
X		end (* case *)
X	end;	(* epredef *)
X
X	procedure eaddr(tp : treeptr);
X
X	begin
X		write('&');
X		if not(tp^.tt in [nid, nselect, nindex, nderef]) then
X			error(evarpar);
X		eexpr(tp)
X	end;
X
X	(*	Emit code for a subroutine call.			*)
X	procedure ecall(tp : treeptr);
X
X	var	tf, tq, tx	: treeptr;
X
X	begin
X		(* find first formal parameter id *)
X		tf := idup(tp^.tcall);
X		case tf^.tt of
X		  nproc,
X		  nfunc:
X			tf := tf^.tsubpar;
X		  nparproc,
X		  nparfunc:
X			tf := tf^.tparparm
X		end;(* case *)
X		if tf <> nil then
X		    begin
X			case tf^.tt of
X			  nvalpar,
X			  nvarpar:
X				tf := tf^.tidl;
X			  nparproc,
X			  nparfunc:
X				tf := tf^.tparid
X			end (* case *)
X		    end;
X		(* emit called function name *)
X		eexpr(tp^.tcall);
X		write('(');
X		(* emit actual parameters *)
X		tq := tp^.taparm;
X		while tq <> nil do
X		    begin
X			if tf^.tup^.tt in [nparfunc, nparproc] then
X			    begin
X				(* single subroutine-nid converted to ncall *)
X				if tq^.tt = ncall then
X					printid(tq^.tcall^.tsym^.lid)
X				else
X					printid(tq^.tsym^.lid)
X			    end
X			else begin
X				tx := typeof(tq);
X				if tx = typnods[tboolean] then
X				    begin
X					tx := tq;
X					while tx^.tt = nuplus do
X						tx := tx^.texps;
X					if tx^.tt in [nin .. nor, nand, nnot]
X									then
X					    begin
X						write('(');
X						printid(defnams[dboolean]^.lid);
X						write(')(');
X						eexpr(tq);
X						write(')')
X					    end
X					else
X						eexpr(tq);
X				    end
X				else if (tx = typnods[tstring]) or
X						(tx = typnods[tset]) then
X				    begin
X					(* cast literal to proper type *)
X					write('*((');
X					etypedef(tf^.tup^.tbind);
X					write(' *)');
X					if tx = typnods[tset] then
X					    begin
X						dropset := true;
X						eexpr(tq);
X						dropset := false
X					    end
X					else
X						eexpr(tq);
X					write(')')
X				    end
X				else if tx = typnods[tnil] then
X				    begin
X					write('(');
X					etypedef(tf^.tup^.tbind);
X					write(')NIL')
X				    end
X				else if tf^.tup^.tbind^.tt = nconfarr then
X				    begin
X					write('(struct ');
X					printid(tf^.tup^.tbind^.tcuid);
X					write(' *)&');
X					eexpr(tq);
X					(* add upper bound of actual value *)
X					if tq^.tnext = nil then
X						write(', ',
X							crange(tx^.taindx):1)
X				    end
X				else begin
X					if tf^.tup^.tt = nvarpar then
X						eaddr(tq)
X					else
X						eexpr(tq)
X				     end
X			    end;
X			tq := tq^.tnext;
X			if tq <> nil then
X			    begin
X				write(', ');
X				(* next formal parameter *)
X				if tf^.tnext = nil then
X				    begin
X					tf := tf^.tup^.tnext;
X					case tf^.tt of
X					  nvalpar,
X					  nvarpar:
X						tf := tf^.tidl;
X					  nparproc,
X					  nparfunc:
X						tf := tf^.tparid
X					end (* case *)
X				    end
X				else
X					tf := tf^.tnext;
X			    end;
X		    end;
X		write(')')
X	end;	(* ecall *)
X
X	(*	Emit code for a general expression.			*)
X	procedure eexpr;
X
X	label	999;
X
X	var	tq	: treeptr;
X		flag	: boolean;
X
X		function constset(tp : treeptr) : boolean;
X
X			function constxps(tp : treeptr) : boolean;
X			begin
X				case tp^.tt of
X				  nrange:
X					if constxps(tp^.texpr) then
X						constxps := constxps(tp^.texpl)
X					else
X						constxps := false;
X				  nempty,
X				  ninteger,
X				  nchar:
X					constxps := true;
X				  nid:
X				    begin
X					tp := idup(tp);
X					constxps := (tp^.tt = nconst)
X							or (tp^.tt = nscalar)
X				    end;
X				  nin, neq, nne, nlt, nle, ngt, nge, nor,
X				  nplus, nminus, nand, nmul, ndiv, nmod,
X				  nquot, nnot, numinus, nuplus, nset,	
X				  nindex, nselect, nderef, ncall,
X				  nreal, nstring, nnil:
X					constxps := false
X				end (* case *)
X			end;
X
X		begin
X			constset := true;
X			while tp <> nil do
X				if constxps(tp) then
X					tp := tp^.tnext
X				else begin
X					constset := false;
X					tp := nil
X				    end
X		end;
X
X	begin	(* eexpr *)
X		donearr := false;
X		if tp^.tt in [nplus, nminus, nmul, nle, nge, neq, nne] then
X		    begin
X			tq := typeof(tp^.texpl);
X			if (tq^.tt in [nset, nsetof]) or
X						(tq = typnods[tset]) then
X			    begin
X				(* set operations *)
X				case tp^.tt of
X				  nplus:
X				    begin
X					setused := true;
X					useunion := true;
X					write('Union')
X				    end;
X				  nminus:
X				    begin
X					setused := true;
X					usediff := true;
X					write('Diff')
X				    end;
X				  nmul:
X				    begin
X					setused := true;
X					useintr := true;
X					write('Inter')
X				    end;
X				  neq:
X				    begin
X					useseq := true;
X					write('Eq')
X				    end;
X				  nne:
X				    begin
X					usesne := true;
X					write('Ne')
X				    end;
X				  nge:
X				    begin
X					usesge := true;
X					write('Ge')
X				    end;
X				  nle:
X				    begin
X					usesle := true;
X					write('Le')
X				    end
X				end;(* case *)
X				if tp^.tt in [nplus, nminus, nmul] then
X					dropset := false;
X				write('(');
X				eexpr(tp^.texpl);
X				if tq^.tt = nsetof then
X					write('.S');
X				write(', ');
X				eexpr(tp^.texpr);
X				tq := typeof(tp^.texpr);
X				if tq^.tt = nsetof then
X					write('.S');
X				write(')');
X				goto 999
X			    end
X		    end;
X		if tp^.tt in [neq, nne, ngt, nlt, nge, nle] then
X		    begin
X			tq := typeof(tp^.texpl);
X			if tq^.tt = nconfarr then
X				fatal(ecmpconf);
X			if (tq^.tt in [nstring, narray]) or
X						(tq = typnods[tstring]) then
X			    begin
X				write('Cmpstr(');
X				eexpr(tp^.texpl);
X				if tq^.tt = narray then
X					write('.A');
X				write(', ');
X				tq := typeof(tp^.texpr);
X				if tq^.tt = nconfarr then
X					fatal(ecmpconf);
X				eexpr(tp^.texpr);
X				if tq^.tt = narray then
X					write('.A');
X				write(')');
X				case tp^.tt of
X				  neq:
X					write(' == ');
X				  nne:
X					write(' != ');
X				  ngt:
X					write(' > ');
X				  nlt:
X					write(' < ');
X				  nge:
X					write(' >= ');
X				  nle:
X					write(' <= ');
X				end;(* case *)
X				write('0');
X				goto 999
X			    end
X		    end;
X		case tp^.tt of
X		  neq, nne, nlt, nle,
X		  ngt, nge, nor, nand, nplus, nminus,
X		  nmul, ndiv, nmod, nquot:
X		    begin
X			flag := cprio[tp^.tt] > cprio[tp^.texpl^.tt];
X			if (tp^.tt in [nlt, nle, ngt, nge]) and
X					not arithexpr(tp^.texpl) then
X			    begin
X				write('(int)');
X				flag := true
X			    end;
X			if flag then
X				write('(');
X			eexpr(tp^.texpl);
X			if flag then
X				write(')');
X			case tp^.tt of
X			  neq:
X				write(' == ');
X			  nne:
X				write(' != ');
X			  nlt:
X				write(' < ');
X			  nle:
X				write(' <= ');
X			  ngt:
X				write(' > ');
X			  nge:
X				write(' >= ');
X			  nor:
X				write(' || ');
X			  nand:
X				write(' && ');
X			  nplus:
X				write(' + ');
X			  nminus:
X				write(' - ');
X			  nmul:
X				write(' * ');
X			  ndiv:
X				write(' / ');
X			  nmod:
X				write(' % ');
X			  nquot:
X			    begin
X				write(' / ((');
X				printid(defnams[dreal]^.lid);
X				write(')')
X			    end
X			end;(* case *)
X			flag := cprio[tp^.tt] > cprio[tp^.texpr^.tt];
X			if (tp^.tt in [nlt, nle, ngt, nge]) and
X					not arithexpr(tp^.texpr) then
X			    begin
X				write('(int)');
X				flag := true
X			    end;
X			if flag then
X				write('(');
X			eexpr(tp^.texpr);
X			if flag then
X				write(')');
X			if tp^.tt = nquot then
X				write(')')
X		    end;
X
X		  nuplus, numinus, nnot:
X		    begin
X			case tp^.tt of
X			  numinus:
X				write('-');
X			  nnot:
X				write('!');
X			  nuplus:
X			end;(* case *)
X			flag := cprio[tp^.tt] >= cprio[tp^.texps^.tt];
X			if flag then
X				write('(');
X			eexpr(tp^.texps);
X			if flag then
X				write(')');
X		    end;
X		  
X		  nin:
X		    begin
X			usememb := true;
X			write('Member((unsigned)(');
X			eexpr(tp^.texpl);
X			write('), ');
X			dropset := true;	(* no need to save set-expr *)
X			eexpr(tp^.texpr);
X			dropset := false;
X			tq := typeof(tp^.texpr);
X			if tq^.tt = nsetof then
X				write('.S');
X			write(')')
X		    end;
X
X		  nassign:
X		    begin
X			tq := typeof(tp^.trhs);
X			if tq = typnods[tstring] then
X			    begin
X				write(voidcast, 'strncpy(');
X				eexpr(tp^.tlhs);
X				write('.A, ');
X				eexpr(tp^.trhs);
X				write(', sizeof(');
X				eexpr(tp^.tlhs);
X				write('.A))')
X			    end
X			else if tq = typnods[tboolean] then
X			    begin
X				eexpr(tp^.tlhs);
X				write(' = ');
X				tq := tp^.trhs;
X				while tq^.tt = nuplus do
X					tq := tq^.texps;
X				if tq^.tt in [nin .. nor, nand, nnot] then
X				    begin
X					write('(');
X					printid(defnams[dboolean]^.lid);
X					write(')(');
X					eexpr(tq);
X					write(')')
X				    end
X				else
X					eexpr(tq)
X			    end
X			else if tq = typnods[tnil] then
X			    begin
X				eexpr(tp^.tlhs);
X				write(' = (');
X				etypedef(typeof(tp^.tlhs));
X				write(')NIL')
X			    end
X			else begin
X				tq := typeof(tp^.tlhs);
X				if tq^.tt = nsetof then
X				    begin
X					usescpy := true;
X					write('Setncpy(');
X					eselect(tp^.tlhs);
X					write('S, ');
X					dropset := true;
X					tq := typeof(tp^.trhs);
X					if tq = typnods[tset] then
X						eexpr(tp^.trhs)
X					else begin
X						eselect(tp^.trhs);
X						write('S')
X					     end;
X					dropset := false;
X					write(', sizeof(');
X					eselect(tp^.tlhs);
X					write('S))')
X				    end
X				else begin
X					eexpr(tp^.tlhs);
X					write(' = ');
X					eexpr(tp^.trhs)
X				     end
X			     end
X		    end;
X
X		  ncall:
X		    begin
X			tq := idup(tp^.tcall);
X			if (tq^.tt in [nfunc, nproc]) and
X					(tq^.tsubstmt <> nil) then
X				if tq^.tsubstmt^.tt = npredef then
X					epredef(tq, tp)
X				else
X					ecall(tp)
X			else
X				ecall(tp)
X		    end;
X
X		  nselect:
X		    begin
X			eselect(tp^.trecord);
X			eexpr(tp^.tfield)
X		    end;
X		  nindex:
X		    begin
X			eselect(tp^.tvariable);
X			write('A[');
X			tq := tp^.toffset;
X			if arithexpr(tq) then
X				eexpr(tq)
X			else begin
X				write('(int)(');
X				eexpr(tq);
X				write(')')
X			     end;
X			tq := typeof(tp^.tvariable);
X			if tq^.tt = narray then
X				if clower(tq^.taindx) <> 0 then
X				    begin
X					write(' - ');
X					tq := typeof(tq^.taindx);
X					if tq^.tt = nsubrange then
X						if arithexpr(tq^.tlo) then
X							eexpr(tq^.tlo)
X						else begin
X							write('(int)(');
X							eexpr(tq^.tlo);
X							write(')')
X						     end
X					else 
X						fatal(etree)
X				    end;
X			write(']')
X		    end;
X		  nderef:
X		    begin
X			tq := typeof(tp^.texps);
X			if (tq^.tt = nfileof) or
X			     ((tq^.tt = npredef) and (tq^.tdef = dtext)) then
X			    begin
X				(* using a file-variable as pointer *)
X				eexpr(tp^.texps);
X				write('.buf')
X			    end
X			else if doarrow = 0 then
X			    begin
X				write('*');
X				eexpr(tp^.texps)
X			    end
X			else begin
X				eexpr(tp^.texps);
X				write('->');
X				donearr := true
X			     end
X		    end;
X		  nid:
X		    begin
X			(* add pointer-dereference if this id is declared as a
X			   var-parameter or as a procedure-parameter *)
X			tq := idup(tp);
X			if tq^.tt = nvarpar then
X			    begin
X				if (doarrow = 0) or
X						(tq^.tattr = areference) then
X				    begin
X					write('(*');
X					printid(tp^.tsym^.lid);
X					write(')')
X				    end
X				else begin
X					printid(tp^.tsym^.lid);
X					write('->');
X					donearr := true
X				     end
X			    end
X			else if (tq^.tt = nconst) and conflag then
X				write(cvalof(tp):1)
X			else if tq^.tt in [nparproc, nparfunc] then
X			    begin
X				write('(*');
X				printid(tp^.tsym^.lid);
X				write(')')
X			    end
X			else
X				printid(tp^.tsym^.lid);
X		    end;
X		  nchar:
X			printchr(tp^.tsym^.lchar);
X		  ninteger:
X			write(tp^.tsym^.linum:1);
X		  nreal:
X			printtok(tp^.tsym^.lfloat);
X		  nstring:
X			printstr(tp^.tsym^.lstr);
X		  nset:
X			if constset(tp^.texps) then
X			    begin
X				(* save set expression for initialization *)
X				write('Conset[', setcnt:1, ']');
X				setcnt := setcnt + 1;
X				tq := mknode(nset);
X				tq^.tnext := setlst;
X				setlst := tq;
X				tq^.texps := tp^.texps
X			    end
X			else begin
X				increment;
X				flag := dropset;
X				(* if a set-constructor is used in an
X				   expression involving + - *  it will need to
X				   be saved temporarily (by Saveset) but often
X				   we can simply forget the set-value when we
X				   have finished using it *)
X				if dropset then
X					dropset := false
X				else
X					write('Saveset(');
X				write('(Tmpset = Newset(), ');
X				tq := tp^.texps;
X				while tq <> nil do
X				    begin
X					case tq^.tt of
X					  nrange:
X					    begin
X						usemksub := true;
X						write(voidcast, 'Mksubr(');
X						write('(unsigned)(');
X						eexpr(tq^.texpl);
X						write('), ');
X						write('(unsigned)(');
X						eexpr(tq^.texpr);
X						write('), Tmpset)')
X					    end;
X					  nin, neq, nne, nlt, nle, ngt, nge,
X					  nor, nand, nmul, ndiv, nmod, nquot,
X					  nplus, nminus, nnot, numinus, nuplus, 
X					  nindex, nselect, nderef, ncall,
X					  ninteger, nchar, nid:
X					    begin
X						useins := true;
X						write(voidcast, 'Insmem(');
X						write('(unsigned)(');
X						eexpr(tq);
X						write('), Tmpset)')
X					    end
X					end;(* case *)
X					tq := tq^.tnext;
X					if tq <> nil then
X					    begin
X						writeln(',');
X						indent
X					    end
X				    end;
X				write(', Tmpset)');
X				if not flag then
X				    begin
X					write(')');
X					setused := true
X				    end;
X				decrement
X			     end;
X		  nnil:
X		    begin
X			tq := tp;
X			repeat
X				tq := tq^.tup
X			until	tq^.tt in [neq, nne, ncall, nassign, npgm];
X			if tq^.tt in [neq, nne] then
X			    begin
X				if typeof(tq^.texpl) = typnods[tnil] then
X					tq := typeof(tq^.texpr)
X				else
X					tq := typeof(tq^.texpl);
X				if tq^.tt = nptr then
X				    begin
X					write('(');
X					etypedef(tq);
X					write(')')
X				    end
X			    end;
X			write('NIL')
X		    end;
X		end;(* case *)
X	999:
X	end;	(* eexpr *)
X
X	(*	Emit constant definitions.				*)
X	procedure econst(tp : treeptr);
X
X	var	sp	: symptr;
X
X	begin
X		while tp <> nil do
X		    begin
X			sp := tp^.tidl^.tsym;
X			if sp^.lid^.inref > 1 then
X				sp^.lid := mkrename('X', sp^.lid);
X			if tp^.tbind^.tt = nstring then
X			    begin
X				(* string constants emitted as
X				   static local variables *)
X				indent;
X				write(static, chartyp, tab1);
X				printid(sp^.lid);
X				write('[]	= ');
X				eexpr(tp^.tbind);
X				writeln(';')
X			    end
X			else begin
X				(* all other constants emitted as
X				   preprocessor # defines *)
X				write(define);
X				printid(sp^.lid);
X				write(space);
X				eexpr(tp^.tbind);
X				writeln
X			    end;
X			tp := tp^.tnext
X		    end
X	end;	(* econst *)
X
X	(*	Emit a typedef.						*)
X	procedure etypedef;
X
X		(*	Workhorse for etypedef, this procedure also	*)
X		(*	renames all fields in record-unions when	*)
X		(*	necessary.					*)
X		procedure etdef(uid : idptr; tp : treeptr);
X
X		var	i	: integer;
X			tq	: treeptr;
X
X			(*	Emit definition for an integer subrange	*)
X			(*	using data from worddefs set up during	*)
X			(*	initialization.				*)
X			procedure etrange(tp : treeptr);
X
X			label	999;
X
X			var	lo, hi	: integer;
X				i	: 1 .. maxmachdefs;
X
X			begin
X				lo := clower(tp);
X				hi := cupper(tp);
X				(* scan CPU word definitions for a type
X				   enclosing wanted range *)
X				for i := 1 to nmachdefs do
X				    with machdefs[i] do
X					if (lo >= lolim) and (hi <= hilim) then
X					    begin
X						(* found it, print type name *)
X						printtok(typstr);
X						goto 999
X					    end;
X				fatal(erange);
X			999:
X			end;
X
X			(*	Print last component of identifier.	*)
X			procedure printsuf(ip : idptr);
X
X			var	w	: toknbuf;
X				i, j	: toknidx;
X
X			begin
X				gettokn(ip^.istr, w);
X				i := 1;
X				j := i;
X				while w[i] <> chr(null) do
X				    begin
X					if w[i] = '.' then
X						j := i;
X					i := i + 1
X				    end;
X				if w[j] = '.' then
X					j := j + 1;
X				while w[j] <> chr(null) do
X				    begin
X					write(w[j]);
X					j := j + 1
X				    end
X			end;
X
X		begin	(* etdef *)
X			case tp^.tt of
X			  nid:
X				printid(tp^.tsym^.lid);
X			  nptr:
X			    begin
X				tq := typeof(tp^.tptrid);
X				if tq^.tt = nrecord then
X				    begin
X					write('struct ');
X					printid(tq^.tuid)
X				    end
X				else
X					printid(tp^.tptrid^.tsym^.lid);
X				write(' *');
X			    end;
X			  nscalar:
X			    begin
X				write('enum { ');
X				increment;
X				tp := tp^.tscalid;
X
X				(* avoid bug in C-compiler:
X					   enums are mixed in same namespace *)
X				if tp^.tsym^.lid^.inref > 1 then
X					tp^.tsym^.lid :=
X						mkrename('E', tp^.tsym^.lid);
X				printid(tp^.tsym^.lid);
X				i := 1;
X				while tp^.tnext <> nil do
X				    begin
X					if i >= 4 then
X					    begin
X						writeln(',');
X						indent;
X						i := 1
X					    end
X					else begin
X						write(', ');
X						i := i + 1
X					     end;
X					tp := tp^.tnext;
X					if tp^.tsym^.lid^.inref > 1 then
X					    tp^.tsym^.lid :=
X						mkrename('E', tp^.tsym^.lid);
X					printid(tp^.tsym^.lid)
X				    end;
X				decrement;
X				write(' } ')
X			    end;
X			  nsubrange:
X			    begin
X				tq := typeof(tp^.tlo);
X				if tq = typnods[tinteger] then
X					etrange(tp)
X				else begin
X					if tq^.tup^.tt = ntype then
X						tq := tq^.tup^.tidl;
X					etdef(nil, tq)
X				     end
X			    end;
X			  nfield:
X			    begin
X				etdef(nil, tp^.tbind);
X				write(tab1);
X				tp := tp^.tidl;
X				if uid <> nil then
X					tp^.tsym^.lid :=
X						mkconc('.', uid, tp^.tsym^.lid);
X				printsuf(tp^.tsym^.lid);
X				i := 1;
X				while tp^.tnext <> nil do
X				    begin
X					if i >= 4 then
X					    begin
X						writeln(',');
X						indent;
X						write(tab1);
X						i := 1
X					    end
X					else begin
X						write(', ');
X						i := i + 1
X					     end;
X					tp := tp^.tnext;
X					if uid <> nil then
X					    tp^.tsym^.lid :=
X						mkconc('.', uid, tp^.tsym^.lid);
X					printsuf(tp^.tsym^.lid);
X				    end;
X				writeln(';');
X			    end;
X			  nrecord:
X			    begin
X				write('struct ');
X				if tp^.tuid = nil then
X					tp^.tuid := uid
X				else if uid = nil then
X					printid(tp^.tuid);
X				writeln(' {');
X				increment;
X				if (tp^.tflist = nil) and
X							(tp^.tvlist = nil) then
X				    begin
X					(* C doesn't allow empty structures *)
X					indent;
X					writeln(inttyp, tab1, 'dummy;')
X				    end;
X				tq := tp^.tflist;
X				while tq <> nil do
X				    begin
X					indent;
X					etdef(uid, tq);
X					tq := tq^.tnext
X				    end;
X				if tp^.tvlist <> nil then
X				    begin
X					indent;
X					writeln('union {');
X					increment;
X					tq := tp^.tvlist;
X					while tq <> nil do
X					    begin
X						if (tq^.tvrnt^.tflist <> nil) or
X						 (tq^.tvrnt^.tvlist <> nil) then
X						    begin
X							indent;
X							if uid = nil then
X							    etdef(mkvrnt,
X								tq^.tvrnt)
X							else
X							    etdef(mkconc('.',
X								   uid, mkvrnt),
X								tq^.tvrnt);
X							writeln(';')
X						    end;
X						tq := tq^.tnext
X					    end;
X					decrement;
X					indent;
X					writeln('} U;');
X				    end;
X				decrement;
X				indent;
X				if tp^.tup^.tt = nvariant then
X				    begin
X					write('} ');
X					printsuf(tp^.tuid)
X				    end
X				else
X					write('}');
X			    end;
X			  nconfarr:
X			    begin
X				write('struct ');
X				printid(tp^.tcuid);
X				write(' { ');
X				etdef(nil, tp^.tcelem);
X				write(tab1, 'A[]; }')
X			    end;
X			  narray:
X			    begin
X				write('struct { ');
X				etdef(nil, tp^.taelem);
X				write(tab1, 'A[');
X				tq := typeof(tp^.taindx);
X				if tq^.tt = nsubrange then
X				    begin
X					if arithexpr(tq^.thi) then
X					    begin
X						eexpr(tq^.thi);
X						if cvalof(tq^.tlo) <> 0 then
X						    begin
X							write(' - ');
X							eexpr(tq^.tlo)
X						    end
X					    end
X					else begin
X						write('(int)(');
X						eexpr(tq^.thi);
X						if cvalof(tq^.tlo) <> 0 then
X						    begin
X							write(') - (int)(');
X							eexpr(tq^.tlo)
X						    end;
X						write(')')
X					     end;
X					write(' + 1')
X				    end
X				else
X					write(crange(tp^.taindx):1);
X				write(']; }')
X			    end;
X			  nfileof:
X			    begin
X				writeln('struct {');
X				indent;
X				writeln(tab1, 'FILE', tab1, '*fp;');
X				indent;
X				writeln(tab1, filebits, tab1, 'eoln:1,');
X				indent;
X				writeln(tab3, 'eof:1,');
X				indent;
X				writeln(tab3, 'out:1,');
X				indent;
X				writeln(tab3, 'init:1,');
X				indent;
X				writeln(tab3, ':', filefill:1, ';');
X				indent;
X				write(tab1);
X				etdef(nil, tp^.tof);
X				writeln(tab1, 'buf;');
X				indent;
X				write('} ')
X			    end;
X			  nsetof:
X				write('struct { ', setwtyp, tab1, 'S[',
X							csetsize(tp):1, ']; }');
X			  npredef:
X			    begin
X				case tp^.tobtyp of
X				  tboolean:
X					printid(defnams[dboolean]^.lid);
X				  tchar:
X					write(chartyp);
X				  tinteger:
X					printid(defnams[dinteger]^.lid);
X				  treal:
X					printid(defnams[dreal]^.lid);
X				  tstring:
X					write(chartyp, ' *');
X				  ttext:
X					write('text');
X				  tnil,
X				  tset,
X				  terror:
X					fatal(etree);
X				  tnone:
X					write(voidtyp);
X				end (* case *)
X			    end;
X			  nempty:
X				write(voidtyp);
X			end;(* case *)
X		end;	(* etdef *)
X	begin
X		etdef(nil, tp)
X	end;	(* etypedef *)
X
X	(*	Emit code for type declarations.			*)
X	procedure etype(tp : treeptr);
X
X	var	sp	: symptr;
X
X	begin
X		while tp <> nil do
X		    begin
X			(* if identifier used more than once we rename the type
X			   to avoid typedef'ing an identifier twice *)
X			sp := tp^.tidl^.tsym;
X			if sp^.lid^.inref > 1 then
X				sp^.lid := mkrename('Y', sp^.lid);
X			indent;
X			write(typdef);
X			etypedef(tp^.tbind);
X			write(tab1);
X			printid(sp^.lid);
X			writeln(';');
X			tp := tp^.tnext
X		    end
X	end;
X
X	(*	Emit code for variable declarations.			*)
X	procedure evar(tp : treeptr);
X
X	label	555;
X
X	var	tq	: treeptr;
X		i	: integer;
X
X	begin
X		while tp <> nil do
X		    begin
X			indent;
X			case tp^.tt of
X			  nvar,
X			  nvalpar,
X			  nvarpar:
X			    begin
X				if tp^.tattr = aregister then
X					write(registr);
X				etypedef(tp^.tbind)
X			    end;
X			  nparproc,
X			  nparfunc:
X			    begin
X				if tp^.tt = nparproc then
X					write(voidtyp)
X				else
X					etypedef(tp^.tpartyp);
X				tq := tp^.tparid;
X				write(tab1, '(*');
X				printid(tq^.tsym^.lid);
X				write(')()');
X				goto 555
X			    end
X			end;(* case *)
X			write(tab1);
X			tq := tp^.tidl;
X			i := 1;
X			repeat
X				if tp^.tt = nvarpar then
X					write('*');
X				printid(tq^.tsym^.lid);
X				tq := tq^.tnext;
X				if tq <> nil then
X				    begin
X					if i >= 6 then
X					    begin
X						i := 1;
X						writeln(',');
X						indent;
X						write(tab1)
X					    end
X					else begin
X						i := i + 1;
X						write(', ')
X					     end
X
END_OF_FILE
if test 50280 -ne `wc -c <'ptc.p.3'`; then
    echo shar: \"'ptc.p.3'\" unpacked with wrong size!
fi
# end of 'ptc.p.3'
fi
echo shar: End of archive 9 \(of 12\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net