xref: /csrg-svn/old/pcc/mip/trees.c (revision 34253)
117749Sralph #ifndef lint
2*34253Sdonn static char *sccsid ="@(#)trees.c	4.36 (Berkeley) 05/11/88";
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
3117749Sralph printact(t, acts)
3217749Sralph 	NODE *t;
3317749Sralph 	int acts;
3417749Sralph {
3517749Sralph 	static struct actions {
3617749Sralph 		int	a_bit;
3717749Sralph 		char	*a_name;
3817749Sralph 	} actions[] = {
3917749Sralph 		{ PUN,		"PUN" },
4017749Sralph 		{ CVTL,		"CVTL" },
4117749Sralph 		{ CVTR,		"CVTR" },
4217749Sralph 		{ TYPL,		"TYPL" },
4317749Sralph 		{ TYPR,		"TYPR" },
4417749Sralph 		{ TYMATCH,	"TYMATCH" },
4517749Sralph 		{ PTMATCH,	"PTMATCH" },
4617749Sralph 		{ LVAL,		"LVAL" },
4717749Sralph 		{ CVTO,		"CVTO" },
4817749Sralph 		{ NCVT,		"NCVT" },
4917749Sralph 		{ OTHER,	"OTHER" },
5017749Sralph 		{ NCVTR,	"NCVTR" },
5117749Sralph 		{ 0 }
5217749Sralph 	};
5317749Sralph 	register struct actions *p;
5417749Sralph 	char *sep = " ";
5517749Sralph 
5617749Sralph 	printf("actions");
5717749Sralph 	for (p = actions; p->a_name; p++)
5817749Sralph 		if (p->a_bit & acts) {
5917749Sralph 			printf("%s%s", sep, p->a_name);
6017749Sralph 			sep = "|";
6117749Sralph 		}
6217749Sralph 	if (!bdebug) {
6317749Sralph 		printf(" for:\n");
6417749Sralph 		fwalk(t, eprint, 0);
6517749Sralph 	} else
6617749Sralph 		putchar('\n');
6717749Sralph }
6817749Sralph #endif
6917749Sralph 
7016179Sralph /* node conventions:
7116179Sralph 
7216179Sralph 	NAME:	rval>0 is stab index for external
7316179Sralph 		rval<0 is -inlabel number
7416179Sralph 		lval is offset in bits
7516179Sralph 	ICON:	lval has the value
7616179Sralph 		rval has the STAB index, or - label number,
7716179Sralph 			if a name whose address is in the constant
7816179Sralph 		rval = NONAME means no name
7916179Sralph 	REG:	rval is reg. identification cookie
8016179Sralph 
8116179Sralph 	*/
8216179Sralph 
8316179Sralph NODE *
8416179Sralph buildtree( o, l, r ) register NODE *l, *r; {
8516179Sralph 	register NODE *p, *q;
8616179Sralph 	register actions;
8716179Sralph 	register opty;
8816179Sralph 	register struct symtab *sp;
8916179Sralph 	register NODE *lr, *ll;
9017749Sralph 	NODE *fixargs();
9116179Sralph 	int i;
9216179Sralph 
9316179Sralph # ifndef BUG1
9416179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9516179Sralph # endif
9616179Sralph 	opty = optype(o);
9716179Sralph 
9816179Sralph 	/* check for constants */
9916179Sralph 
10016179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
10116179Sralph 
10216179Sralph 		switch( o ){
10316179Sralph 
10416179Sralph 		case NOT:
10516179Sralph 			if( hflag ) werror( "constant argument to NOT" );
10616179Sralph 		case UNARY MINUS:
10716179Sralph 		case COMPL:
10816179Sralph 			if( conval( l, o, l ) ) return(l);
10916179Sralph 			break;
11016179Sralph 
11116179Sralph 			}
11216179Sralph 		}
11316179Sralph 
114*34253Sdonn 	else if( opty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
11516179Sralph 
116*34253Sdonn 		switch( o ){
117*34253Sdonn 
118*34253Sdonn 		case NOT:
119*34253Sdonn 			if( hflag ) werror( "constant argument to NOT" );
120*34253Sdonn 			if( l->in.op == FCON )
121*34253Sdonn 				l->tn.lval = l->fpn.fval == 0.0;
122*34253Sdonn 			else
123*34253Sdonn 				l->tn.lval = l->dpn.dval == 0.0;
124*34253Sdonn 			l->tn.rval = NONAME;
125*34253Sdonn 			l->in.op = ICON;
126*34253Sdonn 			l->fn.csiz = l->in.type = INT;
127*34253Sdonn 			l->fn.cdim = 0;
128*34253Sdonn 			return(l);
129*34253Sdonn 		case UNARY MINUS:
130*34253Sdonn 			if( l->in.op == FCON )
131*34253Sdonn 				l->fpn.fval = -l->fpn.fval;
132*34253Sdonn 			else
133*34253Sdonn 				l->dpn.dval = -l->dpn.dval;
134*34253Sdonn 			return(l);
135*34253Sdonn 			}
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 */
312*34253Sdonn 				p->in.type = p->fn.csiz = INT;
313*34253Sdonn 				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:
502*34253Sdonn 			if( l->in.type == CHAR || l->in.type == SHORT )
503*34253Sdonn 				p->in.type = INT;
504*34253Sdonn 			else if( l->in.type == UCHAR || l->in.type == USHORT )
505*34253Sdonn 				p->in.type = UNSIGNED;
506*34253Sdonn 			else
507*34253Sdonn 				p->in.type = l->in.type;
50816179Sralph 		case ASG LS:
50916179Sralph 		case ASG RS:
510*34253Sdonn 			if( r->in.type != INT )
511*34253Sdonn 				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 
59724408Smckusick fpe() {
59824408Smckusick 	if (fpe_count < 0)
59924408Smckusick 		cerror("floating point exception");
60024408Smckusick 	++fpe_count;
60124408Smckusick 	longjmp(gotfpe, 1);
60224408Smckusick 	}
60324408Smckusick 
60417749Sralph /*
60517749Sralph  * Rewrite arguments in a function call.
60617749Sralph  * Structure arguments are massaged, single
60717749Sralph  * precision floating point constants are
60817749Sralph  * cast to double (to eliminate convert code).
60917749Sralph  */
61016179Sralph NODE *
61117749Sralph fixargs( p ) register NODE *p;  {
61217749Sralph 	int o = p->in.op;
61316179Sralph 
61417749Sralph 	if( o == CM ){
61517749Sralph 		p->in.left = fixargs( p->in.left );
61617749Sralph 		p->in.right = fixargs( p->in.right );
61716179Sralph 		return( p );
61816179Sralph 		}
61916179Sralph 
62016179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
62116179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
62216179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
62316179Sralph 		p = clocal(p);
62416179Sralph 		}
62517749Sralph 	else if( o == FCON )
62617749Sralph 		p = makety(p, DOUBLE, 0, 0);
62716179Sralph 	return( p );
62816179Sralph 	}
62916179Sralph 
63016179Sralph chkstr( i, j, type ) TWORD type; {
63116179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
63216179Sralph 	/* i has been checked to contain a MOS or MOU */
63316179Sralph 	/* j is the index in dimtab of the members... */
63416179Sralph 	int k, kk;
63516179Sralph 
63616179Sralph 	extern int ddebug;
63716179Sralph 
63816179Sralph # ifndef BUG1
63916179Sralph #ifndef FLEXNAMES
64016179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
64116179Sralph #else
64216179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
64316179Sralph #endif
64416179Sralph # endif
64516179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
64616179Sralph 	else {
64716179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
64816179Sralph 			if( kk >= SYMTSZ ){
64916179Sralph 				cerror( "gummy structure" );
65016179Sralph 				return(1);
65116179Sralph 				}
65216179Sralph 			if( kk == i ) return( 1 );
65316179Sralph 			switch( stab[kk].stype ){
65416179Sralph 
65516179Sralph 			case STRTY:
65616179Sralph 			case UNIONTY:
65716179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
65816179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
65916179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
66016179Sralph 					werror(
66116179Sralph #ifndef FLEXNAMES
66216179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
66316179Sralph #else
66416179Sralph 					"illegal member use: perhaps %s.%s?",
66516179Sralph #endif
66616179Sralph 					stab[kk].sname, stab[i].sname );
66716179Sralph 					return(1);
66816179Sralph 					}
66916179Sralph 				}
67016179Sralph 			}
67116179Sralph 		}
67216179Sralph 	return( 0 );
67316179Sralph 	}
67416179Sralph 
67516179Sralph conval( p, o, q ) register NODE *p, *q; {
67616179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
67732842Sdonn 	/* works only on integer constants */
67832842Sdonn 	NODE *r;
67916179Sralph 	int i, u;
68016179Sralph 	CONSZ val;
68132857Sdonn 	TWORD utype;
68216179Sralph 
68316179Sralph 	val = q->tn.lval;
68416179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
68516179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
68616179Sralph 
68716179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
68816179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
68916179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
69016179Sralph 
69132857Sdonn 	/* usual type conversions -- handle casts of constants */
69232859Sdonn #define	ISLONG(t)	((t) == LONG || (t) == ULONG)
69332859Sdonn 	if (ISLONG(p->in.type) || ISLONG(q->in.type))
69432859Sdonn 		utype = u ? ULONG : LONG;
69532859Sdonn 	else
69632859Sdonn 		utype = u ? UNSIGNED : INT;
69732857Sdonn 	if( !ISPTR(p->in.type) && p->in.type != utype )
69832857Sdonn 		p = makety(p, utype, 0, (int)utype);
69932857Sdonn 	if( q->in.type != utype )
70032857Sdonn 		q = makety(q, utype, 0, (int)utype);
70132842Sdonn 
70216179Sralph 	switch( o ){
70316179Sralph 
70416179Sralph 	case PLUS:
70516179Sralph 		p->tn.lval += val;
70616179Sralph 		if( p->tn.rval == NONAME ){
70716179Sralph 			p->tn.rval = q->tn.rval;
70816179Sralph 			p->in.type = q->in.type;
70916179Sralph 			}
71016179Sralph 		break;
71116179Sralph 	case MINUS:
71216179Sralph 		p->tn.lval -= val;
71316179Sralph 		break;
71416179Sralph 	case MUL:
71532840Sdonn 		p->tn.lval *= val;
71616179Sralph 		break;
71716179Sralph 	case DIV:
71816179Sralph 		if( val == 0 ) uerror( "division by 0" );
71917749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
72016179Sralph 		else p->tn.lval /= val;
72116179Sralph 		break;
72216179Sralph 	case MOD:
72316179Sralph 		if( val == 0 ) uerror( "division by 0" );
72417749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
72516179Sralph 		else p->tn.lval %= val;
72616179Sralph 		break;
72716179Sralph 	case AND:
72816179Sralph 		p->tn.lval &= val;
72916179Sralph 		break;
73016179Sralph 	case OR:
73116179Sralph 		p->tn.lval |= val;
73216179Sralph 		break;
73316179Sralph 	case ER:
73417749Sralph 		p->tn.lval ^= val;
73516179Sralph 		break;
73616179Sralph 	case LS:
73716179Sralph 		i = val;
73816179Sralph 		p->tn.lval = p->tn.lval << i;
73916179Sralph 		break;
74016179Sralph 	case RS:
74116179Sralph 		i = val;
74217749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
74317749Sralph 		else p->tn.lval = p->tn.lval >> i;
74416179Sralph 		break;
74516179Sralph 
74616179Sralph 	case UNARY MINUS:
74716179Sralph 		p->tn.lval = - p->tn.lval;
74816179Sralph 		break;
74916179Sralph 	case COMPL:
75016179Sralph 		p->tn.lval = ~p->tn.lval;
75116179Sralph 		break;
75216179Sralph 	case NOT:
75316179Sralph 		p->tn.lval = !p->tn.lval;
75416179Sralph 		break;
75516179Sralph 	case LT:
75616179Sralph 		p->tn.lval = p->tn.lval < val;
75716179Sralph 		break;
75816179Sralph 	case LE:
75916179Sralph 		p->tn.lval = p->tn.lval <= val;
76016179Sralph 		break;
76116179Sralph 	case GT:
76216179Sralph 		p->tn.lval = p->tn.lval > val;
76316179Sralph 		break;
76416179Sralph 	case GE:
76516179Sralph 		p->tn.lval = p->tn.lval >= val;
76616179Sralph 		break;
76716179Sralph 	case ULT:
76832848Sdonn 		p->tn.lval = p->tn.lval < (unsigned) val;
76916179Sralph 		break;
77016179Sralph 	case ULE:
77132848Sdonn 		p->tn.lval = p->tn.lval <= (unsigned) val;
77216179Sralph 		break;
77332848Sdonn 	case UGT:
77432848Sdonn 		p->tn.lval = p->tn.lval > (unsigned) val;
77532848Sdonn 		break;
77632840Sdonn 	case UGE:
77732848Sdonn 		p->tn.lval = p->tn.lval >= (unsigned) val;
77832840Sdonn 		break;
77916179Sralph 	case EQ:
78016179Sralph 		p->tn.lval = p->tn.lval == val;
78116179Sralph 		break;
78216179Sralph 	case NE:
78316179Sralph 		p->tn.lval = p->tn.lval != val;
78416179Sralph 		break;
78516179Sralph 	default:
78616179Sralph 		return(0);
78716179Sralph 		}
78816179Sralph 	return(1);
78916179Sralph 	}
79016179Sralph 
79116179Sralph chkpun(p) register NODE *p; {
79216179Sralph 
79316179Sralph 	/* checks p for the existance of a pun */
79416179Sralph 
79516179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
79616179Sralph 
79716179Sralph 	/* one case is when enumerations are used: this applies only to lint */
79816179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
79916179Sralph 	/* we check that this integer is in fact a constant zero... */
80016179Sralph 
80116179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
80216179Sralph 	/* this falls out, because the LHS is never 0 */
80316179Sralph 
80416179Sralph 	register NODE *q;
80516179Sralph 	register t1, t2;
80616179Sralph 	register d1, d2;
80732844Sdonn 	int ref1, ref2;
80816179Sralph 
80916179Sralph 	t1 = p->in.left->in.type;
81016179Sralph 	t2 = p->in.right->in.type;
81116179Sralph 
81216179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
81332841Sdonn 		/* rob pike says this is obnoxious...
81432840Sdonn 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
81532841Sdonn 			werror( "comparison of enums" ); */
81632841Sdonn 		if( t1==ENUMTY && t2==ENUMTY ) {
81732841Sdonn 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
81832841Sdonn 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
81932841Sdonn 			return;
82032841Sdonn 			}
82132841Sdonn 		if ( t1 == ENUMTY ) t1 = INT;
82232841Sdonn 		if ( t2 == ENUMTY ) t2 = INT;
82316179Sralph 		}
82416179Sralph 
82532844Sdonn 	ref1 = ISPTR(t1) || ISARY(t1);
82632844Sdonn 	ref2 = ISPTR(t2) || ISARY(t2);
82716179Sralph 
82832844Sdonn 	if( ref1 ^ ref2 ){
82932844Sdonn 		if( ref1 ) q = p->in.right;
83032844Sdonn 		else q = p->in.left;
83116179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
83216179Sralph 			werror( "illegal combination of pointer and integer, op %s",
83316179Sralph 				opst[p->in.op] );
83416179Sralph 			}
83516179Sralph 		}
83632844Sdonn 	else if( ref1 ){
83732843Sdonn 		if( t1 == t2 ) {
83832843Sdonn 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
83932843Sdonn 				werror( "illegal structure pointer combination" );
84016179Sralph 				return;
84116179Sralph 				}
84232843Sdonn 			d1 = p->in.left->fn.cdim;
84332843Sdonn 			d2 = p->in.right->fn.cdim;
84432843Sdonn 			for( ;; ){
84532843Sdonn 				if( ISARY(t1) ){
84632843Sdonn 					if( dimtab[d1] != dimtab[d2] ){
84732843Sdonn 						werror( "illegal array size combination" );
84832843Sdonn 						return;
84932843Sdonn 						}
85032843Sdonn 					++d1;
85132843Sdonn 					++d2;
85216179Sralph 					}
85332843Sdonn 				else if( !ISPTR(t1) ) break;
85432843Sdonn 				t1 = DECREF(t1);
85516179Sralph 				}
85616179Sralph 			}
857*34253Sdonn 		else if( t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
85832843Sdonn 			werror( "illegal pointer combination" );
85916179Sralph 		}
86016179Sralph 
86116179Sralph 	}
86216179Sralph 
86316179Sralph NODE *
86416179Sralph stref( p ) register NODE *p; {
86516179Sralph 
86616179Sralph 	TWORD t;
86716179Sralph 	int d, s, dsc, align;
86816179Sralph 	OFFSZ off;
86916179Sralph 	register struct symtab *q;
87016179Sralph 
87116179Sralph 	/* make p->x */
87216179Sralph 	/* this is also used to reference automatic variables */
87316179Sralph 
87416179Sralph 	q = &stab[p->in.right->tn.rval];
87516179Sralph 	p->in.right->in.op = FREE;
87616179Sralph 	p->in.op = FREE;
87716179Sralph 	p = pconvert( p->in.left );
87816179Sralph 
87916179Sralph 	/* make p look like ptr to x */
88016179Sralph 
88116179Sralph 	if( !ISPTR(p->in.type)){
88216179Sralph 		p->in.type = PTR+UNIONTY;
88316179Sralph 		}
88416179Sralph 
88516179Sralph 	t = INCREF( q->stype );
88616179Sralph 	d = q->dimoff;
88716179Sralph 	s = q->sizoff;
88816179Sralph 
88916179Sralph 	p = makety( p, t, d, s );
89016179Sralph 
89116179Sralph 	/* compute the offset to be added */
89216179Sralph 
89316179Sralph 	off = q->offset;
89416179Sralph 	dsc = q->sclass;
89516179Sralph 
89616179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
89716179Sralph 		align = ALINT;
89816179Sralph 		s = INT;
89916179Sralph 		off = (off/align)*align;
90016179Sralph 		}
90116179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
90216179Sralph 
90316179Sralph 	p = buildtree( UNARY MUL, p, NIL );
90416179Sralph 
90516179Sralph 	/* if field, build field info */
90616179Sralph 
90716179Sralph 	if( dsc & FIELD ){
90816179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
90916179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
91016179Sralph 		}
91116179Sralph 
91216179Sralph 	return( clocal(p) );
91316179Sralph 	}
91416179Sralph 
91516179Sralph notlval(p) register NODE *p; {
91616179Sralph 
91716179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
91816179Sralph 
91916179Sralph 	again:
92016179Sralph 
92116179Sralph 	switch( p->in.op ){
92216179Sralph 
92316179Sralph 	case FLD:
92416179Sralph 		p = p->in.left;
92516179Sralph 		goto again;
92616179Sralph 
92716179Sralph 	case UNARY MUL:
92816179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
92916179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
93016179Sralph 		/* and the f().a bug, given that f returns a structure */
93116179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
93216179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
93316179Sralph 	case NAME:
93416179Sralph 	case OREG:
93516179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
93616179Sralph 	case REG:
93716179Sralph 		return(0);
93816179Sralph 
93916179Sralph 	default:
94016179Sralph 		return(1);
94116179Sralph 
94216179Sralph 		}
94316179Sralph 
94416179Sralph 	}
94516179Sralph 
94616179Sralph NODE *
94716179Sralph bcon( i ){ /* make a constant node with value i */
94816179Sralph 	register NODE *p;
94916179Sralph 
95016179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
95116179Sralph 	p->tn.lval = i;
95216179Sralph 	p->tn.rval = NONAME;
95316179Sralph 	return( clocal(p) );
95416179Sralph 	}
95516179Sralph 
95616179Sralph NODE *
95716179Sralph bpsize(p) register NODE *p; {
95816179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
95916179Sralph 	}
96016179Sralph 
96116179Sralph OFFSZ
96216179Sralph psize( p ) NODE *p; {
96316179Sralph 	/* p is a node of type pointer; psize returns the
96416179Sralph 	   size of the thing pointed to */
96516179Sralph 
96616179Sralph 	if( !ISPTR(p->in.type) ){
96716179Sralph 		uerror( "pointer required");
96816179Sralph 		return( SZINT );
96916179Sralph 		}
97016179Sralph 	/* note: no pointers to fields */
97116179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
97216179Sralph 	}
97316179Sralph 
97416179Sralph NODE *
97516179Sralph convert( p, f )  register NODE *p; {
97616179Sralph 	/*  convert an operand of p
97716179Sralph 	    f is either CVTL or CVTR
97816179Sralph 	    operand has type int, and is converted by the size of the other side
97916179Sralph 	    */
98016179Sralph 
98116179Sralph 	register NODE *q, *r;
98216179Sralph 
98316179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
98416179Sralph 
98516179Sralph 	r = block( PMCONV,
98616179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
98716179Sralph 	r = clocal(r);
98816179Sralph 	if( f == CVTL )
98916179Sralph 		p->in.left = r;
99016179Sralph 	else
99116179Sralph 		p->in.right = r;
99216179Sralph 	return(p);
99316179Sralph 
99416179Sralph 	}
99516179Sralph 
99625750Sdonn #ifndef econvert
99716179Sralph econvert( p ) register NODE *p; {
99816179Sralph 
99916179Sralph 	/* change enums to ints, or appropriate types */
100016179Sralph 
100116179Sralph 	register TWORD ty;
100216179Sralph 
100316179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
100416179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
100516179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
100616179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
100716179Sralph 		else ty = LONG;
100816179Sralph 		ty = ctype( ty );
100916179Sralph 		p->fn.csiz = ty;
101016179Sralph 		MODTYPE(p->in.type,ty);
101116179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
101216179Sralph 		}
101316179Sralph 	}
101425750Sdonn #endif
101516179Sralph 
101616179Sralph NODE *
101716179Sralph pconvert( p ) register NODE *p; {
101816179Sralph 
101916179Sralph 	/* if p should be changed into a pointer, do so */
102016179Sralph 
102116179Sralph 	if( ISARY( p->in.type) ){
102216179Sralph 		p->in.type = DECREF( p->in.type );
102316179Sralph 		++p->fn.cdim;
102416179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
102516179Sralph 		}
102616179Sralph 	if( ISFTN( p->in.type) )
102716179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
102816179Sralph 
102916179Sralph 	return( p );
103016179Sralph 	}
103116179Sralph 
103216179Sralph NODE *
103316179Sralph oconvert(p) register NODE *p; {
103416179Sralph 	/* convert the result itself: used for pointer and unsigned */
103516179Sralph 
103616179Sralph 	switch(p->in.op) {
103716179Sralph 
103816179Sralph 	case LE:
103916179Sralph 	case LT:
104016179Sralph 	case GE:
104116179Sralph 	case GT:
104216179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
104316179Sralph 	case EQ:
104416179Sralph 	case NE:
104516179Sralph 		return( p );
104616179Sralph 
104716179Sralph 	case MINUS:
104816179Sralph 		return(  clocal( block( PVCONV,
104916179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
105016179Sralph 		}
105116179Sralph 
105216179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
105316179Sralph 
105416179Sralph 	return(p);
105516179Sralph 	}
105616179Sralph 
105716179Sralph NODE *
105816179Sralph ptmatch(p)  register NODE *p; {
105916179Sralph 
106016179Sralph 	/* makes the operands of p agree; they are
106116179Sralph 	   either pointers or integers, by this time */
106216179Sralph 	/* with MINUS, the sizes must be the same */
106316179Sralph 	/* with COLON, the types must be the same */
106416179Sralph 
106516179Sralph 	TWORD t1, t2, t;
106616179Sralph 	int o, d2, d, s2, s;
106716179Sralph 
106816179Sralph 	o = p->in.op;
106916179Sralph 	t = t1 = p->in.left->in.type;
107016179Sralph 	t2 = p->in.right->in.type;
107116179Sralph 	d = p->in.left->fn.cdim;
107216179Sralph 	d2 = p->in.right->fn.cdim;
107316179Sralph 	s = p->in.left->fn.csiz;
107416179Sralph 	s2 = p->in.right->fn.csiz;
107516179Sralph 
107616179Sralph 	switch( o ){
107716179Sralph 
107816179Sralph 	case ASSIGN:
107916179Sralph 	case RETURN:
108016179Sralph 	case CAST:
108116179Sralph 		{  break; }
108216179Sralph 
108316179Sralph 	case MINUS:
108416179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
108516179Sralph 			uerror( "illegal pointer subtraction");
108616179Sralph 			}
108716179Sralph 		   break;
108816179Sralph 		   }
108916179Sralph 	case COLON:
109016179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
109116179Sralph 		   break;
109216179Sralph 		   }
109316179Sralph 	default:  /* must work harder: relationals or comparisons */
109416179Sralph 
109516179Sralph 		if( !ISPTR(t1) ){
109616179Sralph 			t = t2;
109716179Sralph 			d = d2;
109816179Sralph 			s = s2;
109916179Sralph 			break;
110016179Sralph 			}
110116179Sralph 		if( !ISPTR(t2) ){
110216179Sralph 			break;
110316179Sralph 			}
110416179Sralph 
110516179Sralph 		/* both are pointers */
110616179Sralph 		if( talign(t2,s2) < talign(t,s) ){
110716179Sralph 			t = t2;
110816179Sralph 			s = s2;
110916179Sralph 			}
111016179Sralph 		break;
111116179Sralph 		}
111216179Sralph 
111316179Sralph 	p->in.left = makety( p->in.left, t, d, s );
111416179Sralph 	p->in.right = makety( p->in.right, t, d, s );
111516179Sralph 	if( o!=MINUS && !logop(o) ){
111616179Sralph 
111716179Sralph 		p->in.type = t;
111816179Sralph 		p->fn.cdim = d;
111916179Sralph 		p->fn.csiz = s;
112016179Sralph 		}
112116179Sralph 
112216179Sralph 	return(clocal(p));
112316179Sralph 	}
112416179Sralph 
112516179Sralph int tdebug = 0;
112616179Sralph 
112716179Sralph NODE *
112816179Sralph tymatch(p)  register NODE *p; {
112916179Sralph 
113016179Sralph 	/* satisfy the types of various arithmetic binary ops */
113116179Sralph 
113216179Sralph 	/* rules are:
113325750Sdonn 		if assignment, type of LHS
113416179Sralph 		if any float or doubles, make double
113516179Sralph 		if any longs, make long
113616179Sralph 		otherwise, make int
113716179Sralph 		if either operand is unsigned, the result is...
113816179Sralph 	*/
113916179Sralph 
114016179Sralph 	register TWORD t1, t2, t, tu;
114116179Sralph 	register o, u;
114216179Sralph 
114316179Sralph 	o = p->in.op;
114416179Sralph 
114516179Sralph 	t1 = p->in.left->in.type;
114616179Sralph 	t2 = p->in.right->in.type;
114716179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
114816179Sralph 		uerror("void type illegal in expression");
114916179Sralph 
115016179Sralph 	u = 0;
115116179Sralph 	if( ISUNSIGNED(t1) ){
115216179Sralph 		u = 1;
115316179Sralph 		t1 = DEUNSIGN(t1);
115416179Sralph 		}
115516179Sralph 	if( ISUNSIGNED(t2) ){
115616179Sralph 		u = 1;
115716179Sralph 		t2 = DEUNSIGN(t2);
115816179Sralph 		}
115916179Sralph 
116016179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
116116179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
116216179Sralph 
116317749Sralph #ifdef SPRECC
116417749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
116517749Sralph 		t = DOUBLE;
116617749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
116717749Sralph 		t = FLOAT;
116817749Sralph #else
116917749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
117017749Sralph 		t = DOUBLE;
117117749Sralph #endif
117216179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
117316179Sralph 	else t = INT;
117416179Sralph 
117532853Sdonn 	if( o == ASSIGN || o == CAST || o == RETURN )
117632853Sdonn 	{
117716179Sralph 		tu = p->in.left->in.type;
117816179Sralph 		t = t1;
117916179Sralph 		}
118016179Sralph 	else {
118116179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
118216179Sralph 		}
118316179Sralph 
118416179Sralph 	/* because expressions have values that are at least as wide
118516179Sralph 	   as INT or UNSIGNED, the only conversions needed
118616179Sralph 	   are those involving FLOAT/DOUBLE, and those
118716179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
118816179Sralph 
118932858Sdonn 	if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
119025750Sdonn 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
119116179Sralph 
119232858Sdonn 	if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
119332840Sdonn 		if ( tu == ENUMTY ) {/* always asgop */
119432840Sdonn 			p->in.right = makety( p->in.right, INT, 0, INT );
119532840Sdonn 			p->in.right->in.type = tu;
119632840Sdonn 			p->in.right->fn.cdim = p->in.left->fn.cdim;
119732840Sdonn 			p->in.right->fn.csiz = p->in.left->fn.csiz;
119832840Sdonn 			}
119932840Sdonn 		else
120032840Sdonn 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
120116179Sralph 
120216179Sralph 	if( asgop(o) ){
120316179Sralph 		p->in.type = p->in.left->in.type;
120416179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
120516179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
120616179Sralph 		}
120716179Sralph 	else if( !logop(o) ){
120816179Sralph 		p->in.type = tu;
120916179Sralph 		p->fn.cdim = 0;
121016179Sralph 		p->fn.csiz = t;
121116179Sralph 		}
121216179Sralph 
121316179Sralph # ifndef BUG1
121416179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
121516179Sralph # endif
121616179Sralph 
121716179Sralph 	return(p);
121816179Sralph 	}
121916179Sralph 
122016179Sralph NODE *
122116179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
122216179Sralph 	/* make p into type t by inserting a conversion */
122316179Sralph 
122416179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
122516179Sralph 	if( t == p->in.type ){
122616179Sralph 		p->fn.cdim = d;
122716179Sralph 		p->fn.csiz = s;
122816179Sralph 		return( p );
122916179Sralph 		}
123016179Sralph 
123116179Sralph 	if( t & TMASK ){
123216179Sralph 		/* non-simple type */
123317228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
123416179Sralph 		}
123516179Sralph 
123616179Sralph 	if( p->in.op == ICON ){
123717749Sralph 		if (t == DOUBLE) {
123817749Sralph 			p->in.op = DCON;
123917749Sralph 			if (ISUNSIGNED(p->in.type))
124034092Sbostic 				p->dpn.dval = (U_CONSZ) p->tn.lval;
124117749Sralph 			else
124217749Sralph 				p->dpn.dval = p->tn.lval;
124317749Sralph 			p->in.type = p->fn.csiz = t;
124417749Sralph 			return (clocal(p));
124517749Sralph 		}
124617749Sralph 		if (t == FLOAT) {
124716179Sralph 			p->in.op = FCON;
124816179Sralph 			if( ISUNSIGNED(p->in.type) ){
124934092Sbostic 				p->fpn.fval = (U_CONSZ) p->tn.lval;
125016179Sralph 				}
125116179Sralph 			else {
125217749Sralph 				p->fpn.fval = p->tn.lval;
125316179Sralph 				}
125416179Sralph 
125516179Sralph 			p->in.type = p->fn.csiz = t;
125616179Sralph 			return( clocal(p) );
125716179Sralph 			}
125816179Sralph 		}
125917749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
126017749Sralph 		double db;
126116179Sralph 
126217749Sralph 		p->in.op = DCON;
126317749Sralph 		db = p->fpn.fval;
126417749Sralph 		p->dpn.dval = db;
126517749Sralph 		p->in.type = p->fn.csiz = t;
126617749Sralph 		return (clocal(p));
126717749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
126817749Sralph 		float fl;
126917749Sralph 
127017749Sralph 		p->in.op = FCON;
127117749Sralph 		fl = p->dpn.dval;
127217749Sralph #ifdef notdef
127317749Sralph 		if (fl != p->dpn.dval)
127417749Sralph 			werror("float conversion loses precision");
127517749Sralph #endif
127617749Sralph 		p->fpn.fval = fl;
127717749Sralph 		p->in.type = p->fn.csiz = t;
127817749Sralph 		return (clocal(p));
127917749Sralph 	}
128017749Sralph 
128117049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
128216179Sralph 
128316179Sralph 	}
128416179Sralph 
128516179Sralph NODE *
128616179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
128716179Sralph 
128816179Sralph 	register NODE *p;
128916179Sralph 
129016179Sralph 	p = talloc();
129116179Sralph 	p->in.op = o;
129216179Sralph 	p->in.left = l;
129316179Sralph 	p->in.right = r;
129416179Sralph 	p->in.type = t;
129516179Sralph 	p->fn.cdim = d;
129616179Sralph 	p->fn.csiz = s;
129716179Sralph 	return(p);
129816179Sralph 	}
129916179Sralph 
130016179Sralph icons(p) register NODE *p; {
130116179Sralph 	/* if p is an integer constant, return its value */
130216179Sralph 	int val;
130316179Sralph 
130416179Sralph 	if( p->in.op != ICON ){
130516179Sralph 		uerror( "constant expected");
130616179Sralph 		val = 1;
130716179Sralph 		}
130816179Sralph 	else {
130916179Sralph 		val = p->tn.lval;
131016179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
131116179Sralph 		}
131216179Sralph 	tfree( p );
131316179Sralph 	return(val);
131416179Sralph 	}
131516179Sralph 
131616179Sralph /* 	the intent of this table is to examine the
131716179Sralph 	operators, and to check them for
131816179Sralph 	correctness.
131916179Sralph 
132016179Sralph 	The table is searched for the op and the
132116179Sralph 	modified type (where this is one of the
132216179Sralph 	types INT (includes char and short), LONG,
132316179Sralph 	DOUBLE (includes FLOAT), and POINTER
132416179Sralph 
132516179Sralph 	The default action is to make the node type integer
132616179Sralph 
132716179Sralph 	The actions taken include:
132816179Sralph 		PUN	  check for puns
132916179Sralph 		CVTL	  convert the left operand
133016179Sralph 		CVTR	  convert the right operand
133116179Sralph 		TYPL	  the type is determined by the left operand
133216179Sralph 		TYPR	  the type is determined by the right operand
133316179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
133416179Sralph 		PTMATCH	  like TYMATCH, but for pointers
133516179Sralph 		LVAL	  left operand must be lval
133616179Sralph 		CVTO	  convert the op
133716179Sralph 		NCVT	  do not convert the operands
133816179Sralph 		OTHER	  handled by code
133916179Sralph 		NCVTR	  convert the left operand, not the right...
134016179Sralph 
134116179Sralph 	*/
134216179Sralph 
134316179Sralph # define MINT 01  /* integer */
134416179Sralph # define MDBI 02   /* integer or double */
134516179Sralph # define MSTR 04  /* structure */
134616179Sralph # define MPTR 010  /* pointer */
134716179Sralph # define MPTI 020  /* pointer or integer */
134816179Sralph # define MENU 040 /* enumeration variable or member */
134924408Smckusick # define MVOID 0100000 /* void type */
135016179Sralph 
135116179Sralph opact( p )  NODE *p; {
135216179Sralph 
135316179Sralph 	register mt12, mt1, mt2, o;
135416179Sralph 
135524408Smckusick 	mt1 = mt2 = mt12 = 0;
135616179Sralph 
135716179Sralph 	switch( optype(o=p->in.op) ){
135816179Sralph 
135916179Sralph 	case BITYPE:
136024408Smckusick 		mt2 = moditype( p->in.right->in.type );
136116179Sralph 	case UTYPE:
136224408Smckusick 		mt1 = moditype( p->in.left->in.type );
136324408Smckusick 		break;
136416179Sralph 
136516179Sralph 		}
136616179Sralph 
136724408Smckusick 	if( ((mt1 | mt2) & MVOID) &&
136824408Smckusick 	    o != COMOP &&
136932845Sdonn 	    o != COLON &&
137032845Sdonn 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
137124408Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
137224408Smckusick 		/* if lhs of RETURN is void, grammar will complain */
137324408Smckusick 		if( o != RETURN )
137424408Smckusick 			uerror( "value of void expression used" );
137524408Smckusick 		return( NCVT );
137624408Smckusick 		}
137724408Smckusick 	mt12 = mt1 & mt2;
137824408Smckusick 
137916179Sralph 	switch( o ){
138016179Sralph 
138116179Sralph 	case NAME :
138216179Sralph 	case STRING :
138316179Sralph 	case ICON :
138416179Sralph 	case FCON :
138517749Sralph 	case DCON :
138616179Sralph 	case CALL :
138716179Sralph 	case UNARY CALL:
138816179Sralph 	case UNARY MUL:
138916179Sralph 		{  return( OTHER ); }
139016179Sralph 	case UNARY MINUS:
139132844Sdonn 		if( mt1 & MENU ) return( 0 );
139216179Sralph 		if( mt1 & MDBI ) return( TYPL );
139316179Sralph 		break;
139416179Sralph 
139516179Sralph 	case COMPL:
139632844Sdonn 		if( mt1 & MENU ) return( 0 );
139716179Sralph 		if( mt1 & MINT ) return( TYPL );
139816179Sralph 		break;
139916179Sralph 
140016179Sralph 	case UNARY AND:
1401*34253Sdonn 		return( NCVT+OTHER );
140216179Sralph 	case INIT:
140316179Sralph 	case CM:
140416180Sralph 		return( 0 );
140516180Sralph 
140616179Sralph 	case NOT:
140716179Sralph 	case CBRANCH:
140816180Sralph 		if( mt1 & MSTR ) break;
140916180Sralph 		return( 0 );
141016180Sralph 
141116179Sralph 	case ANDAND:
141216179Sralph 	case OROR:
141316180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
141416179Sralph 		return( 0 );
141516179Sralph 
141616179Sralph 	case MUL:
141716179Sralph 	case DIV:
141816179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
141916179Sralph 		break;
142016179Sralph 
142116179Sralph 	case MOD:
142216179Sralph 	case AND:
142316179Sralph 	case OR:
142416179Sralph 	case ER:
142516179Sralph 		if( mt12 & MINT ) return( TYMATCH );
142616179Sralph 		break;
142716179Sralph 
142816179Sralph 	case LS:
142916179Sralph 	case RS:
1430*34253Sdonn 		if( mt12 & MINT ) return( OTHER );
143116179Sralph 		break;
143216179Sralph 
143316179Sralph 	case EQ:
143416179Sralph 	case NE:
143516179Sralph 	case LT:
143616179Sralph 	case LE:
143716179Sralph 	case GT:
143816179Sralph 	case GE:
143932844Sdonn 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
144032844Sdonn 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
144116179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
144216179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
144316179Sralph 		else break;
144416179Sralph 
144516179Sralph 	case QUEST:
144616179Sralph 	case COMOP:
144716179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
144816179Sralph 		return( TYPR );
144916179Sralph 
145016179Sralph 	case STREF:
145116179Sralph 		return( NCVTR+OTHER );
145216179Sralph 
145316179Sralph 	case FORCE:
145416179Sralph 		return( TYPL );
145516179Sralph 
145616179Sralph 	case COLON:
145732844Sdonn 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
145832844Sdonn 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
145916179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
146016179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
146116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
146216179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
146332845Sdonn 		else if( mt12 == MVOID ) return( NCVT+TYPL );
146416179Sralph 		break;
146516179Sralph 
146616179Sralph 	case ASSIGN:
146716179Sralph 	case RETURN:
146816179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
146932844Sdonn 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
147016179Sralph 	case CAST:
147132846Sdonn 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
147232844Sdonn 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
147332846Sdonn 		else if( mt2 == MVOID &&
147418436Smckusick 		        ( p->in.right->in.op == CALL ||
147518436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
147632854Sdonn 		else if( (mt1 & MPTR) && (mt2 & MPTI) )
147732854Sdonn 			return( LVAL+PTMATCH+PUN );
147816179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
147916179Sralph 		break;
148016179Sralph 
148116179Sralph 	case ASG LS:
148216179Sralph 	case ASG RS:
148316179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
148416179Sralph 		break;
148516179Sralph 
148616179Sralph 	case ASG MUL:
148716179Sralph 	case ASG DIV:
148816179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
148916179Sralph 		break;
149016179Sralph 
149116179Sralph 	case ASG MOD:
149216179Sralph 	case ASG AND:
149316179Sralph 	case ASG OR:
149416179Sralph 	case ASG ER:
149516179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
149616179Sralph 		break;
149716179Sralph 
149816179Sralph 	case ASG PLUS:
149916179Sralph 	case ASG MINUS:
150016179Sralph 	case INCR:
150116179Sralph 	case DECR:
150216179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
150316179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
150416179Sralph 		break;
150516179Sralph 
150616179Sralph 	case MINUS:
150716179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
150816179Sralph 		if( mt2 & MPTR ) break;
150916179Sralph 	case PLUS:
151016179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
151116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
151216179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
151316179Sralph 
151416179Sralph 		}
151524408Smckusick 	if( mt12 == MSTR )
151624408Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
151724408Smckusick 	else
151824408Smckusick 		uerror( "operands of %s have incompatible types", opst[o] );
151916179Sralph 	return( NCVT );
152016179Sralph 	}
152116179Sralph 
152216179Sralph moditype( ty ) TWORD ty; {
152316179Sralph 
152416179Sralph 	switch( ty ){
152516179Sralph 
152616179Sralph 	case UNDEF:
152724408Smckusick 		return( MVOID );
152816179Sralph 	case ENUMTY:
152916179Sralph 	case MOETY:
153032840Sdonn 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
153116179Sralph 
153216179Sralph 	case STRTY:
153316179Sralph 	case UNIONTY:
153416179Sralph 		return( MSTR );
153516179Sralph 
153616179Sralph 	case CHAR:
153716179Sralph 	case SHORT:
153816179Sralph 	case UCHAR:
153916179Sralph 	case USHORT:
154016179Sralph 		return( MINT|MPTI|MDBI );
154116179Sralph 	case UNSIGNED:
154216179Sralph 	case ULONG:
154316179Sralph 	case INT:
154416179Sralph 	case LONG:
154516179Sralph 		return( MINT|MDBI|MPTI );
154616179Sralph 	case FLOAT:
154716179Sralph 	case DOUBLE:
154816179Sralph 		return( MDBI );
154916179Sralph 	default:
155016179Sralph 		return( MPTR|MPTI );
155116179Sralph 
155216179Sralph 		}
155316179Sralph 	}
155416179Sralph 
155516179Sralph NODE *
155616179Sralph doszof( p )  register NODE *p; {
155716179Sralph 	/* do sizeof p */
155816179Sralph 	int i;
155916179Sralph 
156016179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
156116179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
156216179Sralph 
156316179Sralph 	tfree(p);
156416179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
156516179Sralph 	return( bcon( i ) );
156616179Sralph 	}
156716179Sralph 
156816179Sralph # ifndef BUG2
156916179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
157016179Sralph 	register ty;
157116179Sralph 
157216179Sralph 	*a = *b = down+1;
157316179Sralph 	while( down > 1 ){
157416179Sralph 		printf( "\t" );
157516179Sralph 		down -= 2;
157616179Sralph 		}
157716179Sralph 	if( down ) printf( "    " );
157816179Sralph 
157916179Sralph 	ty = optype( p->in.op );
158016179Sralph 
158116179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
158216179Sralph 	if( ty == LTYPE ){
158316179Sralph 		printf( CONFMT, p->tn.lval );
158416179Sralph 		printf( ", %d, ", p->tn.rval );
158516179Sralph 		}
158616179Sralph 	tprint( p->in.type );
158716179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
158816179Sralph 	}
158916179Sralph # endif
159016179Sralph 
159132850Sdonn #ifndef PRTDCON
159216179Sralph prtdcon( p ) register NODE *p; {
159317749Sralph 	int o = p->in.op, i;
159416179Sralph 
159517749Sralph 	if( o == DCON || o == FCON ){
159632852Sdonn 		(void) locctr( DATA );
159717749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
159816179Sralph 		deflab( i = getlab() );
159917749Sralph 		if( o == FCON )
160017749Sralph 			fincode( p->fpn.fval, SZFLOAT );
160117749Sralph 		else
160217749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
160316179Sralph 		p->tn.lval = 0;
160416179Sralph 		p->tn.rval = -i;
160517749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
160616179Sralph 		p->in.op = NAME;
160716179Sralph 		}
160816179Sralph 	}
160932850Sdonn #endif PRTDCON
161016179Sralph 
161116179Sralph 
161216179Sralph int edebug = 0;
161316179Sralph ecomp( p ) register NODE *p; {
161416179Sralph # ifndef BUG2
161516179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
161616179Sralph # endif
161716179Sralph 	if( !reached ){
161816179Sralph 		werror( "statement not reached" );
161916179Sralph 		reached = 1;
162016179Sralph 		}
162116179Sralph 	p = optim(p);
162216179Sralph 	walkf( p, prtdcon );
162332852Sdonn 	(void) locctr( PROG );
162416179Sralph 	ecode( p );
162516179Sralph 	tfree(p);
162616179Sralph 	}
162716179Sralph 
162816179Sralph # ifdef STDPRTREE
162916179Sralph # ifndef ONEPASS
163016179Sralph 
163116179Sralph prtree(p) register NODE *p; {
163216179Sralph 
163316179Sralph 	register struct symtab *q;
163416179Sralph 	register ty;
163516179Sralph 
163616179Sralph # ifdef MYPRTREE
163716179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
163816179Sralph #endif
163916179Sralph 
164016179Sralph 	ty = optype(p->in.op);
164116179Sralph 
164216179Sralph 	printf( "%d\t", p->in.op );
164316179Sralph 
164416179Sralph 	if( ty == LTYPE ) {
164516179Sralph 		printf( CONFMT, p->tn.lval );
164616179Sralph 		printf( "\t" );
164716179Sralph 		}
164816179Sralph 	if( ty != BITYPE ) {
164916179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
165016179Sralph 		else printf( "%d\t", p->tn.rval );
165116179Sralph 		}
165216179Sralph 
165316179Sralph 	printf( "%o\t", p->in.type );
165416179Sralph 
165516179Sralph 	/* handle special cases */
165616179Sralph 
165716179Sralph 	switch( p->in.op ){
165816179Sralph 
165916179Sralph 	case NAME:
166016179Sralph 	case ICON:
166116179Sralph 		/* print external name */
166216179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
166316179Sralph 		else if( p->tn.rval >= 0 ){
166416179Sralph 			q = &stab[p->tn.rval];
166516179Sralph 			printf(  "%s\n", exname(q->sname) );
166616179Sralph 			}
166716179Sralph 		else { /* label */
166816179Sralph 			printf( LABFMT, -p->tn.rval );
166916179Sralph 			}
167016179Sralph 		break;
167116179Sralph 
167216179Sralph 	case STARG:
167316179Sralph 	case STASG:
167416179Sralph 	case STCALL:
167516179Sralph 	case UNARY STCALL:
167616179Sralph 		/* print out size */
167716179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
167816179Sralph 
167916179Sralph 		/* note: p->in.left not a field... */
168016179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
168116179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
168216179Sralph 		break;
168316179Sralph 
168416179Sralph 	default:
168516179Sralph 		printf(  "\n" );
168616179Sralph 		}
168716179Sralph 
168816179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
168916179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
169016179Sralph 
169116179Sralph 	}
169216179Sralph 
169316179Sralph # else
169416179Sralph 
169516179Sralph p2tree(p) register NODE *p; {
169616179Sralph 	register ty;
169716179Sralph 
169816179Sralph # ifdef MYP2TREE
169916179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
170016179Sralph # endif
170116179Sralph 
170216179Sralph 	ty = optype(p->in.op);
170316179Sralph 
170416179Sralph 	switch( p->in.op ){
170516179Sralph 
170616179Sralph 	case NAME:
170716179Sralph 	case ICON:
170816179Sralph #ifndef FLEXNAMES
170916179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
171016179Sralph #else
171116179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
171216179Sralph #endif
171316179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
171416179Sralph 			register char *cp;
171516179Sralph 			cp = exname( stab[p->tn.rval].sname );
171616179Sralph #ifndef FLEXNAMES
171732852Sdonn 			{
171832852Sdonn 				register i;
171932852Sdonn 				for( i=0; i<NCHNAM; ++i )
172032852Sdonn 					p->in.name[i] = *cp++;
172132852Sdonn 			}
172216179Sralph #else
172316179Sralph 			p->in.name = tstr(cp);
172416179Sralph #endif
172516179Sralph 			}
172616179Sralph #ifndef FLEXNAMES
172716179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
172816179Sralph #else
172916179Sralph 		else {
173016179Sralph 			char temp[32];
173116179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
173216179Sralph 			p->in.name = tstr(temp);
173316179Sralph 		}
173416179Sralph #endif
173516179Sralph 		break;
173616179Sralph 
173716179Sralph 	case STARG:
173816179Sralph 	case STASG:
173916179Sralph 	case STCALL:
174016179Sralph 	case UNARY STCALL:
174116179Sralph 		/* set up size parameters */
174216179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
174316179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
174416179Sralph 		break;
174516179Sralph 
174616179Sralph 	case REG:
174716179Sralph 		rbusy( p->tn.rval, p->in.type );
174816179Sralph 	default:
174916179Sralph #ifndef FLEXNAMES
175016179Sralph 		p->in.name[0] = '\0';
175116179Sralph #else
175216179Sralph 		p->in.name = "";
175316179Sralph #endif
175416179Sralph 		}
175516179Sralph 
175616179Sralph 	p->in.rall = NOPREF;
175716179Sralph 
175816179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
175916179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
176016179Sralph 	}
176116179Sralph 
176216179Sralph # endif
176316179Sralph # endif
1764