xref: /csrg-svn/old/pcc/mip/trees.c (revision 43235)
117749Sralph #ifndef lint
2*43235Sbostic static char *sccsid ="@(#)trees.c	4.37 (Berkeley) 06/18/90";
317749Sralph #endif
417749Sralph 
518396Sralph # include "pass1.h"
616179Sralph 
724408Smckusick # include <setjmp.h>
824408Smckusick 
917749Sralph int bdebug = 0;
1017749Sralph int adebug = 0;
1117749Sralph extern ddebug;
1217749Sralph extern eprint();
1317749Sralph 
1416179Sralph 	    /* corrections when in violation of lint */
1516179Sralph 
1616179Sralph /*	some special actions, used in finding the type of nodes */
1716179Sralph # define NCVT 01
1816179Sralph # define PUN 02
1916179Sralph # define TYPL 04
2016179Sralph # define TYPR 010
2116179Sralph # define TYMATCH 040
2216179Sralph # define LVAL 0100
2316179Sralph # define CVTO 0200
2416179Sralph # define CVTL 0400
2516179Sralph # define CVTR 01000
2616179Sralph # define PTMATCH 02000
2716179Sralph # define OTHER 04000
2816179Sralph # define NCVTR 010000
2916179Sralph 
3017749Sralph #ifndef BUG1
printact(t,acts)3117749Sralph printact(t, acts)
3217749Sralph 	NODE *t;
3317749Sralph 	int acts;
3417749Sralph {
3517749Sralph 	static struct actions {
3617749Sralph 		int	a_bit;
3717749Sralph 		char	*a_name;
3817749Sralph 	} actions[] = {
3917749Sralph 		{ PUN,		"PUN" },
4017749Sralph 		{ CVTL,		"CVTL" },
4117749Sralph 		{ CVTR,		"CVTR" },
4217749Sralph 		{ TYPL,		"TYPL" },
4317749Sralph 		{ TYPR,		"TYPR" },
4417749Sralph 		{ TYMATCH,	"TYMATCH" },
4517749Sralph 		{ PTMATCH,	"PTMATCH" },
4617749Sralph 		{ LVAL,		"LVAL" },
4717749Sralph 		{ CVTO,		"CVTO" },
4817749Sralph 		{ NCVT,		"NCVT" },
4917749Sralph 		{ OTHER,	"OTHER" },
5017749Sralph 		{ NCVTR,	"NCVTR" },
5117749Sralph 		{ 0 }
5217749Sralph 	};
5317749Sralph 	register struct actions *p;
5417749Sralph 	char *sep = " ";
5517749Sralph 
5617749Sralph 	printf("actions");
5717749Sralph 	for (p = actions; p->a_name; p++)
5817749Sralph 		if (p->a_bit & acts) {
5917749Sralph 			printf("%s%s", sep, p->a_name);
6017749Sralph 			sep = "|";
6117749Sralph 		}
6217749Sralph 	if (!bdebug) {
6317749Sralph 		printf(" for:\n");
6417749Sralph 		fwalk(t, eprint, 0);
6517749Sralph 	} else
6617749Sralph 		putchar('\n');
6717749Sralph }
6817749Sralph #endif
6917749Sralph 
7016179Sralph /* node conventions:
7116179Sralph 
7216179Sralph 	NAME:	rval>0 is stab index for external
7316179Sralph 		rval<0 is -inlabel number
7416179Sralph 		lval is offset in bits
7516179Sralph 	ICON:	lval has the value
7616179Sralph 		rval has the STAB index, or - label number,
7716179Sralph 			if a name whose address is in the constant
7816179Sralph 		rval = NONAME means no name
7916179Sralph 	REG:	rval is reg. identification cookie
8016179Sralph 
8116179Sralph 	*/
8216179Sralph 
8316179Sralph NODE *
buildtree(o,l,r)8416179Sralph buildtree( o, l, r ) register NODE *l, *r; {
8516179Sralph 	register NODE *p, *q;
8616179Sralph 	register actions;
8716179Sralph 	register opty;
8816179Sralph 	register struct symtab *sp;
8916179Sralph 	register NODE *lr, *ll;
9017749Sralph 	NODE *fixargs();
9116179Sralph 	int i;
9216179Sralph 
9316179Sralph # ifndef BUG1
9416179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9516179Sralph # endif
9616179Sralph 	opty = optype(o);
9716179Sralph 
9816179Sralph 	/* check for constants */
9916179Sralph 
10016179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
10116179Sralph 
10216179Sralph 		switch( o ){
10316179Sralph 
10416179Sralph 		case NOT:
10516179Sralph 			if( hflag ) werror( "constant argument to NOT" );
10616179Sralph 		case UNARY MINUS:
10716179Sralph 		case COMPL:
10816179Sralph 			if( conval( l, o, l ) ) return(l);
10916179Sralph 			break;
11016179Sralph 
11116179Sralph 			}
11216179Sralph 		}
11316179Sralph 
11434253Sdonn 	else if( opty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
11516179Sralph 
11634253Sdonn 		switch( o ){
11734253Sdonn 
11834253Sdonn 		case NOT:
11934253Sdonn 			if( hflag ) werror( "constant argument to NOT" );
12034253Sdonn 			if( l->in.op == FCON )
12134253Sdonn 				l->tn.lval = l->fpn.fval == 0.0;
12234253Sdonn 			else
12334253Sdonn 				l->tn.lval = l->dpn.dval == 0.0;
12434253Sdonn 			l->tn.rval = NONAME;
12534253Sdonn 			l->in.op = ICON;
12634253Sdonn 			l->fn.csiz = l->in.type = INT;
12734253Sdonn 			l->fn.cdim = 0;
12834253Sdonn 			return(l);
12934253Sdonn 		case UNARY MINUS:
13034253Sdonn 			if( l->in.op == FCON )
13134253Sdonn 				l->fpn.fval = -l->fpn.fval;
13234253Sdonn 			else
13334253Sdonn 				l->dpn.dval = -l->dpn.dval;
13434253Sdonn 			return(l);
13534253Sdonn 			}
13617749Sralph 		}
13717749Sralph 
13816179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
13916179Sralph 		l->in.op = FREE;
14016179Sralph 		r->in.op = FREE;
14116179Sralph 		if( l->tn.lval ){
14216179Sralph 			tfree( r->in.right );
14316179Sralph 			return( r->in.left );
14416179Sralph 			}
14516179Sralph 		else {
14616179Sralph 			tfree( r->in.left );
14716179Sralph 			return( r->in.right );
14816179Sralph 			}
14916179Sralph 		}
15016179Sralph 
15116179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
15216179Sralph 
15316179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
15416179Sralph 
15516179Sralph 		switch( o ){
15616179Sralph 
15716179Sralph 		case ULT:
15816179Sralph 		case UGT:
15916179Sralph 		case ULE:
16016179Sralph 		case UGE:
16116179Sralph 		case LT:
16216179Sralph 		case GT:
16316179Sralph 		case LE:
16416179Sralph 		case GE:
16516179Sralph 		case EQ:
16616179Sralph 		case NE:
16732851Sdonn 			if( l->in.type == ENUMTY && r->in.type == ENUMTY ){
16832851Sdonn 				p = block( o, l, r, INT, 0, INT );
16932840Sdonn 				chkpun( p );
17032851Sdonn 				p->in.op = FREE;
17132851Sdonn 				}
17232840Sdonn 
17316179Sralph 		case ANDAND:
17416179Sralph 		case OROR:
17516179Sralph 		case CBRANCH:
17616179Sralph 
17716179Sralph 		ccwarn:
17816179Sralph 			if( hflag ) werror( "constant in conditional context" );
17916179Sralph 
18016179Sralph 		case PLUS:
18116179Sralph 		case MINUS:
18216179Sralph 		case MUL:
18316179Sralph 		case DIV:
18416179Sralph 		case MOD:
18516179Sralph 		case AND:
18616179Sralph 		case OR:
18716179Sralph 		case ER:
18816179Sralph 		case LS:
18916179Sralph 		case RS:
19016179Sralph 			if( conval( l, o, r ) ) {
19116179Sralph 				r->in.op = FREE;
19216179Sralph 				return(l);
19316179Sralph 				}
19416179Sralph 			break;
19516179Sralph 			}
19616179Sralph 		}
19724408Smckusick 	else if (opty == BITYPE &&
19824408Smckusick 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
19924408Smckusick 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
20024408Smckusick 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
20124408Smckusick 				extern int fpe_count;
20224408Smckusick 				extern jmp_buf gotfpe;
20316179Sralph 
20424408Smckusick 				fpe_count = 0;
20524408Smckusick 				if (setjmp(gotfpe))
20624408Smckusick 					goto treatfpe;
20717749Sralph 				if (l->in.op == ICON)
20817749Sralph 					l->dpn.dval = l->tn.lval;
20924408Smckusick 				else if (l->in.op == FCON)
21024408Smckusick 					l->dpn.dval = l->fpn.fval;
21117749Sralph 				if (r->in.op == ICON)
21217749Sralph 					r->dpn.dval = r->tn.lval;
21324408Smckusick 				else if (r->in.op == FCON)
21424408Smckusick 					r->dpn.dval = r->fpn.fval;
21517749Sralph 				switch (o) {
21617749Sralph 
21717749Sralph 				case PLUS:
21817749Sralph 					l->dpn.dval += r->dpn.dval;
21924408Smckusick 					break;
22017749Sralph 
22117749Sralph 				case MINUS:
22217749Sralph 					l->dpn.dval -= r->dpn.dval;
22324408Smckusick 					break;
22417749Sralph 
22517749Sralph 				case MUL:
22617749Sralph 					l->dpn.dval *= r->dpn.dval;
22724408Smckusick 					break;
22817749Sralph 
22917749Sralph 				case DIV:
23017749Sralph 					if (r->dpn.dval == 0)
23117749Sralph 						uerror("division by 0.");
23217749Sralph 					else
23317749Sralph 						l->dpn.dval /= r->dpn.dval;
23424408Smckusick 					break;
23524408Smckusick 					}
23624408Smckusick 			treatfpe:
23724408Smckusick 				if (fpe_count > 0) {
23824408Smckusick 					uerror("floating point exception in constant expression");
23924408Smckusick 					l->dpn.dval = 1.0; /* Fairly harmless */
24024408Smckusick 					}
24124408Smckusick 				fpe_count = -1;
24224408Smckusick 				l->in.op = DCON;
24324408Smckusick 				l->in.type = l->fn.csiz = DOUBLE;
24424408Smckusick 				r->in.op = FREE;
24524408Smckusick 				return (l);
24616179Sralph 			}
24724408Smckusick 		}
24816179Sralph 
24924408Smckusick 	/* it's real; we must make a new node */
25016179Sralph 
25116179Sralph 	p = block( o, l, r, INT, 0, INT );
25216179Sralph 
25316179Sralph 	actions = opact(p);
25417749Sralph #ifndef	BUG1
25517749Sralph 	if (adebug)
25617749Sralph 		printact(p, actions);
25717749Sralph #endif
25816179Sralph 
25916179Sralph 	if( actions&LVAL ){ /* check left descendent */
26016179Sralph 		if( notlval(p->in.left) ) {
26132849Sdonn 			uerror( "illegal lvalue operand of assignment operator" );
26216179Sralph 			}
26316179Sralph 		}
26416179Sralph 
26516179Sralph 	if( actions & NCVTR ){
26616179Sralph 		p->in.left = pconvert( p->in.left );
26716179Sralph 		}
26816179Sralph 	else if( !(actions & NCVT ) ){
26916179Sralph 		switch( opty ){
27016179Sralph 
27116179Sralph 		case BITYPE:
27216179Sralph 			p->in.right = pconvert( p->in.right );
27316179Sralph 		case UTYPE:
27416179Sralph 			p->in.left = pconvert( p->in.left );
27516179Sralph 
27616179Sralph 			}
27716179Sralph 		}
27816179Sralph 
27916179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
28016179Sralph 		chkpun(p);
28116179Sralph 		}
28216179Sralph 
28316179Sralph 	if( actions & (TYPL|TYPR) ){
28416179Sralph 
28516179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
28616179Sralph 
28716179Sralph 		p->in.type = q->in.type;
28816179Sralph 		p->fn.cdim = q->fn.cdim;
28916179Sralph 		p->fn.csiz = q->fn.csiz;
29016179Sralph 		}
29116179Sralph 
29216179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
29316179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
29416179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
29516179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
29616179Sralph 
29716179Sralph 	if( actions & OTHER ){
29816179Sralph 		l = p->in.left;
29916179Sralph 		r = p->in.right;
30016179Sralph 
30116179Sralph 		switch(o){
30216179Sralph 
30316179Sralph 		case NAME:
30416179Sralph 			sp = &stab[idname];
30516179Sralph 			if( sp->stype == UNDEF ){
30616179Sralph #ifndef FLEXNAMES
30716179Sralph 				uerror( "%.8s undefined", sp->sname );
30816179Sralph #else
30916179Sralph 				uerror( "%s undefined", sp->sname );
31016179Sralph #endif
31116179Sralph 				/* make p look reasonable */
31234253Sdonn 				p->in.type = p->fn.csiz = INT;
31334253Sdonn 				p->fn.cdim = 0;
31416179Sralph 				p->tn.rval = idname;
31516179Sralph 				p->tn.lval = 0;
31616179Sralph 				defid( p, SNULL );
31716179Sralph 				break;
31816179Sralph 				}
31916179Sralph 			p->in.type = sp->stype;
32016179Sralph 			p->fn.cdim = sp->dimoff;
32116179Sralph 			p->fn.csiz = sp->sizoff;
32216179Sralph 			p->tn.lval = 0;
32316179Sralph 			p->tn.rval = idname;
32416179Sralph 			/* special case: MOETY is really an ICON... */
32516179Sralph 			if( p->in.type == MOETY ){
32616179Sralph 				p->tn.rval = NONAME;
32716179Sralph 				p->tn.lval = sp->offset;
32816179Sralph 				p->fn.cdim = 0;
32916179Sralph 				p->in.type = ENUMTY;
33016179Sralph 				p->in.op = ICON;
33116179Sralph 				}
33216179Sralph 			break;
33316179Sralph 
33416179Sralph 		case ICON:
33516179Sralph 			p->in.type = INT;
33616179Sralph 			p->fn.cdim = 0;
33716179Sralph 			p->fn.csiz = INT;
33816179Sralph 			break;
33916179Sralph 
34016179Sralph 		case STRING:
34116179Sralph 			p->in.op = NAME;
34216179Sralph 			p->in.type = CHAR+ARY;
34316179Sralph 			p->tn.lval = 0;
34416179Sralph 			p->tn.rval = NOLAB;
34516179Sralph 			p->fn.cdim = curdim;
34616179Sralph 			p->fn.csiz = CHAR;
34716179Sralph 			break;
34816179Sralph 
34916179Sralph 		case FCON:
35016179Sralph 			p->tn.lval = 0;
35116179Sralph 			p->tn.rval = 0;
35217749Sralph 			p->in.type = FLOAT;
35317749Sralph 			p->fn.cdim = 0;
35417749Sralph 			p->fn.csiz = FLOAT;
35517749Sralph 			break;
35617749Sralph 
35717749Sralph 		case DCON:
35817749Sralph 			p->tn.lval = 0;
35917749Sralph 			p->tn.rval = 0;
36016179Sralph 			p->in.type = DOUBLE;
36116179Sralph 			p->fn.cdim = 0;
36216179Sralph 			p->fn.csiz = DOUBLE;
36316179Sralph 			break;
36416179Sralph 
36516179Sralph 		case STREF:
36616179Sralph 			/* p->x turned into *(p+offset) */
36716179Sralph 			/* rhs must be a name; check correctness */
36816179Sralph 
36916179Sralph 			i = r->tn.rval;
37016179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
37116179Sralph 				uerror( "member of structure or union required" );
37216179Sralph 				}else
37316179Sralph 			/* if this name is non-unique, find right one */
37416179Sralph 			if( stab[i].sflags & SNONUNIQ &&
37516179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
37616179Sralph 				(l->fn.csiz +1) >= 0 ){
37716179Sralph 				/* nonunique name && structure defined */
37816179Sralph 				char * memnam, * tabnam;
37916179Sralph 				int j;
38016179Sralph 				int memi;
38116179Sralph 				j=dimtab[l->fn.csiz+1];
38216179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
38316179Sralph 					tabnam = stab[memi].sname;
38416179Sralph 					memnam = stab[i].sname;
38516179Sralph # ifndef BUG1
38616179Sralph 					if( ddebug>1 ){
38716179Sralph #ifndef FLEXNAMES
38816179Sralph 						printf("member %.8s==%.8s?\n",
38916179Sralph #else
39016179Sralph 						printf("member %s==%s?\n",
39116179Sralph #endif
39216179Sralph 							memnam, tabnam);
39316179Sralph 						}
39416179Sralph # endif
39516179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
39616179Sralph #ifndef FLEXNAMES
39732851Sdonn 						register k;
39816179Sralph 						for( k=0; k<NCHNAM; ++k ){
39916179Sralph 							if(*memnam++!=*tabnam)
40016179Sralph 								goto next;
40116179Sralph 							if(!*tabnam++) break;
40216179Sralph 							}
40316179Sralph #else
40416179Sralph 						if (memnam != tabnam)
40516179Sralph 							goto next;
40616179Sralph #endif
40716179Sralph 						r->tn.rval = i = memi;
40816179Sralph 						break;
40916179Sralph 						}
41016179Sralph 					next: continue;
41116179Sralph 					}
41216179Sralph 				if( memi < 0 )
41316179Sralph #ifndef FLEXNAMES
41416179Sralph 					uerror("illegal member use: %.8s",
41516179Sralph #else
41616179Sralph 					uerror("illegal member use: %s",
41716179Sralph #endif
41816179Sralph 						stab[i].sname);
41916179Sralph 				}
42016179Sralph 			else {
42116179Sralph 				register j;
42216179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
42316179Sralph 					if( stab[i].sflags & SNONUNIQ ){
42416179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
42516179Sralph 						}
42616179Sralph 					else werror( "struct/union or struct/union pointer required" );
42716179Sralph 					}
42816179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
42916179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
43016179Sralph #ifndef FLEXNAMES
43116179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
43216179Sralph #else
43316179Sralph 					werror( "illegal member use: %s", stab[i].sname );
43416179Sralph #endif
43516179Sralph 					}
43616179Sralph 				}
43716179Sralph 
43816179Sralph 			p = stref( p );
43916179Sralph 			break;
44016179Sralph 
44116179Sralph 		case UNARY MUL:
44216179Sralph 			if( l->in.op == UNARY AND ){
44316179Sralph 				p->in.op = l->in.op = FREE;
44416179Sralph 				p = l->in.left;
44516179Sralph 				}
44616179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
44716179Sralph 			p->in.type = DECREF(l->in.type);
44816179Sralph 			p->fn.cdim = l->fn.cdim;
44916179Sralph 			p->fn.csiz = l->fn.csiz;
45016179Sralph 			break;
45116179Sralph 
45216179Sralph 		case UNARY AND:
45316179Sralph 			switch( l->in.op ){
45416179Sralph 
45516179Sralph 			case UNARY MUL:
45616179Sralph 				p->in.op = l->in.op = FREE;
45716179Sralph 				p = l->in.left;
45816179Sralph 			case NAME:
45916179Sralph 				p->in.type = INCREF( l->in.type );
46016179Sralph 				p->fn.cdim = l->fn.cdim;
46116179Sralph 				p->fn.csiz = l->fn.csiz;
46216179Sralph 				break;
46316179Sralph 
46416179Sralph 			case COMOP:
46516179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
46616179Sralph 				p->in.op = l->in.op = FREE;
46716179Sralph 				p = buildtree( COMOP, l->in.left, lr );
46816179Sralph 				break;
46916179Sralph 
47016179Sralph 			case QUEST:
47116179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
47216179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
47316179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
47416179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
47516179Sralph 				break;
47616179Sralph 
47716179Sralph # ifdef ADDROREG
47816179Sralph 			case OREG:
47916179Sralph 				/* OREG was built in clocal()
48016179Sralph 				 * for an auto or formal parameter
48116179Sralph 				 * now its address is being taken
48216179Sralph 				 * local code must unwind it
48316179Sralph 				 * back to PLUS/MINUS REG ICON
48416179Sralph 				 * according to local conventions
48516179Sralph 				 */
48616179Sralph 				{
48716179Sralph 				extern NODE * addroreg();
48816179Sralph 				p->in.op = FREE;
48916179Sralph 				p = addroreg( l );
49016179Sralph 				}
49116179Sralph 				break;
49216179Sralph 
49316179Sralph # endif
49416179Sralph 			default:
49516179Sralph 				uerror( "unacceptable operand of &" );
49616179Sralph 				break;
49716179Sralph 				}
49816179Sralph 			break;
49916179Sralph 
50016179Sralph 		case LS:
50116179Sralph 		case RS:
50234253Sdonn 			if( l->in.type == CHAR || l->in.type == SHORT )
50334253Sdonn 				p->in.type = INT;
50434253Sdonn 			else if( l->in.type == UCHAR || l->in.type == USHORT )
50534253Sdonn 				p->in.type = UNSIGNED;
50634253Sdonn 			else
50734253Sdonn 				p->in.type = l->in.type;
50816179Sralph 		case ASG LS:
50916179Sralph 		case ASG RS:
51034253Sdonn 			if( r->in.type != INT )
51134253Sdonn 				p->in.right = r = makety(r, INT, 0, INT );
51216179Sralph 			break;
51316179Sralph 
51416179Sralph 		case RETURN:
51516179Sralph 		case ASSIGN:
51616179Sralph 		case CAST:
51716179Sralph 			/* structure assignment */
51816179Sralph 			/* take the addresses of the two sides; then make an
51916179Sralph 			/* operator using STASG and
52016179Sralph 			/* the addresses of left and right */
52116179Sralph 
52216179Sralph 			{
52316179Sralph 				register TWORD t;
52416179Sralph 				register d, s;
52516179Sralph 
52616179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
52716179Sralph 
52816179Sralph 				r = buildtree( UNARY AND, r, NIL );
52916179Sralph 				t = r->in.type;
53016179Sralph 				d = r->fn.cdim;
53116179Sralph 				s = r->fn.csiz;
53216179Sralph 
53316179Sralph 				l = block( STASG, l, r, t, d, s );
53416179Sralph 
53516179Sralph 				if( o == RETURN ){
53616179Sralph 					p->in.op = FREE;
53716179Sralph 					p = l;
53816179Sralph 					break;
53916179Sralph 					}
54016179Sralph 
54116179Sralph 				p->in.op = UNARY MUL;
54216179Sralph 				p->in.left = l;
54316179Sralph 				p->in.right = NIL;
54416179Sralph 				break;
54516179Sralph 				}
54616179Sralph 		case COLON:
54716179Sralph 			/* structure colon */
54816179Sralph 
54916179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
55016179Sralph 			break;
55116179Sralph 
55216179Sralph 		case CALL:
55317749Sralph 			p->in.right = r = fixargs( p->in.right );
55416179Sralph 		case UNARY CALL:
55516179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
55616179Sralph 			p->in.type = DECREF(l->in.type);
55716179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
55816179Sralph 			p->in.type = DECREF( p->in.type );
55916179Sralph 			p->fn.cdim = l->fn.cdim;
56016179Sralph 			p->fn.csiz = l->fn.csiz;
56116179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
56216179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
56316179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
56416179Sralph 				p->in.op += (FORTCALL-CALL);
56516179Sralph 				}
56616179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
56716179Sralph 				/* function returning structure */
56816179Sralph 				/*  make function really return ptr to str., with * */
56916179Sralph 
57016179Sralph 				p->in.op += STCALL-CALL;
57116179Sralph 				p->in.type = INCREF( p->in.type );
57216179Sralph 				p = buildtree( UNARY MUL, p, NIL );
57316179Sralph 
57416179Sralph 				}
57516179Sralph 			break;
57616179Sralph 
57716179Sralph 		default:
57816179Sralph 			cerror( "other code %d", o );
57916179Sralph 			}
58016179Sralph 
58116179Sralph 		}
58216179Sralph 
58316179Sralph 	if( actions & CVTO ) p = oconvert(p);
58416179Sralph 	p = clocal(p);
58516179Sralph 
58616179Sralph # ifndef BUG1
58716179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
58816179Sralph # endif
58916179Sralph 
59016179Sralph 	return(p);
59116179Sralph 
59216179Sralph 	}
59316179Sralph 
59424408Smckusick int fpe_count = -1;
59524408Smckusick jmp_buf gotfpe;
59624408Smckusick 
597*43235Sbostic void
fpe()59824408Smckusick fpe() {
59924408Smckusick 	if (fpe_count < 0)
60024408Smckusick 		cerror("floating point exception");
60124408Smckusick 	++fpe_count;
60224408Smckusick 	longjmp(gotfpe, 1);
60324408Smckusick 	}
60424408Smckusick 
60517749Sralph /*
60617749Sralph  * Rewrite arguments in a function call.
60717749Sralph  * Structure arguments are massaged, single
60817749Sralph  * precision floating point constants are
60917749Sralph  * cast to double (to eliminate convert code).
61017749Sralph  */
61116179Sralph NODE *
fixargs(p)61217749Sralph fixargs( p ) register NODE *p;  {
61317749Sralph 	int o = p->in.op;
61416179Sralph 
61517749Sralph 	if( o == CM ){
61617749Sralph 		p->in.left = fixargs( p->in.left );
61717749Sralph 		p->in.right = fixargs( p->in.right );
61816179Sralph 		return( p );
61916179Sralph 		}
62016179Sralph 
62116179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
62216179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
62316179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
62416179Sralph 		p = clocal(p);
62516179Sralph 		}
62617749Sralph 	else if( o == FCON )
62717749Sralph 		p = makety(p, DOUBLE, 0, 0);
62816179Sralph 	return( p );
62916179Sralph 	}
63016179Sralph 
chkstr(i,j,type)63116179Sralph chkstr( i, j, type ) TWORD type; {
63216179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
63316179Sralph 	/* i has been checked to contain a MOS or MOU */
63416179Sralph 	/* j is the index in dimtab of the members... */
63516179Sralph 	int k, kk;
63616179Sralph 
63716179Sralph 	extern int ddebug;
63816179Sralph 
63916179Sralph # ifndef BUG1
64016179Sralph #ifndef FLEXNAMES
64116179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
64216179Sralph #else
64316179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
64416179Sralph #endif
64516179Sralph # endif
64616179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
64716179Sralph 	else {
64816179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
64916179Sralph 			if( kk >= SYMTSZ ){
65016179Sralph 				cerror( "gummy structure" );
65116179Sralph 				return(1);
65216179Sralph 				}
65316179Sralph 			if( kk == i ) return( 1 );
65416179Sralph 			switch( stab[kk].stype ){
65516179Sralph 
65616179Sralph 			case STRTY:
65716179Sralph 			case UNIONTY:
65816179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
65916179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
66016179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
66116179Sralph 					werror(
66216179Sralph #ifndef FLEXNAMES
66316179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
66416179Sralph #else
66516179Sralph 					"illegal member use: perhaps %s.%s?",
66616179Sralph #endif
66716179Sralph 					stab[kk].sname, stab[i].sname );
66816179Sralph 					return(1);
66916179Sralph 					}
67016179Sralph 				}
67116179Sralph 			}
67216179Sralph 		}
67316179Sralph 	return( 0 );
67416179Sralph 	}
67516179Sralph 
conval(p,o,q)67616179Sralph conval( p, o, q ) register NODE *p, *q; {
67716179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
67832842Sdonn 	/* works only on integer constants */
67932842Sdonn 	NODE *r;
68016179Sralph 	int i, u;
68116179Sralph 	CONSZ val;
68232857Sdonn 	TWORD utype;
68316179Sralph 
68416179Sralph 	val = q->tn.lval;
68516179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
68616179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
68716179Sralph 
68816179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
68916179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
69016179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
69116179Sralph 
69232857Sdonn 	/* usual type conversions -- handle casts of constants */
69332859Sdonn #define	ISLONG(t)	((t) == LONG || (t) == ULONG)
69432859Sdonn 	if (ISLONG(p->in.type) || ISLONG(q->in.type))
69532859Sdonn 		utype = u ? ULONG : LONG;
69632859Sdonn 	else
69732859Sdonn 		utype = u ? UNSIGNED : INT;
69832857Sdonn 	if( !ISPTR(p->in.type) && p->in.type != utype )
69932857Sdonn 		p = makety(p, utype, 0, (int)utype);
70032857Sdonn 	if( q->in.type != utype )
70132857Sdonn 		q = makety(q, utype, 0, (int)utype);
70232842Sdonn 
70316179Sralph 	switch( o ){
70416179Sralph 
70516179Sralph 	case PLUS:
70616179Sralph 		p->tn.lval += val;
70716179Sralph 		if( p->tn.rval == NONAME ){
70816179Sralph 			p->tn.rval = q->tn.rval;
70916179Sralph 			p->in.type = q->in.type;
71016179Sralph 			}
71116179Sralph 		break;
71216179Sralph 	case MINUS:
71316179Sralph 		p->tn.lval -= val;
71416179Sralph 		break;
71516179Sralph 	case MUL:
71632840Sdonn 		p->tn.lval *= val;
71716179Sralph 		break;
71816179Sralph 	case DIV:
71916179Sralph 		if( val == 0 ) uerror( "division by 0" );
72017749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
72116179Sralph 		else p->tn.lval /= val;
72216179Sralph 		break;
72316179Sralph 	case MOD:
72416179Sralph 		if( val == 0 ) uerror( "division by 0" );
72517749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
72616179Sralph 		else p->tn.lval %= val;
72716179Sralph 		break;
72816179Sralph 	case AND:
72916179Sralph 		p->tn.lval &= val;
73016179Sralph 		break;
73116179Sralph 	case OR:
73216179Sralph 		p->tn.lval |= val;
73316179Sralph 		break;
73416179Sralph 	case ER:
73517749Sralph 		p->tn.lval ^= val;
73616179Sralph 		break;
73716179Sralph 	case LS:
73816179Sralph 		i = val;
73916179Sralph 		p->tn.lval = p->tn.lval << i;
74016179Sralph 		break;
74116179Sralph 	case RS:
74216179Sralph 		i = val;
74317749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
74417749Sralph 		else p->tn.lval = p->tn.lval >> i;
74516179Sralph 		break;
74616179Sralph 
74716179Sralph 	case UNARY MINUS:
74816179Sralph 		p->tn.lval = - p->tn.lval;
74916179Sralph 		break;
75016179Sralph 	case COMPL:
75116179Sralph 		p->tn.lval = ~p->tn.lval;
75216179Sralph 		break;
75316179Sralph 	case NOT:
75416179Sralph 		p->tn.lval = !p->tn.lval;
75516179Sralph 		break;
75616179Sralph 	case LT:
75716179Sralph 		p->tn.lval = p->tn.lval < val;
75816179Sralph 		break;
75916179Sralph 	case LE:
76016179Sralph 		p->tn.lval = p->tn.lval <= val;
76116179Sralph 		break;
76216179Sralph 	case GT:
76316179Sralph 		p->tn.lval = p->tn.lval > val;
76416179Sralph 		break;
76516179Sralph 	case GE:
76616179Sralph 		p->tn.lval = p->tn.lval >= val;
76716179Sralph 		break;
76816179Sralph 	case ULT:
76932848Sdonn 		p->tn.lval = p->tn.lval < (unsigned) val;
77016179Sralph 		break;
77116179Sralph 	case ULE:
77232848Sdonn 		p->tn.lval = p->tn.lval <= (unsigned) val;
77316179Sralph 		break;
77432848Sdonn 	case UGT:
77532848Sdonn 		p->tn.lval = p->tn.lval > (unsigned) val;
77632848Sdonn 		break;
77732840Sdonn 	case UGE:
77832848Sdonn 		p->tn.lval = p->tn.lval >= (unsigned) val;
77932840Sdonn 		break;
78016179Sralph 	case EQ:
78116179Sralph 		p->tn.lval = p->tn.lval == val;
78216179Sralph 		break;
78316179Sralph 	case NE:
78416179Sralph 		p->tn.lval = p->tn.lval != val;
78516179Sralph 		break;
78616179Sralph 	default:
78716179Sralph 		return(0);
78816179Sralph 		}
78916179Sralph 	return(1);
79016179Sralph 	}
79116179Sralph 
chkpun(p)79216179Sralph chkpun(p) register NODE *p; {
79316179Sralph 
79416179Sralph 	/* checks p for the existance of a pun */
79516179Sralph 
79616179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
79716179Sralph 
79816179Sralph 	/* one case is when enumerations are used: this applies only to lint */
79916179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
80016179Sralph 	/* we check that this integer is in fact a constant zero... */
80116179Sralph 
80216179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
80316179Sralph 	/* this falls out, because the LHS is never 0 */
80416179Sralph 
80516179Sralph 	register NODE *q;
80616179Sralph 	register t1, t2;
80716179Sralph 	register d1, d2;
80832844Sdonn 	int ref1, ref2;
80916179Sralph 
81016179Sralph 	t1 = p->in.left->in.type;
81116179Sralph 	t2 = p->in.right->in.type;
81216179Sralph 
81316179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
81432841Sdonn 		/* rob pike says this is obnoxious...
81532840Sdonn 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
81632841Sdonn 			werror( "comparison of enums" ); */
81732841Sdonn 		if( t1==ENUMTY && t2==ENUMTY ) {
81832841Sdonn 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
81932841Sdonn 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
82032841Sdonn 			return;
82132841Sdonn 			}
82232841Sdonn 		if ( t1 == ENUMTY ) t1 = INT;
82332841Sdonn 		if ( t2 == ENUMTY ) t2 = INT;
82416179Sralph 		}
82516179Sralph 
82632844Sdonn 	ref1 = ISPTR(t1) || ISARY(t1);
82732844Sdonn 	ref2 = ISPTR(t2) || ISARY(t2);
82816179Sralph 
82932844Sdonn 	if( ref1 ^ ref2 ){
83032844Sdonn 		if( ref1 ) q = p->in.right;
83132844Sdonn 		else q = p->in.left;
83216179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
83316179Sralph 			werror( "illegal combination of pointer and integer, op %s",
83416179Sralph 				opst[p->in.op] );
83516179Sralph 			}
83616179Sralph 		}
83732844Sdonn 	else if( ref1 ){
83832843Sdonn 		if( t1 == t2 ) {
83932843Sdonn 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
84032843Sdonn 				werror( "illegal structure pointer combination" );
84116179Sralph 				return;
84216179Sralph 				}
84332843Sdonn 			d1 = p->in.left->fn.cdim;
84432843Sdonn 			d2 = p->in.right->fn.cdim;
84532843Sdonn 			for( ;; ){
84632843Sdonn 				if( ISARY(t1) ){
84732843Sdonn 					if( dimtab[d1] != dimtab[d2] ){
84832843Sdonn 						werror( "illegal array size combination" );
84932843Sdonn 						return;
85032843Sdonn 						}
85132843Sdonn 					++d1;
85232843Sdonn 					++d2;
85316179Sralph 					}
85432843Sdonn 				else if( !ISPTR(t1) ) break;
85532843Sdonn 				t1 = DECREF(t1);
85616179Sralph 				}
85716179Sralph 			}
85834253Sdonn 		else if( t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
85932843Sdonn 			werror( "illegal pointer combination" );
86016179Sralph 		}
86116179Sralph 
86216179Sralph 	}
86316179Sralph 
86416179Sralph NODE *
stref(p)86516179Sralph stref( p ) register NODE *p; {
86616179Sralph 
86716179Sralph 	TWORD t;
86816179Sralph 	int d, s, dsc, align;
86916179Sralph 	OFFSZ off;
87016179Sralph 	register struct symtab *q;
87116179Sralph 
87216179Sralph 	/* make p->x */
87316179Sralph 	/* this is also used to reference automatic variables */
87416179Sralph 
87516179Sralph 	q = &stab[p->in.right->tn.rval];
87616179Sralph 	p->in.right->in.op = FREE;
87716179Sralph 	p->in.op = FREE;
87816179Sralph 	p = pconvert( p->in.left );
87916179Sralph 
88016179Sralph 	/* make p look like ptr to x */
88116179Sralph 
88216179Sralph 	if( !ISPTR(p->in.type)){
88316179Sralph 		p->in.type = PTR+UNIONTY;
88416179Sralph 		}
88516179Sralph 
88616179Sralph 	t = INCREF( q->stype );
88716179Sralph 	d = q->dimoff;
88816179Sralph 	s = q->sizoff;
88916179Sralph 
89016179Sralph 	p = makety( p, t, d, s );
89116179Sralph 
89216179Sralph 	/* compute the offset to be added */
89316179Sralph 
89416179Sralph 	off = q->offset;
89516179Sralph 	dsc = q->sclass;
89616179Sralph 
89716179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
89816179Sralph 		align = ALINT;
89916179Sralph 		s = INT;
90016179Sralph 		off = (off/align)*align;
90116179Sralph 		}
90216179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
90316179Sralph 
90416179Sralph 	p = buildtree( UNARY MUL, p, NIL );
90516179Sralph 
90616179Sralph 	/* if field, build field info */
90716179Sralph 
90816179Sralph 	if( dsc & FIELD ){
90916179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
91016179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
91116179Sralph 		}
91216179Sralph 
91316179Sralph 	return( clocal(p) );
91416179Sralph 	}
91516179Sralph 
notlval(p)91616179Sralph notlval(p) register NODE *p; {
91716179Sralph 
91816179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
91916179Sralph 
92016179Sralph 	again:
92116179Sralph 
92216179Sralph 	switch( p->in.op ){
92316179Sralph 
92416179Sralph 	case FLD:
92516179Sralph 		p = p->in.left;
92616179Sralph 		goto again;
92716179Sralph 
92816179Sralph 	case UNARY MUL:
92916179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
93016179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
93116179Sralph 		/* and the f().a bug, given that f returns a structure */
93216179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
93316179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
93416179Sralph 	case NAME:
93516179Sralph 	case OREG:
93616179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
93716179Sralph 	case REG:
93816179Sralph 		return(0);
93916179Sralph 
94016179Sralph 	default:
94116179Sralph 		return(1);
94216179Sralph 
94316179Sralph 		}
94416179Sralph 
94516179Sralph 	}
94616179Sralph 
94716179Sralph NODE *
bcon(i)94816179Sralph bcon( i ){ /* make a constant node with value i */
94916179Sralph 	register NODE *p;
95016179Sralph 
95116179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
95216179Sralph 	p->tn.lval = i;
95316179Sralph 	p->tn.rval = NONAME;
95416179Sralph 	return( clocal(p) );
95516179Sralph 	}
95616179Sralph 
95716179Sralph NODE *
bpsize(p)95816179Sralph bpsize(p) register NODE *p; {
95916179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
96016179Sralph 	}
96116179Sralph 
96216179Sralph OFFSZ
psize(p)96316179Sralph psize( p ) NODE *p; {
96416179Sralph 	/* p is a node of type pointer; psize returns the
96516179Sralph 	   size of the thing pointed to */
96616179Sralph 
96716179Sralph 	if( !ISPTR(p->in.type) ){
96816179Sralph 		uerror( "pointer required");
96916179Sralph 		return( SZINT );
97016179Sralph 		}
97116179Sralph 	/* note: no pointers to fields */
97216179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
97316179Sralph 	}
97416179Sralph 
97516179Sralph NODE *
convert(p,f)97616179Sralph convert( p, f )  register NODE *p; {
97716179Sralph 	/*  convert an operand of p
97816179Sralph 	    f is either CVTL or CVTR
97916179Sralph 	    operand has type int, and is converted by the size of the other side
98016179Sralph 	    */
98116179Sralph 
98216179Sralph 	register NODE *q, *r;
98316179Sralph 
98416179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
98516179Sralph 
98616179Sralph 	r = block( PMCONV,
98716179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
98816179Sralph 	r = clocal(r);
98916179Sralph 	if( f == CVTL )
99016179Sralph 		p->in.left = r;
99116179Sralph 	else
99216179Sralph 		p->in.right = r;
99316179Sralph 	return(p);
99416179Sralph 
99516179Sralph 	}
99616179Sralph 
99725750Sdonn #ifndef econvert
econvert(p)99816179Sralph econvert( p ) register NODE *p; {
99916179Sralph 
100016179Sralph 	/* change enums to ints, or appropriate types */
100116179Sralph 
100216179Sralph 	register TWORD ty;
100316179Sralph 
100416179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
100516179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
100616179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
100716179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
100816179Sralph 		else ty = LONG;
100916179Sralph 		ty = ctype( ty );
101016179Sralph 		p->fn.csiz = ty;
101116179Sralph 		MODTYPE(p->in.type,ty);
101216179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
101316179Sralph 		}
101416179Sralph 	}
101525750Sdonn #endif
101616179Sralph 
101716179Sralph NODE *
pconvert(p)101816179Sralph pconvert( p ) register NODE *p; {
101916179Sralph 
102016179Sralph 	/* if p should be changed into a pointer, do so */
102116179Sralph 
102216179Sralph 	if( ISARY( p->in.type) ){
102316179Sralph 		p->in.type = DECREF( p->in.type );
102416179Sralph 		++p->fn.cdim;
102516179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
102616179Sralph 		}
102716179Sralph 	if( ISFTN( p->in.type) )
102816179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
102916179Sralph 
103016179Sralph 	return( p );
103116179Sralph 	}
103216179Sralph 
103316179Sralph NODE *
oconvert(p)103416179Sralph oconvert(p) register NODE *p; {
103516179Sralph 	/* convert the result itself: used for pointer and unsigned */
103616179Sralph 
103716179Sralph 	switch(p->in.op) {
103816179Sralph 
103916179Sralph 	case LE:
104016179Sralph 	case LT:
104116179Sralph 	case GE:
104216179Sralph 	case GT:
104316179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
104416179Sralph 	case EQ:
104516179Sralph 	case NE:
104616179Sralph 		return( p );
104716179Sralph 
104816179Sralph 	case MINUS:
104916179Sralph 		return(  clocal( block( PVCONV,
105016179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
105116179Sralph 		}
105216179Sralph 
105316179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
105416179Sralph 
105516179Sralph 	return(p);
105616179Sralph 	}
105716179Sralph 
105816179Sralph NODE *
ptmatch(p)105916179Sralph ptmatch(p)  register NODE *p; {
106016179Sralph 
106116179Sralph 	/* makes the operands of p agree; they are
106216179Sralph 	   either pointers or integers, by this time */
106316179Sralph 	/* with MINUS, the sizes must be the same */
106416179Sralph 	/* with COLON, the types must be the same */
106516179Sralph 
106616179Sralph 	TWORD t1, t2, t;
106716179Sralph 	int o, d2, d, s2, s;
106816179Sralph 
106916179Sralph 	o = p->in.op;
107016179Sralph 	t = t1 = p->in.left->in.type;
107116179Sralph 	t2 = p->in.right->in.type;
107216179Sralph 	d = p->in.left->fn.cdim;
107316179Sralph 	d2 = p->in.right->fn.cdim;
107416179Sralph 	s = p->in.left->fn.csiz;
107516179Sralph 	s2 = p->in.right->fn.csiz;
107616179Sralph 
107716179Sralph 	switch( o ){
107816179Sralph 
107916179Sralph 	case ASSIGN:
108016179Sralph 	case RETURN:
108116179Sralph 	case CAST:
108216179Sralph 		{  break; }
108316179Sralph 
108416179Sralph 	case MINUS:
108516179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
108616179Sralph 			uerror( "illegal pointer subtraction");
108716179Sralph 			}
108816179Sralph 		   break;
108916179Sralph 		   }
109016179Sralph 	case COLON:
109116179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
109216179Sralph 		   break;
109316179Sralph 		   }
109416179Sralph 	default:  /* must work harder: relationals or comparisons */
109516179Sralph 
109616179Sralph 		if( !ISPTR(t1) ){
109716179Sralph 			t = t2;
109816179Sralph 			d = d2;
109916179Sralph 			s = s2;
110016179Sralph 			break;
110116179Sralph 			}
110216179Sralph 		if( !ISPTR(t2) ){
110316179Sralph 			break;
110416179Sralph 			}
110516179Sralph 
110616179Sralph 		/* both are pointers */
110716179Sralph 		if( talign(t2,s2) < talign(t,s) ){
110816179Sralph 			t = t2;
110916179Sralph 			s = s2;
111016179Sralph 			}
111116179Sralph 		break;
111216179Sralph 		}
111316179Sralph 
111416179Sralph 	p->in.left = makety( p->in.left, t, d, s );
111516179Sralph 	p->in.right = makety( p->in.right, t, d, s );
111616179Sralph 	if( o!=MINUS && !logop(o) ){
111716179Sralph 
111816179Sralph 		p->in.type = t;
111916179Sralph 		p->fn.cdim = d;
112016179Sralph 		p->fn.csiz = s;
112116179Sralph 		}
112216179Sralph 
112316179Sralph 	return(clocal(p));
112416179Sralph 	}
112516179Sralph 
112616179Sralph int tdebug = 0;
112716179Sralph 
112816179Sralph NODE *
tymatch(p)112916179Sralph tymatch(p)  register NODE *p; {
113016179Sralph 
113116179Sralph 	/* satisfy the types of various arithmetic binary ops */
113216179Sralph 
113316179Sralph 	/* rules are:
113425750Sdonn 		if assignment, type of LHS
113516179Sralph 		if any float or doubles, make double
113616179Sralph 		if any longs, make long
113716179Sralph 		otherwise, make int
113816179Sralph 		if either operand is unsigned, the result is...
113916179Sralph 	*/
114016179Sralph 
114116179Sralph 	register TWORD t1, t2, t, tu;
114216179Sralph 	register o, u;
114316179Sralph 
114416179Sralph 	o = p->in.op;
114516179Sralph 
114616179Sralph 	t1 = p->in.left->in.type;
114716179Sralph 	t2 = p->in.right->in.type;
114816179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
114916179Sralph 		uerror("void type illegal in expression");
115016179Sralph 
115116179Sralph 	u = 0;
115216179Sralph 	if( ISUNSIGNED(t1) ){
115316179Sralph 		u = 1;
115416179Sralph 		t1 = DEUNSIGN(t1);
115516179Sralph 		}
115616179Sralph 	if( ISUNSIGNED(t2) ){
115716179Sralph 		u = 1;
115816179Sralph 		t2 = DEUNSIGN(t2);
115916179Sralph 		}
116016179Sralph 
116116179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
116216179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
116316179Sralph 
116417749Sralph #ifdef SPRECC
116517749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
116617749Sralph 		t = DOUBLE;
116717749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
116817749Sralph 		t = FLOAT;
116917749Sralph #else
117017749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
117117749Sralph 		t = DOUBLE;
117217749Sralph #endif
117316179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
117416179Sralph 	else t = INT;
117516179Sralph 
117632853Sdonn 	if( o == ASSIGN || o == CAST || o == RETURN )
117732853Sdonn 	{
117816179Sralph 		tu = p->in.left->in.type;
117916179Sralph 		t = t1;
118016179Sralph 		}
118116179Sralph 	else {
118216179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
118316179Sralph 		}
118416179Sralph 
118516179Sralph 	/* because expressions have values that are at least as wide
118616179Sralph 	   as INT or UNSIGNED, the only conversions needed
118716179Sralph 	   are those involving FLOAT/DOUBLE, and those
118816179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
118916179Sralph 
119032858Sdonn 	if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
119125750Sdonn 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
119216179Sralph 
119332858Sdonn 	if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
119432840Sdonn 		if ( tu == ENUMTY ) {/* always asgop */
119532840Sdonn 			p->in.right = makety( p->in.right, INT, 0, INT );
119632840Sdonn 			p->in.right->in.type = tu;
119732840Sdonn 			p->in.right->fn.cdim = p->in.left->fn.cdim;
119832840Sdonn 			p->in.right->fn.csiz = p->in.left->fn.csiz;
119932840Sdonn 			}
120032840Sdonn 		else
120132840Sdonn 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
120216179Sralph 
120316179Sralph 	if( asgop(o) ){
120416179Sralph 		p->in.type = p->in.left->in.type;
120516179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
120616179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
120716179Sralph 		}
120816179Sralph 	else if( !logop(o) ){
120916179Sralph 		p->in.type = tu;
121016179Sralph 		p->fn.cdim = 0;
121116179Sralph 		p->fn.csiz = t;
121216179Sralph 		}
121316179Sralph 
121416179Sralph # ifndef BUG1
121516179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
121616179Sralph # endif
121716179Sralph 
121816179Sralph 	return(p);
121916179Sralph 	}
122016179Sralph 
122116179Sralph NODE *
makety(p,t,d,s)122216179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
122316179Sralph 	/* make p into type t by inserting a conversion */
122416179Sralph 
122516179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
122616179Sralph 	if( t == p->in.type ){
122716179Sralph 		p->fn.cdim = d;
122816179Sralph 		p->fn.csiz = s;
122916179Sralph 		return( p );
123016179Sralph 		}
123116179Sralph 
123216179Sralph 	if( t & TMASK ){
123316179Sralph 		/* non-simple type */
123417228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
123516179Sralph 		}
123616179Sralph 
123716179Sralph 	if( p->in.op == ICON ){
123817749Sralph 		if (t == DOUBLE) {
123917749Sralph 			p->in.op = DCON;
124017749Sralph 			if (ISUNSIGNED(p->in.type))
124134092Sbostic 				p->dpn.dval = (U_CONSZ) p->tn.lval;
124217749Sralph 			else
124317749Sralph 				p->dpn.dval = p->tn.lval;
124417749Sralph 			p->in.type = p->fn.csiz = t;
124517749Sralph 			return (clocal(p));
124617749Sralph 		}
124717749Sralph 		if (t == FLOAT) {
124816179Sralph 			p->in.op = FCON;
124916179Sralph 			if( ISUNSIGNED(p->in.type) ){
125034092Sbostic 				p->fpn.fval = (U_CONSZ) p->tn.lval;
125116179Sralph 				}
125216179Sralph 			else {
125317749Sralph 				p->fpn.fval = p->tn.lval;
125416179Sralph 				}
125516179Sralph 
125616179Sralph 			p->in.type = p->fn.csiz = t;
125716179Sralph 			return( clocal(p) );
125816179Sralph 			}
125916179Sralph 		}
126017749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
126117749Sralph 		double db;
126216179Sralph 
126317749Sralph 		p->in.op = DCON;
126417749Sralph 		db = p->fpn.fval;
126517749Sralph 		p->dpn.dval = db;
126617749Sralph 		p->in.type = p->fn.csiz = t;
126717749Sralph 		return (clocal(p));
126817749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
126917749Sralph 		float fl;
127017749Sralph 
127117749Sralph 		p->in.op = FCON;
127217749Sralph 		fl = p->dpn.dval;
127317749Sralph #ifdef notdef
127417749Sralph 		if (fl != p->dpn.dval)
127517749Sralph 			werror("float conversion loses precision");
127617749Sralph #endif
127717749Sralph 		p->fpn.fval = fl;
127817749Sralph 		p->in.type = p->fn.csiz = t;
127917749Sralph 		return (clocal(p));
128017749Sralph 	}
128117749Sralph 
128217049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
128316179Sralph 
128416179Sralph 	}
128516179Sralph 
128616179Sralph NODE *
block(o,l,r,t,d,s)128716179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
128816179Sralph 
128916179Sralph 	register NODE *p;
129016179Sralph 
129116179Sralph 	p = talloc();
129216179Sralph 	p->in.op = o;
129316179Sralph 	p->in.left = l;
129416179Sralph 	p->in.right = r;
129516179Sralph 	p->in.type = t;
129616179Sralph 	p->fn.cdim = d;
129716179Sralph 	p->fn.csiz = s;
129816179Sralph 	return(p);
129916179Sralph 	}
130016179Sralph 
icons(p)130116179Sralph icons(p) register NODE *p; {
130216179Sralph 	/* if p is an integer constant, return its value */
130316179Sralph 	int val;
130416179Sralph 
130516179Sralph 	if( p->in.op != ICON ){
130616179Sralph 		uerror( "constant expected");
130716179Sralph 		val = 1;
130816179Sralph 		}
130916179Sralph 	else {
131016179Sralph 		val = p->tn.lval;
131116179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
131216179Sralph 		}
131316179Sralph 	tfree( p );
131416179Sralph 	return(val);
131516179Sralph 	}
131616179Sralph 
131716179Sralph /* 	the intent of this table is to examine the
131816179Sralph 	operators, and to check them for
131916179Sralph 	correctness.
132016179Sralph 
132116179Sralph 	The table is searched for the op and the
132216179Sralph 	modified type (where this is one of the
132316179Sralph 	types INT (includes char and short), LONG,
132416179Sralph 	DOUBLE (includes FLOAT), and POINTER
132516179Sralph 
132616179Sralph 	The default action is to make the node type integer
132716179Sralph 
132816179Sralph 	The actions taken include:
132916179Sralph 		PUN	  check for puns
133016179Sralph 		CVTL	  convert the left operand
133116179Sralph 		CVTR	  convert the right operand
133216179Sralph 		TYPL	  the type is determined by the left operand
133316179Sralph 		TYPR	  the type is determined by the right operand
133416179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
133516179Sralph 		PTMATCH	  like TYMATCH, but for pointers
133616179Sralph 		LVAL	  left operand must be lval
133716179Sralph 		CVTO	  convert the op
133816179Sralph 		NCVT	  do not convert the operands
133916179Sralph 		OTHER	  handled by code
134016179Sralph 		NCVTR	  convert the left operand, not the right...
134116179Sralph 
134216179Sralph 	*/
134316179Sralph 
134416179Sralph # define MINT 01  /* integer */
134516179Sralph # define MDBI 02   /* integer or double */
134616179Sralph # define MSTR 04  /* structure */
134716179Sralph # define MPTR 010  /* pointer */
134816179Sralph # define MPTI 020  /* pointer or integer */
134916179Sralph # define MENU 040 /* enumeration variable or member */
135024408Smckusick # define MVOID 0100000 /* void type */
135116179Sralph 
opact(p)135216179Sralph opact( p )  NODE *p; {
135316179Sralph 
135416179Sralph 	register mt12, mt1, mt2, o;
135516179Sralph 
135624408Smckusick 	mt1 = mt2 = mt12 = 0;
135716179Sralph 
135816179Sralph 	switch( optype(o=p->in.op) ){
135916179Sralph 
136016179Sralph 	case BITYPE:
136124408Smckusick 		mt2 = moditype( p->in.right->in.type );
136216179Sralph 	case UTYPE:
136324408Smckusick 		mt1 = moditype( p->in.left->in.type );
136424408Smckusick 		break;
136516179Sralph 
136616179Sralph 		}
136716179Sralph 
136824408Smckusick 	if( ((mt1 | mt2) & MVOID) &&
136924408Smckusick 	    o != COMOP &&
137032845Sdonn 	    o != COLON &&
137132845Sdonn 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
137224408Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
137324408Smckusick 		/* if lhs of RETURN is void, grammar will complain */
137424408Smckusick 		if( o != RETURN )
137524408Smckusick 			uerror( "value of void expression used" );
137624408Smckusick 		return( NCVT );
137724408Smckusick 		}
137824408Smckusick 	mt12 = mt1 & mt2;
137924408Smckusick 
138016179Sralph 	switch( o ){
138116179Sralph 
138216179Sralph 	case NAME :
138316179Sralph 	case STRING :
138416179Sralph 	case ICON :
138516179Sralph 	case FCON :
138617749Sralph 	case DCON :
138716179Sralph 	case CALL :
138816179Sralph 	case UNARY CALL:
138916179Sralph 	case UNARY MUL:
139016179Sralph 		{  return( OTHER ); }
139116179Sralph 	case UNARY MINUS:
139232844Sdonn 		if( mt1 & MENU ) return( 0 );
139316179Sralph 		if( mt1 & MDBI ) return( TYPL );
139416179Sralph 		break;
139516179Sralph 
139616179Sralph 	case COMPL:
139732844Sdonn 		if( mt1 & MENU ) return( 0 );
139816179Sralph 		if( mt1 & MINT ) return( TYPL );
139916179Sralph 		break;
140016179Sralph 
140116179Sralph 	case UNARY AND:
140234253Sdonn 		return( NCVT+OTHER );
140316179Sralph 	case INIT:
140416179Sralph 	case CM:
140516180Sralph 		return( 0 );
140616180Sralph 
140716179Sralph 	case NOT:
140816179Sralph 	case CBRANCH:
140916180Sralph 		if( mt1 & MSTR ) break;
141016180Sralph 		return( 0 );
141116180Sralph 
141216179Sralph 	case ANDAND:
141316179Sralph 	case OROR:
141416180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
141516179Sralph 		return( 0 );
141616179Sralph 
141716179Sralph 	case MUL:
141816179Sralph 	case DIV:
141916179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
142016179Sralph 		break;
142116179Sralph 
142216179Sralph 	case MOD:
142316179Sralph 	case AND:
142416179Sralph 	case OR:
142516179Sralph 	case ER:
142616179Sralph 		if( mt12 & MINT ) return( TYMATCH );
142716179Sralph 		break;
142816179Sralph 
142916179Sralph 	case LS:
143016179Sralph 	case RS:
143134253Sdonn 		if( mt12 & MINT ) return( OTHER );
143216179Sralph 		break;
143316179Sralph 
143416179Sralph 	case EQ:
143516179Sralph 	case NE:
143616179Sralph 	case LT:
143716179Sralph 	case LE:
143816179Sralph 	case GT:
143916179Sralph 	case GE:
144032844Sdonn 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
144132844Sdonn 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
144216179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
144316179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
144416179Sralph 		else break;
144516179Sralph 
144616179Sralph 	case QUEST:
144716179Sralph 	case COMOP:
144816179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
144916179Sralph 		return( TYPR );
145016179Sralph 
145116179Sralph 	case STREF:
145216179Sralph 		return( NCVTR+OTHER );
145316179Sralph 
145416179Sralph 	case FORCE:
145516179Sralph 		return( TYPL );
145616179Sralph 
145716179Sralph 	case COLON:
145832844Sdonn 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
145932844Sdonn 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
146016179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
146116179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
146216179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
146316179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
146432845Sdonn 		else if( mt12 == MVOID ) return( NCVT+TYPL );
146516179Sralph 		break;
146616179Sralph 
146716179Sralph 	case ASSIGN:
146816179Sralph 	case RETURN:
146916179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
147032844Sdonn 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
147116179Sralph 	case CAST:
147232846Sdonn 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
147332844Sdonn 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
147432846Sdonn 		else if( mt2 == MVOID &&
147518436Smckusick 		        ( p->in.right->in.op == CALL ||
147618436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
147732854Sdonn 		else if( (mt1 & MPTR) && (mt2 & MPTI) )
147832854Sdonn 			return( LVAL+PTMATCH+PUN );
147916179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
148016179Sralph 		break;
148116179Sralph 
148216179Sralph 	case ASG LS:
148316179Sralph 	case ASG RS:
148416179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
148516179Sralph 		break;
148616179Sralph 
148716179Sralph 	case ASG MUL:
148816179Sralph 	case ASG DIV:
148916179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
149016179Sralph 		break;
149116179Sralph 
149216179Sralph 	case ASG MOD:
149316179Sralph 	case ASG AND:
149416179Sralph 	case ASG OR:
149516179Sralph 	case ASG ER:
149616179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
149716179Sralph 		break;
149816179Sralph 
149916179Sralph 	case ASG PLUS:
150016179Sralph 	case ASG MINUS:
150116179Sralph 	case INCR:
150216179Sralph 	case DECR:
150316179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
150416179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
150516179Sralph 		break;
150616179Sralph 
150716179Sralph 	case MINUS:
150816179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
150916179Sralph 		if( mt2 & MPTR ) break;
151016179Sralph 	case PLUS:
151116179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
151216179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
151316179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
151416179Sralph 
151516179Sralph 		}
151624408Smckusick 	if( mt12 == MSTR )
151724408Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
151824408Smckusick 	else
151924408Smckusick 		uerror( "operands of %s have incompatible types", opst[o] );
152016179Sralph 	return( NCVT );
152116179Sralph 	}
152216179Sralph 
moditype(ty)152316179Sralph moditype( ty ) TWORD ty; {
152416179Sralph 
152516179Sralph 	switch( ty ){
152616179Sralph 
152716179Sralph 	case UNDEF:
152824408Smckusick 		return( MVOID );
152916179Sralph 	case ENUMTY:
153016179Sralph 	case MOETY:
153132840Sdonn 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
153216179Sralph 
153316179Sralph 	case STRTY:
153416179Sralph 	case UNIONTY:
153516179Sralph 		return( MSTR );
153616179Sralph 
153716179Sralph 	case CHAR:
153816179Sralph 	case SHORT:
153916179Sralph 	case UCHAR:
154016179Sralph 	case USHORT:
154116179Sralph 		return( MINT|MPTI|MDBI );
154216179Sralph 	case UNSIGNED:
154316179Sralph 	case ULONG:
154416179Sralph 	case INT:
154516179Sralph 	case LONG:
154616179Sralph 		return( MINT|MDBI|MPTI );
154716179Sralph 	case FLOAT:
154816179Sralph 	case DOUBLE:
154916179Sralph 		return( MDBI );
155016179Sralph 	default:
155116179Sralph 		return( MPTR|MPTI );
155216179Sralph 
155316179Sralph 		}
155416179Sralph 	}
155516179Sralph 
155616179Sralph NODE *
doszof(p)155716179Sralph doszof( p )  register NODE *p; {
155816179Sralph 	/* do sizeof p */
155916179Sralph 	int i;
156016179Sralph 
156116179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
156216179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
156316179Sralph 
156416179Sralph 	tfree(p);
156516179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
156616179Sralph 	return( bcon( i ) );
156716179Sralph 	}
156816179Sralph 
156916179Sralph # ifndef BUG2
eprint(p,down,a,b)157016179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
157116179Sralph 	register ty;
157216179Sralph 
157316179Sralph 	*a = *b = down+1;
157416179Sralph 	while( down > 1 ){
157516179Sralph 		printf( "\t" );
157616179Sralph 		down -= 2;
157716179Sralph 		}
157816179Sralph 	if( down ) printf( "    " );
157916179Sralph 
158016179Sralph 	ty = optype( p->in.op );
158116179Sralph 
158216179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
158316179Sralph 	if( ty == LTYPE ){
158416179Sralph 		printf( CONFMT, p->tn.lval );
158516179Sralph 		printf( ", %d, ", p->tn.rval );
158616179Sralph 		}
158716179Sralph 	tprint( p->in.type );
158816179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
158916179Sralph 	}
159016179Sralph # endif
159116179Sralph 
159232850Sdonn #ifndef PRTDCON
prtdcon(p)159316179Sralph prtdcon( p ) register NODE *p; {
159417749Sralph 	int o = p->in.op, i;
159516179Sralph 
159617749Sralph 	if( o == DCON || o == FCON ){
159732852Sdonn 		(void) locctr( DATA );
159817749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
159916179Sralph 		deflab( i = getlab() );
160017749Sralph 		if( o == FCON )
160117749Sralph 			fincode( p->fpn.fval, SZFLOAT );
160217749Sralph 		else
160317749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
160416179Sralph 		p->tn.lval = 0;
160516179Sralph 		p->tn.rval = -i;
160617749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
160716179Sralph 		p->in.op = NAME;
160816179Sralph 		}
160916179Sralph 	}
161032850Sdonn #endif PRTDCON
161116179Sralph 
161216179Sralph 
161316179Sralph int edebug = 0;
ecomp(p)161416179Sralph ecomp( p ) register NODE *p; {
161516179Sralph # ifndef BUG2
161616179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
161716179Sralph # endif
161816179Sralph 	if( !reached ){
161916179Sralph 		werror( "statement not reached" );
162016179Sralph 		reached = 1;
162116179Sralph 		}
162216179Sralph 	p = optim(p);
162316179Sralph 	walkf( p, prtdcon );
162432852Sdonn 	(void) locctr( PROG );
162516179Sralph 	ecode( p );
162616179Sralph 	tfree(p);
162716179Sralph 	}
162816179Sralph 
162916179Sralph # ifdef STDPRTREE
163016179Sralph # ifndef ONEPASS
163116179Sralph 
prtree(p)163216179Sralph prtree(p) register NODE *p; {
163316179Sralph 
163416179Sralph 	register struct symtab *q;
163516179Sralph 	register ty;
163616179Sralph 
163716179Sralph # ifdef MYPRTREE
163816179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
163916179Sralph #endif
164016179Sralph 
164116179Sralph 	ty = optype(p->in.op);
164216179Sralph 
164316179Sralph 	printf( "%d\t", p->in.op );
164416179Sralph 
164516179Sralph 	if( ty == LTYPE ) {
164616179Sralph 		printf( CONFMT, p->tn.lval );
164716179Sralph 		printf( "\t" );
164816179Sralph 		}
164916179Sralph 	if( ty != BITYPE ) {
165016179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
165116179Sralph 		else printf( "%d\t", p->tn.rval );
165216179Sralph 		}
165316179Sralph 
165416179Sralph 	printf( "%o\t", p->in.type );
165516179Sralph 
165616179Sralph 	/* handle special cases */
165716179Sralph 
165816179Sralph 	switch( p->in.op ){
165916179Sralph 
166016179Sralph 	case NAME:
166116179Sralph 	case ICON:
166216179Sralph 		/* print external name */
166316179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
166416179Sralph 		else if( p->tn.rval >= 0 ){
166516179Sralph 			q = &stab[p->tn.rval];
166616179Sralph 			printf(  "%s\n", exname(q->sname) );
166716179Sralph 			}
166816179Sralph 		else { /* label */
166916179Sralph 			printf( LABFMT, -p->tn.rval );
167016179Sralph 			}
167116179Sralph 		break;
167216179Sralph 
167316179Sralph 	case STARG:
167416179Sralph 	case STASG:
167516179Sralph 	case STCALL:
167616179Sralph 	case UNARY STCALL:
167716179Sralph 		/* print out size */
167816179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
167916179Sralph 
168016179Sralph 		/* note: p->in.left not a field... */
168116179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
168216179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
168316179Sralph 		break;
168416179Sralph 
168516179Sralph 	default:
168616179Sralph 		printf(  "\n" );
168716179Sralph 		}
168816179Sralph 
168916179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
169016179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
169116179Sralph 
169216179Sralph 	}
169316179Sralph 
169416179Sralph # else
169516179Sralph 
p2tree(p)169616179Sralph p2tree(p) register NODE *p; {
169716179Sralph 	register ty;
169816179Sralph 
169916179Sralph # ifdef MYP2TREE
170016179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
170116179Sralph # endif
170216179Sralph 
170316179Sralph 	ty = optype(p->in.op);
170416179Sralph 
170516179Sralph 	switch( p->in.op ){
170616179Sralph 
170716179Sralph 	case NAME:
170816179Sralph 	case ICON:
170916179Sralph #ifndef FLEXNAMES
171016179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
171116179Sralph #else
171216179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
171316179Sralph #endif
171416179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
171516179Sralph 			register char *cp;
171616179Sralph 			cp = exname( stab[p->tn.rval].sname );
171716179Sralph #ifndef FLEXNAMES
171832852Sdonn 			{
171932852Sdonn 				register i;
172032852Sdonn 				for( i=0; i<NCHNAM; ++i )
172132852Sdonn 					p->in.name[i] = *cp++;
172232852Sdonn 			}
172316179Sralph #else
172416179Sralph 			p->in.name = tstr(cp);
172516179Sralph #endif
172616179Sralph 			}
172716179Sralph #ifndef FLEXNAMES
172816179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
172916179Sralph #else
173016179Sralph 		else {
173116179Sralph 			char temp[32];
173216179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
173316179Sralph 			p->in.name = tstr(temp);
173416179Sralph 		}
173516179Sralph #endif
173616179Sralph 		break;
173716179Sralph 
173816179Sralph 	case STARG:
173916179Sralph 	case STASG:
174016179Sralph 	case STCALL:
174116179Sralph 	case UNARY STCALL:
174216179Sralph 		/* set up size parameters */
174316179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
174416179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
174516179Sralph 		break;
174616179Sralph 
174716179Sralph 	case REG:
174816179Sralph 		rbusy( p->tn.rval, p->in.type );
174916179Sralph 	default:
175016179Sralph #ifndef FLEXNAMES
175116179Sralph 		p->in.name[0] = '\0';
175216179Sralph #else
175316179Sralph 		p->in.name = "";
175416179Sralph #endif
175516179Sralph 		}
175616179Sralph 
175716179Sralph 	p->in.rall = NOPREF;
175816179Sralph 
175916179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
176016179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
176116179Sralph 	}
176216179Sralph 
176316179Sralph # endif
176416179Sralph # endif
1765