xref: /original-bsd/old/pcc/mip/trees.c (revision 10cfdb8a)
19411d0f5Sralph #ifndef lint
2*10cfdb8aSbostic static char *sccsid ="@(#)trees.c	4.37 (Berkeley) 06/18/90";
39411d0f5Sralph #endif
49411d0f5Sralph 
5c975fa10Sralph # include "pass1.h"
685b1171fSralph 
7d0dde492Smckusick # include <setjmp.h>
8d0dde492Smckusick 
99411d0f5Sralph int bdebug = 0;
109411d0f5Sralph int adebug = 0;
119411d0f5Sralph extern ddebug;
129411d0f5Sralph extern eprint();
139411d0f5Sralph 
1485b1171fSralph 	    /* corrections when in violation of lint */
1585b1171fSralph 
1685b1171fSralph /*	some special actions, used in finding the type of nodes */
1785b1171fSralph # define NCVT 01
1885b1171fSralph # define PUN 02
1985b1171fSralph # define TYPL 04
2085b1171fSralph # define TYPR 010
2185b1171fSralph # define TYMATCH 040
2285b1171fSralph # define LVAL 0100
2385b1171fSralph # define CVTO 0200
2485b1171fSralph # define CVTL 0400
2585b1171fSralph # define CVTR 01000
2685b1171fSralph # define PTMATCH 02000
2785b1171fSralph # define OTHER 04000
2885b1171fSralph # define NCVTR 010000
2985b1171fSralph 
309411d0f5Sralph #ifndef BUG1
printact(t,acts)319411d0f5Sralph printact(t, acts)
329411d0f5Sralph 	NODE *t;
339411d0f5Sralph 	int acts;
349411d0f5Sralph {
359411d0f5Sralph 	static struct actions {
369411d0f5Sralph 		int	a_bit;
379411d0f5Sralph 		char	*a_name;
389411d0f5Sralph 	} actions[] = {
399411d0f5Sralph 		{ PUN,		"PUN" },
409411d0f5Sralph 		{ CVTL,		"CVTL" },
419411d0f5Sralph 		{ CVTR,		"CVTR" },
429411d0f5Sralph 		{ TYPL,		"TYPL" },
439411d0f5Sralph 		{ TYPR,		"TYPR" },
449411d0f5Sralph 		{ TYMATCH,	"TYMATCH" },
459411d0f5Sralph 		{ PTMATCH,	"PTMATCH" },
469411d0f5Sralph 		{ LVAL,		"LVAL" },
479411d0f5Sralph 		{ CVTO,		"CVTO" },
489411d0f5Sralph 		{ NCVT,		"NCVT" },
499411d0f5Sralph 		{ OTHER,	"OTHER" },
509411d0f5Sralph 		{ NCVTR,	"NCVTR" },
519411d0f5Sralph 		{ 0 }
529411d0f5Sralph 	};
539411d0f5Sralph 	register struct actions *p;
549411d0f5Sralph 	char *sep = " ";
559411d0f5Sralph 
569411d0f5Sralph 	printf("actions");
579411d0f5Sralph 	for (p = actions; p->a_name; p++)
589411d0f5Sralph 		if (p->a_bit & acts) {
599411d0f5Sralph 			printf("%s%s", sep, p->a_name);
609411d0f5Sralph 			sep = "|";
619411d0f5Sralph 		}
629411d0f5Sralph 	if (!bdebug) {
639411d0f5Sralph 		printf(" for:\n");
649411d0f5Sralph 		fwalk(t, eprint, 0);
659411d0f5Sralph 	} else
669411d0f5Sralph 		putchar('\n');
679411d0f5Sralph }
689411d0f5Sralph #endif
699411d0f5Sralph 
7085b1171fSralph /* node conventions:
7185b1171fSralph 
7285b1171fSralph 	NAME:	rval>0 is stab index for external
7385b1171fSralph 		rval<0 is -inlabel number
7485b1171fSralph 		lval is offset in bits
7585b1171fSralph 	ICON:	lval has the value
7685b1171fSralph 		rval has the STAB index, or - label number,
7785b1171fSralph 			if a name whose address is in the constant
7885b1171fSralph 		rval = NONAME means no name
7985b1171fSralph 	REG:	rval is reg. identification cookie
8085b1171fSralph 
8185b1171fSralph 	*/
8285b1171fSralph 
8385b1171fSralph NODE *
buildtree(o,l,r)8485b1171fSralph buildtree( o, l, r ) register NODE *l, *r; {
8585b1171fSralph 	register NODE *p, *q;
8685b1171fSralph 	register actions;
8785b1171fSralph 	register opty;
8885b1171fSralph 	register struct symtab *sp;
8985b1171fSralph 	register NODE *lr, *ll;
909411d0f5Sralph 	NODE *fixargs();
9185b1171fSralph 	int i;
9285b1171fSralph 
9385b1171fSralph # ifndef BUG1
9485b1171fSralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9585b1171fSralph # endif
9685b1171fSralph 	opty = optype(o);
9785b1171fSralph 
9885b1171fSralph 	/* check for constants */
9985b1171fSralph 
10085b1171fSralph 	if( opty == UTYPE && l->in.op == ICON ){
10185b1171fSralph 
10285b1171fSralph 		switch( o ){
10385b1171fSralph 
10485b1171fSralph 		case NOT:
10585b1171fSralph 			if( hflag ) werror( "constant argument to NOT" );
10685b1171fSralph 		case UNARY MINUS:
10785b1171fSralph 		case COMPL:
10885b1171fSralph 			if( conval( l, o, l ) ) return(l);
10985b1171fSralph 			break;
11085b1171fSralph 
11185b1171fSralph 			}
11285b1171fSralph 		}
11385b1171fSralph 
114007a19b4Sdonn 	else if( opty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
1159411d0f5Sralph 
116007a19b4Sdonn 		switch( o ){
117007a19b4Sdonn 
118007a19b4Sdonn 		case NOT:
119007a19b4Sdonn 			if( hflag ) werror( "constant argument to NOT" );
120007a19b4Sdonn 			if( l->in.op == FCON )
121007a19b4Sdonn 				l->tn.lval = l->fpn.fval == 0.0;
122007a19b4Sdonn 			else
123007a19b4Sdonn 				l->tn.lval = l->dpn.dval == 0.0;
124007a19b4Sdonn 			l->tn.rval = NONAME;
125007a19b4Sdonn 			l->in.op = ICON;
126007a19b4Sdonn 			l->fn.csiz = l->in.type = INT;
127007a19b4Sdonn 			l->fn.cdim = 0;
128007a19b4Sdonn 			return(l);
129007a19b4Sdonn 		case UNARY MINUS:
130007a19b4Sdonn 			if( l->in.op == FCON )
131007a19b4Sdonn 				l->fpn.fval = -l->fpn.fval;
132007a19b4Sdonn 			else
1339411d0f5Sralph 				l->dpn.dval = -l->dpn.dval;
13485b1171fSralph 			return(l);
13585b1171fSralph 			}
136007a19b4Sdonn 		}
13785b1171fSralph 
13885b1171fSralph 	else if( o==QUEST && l->in.op==ICON ) {
13985b1171fSralph 		l->in.op = FREE;
14085b1171fSralph 		r->in.op = FREE;
14185b1171fSralph 		if( l->tn.lval ){
14285b1171fSralph 			tfree( r->in.right );
14385b1171fSralph 			return( r->in.left );
14485b1171fSralph 			}
14585b1171fSralph 		else {
14685b1171fSralph 			tfree( r->in.left );
14785b1171fSralph 			return( r->in.right );
14885b1171fSralph 			}
14985b1171fSralph 		}
15085b1171fSralph 
15185b1171fSralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
15285b1171fSralph 
15385b1171fSralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
15485b1171fSralph 
15585b1171fSralph 		switch( o ){
15685b1171fSralph 
15785b1171fSralph 		case ULT:
15885b1171fSralph 		case UGT:
15985b1171fSralph 		case ULE:
16085b1171fSralph 		case UGE:
16185b1171fSralph 		case LT:
16285b1171fSralph 		case GT:
16385b1171fSralph 		case LE:
16485b1171fSralph 		case GE:
16585b1171fSralph 		case EQ:
16685b1171fSralph 		case NE:
167eb7dc8d0Sdonn 			if( l->in.type == ENUMTY && r->in.type == ENUMTY ){
168eb7dc8d0Sdonn 				p = block( o, l, r, INT, 0, INT );
1692a1a76a1Sdonn 				chkpun( p );
170eb7dc8d0Sdonn 				p->in.op = FREE;
171eb7dc8d0Sdonn 				}
1722a1a76a1Sdonn 
17385b1171fSralph 		case ANDAND:
17485b1171fSralph 		case OROR:
17585b1171fSralph 		case CBRANCH:
17685b1171fSralph 
17785b1171fSralph 		ccwarn:
17885b1171fSralph 			if( hflag ) werror( "constant in conditional context" );
17985b1171fSralph 
18085b1171fSralph 		case PLUS:
18185b1171fSralph 		case MINUS:
18285b1171fSralph 		case MUL:
18385b1171fSralph 		case DIV:
18485b1171fSralph 		case MOD:
18585b1171fSralph 		case AND:
18685b1171fSralph 		case OR:
18785b1171fSralph 		case ER:
18885b1171fSralph 		case LS:
18985b1171fSralph 		case RS:
19085b1171fSralph 			if( conval( l, o, r ) ) {
19185b1171fSralph 				r->in.op = FREE;
19285b1171fSralph 				return(l);
19385b1171fSralph 				}
19485b1171fSralph 			break;
19585b1171fSralph 			}
19685b1171fSralph 		}
197d0dde492Smckusick 	else if (opty == BITYPE &&
198d0dde492Smckusick 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
199d0dde492Smckusick 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
200d0dde492Smckusick 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
201d0dde492Smckusick 				extern int fpe_count;
202d0dde492Smckusick 				extern jmp_buf gotfpe;
2039411d0f5Sralph 
204d0dde492Smckusick 				fpe_count = 0;
205d0dde492Smckusick 				if (setjmp(gotfpe))
206d0dde492Smckusick 					goto treatfpe;
2079411d0f5Sralph 				if (l->in.op == ICON)
2089411d0f5Sralph 					l->dpn.dval = l->tn.lval;
209d0dde492Smckusick 				else if (l->in.op == FCON)
210d0dde492Smckusick 					l->dpn.dval = l->fpn.fval;
2119411d0f5Sralph 				if (r->in.op == ICON)
2129411d0f5Sralph 					r->dpn.dval = r->tn.lval;
213d0dde492Smckusick 				else if (r->in.op == FCON)
214d0dde492Smckusick 					r->dpn.dval = r->fpn.fval;
21585b1171fSralph 				switch (o) {
2169411d0f5Sralph 
21785b1171fSralph 				case PLUS:
2189411d0f5Sralph 					l->dpn.dval += r->dpn.dval;
219d0dde492Smckusick 					break;
2209411d0f5Sralph 
22185b1171fSralph 				case MINUS:
2229411d0f5Sralph 					l->dpn.dval -= r->dpn.dval;
223d0dde492Smckusick 					break;
2249411d0f5Sralph 
22585b1171fSralph 				case MUL:
2269411d0f5Sralph 					l->dpn.dval *= r->dpn.dval;
227d0dde492Smckusick 					break;
2289411d0f5Sralph 
22985b1171fSralph 				case DIV:
2309411d0f5Sralph 					if (r->dpn.dval == 0)
2319411d0f5Sralph 						uerror("division by 0.");
2329411d0f5Sralph 					else
2339411d0f5Sralph 						l->dpn.dval /= r->dpn.dval;
234d0dde492Smckusick 					break;
235d0dde492Smckusick 					}
236d0dde492Smckusick 			treatfpe:
237d0dde492Smckusick 				if (fpe_count > 0) {
238d0dde492Smckusick 					uerror("floating point exception in constant expression");
239d0dde492Smckusick 					l->dpn.dval = 1.0; /* Fairly harmless */
240d0dde492Smckusick 					}
241d0dde492Smckusick 				fpe_count = -1;
242d0dde492Smckusick 				l->in.op = DCON;
243d0dde492Smckusick 				l->in.type = l->fn.csiz = DOUBLE;
244d0dde492Smckusick 				r->in.op = FREE;
24585b1171fSralph 				return (l);
24685b1171fSralph 			}
24785b1171fSralph 		}
24885b1171fSralph 
249d0dde492Smckusick 	/* it's real; we must make a new node */
25085b1171fSralph 
25185b1171fSralph 	p = block( o, l, r, INT, 0, INT );
25285b1171fSralph 
25385b1171fSralph 	actions = opact(p);
2549411d0f5Sralph #ifndef	BUG1
2559411d0f5Sralph 	if (adebug)
2569411d0f5Sralph 		printact(p, actions);
2579411d0f5Sralph #endif
25885b1171fSralph 
25985b1171fSralph 	if( actions&LVAL ){ /* check left descendent */
26085b1171fSralph 		if( notlval(p->in.left) ) {
26109ddf2aaSdonn 			uerror( "illegal lvalue operand of assignment operator" );
26285b1171fSralph 			}
26385b1171fSralph 		}
26485b1171fSralph 
26585b1171fSralph 	if( actions & NCVTR ){
26685b1171fSralph 		p->in.left = pconvert( p->in.left );
26785b1171fSralph 		}
26885b1171fSralph 	else if( !(actions & NCVT ) ){
26985b1171fSralph 		switch( opty ){
27085b1171fSralph 
27185b1171fSralph 		case BITYPE:
27285b1171fSralph 			p->in.right = pconvert( p->in.right );
27385b1171fSralph 		case UTYPE:
27485b1171fSralph 			p->in.left = pconvert( p->in.left );
27585b1171fSralph 
27685b1171fSralph 			}
27785b1171fSralph 		}
27885b1171fSralph 
27985b1171fSralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
28085b1171fSralph 		chkpun(p);
28185b1171fSralph 		}
28285b1171fSralph 
28385b1171fSralph 	if( actions & (TYPL|TYPR) ){
28485b1171fSralph 
28585b1171fSralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
28685b1171fSralph 
28785b1171fSralph 		p->in.type = q->in.type;
28885b1171fSralph 		p->fn.cdim = q->fn.cdim;
28985b1171fSralph 		p->fn.csiz = q->fn.csiz;
29085b1171fSralph 		}
29185b1171fSralph 
29285b1171fSralph 	if( actions & CVTL ) p = convert( p, CVTL );
29385b1171fSralph 	if( actions & CVTR ) p = convert( p, CVTR );
29485b1171fSralph 	if( actions & TYMATCH ) p = tymatch(p);
29585b1171fSralph 	if( actions & PTMATCH ) p = ptmatch(p);
29685b1171fSralph 
29785b1171fSralph 	if( actions & OTHER ){
29885b1171fSralph 		l = p->in.left;
29985b1171fSralph 		r = p->in.right;
30085b1171fSralph 
30185b1171fSralph 		switch(o){
30285b1171fSralph 
30385b1171fSralph 		case NAME:
30485b1171fSralph 			sp = &stab[idname];
30585b1171fSralph 			if( sp->stype == UNDEF ){
30685b1171fSralph #ifndef FLEXNAMES
30785b1171fSralph 				uerror( "%.8s undefined", sp->sname );
30885b1171fSralph #else
30985b1171fSralph 				uerror( "%s undefined", sp->sname );
31085b1171fSralph #endif
31185b1171fSralph 				/* make p look reasonable */
312007a19b4Sdonn 				p->in.type = p->fn.csiz = INT;
313007a19b4Sdonn 				p->fn.cdim = 0;
31485b1171fSralph 				p->tn.rval = idname;
31585b1171fSralph 				p->tn.lval = 0;
31685b1171fSralph 				defid( p, SNULL );
31785b1171fSralph 				break;
31885b1171fSralph 				}
31985b1171fSralph 			p->in.type = sp->stype;
32085b1171fSralph 			p->fn.cdim = sp->dimoff;
32185b1171fSralph 			p->fn.csiz = sp->sizoff;
32285b1171fSralph 			p->tn.lval = 0;
32385b1171fSralph 			p->tn.rval = idname;
32485b1171fSralph 			/* special case: MOETY is really an ICON... */
32585b1171fSralph 			if( p->in.type == MOETY ){
32685b1171fSralph 				p->tn.rval = NONAME;
32785b1171fSralph 				p->tn.lval = sp->offset;
32885b1171fSralph 				p->fn.cdim = 0;
32985b1171fSralph 				p->in.type = ENUMTY;
33085b1171fSralph 				p->in.op = ICON;
33185b1171fSralph 				}
33285b1171fSralph 			break;
33385b1171fSralph 
33485b1171fSralph 		case ICON:
33585b1171fSralph 			p->in.type = INT;
33685b1171fSralph 			p->fn.cdim = 0;
33785b1171fSralph 			p->fn.csiz = INT;
33885b1171fSralph 			break;
33985b1171fSralph 
34085b1171fSralph 		case STRING:
34185b1171fSralph 			p->in.op = NAME;
34285b1171fSralph 			p->in.type = CHAR+ARY;
34385b1171fSralph 			p->tn.lval = 0;
34485b1171fSralph 			p->tn.rval = NOLAB;
34585b1171fSralph 			p->fn.cdim = curdim;
34685b1171fSralph 			p->fn.csiz = CHAR;
34785b1171fSralph 			break;
34885b1171fSralph 
34985b1171fSralph 		case FCON:
35085b1171fSralph 			p->tn.lval = 0;
35185b1171fSralph 			p->tn.rval = 0;
3529411d0f5Sralph 			p->in.type = FLOAT;
3539411d0f5Sralph 			p->fn.cdim = 0;
3549411d0f5Sralph 			p->fn.csiz = FLOAT;
3559411d0f5Sralph 			break;
3569411d0f5Sralph 
3579411d0f5Sralph 		case DCON:
3589411d0f5Sralph 			p->tn.lval = 0;
3599411d0f5Sralph 			p->tn.rval = 0;
36085b1171fSralph 			p->in.type = DOUBLE;
36185b1171fSralph 			p->fn.cdim = 0;
36285b1171fSralph 			p->fn.csiz = DOUBLE;
36385b1171fSralph 			break;
36485b1171fSralph 
36585b1171fSralph 		case STREF:
36685b1171fSralph 			/* p->x turned into *(p+offset) */
36785b1171fSralph 			/* rhs must be a name; check correctness */
36885b1171fSralph 
36985b1171fSralph 			i = r->tn.rval;
37085b1171fSralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
37185b1171fSralph 				uerror( "member of structure or union required" );
37285b1171fSralph 				}else
37385b1171fSralph 			/* if this name is non-unique, find right one */
37485b1171fSralph 			if( stab[i].sflags & SNONUNIQ &&
37585b1171fSralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
37685b1171fSralph 				(l->fn.csiz +1) >= 0 ){
37785b1171fSralph 				/* nonunique name && structure defined */
37885b1171fSralph 				char * memnam, * tabnam;
37985b1171fSralph 				int j;
38085b1171fSralph 				int memi;
38185b1171fSralph 				j=dimtab[l->fn.csiz+1];
38285b1171fSralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
38385b1171fSralph 					tabnam = stab[memi].sname;
38485b1171fSralph 					memnam = stab[i].sname;
38585b1171fSralph # ifndef BUG1
38685b1171fSralph 					if( ddebug>1 ){
38785b1171fSralph #ifndef FLEXNAMES
38885b1171fSralph 						printf("member %.8s==%.8s?\n",
38985b1171fSralph #else
39085b1171fSralph 						printf("member %s==%s?\n",
39185b1171fSralph #endif
39285b1171fSralph 							memnam, tabnam);
39385b1171fSralph 						}
39485b1171fSralph # endif
39585b1171fSralph 					if( stab[memi].sflags & SNONUNIQ ){
39685b1171fSralph #ifndef FLEXNAMES
397eb7dc8d0Sdonn 						register k;
39885b1171fSralph 						for( k=0; k<NCHNAM; ++k ){
39985b1171fSralph 							if(*memnam++!=*tabnam)
40085b1171fSralph 								goto next;
40185b1171fSralph 							if(!*tabnam++) break;
40285b1171fSralph 							}
40385b1171fSralph #else
40485b1171fSralph 						if (memnam != tabnam)
40585b1171fSralph 							goto next;
40685b1171fSralph #endif
40785b1171fSralph 						r->tn.rval = i = memi;
40885b1171fSralph 						break;
40985b1171fSralph 						}
41085b1171fSralph 					next: continue;
41185b1171fSralph 					}
41285b1171fSralph 				if( memi < 0 )
41385b1171fSralph #ifndef FLEXNAMES
41485b1171fSralph 					uerror("illegal member use: %.8s",
41585b1171fSralph #else
41685b1171fSralph 					uerror("illegal member use: %s",
41785b1171fSralph #endif
41885b1171fSralph 						stab[i].sname);
41985b1171fSralph 				}
42085b1171fSralph 			else {
42185b1171fSralph 				register j;
42285b1171fSralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
42385b1171fSralph 					if( stab[i].sflags & SNONUNIQ ){
42485b1171fSralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
42585b1171fSralph 						}
42685b1171fSralph 					else werror( "struct/union or struct/union pointer required" );
42785b1171fSralph 					}
42885b1171fSralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
42985b1171fSralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
43085b1171fSralph #ifndef FLEXNAMES
43185b1171fSralph 					werror( "illegal member use: %.8s", stab[i].sname );
43285b1171fSralph #else
43385b1171fSralph 					werror( "illegal member use: %s", stab[i].sname );
43485b1171fSralph #endif
43585b1171fSralph 					}
43685b1171fSralph 				}
43785b1171fSralph 
43885b1171fSralph 			p = stref( p );
43985b1171fSralph 			break;
44085b1171fSralph 
44185b1171fSralph 		case UNARY MUL:
44285b1171fSralph 			if( l->in.op == UNARY AND ){
44385b1171fSralph 				p->in.op = l->in.op = FREE;
44485b1171fSralph 				p = l->in.left;
44585b1171fSralph 				}
44685b1171fSralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
44785b1171fSralph 			p->in.type = DECREF(l->in.type);
44885b1171fSralph 			p->fn.cdim = l->fn.cdim;
44985b1171fSralph 			p->fn.csiz = l->fn.csiz;
45085b1171fSralph 			break;
45185b1171fSralph 
45285b1171fSralph 		case UNARY AND:
45385b1171fSralph 			switch( l->in.op ){
45485b1171fSralph 
45585b1171fSralph 			case UNARY MUL:
45685b1171fSralph 				p->in.op = l->in.op = FREE;
45785b1171fSralph 				p = l->in.left;
45885b1171fSralph 			case NAME:
45985b1171fSralph 				p->in.type = INCREF( l->in.type );
46085b1171fSralph 				p->fn.cdim = l->fn.cdim;
46185b1171fSralph 				p->fn.csiz = l->fn.csiz;
46285b1171fSralph 				break;
46385b1171fSralph 
46485b1171fSralph 			case COMOP:
46585b1171fSralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
46685b1171fSralph 				p->in.op = l->in.op = FREE;
46785b1171fSralph 				p = buildtree( COMOP, l->in.left, lr );
46885b1171fSralph 				break;
46985b1171fSralph 
47085b1171fSralph 			case QUEST:
47185b1171fSralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
47285b1171fSralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
47385b1171fSralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
47485b1171fSralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
47585b1171fSralph 				break;
47685b1171fSralph 
47785b1171fSralph # ifdef ADDROREG
47885b1171fSralph 			case OREG:
47985b1171fSralph 				/* OREG was built in clocal()
48085b1171fSralph 				 * for an auto or formal parameter
48185b1171fSralph 				 * now its address is being taken
48285b1171fSralph 				 * local code must unwind it
48385b1171fSralph 				 * back to PLUS/MINUS REG ICON
48485b1171fSralph 				 * according to local conventions
48585b1171fSralph 				 */
48685b1171fSralph 				{
48785b1171fSralph 				extern NODE * addroreg();
48885b1171fSralph 				p->in.op = FREE;
48985b1171fSralph 				p = addroreg( l );
49085b1171fSralph 				}
49185b1171fSralph 				break;
49285b1171fSralph 
49385b1171fSralph # endif
49485b1171fSralph 			default:
49585b1171fSralph 				uerror( "unacceptable operand of &" );
49685b1171fSralph 				break;
49785b1171fSralph 				}
49885b1171fSralph 			break;
49985b1171fSralph 
50085b1171fSralph 		case LS:
50185b1171fSralph 		case RS:
502007a19b4Sdonn 			if( l->in.type == CHAR || l->in.type == SHORT )
503007a19b4Sdonn 				p->in.type = INT;
504007a19b4Sdonn 			else if( l->in.type == UCHAR || l->in.type == USHORT )
505007a19b4Sdonn 				p->in.type = UNSIGNED;
506007a19b4Sdonn 			else
507007a19b4Sdonn 				p->in.type = l->in.type;
50885b1171fSralph 		case ASG LS:
50985b1171fSralph 		case ASG RS:
510007a19b4Sdonn 			if( r->in.type != INT )
511007a19b4Sdonn 				p->in.right = r = makety(r, INT, 0, INT );
51285b1171fSralph 			break;
51385b1171fSralph 
51485b1171fSralph 		case RETURN:
51585b1171fSralph 		case ASSIGN:
51685b1171fSralph 		case CAST:
51785b1171fSralph 			/* structure assignment */
51885b1171fSralph 			/* take the addresses of the two sides; then make an
51985b1171fSralph 			/* operator using STASG and
52085b1171fSralph 			/* the addresses of left and right */
52185b1171fSralph 
52285b1171fSralph 			{
52385b1171fSralph 				register TWORD t;
52485b1171fSralph 				register d, s;
52585b1171fSralph 
52685b1171fSralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
52785b1171fSralph 
52885b1171fSralph 				r = buildtree( UNARY AND, r, NIL );
52985b1171fSralph 				t = r->in.type;
53085b1171fSralph 				d = r->fn.cdim;
53185b1171fSralph 				s = r->fn.csiz;
53285b1171fSralph 
53385b1171fSralph 				l = block( STASG, l, r, t, d, s );
53485b1171fSralph 
53585b1171fSralph 				if( o == RETURN ){
53685b1171fSralph 					p->in.op = FREE;
53785b1171fSralph 					p = l;
53885b1171fSralph 					break;
53985b1171fSralph 					}
54085b1171fSralph 
54185b1171fSralph 				p->in.op = UNARY MUL;
54285b1171fSralph 				p->in.left = l;
54385b1171fSralph 				p->in.right = NIL;
54485b1171fSralph 				break;
54585b1171fSralph 				}
54685b1171fSralph 		case COLON:
54785b1171fSralph 			/* structure colon */
54885b1171fSralph 
54985b1171fSralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
55085b1171fSralph 			break;
55185b1171fSralph 
55285b1171fSralph 		case CALL:
5539411d0f5Sralph 			p->in.right = r = fixargs( p->in.right );
55485b1171fSralph 		case UNARY CALL:
55585b1171fSralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
55685b1171fSralph 			p->in.type = DECREF(l->in.type);
55785b1171fSralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
55885b1171fSralph 			p->in.type = DECREF( p->in.type );
55985b1171fSralph 			p->fn.cdim = l->fn.cdim;
56085b1171fSralph 			p->fn.csiz = l->fn.csiz;
56185b1171fSralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
56285b1171fSralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
56385b1171fSralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
56485b1171fSralph 				p->in.op += (FORTCALL-CALL);
56585b1171fSralph 				}
56685b1171fSralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
56785b1171fSralph 				/* function returning structure */
56885b1171fSralph 				/*  make function really return ptr to str., with * */
56985b1171fSralph 
57085b1171fSralph 				p->in.op += STCALL-CALL;
57185b1171fSralph 				p->in.type = INCREF( p->in.type );
57285b1171fSralph 				p = buildtree( UNARY MUL, p, NIL );
57385b1171fSralph 
57485b1171fSralph 				}
57585b1171fSralph 			break;
57685b1171fSralph 
57785b1171fSralph 		default:
57885b1171fSralph 			cerror( "other code %d", o );
57985b1171fSralph 			}
58085b1171fSralph 
58185b1171fSralph 		}
58285b1171fSralph 
58385b1171fSralph 	if( actions & CVTO ) p = oconvert(p);
58485b1171fSralph 	p = clocal(p);
58585b1171fSralph 
58685b1171fSralph # ifndef BUG1
58785b1171fSralph 	if( bdebug ) fwalk( p, eprint, 0 );
58885b1171fSralph # endif
58985b1171fSralph 
59085b1171fSralph 	return(p);
59185b1171fSralph 
59285b1171fSralph 	}
59385b1171fSralph 
594d0dde492Smckusick int fpe_count = -1;
595d0dde492Smckusick jmp_buf gotfpe;
596d0dde492Smckusick 
597*10cfdb8aSbostic void
fpe()598d0dde492Smckusick fpe() {
599d0dde492Smckusick 	if (fpe_count < 0)
600d0dde492Smckusick 		cerror("floating point exception");
601d0dde492Smckusick 	++fpe_count;
602d0dde492Smckusick 	longjmp(gotfpe, 1);
603d0dde492Smckusick 	}
604d0dde492Smckusick 
6059411d0f5Sralph /*
6069411d0f5Sralph  * Rewrite arguments in a function call.
6079411d0f5Sralph  * Structure arguments are massaged, single
6089411d0f5Sralph  * precision floating point constants are
6099411d0f5Sralph  * cast to double (to eliminate convert code).
6109411d0f5Sralph  */
61185b1171fSralph NODE *
fixargs(p)6129411d0f5Sralph fixargs( p ) register NODE *p;  {
6139411d0f5Sralph 	int o = p->in.op;
61485b1171fSralph 
6159411d0f5Sralph 	if( o == CM ){
6169411d0f5Sralph 		p->in.left = fixargs( p->in.left );
6179411d0f5Sralph 		p->in.right = fixargs( p->in.right );
61885b1171fSralph 		return( p );
61985b1171fSralph 		}
62085b1171fSralph 
62185b1171fSralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
62285b1171fSralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
62385b1171fSralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
62485b1171fSralph 		p = clocal(p);
62585b1171fSralph 		}
6269411d0f5Sralph 	else if( o == FCON )
6279411d0f5Sralph 		p = makety(p, DOUBLE, 0, 0);
62885b1171fSralph 	return( p );
62985b1171fSralph 	}
63085b1171fSralph 
chkstr(i,j,type)63185b1171fSralph chkstr( i, j, type ) TWORD type; {
63285b1171fSralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
63385b1171fSralph 	/* i has been checked to contain a MOS or MOU */
63485b1171fSralph 	/* j is the index in dimtab of the members... */
63585b1171fSralph 	int k, kk;
63685b1171fSralph 
63785b1171fSralph 	extern int ddebug;
63885b1171fSralph 
63985b1171fSralph # ifndef BUG1
64085b1171fSralph #ifndef FLEXNAMES
64185b1171fSralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
64285b1171fSralph #else
64385b1171fSralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
64485b1171fSralph #endif
64585b1171fSralph # endif
64685b1171fSralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
64785b1171fSralph 	else {
64885b1171fSralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
64985b1171fSralph 			if( kk >= SYMTSZ ){
65085b1171fSralph 				cerror( "gummy structure" );
65185b1171fSralph 				return(1);
65285b1171fSralph 				}
65385b1171fSralph 			if( kk == i ) return( 1 );
65485b1171fSralph 			switch( stab[kk].stype ){
65585b1171fSralph 
65685b1171fSralph 			case STRTY:
65785b1171fSralph 			case UNIONTY:
65885b1171fSralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
65985b1171fSralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
66085b1171fSralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
66185b1171fSralph 					werror(
66285b1171fSralph #ifndef FLEXNAMES
66385b1171fSralph 					"illegal member use: perhaps %.8s.%.8s?",
66485b1171fSralph #else
66585b1171fSralph 					"illegal member use: perhaps %s.%s?",
66685b1171fSralph #endif
66785b1171fSralph 					stab[kk].sname, stab[i].sname );
66885b1171fSralph 					return(1);
66985b1171fSralph 					}
67085b1171fSralph 				}
67185b1171fSralph 			}
67285b1171fSralph 		}
67385b1171fSralph 	return( 0 );
67485b1171fSralph 	}
67585b1171fSralph 
conval(p,o,q)67685b1171fSralph conval( p, o, q ) register NODE *p, *q; {
67785b1171fSralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
67897187f20Sdonn 	/* works only on integer constants */
67997187f20Sdonn 	NODE *r;
68085b1171fSralph 	int i, u;
68185b1171fSralph 	CONSZ val;
6829d332cffSdonn 	TWORD utype;
68385b1171fSralph 
68485b1171fSralph 	val = q->tn.lval;
68585b1171fSralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
68685b1171fSralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
68785b1171fSralph 
68885b1171fSralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
68985b1171fSralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
69085b1171fSralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
69185b1171fSralph 
6929d332cffSdonn 	/* usual type conversions -- handle casts of constants */
6935d572d7fSdonn #define	ISLONG(t)	((t) == LONG || (t) == ULONG)
6945d572d7fSdonn 	if (ISLONG(p->in.type) || ISLONG(q->in.type))
6955d572d7fSdonn 		utype = u ? ULONG : LONG;
6965d572d7fSdonn 	else
6979d332cffSdonn 		utype = u ? UNSIGNED : INT;
6989d332cffSdonn 	if( !ISPTR(p->in.type) && p->in.type != utype )
6999d332cffSdonn 		p = makety(p, utype, 0, (int)utype);
7009d332cffSdonn 	if( q->in.type != utype )
7019d332cffSdonn 		q = makety(q, utype, 0, (int)utype);
70297187f20Sdonn 
70385b1171fSralph 	switch( o ){
70485b1171fSralph 
70585b1171fSralph 	case PLUS:
70685b1171fSralph 		p->tn.lval += val;
70785b1171fSralph 		if( p->tn.rval == NONAME ){
70885b1171fSralph 			p->tn.rval = q->tn.rval;
70985b1171fSralph 			p->in.type = q->in.type;
71085b1171fSralph 			}
71185b1171fSralph 		break;
71285b1171fSralph 	case MINUS:
71385b1171fSralph 		p->tn.lval -= val;
71485b1171fSralph 		break;
71585b1171fSralph 	case MUL:
7162a1a76a1Sdonn 		p->tn.lval *= val;
71785b1171fSralph 		break;
71885b1171fSralph 	case DIV:
71985b1171fSralph 		if( val == 0 ) uerror( "division by 0" );
7209411d0f5Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
72185b1171fSralph 		else p->tn.lval /= val;
72285b1171fSralph 		break;
72385b1171fSralph 	case MOD:
72485b1171fSralph 		if( val == 0 ) uerror( "division by 0" );
7259411d0f5Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
72685b1171fSralph 		else p->tn.lval %= val;
72785b1171fSralph 		break;
72885b1171fSralph 	case AND:
72985b1171fSralph 		p->tn.lval &= val;
73085b1171fSralph 		break;
73185b1171fSralph 	case OR:
73285b1171fSralph 		p->tn.lval |= val;
73385b1171fSralph 		break;
73485b1171fSralph 	case ER:
73585b1171fSralph 		p->tn.lval ^= val;
73685b1171fSralph 		break;
73785b1171fSralph 	case LS:
73885b1171fSralph 		i = val;
73985b1171fSralph 		p->tn.lval = p->tn.lval << i;
74085b1171fSralph 		break;
74185b1171fSralph 	case RS:
74285b1171fSralph 		i = val;
7439411d0f5Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
7449411d0f5Sralph 		else p->tn.lval = p->tn.lval >> i;
74585b1171fSralph 		break;
74685b1171fSralph 
74785b1171fSralph 	case UNARY MINUS:
74885b1171fSralph 		p->tn.lval = - p->tn.lval;
74985b1171fSralph 		break;
75085b1171fSralph 	case COMPL:
75185b1171fSralph 		p->tn.lval = ~p->tn.lval;
75285b1171fSralph 		break;
75385b1171fSralph 	case NOT:
75485b1171fSralph 		p->tn.lval = !p->tn.lval;
75585b1171fSralph 		break;
75685b1171fSralph 	case LT:
75785b1171fSralph 		p->tn.lval = p->tn.lval < val;
75885b1171fSralph 		break;
75985b1171fSralph 	case LE:
76085b1171fSralph 		p->tn.lval = p->tn.lval <= val;
76185b1171fSralph 		break;
76285b1171fSralph 	case GT:
76385b1171fSralph 		p->tn.lval = p->tn.lval > val;
76485b1171fSralph 		break;
76585b1171fSralph 	case GE:
76685b1171fSralph 		p->tn.lval = p->tn.lval >= val;
76785b1171fSralph 		break;
76885b1171fSralph 	case ULT:
7695eb997faSdonn 		p->tn.lval = p->tn.lval < (unsigned) val;
77085b1171fSralph 		break;
77185b1171fSralph 	case ULE:
7725eb997faSdonn 		p->tn.lval = p->tn.lval <= (unsigned) val;
7732a1a76a1Sdonn 		break;
7742a1a76a1Sdonn 	case UGT:
7755eb997faSdonn 		p->tn.lval = p->tn.lval > (unsigned) val;
7765eb997faSdonn 		break;
7775eb997faSdonn 	case UGE:
7785eb997faSdonn 		p->tn.lval = p->tn.lval >= (unsigned) val;
77985b1171fSralph 		break;
78085b1171fSralph 	case EQ:
78185b1171fSralph 		p->tn.lval = p->tn.lval == val;
78285b1171fSralph 		break;
78385b1171fSralph 	case NE:
78485b1171fSralph 		p->tn.lval = p->tn.lval != val;
78585b1171fSralph 		break;
78685b1171fSralph 	default:
78785b1171fSralph 		return(0);
78885b1171fSralph 		}
78985b1171fSralph 	return(1);
79085b1171fSralph 	}
79185b1171fSralph 
chkpun(p)79285b1171fSralph chkpun(p) register NODE *p; {
79385b1171fSralph 
79485b1171fSralph 	/* checks p for the existance of a pun */
79585b1171fSralph 
79685b1171fSralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
79785b1171fSralph 
79885b1171fSralph 	/* one case is when enumerations are used: this applies only to lint */
79985b1171fSralph 	/* in the other case, one operand is a pointer, the other integer type */
80085b1171fSralph 	/* we check that this integer is in fact a constant zero... */
80185b1171fSralph 
80285b1171fSralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
80385b1171fSralph 	/* this falls out, because the LHS is never 0 */
80485b1171fSralph 
80585b1171fSralph 	register NODE *q;
80685b1171fSralph 	register t1, t2;
80785b1171fSralph 	register d1, d2;
80858dcaca6Sdonn 	int ref1, ref2;
80985b1171fSralph 
81085b1171fSralph 	t1 = p->in.left->in.type;
81185b1171fSralph 	t2 = p->in.right->in.type;
81285b1171fSralph 
81385b1171fSralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
8146c817b2bSdonn 		/* rob pike says this is obnoxious...
8152a1a76a1Sdonn 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
8166c817b2bSdonn 			werror( "comparison of enums" ); */
8176c817b2bSdonn 		if( t1==ENUMTY && t2==ENUMTY ) {
8186c817b2bSdonn 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
81985b1171fSralph 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
82085b1171fSralph 			return;
82185b1171fSralph 			}
8226c817b2bSdonn 		if ( t1 == ENUMTY ) t1 = INT;
8236c817b2bSdonn 		if ( t2 == ENUMTY ) t2 = INT;
8246c817b2bSdonn 		}
82585b1171fSralph 
82658dcaca6Sdonn 	ref1 = ISPTR(t1) || ISARY(t1);
82758dcaca6Sdonn 	ref2 = ISPTR(t2) || ISARY(t2);
82885b1171fSralph 
82958dcaca6Sdonn 	if( ref1 ^ ref2 ){
83058dcaca6Sdonn 		if( ref1 ) q = p->in.right;
83158dcaca6Sdonn 		else q = p->in.left;
83285b1171fSralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
83385b1171fSralph 			werror( "illegal combination of pointer and integer, op %s",
83485b1171fSralph 				opst[p->in.op] );
83585b1171fSralph 			}
83685b1171fSralph 		}
83758dcaca6Sdonn 	else if( ref1 ){
8387cd1d6a9Sdonn 		if( t1 == t2 ) {
8397cd1d6a9Sdonn 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
8407cd1d6a9Sdonn 				werror( "illegal structure pointer combination" );
8417cd1d6a9Sdonn 				return;
8427cd1d6a9Sdonn 				}
84385b1171fSralph 			d1 = p->in.left->fn.cdim;
84485b1171fSralph 			d2 = p->in.right->fn.cdim;
84585b1171fSralph 			for( ;; ){
8467cd1d6a9Sdonn 				if( ISARY(t1) ){
8477cd1d6a9Sdonn 					if( dimtab[d1] != dimtab[d2] ){
84885b1171fSralph 						werror( "illegal array size combination" );
84985b1171fSralph 						return;
85085b1171fSralph 						}
8517cd1d6a9Sdonn 					++d1;
8527cd1d6a9Sdonn 					++d2;
85385b1171fSralph 					}
8547cd1d6a9Sdonn 				else if( !ISPTR(t1) ) break;
85585b1171fSralph 				t1 = DECREF(t1);
85685b1171fSralph 				}
8577cd1d6a9Sdonn 			}
858007a19b4Sdonn 		else if( t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
85985b1171fSralph 			werror( "illegal pointer combination" );
86085b1171fSralph 		}
86185b1171fSralph 
86285b1171fSralph 	}
86385b1171fSralph 
86485b1171fSralph NODE *
stref(p)86585b1171fSralph stref( p ) register NODE *p; {
86685b1171fSralph 
86785b1171fSralph 	TWORD t;
86885b1171fSralph 	int d, s, dsc, align;
86985b1171fSralph 	OFFSZ off;
87085b1171fSralph 	register struct symtab *q;
87185b1171fSralph 
87285b1171fSralph 	/* make p->x */
87385b1171fSralph 	/* this is also used to reference automatic variables */
87485b1171fSralph 
87585b1171fSralph 	q = &stab[p->in.right->tn.rval];
87685b1171fSralph 	p->in.right->in.op = FREE;
87785b1171fSralph 	p->in.op = FREE;
87885b1171fSralph 	p = pconvert( p->in.left );
87985b1171fSralph 
88085b1171fSralph 	/* make p look like ptr to x */
88185b1171fSralph 
88285b1171fSralph 	if( !ISPTR(p->in.type)){
88385b1171fSralph 		p->in.type = PTR+UNIONTY;
88485b1171fSralph 		}
88585b1171fSralph 
88685b1171fSralph 	t = INCREF( q->stype );
88785b1171fSralph 	d = q->dimoff;
88885b1171fSralph 	s = q->sizoff;
88985b1171fSralph 
89085b1171fSralph 	p = makety( p, t, d, s );
89185b1171fSralph 
89285b1171fSralph 	/* compute the offset to be added */
89385b1171fSralph 
89485b1171fSralph 	off = q->offset;
89585b1171fSralph 	dsc = q->sclass;
89685b1171fSralph 
89785b1171fSralph 	if( dsc & FIELD ) {  /* normalize offset */
89885b1171fSralph 		align = ALINT;
89985b1171fSralph 		s = INT;
90085b1171fSralph 		off = (off/align)*align;
90185b1171fSralph 		}
90285b1171fSralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
90385b1171fSralph 
90485b1171fSralph 	p = buildtree( UNARY MUL, p, NIL );
90585b1171fSralph 
90685b1171fSralph 	/* if field, build field info */
90785b1171fSralph 
90885b1171fSralph 	if( dsc & FIELD ){
90985b1171fSralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
91085b1171fSralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
91185b1171fSralph 		}
91285b1171fSralph 
91385b1171fSralph 	return( clocal(p) );
91485b1171fSralph 	}
91585b1171fSralph 
notlval(p)91685b1171fSralph notlval(p) register NODE *p; {
91785b1171fSralph 
91885b1171fSralph 	/* return 0 if p an lvalue, 1 otherwise */
91985b1171fSralph 
92085b1171fSralph 	again:
92185b1171fSralph 
92285b1171fSralph 	switch( p->in.op ){
92385b1171fSralph 
92485b1171fSralph 	case FLD:
92585b1171fSralph 		p = p->in.left;
92685b1171fSralph 		goto again;
92785b1171fSralph 
92885b1171fSralph 	case UNARY MUL:
92985b1171fSralph 		/* fix the &(a=b) bug, given that a and b are structures */
93085b1171fSralph 		if( p->in.left->in.op == STASG ) return( 1 );
93185b1171fSralph 		/* and the f().a bug, given that f returns a structure */
93285b1171fSralph 		if( p->in.left->in.op == UNARY STCALL ||
93385b1171fSralph 		    p->in.left->in.op == STCALL ) return( 1 );
93485b1171fSralph 	case NAME:
93585b1171fSralph 	case OREG:
93685b1171fSralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
93785b1171fSralph 	case REG:
93885b1171fSralph 		return(0);
93985b1171fSralph 
94085b1171fSralph 	default:
94185b1171fSralph 		return(1);
94285b1171fSralph 
94385b1171fSralph 		}
94485b1171fSralph 
94585b1171fSralph 	}
94685b1171fSralph 
94785b1171fSralph NODE *
bcon(i)94885b1171fSralph bcon( i ){ /* make a constant node with value i */
94985b1171fSralph 	register NODE *p;
95085b1171fSralph 
95185b1171fSralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
95285b1171fSralph 	p->tn.lval = i;
95385b1171fSralph 	p->tn.rval = NONAME;
95485b1171fSralph 	return( clocal(p) );
95585b1171fSralph 	}
95685b1171fSralph 
95785b1171fSralph NODE *
bpsize(p)95885b1171fSralph bpsize(p) register NODE *p; {
95985b1171fSralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
96085b1171fSralph 	}
96185b1171fSralph 
96285b1171fSralph OFFSZ
psize(p)96385b1171fSralph psize( p ) NODE *p; {
96485b1171fSralph 	/* p is a node of type pointer; psize returns the
96585b1171fSralph 	   size of the thing pointed to */
96685b1171fSralph 
96785b1171fSralph 	if( !ISPTR(p->in.type) ){
96885b1171fSralph 		uerror( "pointer required");
96985b1171fSralph 		return( SZINT );
97085b1171fSralph 		}
97185b1171fSralph 	/* note: no pointers to fields */
97285b1171fSralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
97385b1171fSralph 	}
97485b1171fSralph 
97585b1171fSralph NODE *
convert(p,f)97685b1171fSralph convert( p, f )  register NODE *p; {
97785b1171fSralph 	/*  convert an operand of p
97885b1171fSralph 	    f is either CVTL or CVTR
97985b1171fSralph 	    operand has type int, and is converted by the size of the other side
98085b1171fSralph 	    */
98185b1171fSralph 
98285b1171fSralph 	register NODE *q, *r;
98385b1171fSralph 
98485b1171fSralph 	q = (f==CVTL)?p->in.left:p->in.right;
98585b1171fSralph 
98685b1171fSralph 	r = block( PMCONV,
98785b1171fSralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
98885b1171fSralph 	r = clocal(r);
98985b1171fSralph 	if( f == CVTL )
99085b1171fSralph 		p->in.left = r;
99185b1171fSralph 	else
99285b1171fSralph 		p->in.right = r;
99385b1171fSralph 	return(p);
99485b1171fSralph 
99585b1171fSralph 	}
99685b1171fSralph 
9975b9e3d1eSdonn #ifndef econvert
econvert(p)99885b1171fSralph econvert( p ) register NODE *p; {
99985b1171fSralph 
100085b1171fSralph 	/* change enums to ints, or appropriate types */
100185b1171fSralph 
100285b1171fSralph 	register TWORD ty;
100385b1171fSralph 
100485b1171fSralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
100585b1171fSralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
100685b1171fSralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
100785b1171fSralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
100885b1171fSralph 		else ty = LONG;
100985b1171fSralph 		ty = ctype( ty );
101085b1171fSralph 		p->fn.csiz = ty;
101185b1171fSralph 		MODTYPE(p->in.type,ty);
101285b1171fSralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
101385b1171fSralph 		}
101485b1171fSralph 	}
10155b9e3d1eSdonn #endif
101685b1171fSralph 
101785b1171fSralph NODE *
pconvert(p)101885b1171fSralph pconvert( p ) register NODE *p; {
101985b1171fSralph 
102085b1171fSralph 	/* if p should be changed into a pointer, do so */
102185b1171fSralph 
102285b1171fSralph 	if( ISARY( p->in.type) ){
102385b1171fSralph 		p->in.type = DECREF( p->in.type );
102485b1171fSralph 		++p->fn.cdim;
102585b1171fSralph 		return( buildtree( UNARY AND, p, NIL ) );
102685b1171fSralph 		}
102785b1171fSralph 	if( ISFTN( p->in.type) )
102885b1171fSralph 		return( buildtree( UNARY AND, p, NIL ) );
102985b1171fSralph 
103085b1171fSralph 	return( p );
103185b1171fSralph 	}
103285b1171fSralph 
103385b1171fSralph NODE *
oconvert(p)103485b1171fSralph oconvert(p) register NODE *p; {
103585b1171fSralph 	/* convert the result itself: used for pointer and unsigned */
103685b1171fSralph 
103785b1171fSralph 	switch(p->in.op) {
103885b1171fSralph 
103985b1171fSralph 	case LE:
104085b1171fSralph 	case LT:
104185b1171fSralph 	case GE:
104285b1171fSralph 	case GT:
104385b1171fSralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
104485b1171fSralph 	case EQ:
104585b1171fSralph 	case NE:
104685b1171fSralph 		return( p );
104785b1171fSralph 
104885b1171fSralph 	case MINUS:
104985b1171fSralph 		return(  clocal( block( PVCONV,
105085b1171fSralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
105185b1171fSralph 		}
105285b1171fSralph 
105385b1171fSralph 	cerror( "illegal oconvert: %d", p->in.op );
105485b1171fSralph 
105585b1171fSralph 	return(p);
105685b1171fSralph 	}
105785b1171fSralph 
105885b1171fSralph NODE *
ptmatch(p)105985b1171fSralph ptmatch(p)  register NODE *p; {
106085b1171fSralph 
106185b1171fSralph 	/* makes the operands of p agree; they are
106285b1171fSralph 	   either pointers or integers, by this time */
106385b1171fSralph 	/* with MINUS, the sizes must be the same */
106485b1171fSralph 	/* with COLON, the types must be the same */
106585b1171fSralph 
106685b1171fSralph 	TWORD t1, t2, t;
106785b1171fSralph 	int o, d2, d, s2, s;
106885b1171fSralph 
106985b1171fSralph 	o = p->in.op;
107085b1171fSralph 	t = t1 = p->in.left->in.type;
107185b1171fSralph 	t2 = p->in.right->in.type;
107285b1171fSralph 	d = p->in.left->fn.cdim;
107385b1171fSralph 	d2 = p->in.right->fn.cdim;
107485b1171fSralph 	s = p->in.left->fn.csiz;
107585b1171fSralph 	s2 = p->in.right->fn.csiz;
107685b1171fSralph 
107785b1171fSralph 	switch( o ){
107885b1171fSralph 
107985b1171fSralph 	case ASSIGN:
108085b1171fSralph 	case RETURN:
108185b1171fSralph 	case CAST:
108285b1171fSralph 		{  break; }
108385b1171fSralph 
108485b1171fSralph 	case MINUS:
108585b1171fSralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
108685b1171fSralph 			uerror( "illegal pointer subtraction");
108785b1171fSralph 			}
108885b1171fSralph 		   break;
108985b1171fSralph 		   }
109085b1171fSralph 	case COLON:
109185b1171fSralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
109285b1171fSralph 		   break;
109385b1171fSralph 		   }
109485b1171fSralph 	default:  /* must work harder: relationals or comparisons */
109585b1171fSralph 
109685b1171fSralph 		if( !ISPTR(t1) ){
109785b1171fSralph 			t = t2;
109885b1171fSralph 			d = d2;
109985b1171fSralph 			s = s2;
110085b1171fSralph 			break;
110185b1171fSralph 			}
110285b1171fSralph 		if( !ISPTR(t2) ){
110385b1171fSralph 			break;
110485b1171fSralph 			}
110585b1171fSralph 
110685b1171fSralph 		/* both are pointers */
110785b1171fSralph 		if( talign(t2,s2) < talign(t,s) ){
110885b1171fSralph 			t = t2;
110985b1171fSralph 			s = s2;
111085b1171fSralph 			}
111185b1171fSralph 		break;
111285b1171fSralph 		}
111385b1171fSralph 
111485b1171fSralph 	p->in.left = makety( p->in.left, t, d, s );
111585b1171fSralph 	p->in.right = makety( p->in.right, t, d, s );
111685b1171fSralph 	if( o!=MINUS && !logop(o) ){
111785b1171fSralph 
111885b1171fSralph 		p->in.type = t;
111985b1171fSralph 		p->fn.cdim = d;
112085b1171fSralph 		p->fn.csiz = s;
112185b1171fSralph 		}
112285b1171fSralph 
112385b1171fSralph 	return(clocal(p));
112485b1171fSralph 	}
112585b1171fSralph 
112685b1171fSralph int tdebug = 0;
112785b1171fSralph 
112885b1171fSralph NODE *
tymatch(p)112985b1171fSralph tymatch(p)  register NODE *p; {
113085b1171fSralph 
113185b1171fSralph 	/* satisfy the types of various arithmetic binary ops */
113285b1171fSralph 
113385b1171fSralph 	/* rules are:
11345b9e3d1eSdonn 		if assignment, type of LHS
113585b1171fSralph 		if any float or doubles, make double
113685b1171fSralph 		if any longs, make long
113785b1171fSralph 		otherwise, make int
113885b1171fSralph 		if either operand is unsigned, the result is...
113985b1171fSralph 	*/
114085b1171fSralph 
114185b1171fSralph 	register TWORD t1, t2, t, tu;
114285b1171fSralph 	register o, u;
114385b1171fSralph 
114485b1171fSralph 	o = p->in.op;
114585b1171fSralph 
114685b1171fSralph 	t1 = p->in.left->in.type;
114785b1171fSralph 	t2 = p->in.right->in.type;
114885b1171fSralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
114985b1171fSralph 		uerror("void type illegal in expression");
115085b1171fSralph 
115185b1171fSralph 	u = 0;
115285b1171fSralph 	if( ISUNSIGNED(t1) ){
115385b1171fSralph 		u = 1;
115485b1171fSralph 		t1 = DEUNSIGN(t1);
115585b1171fSralph 		}
115685b1171fSralph 	if( ISUNSIGNED(t2) ){
115785b1171fSralph 		u = 1;
115885b1171fSralph 		t2 = DEUNSIGN(t2);
115985b1171fSralph 		}
116085b1171fSralph 
116185b1171fSralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
116285b1171fSralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
116385b1171fSralph 
11649411d0f5Sralph #ifdef SPRECC
11659411d0f5Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
11669411d0f5Sralph 		t = DOUBLE;
11679411d0f5Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
11689411d0f5Sralph 		t = FLOAT;
11699411d0f5Sralph #else
11709411d0f5Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
11719411d0f5Sralph 		t = DOUBLE;
11729411d0f5Sralph #endif
117385b1171fSralph 	else if( t1==LONG || t2==LONG ) t = LONG;
117485b1171fSralph 	else t = INT;
117585b1171fSralph 
11764306b042Sdonn 	if( o == ASSIGN || o == CAST || o == RETURN )
11774306b042Sdonn 	{
117885b1171fSralph 		tu = p->in.left->in.type;
117985b1171fSralph 		t = t1;
118085b1171fSralph 		}
118185b1171fSralph 	else {
118285b1171fSralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
118385b1171fSralph 		}
118485b1171fSralph 
118585b1171fSralph 	/* because expressions have values that are at least as wide
118685b1171fSralph 	   as INT or UNSIGNED, the only conversions needed
118785b1171fSralph 	   are those involving FLOAT/DOUBLE, and those
118885b1171fSralph 	   from LONG to INT and ULONG to UNSIGNED */
118985b1171fSralph 
119066edcb48Sdonn 	if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
11915b9e3d1eSdonn 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
119285b1171fSralph 
119366edcb48Sdonn 	if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
11942a1a76a1Sdonn 		if ( tu == ENUMTY ) {/* always asgop */
11952a1a76a1Sdonn 			p->in.right = makety( p->in.right, INT, 0, INT );
11962a1a76a1Sdonn 			p->in.right->in.type = tu;
11972a1a76a1Sdonn 			p->in.right->fn.cdim = p->in.left->fn.cdim;
11982a1a76a1Sdonn 			p->in.right->fn.csiz = p->in.left->fn.csiz;
11992a1a76a1Sdonn 			}
12002a1a76a1Sdonn 		else
12015b9e3d1eSdonn 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
120285b1171fSralph 
120385b1171fSralph 	if( asgop(o) ){
120485b1171fSralph 		p->in.type = p->in.left->in.type;
120585b1171fSralph 		p->fn.cdim = p->in.left->fn.cdim;
120685b1171fSralph 		p->fn.csiz = p->in.left->fn.csiz;
120785b1171fSralph 		}
120885b1171fSralph 	else if( !logop(o) ){
120985b1171fSralph 		p->in.type = tu;
121085b1171fSralph 		p->fn.cdim = 0;
121185b1171fSralph 		p->fn.csiz = t;
121285b1171fSralph 		}
121385b1171fSralph 
121485b1171fSralph # ifndef BUG1
121585b1171fSralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
121685b1171fSralph # endif
121785b1171fSralph 
121885b1171fSralph 	return(p);
121985b1171fSralph 	}
122085b1171fSralph 
122185b1171fSralph NODE *
makety(p,t,d,s)122285b1171fSralph makety( p, t, d, s ) register NODE *p; TWORD t; {
122385b1171fSralph 	/* make p into type t by inserting a conversion */
122485b1171fSralph 
122585b1171fSralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
122685b1171fSralph 	if( t == p->in.type ){
122785b1171fSralph 		p->fn.cdim = d;
122885b1171fSralph 		p->fn.csiz = s;
122985b1171fSralph 		return( p );
123085b1171fSralph 		}
123185b1171fSralph 
123285b1171fSralph 	if( t & TMASK ){
123385b1171fSralph 		/* non-simple type */
12344a7a2b7bSralph 		return( block( PCONV, p, NIL, t, d, s ) );
123585b1171fSralph 		}
123685b1171fSralph 
123785b1171fSralph 	if( p->in.op == ICON ){
12389411d0f5Sralph 		if (t == DOUBLE) {
12399411d0f5Sralph 			p->in.op = DCON;
12409411d0f5Sralph 			if (ISUNSIGNED(p->in.type))
1241c202b11fSbostic 				p->dpn.dval = (U_CONSZ) p->tn.lval;
12429411d0f5Sralph 			else
12439411d0f5Sralph 				p->dpn.dval = p->tn.lval;
12449411d0f5Sralph 			p->in.type = p->fn.csiz = t;
12459411d0f5Sralph 			return (clocal(p));
12469411d0f5Sralph 		}
12479411d0f5Sralph 		if (t == FLOAT) {
124885b1171fSralph 			p->in.op = FCON;
124985b1171fSralph 			if( ISUNSIGNED(p->in.type) ){
1250c202b11fSbostic 				p->fpn.fval = (U_CONSZ) p->tn.lval;
125185b1171fSralph 				}
125285b1171fSralph 			else {
12539411d0f5Sralph 				p->fpn.fval = p->tn.lval;
125485b1171fSralph 				}
125585b1171fSralph 
125685b1171fSralph 			p->in.type = p->fn.csiz = t;
125785b1171fSralph 			return( clocal(p) );
125885b1171fSralph 			}
125985b1171fSralph 		}
12609411d0f5Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
12619411d0f5Sralph 		double db;
12629411d0f5Sralph 
12639411d0f5Sralph 		p->in.op = DCON;
12649411d0f5Sralph 		db = p->fpn.fval;
12659411d0f5Sralph 		p->dpn.dval = db;
12669411d0f5Sralph 		p->in.type = p->fn.csiz = t;
12679411d0f5Sralph 		return (clocal(p));
12689411d0f5Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
12699411d0f5Sralph 		float fl;
12709411d0f5Sralph 
12719411d0f5Sralph 		p->in.op = FCON;
12729411d0f5Sralph 		fl = p->dpn.dval;
12739411d0f5Sralph #ifdef notdef
12749411d0f5Sralph 		if (fl != p->dpn.dval)
12759411d0f5Sralph 			werror("float conversion loses precision");
12769411d0f5Sralph #endif
12779411d0f5Sralph 		p->fpn.fval = fl;
12789411d0f5Sralph 		p->in.type = p->fn.csiz = t;
12799411d0f5Sralph 		return (clocal(p));
12809411d0f5Sralph 	}
128185b1171fSralph 
12821e9f4dc5Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
128385b1171fSralph 
128485b1171fSralph 	}
128585b1171fSralph 
128685b1171fSralph NODE *
block(o,l,r,t,d,s)128785b1171fSralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
128885b1171fSralph 
128985b1171fSralph 	register NODE *p;
129085b1171fSralph 
129185b1171fSralph 	p = talloc();
129285b1171fSralph 	p->in.op = o;
129385b1171fSralph 	p->in.left = l;
129485b1171fSralph 	p->in.right = r;
129585b1171fSralph 	p->in.type = t;
129685b1171fSralph 	p->fn.cdim = d;
129785b1171fSralph 	p->fn.csiz = s;
129885b1171fSralph 	return(p);
129985b1171fSralph 	}
130085b1171fSralph 
icons(p)130185b1171fSralph icons(p) register NODE *p; {
130285b1171fSralph 	/* if p is an integer constant, return its value */
130385b1171fSralph 	int val;
130485b1171fSralph 
130585b1171fSralph 	if( p->in.op != ICON ){
130685b1171fSralph 		uerror( "constant expected");
130785b1171fSralph 		val = 1;
130885b1171fSralph 		}
130985b1171fSralph 	else {
131085b1171fSralph 		val = p->tn.lval;
131185b1171fSralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
131285b1171fSralph 		}
131385b1171fSralph 	tfree( p );
131485b1171fSralph 	return(val);
131585b1171fSralph 	}
131685b1171fSralph 
131785b1171fSralph /* 	the intent of this table is to examine the
131885b1171fSralph 	operators, and to check them for
131985b1171fSralph 	correctness.
132085b1171fSralph 
132185b1171fSralph 	The table is searched for the op and the
132285b1171fSralph 	modified type (where this is one of the
132385b1171fSralph 	types INT (includes char and short), LONG,
132485b1171fSralph 	DOUBLE (includes FLOAT), and POINTER
132585b1171fSralph 
132685b1171fSralph 	The default action is to make the node type integer
132785b1171fSralph 
132885b1171fSralph 	The actions taken include:
132985b1171fSralph 		PUN	  check for puns
133085b1171fSralph 		CVTL	  convert the left operand
133185b1171fSralph 		CVTR	  convert the right operand
133285b1171fSralph 		TYPL	  the type is determined by the left operand
133385b1171fSralph 		TYPR	  the type is determined by the right operand
133485b1171fSralph 		TYMATCH	  force type of left and right to match, by inserting conversions
133585b1171fSralph 		PTMATCH	  like TYMATCH, but for pointers
133685b1171fSralph 		LVAL	  left operand must be lval
133785b1171fSralph 		CVTO	  convert the op
133885b1171fSralph 		NCVT	  do not convert the operands
133985b1171fSralph 		OTHER	  handled by code
134085b1171fSralph 		NCVTR	  convert the left operand, not the right...
134185b1171fSralph 
134285b1171fSralph 	*/
134385b1171fSralph 
134485b1171fSralph # define MINT 01  /* integer */
134585b1171fSralph # define MDBI 02   /* integer or double */
134685b1171fSralph # define MSTR 04  /* structure */
134785b1171fSralph # define MPTR 010  /* pointer */
134885b1171fSralph # define MPTI 020  /* pointer or integer */
134985b1171fSralph # define MENU 040 /* enumeration variable or member */
1350d0dde492Smckusick # define MVOID 0100000 /* void type */
135185b1171fSralph 
opact(p)135285b1171fSralph opact( p )  NODE *p; {
135385b1171fSralph 
135485b1171fSralph 	register mt12, mt1, mt2, o;
135585b1171fSralph 
1356d0dde492Smckusick 	mt1 = mt2 = mt12 = 0;
135785b1171fSralph 
135885b1171fSralph 	switch( optype(o=p->in.op) ){
135985b1171fSralph 
136085b1171fSralph 	case BITYPE:
1361d0dde492Smckusick 		mt2 = moditype( p->in.right->in.type );
136285b1171fSralph 	case UTYPE:
1363d0dde492Smckusick 		mt1 = moditype( p->in.left->in.type );
1364d0dde492Smckusick 		break;
136585b1171fSralph 
136685b1171fSralph 		}
136785b1171fSralph 
1368d0dde492Smckusick 	if( ((mt1 | mt2) & MVOID) &&
1369d0dde492Smckusick 	    o != COMOP &&
13704a39ba84Sdonn 	    o != COLON &&
13714a39ba84Sdonn 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
1372d0dde492Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
1373d0dde492Smckusick 		/* if lhs of RETURN is void, grammar will complain */
1374d0dde492Smckusick 		if( o != RETURN )
1375d0dde492Smckusick 			uerror( "value of void expression used" );
1376d0dde492Smckusick 		return( NCVT );
1377d0dde492Smckusick 		}
1378d0dde492Smckusick 	mt12 = mt1 & mt2;
1379d0dde492Smckusick 
138085b1171fSralph 	switch( o ){
138185b1171fSralph 
138285b1171fSralph 	case NAME :
138385b1171fSralph 	case STRING :
138485b1171fSralph 	case ICON :
138585b1171fSralph 	case FCON :
13869411d0f5Sralph 	case DCON :
138785b1171fSralph 	case CALL :
138885b1171fSralph 	case UNARY CALL:
138985b1171fSralph 	case UNARY MUL:
139085b1171fSralph 		{  return( OTHER ); }
139185b1171fSralph 	case UNARY MINUS:
139258dcaca6Sdonn 		if( mt1 & MENU ) return( 0 );
139385b1171fSralph 		if( mt1 & MDBI ) return( TYPL );
139485b1171fSralph 		break;
139585b1171fSralph 
139685b1171fSralph 	case COMPL:
139758dcaca6Sdonn 		if( mt1 & MENU ) return( 0 );
139885b1171fSralph 		if( mt1 & MINT ) return( TYPL );
139985b1171fSralph 		break;
140085b1171fSralph 
140185b1171fSralph 	case UNARY AND:
1402007a19b4Sdonn 		return( NCVT+OTHER );
140385b1171fSralph 	case INIT:
140485b1171fSralph 	case CM:
1405e3d916c2Sralph 		return( 0 );
1406e3d916c2Sralph 
140785b1171fSralph 	case NOT:
140885b1171fSralph 	case CBRANCH:
1409e3d916c2Sralph 		if( mt1 & MSTR ) break;
1410e3d916c2Sralph 		return( 0 );
1411e3d916c2Sralph 
141285b1171fSralph 	case ANDAND:
141385b1171fSralph 	case OROR:
1414e3d916c2Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
141585b1171fSralph 		return( 0 );
141685b1171fSralph 
141785b1171fSralph 	case MUL:
141885b1171fSralph 	case DIV:
141985b1171fSralph 		if( mt12 & MDBI ) return( TYMATCH );
142085b1171fSralph 		break;
142185b1171fSralph 
142285b1171fSralph 	case MOD:
142385b1171fSralph 	case AND:
142485b1171fSralph 	case OR:
142585b1171fSralph 	case ER:
142685b1171fSralph 		if( mt12 & MINT ) return( TYMATCH );
142785b1171fSralph 		break;
142885b1171fSralph 
142985b1171fSralph 	case LS:
143085b1171fSralph 	case RS:
1431007a19b4Sdonn 		if( mt12 & MINT ) return( OTHER );
143285b1171fSralph 		break;
143385b1171fSralph 
143485b1171fSralph 	case EQ:
143585b1171fSralph 	case NE:
143685b1171fSralph 	case LT:
143785b1171fSralph 	case LE:
143885b1171fSralph 	case GT:
143985b1171fSralph 	case GE:
144058dcaca6Sdonn 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
144158dcaca6Sdonn 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
144285b1171fSralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
144385b1171fSralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
144485b1171fSralph 		else break;
144585b1171fSralph 
144685b1171fSralph 	case QUEST:
144785b1171fSralph 	case COMOP:
144885b1171fSralph 		if( mt2&MENU ) return( TYPR+NCVTR );
144985b1171fSralph 		return( TYPR );
145085b1171fSralph 
145185b1171fSralph 	case STREF:
145285b1171fSralph 		return( NCVTR+OTHER );
145385b1171fSralph 
145485b1171fSralph 	case FORCE:
145585b1171fSralph 		return( TYPL );
145685b1171fSralph 
145785b1171fSralph 	case COLON:
145858dcaca6Sdonn 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
145958dcaca6Sdonn 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
146085b1171fSralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
146185b1171fSralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
146285b1171fSralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
146385b1171fSralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
14644a39ba84Sdonn 		else if( mt12 == MVOID ) return( NCVT+TYPL );
146585b1171fSralph 		break;
146685b1171fSralph 
146785b1171fSralph 	case ASSIGN:
146885b1171fSralph 	case RETURN:
146985b1171fSralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
147058dcaca6Sdonn 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
147185b1171fSralph 	case CAST:
14721b8d7ffdSdonn 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
147358dcaca6Sdonn 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
14741b8d7ffdSdonn 		else if( mt2 == MVOID &&
147578bda08aSmckusick 		        ( p->in.right->in.op == CALL ||
147678bda08aSmckusick 			  p->in.right->in.op == UNARY CALL)) break;
1477a30a413aSdonn 		else if( (mt1 & MPTR) && (mt2 & MPTI) )
1478a30a413aSdonn 			return( LVAL+PTMATCH+PUN );
147985b1171fSralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
148085b1171fSralph 		break;
148185b1171fSralph 
148285b1171fSralph 	case ASG LS:
148385b1171fSralph 	case ASG RS:
148485b1171fSralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
148585b1171fSralph 		break;
148685b1171fSralph 
148785b1171fSralph 	case ASG MUL:
148885b1171fSralph 	case ASG DIV:
148985b1171fSralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
149085b1171fSralph 		break;
149185b1171fSralph 
149285b1171fSralph 	case ASG MOD:
149385b1171fSralph 	case ASG AND:
149485b1171fSralph 	case ASG OR:
149585b1171fSralph 	case ASG ER:
149685b1171fSralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
149785b1171fSralph 		break;
149885b1171fSralph 
149985b1171fSralph 	case ASG PLUS:
150085b1171fSralph 	case ASG MINUS:
150185b1171fSralph 	case INCR:
150285b1171fSralph 	case DECR:
150385b1171fSralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
150485b1171fSralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
150585b1171fSralph 		break;
150685b1171fSralph 
150785b1171fSralph 	case MINUS:
150885b1171fSralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
150985b1171fSralph 		if( mt2 & MPTR ) break;
151085b1171fSralph 	case PLUS:
151185b1171fSralph 		if( mt12 & MDBI ) return( TYMATCH );
151285b1171fSralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
151385b1171fSralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
151485b1171fSralph 
151585b1171fSralph 		}
1516d0dde492Smckusick 	if( mt12 == MSTR )
1517d0dde492Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1518d0dde492Smckusick 	else
151985b1171fSralph 		uerror( "operands of %s have incompatible types", opst[o] );
152085b1171fSralph 	return( NCVT );
152185b1171fSralph 	}
152285b1171fSralph 
moditype(ty)152385b1171fSralph moditype( ty ) TWORD ty; {
152485b1171fSralph 
152585b1171fSralph 	switch( ty ){
152685b1171fSralph 
152785b1171fSralph 	case UNDEF:
1528d0dde492Smckusick 		return( MVOID );
152985b1171fSralph 	case ENUMTY:
153085b1171fSralph 	case MOETY:
15312a1a76a1Sdonn 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
153285b1171fSralph 
153385b1171fSralph 	case STRTY:
153485b1171fSralph 	case UNIONTY:
153585b1171fSralph 		return( MSTR );
153685b1171fSralph 
153785b1171fSralph 	case CHAR:
153885b1171fSralph 	case SHORT:
153985b1171fSralph 	case UCHAR:
154085b1171fSralph 	case USHORT:
154185b1171fSralph 		return( MINT|MPTI|MDBI );
154285b1171fSralph 	case UNSIGNED:
154385b1171fSralph 	case ULONG:
154485b1171fSralph 	case INT:
154585b1171fSralph 	case LONG:
154685b1171fSralph 		return( MINT|MDBI|MPTI );
154785b1171fSralph 	case FLOAT:
154885b1171fSralph 	case DOUBLE:
154985b1171fSralph 		return( MDBI );
155085b1171fSralph 	default:
155185b1171fSralph 		return( MPTR|MPTI );
155285b1171fSralph 
155385b1171fSralph 		}
155485b1171fSralph 	}
155585b1171fSralph 
155685b1171fSralph NODE *
doszof(p)155785b1171fSralph doszof( p )  register NODE *p; {
155885b1171fSralph 	/* do sizeof p */
155985b1171fSralph 	int i;
156085b1171fSralph 
156185b1171fSralph 	/* whatever is the meaning of this if it is a bitfield? */
156285b1171fSralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
156385b1171fSralph 
156485b1171fSralph 	tfree(p);
156585b1171fSralph 	if( i <= 0 ) werror( "sizeof returns 0" );
156685b1171fSralph 	return( bcon( i ) );
156785b1171fSralph 	}
156885b1171fSralph 
156985b1171fSralph # ifndef BUG2
eprint(p,down,a,b)157085b1171fSralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
157185b1171fSralph 	register ty;
157285b1171fSralph 
157385b1171fSralph 	*a = *b = down+1;
157485b1171fSralph 	while( down > 1 ){
157585b1171fSralph 		printf( "\t" );
157685b1171fSralph 		down -= 2;
157785b1171fSralph 		}
157885b1171fSralph 	if( down ) printf( "    " );
157985b1171fSralph 
158085b1171fSralph 	ty = optype( p->in.op );
158185b1171fSralph 
158285b1171fSralph 	printf("%o) %s, ", p, opst[p->in.op] );
158385b1171fSralph 	if( ty == LTYPE ){
158485b1171fSralph 		printf( CONFMT, p->tn.lval );
158585b1171fSralph 		printf( ", %d, ", p->tn.rval );
158685b1171fSralph 		}
158785b1171fSralph 	tprint( p->in.type );
158885b1171fSralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
158985b1171fSralph 	}
159085b1171fSralph # endif
159185b1171fSralph 
1592bd26bb5eSdonn #ifndef PRTDCON
prtdcon(p)159385b1171fSralph prtdcon( p ) register NODE *p; {
15949411d0f5Sralph 	int o = p->in.op, i;
159585b1171fSralph 
15969411d0f5Sralph 	if( o == DCON || o == FCON ){
15977b5a1073Sdonn 		(void) locctr( DATA );
15989411d0f5Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
159985b1171fSralph 		deflab( i = getlab() );
16009411d0f5Sralph 		if( o == FCON )
16019411d0f5Sralph 			fincode( p->fpn.fval, SZFLOAT );
16029411d0f5Sralph 		else
16039411d0f5Sralph 			fincode( p->dpn.dval, SZDOUBLE );
160485b1171fSralph 		p->tn.lval = 0;
160585b1171fSralph 		p->tn.rval = -i;
16069411d0f5Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
160785b1171fSralph 		p->in.op = NAME;
160885b1171fSralph 		}
160985b1171fSralph 	}
1610bd26bb5eSdonn #endif PRTDCON
161185b1171fSralph 
161285b1171fSralph 
161385b1171fSralph int edebug = 0;
ecomp(p)161485b1171fSralph ecomp( p ) register NODE *p; {
161585b1171fSralph # ifndef BUG2
161685b1171fSralph 	if( edebug ) fwalk( p, eprint, 0 );
161785b1171fSralph # endif
161885b1171fSralph 	if( !reached ){
161985b1171fSralph 		werror( "statement not reached" );
162085b1171fSralph 		reached = 1;
162185b1171fSralph 		}
162285b1171fSralph 	p = optim(p);
162385b1171fSralph 	walkf( p, prtdcon );
16247b5a1073Sdonn 	(void) locctr( PROG );
162585b1171fSralph 	ecode( p );
162685b1171fSralph 	tfree(p);
162785b1171fSralph 	}
162885b1171fSralph 
162985b1171fSralph # ifdef STDPRTREE
163085b1171fSralph # ifndef ONEPASS
163185b1171fSralph 
prtree(p)163285b1171fSralph prtree(p) register NODE *p; {
163385b1171fSralph 
163485b1171fSralph 	register struct symtab *q;
163585b1171fSralph 	register ty;
163685b1171fSralph 
163785b1171fSralph # ifdef MYPRTREE
163885b1171fSralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
163985b1171fSralph #endif
164085b1171fSralph 
164185b1171fSralph 	ty = optype(p->in.op);
164285b1171fSralph 
164385b1171fSralph 	printf( "%d\t", p->in.op );
164485b1171fSralph 
164585b1171fSralph 	if( ty == LTYPE ) {
164685b1171fSralph 		printf( CONFMT, p->tn.lval );
164785b1171fSralph 		printf( "\t" );
164885b1171fSralph 		}
164985b1171fSralph 	if( ty != BITYPE ) {
165085b1171fSralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
165185b1171fSralph 		else printf( "%d\t", p->tn.rval );
165285b1171fSralph 		}
165385b1171fSralph 
165485b1171fSralph 	printf( "%o\t", p->in.type );
165585b1171fSralph 
165685b1171fSralph 	/* handle special cases */
165785b1171fSralph 
165885b1171fSralph 	switch( p->in.op ){
165985b1171fSralph 
166085b1171fSralph 	case NAME:
166185b1171fSralph 	case ICON:
166285b1171fSralph 		/* print external name */
166385b1171fSralph 		if( p->tn.rval == NONAME ) printf( "\n" );
166485b1171fSralph 		else if( p->tn.rval >= 0 ){
166585b1171fSralph 			q = &stab[p->tn.rval];
166685b1171fSralph 			printf(  "%s\n", exname(q->sname) );
166785b1171fSralph 			}
166885b1171fSralph 		else { /* label */
166985b1171fSralph 			printf( LABFMT, -p->tn.rval );
167085b1171fSralph 			}
167185b1171fSralph 		break;
167285b1171fSralph 
167385b1171fSralph 	case STARG:
167485b1171fSralph 	case STASG:
167585b1171fSralph 	case STCALL:
167685b1171fSralph 	case UNARY STCALL:
167785b1171fSralph 		/* print out size */
167885b1171fSralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
167985b1171fSralph 
168085b1171fSralph 		/* note: p->in.left not a field... */
168185b1171fSralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
168285b1171fSralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
168385b1171fSralph 		break;
168485b1171fSralph 
168585b1171fSralph 	default:
168685b1171fSralph 		printf(  "\n" );
168785b1171fSralph 		}
168885b1171fSralph 
168985b1171fSralph 	if( ty != LTYPE ) prtree( p->in.left );
169085b1171fSralph 	if( ty == BITYPE ) prtree( p->in.right );
169185b1171fSralph 
169285b1171fSralph 	}
169385b1171fSralph 
169485b1171fSralph # else
169585b1171fSralph 
p2tree(p)169685b1171fSralph p2tree(p) register NODE *p; {
169785b1171fSralph 	register ty;
169885b1171fSralph 
169985b1171fSralph # ifdef MYP2TREE
170085b1171fSralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
170185b1171fSralph # endif
170285b1171fSralph 
170385b1171fSralph 	ty = optype(p->in.op);
170485b1171fSralph 
170585b1171fSralph 	switch( p->in.op ){
170685b1171fSralph 
170785b1171fSralph 	case NAME:
170885b1171fSralph 	case ICON:
170985b1171fSralph #ifndef FLEXNAMES
171085b1171fSralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
171185b1171fSralph #else
171285b1171fSralph 		if( p->tn.rval == NONAME ) p->in.name = "";
171385b1171fSralph #endif
171485b1171fSralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
171585b1171fSralph 			register char *cp;
171685b1171fSralph 			cp = exname( stab[p->tn.rval].sname );
171785b1171fSralph #ifndef FLEXNAMES
17187b5a1073Sdonn 			{
17197b5a1073Sdonn 				register i;
17207b5a1073Sdonn 				for( i=0; i<NCHNAM; ++i )
17217b5a1073Sdonn 					p->in.name[i] = *cp++;
17227b5a1073Sdonn 			}
172385b1171fSralph #else
172485b1171fSralph 			p->in.name = tstr(cp);
172585b1171fSralph #endif
172685b1171fSralph 			}
172785b1171fSralph #ifndef FLEXNAMES
172885b1171fSralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
172985b1171fSralph #else
173085b1171fSralph 		else {
173185b1171fSralph 			char temp[32];
173285b1171fSralph 			sprintf( temp, LABFMT, -p->tn.rval );
173385b1171fSralph 			p->in.name = tstr(temp);
173485b1171fSralph 		}
173585b1171fSralph #endif
173685b1171fSralph 		break;
173785b1171fSralph 
173885b1171fSralph 	case STARG:
173985b1171fSralph 	case STASG:
174085b1171fSralph 	case STCALL:
174185b1171fSralph 	case UNARY STCALL:
174285b1171fSralph 		/* set up size parameters */
174385b1171fSralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
174485b1171fSralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
174585b1171fSralph 		break;
174685b1171fSralph 
174785b1171fSralph 	case REG:
174885b1171fSralph 		rbusy( p->tn.rval, p->in.type );
174985b1171fSralph 	default:
175085b1171fSralph #ifndef FLEXNAMES
175185b1171fSralph 		p->in.name[0] = '\0';
175285b1171fSralph #else
175385b1171fSralph 		p->in.name = "";
175485b1171fSralph #endif
175585b1171fSralph 		}
175685b1171fSralph 
175785b1171fSralph 	p->in.rall = NOPREF;
175885b1171fSralph 
175985b1171fSralph 	if( ty != LTYPE ) p2tree( p->in.left );
176085b1171fSralph 	if( ty == BITYPE ) p2tree( p->in.right );
176185b1171fSralph 	}
176285b1171fSralph 
176385b1171fSralph # endif
176485b1171fSralph # endif
1765