xref: /csrg-svn/old/pcc/mip/trees.c (revision 24408)
117749Sralph #ifndef lint
2*24408Smckusick static char *sccsid ="@(#)trees.c	4.9 (Berkeley) 08/22/85";
317749Sralph #endif
417749Sralph 
518396Sralph # include "pass1.h"
616179Sralph 
7*24408Smckusick # include <setjmp.h>
8*24408Smckusick 
917749Sralph int bdebug = 0;
1017749Sralph int adebug = 0;
1117749Sralph extern ddebug;
1217749Sralph extern eprint();
1317749Sralph 
1416179Sralph 	    /* corrections when in violation of lint */
1516179Sralph 
1616179Sralph /*	some special actions, used in finding the type of nodes */
1716179Sralph # define NCVT 01
1816179Sralph # define PUN 02
1916179Sralph # define TYPL 04
2016179Sralph # define TYPR 010
2116179Sralph # define TYMATCH 040
2216179Sralph # define LVAL 0100
2316179Sralph # define CVTO 0200
2416179Sralph # define CVTL 0400
2516179Sralph # define CVTR 01000
2616179Sralph # define PTMATCH 02000
2716179Sralph # define OTHER 04000
2816179Sralph # define NCVTR 010000
2916179Sralph 
3017749Sralph #ifndef BUG1
3117749Sralph printact(t, acts)
3217749Sralph 	NODE *t;
3317749Sralph 	int acts;
3417749Sralph {
3517749Sralph 	static struct actions {
3617749Sralph 		int	a_bit;
3717749Sralph 		char	*a_name;
3817749Sralph 	} actions[] = {
3917749Sralph 		{ PUN,		"PUN" },
4017749Sralph 		{ CVTL,		"CVTL" },
4117749Sralph 		{ CVTR,		"CVTR" },
4217749Sralph 		{ TYPL,		"TYPL" },
4317749Sralph 		{ TYPR,		"TYPR" },
4417749Sralph 		{ TYMATCH,	"TYMATCH" },
4517749Sralph 		{ PTMATCH,	"PTMATCH" },
4617749Sralph 		{ LVAL,		"LVAL" },
4717749Sralph 		{ CVTO,		"CVTO" },
4817749Sralph 		{ NCVT,		"NCVT" },
4917749Sralph 		{ OTHER,	"OTHER" },
5017749Sralph 		{ NCVTR,	"NCVTR" },
5117749Sralph 		{ 0 }
5217749Sralph 	};
5317749Sralph 	register struct actions *p;
5417749Sralph 	char *sep = " ";
5517749Sralph 
5617749Sralph 	printf("actions");
5717749Sralph 	for (p = actions; p->a_name; p++)
5817749Sralph 		if (p->a_bit & acts) {
5917749Sralph 			printf("%s%s", sep, p->a_name);
6017749Sralph 			sep = "|";
6117749Sralph 		}
6217749Sralph 	if (!bdebug) {
6317749Sralph 		printf(" for:\n");
6417749Sralph 		fwalk(t, eprint, 0);
6517749Sralph 	} else
6617749Sralph 		putchar('\n');
6717749Sralph }
6817749Sralph #endif
6917749Sralph 
7016179Sralph /* node conventions:
7116179Sralph 
7216179Sralph 	NAME:	rval>0 is stab index for external
7316179Sralph 		rval<0 is -inlabel number
7416179Sralph 		lval is offset in bits
7516179Sralph 	ICON:	lval has the value
7616179Sralph 		rval has the STAB index, or - label number,
7716179Sralph 			if a name whose address is in the constant
7816179Sralph 		rval = NONAME means no name
7916179Sralph 	REG:	rval is reg. identification cookie
8016179Sralph 
8116179Sralph 	*/
8216179Sralph 
8316179Sralph NODE *
8416179Sralph buildtree( o, l, r ) register NODE *l, *r; {
8516179Sralph 	register NODE *p, *q;
8616179Sralph 	register actions;
8716179Sralph 	register opty;
8816179Sralph 	register struct symtab *sp;
8916179Sralph 	register NODE *lr, *ll;
9017749Sralph 	NODE *fixargs();
9116179Sralph 	int i;
9216179Sralph 
9316179Sralph # ifndef BUG1
9416179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9516179Sralph # endif
9616179Sralph 	opty = optype(o);
9716179Sralph 
9816179Sralph 	/* check for constants */
9916179Sralph 
10016179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
10116179Sralph 
10216179Sralph 		switch( o ){
10316179Sralph 
10416179Sralph 		case NOT:
10516179Sralph 			if( hflag ) werror( "constant argument to NOT" );
10616179Sralph 		case UNARY MINUS:
10716179Sralph 		case COMPL:
10816179Sralph 			if( conval( l, o, l ) ) return(l);
10916179Sralph 			break;
11016179Sralph 
11116179Sralph 			}
11216179Sralph 		}
11316179Sralph 
11416179Sralph 	else if( o==UNARY MINUS && l->in.op==FCON ){
11517749Sralph 		l->fpn.fval = -l->fpn.fval;
11616179Sralph 		return(l);
11716179Sralph 		}
11816179Sralph 
11917749Sralph 	else if( o==UNARY MINUS && l->in.op==DCON ){
12017749Sralph 		l->dpn.dval = -l->dpn.dval;
12117749Sralph 		return(l);
12217749Sralph 		}
12317749Sralph 
12416179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
12516179Sralph 		l->in.op = FREE;
12616179Sralph 		r->in.op = FREE;
12716179Sralph 		if( l->tn.lval ){
12816179Sralph 			tfree( r->in.right );
12916179Sralph 			return( r->in.left );
13016179Sralph 			}
13116179Sralph 		else {
13216179Sralph 			tfree( r->in.left );
13316179Sralph 			return( r->in.right );
13416179Sralph 			}
13516179Sralph 		}
13616179Sralph 
13716179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
13816179Sralph 
13916179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
14016179Sralph 
14116179Sralph 		switch( o ){
14216179Sralph 
14316179Sralph 		case ULT:
14416179Sralph 		case UGT:
14516179Sralph 		case ULE:
14616179Sralph 		case UGE:
14716179Sralph 		case LT:
14816179Sralph 		case GT:
14916179Sralph 		case LE:
15016179Sralph 		case GE:
15116179Sralph 		case EQ:
15216179Sralph 		case NE:
15316179Sralph 		case ANDAND:
15416179Sralph 		case OROR:
15516179Sralph 		case CBRANCH:
15616179Sralph 
15716179Sralph 		ccwarn:
15816179Sralph 			if( hflag ) werror( "constant in conditional context" );
15916179Sralph 
16016179Sralph 		case PLUS:
16116179Sralph 		case MINUS:
16216179Sralph 		case MUL:
16316179Sralph 		case DIV:
16416179Sralph 		case MOD:
16516179Sralph 		case AND:
16616179Sralph 		case OR:
16716179Sralph 		case ER:
16816179Sralph 		case LS:
16916179Sralph 		case RS:
17016179Sralph 			if( conval( l, o, r ) ) {
17116179Sralph 				r->in.op = FREE;
17216179Sralph 				return(l);
17316179Sralph 				}
17416179Sralph 			break;
17516179Sralph 			}
17616179Sralph 		}
177*24408Smckusick 	else if (opty == BITYPE &&
178*24408Smckusick 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
179*24408Smckusick 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
180*24408Smckusick 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
181*24408Smckusick 				extern int fpe_count;
182*24408Smckusick 				extern jmp_buf gotfpe;
18316179Sralph 
184*24408Smckusick 				fpe_count = 0;
185*24408Smckusick 				if (setjmp(gotfpe))
186*24408Smckusick 					goto treatfpe;
18717749Sralph 				if (l->in.op == ICON)
18817749Sralph 					l->dpn.dval = l->tn.lval;
189*24408Smckusick 				else if (l->in.op == FCON)
190*24408Smckusick 					l->dpn.dval = l->fpn.fval;
19117749Sralph 				if (r->in.op == ICON)
19217749Sralph 					r->dpn.dval = r->tn.lval;
193*24408Smckusick 				else if (r->in.op == FCON)
194*24408Smckusick 					r->dpn.dval = r->fpn.fval;
19517749Sralph 				switch (o) {
19617749Sralph 
19717749Sralph 				case PLUS:
19817749Sralph 					l->dpn.dval += r->dpn.dval;
199*24408Smckusick 					break;
20017749Sralph 
20117749Sralph 				case MINUS:
20217749Sralph 					l->dpn.dval -= r->dpn.dval;
203*24408Smckusick 					break;
20417749Sralph 
20517749Sralph 				case MUL:
20617749Sralph 					l->dpn.dval *= r->dpn.dval;
207*24408Smckusick 					break;
20817749Sralph 
20917749Sralph 				case DIV:
21017749Sralph 					if (r->dpn.dval == 0)
21117749Sralph 						uerror("division by 0.");
21217749Sralph 					else
21317749Sralph 						l->dpn.dval /= r->dpn.dval;
214*24408Smckusick 					break;
215*24408Smckusick 					}
216*24408Smckusick 			treatfpe:
217*24408Smckusick 				if (fpe_count > 0) {
218*24408Smckusick 					uerror("floating point exception in constant expression");
219*24408Smckusick 					l->dpn.dval = 1.0; /* Fairly harmless */
220*24408Smckusick 					}
221*24408Smckusick 				fpe_count = -1;
222*24408Smckusick 				l->in.op = DCON;
223*24408Smckusick 				l->in.type = l->fn.csiz = DOUBLE;
224*24408Smckusick 				r->in.op = FREE;
225*24408Smckusick 				return (l);
22616179Sralph 			}
227*24408Smckusick 		}
22816179Sralph 
229*24408Smckusick 	/* it's real; we must make a new node */
23016179Sralph 
23116179Sralph 	p = block( o, l, r, INT, 0, INT );
23216179Sralph 
23316179Sralph 	actions = opact(p);
23417749Sralph #ifndef	BUG1
23517749Sralph 	if (adebug)
23617749Sralph 		printact(p, actions);
23717749Sralph #endif
23816179Sralph 
23916179Sralph 	if( actions&LVAL ){ /* check left descendent */
24016179Sralph 		if( notlval(p->in.left) ) {
24116179Sralph 			uerror( "illegal lhs of assignment operator" );
24216179Sralph 			}
24316179Sralph 		}
24416179Sralph 
24516179Sralph 	if( actions & NCVTR ){
24616179Sralph 		p->in.left = pconvert( p->in.left );
24716179Sralph 		}
24816179Sralph 	else if( !(actions & NCVT ) ){
24916179Sralph 		switch( opty ){
25016179Sralph 
25116179Sralph 		case BITYPE:
25216179Sralph 			p->in.right = pconvert( p->in.right );
25316179Sralph 		case UTYPE:
25416179Sralph 			p->in.left = pconvert( p->in.left );
25516179Sralph 
25616179Sralph 			}
25716179Sralph 		}
25816179Sralph 
25916179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
26016179Sralph 		chkpun(p);
26116179Sralph 		}
26216179Sralph 
26316179Sralph 	if( actions & (TYPL|TYPR) ){
26416179Sralph 
26516179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
26616179Sralph 
26716179Sralph 		p->in.type = q->in.type;
26816179Sralph 		p->fn.cdim = q->fn.cdim;
26916179Sralph 		p->fn.csiz = q->fn.csiz;
27016179Sralph 		}
27116179Sralph 
27216179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
27316179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
27416179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
27516179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
27616179Sralph 
27716179Sralph 	if( actions & OTHER ){
27816179Sralph 		l = p->in.left;
27916179Sralph 		r = p->in.right;
28016179Sralph 
28116179Sralph 		switch(o){
28216179Sralph 
28316179Sralph 		case NAME:
28416179Sralph 			sp = &stab[idname];
28516179Sralph 			if( sp->stype == UNDEF ){
28616179Sralph #ifndef FLEXNAMES
28716179Sralph 				uerror( "%.8s undefined", sp->sname );
28816179Sralph #else
28916179Sralph 				uerror( "%s undefined", sp->sname );
29016179Sralph #endif
29116179Sralph 				/* make p look reasonable */
29216179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
29316179Sralph 				p->tn.rval = idname;
29416179Sralph 				p->tn.lval = 0;
29516179Sralph 				defid( p, SNULL );
29616179Sralph 				break;
29716179Sralph 				}
29816179Sralph 			p->in.type = sp->stype;
29916179Sralph 			p->fn.cdim = sp->dimoff;
30016179Sralph 			p->fn.csiz = sp->sizoff;
30116179Sralph 			p->tn.lval = 0;
30216179Sralph 			p->tn.rval = idname;
30316179Sralph 			/* special case: MOETY is really an ICON... */
30416179Sralph 			if( p->in.type == MOETY ){
30516179Sralph 				p->tn.rval = NONAME;
30616179Sralph 				p->tn.lval = sp->offset;
30716179Sralph 				p->fn.cdim = 0;
30816179Sralph 				p->in.type = ENUMTY;
30916179Sralph 				p->in.op = ICON;
31016179Sralph 				}
31116179Sralph 			break;
31216179Sralph 
31316179Sralph 		case ICON:
31416179Sralph 			p->in.type = INT;
31516179Sralph 			p->fn.cdim = 0;
31616179Sralph 			p->fn.csiz = INT;
31716179Sralph 			break;
31816179Sralph 
31916179Sralph 		case STRING:
32016179Sralph 			p->in.op = NAME;
32116179Sralph 			p->in.type = CHAR+ARY;
32216179Sralph 			p->tn.lval = 0;
32316179Sralph 			p->tn.rval = NOLAB;
32416179Sralph 			p->fn.cdim = curdim;
32516179Sralph 			p->fn.csiz = CHAR;
32616179Sralph 			break;
32716179Sralph 
32816179Sralph 		case FCON:
32916179Sralph 			p->tn.lval = 0;
33016179Sralph 			p->tn.rval = 0;
33117749Sralph 			p->in.type = FLOAT;
33217749Sralph 			p->fn.cdim = 0;
33317749Sralph 			p->fn.csiz = FLOAT;
33417749Sralph 			break;
33517749Sralph 
33617749Sralph 		case DCON:
33717749Sralph 			p->tn.lval = 0;
33817749Sralph 			p->tn.rval = 0;
33916179Sralph 			p->in.type = DOUBLE;
34016179Sralph 			p->fn.cdim = 0;
34116179Sralph 			p->fn.csiz = DOUBLE;
34216179Sralph 			break;
34316179Sralph 
34416179Sralph 		case STREF:
34516179Sralph 			/* p->x turned into *(p+offset) */
34616179Sralph 			/* rhs must be a name; check correctness */
34716179Sralph 
34816179Sralph 			i = r->tn.rval;
34916179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
35016179Sralph 				uerror( "member of structure or union required" );
35116179Sralph 				}else
35216179Sralph 			/* if this name is non-unique, find right one */
35316179Sralph 			if( stab[i].sflags & SNONUNIQ &&
35416179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
35516179Sralph 				(l->fn.csiz +1) >= 0 ){
35616179Sralph 				/* nonunique name && structure defined */
35716179Sralph 				char * memnam, * tabnam;
35816179Sralph 				register k;
35916179Sralph 				int j;
36016179Sralph 				int memi;
36116179Sralph 				j=dimtab[l->fn.csiz+1];
36216179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
36316179Sralph 					tabnam = stab[memi].sname;
36416179Sralph 					memnam = stab[i].sname;
36516179Sralph # ifndef BUG1
36616179Sralph 					if( ddebug>1 ){
36716179Sralph #ifndef FLEXNAMES
36816179Sralph 						printf("member %.8s==%.8s?\n",
36916179Sralph #else
37016179Sralph 						printf("member %s==%s?\n",
37116179Sralph #endif
37216179Sralph 							memnam, tabnam);
37316179Sralph 						}
37416179Sralph # endif
37516179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
37616179Sralph #ifndef FLEXNAMES
37716179Sralph 						for( k=0; k<NCHNAM; ++k ){
37816179Sralph 							if(*memnam++!=*tabnam)
37916179Sralph 								goto next;
38016179Sralph 							if(!*tabnam++) break;
38116179Sralph 							}
38216179Sralph #else
38316179Sralph 						if (memnam != tabnam)
38416179Sralph 							goto next;
38516179Sralph #endif
38616179Sralph 						r->tn.rval = i = memi;
38716179Sralph 						break;
38816179Sralph 						}
38916179Sralph 					next: continue;
39016179Sralph 					}
39116179Sralph 				if( memi < 0 )
39216179Sralph #ifndef FLEXNAMES
39316179Sralph 					uerror("illegal member use: %.8s",
39416179Sralph #else
39516179Sralph 					uerror("illegal member use: %s",
39616179Sralph #endif
39716179Sralph 						stab[i].sname);
39816179Sralph 				}
39916179Sralph 			else {
40016179Sralph 				register j;
40116179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
40216179Sralph 					if( stab[i].sflags & SNONUNIQ ){
40316179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
40416179Sralph 						}
40516179Sralph 					else werror( "struct/union or struct/union pointer required" );
40616179Sralph 					}
40716179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
40816179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
40916179Sralph #ifndef FLEXNAMES
41016179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
41116179Sralph #else
41216179Sralph 					werror( "illegal member use: %s", stab[i].sname );
41316179Sralph #endif
41416179Sralph 					}
41516179Sralph 				}
41616179Sralph 
41716179Sralph 			p = stref( p );
41816179Sralph 			break;
41916179Sralph 
42016179Sralph 		case UNARY MUL:
42116179Sralph 			if( l->in.op == UNARY AND ){
42216179Sralph 				p->in.op = l->in.op = FREE;
42316179Sralph 				p = l->in.left;
42416179Sralph 				}
42516179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
42616179Sralph 			p->in.type = DECREF(l->in.type);
42716179Sralph 			p->fn.cdim = l->fn.cdim;
42816179Sralph 			p->fn.csiz = l->fn.csiz;
42916179Sralph 			break;
43016179Sralph 
43116179Sralph 		case UNARY AND:
43216179Sralph 			switch( l->in.op ){
43316179Sralph 
43416179Sralph 			case UNARY MUL:
43516179Sralph 				p->in.op = l->in.op = FREE;
43616179Sralph 				p = l->in.left;
43716179Sralph 			case NAME:
43816179Sralph 				p->in.type = INCREF( l->in.type );
43916179Sralph 				p->fn.cdim = l->fn.cdim;
44016179Sralph 				p->fn.csiz = l->fn.csiz;
44116179Sralph 				break;
44216179Sralph 
44316179Sralph 			case COMOP:
44416179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
44516179Sralph 				p->in.op = l->in.op = FREE;
44616179Sralph 				p = buildtree( COMOP, l->in.left, lr );
44716179Sralph 				break;
44816179Sralph 
44916179Sralph 			case QUEST:
45016179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
45116179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
45216179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
45316179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
45416179Sralph 				break;
45516179Sralph 
45616179Sralph # ifdef ADDROREG
45716179Sralph 			case OREG:
45816179Sralph 				/* OREG was built in clocal()
45916179Sralph 				 * for an auto or formal parameter
46016179Sralph 				 * now its address is being taken
46116179Sralph 				 * local code must unwind it
46216179Sralph 				 * back to PLUS/MINUS REG ICON
46316179Sralph 				 * according to local conventions
46416179Sralph 				 */
46516179Sralph 				{
46616179Sralph 				extern NODE * addroreg();
46716179Sralph 				p->in.op = FREE;
46816179Sralph 				p = addroreg( l );
46916179Sralph 				}
47016179Sralph 				break;
47116179Sralph 
47216179Sralph # endif
47316179Sralph 			default:
47416179Sralph 				uerror( "unacceptable operand of &" );
47516179Sralph 				break;
47616179Sralph 				}
47716179Sralph 			break;
47816179Sralph 
47916179Sralph 		case LS:
48016179Sralph 		case RS:
48116179Sralph 		case ASG LS:
48216179Sralph 		case ASG RS:
48316179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
48416179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
48516179Sralph 			break;
48616179Sralph 
48716179Sralph 		case RETURN:
48816179Sralph 		case ASSIGN:
48916179Sralph 		case CAST:
49016179Sralph 			/* structure assignment */
49116179Sralph 			/* take the addresses of the two sides; then make an
49216179Sralph 			/* operator using STASG and
49316179Sralph 			/* the addresses of left and right */
49416179Sralph 
49516179Sralph 			{
49616179Sralph 				register TWORD t;
49716179Sralph 				register d, s;
49816179Sralph 
49916179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
50016179Sralph 
50116179Sralph 				r = buildtree( UNARY AND, r, NIL );
50216179Sralph 				t = r->in.type;
50316179Sralph 				d = r->fn.cdim;
50416179Sralph 				s = r->fn.csiz;
50516179Sralph 
50616179Sralph 				l = block( STASG, l, r, t, d, s );
50716179Sralph 
50816179Sralph 				if( o == RETURN ){
50916179Sralph 					p->in.op = FREE;
51016179Sralph 					p = l;
51116179Sralph 					break;
51216179Sralph 					}
51316179Sralph 
51416179Sralph 				p->in.op = UNARY MUL;
51516179Sralph 				p->in.left = l;
51616179Sralph 				p->in.right = NIL;
51716179Sralph 				break;
51816179Sralph 				}
51916179Sralph 		case COLON:
52016179Sralph 			/* structure colon */
52116179Sralph 
52216179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
52316179Sralph 			break;
52416179Sralph 
52516179Sralph 		case CALL:
52617749Sralph 			p->in.right = r = fixargs( p->in.right );
52716179Sralph 		case UNARY CALL:
52816179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
52916179Sralph 			p->in.type = DECREF(l->in.type);
53016179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
53116179Sralph 			p->in.type = DECREF( p->in.type );
53216179Sralph 			p->fn.cdim = l->fn.cdim;
53316179Sralph 			p->fn.csiz = l->fn.csiz;
53416179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
53516179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
53616179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
53716179Sralph 				p->in.op += (FORTCALL-CALL);
53816179Sralph 				}
53916179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
54016179Sralph 				/* function returning structure */
54116179Sralph 				/*  make function really return ptr to str., with * */
54216179Sralph 
54316179Sralph 				p->in.op += STCALL-CALL;
54416179Sralph 				p->in.type = INCREF( p->in.type );
54516179Sralph 				p = buildtree( UNARY MUL, p, NIL );
54616179Sralph 
54716179Sralph 				}
54816179Sralph 			break;
54916179Sralph 
55016179Sralph 		default:
55116179Sralph 			cerror( "other code %d", o );
55216179Sralph 			}
55316179Sralph 
55416179Sralph 		}
55516179Sralph 
55616179Sralph 	if( actions & CVTO ) p = oconvert(p);
55716179Sralph 	p = clocal(p);
55816179Sralph 
55916179Sralph # ifndef BUG1
56016179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
56116179Sralph # endif
56216179Sralph 
56316179Sralph 	return(p);
56416179Sralph 
56516179Sralph 	}
56616179Sralph 
567*24408Smckusick int fpe_count = -1;
568*24408Smckusick jmp_buf gotfpe;
569*24408Smckusick 
570*24408Smckusick fpe() {
571*24408Smckusick 	if (fpe_count < 0)
572*24408Smckusick 		cerror("floating point exception");
573*24408Smckusick 	++fpe_count;
574*24408Smckusick 	longjmp(gotfpe, 1);
575*24408Smckusick 	}
576*24408Smckusick 
57717749Sralph /*
57817749Sralph  * Rewrite arguments in a function call.
57917749Sralph  * Structure arguments are massaged, single
58017749Sralph  * precision floating point constants are
58117749Sralph  * cast to double (to eliminate convert code).
58217749Sralph  */
58316179Sralph NODE *
58417749Sralph fixargs( p ) register NODE *p;  {
58517749Sralph 	int o = p->in.op;
58616179Sralph 
58717749Sralph 	if( o == CM ){
58817749Sralph 		p->in.left = fixargs( p->in.left );
58917749Sralph 		p->in.right = fixargs( p->in.right );
59016179Sralph 		return( p );
59116179Sralph 		}
59216179Sralph 
59316179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
59416179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
59516179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
59616179Sralph 		p = clocal(p);
59716179Sralph 		}
59817749Sralph 	else if( o == FCON )
59917749Sralph 		p = makety(p, DOUBLE, 0, 0);
60016179Sralph 	return( p );
60116179Sralph 	}
60216179Sralph 
60316179Sralph chkstr( i, j, type ) TWORD type; {
60416179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
60516179Sralph 	/* i has been checked to contain a MOS or MOU */
60616179Sralph 	/* j is the index in dimtab of the members... */
60716179Sralph 	int k, kk;
60816179Sralph 
60916179Sralph 	extern int ddebug;
61016179Sralph 
61116179Sralph # ifndef BUG1
61216179Sralph #ifndef FLEXNAMES
61316179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
61416179Sralph #else
61516179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
61616179Sralph #endif
61716179Sralph # endif
61816179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
61916179Sralph 	else {
62016179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
62116179Sralph 			if( kk >= SYMTSZ ){
62216179Sralph 				cerror( "gummy structure" );
62316179Sralph 				return(1);
62416179Sralph 				}
62516179Sralph 			if( kk == i ) return( 1 );
62616179Sralph 			switch( stab[kk].stype ){
62716179Sralph 
62816179Sralph 			case STRTY:
62916179Sralph 			case UNIONTY:
63016179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
63116179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
63216179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
63316179Sralph 					werror(
63416179Sralph #ifndef FLEXNAMES
63516179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
63616179Sralph #else
63716179Sralph 					"illegal member use: perhaps %s.%s?",
63816179Sralph #endif
63916179Sralph 					stab[kk].sname, stab[i].sname );
64016179Sralph 					return(1);
64116179Sralph 					}
64216179Sralph 				}
64316179Sralph 			}
64416179Sralph 		}
64516179Sralph 	return( 0 );
64616179Sralph 	}
64716179Sralph 
64816179Sralph conval( p, o, q ) register NODE *p, *q; {
64916179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
65016179Sralph 	int i, u;
65116179Sralph 	CONSZ val;
65216179Sralph 
65316179Sralph 	val = q->tn.lval;
65416179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
65516179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
65616179Sralph 
65716179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
65816179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
65916179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
66016179Sralph 
66116179Sralph 	switch( o ){
66216179Sralph 
66316179Sralph 	case PLUS:
66416179Sralph 		p->tn.lval += val;
66516179Sralph 		if( p->tn.rval == NONAME ){
66616179Sralph 			p->tn.rval = q->tn.rval;
66716179Sralph 			p->in.type = q->in.type;
66816179Sralph 			}
66916179Sralph 		break;
67016179Sralph 	case MINUS:
67116179Sralph 		p->tn.lval -= val;
67216179Sralph 		break;
67316179Sralph 	case MUL:
67416179Sralph 		p->tn.lval *= val;
67516179Sralph 		break;
67616179Sralph 	case DIV:
67716179Sralph 		if( val == 0 ) uerror( "division by 0" );
67817749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
67916179Sralph 		else p->tn.lval /= val;
68016179Sralph 		break;
68116179Sralph 	case MOD:
68216179Sralph 		if( val == 0 ) uerror( "division by 0" );
68317749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
68416179Sralph 		else p->tn.lval %= val;
68516179Sralph 		break;
68616179Sralph 	case AND:
68716179Sralph 		p->tn.lval &= val;
68816179Sralph 		break;
68916179Sralph 	case OR:
69016179Sralph 		p->tn.lval |= val;
69116179Sralph 		break;
69216179Sralph 	case ER:
69317749Sralph 		p->tn.lval ^= val;
69416179Sralph 		break;
69516179Sralph 	case LS:
69616179Sralph 		i = val;
69716179Sralph 		p->tn.lval = p->tn.lval << i;
69816179Sralph 		break;
69916179Sralph 	case RS:
70016179Sralph 		i = val;
70117749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
70217749Sralph 		else p->tn.lval = p->tn.lval >> i;
70316179Sralph 		break;
70416179Sralph 
70516179Sralph 	case UNARY MINUS:
70616179Sralph 		p->tn.lval = - p->tn.lval;
70716179Sralph 		break;
70816179Sralph 	case COMPL:
70916179Sralph 		p->tn.lval = ~p->tn.lval;
71016179Sralph 		break;
71116179Sralph 	case NOT:
71216179Sralph 		p->tn.lval = !p->tn.lval;
71316179Sralph 		break;
71416179Sralph 	case LT:
71516179Sralph 		p->tn.lval = p->tn.lval < val;
71616179Sralph 		break;
71716179Sralph 	case LE:
71816179Sralph 		p->tn.lval = p->tn.lval <= val;
71916179Sralph 		break;
72016179Sralph 	case GT:
72116179Sralph 		p->tn.lval = p->tn.lval > val;
72216179Sralph 		break;
72316179Sralph 	case GE:
72416179Sralph 		p->tn.lval = p->tn.lval >= val;
72516179Sralph 		break;
72616179Sralph 	case ULT:
72716179Sralph 		p->tn.lval = (p->tn.lval-val)<0;
72816179Sralph 		break;
72916179Sralph 	case ULE:
73016179Sralph 		p->tn.lval = (p->tn.lval-val)<=0;
73116179Sralph 		break;
73216179Sralph 	case UGE:
73316179Sralph 		p->tn.lval = (p->tn.lval-val)>=0;
73416179Sralph 		break;
73516179Sralph 	case UGT:
73616179Sralph 		p->tn.lval = (p->tn.lval-val)>0;
73716179Sralph 		break;
73816179Sralph 	case EQ:
73916179Sralph 		p->tn.lval = p->tn.lval == val;
74016179Sralph 		break;
74116179Sralph 	case NE:
74216179Sralph 		p->tn.lval = p->tn.lval != val;
74316179Sralph 		break;
74416179Sralph 	default:
74516179Sralph 		return(0);
74616179Sralph 		}
74716179Sralph 	return(1);
74816179Sralph 	}
74916179Sralph 
75016179Sralph chkpun(p) register NODE *p; {
75116179Sralph 
75216179Sralph 	/* checks p for the existance of a pun */
75316179Sralph 
75416179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
75516179Sralph 
75616179Sralph 	/* one case is when enumerations are used: this applies only to lint */
75716179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
75816179Sralph 	/* we check that this integer is in fact a constant zero... */
75916179Sralph 
76016179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
76116179Sralph 	/* this falls out, because the LHS is never 0 */
76216179Sralph 
76316179Sralph 	register NODE *q;
76416179Sralph 	register t1, t2;
76516179Sralph 	register d1, d2;
76616179Sralph 
76716179Sralph 	t1 = p->in.left->in.type;
76816179Sralph 	t2 = p->in.right->in.type;
76916179Sralph 
77016179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
77116179Sralph 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
77216179Sralph 			uerror( "illegal comparison of enums" );
77316179Sralph 			return;
77416179Sralph 			}
77516179Sralph 		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
77616179Sralph 		werror( "enumeration type clash, operator %s", opst[p->in.op] );
77716179Sralph 		return;
77816179Sralph 		}
77916179Sralph 
78016179Sralph 	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
78116179Sralph 	else q = p->in.left;
78216179Sralph 
78316179Sralph 	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
78416179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
78516179Sralph 			werror( "illegal combination of pointer and integer, op %s",
78616179Sralph 				opst[p->in.op] );
78716179Sralph 			}
78816179Sralph 		}
78916179Sralph 	else {
79016179Sralph 		d1 = p->in.left->fn.cdim;
79116179Sralph 		d2 = p->in.right->fn.cdim;
79216179Sralph 		for( ;; ){
79316179Sralph 			if( t1 == t2 ) {;
79416179Sralph 				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
79516179Sralph 					werror( "illegal structure pointer combination" );
79616179Sralph 					}
79716179Sralph 				return;
79816179Sralph 				}
79916179Sralph 			if( ISARY(t1) || ISPTR(t1) ){
80016179Sralph 				if( !ISARY(t2) && !ISPTR(t2) ) break;
80116179Sralph 				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
80216179Sralph 					werror( "illegal array size combination" );
80316179Sralph 					return;
80416179Sralph 					}
80516179Sralph 				if( ISARY(t1) ) ++d1;
80616179Sralph 				if( ISARY(t2) ) ++d2;
80716179Sralph 				}
80816179Sralph 			else break;
80916179Sralph 			t1 = DECREF(t1);
81016179Sralph 			t2 = DECREF(t2);
81116179Sralph 			}
81216179Sralph 		werror( "illegal pointer combination" );
81316179Sralph 		}
81416179Sralph 
81516179Sralph 	}
81616179Sralph 
81716179Sralph NODE *
81816179Sralph stref( p ) register NODE *p; {
81916179Sralph 
82016179Sralph 	TWORD t;
82116179Sralph 	int d, s, dsc, align;
82216179Sralph 	OFFSZ off;
82316179Sralph 	register struct symtab *q;
82416179Sralph 
82516179Sralph 	/* make p->x */
82616179Sralph 	/* this is also used to reference automatic variables */
82716179Sralph 
82816179Sralph 	q = &stab[p->in.right->tn.rval];
82916179Sralph 	p->in.right->in.op = FREE;
83016179Sralph 	p->in.op = FREE;
83116179Sralph 	p = pconvert( p->in.left );
83216179Sralph 
83316179Sralph 	/* make p look like ptr to x */
83416179Sralph 
83516179Sralph 	if( !ISPTR(p->in.type)){
83616179Sralph 		p->in.type = PTR+UNIONTY;
83716179Sralph 		}
83816179Sralph 
83916179Sralph 	t = INCREF( q->stype );
84016179Sralph 	d = q->dimoff;
84116179Sralph 	s = q->sizoff;
84216179Sralph 
84316179Sralph 	p = makety( p, t, d, s );
84416179Sralph 
84516179Sralph 	/* compute the offset to be added */
84616179Sralph 
84716179Sralph 	off = q->offset;
84816179Sralph 	dsc = q->sclass;
84916179Sralph 
85016179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
85116179Sralph 		align = ALINT;
85216179Sralph 		s = INT;
85316179Sralph 		off = (off/align)*align;
85416179Sralph 		}
85516179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
85616179Sralph 
85716179Sralph 	p = buildtree( UNARY MUL, p, NIL );
85816179Sralph 
85916179Sralph 	/* if field, build field info */
86016179Sralph 
86116179Sralph 	if( dsc & FIELD ){
86216179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
86316179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
86416179Sralph 		}
86516179Sralph 
86616179Sralph 	return( clocal(p) );
86716179Sralph 	}
86816179Sralph 
86916179Sralph notlval(p) register NODE *p; {
87016179Sralph 
87116179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
87216179Sralph 
87316179Sralph 	again:
87416179Sralph 
87516179Sralph 	switch( p->in.op ){
87616179Sralph 
87716179Sralph 	case FLD:
87816179Sralph 		p = p->in.left;
87916179Sralph 		goto again;
88016179Sralph 
88116179Sralph 	case UNARY MUL:
88216179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
88316179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
88416179Sralph 		/* and the f().a bug, given that f returns a structure */
88516179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
88616179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
88716179Sralph 	case NAME:
88816179Sralph 	case OREG:
88916179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
89016179Sralph 	case REG:
89116179Sralph 		return(0);
89216179Sralph 
89316179Sralph 	default:
89416179Sralph 		return(1);
89516179Sralph 
89616179Sralph 		}
89716179Sralph 
89816179Sralph 	}
89916179Sralph 
90016179Sralph NODE *
90116179Sralph bcon( i ){ /* make a constant node with value i */
90216179Sralph 	register NODE *p;
90316179Sralph 
90416179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
90516179Sralph 	p->tn.lval = i;
90616179Sralph 	p->tn.rval = NONAME;
90716179Sralph 	return( clocal(p) );
90816179Sralph 	}
90916179Sralph 
91016179Sralph NODE *
91116179Sralph bpsize(p) register NODE *p; {
91216179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
91316179Sralph 	}
91416179Sralph 
91516179Sralph OFFSZ
91616179Sralph psize( p ) NODE *p; {
91716179Sralph 	/* p is a node of type pointer; psize returns the
91816179Sralph 	   size of the thing pointed to */
91916179Sralph 
92016179Sralph 	if( !ISPTR(p->in.type) ){
92116179Sralph 		uerror( "pointer required");
92216179Sralph 		return( SZINT );
92316179Sralph 		}
92416179Sralph 	/* note: no pointers to fields */
92516179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
92616179Sralph 	}
92716179Sralph 
92816179Sralph NODE *
92916179Sralph convert( p, f )  register NODE *p; {
93016179Sralph 	/*  convert an operand of p
93116179Sralph 	    f is either CVTL or CVTR
93216179Sralph 	    operand has type int, and is converted by the size of the other side
93316179Sralph 	    */
93416179Sralph 
93516179Sralph 	register NODE *q, *r;
93616179Sralph 
93716179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
93816179Sralph 
93916179Sralph 	r = block( PMCONV,
94016179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
94116179Sralph 	r = clocal(r);
94216179Sralph 	if( f == CVTL )
94316179Sralph 		p->in.left = r;
94416179Sralph 	else
94516179Sralph 		p->in.right = r;
94616179Sralph 	return(p);
94716179Sralph 
94816179Sralph 	}
94916179Sralph 
95016179Sralph econvert( p ) register NODE *p; {
95116179Sralph 
95216179Sralph 	/* change enums to ints, or appropriate types */
95316179Sralph 
95416179Sralph 	register TWORD ty;
95516179Sralph 
95616179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
95716179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
95816179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
95916179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
96016179Sralph 		else ty = LONG;
96116179Sralph 		ty = ctype( ty );
96216179Sralph 		p->fn.csiz = ty;
96316179Sralph 		MODTYPE(p->in.type,ty);
96416179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
96516179Sralph 		}
96616179Sralph 	}
96716179Sralph 
96816179Sralph NODE *
96916179Sralph pconvert( p ) register NODE *p; {
97016179Sralph 
97116179Sralph 	/* if p should be changed into a pointer, do so */
97216179Sralph 
97316179Sralph 	if( ISARY( p->in.type) ){
97416179Sralph 		p->in.type = DECREF( p->in.type );
97516179Sralph 		++p->fn.cdim;
97616179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
97716179Sralph 		}
97816179Sralph 	if( ISFTN( p->in.type) )
97916179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
98016179Sralph 
98116179Sralph 	return( p );
98216179Sralph 	}
98316179Sralph 
98416179Sralph NODE *
98516179Sralph oconvert(p) register NODE *p; {
98616179Sralph 	/* convert the result itself: used for pointer and unsigned */
98716179Sralph 
98816179Sralph 	switch(p->in.op) {
98916179Sralph 
99016179Sralph 	case LE:
99116179Sralph 	case LT:
99216179Sralph 	case GE:
99316179Sralph 	case GT:
99416179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
99516179Sralph 	case EQ:
99616179Sralph 	case NE:
99716179Sralph 		return( p );
99816179Sralph 
99916179Sralph 	case MINUS:
100016179Sralph 		return(  clocal( block( PVCONV,
100116179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
100216179Sralph 		}
100316179Sralph 
100416179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
100516179Sralph 
100616179Sralph 	return(p);
100716179Sralph 	}
100816179Sralph 
100916179Sralph NODE *
101016179Sralph ptmatch(p)  register NODE *p; {
101116179Sralph 
101216179Sralph 	/* makes the operands of p agree; they are
101316179Sralph 	   either pointers or integers, by this time */
101416179Sralph 	/* with MINUS, the sizes must be the same */
101516179Sralph 	/* with COLON, the types must be the same */
101616179Sralph 
101716179Sralph 	TWORD t1, t2, t;
101816179Sralph 	int o, d2, d, s2, s;
101916179Sralph 
102016179Sralph 	o = p->in.op;
102116179Sralph 	t = t1 = p->in.left->in.type;
102216179Sralph 	t2 = p->in.right->in.type;
102316179Sralph 	d = p->in.left->fn.cdim;
102416179Sralph 	d2 = p->in.right->fn.cdim;
102516179Sralph 	s = p->in.left->fn.csiz;
102616179Sralph 	s2 = p->in.right->fn.csiz;
102716179Sralph 
102816179Sralph 	switch( o ){
102916179Sralph 
103016179Sralph 	case ASSIGN:
103116179Sralph 	case RETURN:
103216179Sralph 	case CAST:
103316179Sralph 		{  break; }
103416179Sralph 
103516179Sralph 	case MINUS:
103616179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
103716179Sralph 			uerror( "illegal pointer subtraction");
103816179Sralph 			}
103916179Sralph 		   break;
104016179Sralph 		   }
104116179Sralph 	case COLON:
104216179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
104316179Sralph 		   break;
104416179Sralph 		   }
104516179Sralph 	default:  /* must work harder: relationals or comparisons */
104616179Sralph 
104716179Sralph 		if( !ISPTR(t1) ){
104816179Sralph 			t = t2;
104916179Sralph 			d = d2;
105016179Sralph 			s = s2;
105116179Sralph 			break;
105216179Sralph 			}
105316179Sralph 		if( !ISPTR(t2) ){
105416179Sralph 			break;
105516179Sralph 			}
105616179Sralph 
105716179Sralph 		/* both are pointers */
105816179Sralph 		if( talign(t2,s2) < talign(t,s) ){
105916179Sralph 			t = t2;
106016179Sralph 			s = s2;
106116179Sralph 			}
106216179Sralph 		break;
106316179Sralph 		}
106416179Sralph 
106516179Sralph 	p->in.left = makety( p->in.left, t, d, s );
106616179Sralph 	p->in.right = makety( p->in.right, t, d, s );
106716179Sralph 	if( o!=MINUS && !logop(o) ){
106816179Sralph 
106916179Sralph 		p->in.type = t;
107016179Sralph 		p->fn.cdim = d;
107116179Sralph 		p->fn.csiz = s;
107216179Sralph 		}
107316179Sralph 
107416179Sralph 	return(clocal(p));
107516179Sralph 	}
107616179Sralph 
107716179Sralph int tdebug = 0;
107816179Sralph 
107916179Sralph NODE *
108016179Sralph tymatch(p)  register NODE *p; {
108116179Sralph 
108216179Sralph 	/* satisfy the types of various arithmetic binary ops */
108316179Sralph 
108416179Sralph 	/* rules are:
108516179Sralph 		if assignment, op, type of LHS
108616179Sralph 		if any float or doubles, make double
108716179Sralph 		if any longs, make long
108816179Sralph 		otherwise, make int
108916179Sralph 		if either operand is unsigned, the result is...
109016179Sralph 	*/
109116179Sralph 
109216179Sralph 	register TWORD t1, t2, t, tu;
109316179Sralph 	register o, u;
109416179Sralph 
109516179Sralph 	o = p->in.op;
109616179Sralph 
109716179Sralph 	t1 = p->in.left->in.type;
109816179Sralph 	t2 = p->in.right->in.type;
109916179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
110016179Sralph 		uerror("void type illegal in expression");
110116179Sralph 
110216179Sralph 	u = 0;
110316179Sralph 	if( ISUNSIGNED(t1) ){
110416179Sralph 		u = 1;
110516179Sralph 		t1 = DEUNSIGN(t1);
110616179Sralph 		}
110716179Sralph 	if( ISUNSIGNED(t2) ){
110816179Sralph 		u = 1;
110916179Sralph 		t2 = DEUNSIGN(t2);
111016179Sralph 		}
111116179Sralph 
111216179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
111316179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
111416179Sralph 
111517749Sralph #ifdef SPRECC
111617749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
111717749Sralph 		t = DOUBLE;
111817749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
111917749Sralph 		t = FLOAT;
112017749Sralph #else
112117749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
112217749Sralph 		t = DOUBLE;
112317749Sralph #endif
112416179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
112516179Sralph 	else t = INT;
112616179Sralph 
112716179Sralph 	if( asgop(o) ){
112816179Sralph 		tu = p->in.left->in.type;
112916179Sralph 		t = t1;
113016179Sralph 		}
113116179Sralph 	else {
113216179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
113316179Sralph 		}
113416179Sralph 
113516179Sralph 	/* because expressions have values that are at least as wide
113616179Sralph 	   as INT or UNSIGNED, the only conversions needed
113716179Sralph 	   are those involving FLOAT/DOUBLE, and those
113816179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
113916179Sralph 
114016179Sralph 	if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
114116179Sralph 
114216179Sralph 	if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
114316179Sralph 
114416179Sralph 	if( asgop(o) ){
114516179Sralph 		p->in.type = p->in.left->in.type;
114616179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
114716179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
114816179Sralph 		}
114916179Sralph 	else if( !logop(o) ){
115016179Sralph 		p->in.type = tu;
115116179Sralph 		p->fn.cdim = 0;
115216179Sralph 		p->fn.csiz = t;
115316179Sralph 		}
115416179Sralph 
115516179Sralph # ifndef BUG1
115616179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
115716179Sralph # endif
115816179Sralph 
115916179Sralph 	return(p);
116016179Sralph 	}
116116179Sralph 
116216179Sralph NODE *
116316179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
116416179Sralph 	/* make p into type t by inserting a conversion */
116516179Sralph 
116616179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
116716179Sralph 	if( t == p->in.type ){
116816179Sralph 		p->fn.cdim = d;
116916179Sralph 		p->fn.csiz = s;
117016179Sralph 		return( p );
117116179Sralph 		}
117216179Sralph 
117316179Sralph 	if( t & TMASK ){
117416179Sralph 		/* non-simple type */
117517228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
117616179Sralph 		}
117716179Sralph 
117816179Sralph 	if( p->in.op == ICON ){
117917749Sralph 		if (t == DOUBLE) {
118017749Sralph 			p->in.op = DCON;
118117749Sralph 			if (ISUNSIGNED(p->in.type))
118217749Sralph 				p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
118317749Sralph 			else
118417749Sralph 				p->dpn.dval = p->tn.lval;
118517749Sralph 			p->in.type = p->fn.csiz = t;
118617749Sralph 			return (clocal(p));
118717749Sralph 		}
118817749Sralph 		if (t == FLOAT) {
118916179Sralph 			p->in.op = FCON;
119016179Sralph 			if( ISUNSIGNED(p->in.type) ){
119117749Sralph 				p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval;
119216179Sralph 				}
119316179Sralph 			else {
119417749Sralph 				p->fpn.fval = p->tn.lval;
119516179Sralph 				}
119616179Sralph 
119716179Sralph 			p->in.type = p->fn.csiz = t;
119816179Sralph 			return( clocal(p) );
119916179Sralph 			}
120016179Sralph 		}
120117749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
120217749Sralph 		double db;
120316179Sralph 
120417749Sralph 		p->in.op = DCON;
120517749Sralph 		db = p->fpn.fval;
120617749Sralph 		p->dpn.dval = db;
120717749Sralph 		p->in.type = p->fn.csiz = t;
120817749Sralph 		return (clocal(p));
120917749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
121017749Sralph 		float fl;
121117749Sralph 
121217749Sralph 		p->in.op = FCON;
121317749Sralph 		fl = p->dpn.dval;
121417749Sralph #ifdef notdef
121517749Sralph 		if (fl != p->dpn.dval)
121617749Sralph 			werror("float conversion loses precision");
121717749Sralph #endif
121817749Sralph 		p->fpn.fval = fl;
121917749Sralph 		p->in.type = p->fn.csiz = t;
122017749Sralph 		return (clocal(p));
122117749Sralph 	}
122217749Sralph 
122317049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
122416179Sralph 
122516179Sralph 	}
122616179Sralph 
122716179Sralph NODE *
122816179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
122916179Sralph 
123016179Sralph 	register NODE *p;
123116179Sralph 
123216179Sralph 	p = talloc();
123316179Sralph 	p->in.op = o;
123416179Sralph 	p->in.left = l;
123516179Sralph 	p->in.right = r;
123616179Sralph 	p->in.type = t;
123716179Sralph 	p->fn.cdim = d;
123816179Sralph 	p->fn.csiz = s;
123916179Sralph 	return(p);
124016179Sralph 	}
124116179Sralph 
124216179Sralph icons(p) register NODE *p; {
124316179Sralph 	/* if p is an integer constant, return its value */
124416179Sralph 	int val;
124516179Sralph 
124616179Sralph 	if( p->in.op != ICON ){
124716179Sralph 		uerror( "constant expected");
124816179Sralph 		val = 1;
124916179Sralph 		}
125016179Sralph 	else {
125116179Sralph 		val = p->tn.lval;
125216179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
125316179Sralph 		}
125416179Sralph 	tfree( p );
125516179Sralph 	return(val);
125616179Sralph 	}
125716179Sralph 
125816179Sralph /* 	the intent of this table is to examine the
125916179Sralph 	operators, and to check them for
126016179Sralph 	correctness.
126116179Sralph 
126216179Sralph 	The table is searched for the op and the
126316179Sralph 	modified type (where this is one of the
126416179Sralph 	types INT (includes char and short), LONG,
126516179Sralph 	DOUBLE (includes FLOAT), and POINTER
126616179Sralph 
126716179Sralph 	The default action is to make the node type integer
126816179Sralph 
126916179Sralph 	The actions taken include:
127016179Sralph 		PUN	  check for puns
127116179Sralph 		CVTL	  convert the left operand
127216179Sralph 		CVTR	  convert the right operand
127316179Sralph 		TYPL	  the type is determined by the left operand
127416179Sralph 		TYPR	  the type is determined by the right operand
127516179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
127616179Sralph 		PTMATCH	  like TYMATCH, but for pointers
127716179Sralph 		LVAL	  left operand must be lval
127816179Sralph 		CVTO	  convert the op
127916179Sralph 		NCVT	  do not convert the operands
128016179Sralph 		OTHER	  handled by code
128116179Sralph 		NCVTR	  convert the left operand, not the right...
128216179Sralph 
128316179Sralph 	*/
128416179Sralph 
128516179Sralph # define MINT 01  /* integer */
128616179Sralph # define MDBI 02   /* integer or double */
128716179Sralph # define MSTR 04  /* structure */
128816179Sralph # define MPTR 010  /* pointer */
128916179Sralph # define MPTI 020  /* pointer or integer */
129016179Sralph # define MENU 040 /* enumeration variable or member */
1291*24408Smckusick # define MVOID 0100000 /* void type */
129216179Sralph 
129316179Sralph opact( p )  NODE *p; {
129416179Sralph 
129516179Sralph 	register mt12, mt1, mt2, o;
129616179Sralph 
1297*24408Smckusick 	mt1 = mt2 = mt12 = 0;
129816179Sralph 
129916179Sralph 	switch( optype(o=p->in.op) ){
130016179Sralph 
130116179Sralph 	case BITYPE:
1302*24408Smckusick 		mt2 = moditype( p->in.right->in.type );
130316179Sralph 	case UTYPE:
1304*24408Smckusick 		mt1 = moditype( p->in.left->in.type );
1305*24408Smckusick 		break;
130616179Sralph 
130716179Sralph 		}
130816179Sralph 
1309*24408Smckusick 	if( ((mt1 | mt2) & MVOID) &&
1310*24408Smckusick 	    o != COMOP &&
1311*24408Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
1312*24408Smckusick 		/* if lhs of RETURN is void, grammar will complain */
1313*24408Smckusick 		if( o != RETURN )
1314*24408Smckusick 			uerror( "value of void expression used" );
1315*24408Smckusick 		return( NCVT );
1316*24408Smckusick 		}
1317*24408Smckusick 	mt1 &= ~MVOID;
1318*24408Smckusick 	mt2 &= ~MVOID;
1319*24408Smckusick 	mt12 = mt1 & mt2;
1320*24408Smckusick 
132116179Sralph 	switch( o ){
132216179Sralph 
132316179Sralph 	case NAME :
132416179Sralph 	case STRING :
132516179Sralph 	case ICON :
132616179Sralph 	case FCON :
132717749Sralph 	case DCON :
132816179Sralph 	case CALL :
132916179Sralph 	case UNARY CALL:
133016179Sralph 	case UNARY MUL:
133116179Sralph 		{  return( OTHER ); }
133216179Sralph 	case UNARY MINUS:
133316179Sralph 		if( mt1 & MDBI ) return( TYPL );
133416179Sralph 		break;
133516179Sralph 
133616179Sralph 	case COMPL:
133716179Sralph 		if( mt1 & MINT ) return( TYPL );
133816179Sralph 		break;
133916179Sralph 
134016179Sralph 	case UNARY AND:
134116179Sralph 		{  return( NCVT+OTHER ); }
134216179Sralph 	case INIT:
134316179Sralph 	case CM:
134416180Sralph 		return( 0 );
134516180Sralph 
134616179Sralph 	case NOT:
134716179Sralph 	case CBRANCH:
134816180Sralph 		if( mt1 & MSTR ) break;
134916180Sralph 		return( 0 );
135016180Sralph 
135116179Sralph 	case ANDAND:
135216179Sralph 	case OROR:
135316180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
135416179Sralph 		return( 0 );
135516179Sralph 
135616179Sralph 	case MUL:
135716179Sralph 	case DIV:
135816179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
135916179Sralph 		break;
136016179Sralph 
136116179Sralph 	case MOD:
136216179Sralph 	case AND:
136316179Sralph 	case OR:
136416179Sralph 	case ER:
136516179Sralph 		if( mt12 & MINT ) return( TYMATCH );
136616179Sralph 		break;
136716179Sralph 
136816179Sralph 	case LS:
136916179Sralph 	case RS:
137016179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
137116179Sralph 		break;
137216179Sralph 
137316179Sralph 	case EQ:
137416179Sralph 	case NE:
137516179Sralph 	case LT:
137616179Sralph 	case LE:
137716179Sralph 	case GT:
137816179Sralph 	case GE:
137916179Sralph 		if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
138016179Sralph 		if( mt12 & MDBI ) return( TYMATCH+CVTO );
138116179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
138216179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
138316179Sralph 		else break;
138416179Sralph 
138516179Sralph 	case QUEST:
138616179Sralph 	case COMOP:
138716179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
138816179Sralph 		return( TYPR );
138916179Sralph 
139016179Sralph 	case STREF:
139116179Sralph 		return( NCVTR+OTHER );
139216179Sralph 
139316179Sralph 	case FORCE:
139416179Sralph 		return( TYPL );
139516179Sralph 
139616179Sralph 	case COLON:
139716179Sralph 		if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
139816179Sralph 		else if( mt12 & MDBI ) return( TYMATCH );
139916179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
140016179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
140116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
140216179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
140316179Sralph 		break;
140416179Sralph 
140516179Sralph 	case ASSIGN:
140616179Sralph 	case RETURN:
140716179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
140816179Sralph 	case CAST:
140916179Sralph 		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
141016179Sralph 		if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
141116179Sralph 		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
141218436Smckusick 		else if( mt2 == 0 &&
141318436Smckusick 		        ( p->in.right->in.op == CALL ||
141418436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
141516179Sralph 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
141616179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
141716179Sralph 		break;
141816179Sralph 
141916179Sralph 	case ASG LS:
142016179Sralph 	case ASG RS:
142116179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
142216179Sralph 		break;
142316179Sralph 
142416179Sralph 	case ASG MUL:
142516179Sralph 	case ASG DIV:
142616179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
142716179Sralph 		break;
142816179Sralph 
142916179Sralph 	case ASG MOD:
143016179Sralph 	case ASG AND:
143116179Sralph 	case ASG OR:
143216179Sralph 	case ASG ER:
143316179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
143416179Sralph 		break;
143516179Sralph 
143616179Sralph 	case ASG PLUS:
143716179Sralph 	case ASG MINUS:
143816179Sralph 	case INCR:
143916179Sralph 	case DECR:
144016179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
144116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
144216179Sralph 		break;
144316179Sralph 
144416179Sralph 	case MINUS:
144516179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
144616179Sralph 		if( mt2 & MPTR ) break;
144716179Sralph 	case PLUS:
144816179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
144916179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
145016179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
145116179Sralph 
145216179Sralph 		}
1453*24408Smckusick 	if( mt12 == MSTR )
1454*24408Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1455*24408Smckusick 	else
1456*24408Smckusick 		uerror( "operands of %s have incompatible types", opst[o] );
145716179Sralph 	return( NCVT );
145816179Sralph 	}
145916179Sralph 
146016179Sralph moditype( ty ) TWORD ty; {
146116179Sralph 
146216179Sralph 	switch( ty ){
146316179Sralph 
146416179Sralph 	case TVOID:
146517206Sralph 		return( MPTR );
146616179Sralph 	case UNDEF:
1467*24408Smckusick 		return( MVOID );
146816179Sralph 	case ENUMTY:
146916179Sralph 	case MOETY:
147016179Sralph 		return( MENU );
147116179Sralph 
147216179Sralph 	case STRTY:
147316179Sralph 	case UNIONTY:
147416179Sralph 		return( MSTR );
147516179Sralph 
147616179Sralph 	case CHAR:
147716179Sralph 	case SHORT:
147816179Sralph 	case UCHAR:
147916179Sralph 	case USHORT:
148016179Sralph 		return( MINT|MPTI|MDBI );
148116179Sralph 	case UNSIGNED:
148216179Sralph 	case ULONG:
148316179Sralph 	case INT:
148416179Sralph 	case LONG:
148516179Sralph 		return( MINT|MDBI|MPTI );
148616179Sralph 	case FLOAT:
148716179Sralph 	case DOUBLE:
148816179Sralph 		return( MDBI );
148916179Sralph 	default:
149016179Sralph 		return( MPTR|MPTI );
149116179Sralph 
149216179Sralph 		}
149316179Sralph 	}
149416179Sralph 
149516179Sralph NODE *
149616179Sralph doszof( p )  register NODE *p; {
149716179Sralph 	/* do sizeof p */
149816179Sralph 	int i;
149916179Sralph 
150016179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
150116179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
150216179Sralph 
150316179Sralph 	tfree(p);
150416179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
150516179Sralph 	return( bcon( i ) );
150616179Sralph 	}
150716179Sralph 
150816179Sralph # ifndef BUG2
150916179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
151016179Sralph 	register ty;
151116179Sralph 
151216179Sralph 	*a = *b = down+1;
151316179Sralph 	while( down > 1 ){
151416179Sralph 		printf( "\t" );
151516179Sralph 		down -= 2;
151616179Sralph 		}
151716179Sralph 	if( down ) printf( "    " );
151816179Sralph 
151916179Sralph 	ty = optype( p->in.op );
152016179Sralph 
152116179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
152216179Sralph 	if( ty == LTYPE ){
152316179Sralph 		printf( CONFMT, p->tn.lval );
152416179Sralph 		printf( ", %d, ", p->tn.rval );
152516179Sralph 		}
152616179Sralph 	tprint( p->in.type );
152716179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
152816179Sralph 	}
152916179Sralph # endif
153016179Sralph 
153116179Sralph prtdcon( p ) register NODE *p; {
153217749Sralph 	int o = p->in.op, i;
153316179Sralph 
153417749Sralph 	if( o == DCON || o == FCON ){
153516179Sralph 		locctr( DATA );
153617749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
153716179Sralph 		deflab( i = getlab() );
153817749Sralph 		if( o == FCON )
153917749Sralph 			fincode( p->fpn.fval, SZFLOAT );
154017749Sralph 		else
154117749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
154216179Sralph 		p->tn.lval = 0;
154316179Sralph 		p->tn.rval = -i;
154417749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
154516179Sralph 		p->in.op = NAME;
154616179Sralph 		}
154716179Sralph 	}
154816179Sralph 
154916179Sralph 
155016179Sralph int edebug = 0;
155116179Sralph ecomp( p ) register NODE *p; {
155216179Sralph # ifndef BUG2
155316179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
155416179Sralph # endif
155516179Sralph 	if( !reached ){
155616179Sralph 		werror( "statement not reached" );
155716179Sralph 		reached = 1;
155816179Sralph 		}
155916179Sralph 	p = optim(p);
156016179Sralph 	walkf( p, prtdcon );
156116179Sralph 	locctr( PROG );
156216179Sralph 	ecode( p );
156316179Sralph 	tfree(p);
156416179Sralph 	}
156516179Sralph 
156616179Sralph # ifdef STDPRTREE
156716179Sralph # ifndef ONEPASS
156816179Sralph 
156916179Sralph prtree(p) register NODE *p; {
157016179Sralph 
157116179Sralph 	register struct symtab *q;
157216179Sralph 	register ty;
157316179Sralph 
157416179Sralph # ifdef MYPRTREE
157516179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
157616179Sralph #endif
157716179Sralph 
157816179Sralph 	ty = optype(p->in.op);
157916179Sralph 
158016179Sralph 	printf( "%d\t", p->in.op );
158116179Sralph 
158216179Sralph 	if( ty == LTYPE ) {
158316179Sralph 		printf( CONFMT, p->tn.lval );
158416179Sralph 		printf( "\t" );
158516179Sralph 		}
158616179Sralph 	if( ty != BITYPE ) {
158716179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
158816179Sralph 		else printf( "%d\t", p->tn.rval );
158916179Sralph 		}
159016179Sralph 
159116179Sralph 	printf( "%o\t", p->in.type );
159216179Sralph 
159316179Sralph 	/* handle special cases */
159416179Sralph 
159516179Sralph 	switch( p->in.op ){
159616179Sralph 
159716179Sralph 	case NAME:
159816179Sralph 	case ICON:
159916179Sralph 		/* print external name */
160016179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
160116179Sralph 		else if( p->tn.rval >= 0 ){
160216179Sralph 			q = &stab[p->tn.rval];
160316179Sralph 			printf(  "%s\n", exname(q->sname) );
160416179Sralph 			}
160516179Sralph 		else { /* label */
160616179Sralph 			printf( LABFMT, -p->tn.rval );
160716179Sralph 			}
160816179Sralph 		break;
160916179Sralph 
161016179Sralph 	case STARG:
161116179Sralph 	case STASG:
161216179Sralph 	case STCALL:
161316179Sralph 	case UNARY STCALL:
161416179Sralph 		/* print out size */
161516179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
161616179Sralph 
161716179Sralph 		/* note: p->in.left not a field... */
161816179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
161916179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
162016179Sralph 		break;
162116179Sralph 
162216179Sralph 	default:
162316179Sralph 		printf(  "\n" );
162416179Sralph 		}
162516179Sralph 
162616179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
162716179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
162816179Sralph 
162916179Sralph 	}
163016179Sralph 
163116179Sralph # else
163216179Sralph 
163316179Sralph p2tree(p) register NODE *p; {
163416179Sralph 	register ty;
163516179Sralph 
163616179Sralph # ifdef MYP2TREE
163716179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
163816179Sralph # endif
163916179Sralph 
164016179Sralph 	ty = optype(p->in.op);
164116179Sralph 
164216179Sralph 	switch( p->in.op ){
164316179Sralph 
164416179Sralph 	case NAME:
164516179Sralph 	case ICON:
164616179Sralph #ifndef FLEXNAMES
164716179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
164816179Sralph #else
164916179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
165016179Sralph #endif
165116179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
165216179Sralph 			register char *cp;
165316179Sralph 			register i;
165416179Sralph 			cp = exname( stab[p->tn.rval].sname );
165516179Sralph #ifndef FLEXNAMES
165616179Sralph 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
165716179Sralph #else
165816179Sralph 			p->in.name = tstr(cp);
165916179Sralph #endif
166016179Sralph 			}
166116179Sralph #ifndef FLEXNAMES
166216179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
166316179Sralph #else
166416179Sralph 		else {
166516179Sralph 			char temp[32];
166616179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
166716179Sralph 			p->in.name = tstr(temp);
166816179Sralph 		}
166916179Sralph #endif
167016179Sralph 		break;
167116179Sralph 
167216179Sralph 	case STARG:
167316179Sralph 	case STASG:
167416179Sralph 	case STCALL:
167516179Sralph 	case UNARY STCALL:
167616179Sralph 		/* set up size parameters */
167716179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
167816179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
167916179Sralph 		break;
168016179Sralph 
168116179Sralph 	case REG:
168216179Sralph 		rbusy( p->tn.rval, p->in.type );
168316179Sralph 	default:
168416179Sralph #ifndef FLEXNAMES
168516179Sralph 		p->in.name[0] = '\0';
168616179Sralph #else
168716179Sralph 		p->in.name = "";
168816179Sralph #endif
168916179Sralph 		}
169016179Sralph 
169116179Sralph 	p->in.rall = NOPREF;
169216179Sralph 
169316179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
169416179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
169516179Sralph 	}
169616179Sralph 
169716179Sralph # endif
169816179Sralph # endif
1699