xref: /csrg-svn/old/pcc/mip/trees.c (revision 17749)
1*17749Sralph #ifndef lint
2*17749Sralph static char *sccsid ="@(#)trees.c	4.6 (Berkeley) 01/18/85";
3*17749Sralph #endif
4*17749Sralph 
516179Sralph # include "mfile1"
616179Sralph 
7*17749Sralph int bdebug = 0;
8*17749Sralph int adebug = 0;
9*17749Sralph extern ddebug;
10*17749Sralph extern eprint();
11*17749Sralph 
1216179Sralph 	    /* corrections when in violation of lint */
1316179Sralph 
1416179Sralph /*	some special actions, used in finding the type of nodes */
1516179Sralph # define NCVT 01
1616179Sralph # define PUN 02
1716179Sralph # define TYPL 04
1816179Sralph # define TYPR 010
1916179Sralph # define TYMATCH 040
2016179Sralph # define LVAL 0100
2116179Sralph # define CVTO 0200
2216179Sralph # define CVTL 0400
2316179Sralph # define CVTR 01000
2416179Sralph # define PTMATCH 02000
2516179Sralph # define OTHER 04000
2616179Sralph # define NCVTR 010000
2716179Sralph 
28*17749Sralph #ifndef BUG1
29*17749Sralph printact(t, acts)
30*17749Sralph 	NODE *t;
31*17749Sralph 	int acts;
32*17749Sralph {
33*17749Sralph 	static struct actions {
34*17749Sralph 		int	a_bit;
35*17749Sralph 		char	*a_name;
36*17749Sralph 	} actions[] = {
37*17749Sralph 		{ PUN,		"PUN" },
38*17749Sralph 		{ CVTL,		"CVTL" },
39*17749Sralph 		{ CVTR,		"CVTR" },
40*17749Sralph 		{ TYPL,		"TYPL" },
41*17749Sralph 		{ TYPR,		"TYPR" },
42*17749Sralph 		{ TYMATCH,	"TYMATCH" },
43*17749Sralph 		{ PTMATCH,	"PTMATCH" },
44*17749Sralph 		{ LVAL,		"LVAL" },
45*17749Sralph 		{ CVTO,		"CVTO" },
46*17749Sralph 		{ NCVT,		"NCVT" },
47*17749Sralph 		{ OTHER,	"OTHER" },
48*17749Sralph 		{ NCVTR,	"NCVTR" },
49*17749Sralph 		{ 0 }
50*17749Sralph 	};
51*17749Sralph 	register struct actions *p;
52*17749Sralph 	char *sep = " ";
53*17749Sralph 
54*17749Sralph 	printf("actions");
55*17749Sralph 	for (p = actions; p->a_name; p++)
56*17749Sralph 		if (p->a_bit & acts) {
57*17749Sralph 			printf("%s%s", sep, p->a_name);
58*17749Sralph 			sep = "|";
59*17749Sralph 		}
60*17749Sralph 	if (!bdebug) {
61*17749Sralph 		printf(" for:\n");
62*17749Sralph 		fwalk(t, eprint, 0);
63*17749Sralph 	} else
64*17749Sralph 		putchar('\n');
65*17749Sralph }
66*17749Sralph #endif
67*17749Sralph 
6816179Sralph /* node conventions:
6916179Sralph 
7016179Sralph 	NAME:	rval>0 is stab index for external
7116179Sralph 		rval<0 is -inlabel number
7216179Sralph 		lval is offset in bits
7316179Sralph 	ICON:	lval has the value
7416179Sralph 		rval has the STAB index, or - label number,
7516179Sralph 			if a name whose address is in the constant
7616179Sralph 		rval = NONAME means no name
7716179Sralph 	REG:	rval is reg. identification cookie
7816179Sralph 
7916179Sralph 	*/
8016179Sralph 
8116179Sralph NODE *
8216179Sralph buildtree( o, l, r ) register NODE *l, *r; {
8316179Sralph 	register NODE *p, *q;
8416179Sralph 	register actions;
8516179Sralph 	register opty;
8616179Sralph 	register struct symtab *sp;
8716179Sralph 	register NODE *lr, *ll;
88*17749Sralph 	NODE *fixargs();
8916179Sralph 	int i;
9016179Sralph 
9116179Sralph # ifndef BUG1
9216179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9316179Sralph # endif
9416179Sralph 	opty = optype(o);
9516179Sralph 
9616179Sralph 	/* check for constants */
9716179Sralph 
9816179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
9916179Sralph 
10016179Sralph 		switch( o ){
10116179Sralph 
10216179Sralph 		case NOT:
10316179Sralph 			if( hflag ) werror( "constant argument to NOT" );
10416179Sralph 		case UNARY MINUS:
10516179Sralph 		case COMPL:
10616179Sralph 			if( conval( l, o, l ) ) return(l);
10716179Sralph 			break;
10816179Sralph 
10916179Sralph 			}
11016179Sralph 		}
11116179Sralph 
11216179Sralph 	else if( o==UNARY MINUS && l->in.op==FCON ){
113*17749Sralph 		l->fpn.fval = -l->fpn.fval;
11416179Sralph 		return(l);
11516179Sralph 		}
11616179Sralph 
117*17749Sralph 	else if( o==UNARY MINUS && l->in.op==DCON ){
118*17749Sralph 		l->dpn.dval = -l->dpn.dval;
119*17749Sralph 		return(l);
120*17749Sralph 		}
121*17749Sralph 
12216179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
12316179Sralph 		l->in.op = FREE;
12416179Sralph 		r->in.op = FREE;
12516179Sralph 		if( l->tn.lval ){
12616179Sralph 			tfree( r->in.right );
12716179Sralph 			return( r->in.left );
12816179Sralph 			}
12916179Sralph 		else {
13016179Sralph 			tfree( r->in.left );
13116179Sralph 			return( r->in.right );
13216179Sralph 			}
13316179Sralph 		}
13416179Sralph 
13516179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
13616179Sralph 
13716179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
13816179Sralph 
13916179Sralph 		switch( o ){
14016179Sralph 
14116179Sralph 		case ULT:
14216179Sralph 		case UGT:
14316179Sralph 		case ULE:
14416179Sralph 		case UGE:
14516179Sralph 		case LT:
14616179Sralph 		case GT:
14716179Sralph 		case LE:
14816179Sralph 		case GE:
14916179Sralph 		case EQ:
15016179Sralph 		case NE:
15116179Sralph 		case ANDAND:
15216179Sralph 		case OROR:
15316179Sralph 		case CBRANCH:
15416179Sralph 
15516179Sralph 		ccwarn:
15616179Sralph 			if( hflag ) werror( "constant in conditional context" );
15716179Sralph 
15816179Sralph 		case PLUS:
15916179Sralph 		case MINUS:
16016179Sralph 		case MUL:
16116179Sralph 		case DIV:
16216179Sralph 		case MOD:
16316179Sralph 		case AND:
16416179Sralph 		case OR:
16516179Sralph 		case ER:
16616179Sralph 		case LS:
16716179Sralph 		case RS:
16816179Sralph 			if( conval( l, o, r ) ) {
16916179Sralph 				r->in.op = FREE;
17016179Sralph 				return(l);
17116179Sralph 				}
17216179Sralph 			break;
17316179Sralph 			}
17416179Sralph 		}
175*17749Sralph 	else if (opty == BITYPE) {
176*17749Sralph 		if ((l->in.op == FCON || l->in.op == ICON) &&
177*17749Sralph 		    (r->in.op == FCON || r->in.op == ICON))
178*17749Sralph 			switch (o) {
17916179Sralph 
180*17749Sralph 			case PLUS:
181*17749Sralph 			case MINUS:
182*17749Sralph 			case MUL:
183*17749Sralph 			case DIV:
184*17749Sralph 				if (l->in.op == ICON)
185*17749Sralph 					l->fpn.fval = l->tn.lval;
186*17749Sralph 				if (r->in.op == ICON)
187*17749Sralph 					r->fpn.fval = r->tn.lval;
188*17749Sralph 				l->in.op = FCON;
189*17749Sralph 				l->in.type = l->fn.csiz = FLOAT;
190*17749Sralph 				r->in.op = FREE;
191*17749Sralph 				switch (o) {
192*17749Sralph 
193*17749Sralph 				case PLUS:
194*17749Sralph 					l->fpn.fval += r->fpn.fval;
195*17749Sralph 					return (l);
196*17749Sralph 
197*17749Sralph 				case MINUS:
198*17749Sralph 					l->fpn.fval -= r->fpn.fval;
199*17749Sralph 					return (l);
200*17749Sralph 
201*17749Sralph 				case MUL:
202*17749Sralph 					l->fpn.fval *= r->fpn.fval;
203*17749Sralph 					return (l);
204*17749Sralph 
205*17749Sralph 				case DIV:
206*17749Sralph 					if (r->fpn.fval == 0)
207*17749Sralph 						uerror("division by 0.");
208*17749Sralph 					else
209*17749Sralph 						l->fpn.fval /= r->fpn.fval;
210*17749Sralph 					return (l);
21116179Sralph 				}
212*17749Sralph 			}
213*17749Sralph 		else if ((l->in.op == DCON || l->in.op == ICON) &&
214*17749Sralph 		    (r->in.op == DCON || r->in.op == ICON))
215*17749Sralph 			switch (o) {
216*17749Sralph 
21716179Sralph 			case PLUS:
21816179Sralph 			case MINUS:
21916179Sralph 			case MUL:
22016179Sralph 			case DIV:
221*17749Sralph 				if (l->in.op == ICON)
222*17749Sralph 					l->dpn.dval = l->tn.lval;
223*17749Sralph 				if (r->in.op == ICON)
224*17749Sralph 					r->dpn.dval = r->tn.lval;
225*17749Sralph 				l->in.op = DCON;
226*17749Sralph 				l->in.type = l->fn.csiz = DOUBLE;
227*17749Sralph 				r->in.op = FREE;
228*17749Sralph 				switch (o) {
229*17749Sralph 
230*17749Sralph 				case PLUS:
231*17749Sralph 					l->dpn.dval += r->dpn.dval;
232*17749Sralph 					return (l);
233*17749Sralph 
234*17749Sralph 				case MINUS:
235*17749Sralph 					l->dpn.dval -= r->dpn.dval;
236*17749Sralph 					return (l);
237*17749Sralph 
238*17749Sralph 				case MUL:
239*17749Sralph 					l->dpn.dval *= r->dpn.dval;
240*17749Sralph 					return (l);
241*17749Sralph 
242*17749Sralph 				case DIV:
243*17749Sralph 					if (r->dpn.dval == 0)
244*17749Sralph 						uerror("division by 0.");
245*17749Sralph 					else
246*17749Sralph 						l->dpn.dval /= r->dpn.dval;
247*17749Sralph 					return (l);
24816179Sralph 				}
24916179Sralph 			}
250*17749Sralph 	}
25116179Sralph 
25216179Sralph 	/* its real; we must make a new node */
25316179Sralph 
25416179Sralph 	p = block( o, l, r, INT, 0, INT );
25516179Sralph 
25616179Sralph 	actions = opact(p);
257*17749Sralph #ifndef	BUG1
258*17749Sralph 	if (adebug)
259*17749Sralph 		printact(p, actions);
260*17749Sralph #endif
26116179Sralph 
26216179Sralph 	if( actions&LVAL ){ /* check left descendent */
26316179Sralph 		if( notlval(p->in.left) ) {
26416179Sralph 			uerror( "illegal lhs of assignment operator" );
26516179Sralph 			}
26616179Sralph 		}
26716179Sralph 
26816179Sralph 	if( actions & NCVTR ){
26916179Sralph 		p->in.left = pconvert( p->in.left );
27016179Sralph 		}
27116179Sralph 	else if( !(actions & NCVT ) ){
27216179Sralph 		switch( opty ){
27316179Sralph 
27416179Sralph 		case BITYPE:
27516179Sralph 			p->in.right = pconvert( p->in.right );
27616179Sralph 		case UTYPE:
27716179Sralph 			p->in.left = pconvert( p->in.left );
27816179Sralph 
27916179Sralph 			}
28016179Sralph 		}
28116179Sralph 
28216179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
28316179Sralph 		chkpun(p);
28416179Sralph 		}
28516179Sralph 
28616179Sralph 	if( actions & (TYPL|TYPR) ){
28716179Sralph 
28816179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
28916179Sralph 
29016179Sralph 		p->in.type = q->in.type;
29116179Sralph 		p->fn.cdim = q->fn.cdim;
29216179Sralph 		p->fn.csiz = q->fn.csiz;
29316179Sralph 		}
29416179Sralph 
29516179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
29616179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
29716179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
29816179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
29916179Sralph 
30016179Sralph 	if( actions & OTHER ){
30116179Sralph 		l = p->in.left;
30216179Sralph 		r = p->in.right;
30316179Sralph 
30416179Sralph 		switch(o){
30516179Sralph 
30616179Sralph 		case NAME:
30716179Sralph 			sp = &stab[idname];
30816179Sralph 			if( sp->stype == UNDEF ){
30916179Sralph #ifndef FLEXNAMES
31016179Sralph 				uerror( "%.8s undefined", sp->sname );
31116179Sralph #else
31216179Sralph 				uerror( "%s undefined", sp->sname );
31316179Sralph #endif
31416179Sralph 				/* make p look reasonable */
31516179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
31616179Sralph 				p->tn.rval = idname;
31716179Sralph 				p->tn.lval = 0;
31816179Sralph 				defid( p, SNULL );
31916179Sralph 				break;
32016179Sralph 				}
32116179Sralph 			p->in.type = sp->stype;
32216179Sralph 			p->fn.cdim = sp->dimoff;
32316179Sralph 			p->fn.csiz = sp->sizoff;
32416179Sralph 			p->tn.lval = 0;
32516179Sralph 			p->tn.rval = idname;
32616179Sralph 			/* special case: MOETY is really an ICON... */
32716179Sralph 			if( p->in.type == MOETY ){
32816179Sralph 				p->tn.rval = NONAME;
32916179Sralph 				p->tn.lval = sp->offset;
33016179Sralph 				p->fn.cdim = 0;
33116179Sralph 				p->in.type = ENUMTY;
33216179Sralph 				p->in.op = ICON;
33316179Sralph 				}
33416179Sralph 			break;
33516179Sralph 
33616179Sralph 		case ICON:
33716179Sralph 			p->in.type = INT;
33816179Sralph 			p->fn.cdim = 0;
33916179Sralph 			p->fn.csiz = INT;
34016179Sralph 			break;
34116179Sralph 
34216179Sralph 		case STRING:
34316179Sralph 			p->in.op = NAME;
34416179Sralph 			p->in.type = CHAR+ARY;
34516179Sralph 			p->tn.lval = 0;
34616179Sralph 			p->tn.rval = NOLAB;
34716179Sralph 			p->fn.cdim = curdim;
34816179Sralph 			p->fn.csiz = CHAR;
34916179Sralph 			break;
35016179Sralph 
35116179Sralph 		case FCON:
35216179Sralph 			p->tn.lval = 0;
35316179Sralph 			p->tn.rval = 0;
354*17749Sralph 			p->in.type = FLOAT;
355*17749Sralph 			p->fn.cdim = 0;
356*17749Sralph 			p->fn.csiz = FLOAT;
357*17749Sralph 			break;
358*17749Sralph 
359*17749Sralph 		case DCON:
360*17749Sralph 			p->tn.lval = 0;
361*17749Sralph 			p->tn.rval = 0;
36216179Sralph 			p->in.type = DOUBLE;
36316179Sralph 			p->fn.cdim = 0;
36416179Sralph 			p->fn.csiz = DOUBLE;
36516179Sralph 			break;
36616179Sralph 
36716179Sralph 		case STREF:
36816179Sralph 			/* p->x turned into *(p+offset) */
36916179Sralph 			/* rhs must be a name; check correctness */
37016179Sralph 
37116179Sralph 			i = r->tn.rval;
37216179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
37316179Sralph 				uerror( "member of structure or union required" );
37416179Sralph 				}else
37516179Sralph 			/* if this name is non-unique, find right one */
37616179Sralph 			if( stab[i].sflags & SNONUNIQ &&
37716179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
37816179Sralph 				(l->fn.csiz +1) >= 0 ){
37916179Sralph 				/* nonunique name && structure defined */
38016179Sralph 				char * memnam, * tabnam;
38116179Sralph 				register k;
38216179Sralph 				int j;
38316179Sralph 				int memi;
38416179Sralph 				j=dimtab[l->fn.csiz+1];
38516179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
38616179Sralph 					tabnam = stab[memi].sname;
38716179Sralph 					memnam = stab[i].sname;
38816179Sralph # ifndef BUG1
38916179Sralph 					if( ddebug>1 ){
39016179Sralph #ifndef FLEXNAMES
39116179Sralph 						printf("member %.8s==%.8s?\n",
39216179Sralph #else
39316179Sralph 						printf("member %s==%s?\n",
39416179Sralph #endif
39516179Sralph 							memnam, tabnam);
39616179Sralph 						}
39716179Sralph # endif
39816179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
39916179Sralph #ifndef FLEXNAMES
40016179Sralph 						for( k=0; k<NCHNAM; ++k ){
40116179Sralph 							if(*memnam++!=*tabnam)
40216179Sralph 								goto next;
40316179Sralph 							if(!*tabnam++) break;
40416179Sralph 							}
40516179Sralph #else
40616179Sralph 						if (memnam != tabnam)
40716179Sralph 							goto next;
40816179Sralph #endif
40916179Sralph 						r->tn.rval = i = memi;
41016179Sralph 						break;
41116179Sralph 						}
41216179Sralph 					next: continue;
41316179Sralph 					}
41416179Sralph 				if( memi < 0 )
41516179Sralph #ifndef FLEXNAMES
41616179Sralph 					uerror("illegal member use: %.8s",
41716179Sralph #else
41816179Sralph 					uerror("illegal member use: %s",
41916179Sralph #endif
42016179Sralph 						stab[i].sname);
42116179Sralph 				}
42216179Sralph 			else {
42316179Sralph 				register j;
42416179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
42516179Sralph 					if( stab[i].sflags & SNONUNIQ ){
42616179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
42716179Sralph 						}
42816179Sralph 					else werror( "struct/union or struct/union pointer required" );
42916179Sralph 					}
43016179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
43116179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
43216179Sralph #ifndef FLEXNAMES
43316179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
43416179Sralph #else
43516179Sralph 					werror( "illegal member use: %s", stab[i].sname );
43616179Sralph #endif
43716179Sralph 					}
43816179Sralph 				}
43916179Sralph 
44016179Sralph 			p = stref( p );
44116179Sralph 			break;
44216179Sralph 
44316179Sralph 		case UNARY MUL:
44416179Sralph 			if( l->in.op == UNARY AND ){
44516179Sralph 				p->in.op = l->in.op = FREE;
44616179Sralph 				p = l->in.left;
44716179Sralph 				}
44816179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
44916179Sralph 			p->in.type = DECREF(l->in.type);
45016179Sralph 			p->fn.cdim = l->fn.cdim;
45116179Sralph 			p->fn.csiz = l->fn.csiz;
45216179Sralph 			break;
45316179Sralph 
45416179Sralph 		case UNARY AND:
45516179Sralph 			switch( l->in.op ){
45616179Sralph 
45716179Sralph 			case UNARY MUL:
45816179Sralph 				p->in.op = l->in.op = FREE;
45916179Sralph 				p = l->in.left;
46016179Sralph 			case NAME:
46116179Sralph 				p->in.type = INCREF( l->in.type );
46216179Sralph 				p->fn.cdim = l->fn.cdim;
46316179Sralph 				p->fn.csiz = l->fn.csiz;
46416179Sralph 				break;
46516179Sralph 
46616179Sralph 			case COMOP:
46716179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
46816179Sralph 				p->in.op = l->in.op = FREE;
46916179Sralph 				p = buildtree( COMOP, l->in.left, lr );
47016179Sralph 				break;
47116179Sralph 
47216179Sralph 			case QUEST:
47316179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
47416179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
47516179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
47616179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
47716179Sralph 				break;
47816179Sralph 
47916179Sralph # ifdef ADDROREG
48016179Sralph 			case OREG:
48116179Sralph 				/* OREG was built in clocal()
48216179Sralph 				 * for an auto or formal parameter
48316179Sralph 				 * now its address is being taken
48416179Sralph 				 * local code must unwind it
48516179Sralph 				 * back to PLUS/MINUS REG ICON
48616179Sralph 				 * according to local conventions
48716179Sralph 				 */
48816179Sralph 				{
48916179Sralph 				extern NODE * addroreg();
49016179Sralph 				p->in.op = FREE;
49116179Sralph 				p = addroreg( l );
49216179Sralph 				}
49316179Sralph 				break;
49416179Sralph 
49516179Sralph # endif
49616179Sralph 			default:
49716179Sralph 				uerror( "unacceptable operand of &" );
49816179Sralph 				break;
49916179Sralph 				}
50016179Sralph 			break;
50116179Sralph 
50216179Sralph 		case LS:
50316179Sralph 		case RS:
50416179Sralph 		case ASG LS:
50516179Sralph 		case ASG RS:
50616179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
50716179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
50816179Sralph 			break;
50916179Sralph 
51016179Sralph 		case RETURN:
51116179Sralph 		case ASSIGN:
51216179Sralph 		case CAST:
51316179Sralph 			/* structure assignment */
51416179Sralph 			/* take the addresses of the two sides; then make an
51516179Sralph 			/* operator using STASG and
51616179Sralph 			/* the addresses of left and right */
51716179Sralph 
51816179Sralph 			{
51916179Sralph 				register TWORD t;
52016179Sralph 				register d, s;
52116179Sralph 
52216179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
52316179Sralph 
52416179Sralph 				r = buildtree( UNARY AND, r, NIL );
52516179Sralph 				t = r->in.type;
52616179Sralph 				d = r->fn.cdim;
52716179Sralph 				s = r->fn.csiz;
52816179Sralph 
52916179Sralph 				l = block( STASG, l, r, t, d, s );
53016179Sralph 
53116179Sralph 				if( o == RETURN ){
53216179Sralph 					p->in.op = FREE;
53316179Sralph 					p = l;
53416179Sralph 					break;
53516179Sralph 					}
53616179Sralph 
53716179Sralph 				p->in.op = UNARY MUL;
53816179Sralph 				p->in.left = l;
53916179Sralph 				p->in.right = NIL;
54016179Sralph 				break;
54116179Sralph 				}
54216179Sralph 		case COLON:
54316179Sralph 			/* structure colon */
54416179Sralph 
54516179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
54616179Sralph 			break;
54716179Sralph 
54816179Sralph 		case CALL:
549*17749Sralph 			p->in.right = r = fixargs( p->in.right );
55016179Sralph 		case UNARY CALL:
55116179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
55216179Sralph 			p->in.type = DECREF(l->in.type);
55316179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
55416179Sralph 			p->in.type = DECREF( p->in.type );
55516179Sralph 			p->fn.cdim = l->fn.cdim;
55616179Sralph 			p->fn.csiz = l->fn.csiz;
55716179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
55816179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
55916179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
56016179Sralph 				p->in.op += (FORTCALL-CALL);
56116179Sralph 				}
56216179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
56316179Sralph 				/* function returning structure */
56416179Sralph 				/*  make function really return ptr to str., with * */
56516179Sralph 
56616179Sralph 				p->in.op += STCALL-CALL;
56716179Sralph 				p->in.type = INCREF( p->in.type );
56816179Sralph 				p = buildtree( UNARY MUL, p, NIL );
56916179Sralph 
57016179Sralph 				}
57116179Sralph 			break;
57216179Sralph 
57316179Sralph 		default:
57416179Sralph 			cerror( "other code %d", o );
57516179Sralph 			}
57616179Sralph 
57716179Sralph 		}
57816179Sralph 
57916179Sralph 	if( actions & CVTO ) p = oconvert(p);
58016179Sralph 	p = clocal(p);
58116179Sralph 
58216179Sralph # ifndef BUG1
58316179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
58416179Sralph # endif
58516179Sralph 
58616179Sralph 	return(p);
58716179Sralph 
58816179Sralph 	}
58916179Sralph 
590*17749Sralph /*
591*17749Sralph  * Rewrite arguments in a function call.
592*17749Sralph  * Structure arguments are massaged, single
593*17749Sralph  * precision floating point constants are
594*17749Sralph  * cast to double (to eliminate convert code).
595*17749Sralph  */
59616179Sralph NODE *
597*17749Sralph fixargs( p ) register NODE *p;  {
598*17749Sralph 	int o = p->in.op;
59916179Sralph 
600*17749Sralph 	if( o == CM ){
601*17749Sralph 		p->in.left = fixargs( p->in.left );
602*17749Sralph 		p->in.right = fixargs( p->in.right );
60316179Sralph 		return( p );
60416179Sralph 		}
60516179Sralph 
60616179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
60716179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
60816179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
60916179Sralph 		p = clocal(p);
61016179Sralph 		}
611*17749Sralph 	else if( o == FCON )
612*17749Sralph 		p = makety(p, DOUBLE, 0, 0);
61316179Sralph 	return( p );
61416179Sralph 	}
61516179Sralph 
61616179Sralph chkstr( i, j, type ) TWORD type; {
61716179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
61816179Sralph 	/* i has been checked to contain a MOS or MOU */
61916179Sralph 	/* j is the index in dimtab of the members... */
62016179Sralph 	int k, kk;
62116179Sralph 
62216179Sralph 	extern int ddebug;
62316179Sralph 
62416179Sralph # ifndef BUG1
62516179Sralph #ifndef FLEXNAMES
62616179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
62716179Sralph #else
62816179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
62916179Sralph #endif
63016179Sralph # endif
63116179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
63216179Sralph 	else {
63316179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
63416179Sralph 			if( kk >= SYMTSZ ){
63516179Sralph 				cerror( "gummy structure" );
63616179Sralph 				return(1);
63716179Sralph 				}
63816179Sralph 			if( kk == i ) return( 1 );
63916179Sralph 			switch( stab[kk].stype ){
64016179Sralph 
64116179Sralph 			case STRTY:
64216179Sralph 			case UNIONTY:
64316179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
64416179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
64516179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
64616179Sralph 					werror(
64716179Sralph #ifndef FLEXNAMES
64816179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
64916179Sralph #else
65016179Sralph 					"illegal member use: perhaps %s.%s?",
65116179Sralph #endif
65216179Sralph 					stab[kk].sname, stab[i].sname );
65316179Sralph 					return(1);
65416179Sralph 					}
65516179Sralph 				}
65616179Sralph 			}
65716179Sralph 		}
65816179Sralph 	return( 0 );
65916179Sralph 	}
66016179Sralph 
66116179Sralph conval( p, o, q ) register NODE *p, *q; {
66216179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
66316179Sralph 	int i, u;
66416179Sralph 	CONSZ val;
66516179Sralph 
66616179Sralph 	val = q->tn.lval;
66716179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
66816179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
66916179Sralph 
67016179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
67116179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
67216179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
67316179Sralph 
67416179Sralph 	switch( o ){
67516179Sralph 
67616179Sralph 	case PLUS:
67716179Sralph 		p->tn.lval += val;
67816179Sralph 		if( p->tn.rval == NONAME ){
67916179Sralph 			p->tn.rval = q->tn.rval;
68016179Sralph 			p->in.type = q->in.type;
68116179Sralph 			}
68216179Sralph 		break;
68316179Sralph 	case MINUS:
68416179Sralph 		p->tn.lval -= val;
68516179Sralph 		break;
68616179Sralph 	case MUL:
68716179Sralph 		p->tn.lval *= val;
68816179Sralph 		break;
68916179Sralph 	case DIV:
69016179Sralph 		if( val == 0 ) uerror( "division by 0" );
691*17749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
69216179Sralph 		else p->tn.lval /= val;
69316179Sralph 		break;
69416179Sralph 	case MOD:
69516179Sralph 		if( val == 0 ) uerror( "division by 0" );
696*17749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
69716179Sralph 		else p->tn.lval %= val;
69816179Sralph 		break;
69916179Sralph 	case AND:
70016179Sralph 		p->tn.lval &= val;
70116179Sralph 		break;
70216179Sralph 	case OR:
70316179Sralph 		p->tn.lval |= val;
70416179Sralph 		break;
70516179Sralph 	case ER:
706*17749Sralph 		p->tn.lval ^= val;
70716179Sralph 		break;
70816179Sralph 	case LS:
70916179Sralph 		i = val;
71016179Sralph 		p->tn.lval = p->tn.lval << i;
71116179Sralph 		break;
71216179Sralph 	case RS:
71316179Sralph 		i = val;
714*17749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
715*17749Sralph 		else p->tn.lval = p->tn.lval >> i;
71616179Sralph 		break;
71716179Sralph 
71816179Sralph 	case UNARY MINUS:
71916179Sralph 		p->tn.lval = - p->tn.lval;
72016179Sralph 		break;
72116179Sralph 	case COMPL:
72216179Sralph 		p->tn.lval = ~p->tn.lval;
72316179Sralph 		break;
72416179Sralph 	case NOT:
72516179Sralph 		p->tn.lval = !p->tn.lval;
72616179Sralph 		break;
72716179Sralph 	case LT:
72816179Sralph 		p->tn.lval = p->tn.lval < val;
72916179Sralph 		break;
73016179Sralph 	case LE:
73116179Sralph 		p->tn.lval = p->tn.lval <= val;
73216179Sralph 		break;
73316179Sralph 	case GT:
73416179Sralph 		p->tn.lval = p->tn.lval > val;
73516179Sralph 		break;
73616179Sralph 	case GE:
73716179Sralph 		p->tn.lval = p->tn.lval >= val;
73816179Sralph 		break;
73916179Sralph 	case ULT:
74016179Sralph 		p->tn.lval = (p->tn.lval-val)<0;
74116179Sralph 		break;
74216179Sralph 	case ULE:
74316179Sralph 		p->tn.lval = (p->tn.lval-val)<=0;
74416179Sralph 		break;
74516179Sralph 	case UGE:
74616179Sralph 		p->tn.lval = (p->tn.lval-val)>=0;
74716179Sralph 		break;
74816179Sralph 	case UGT:
74916179Sralph 		p->tn.lval = (p->tn.lval-val)>0;
75016179Sralph 		break;
75116179Sralph 	case EQ:
75216179Sralph 		p->tn.lval = p->tn.lval == val;
75316179Sralph 		break;
75416179Sralph 	case NE:
75516179Sralph 		p->tn.lval = p->tn.lval != val;
75616179Sralph 		break;
75716179Sralph 	default:
75816179Sralph 		return(0);
75916179Sralph 		}
76016179Sralph 	return(1);
76116179Sralph 	}
76216179Sralph 
76316179Sralph chkpun(p) register NODE *p; {
76416179Sralph 
76516179Sralph 	/* checks p for the existance of a pun */
76616179Sralph 
76716179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
76816179Sralph 
76916179Sralph 	/* one case is when enumerations are used: this applies only to lint */
77016179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
77116179Sralph 	/* we check that this integer is in fact a constant zero... */
77216179Sralph 
77316179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
77416179Sralph 	/* this falls out, because the LHS is never 0 */
77516179Sralph 
77616179Sralph 	register NODE *q;
77716179Sralph 	register t1, t2;
77816179Sralph 	register d1, d2;
77916179Sralph 
78016179Sralph 	t1 = p->in.left->in.type;
78116179Sralph 	t2 = p->in.right->in.type;
78216179Sralph 
78316179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
78416179Sralph 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
78516179Sralph 			uerror( "illegal comparison of enums" );
78616179Sralph 			return;
78716179Sralph 			}
78816179Sralph 		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
78916179Sralph 		werror( "enumeration type clash, operator %s", opst[p->in.op] );
79016179Sralph 		return;
79116179Sralph 		}
79216179Sralph 
79316179Sralph 	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
79416179Sralph 	else q = p->in.left;
79516179Sralph 
79616179Sralph 	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
79716179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
79816179Sralph 			werror( "illegal combination of pointer and integer, op %s",
79916179Sralph 				opst[p->in.op] );
80016179Sralph 			}
80116179Sralph 		}
80216179Sralph 	else {
80316179Sralph 		d1 = p->in.left->fn.cdim;
80416179Sralph 		d2 = p->in.right->fn.cdim;
80516179Sralph 		for( ;; ){
80616179Sralph 			if( t1 == t2 ) {;
80716179Sralph 				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
80816179Sralph 					werror( "illegal structure pointer combination" );
80916179Sralph 					}
81016179Sralph 				return;
81116179Sralph 				}
81216179Sralph 			if( ISARY(t1) || ISPTR(t1) ){
81316179Sralph 				if( !ISARY(t2) && !ISPTR(t2) ) break;
81416179Sralph 				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
81516179Sralph 					werror( "illegal array size combination" );
81616179Sralph 					return;
81716179Sralph 					}
81816179Sralph 				if( ISARY(t1) ) ++d1;
81916179Sralph 				if( ISARY(t2) ) ++d2;
82016179Sralph 				}
82116179Sralph 			else break;
82216179Sralph 			t1 = DECREF(t1);
82316179Sralph 			t2 = DECREF(t2);
82416179Sralph 			}
82516179Sralph 		werror( "illegal pointer combination" );
82616179Sralph 		}
82716179Sralph 
82816179Sralph 	}
82916179Sralph 
83016179Sralph NODE *
83116179Sralph stref( p ) register NODE *p; {
83216179Sralph 
83316179Sralph 	TWORD t;
83416179Sralph 	int d, s, dsc, align;
83516179Sralph 	OFFSZ off;
83616179Sralph 	register struct symtab *q;
83716179Sralph 
83816179Sralph 	/* make p->x */
83916179Sralph 	/* this is also used to reference automatic variables */
84016179Sralph 
84116179Sralph 	q = &stab[p->in.right->tn.rval];
84216179Sralph 	p->in.right->in.op = FREE;
84316179Sralph 	p->in.op = FREE;
84416179Sralph 	p = pconvert( p->in.left );
84516179Sralph 
84616179Sralph 	/* make p look like ptr to x */
84716179Sralph 
84816179Sralph 	if( !ISPTR(p->in.type)){
84916179Sralph 		p->in.type = PTR+UNIONTY;
85016179Sralph 		}
85116179Sralph 
85216179Sralph 	t = INCREF( q->stype );
85316179Sralph 	d = q->dimoff;
85416179Sralph 	s = q->sizoff;
85516179Sralph 
85616179Sralph 	p = makety( p, t, d, s );
85716179Sralph 
85816179Sralph 	/* compute the offset to be added */
85916179Sralph 
86016179Sralph 	off = q->offset;
86116179Sralph 	dsc = q->sclass;
86216179Sralph 
86316179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
86416179Sralph 		align = ALINT;
86516179Sralph 		s = INT;
86616179Sralph 		off = (off/align)*align;
86716179Sralph 		}
86816179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
86916179Sralph 
87016179Sralph 	p = buildtree( UNARY MUL, p, NIL );
87116179Sralph 
87216179Sralph 	/* if field, build field info */
87316179Sralph 
87416179Sralph 	if( dsc & FIELD ){
87516179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
87616179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
87716179Sralph 		}
87816179Sralph 
87916179Sralph 	return( clocal(p) );
88016179Sralph 	}
88116179Sralph 
88216179Sralph notlval(p) register NODE *p; {
88316179Sralph 
88416179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
88516179Sralph 
88616179Sralph 	again:
88716179Sralph 
88816179Sralph 	switch( p->in.op ){
88916179Sralph 
89016179Sralph 	case FLD:
89116179Sralph 		p = p->in.left;
89216179Sralph 		goto again;
89316179Sralph 
89416179Sralph 	case UNARY MUL:
89516179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
89616179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
89716179Sralph 		/* and the f().a bug, given that f returns a structure */
89816179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
89916179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
90016179Sralph 	case NAME:
90116179Sralph 	case OREG:
90216179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
90316179Sralph 	case REG:
90416179Sralph 		return(0);
90516179Sralph 
90616179Sralph 	default:
90716179Sralph 		return(1);
90816179Sralph 
90916179Sralph 		}
91016179Sralph 
91116179Sralph 	}
91216179Sralph 
91316179Sralph NODE *
91416179Sralph bcon( i ){ /* make a constant node with value i */
91516179Sralph 	register NODE *p;
91616179Sralph 
91716179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
91816179Sralph 	p->tn.lval = i;
91916179Sralph 	p->tn.rval = NONAME;
92016179Sralph 	return( clocal(p) );
92116179Sralph 	}
92216179Sralph 
92316179Sralph NODE *
92416179Sralph bpsize(p) register NODE *p; {
92516179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
92616179Sralph 	}
92716179Sralph 
92816179Sralph OFFSZ
92916179Sralph psize( p ) NODE *p; {
93016179Sralph 	/* p is a node of type pointer; psize returns the
93116179Sralph 	   size of the thing pointed to */
93216179Sralph 
93316179Sralph 	if( !ISPTR(p->in.type) ){
93416179Sralph 		uerror( "pointer required");
93516179Sralph 		return( SZINT );
93616179Sralph 		}
93716179Sralph 	/* note: no pointers to fields */
93816179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
93916179Sralph 	}
94016179Sralph 
94116179Sralph NODE *
94216179Sralph convert( p, f )  register NODE *p; {
94316179Sralph 	/*  convert an operand of p
94416179Sralph 	    f is either CVTL or CVTR
94516179Sralph 	    operand has type int, and is converted by the size of the other side
94616179Sralph 	    */
94716179Sralph 
94816179Sralph 	register NODE *q, *r;
94916179Sralph 
95016179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
95116179Sralph 
95216179Sralph 	r = block( PMCONV,
95316179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
95416179Sralph 	r = clocal(r);
95516179Sralph 	if( f == CVTL )
95616179Sralph 		p->in.left = r;
95716179Sralph 	else
95816179Sralph 		p->in.right = r;
95916179Sralph 	return(p);
96016179Sralph 
96116179Sralph 	}
96216179Sralph 
96316179Sralph econvert( p ) register NODE *p; {
96416179Sralph 
96516179Sralph 	/* change enums to ints, or appropriate types */
96616179Sralph 
96716179Sralph 	register TWORD ty;
96816179Sralph 
96916179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
97016179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
97116179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
97216179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
97316179Sralph 		else ty = LONG;
97416179Sralph 		ty = ctype( ty );
97516179Sralph 		p->fn.csiz = ty;
97616179Sralph 		MODTYPE(p->in.type,ty);
97716179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
97816179Sralph 		}
97916179Sralph 	}
98016179Sralph 
98116179Sralph NODE *
98216179Sralph pconvert( p ) register NODE *p; {
98316179Sralph 
98416179Sralph 	/* if p should be changed into a pointer, do so */
98516179Sralph 
98616179Sralph 	if( ISARY( p->in.type) ){
98716179Sralph 		p->in.type = DECREF( p->in.type );
98816179Sralph 		++p->fn.cdim;
98916179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
99016179Sralph 		}
99116179Sralph 	if( ISFTN( p->in.type) )
99216179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
99316179Sralph 
99416179Sralph 	return( p );
99516179Sralph 	}
99616179Sralph 
99716179Sralph NODE *
99816179Sralph oconvert(p) register NODE *p; {
99916179Sralph 	/* convert the result itself: used for pointer and unsigned */
100016179Sralph 
100116179Sralph 	switch(p->in.op) {
100216179Sralph 
100316179Sralph 	case LE:
100416179Sralph 	case LT:
100516179Sralph 	case GE:
100616179Sralph 	case GT:
100716179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
100816179Sralph 	case EQ:
100916179Sralph 	case NE:
101016179Sralph 		return( p );
101116179Sralph 
101216179Sralph 	case MINUS:
101316179Sralph 		return(  clocal( block( PVCONV,
101416179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
101516179Sralph 		}
101616179Sralph 
101716179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
101816179Sralph 
101916179Sralph 	return(p);
102016179Sralph 	}
102116179Sralph 
102216179Sralph NODE *
102316179Sralph ptmatch(p)  register NODE *p; {
102416179Sralph 
102516179Sralph 	/* makes the operands of p agree; they are
102616179Sralph 	   either pointers or integers, by this time */
102716179Sralph 	/* with MINUS, the sizes must be the same */
102816179Sralph 	/* with COLON, the types must be the same */
102916179Sralph 
103016179Sralph 	TWORD t1, t2, t;
103116179Sralph 	int o, d2, d, s2, s;
103216179Sralph 
103316179Sralph 	o = p->in.op;
103416179Sralph 	t = t1 = p->in.left->in.type;
103516179Sralph 	t2 = p->in.right->in.type;
103616179Sralph 	d = p->in.left->fn.cdim;
103716179Sralph 	d2 = p->in.right->fn.cdim;
103816179Sralph 	s = p->in.left->fn.csiz;
103916179Sralph 	s2 = p->in.right->fn.csiz;
104016179Sralph 
104116179Sralph 	switch( o ){
104216179Sralph 
104316179Sralph 	case ASSIGN:
104416179Sralph 	case RETURN:
104516179Sralph 	case CAST:
104616179Sralph 		{  break; }
104716179Sralph 
104816179Sralph 	case MINUS:
104916179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
105016179Sralph 			uerror( "illegal pointer subtraction");
105116179Sralph 			}
105216179Sralph 		   break;
105316179Sralph 		   }
105416179Sralph 	case COLON:
105516179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
105616179Sralph 		   break;
105716179Sralph 		   }
105816179Sralph 	default:  /* must work harder: relationals or comparisons */
105916179Sralph 
106016179Sralph 		if( !ISPTR(t1) ){
106116179Sralph 			t = t2;
106216179Sralph 			d = d2;
106316179Sralph 			s = s2;
106416179Sralph 			break;
106516179Sralph 			}
106616179Sralph 		if( !ISPTR(t2) ){
106716179Sralph 			break;
106816179Sralph 			}
106916179Sralph 
107016179Sralph 		/* both are pointers */
107116179Sralph 		if( talign(t2,s2) < talign(t,s) ){
107216179Sralph 			t = t2;
107316179Sralph 			s = s2;
107416179Sralph 			}
107516179Sralph 		break;
107616179Sralph 		}
107716179Sralph 
107816179Sralph 	p->in.left = makety( p->in.left, t, d, s );
107916179Sralph 	p->in.right = makety( p->in.right, t, d, s );
108016179Sralph 	if( o!=MINUS && !logop(o) ){
108116179Sralph 
108216179Sralph 		p->in.type = t;
108316179Sralph 		p->fn.cdim = d;
108416179Sralph 		p->fn.csiz = s;
108516179Sralph 		}
108616179Sralph 
108716179Sralph 	return(clocal(p));
108816179Sralph 	}
108916179Sralph 
109016179Sralph int tdebug = 0;
109116179Sralph 
109216179Sralph NODE *
109316179Sralph tymatch(p)  register NODE *p; {
109416179Sralph 
109516179Sralph 	/* satisfy the types of various arithmetic binary ops */
109616179Sralph 
109716179Sralph 	/* rules are:
109816179Sralph 		if assignment, op, type of LHS
109916179Sralph 		if any float or doubles, make double
110016179Sralph 		if any longs, make long
110116179Sralph 		otherwise, make int
110216179Sralph 		if either operand is unsigned, the result is...
110316179Sralph 	*/
110416179Sralph 
110516179Sralph 	register TWORD t1, t2, t, tu;
110616179Sralph 	register o, u;
110716179Sralph 
110816179Sralph 	o = p->in.op;
110916179Sralph 
111016179Sralph 	t1 = p->in.left->in.type;
111116179Sralph 	t2 = p->in.right->in.type;
111216179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
111316179Sralph 		uerror("void type illegal in expression");
111416179Sralph 
111516179Sralph 	u = 0;
111616179Sralph 	if( ISUNSIGNED(t1) ){
111716179Sralph 		u = 1;
111816179Sralph 		t1 = DEUNSIGN(t1);
111916179Sralph 		}
112016179Sralph 	if( ISUNSIGNED(t2) ){
112116179Sralph 		u = 1;
112216179Sralph 		t2 = DEUNSIGN(t2);
112316179Sralph 		}
112416179Sralph 
112516179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
112616179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
112716179Sralph 
1128*17749Sralph #ifdef SPRECC
1129*17749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
1130*17749Sralph 		t = DOUBLE;
1131*17749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
1132*17749Sralph 		t = FLOAT;
1133*17749Sralph #else
1134*17749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
1135*17749Sralph 		t = DOUBLE;
1136*17749Sralph #endif
113716179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
113816179Sralph 	else t = INT;
113916179Sralph 
114016179Sralph 	if( asgop(o) ){
114116179Sralph 		tu = p->in.left->in.type;
114216179Sralph 		t = t1;
114316179Sralph 		}
114416179Sralph 	else {
114516179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
114616179Sralph 		}
114716179Sralph 
114816179Sralph 	/* because expressions have values that are at least as wide
114916179Sralph 	   as INT or UNSIGNED, the only conversions needed
115016179Sralph 	   are those involving FLOAT/DOUBLE, and those
115116179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
115216179Sralph 
115316179Sralph 	if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
115416179Sralph 
115516179Sralph 	if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
115616179Sralph 
115716179Sralph 	if( asgop(o) ){
115816179Sralph 		p->in.type = p->in.left->in.type;
115916179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
116016179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
116116179Sralph 		}
116216179Sralph 	else if( !logop(o) ){
116316179Sralph 		p->in.type = tu;
116416179Sralph 		p->fn.cdim = 0;
116516179Sralph 		p->fn.csiz = t;
116616179Sralph 		}
116716179Sralph 
116816179Sralph # ifndef BUG1
116916179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
117016179Sralph # endif
117116179Sralph 
117216179Sralph 	return(p);
117316179Sralph 	}
117416179Sralph 
117516179Sralph NODE *
117616179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
117716179Sralph 	/* make p into type t by inserting a conversion */
117816179Sralph 
117916179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
118016179Sralph 	if( t == p->in.type ){
118116179Sralph 		p->fn.cdim = d;
118216179Sralph 		p->fn.csiz = s;
118316179Sralph 		return( p );
118416179Sralph 		}
118516179Sralph 
118616179Sralph 	if( t & TMASK ){
118716179Sralph 		/* non-simple type */
118817228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
118916179Sralph 		}
119016179Sralph 
119116179Sralph 	if( p->in.op == ICON ){
1192*17749Sralph 		if (t == DOUBLE) {
1193*17749Sralph 			p->in.op = DCON;
1194*17749Sralph 			if (ISUNSIGNED(p->in.type))
1195*17749Sralph 				p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
1196*17749Sralph 			else
1197*17749Sralph 				p->dpn.dval = p->tn.lval;
1198*17749Sralph 			p->in.type = p->fn.csiz = t;
1199*17749Sralph 			return (clocal(p));
1200*17749Sralph 		}
1201*17749Sralph 		if (t == FLOAT) {
120216179Sralph 			p->in.op = FCON;
120316179Sralph 			if( ISUNSIGNED(p->in.type) ){
1204*17749Sralph 				p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval;
120516179Sralph 				}
120616179Sralph 			else {
1207*17749Sralph 				p->fpn.fval = p->tn.lval;
120816179Sralph 				}
120916179Sralph 
121016179Sralph 			p->in.type = p->fn.csiz = t;
121116179Sralph 			return( clocal(p) );
121216179Sralph 			}
121316179Sralph 		}
1214*17749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
1215*17749Sralph 		double db;
121616179Sralph 
1217*17749Sralph 		p->in.op = DCON;
1218*17749Sralph 		db = p->fpn.fval;
1219*17749Sralph 		p->dpn.dval = db;
1220*17749Sralph 		p->in.type = p->fn.csiz = t;
1221*17749Sralph 		return (clocal(p));
1222*17749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
1223*17749Sralph 		float fl;
1224*17749Sralph 
1225*17749Sralph 		p->in.op = FCON;
1226*17749Sralph 		fl = p->dpn.dval;
1227*17749Sralph #ifdef notdef
1228*17749Sralph 		if (fl != p->dpn.dval)
1229*17749Sralph 			werror("float conversion loses precision");
1230*17749Sralph #endif
1231*17749Sralph 		p->fpn.fval = fl;
1232*17749Sralph 		p->in.type = p->fn.csiz = t;
1233*17749Sralph 		return (clocal(p));
1234*17749Sralph 	}
1235*17749Sralph 
123617049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
123716179Sralph 
123816179Sralph 	}
123916179Sralph 
124016179Sralph NODE *
124116179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
124216179Sralph 
124316179Sralph 	register NODE *p;
124416179Sralph 
124516179Sralph 	p = talloc();
124616179Sralph 	p->in.op = o;
124716179Sralph 	p->in.left = l;
124816179Sralph 	p->in.right = r;
124916179Sralph 	p->in.type = t;
125016179Sralph 	p->fn.cdim = d;
125116179Sralph 	p->fn.csiz = s;
125216179Sralph 	return(p);
125316179Sralph 	}
125416179Sralph 
125516179Sralph icons(p) register NODE *p; {
125616179Sralph 	/* if p is an integer constant, return its value */
125716179Sralph 	int val;
125816179Sralph 
125916179Sralph 	if( p->in.op != ICON ){
126016179Sralph 		uerror( "constant expected");
126116179Sralph 		val = 1;
126216179Sralph 		}
126316179Sralph 	else {
126416179Sralph 		val = p->tn.lval;
126516179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
126616179Sralph 		}
126716179Sralph 	tfree( p );
126816179Sralph 	return(val);
126916179Sralph 	}
127016179Sralph 
127116179Sralph /* 	the intent of this table is to examine the
127216179Sralph 	operators, and to check them for
127316179Sralph 	correctness.
127416179Sralph 
127516179Sralph 	The table is searched for the op and the
127616179Sralph 	modified type (where this is one of the
127716179Sralph 	types INT (includes char and short), LONG,
127816179Sralph 	DOUBLE (includes FLOAT), and POINTER
127916179Sralph 
128016179Sralph 	The default action is to make the node type integer
128116179Sralph 
128216179Sralph 	The actions taken include:
128316179Sralph 		PUN	  check for puns
128416179Sralph 		CVTL	  convert the left operand
128516179Sralph 		CVTR	  convert the right operand
128616179Sralph 		TYPL	  the type is determined by the left operand
128716179Sralph 		TYPR	  the type is determined by the right operand
128816179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
128916179Sralph 		PTMATCH	  like TYMATCH, but for pointers
129016179Sralph 		LVAL	  left operand must be lval
129116179Sralph 		CVTO	  convert the op
129216179Sralph 		NCVT	  do not convert the operands
129316179Sralph 		OTHER	  handled by code
129416179Sralph 		NCVTR	  convert the left operand, not the right...
129516179Sralph 
129616179Sralph 	*/
129716179Sralph 
129816179Sralph # define MINT 01  /* integer */
129916179Sralph # define MDBI 02   /* integer or double */
130016179Sralph # define MSTR 04  /* structure */
130116179Sralph # define MPTR 010  /* pointer */
130216179Sralph # define MPTI 020  /* pointer or integer */
130316179Sralph # define MENU 040 /* enumeration variable or member */
130416179Sralph 
130516179Sralph opact( p )  NODE *p; {
130616179Sralph 
130716179Sralph 	register mt12, mt1, mt2, o;
130816179Sralph 
130916179Sralph 	mt12 = 0;
131016179Sralph 
131116179Sralph 	switch( optype(o=p->in.op) ){
131216179Sralph 
131316179Sralph 	case BITYPE:
131416179Sralph 		mt12=mt2 = moditype( p->in.right->in.type );
131516179Sralph 	case UTYPE:
131616179Sralph 		mt12 &= (mt1 = moditype( p->in.left->in.type ));
131716179Sralph 
131816179Sralph 		}
131916179Sralph 
132016179Sralph 	switch( o ){
132116179Sralph 
132216179Sralph 	case NAME :
132316179Sralph 	case STRING :
132416179Sralph 	case ICON :
132516179Sralph 	case FCON :
1326*17749Sralph 	case DCON :
132716179Sralph 	case CALL :
132816179Sralph 	case UNARY CALL:
132916179Sralph 	case UNARY MUL:
133016179Sralph 		{  return( OTHER ); }
133116179Sralph 	case UNARY MINUS:
133216179Sralph 		if( mt1 & MDBI ) return( TYPL );
133316179Sralph 		break;
133416179Sralph 
133516179Sralph 	case COMPL:
133616179Sralph 		if( mt1 & MINT ) return( TYPL );
133716179Sralph 		break;
133816179Sralph 
133916179Sralph 	case UNARY AND:
134016179Sralph 		{  return( NCVT+OTHER ); }
134116179Sralph 	case INIT:
134216179Sralph 	case CM:
134316180Sralph 		return( 0 );
134416180Sralph 
134516179Sralph 	case NOT:
134616179Sralph 	case CBRANCH:
134716180Sralph 		if( mt1 & MSTR ) break;
134816180Sralph 		return( 0 );
134916180Sralph 
135016179Sralph 	case ANDAND:
135116179Sralph 	case OROR:
135216180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
135316179Sralph 		return( 0 );
135416179Sralph 
135516179Sralph 	case MUL:
135616179Sralph 	case DIV:
135716179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
135816179Sralph 		break;
135916179Sralph 
136016179Sralph 	case MOD:
136116179Sralph 	case AND:
136216179Sralph 	case OR:
136316179Sralph 	case ER:
136416179Sralph 		if( mt12 & MINT ) return( TYMATCH );
136516179Sralph 		break;
136616179Sralph 
136716179Sralph 	case LS:
136816179Sralph 	case RS:
136916179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
137016179Sralph 		break;
137116179Sralph 
137216179Sralph 	case EQ:
137316179Sralph 	case NE:
137416179Sralph 	case LT:
137516179Sralph 	case LE:
137616179Sralph 	case GT:
137716179Sralph 	case GE:
137816179Sralph 		if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
137916179Sralph 		if( mt12 & MDBI ) return( TYMATCH+CVTO );
138016179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
138116179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
138216179Sralph 		else break;
138316179Sralph 
138416179Sralph 	case QUEST:
138516179Sralph 	case COMOP:
138616179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
138716179Sralph 		return( TYPR );
138816179Sralph 
138916179Sralph 	case STREF:
139016179Sralph 		return( NCVTR+OTHER );
139116179Sralph 
139216179Sralph 	case FORCE:
139316179Sralph 		return( TYPL );
139416179Sralph 
139516179Sralph 	case COLON:
139616179Sralph 		if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
139716179Sralph 		else if( mt12 & MDBI ) return( TYMATCH );
139816179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
139916179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
140016179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
140116179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
140216179Sralph 		break;
140316179Sralph 
140416179Sralph 	case ASSIGN:
140516179Sralph 	case RETURN:
140616179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
140716179Sralph 	case CAST:
140816179Sralph 		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
140916179Sralph 		if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
141016179Sralph 		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
141116179Sralph 		else if( mt12 == 0 ) break;
141216179Sralph 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
141316179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
141416179Sralph 		break;
141516179Sralph 
141616179Sralph 	case ASG LS:
141716179Sralph 	case ASG RS:
141816179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
141916179Sralph 		break;
142016179Sralph 
142116179Sralph 	case ASG MUL:
142216179Sralph 	case ASG DIV:
142316179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
142416179Sralph 		break;
142516179Sralph 
142616179Sralph 	case ASG MOD:
142716179Sralph 	case ASG AND:
142816179Sralph 	case ASG OR:
142916179Sralph 	case ASG ER:
143016179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
143116179Sralph 		break;
143216179Sralph 
143316179Sralph 	case ASG PLUS:
143416179Sralph 	case ASG MINUS:
143516179Sralph 	case INCR:
143616179Sralph 	case DECR:
143716179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
143816179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
143916179Sralph 		break;
144016179Sralph 
144116179Sralph 	case MINUS:
144216179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
144316179Sralph 		if( mt2 & MPTR ) break;
144416179Sralph 	case PLUS:
144516179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
144616179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
144716179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
144816179Sralph 
144916179Sralph 		}
145016179Sralph 	uerror( "operands of %s have incompatible types", opst[o] );
145116179Sralph 	return( NCVT );
145216179Sralph 	}
145316179Sralph 
145416179Sralph moditype( ty ) TWORD ty; {
145516179Sralph 
145616179Sralph 	switch( ty ){
145716179Sralph 
145816179Sralph 	case TVOID:
145917206Sralph 		return( MPTR );
146016179Sralph 	case UNDEF:
146116179Sralph 		return(0); /* type is void */
146216179Sralph 	case ENUMTY:
146316179Sralph 	case MOETY:
146416179Sralph 		return( MENU );
146516179Sralph 
146616179Sralph 	case STRTY:
146716179Sralph 	case UNIONTY:
146816179Sralph 		return( MSTR );
146916179Sralph 
147016179Sralph 	case CHAR:
147116179Sralph 	case SHORT:
147216179Sralph 	case UCHAR:
147316179Sralph 	case USHORT:
147416179Sralph 		return( MINT|MPTI|MDBI );
147516179Sralph 	case UNSIGNED:
147616179Sralph 	case ULONG:
147716179Sralph 	case INT:
147816179Sralph 	case LONG:
147916179Sralph 		return( MINT|MDBI|MPTI );
148016179Sralph 	case FLOAT:
148116179Sralph 	case DOUBLE:
148216179Sralph 		return( MDBI );
148316179Sralph 	default:
148416179Sralph 		return( MPTR|MPTI );
148516179Sralph 
148616179Sralph 		}
148716179Sralph 	}
148816179Sralph 
148916179Sralph NODE *
149016179Sralph doszof( p )  register NODE *p; {
149116179Sralph 	/* do sizeof p */
149216179Sralph 	int i;
149316179Sralph 
149416179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
149516179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
149616179Sralph 
149716179Sralph 	tfree(p);
149816179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
149916179Sralph 	return( bcon( i ) );
150016179Sralph 	}
150116179Sralph 
150216179Sralph # ifndef BUG2
150316179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
150416179Sralph 	register ty;
150516179Sralph 
150616179Sralph 	*a = *b = down+1;
150716179Sralph 	while( down > 1 ){
150816179Sralph 		printf( "\t" );
150916179Sralph 		down -= 2;
151016179Sralph 		}
151116179Sralph 	if( down ) printf( "    " );
151216179Sralph 
151316179Sralph 	ty = optype( p->in.op );
151416179Sralph 
151516179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
151616179Sralph 	if( ty == LTYPE ){
151716179Sralph 		printf( CONFMT, p->tn.lval );
151816179Sralph 		printf( ", %d, ", p->tn.rval );
151916179Sralph 		}
152016179Sralph 	tprint( p->in.type );
152116179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
152216179Sralph 	}
152316179Sralph # endif
152416179Sralph 
152516179Sralph prtdcon( p ) register NODE *p; {
1526*17749Sralph 	int o = p->in.op, i;
152716179Sralph 
1528*17749Sralph 	if( o == DCON || o == FCON ){
152916179Sralph 		locctr( DATA );
1530*17749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
153116179Sralph 		deflab( i = getlab() );
1532*17749Sralph 		if( o == FCON )
1533*17749Sralph 			fincode( p->fpn.fval, SZFLOAT );
1534*17749Sralph 		else
1535*17749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
153616179Sralph 		p->tn.lval = 0;
153716179Sralph 		p->tn.rval = -i;
1538*17749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
153916179Sralph 		p->in.op = NAME;
154016179Sralph 		}
154116179Sralph 	}
154216179Sralph 
154316179Sralph 
154416179Sralph int edebug = 0;
154516179Sralph ecomp( p ) register NODE *p; {
154616179Sralph # ifndef BUG2
154716179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
154816179Sralph # endif
154916179Sralph 	if( !reached ){
155016179Sralph 		werror( "statement not reached" );
155116179Sralph 		reached = 1;
155216179Sralph 		}
155316179Sralph 	p = optim(p);
155416179Sralph 	walkf( p, prtdcon );
155516179Sralph 	locctr( PROG );
155616179Sralph 	ecode( p );
155716179Sralph 	tfree(p);
155816179Sralph 	}
155916179Sralph 
156016179Sralph # ifdef STDPRTREE
156116179Sralph # ifndef ONEPASS
156216179Sralph 
156316179Sralph prtree(p) register NODE *p; {
156416179Sralph 
156516179Sralph 	register struct symtab *q;
156616179Sralph 	register ty;
156716179Sralph 
156816179Sralph # ifdef MYPRTREE
156916179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
157016179Sralph #endif
157116179Sralph 
157216179Sralph 	ty = optype(p->in.op);
157316179Sralph 
157416179Sralph 	printf( "%d\t", p->in.op );
157516179Sralph 
157616179Sralph 	if( ty == LTYPE ) {
157716179Sralph 		printf( CONFMT, p->tn.lval );
157816179Sralph 		printf( "\t" );
157916179Sralph 		}
158016179Sralph 	if( ty != BITYPE ) {
158116179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
158216179Sralph 		else printf( "%d\t", p->tn.rval );
158316179Sralph 		}
158416179Sralph 
158516179Sralph 	printf( "%o\t", p->in.type );
158616179Sralph 
158716179Sralph 	/* handle special cases */
158816179Sralph 
158916179Sralph 	switch( p->in.op ){
159016179Sralph 
159116179Sralph 	case NAME:
159216179Sralph 	case ICON:
159316179Sralph 		/* print external name */
159416179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
159516179Sralph 		else if( p->tn.rval >= 0 ){
159616179Sralph 			q = &stab[p->tn.rval];
159716179Sralph 			printf(  "%s\n", exname(q->sname) );
159816179Sralph 			}
159916179Sralph 		else { /* label */
160016179Sralph 			printf( LABFMT, -p->tn.rval );
160116179Sralph 			}
160216179Sralph 		break;
160316179Sralph 
160416179Sralph 	case STARG:
160516179Sralph 	case STASG:
160616179Sralph 	case STCALL:
160716179Sralph 	case UNARY STCALL:
160816179Sralph 		/* print out size */
160916179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
161016179Sralph 
161116179Sralph 		/* note: p->in.left not a field... */
161216179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
161316179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
161416179Sralph 		break;
161516179Sralph 
161616179Sralph 	default:
161716179Sralph 		printf(  "\n" );
161816179Sralph 		}
161916179Sralph 
162016179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
162116179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
162216179Sralph 
162316179Sralph 	}
162416179Sralph 
162516179Sralph # else
162616179Sralph 
162716179Sralph p2tree(p) register NODE *p; {
162816179Sralph 	register ty;
162916179Sralph 
163016179Sralph # ifdef MYP2TREE
163116179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
163216179Sralph # endif
163316179Sralph 
163416179Sralph 	ty = optype(p->in.op);
163516179Sralph 
163616179Sralph 	switch( p->in.op ){
163716179Sralph 
163816179Sralph 	case NAME:
163916179Sralph 	case ICON:
164016179Sralph #ifndef FLEXNAMES
164116179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
164216179Sralph #else
164316179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
164416179Sralph #endif
164516179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
164616179Sralph 			register char *cp;
164716179Sralph 			register i;
164816179Sralph 			cp = exname( stab[p->tn.rval].sname );
164916179Sralph #ifndef FLEXNAMES
165016179Sralph 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
165116179Sralph #else
165216179Sralph 			p->in.name = tstr(cp);
165316179Sralph #endif
165416179Sralph 			}
165516179Sralph #ifndef FLEXNAMES
165616179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
165716179Sralph #else
165816179Sralph 		else {
165916179Sralph 			char temp[32];
166016179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
166116179Sralph 			p->in.name = tstr(temp);
166216179Sralph 		}
166316179Sralph #endif
166416179Sralph 		break;
166516179Sralph 
166616179Sralph 	case STARG:
166716179Sralph 	case STASG:
166816179Sralph 	case STCALL:
166916179Sralph 	case UNARY STCALL:
167016179Sralph 		/* set up size parameters */
167116179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
167216179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
167316179Sralph 		break;
167416179Sralph 
167516179Sralph 	case REG:
167616179Sralph 		rbusy( p->tn.rval, p->in.type );
167716179Sralph 	default:
167816179Sralph #ifndef FLEXNAMES
167916179Sralph 		p->in.name[0] = '\0';
168016179Sralph #else
168116179Sralph 		p->in.name = "";
168216179Sralph #endif
168316179Sralph 		}
168416179Sralph 
168516179Sralph 	p->in.rall = NOPREF;
168616179Sralph 
168716179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
168816179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
168916179Sralph 	}
169016179Sralph 
169116179Sralph # endif
169216179Sralph # endif
1693