xref: /csrg-svn/old/pcc/mip/trees.c (revision 32850)
117749Sralph #ifndef lint
2*32850Sdonn static char *sccsid ="@(#)trees.c	4.25 (Berkeley) 12/10/87";
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 
11416179Sralph 	else if( o==UNARY MINUS && l->in.op==FCON ){
11517749Sralph 		l->fpn.fval = -l->fpn.fval;
11616179Sralph 		return(l);
11716179Sralph 		}
11816179Sralph 
11917749Sralph 	else if( o==UNARY MINUS && l->in.op==DCON ){
12017749Sralph 		l->dpn.dval = -l->dpn.dval;
12117749Sralph 		return(l);
12217749Sralph 		}
12317749Sralph 
12416179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
12516179Sralph 		l->in.op = FREE;
12616179Sralph 		r->in.op = FREE;
12716179Sralph 		if( l->tn.lval ){
12816179Sralph 			tfree( r->in.right );
12916179Sralph 			return( r->in.left );
13016179Sralph 			}
13116179Sralph 		else {
13216179Sralph 			tfree( r->in.left );
13316179Sralph 			return( r->in.right );
13416179Sralph 			}
13516179Sralph 		}
13616179Sralph 
13716179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
13816179Sralph 
13916179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
14016179Sralph 
14116179Sralph 		switch( o ){
14216179Sralph 
14316179Sralph 		case ULT:
14416179Sralph 		case UGT:
14516179Sralph 		case ULE:
14616179Sralph 		case UGE:
14716179Sralph 		case LT:
14816179Sralph 		case GT:
14916179Sralph 		case LE:
15016179Sralph 		case GE:
15116179Sralph 		case EQ:
15216179Sralph 		case NE:
15332840Sdonn 			if( l->in.type == ENUMTY && r->in.type == ENUMTY )
15432840Sdonn 				chkpun( p );
15532840Sdonn 
15616179Sralph 		case ANDAND:
15716179Sralph 		case OROR:
15816179Sralph 		case CBRANCH:
15916179Sralph 
16016179Sralph 		ccwarn:
16116179Sralph 			if( hflag ) werror( "constant in conditional context" );
16216179Sralph 
16316179Sralph 		case PLUS:
16416179Sralph 		case MINUS:
16516179Sralph 		case MUL:
16616179Sralph 		case DIV:
16716179Sralph 		case MOD:
16816179Sralph 		case AND:
16916179Sralph 		case OR:
17016179Sralph 		case ER:
17116179Sralph 		case LS:
17216179Sralph 		case RS:
17316179Sralph 			if( conval( l, o, r ) ) {
17416179Sralph 				r->in.op = FREE;
17516179Sralph 				return(l);
17616179Sralph 				}
17716179Sralph 			break;
17816179Sralph 			}
17916179Sralph 		}
18024408Smckusick 	else if (opty == BITYPE &&
18124408Smckusick 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
18224408Smckusick 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
18324408Smckusick 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
18424408Smckusick 				extern int fpe_count;
18524408Smckusick 				extern jmp_buf gotfpe;
18616179Sralph 
18724408Smckusick 				fpe_count = 0;
18824408Smckusick 				if (setjmp(gotfpe))
18924408Smckusick 					goto treatfpe;
19017749Sralph 				if (l->in.op == ICON)
19117749Sralph 					l->dpn.dval = l->tn.lval;
19224408Smckusick 				else if (l->in.op == FCON)
19324408Smckusick 					l->dpn.dval = l->fpn.fval;
19417749Sralph 				if (r->in.op == ICON)
19517749Sralph 					r->dpn.dval = r->tn.lval;
19624408Smckusick 				else if (r->in.op == FCON)
19724408Smckusick 					r->dpn.dval = r->fpn.fval;
19817749Sralph 				switch (o) {
19917749Sralph 
20017749Sralph 				case PLUS:
20117749Sralph 					l->dpn.dval += r->dpn.dval;
20224408Smckusick 					break;
20317749Sralph 
20417749Sralph 				case MINUS:
20517749Sralph 					l->dpn.dval -= r->dpn.dval;
20624408Smckusick 					break;
20717749Sralph 
20817749Sralph 				case MUL:
20917749Sralph 					l->dpn.dval *= r->dpn.dval;
21024408Smckusick 					break;
21117749Sralph 
21217749Sralph 				case DIV:
21317749Sralph 					if (r->dpn.dval == 0)
21417749Sralph 						uerror("division by 0.");
21517749Sralph 					else
21617749Sralph 						l->dpn.dval /= r->dpn.dval;
21724408Smckusick 					break;
21824408Smckusick 					}
21924408Smckusick 			treatfpe:
22024408Smckusick 				if (fpe_count > 0) {
22124408Smckusick 					uerror("floating point exception in constant expression");
22224408Smckusick 					l->dpn.dval = 1.0; /* Fairly harmless */
22324408Smckusick 					}
22424408Smckusick 				fpe_count = -1;
22524408Smckusick 				l->in.op = DCON;
22624408Smckusick 				l->in.type = l->fn.csiz = DOUBLE;
22724408Smckusick 				r->in.op = FREE;
22824408Smckusick 				return (l);
22916179Sralph 			}
23024408Smckusick 		}
23116179Sralph 
23224408Smckusick 	/* it's real; we must make a new node */
23316179Sralph 
23416179Sralph 	p = block( o, l, r, INT, 0, INT );
23516179Sralph 
23616179Sralph 	actions = opact(p);
23717749Sralph #ifndef	BUG1
23817749Sralph 	if (adebug)
23917749Sralph 		printact(p, actions);
24017749Sralph #endif
24116179Sralph 
24216179Sralph 	if( actions&LVAL ){ /* check left descendent */
24316179Sralph 		if( notlval(p->in.left) ) {
24432849Sdonn 			uerror( "illegal lvalue operand of assignment operator" );
24516179Sralph 			}
24616179Sralph 		}
24716179Sralph 
24816179Sralph 	if( actions & NCVTR ){
24916179Sralph 		p->in.left = pconvert( p->in.left );
25016179Sralph 		}
25116179Sralph 	else if( !(actions & NCVT ) ){
25216179Sralph 		switch( opty ){
25316179Sralph 
25416179Sralph 		case BITYPE:
25516179Sralph 			p->in.right = pconvert( p->in.right );
25616179Sralph 		case UTYPE:
25716179Sralph 			p->in.left = pconvert( p->in.left );
25816179Sralph 
25916179Sralph 			}
26016179Sralph 		}
26116179Sralph 
26216179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
26316179Sralph 		chkpun(p);
26416179Sralph 		}
26516179Sralph 
26616179Sralph 	if( actions & (TYPL|TYPR) ){
26716179Sralph 
26816179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
26916179Sralph 
27016179Sralph 		p->in.type = q->in.type;
27116179Sralph 		p->fn.cdim = q->fn.cdim;
27216179Sralph 		p->fn.csiz = q->fn.csiz;
27316179Sralph 		}
27416179Sralph 
27516179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
27616179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
27716179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
27816179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
27916179Sralph 
28016179Sralph 	if( actions & OTHER ){
28116179Sralph 		l = p->in.left;
28216179Sralph 		r = p->in.right;
28316179Sralph 
28416179Sralph 		switch(o){
28516179Sralph 
28616179Sralph 		case NAME:
28716179Sralph 			sp = &stab[idname];
28816179Sralph 			if( sp->stype == UNDEF ){
28916179Sralph #ifndef FLEXNAMES
29016179Sralph 				uerror( "%.8s undefined", sp->sname );
29116179Sralph #else
29216179Sralph 				uerror( "%s undefined", sp->sname );
29316179Sralph #endif
29416179Sralph 				/* make p look reasonable */
29516179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
29616179Sralph 				p->tn.rval = idname;
29716179Sralph 				p->tn.lval = 0;
29816179Sralph 				defid( p, SNULL );
29916179Sralph 				break;
30016179Sralph 				}
30116179Sralph 			p->in.type = sp->stype;
30216179Sralph 			p->fn.cdim = sp->dimoff;
30316179Sralph 			p->fn.csiz = sp->sizoff;
30416179Sralph 			p->tn.lval = 0;
30516179Sralph 			p->tn.rval = idname;
30616179Sralph 			/* special case: MOETY is really an ICON... */
30716179Sralph 			if( p->in.type == MOETY ){
30816179Sralph 				p->tn.rval = NONAME;
30916179Sralph 				p->tn.lval = sp->offset;
31016179Sralph 				p->fn.cdim = 0;
31116179Sralph 				p->in.type = ENUMTY;
31216179Sralph 				p->in.op = ICON;
31316179Sralph 				}
31416179Sralph 			break;
31516179Sralph 
31616179Sralph 		case ICON:
31716179Sralph 			p->in.type = INT;
31816179Sralph 			p->fn.cdim = 0;
31916179Sralph 			p->fn.csiz = INT;
32016179Sralph 			break;
32116179Sralph 
32216179Sralph 		case STRING:
32316179Sralph 			p->in.op = NAME;
32416179Sralph 			p->in.type = CHAR+ARY;
32516179Sralph 			p->tn.lval = 0;
32616179Sralph 			p->tn.rval = NOLAB;
32716179Sralph 			p->fn.cdim = curdim;
32816179Sralph 			p->fn.csiz = CHAR;
32916179Sralph 			break;
33016179Sralph 
33116179Sralph 		case FCON:
33216179Sralph 			p->tn.lval = 0;
33316179Sralph 			p->tn.rval = 0;
33417749Sralph 			p->in.type = FLOAT;
33517749Sralph 			p->fn.cdim = 0;
33617749Sralph 			p->fn.csiz = FLOAT;
33717749Sralph 			break;
33817749Sralph 
33917749Sralph 		case DCON:
34017749Sralph 			p->tn.lval = 0;
34117749Sralph 			p->tn.rval = 0;
34216179Sralph 			p->in.type = DOUBLE;
34316179Sralph 			p->fn.cdim = 0;
34416179Sralph 			p->fn.csiz = DOUBLE;
34516179Sralph 			break;
34616179Sralph 
34716179Sralph 		case STREF:
34816179Sralph 			/* p->x turned into *(p+offset) */
34916179Sralph 			/* rhs must be a name; check correctness */
35016179Sralph 
35116179Sralph 			i = r->tn.rval;
35216179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
35316179Sralph 				uerror( "member of structure or union required" );
35416179Sralph 				}else
35516179Sralph 			/* if this name is non-unique, find right one */
35616179Sralph 			if( stab[i].sflags & SNONUNIQ &&
35716179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
35816179Sralph 				(l->fn.csiz +1) >= 0 ){
35916179Sralph 				/* nonunique name && structure defined */
36016179Sralph 				char * memnam, * tabnam;
36116179Sralph 				register k;
36216179Sralph 				int j;
36316179Sralph 				int memi;
36416179Sralph 				j=dimtab[l->fn.csiz+1];
36516179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
36616179Sralph 					tabnam = stab[memi].sname;
36716179Sralph 					memnam = stab[i].sname;
36816179Sralph # ifndef BUG1
36916179Sralph 					if( ddebug>1 ){
37016179Sralph #ifndef FLEXNAMES
37116179Sralph 						printf("member %.8s==%.8s?\n",
37216179Sralph #else
37316179Sralph 						printf("member %s==%s?\n",
37416179Sralph #endif
37516179Sralph 							memnam, tabnam);
37616179Sralph 						}
37716179Sralph # endif
37816179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
37916179Sralph #ifndef FLEXNAMES
38016179Sralph 						for( k=0; k<NCHNAM; ++k ){
38116179Sralph 							if(*memnam++!=*tabnam)
38216179Sralph 								goto next;
38316179Sralph 							if(!*tabnam++) break;
38416179Sralph 							}
38516179Sralph #else
38616179Sralph 						if (memnam != tabnam)
38716179Sralph 							goto next;
38816179Sralph #endif
38916179Sralph 						r->tn.rval = i = memi;
39016179Sralph 						break;
39116179Sralph 						}
39216179Sralph 					next: continue;
39316179Sralph 					}
39416179Sralph 				if( memi < 0 )
39516179Sralph #ifndef FLEXNAMES
39616179Sralph 					uerror("illegal member use: %.8s",
39716179Sralph #else
39816179Sralph 					uerror("illegal member use: %s",
39916179Sralph #endif
40016179Sralph 						stab[i].sname);
40116179Sralph 				}
40216179Sralph 			else {
40316179Sralph 				register j;
40416179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
40516179Sralph 					if( stab[i].sflags & SNONUNIQ ){
40616179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
40716179Sralph 						}
40816179Sralph 					else werror( "struct/union or struct/union pointer required" );
40916179Sralph 					}
41016179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
41116179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
41216179Sralph #ifndef FLEXNAMES
41316179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
41416179Sralph #else
41516179Sralph 					werror( "illegal member use: %s", stab[i].sname );
41616179Sralph #endif
41716179Sralph 					}
41816179Sralph 				}
41916179Sralph 
42016179Sralph 			p = stref( p );
42116179Sralph 			break;
42216179Sralph 
42316179Sralph 		case UNARY MUL:
42416179Sralph 			if( l->in.op == UNARY AND ){
42516179Sralph 				p->in.op = l->in.op = FREE;
42616179Sralph 				p = l->in.left;
42716179Sralph 				}
42816179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
42916179Sralph 			p->in.type = DECREF(l->in.type);
43016179Sralph 			p->fn.cdim = l->fn.cdim;
43116179Sralph 			p->fn.csiz = l->fn.csiz;
43216179Sralph 			break;
43316179Sralph 
43416179Sralph 		case UNARY AND:
43516179Sralph 			switch( l->in.op ){
43616179Sralph 
43716179Sralph 			case UNARY MUL:
43816179Sralph 				p->in.op = l->in.op = FREE;
43916179Sralph 				p = l->in.left;
44016179Sralph 			case NAME:
44116179Sralph 				p->in.type = INCREF( l->in.type );
44216179Sralph 				p->fn.cdim = l->fn.cdim;
44316179Sralph 				p->fn.csiz = l->fn.csiz;
44416179Sralph 				break;
44516179Sralph 
44616179Sralph 			case COMOP:
44716179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
44816179Sralph 				p->in.op = l->in.op = FREE;
44916179Sralph 				p = buildtree( COMOP, l->in.left, lr );
45016179Sralph 				break;
45116179Sralph 
45216179Sralph 			case QUEST:
45316179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
45416179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
45516179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
45616179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
45716179Sralph 				break;
45816179Sralph 
45916179Sralph # ifdef ADDROREG
46016179Sralph 			case OREG:
46116179Sralph 				/* OREG was built in clocal()
46216179Sralph 				 * for an auto or formal parameter
46316179Sralph 				 * now its address is being taken
46416179Sralph 				 * local code must unwind it
46516179Sralph 				 * back to PLUS/MINUS REG ICON
46616179Sralph 				 * according to local conventions
46716179Sralph 				 */
46816179Sralph 				{
46916179Sralph 				extern NODE * addroreg();
47016179Sralph 				p->in.op = FREE;
47116179Sralph 				p = addroreg( l );
47216179Sralph 				}
47316179Sralph 				break;
47416179Sralph 
47516179Sralph # endif
47616179Sralph 			default:
47716179Sralph 				uerror( "unacceptable operand of &" );
47816179Sralph 				break;
47916179Sralph 				}
48016179Sralph 			break;
48116179Sralph 
48216179Sralph 		case LS:
48316179Sralph 		case RS:
48416179Sralph 		case ASG LS:
48516179Sralph 		case ASG RS:
48616179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
48716179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
48816179Sralph 			break;
48916179Sralph 
49016179Sralph 		case RETURN:
49116179Sralph 		case ASSIGN:
49216179Sralph 		case CAST:
49316179Sralph 			/* structure assignment */
49416179Sralph 			/* take the addresses of the two sides; then make an
49516179Sralph 			/* operator using STASG and
49616179Sralph 			/* the addresses of left and right */
49716179Sralph 
49816179Sralph 			{
49916179Sralph 				register TWORD t;
50016179Sralph 				register d, s;
50116179Sralph 
50216179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
50316179Sralph 
50416179Sralph 				r = buildtree( UNARY AND, r, NIL );
50516179Sralph 				t = r->in.type;
50616179Sralph 				d = r->fn.cdim;
50716179Sralph 				s = r->fn.csiz;
50816179Sralph 
50916179Sralph 				l = block( STASG, l, r, t, d, s );
51016179Sralph 
51116179Sralph 				if( o == RETURN ){
51216179Sralph 					p->in.op = FREE;
51316179Sralph 					p = l;
51416179Sralph 					break;
51516179Sralph 					}
51616179Sralph 
51716179Sralph 				p->in.op = UNARY MUL;
51816179Sralph 				p->in.left = l;
51916179Sralph 				p->in.right = NIL;
52016179Sralph 				break;
52116179Sralph 				}
52216179Sralph 		case COLON:
52316179Sralph 			/* structure colon */
52416179Sralph 
52516179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
52616179Sralph 			break;
52716179Sralph 
52816179Sralph 		case CALL:
52917749Sralph 			p->in.right = r = fixargs( p->in.right );
53016179Sralph 		case UNARY CALL:
53116179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
53216179Sralph 			p->in.type = DECREF(l->in.type);
53316179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
53416179Sralph 			p->in.type = DECREF( p->in.type );
53516179Sralph 			p->fn.cdim = l->fn.cdim;
53616179Sralph 			p->fn.csiz = l->fn.csiz;
53716179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
53816179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
53916179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
54016179Sralph 				p->in.op += (FORTCALL-CALL);
54116179Sralph 				}
54216179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
54316179Sralph 				/* function returning structure */
54416179Sralph 				/*  make function really return ptr to str., with * */
54516179Sralph 
54616179Sralph 				p->in.op += STCALL-CALL;
54716179Sralph 				p->in.type = INCREF( p->in.type );
54816179Sralph 				p = buildtree( UNARY MUL, p, NIL );
54916179Sralph 
55016179Sralph 				}
55116179Sralph 			break;
55216179Sralph 
55316179Sralph 		default:
55416179Sralph 			cerror( "other code %d", o );
55516179Sralph 			}
55616179Sralph 
55716179Sralph 		}
55816179Sralph 
55916179Sralph 	if( actions & CVTO ) p = oconvert(p);
56016179Sralph 	p = clocal(p);
56116179Sralph 
56216179Sralph # ifndef BUG1
56316179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
56416179Sralph # endif
56516179Sralph 
56616179Sralph 	return(p);
56716179Sralph 
56816179Sralph 	}
56916179Sralph 
57024408Smckusick int fpe_count = -1;
57124408Smckusick jmp_buf gotfpe;
57224408Smckusick 
57324408Smckusick fpe() {
57424408Smckusick 	if (fpe_count < 0)
57524408Smckusick 		cerror("floating point exception");
57624408Smckusick 	++fpe_count;
57724408Smckusick 	longjmp(gotfpe, 1);
57824408Smckusick 	}
57924408Smckusick 
58017749Sralph /*
58117749Sralph  * Rewrite arguments in a function call.
58217749Sralph  * Structure arguments are massaged, single
58317749Sralph  * precision floating point constants are
58417749Sralph  * cast to double (to eliminate convert code).
58517749Sralph  */
58616179Sralph NODE *
58717749Sralph fixargs( p ) register NODE *p;  {
58817749Sralph 	int o = p->in.op;
58916179Sralph 
59017749Sralph 	if( o == CM ){
59117749Sralph 		p->in.left = fixargs( p->in.left );
59217749Sralph 		p->in.right = fixargs( p->in.right );
59316179Sralph 		return( p );
59416179Sralph 		}
59516179Sralph 
59616179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
59716179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
59816179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
59916179Sralph 		p = clocal(p);
60016179Sralph 		}
60117749Sralph 	else if( o == FCON )
60217749Sralph 		p = makety(p, DOUBLE, 0, 0);
60316179Sralph 	return( p );
60416179Sralph 	}
60516179Sralph 
60616179Sralph chkstr( i, j, type ) TWORD type; {
60716179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
60816179Sralph 	/* i has been checked to contain a MOS or MOU */
60916179Sralph 	/* j is the index in dimtab of the members... */
61016179Sralph 	int k, kk;
61116179Sralph 
61216179Sralph 	extern int ddebug;
61316179Sralph 
61416179Sralph # ifndef BUG1
61516179Sralph #ifndef FLEXNAMES
61616179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
61716179Sralph #else
61816179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
61916179Sralph #endif
62016179Sralph # endif
62116179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
62216179Sralph 	else {
62316179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
62416179Sralph 			if( kk >= SYMTSZ ){
62516179Sralph 				cerror( "gummy structure" );
62616179Sralph 				return(1);
62716179Sralph 				}
62816179Sralph 			if( kk == i ) return( 1 );
62916179Sralph 			switch( stab[kk].stype ){
63016179Sralph 
63116179Sralph 			case STRTY:
63216179Sralph 			case UNIONTY:
63316179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
63416179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
63516179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
63616179Sralph 					werror(
63716179Sralph #ifndef FLEXNAMES
63816179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
63916179Sralph #else
64016179Sralph 					"illegal member use: perhaps %s.%s?",
64116179Sralph #endif
64216179Sralph 					stab[kk].sname, stab[i].sname );
64316179Sralph 					return(1);
64416179Sralph 					}
64516179Sralph 				}
64616179Sralph 			}
64716179Sralph 		}
64816179Sralph 	return( 0 );
64916179Sralph 	}
65016179Sralph 
65116179Sralph conval( p, o, q ) register NODE *p, *q; {
65216179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
65332842Sdonn 	/* works only on integer constants */
65432842Sdonn 	NODE *r;
65516179Sralph 	int i, u;
65616179Sralph 	CONSZ val;
65716179Sralph 
65816179Sralph 	val = q->tn.lval;
65916179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
66016179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
66116179Sralph 
66216179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
66316179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
66416179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
66516179Sralph 
66632842Sdonn 	if( p->in.type != INT || q->in.type != INT ){
66732842Sdonn 		/* will this always work if p == q and o is UTYPE? */
66832842Sdonn 		r = block( o, p, q, INT, 0, INT );
66932842Sdonn 		r = tymatch( r );
67032842Sdonn 		p->in.type = r->in.type;
67132842Sdonn 		p->fn.cdim = r->fn.cdim;
67232842Sdonn 		p->fn.csiz = r->fn.csiz;
67332842Sdonn 		r->in.op = FREE;
67432842Sdonn 		}
67532842Sdonn 
67616179Sralph 	switch( o ){
67716179Sralph 
67816179Sralph 	case PLUS:
67916179Sralph 		p->tn.lval += val;
68016179Sralph 		if( p->tn.rval == NONAME ){
68116179Sralph 			p->tn.rval = q->tn.rval;
68216179Sralph 			p->in.type = q->in.type;
68316179Sralph 			}
68416179Sralph 		break;
68516179Sralph 	case MINUS:
68616179Sralph 		p->tn.lval -= val;
68716179Sralph 		break;
68816179Sralph 	case MUL:
68932840Sdonn 		p->tn.lval *= val;
69016179Sralph 		break;
69116179Sralph 	case DIV:
69216179Sralph 		if( val == 0 ) uerror( "division by 0" );
69317749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
69416179Sralph 		else p->tn.lval /= val;
69516179Sralph 		break;
69616179Sralph 	case MOD:
69716179Sralph 		if( val == 0 ) uerror( "division by 0" );
69817749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
69916179Sralph 		else p->tn.lval %= val;
70016179Sralph 		break;
70116179Sralph 	case AND:
70216179Sralph 		p->tn.lval &= val;
70316179Sralph 		break;
70416179Sralph 	case OR:
70516179Sralph 		p->tn.lval |= val;
70616179Sralph 		break;
70716179Sralph 	case ER:
70817749Sralph 		p->tn.lval ^= val;
70916179Sralph 		break;
71016179Sralph 	case LS:
71116179Sralph 		i = val;
71216179Sralph 		p->tn.lval = p->tn.lval << i;
71316179Sralph 		break;
71416179Sralph 	case RS:
71516179Sralph 		i = val;
71617749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
71717749Sralph 		else p->tn.lval = p->tn.lval >> i;
71816179Sralph 		break;
71916179Sralph 
72016179Sralph 	case UNARY MINUS:
72116179Sralph 		p->tn.lval = - p->tn.lval;
72216179Sralph 		break;
72316179Sralph 	case COMPL:
72416179Sralph 		p->tn.lval = ~p->tn.lval;
72516179Sralph 		break;
72616179Sralph 	case NOT:
72716179Sralph 		p->tn.lval = !p->tn.lval;
72816179Sralph 		break;
72916179Sralph 	case LT:
73016179Sralph 		p->tn.lval = p->tn.lval < val;
73116179Sralph 		break;
73216179Sralph 	case LE:
73316179Sralph 		p->tn.lval = p->tn.lval <= val;
73416179Sralph 		break;
73516179Sralph 	case GT:
73616179Sralph 		p->tn.lval = p->tn.lval > val;
73716179Sralph 		break;
73816179Sralph 	case GE:
73916179Sralph 		p->tn.lval = p->tn.lval >= val;
74016179Sralph 		break;
74116179Sralph 	case ULT:
74232848Sdonn 		p->tn.lval = p->tn.lval < (unsigned) val;
74316179Sralph 		break;
74416179Sralph 	case ULE:
74532848Sdonn 		p->tn.lval = p->tn.lval <= (unsigned) val;
74616179Sralph 		break;
74732848Sdonn 	case UGT:
74832848Sdonn 		p->tn.lval = p->tn.lval > (unsigned) val;
74932848Sdonn 		break;
75032840Sdonn 	case UGE:
75132848Sdonn 		p->tn.lval = p->tn.lval >= (unsigned) val;
75232840Sdonn 		break;
75316179Sralph 	case EQ:
75416179Sralph 		p->tn.lval = p->tn.lval == val;
75516179Sralph 		break;
75616179Sralph 	case NE:
75716179Sralph 		p->tn.lval = p->tn.lval != val;
75816179Sralph 		break;
75916179Sralph 	default:
76016179Sralph 		return(0);
76116179Sralph 		}
76216179Sralph 	return(1);
76316179Sralph 	}
76416179Sralph 
76516179Sralph chkpun(p) register NODE *p; {
76616179Sralph 
76716179Sralph 	/* checks p for the existance of a pun */
76816179Sralph 
76916179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
77016179Sralph 
77116179Sralph 	/* one case is when enumerations are used: this applies only to lint */
77216179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
77316179Sralph 	/* we check that this integer is in fact a constant zero... */
77416179Sralph 
77516179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
77616179Sralph 	/* this falls out, because the LHS is never 0 */
77716179Sralph 
77816179Sralph 	register NODE *q;
77916179Sralph 	register t1, t2;
78016179Sralph 	register d1, d2;
78132844Sdonn 	int ref1, ref2;
78216179Sralph 
78316179Sralph 	t1 = p->in.left->in.type;
78416179Sralph 	t2 = p->in.right->in.type;
78516179Sralph 
78616179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
78732841Sdonn 		/* rob pike says this is obnoxious...
78832840Sdonn 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
78932841Sdonn 			werror( "comparison of enums" ); */
79032841Sdonn 		if( t1==ENUMTY && t2==ENUMTY ) {
79132841Sdonn 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
79232841Sdonn 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
79332841Sdonn 			return;
79432841Sdonn 			}
79532841Sdonn 		if ( t1 == ENUMTY ) t1 = INT;
79632841Sdonn 		if ( t2 == ENUMTY ) t2 = INT;
79716179Sralph 		}
79816179Sralph 
79932844Sdonn 	ref1 = ISPTR(t1) || ISARY(t1);
80032844Sdonn 	ref2 = ISPTR(t2) || ISARY(t2);
80116179Sralph 
80232844Sdonn 	if( ref1 ^ ref2 ){
80332844Sdonn 		if( ref1 ) q = p->in.right;
80432844Sdonn 		else q = p->in.left;
80516179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
80616179Sralph 			werror( "illegal combination of pointer and integer, op %s",
80716179Sralph 				opst[p->in.op] );
80816179Sralph 			}
80916179Sralph 		}
81032844Sdonn 	else if( ref1 ){
81132843Sdonn 		if( t1 == t2 ) {
81232843Sdonn 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
81332843Sdonn 				werror( "illegal structure pointer combination" );
81416179Sralph 				return;
81516179Sralph 				}
81632843Sdonn 			d1 = p->in.left->fn.cdim;
81732843Sdonn 			d2 = p->in.right->fn.cdim;
81832843Sdonn 			for( ;; ){
81932843Sdonn 				if( ISARY(t1) ){
82032843Sdonn 					if( dimtab[d1] != dimtab[d2] ){
82132843Sdonn 						werror( "illegal array size combination" );
82232843Sdonn 						return;
82332843Sdonn 						}
82432843Sdonn 					++d1;
82532843Sdonn 					++d2;
82616179Sralph 					}
82732843Sdonn 				else if( !ISPTR(t1) ) break;
82832843Sdonn 				t1 = DECREF(t1);
82916179Sralph 				}
83016179Sralph 			}
83132843Sdonn 		else
83232843Sdonn 			werror( "illegal pointer combination" );
83316179Sralph 		}
83416179Sralph 
83516179Sralph 	}
83616179Sralph 
83716179Sralph NODE *
83816179Sralph stref( p ) register NODE *p; {
83916179Sralph 
84016179Sralph 	TWORD t;
84116179Sralph 	int d, s, dsc, align;
84216179Sralph 	OFFSZ off;
84316179Sralph 	register struct symtab *q;
84416179Sralph 
84516179Sralph 	/* make p->x */
84616179Sralph 	/* this is also used to reference automatic variables */
84716179Sralph 
84816179Sralph 	q = &stab[p->in.right->tn.rval];
84916179Sralph 	p->in.right->in.op = FREE;
85016179Sralph 	p->in.op = FREE;
85116179Sralph 	p = pconvert( p->in.left );
85216179Sralph 
85316179Sralph 	/* make p look like ptr to x */
85416179Sralph 
85516179Sralph 	if( !ISPTR(p->in.type)){
85616179Sralph 		p->in.type = PTR+UNIONTY;
85716179Sralph 		}
85816179Sralph 
85916179Sralph 	t = INCREF( q->stype );
86016179Sralph 	d = q->dimoff;
86116179Sralph 	s = q->sizoff;
86216179Sralph 
86316179Sralph 	p = makety( p, t, d, s );
86416179Sralph 
86516179Sralph 	/* compute the offset to be added */
86616179Sralph 
86716179Sralph 	off = q->offset;
86816179Sralph 	dsc = q->sclass;
86916179Sralph 
87016179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
87116179Sralph 		align = ALINT;
87216179Sralph 		s = INT;
87316179Sralph 		off = (off/align)*align;
87416179Sralph 		}
87516179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
87616179Sralph 
87716179Sralph 	p = buildtree( UNARY MUL, p, NIL );
87816179Sralph 
87916179Sralph 	/* if field, build field info */
88016179Sralph 
88116179Sralph 	if( dsc & FIELD ){
88216179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
88316179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
88416179Sralph 		}
88516179Sralph 
88616179Sralph 	return( clocal(p) );
88716179Sralph 	}
88816179Sralph 
88916179Sralph notlval(p) register NODE *p; {
89016179Sralph 
89116179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
89216179Sralph 
89316179Sralph 	again:
89416179Sralph 
89516179Sralph 	switch( p->in.op ){
89616179Sralph 
89716179Sralph 	case FLD:
89816179Sralph 		p = p->in.left;
89916179Sralph 		goto again;
90016179Sralph 
90116179Sralph 	case UNARY MUL:
90216179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
90316179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
90416179Sralph 		/* and the f().a bug, given that f returns a structure */
90516179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
90616179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
90716179Sralph 	case NAME:
90816179Sralph 	case OREG:
90916179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
91016179Sralph 	case REG:
91116179Sralph 		return(0);
91216179Sralph 
91316179Sralph 	default:
91416179Sralph 		return(1);
91516179Sralph 
91616179Sralph 		}
91716179Sralph 
91816179Sralph 	}
91916179Sralph 
92016179Sralph NODE *
92116179Sralph bcon( i ){ /* make a constant node with value i */
92216179Sralph 	register NODE *p;
92316179Sralph 
92416179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
92516179Sralph 	p->tn.lval = i;
92616179Sralph 	p->tn.rval = NONAME;
92716179Sralph 	return( clocal(p) );
92816179Sralph 	}
92916179Sralph 
93016179Sralph NODE *
93116179Sralph bpsize(p) register NODE *p; {
93216179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
93316179Sralph 	}
93416179Sralph 
93516179Sralph OFFSZ
93616179Sralph psize( p ) NODE *p; {
93716179Sralph 	/* p is a node of type pointer; psize returns the
93816179Sralph 	   size of the thing pointed to */
93916179Sralph 
94016179Sralph 	if( !ISPTR(p->in.type) ){
94116179Sralph 		uerror( "pointer required");
94216179Sralph 		return( SZINT );
94316179Sralph 		}
94416179Sralph 	/* note: no pointers to fields */
94516179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
94616179Sralph 	}
94716179Sralph 
94816179Sralph NODE *
94916179Sralph convert( p, f )  register NODE *p; {
95016179Sralph 	/*  convert an operand of p
95116179Sralph 	    f is either CVTL or CVTR
95216179Sralph 	    operand has type int, and is converted by the size of the other side
95316179Sralph 	    */
95416179Sralph 
95516179Sralph 	register NODE *q, *r;
95616179Sralph 
95716179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
95816179Sralph 
95916179Sralph 	r = block( PMCONV,
96016179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
96116179Sralph 	r = clocal(r);
96216179Sralph 	if( f == CVTL )
96316179Sralph 		p->in.left = r;
96416179Sralph 	else
96516179Sralph 		p->in.right = r;
96616179Sralph 	return(p);
96716179Sralph 
96816179Sralph 	}
96916179Sralph 
97025750Sdonn #ifndef econvert
97116179Sralph econvert( p ) register NODE *p; {
97216179Sralph 
97316179Sralph 	/* change enums to ints, or appropriate types */
97416179Sralph 
97516179Sralph 	register TWORD ty;
97616179Sralph 
97716179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
97816179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
97916179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
98016179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
98116179Sralph 		else ty = LONG;
98216179Sralph 		ty = ctype( ty );
98316179Sralph 		p->fn.csiz = ty;
98416179Sralph 		MODTYPE(p->in.type,ty);
98516179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
98616179Sralph 		}
98716179Sralph 	}
98825750Sdonn #endif
98916179Sralph 
99016179Sralph NODE *
99116179Sralph pconvert( p ) register NODE *p; {
99216179Sralph 
99316179Sralph 	/* if p should be changed into a pointer, do so */
99416179Sralph 
99516179Sralph 	if( ISARY( p->in.type) ){
99616179Sralph 		p->in.type = DECREF( p->in.type );
99716179Sralph 		++p->fn.cdim;
99816179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
99916179Sralph 		}
100016179Sralph 	if( ISFTN( p->in.type) )
100116179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
100216179Sralph 
100316179Sralph 	return( p );
100416179Sralph 	}
100516179Sralph 
100616179Sralph NODE *
100716179Sralph oconvert(p) register NODE *p; {
100816179Sralph 	/* convert the result itself: used for pointer and unsigned */
100916179Sralph 
101016179Sralph 	switch(p->in.op) {
101116179Sralph 
101216179Sralph 	case LE:
101316179Sralph 	case LT:
101416179Sralph 	case GE:
101516179Sralph 	case GT:
101616179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
101716179Sralph 	case EQ:
101816179Sralph 	case NE:
101916179Sralph 		return( p );
102016179Sralph 
102116179Sralph 	case MINUS:
102216179Sralph 		return(  clocal( block( PVCONV,
102316179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
102416179Sralph 		}
102516179Sralph 
102616179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
102716179Sralph 
102816179Sralph 	return(p);
102916179Sralph 	}
103016179Sralph 
103116179Sralph NODE *
103216179Sralph ptmatch(p)  register NODE *p; {
103316179Sralph 
103416179Sralph 	/* makes the operands of p agree; they are
103516179Sralph 	   either pointers or integers, by this time */
103616179Sralph 	/* with MINUS, the sizes must be the same */
103716179Sralph 	/* with COLON, the types must be the same */
103816179Sralph 
103916179Sralph 	TWORD t1, t2, t;
104016179Sralph 	int o, d2, d, s2, s;
104116179Sralph 
104216179Sralph 	o = p->in.op;
104316179Sralph 	t = t1 = p->in.left->in.type;
104416179Sralph 	t2 = p->in.right->in.type;
104516179Sralph 	d = p->in.left->fn.cdim;
104616179Sralph 	d2 = p->in.right->fn.cdim;
104716179Sralph 	s = p->in.left->fn.csiz;
104816179Sralph 	s2 = p->in.right->fn.csiz;
104916179Sralph 
105016179Sralph 	switch( o ){
105116179Sralph 
105216179Sralph 	case ASSIGN:
105316179Sralph 	case RETURN:
105416179Sralph 	case CAST:
105516179Sralph 		{  break; }
105616179Sralph 
105716179Sralph 	case MINUS:
105816179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
105916179Sralph 			uerror( "illegal pointer subtraction");
106016179Sralph 			}
106116179Sralph 		   break;
106216179Sralph 		   }
106316179Sralph 	case COLON:
106416179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
106516179Sralph 		   break;
106616179Sralph 		   }
106716179Sralph 	default:  /* must work harder: relationals or comparisons */
106816179Sralph 
106916179Sralph 		if( !ISPTR(t1) ){
107016179Sralph 			t = t2;
107116179Sralph 			d = d2;
107216179Sralph 			s = s2;
107316179Sralph 			break;
107416179Sralph 			}
107516179Sralph 		if( !ISPTR(t2) ){
107616179Sralph 			break;
107716179Sralph 			}
107816179Sralph 
107916179Sralph 		/* both are pointers */
108016179Sralph 		if( talign(t2,s2) < talign(t,s) ){
108116179Sralph 			t = t2;
108216179Sralph 			s = s2;
108316179Sralph 			}
108416179Sralph 		break;
108516179Sralph 		}
108616179Sralph 
108716179Sralph 	p->in.left = makety( p->in.left, t, d, s );
108816179Sralph 	p->in.right = makety( p->in.right, t, d, s );
108916179Sralph 	if( o!=MINUS && !logop(o) ){
109016179Sralph 
109116179Sralph 		p->in.type = t;
109216179Sralph 		p->fn.cdim = d;
109316179Sralph 		p->fn.csiz = s;
109416179Sralph 		}
109516179Sralph 
109616179Sralph 	return(clocal(p));
109716179Sralph 	}
109816179Sralph 
109916179Sralph int tdebug = 0;
110016179Sralph 
110116179Sralph NODE *
110216179Sralph tymatch(p)  register NODE *p; {
110316179Sralph 
110416179Sralph 	/* satisfy the types of various arithmetic binary ops */
110516179Sralph 
110616179Sralph 	/* rules are:
110725750Sdonn 		if assignment, type of LHS
110816179Sralph 		if any float or doubles, make double
110916179Sralph 		if any longs, make long
111016179Sralph 		otherwise, make int
111116179Sralph 		if either operand is unsigned, the result is...
111216179Sralph 	*/
111316179Sralph 
111416179Sralph 	register TWORD t1, t2, t, tu;
111516179Sralph 	register o, u;
111616179Sralph 
111716179Sralph 	o = p->in.op;
111816179Sralph 
111916179Sralph 	t1 = p->in.left->in.type;
112016179Sralph 	t2 = p->in.right->in.type;
112116179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
112216179Sralph 		uerror("void type illegal in expression");
112316179Sralph 
112416179Sralph 	u = 0;
112516179Sralph 	if( ISUNSIGNED(t1) ){
112616179Sralph 		u = 1;
112716179Sralph 		t1 = DEUNSIGN(t1);
112816179Sralph 		}
112916179Sralph 	if( ISUNSIGNED(t2) ){
113016179Sralph 		u = 1;
113116179Sralph 		t2 = DEUNSIGN(t2);
113216179Sralph 		}
113316179Sralph 
113416179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
113516179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
113616179Sralph 
113717749Sralph #ifdef SPRECC
113817749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
113917749Sralph 		t = DOUBLE;
114017749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
114117749Sralph 		t = FLOAT;
114217749Sralph #else
114317749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
114417749Sralph 		t = DOUBLE;
114517749Sralph #endif
114616179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
114716179Sralph 	else t = INT;
114816179Sralph 
1149*32850Sdonn #ifdef tahoe
1150*32850Sdonn 	if( asgop(o) ){
1151*32850Sdonn #else
115225750Sdonn 	if( o == ASSIGN || o == CAST || o == RETURN ){
1153*32850Sdonn #endif
115416179Sralph 		tu = p->in.left->in.type;
115516179Sralph 		t = t1;
115616179Sralph 		}
115716179Sralph 	else {
115816179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
115916179Sralph 		}
116016179Sralph 
116116179Sralph 	/* because expressions have values that are at least as wide
116216179Sralph 	   as INT or UNSIGNED, the only conversions needed
116316179Sralph 	   are those involving FLOAT/DOUBLE, and those
116416179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
116516179Sralph 
1166*32850Sdonn #ifdef tahoe
1167*32850Sdonn 	if( t != t1 )
1168*32850Sdonn #else
116925750Sdonn 	if( t != t1 && ! asgop(o) )
1170*32850Sdonn #endif
117125750Sdonn 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
117216179Sralph 
117332840Sdonn 	if( t != t2 || o==CAST)
117432840Sdonn 		if ( tu == ENUMTY ) {/* always asgop */
117532840Sdonn 			p->in.right = makety( p->in.right, INT, 0, INT );
117632840Sdonn 			p->in.right->in.type = tu;
117732840Sdonn 			p->in.right->fn.cdim = p->in.left->fn.cdim;
117832840Sdonn 			p->in.right->fn.csiz = p->in.left->fn.csiz;
117932840Sdonn 			}
118032840Sdonn 		else
118132840Sdonn 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
118216179Sralph 
118316179Sralph 	if( asgop(o) ){
118416179Sralph 		p->in.type = p->in.left->in.type;
118516179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
118616179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
118716179Sralph 		}
118816179Sralph 	else if( !logop(o) ){
118916179Sralph 		p->in.type = tu;
119016179Sralph 		p->fn.cdim = 0;
119116179Sralph 		p->fn.csiz = t;
119216179Sralph 		}
119316179Sralph 
119416179Sralph # ifndef BUG1
119516179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
119616179Sralph # endif
119716179Sralph 
119816179Sralph 	return(p);
119916179Sralph 	}
120016179Sralph 
120116179Sralph NODE *
120216179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
120316179Sralph 	/* make p into type t by inserting a conversion */
120416179Sralph 
120516179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
120616179Sralph 	if( t == p->in.type ){
120716179Sralph 		p->fn.cdim = d;
120816179Sralph 		p->fn.csiz = s;
120916179Sralph 		return( p );
121016179Sralph 		}
121116179Sralph 
121216179Sralph 	if( t & TMASK ){
121316179Sralph 		/* non-simple type */
121417228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
121516179Sralph 		}
121616179Sralph 
121716179Sralph 	if( p->in.op == ICON ){
121817749Sralph 		if (t == DOUBLE) {
121917749Sralph 			p->in.op = DCON;
122017749Sralph 			if (ISUNSIGNED(p->in.type))
122132847Sdonn 				p->dpn.dval = (unsigned CONSZ) p->tn.lval;
122217749Sralph 			else
122317749Sralph 				p->dpn.dval = p->tn.lval;
122417749Sralph 			p->in.type = p->fn.csiz = t;
122517749Sralph 			return (clocal(p));
122617749Sralph 		}
122717749Sralph 		if (t == FLOAT) {
122816179Sralph 			p->in.op = FCON;
122916179Sralph 			if( ISUNSIGNED(p->in.type) ){
123032847Sdonn 				p->fpn.fval = (unsigned CONSZ) p->tn.lval;
123116179Sralph 				}
123216179Sralph 			else {
123317749Sralph 				p->fpn.fval = p->tn.lval;
123416179Sralph 				}
123516179Sralph 
123616179Sralph 			p->in.type = p->fn.csiz = t;
123716179Sralph 			return( clocal(p) );
123816179Sralph 			}
123916179Sralph 		}
124017749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
124117749Sralph 		double db;
124216179Sralph 
124317749Sralph 		p->in.op = DCON;
124417749Sralph 		db = p->fpn.fval;
124517749Sralph 		p->dpn.dval = db;
124617749Sralph 		p->in.type = p->fn.csiz = t;
124717749Sralph 		return (clocal(p));
124817749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
124917749Sralph 		float fl;
125017749Sralph 
125117749Sralph 		p->in.op = FCON;
125217749Sralph 		fl = p->dpn.dval;
125317749Sralph #ifdef notdef
125417749Sralph 		if (fl != p->dpn.dval)
125517749Sralph 			werror("float conversion loses precision");
125617749Sralph #endif
125717749Sralph 		p->fpn.fval = fl;
125817749Sralph 		p->in.type = p->fn.csiz = t;
125917749Sralph 		return (clocal(p));
126017749Sralph 	}
126117749Sralph 
126217049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
126316179Sralph 
126416179Sralph 	}
126516179Sralph 
126616179Sralph NODE *
126716179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
126816179Sralph 
126916179Sralph 	register NODE *p;
127016179Sralph 
127116179Sralph 	p = talloc();
127216179Sralph 	p->in.op = o;
127316179Sralph 	p->in.left = l;
127416179Sralph 	p->in.right = r;
127516179Sralph 	p->in.type = t;
127616179Sralph 	p->fn.cdim = d;
127716179Sralph 	p->fn.csiz = s;
127816179Sralph 	return(p);
127916179Sralph 	}
128016179Sralph 
128116179Sralph icons(p) register NODE *p; {
128216179Sralph 	/* if p is an integer constant, return its value */
128316179Sralph 	int val;
128416179Sralph 
128516179Sralph 	if( p->in.op != ICON ){
128616179Sralph 		uerror( "constant expected");
128716179Sralph 		val = 1;
128816179Sralph 		}
128916179Sralph 	else {
129016179Sralph 		val = p->tn.lval;
129116179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
129216179Sralph 		}
129316179Sralph 	tfree( p );
129416179Sralph 	return(val);
129516179Sralph 	}
129616179Sralph 
129716179Sralph /* 	the intent of this table is to examine the
129816179Sralph 	operators, and to check them for
129916179Sralph 	correctness.
130016179Sralph 
130116179Sralph 	The table is searched for the op and the
130216179Sralph 	modified type (where this is one of the
130316179Sralph 	types INT (includes char and short), LONG,
130416179Sralph 	DOUBLE (includes FLOAT), and POINTER
130516179Sralph 
130616179Sralph 	The default action is to make the node type integer
130716179Sralph 
130816179Sralph 	The actions taken include:
130916179Sralph 		PUN	  check for puns
131016179Sralph 		CVTL	  convert the left operand
131116179Sralph 		CVTR	  convert the right operand
131216179Sralph 		TYPL	  the type is determined by the left operand
131316179Sralph 		TYPR	  the type is determined by the right operand
131416179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
131516179Sralph 		PTMATCH	  like TYMATCH, but for pointers
131616179Sralph 		LVAL	  left operand must be lval
131716179Sralph 		CVTO	  convert the op
131816179Sralph 		NCVT	  do not convert the operands
131916179Sralph 		OTHER	  handled by code
132016179Sralph 		NCVTR	  convert the left operand, not the right...
132116179Sralph 
132216179Sralph 	*/
132316179Sralph 
132416179Sralph # define MINT 01  /* integer */
132516179Sralph # define MDBI 02   /* integer or double */
132616179Sralph # define MSTR 04  /* structure */
132716179Sralph # define MPTR 010  /* pointer */
132816179Sralph # define MPTI 020  /* pointer or integer */
132916179Sralph # define MENU 040 /* enumeration variable or member */
133024408Smckusick # define MVOID 0100000 /* void type */
133116179Sralph 
133216179Sralph opact( p )  NODE *p; {
133316179Sralph 
133416179Sralph 	register mt12, mt1, mt2, o;
133516179Sralph 
133624408Smckusick 	mt1 = mt2 = mt12 = 0;
133716179Sralph 
133816179Sralph 	switch( optype(o=p->in.op) ){
133916179Sralph 
134016179Sralph 	case BITYPE:
134124408Smckusick 		mt2 = moditype( p->in.right->in.type );
134216179Sralph 	case UTYPE:
134324408Smckusick 		mt1 = moditype( p->in.left->in.type );
134424408Smckusick 		break;
134516179Sralph 
134616179Sralph 		}
134716179Sralph 
134824408Smckusick 	if( ((mt1 | mt2) & MVOID) &&
134924408Smckusick 	    o != COMOP &&
135032845Sdonn 	    o != COLON &&
135132845Sdonn 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
135224408Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
135324408Smckusick 		/* if lhs of RETURN is void, grammar will complain */
135424408Smckusick 		if( o != RETURN )
135524408Smckusick 			uerror( "value of void expression used" );
135624408Smckusick 		return( NCVT );
135724408Smckusick 		}
135824408Smckusick 	mt12 = mt1 & mt2;
135924408Smckusick 
136016179Sralph 	switch( o ){
136116179Sralph 
136216179Sralph 	case NAME :
136316179Sralph 	case STRING :
136416179Sralph 	case ICON :
136516179Sralph 	case FCON :
136617749Sralph 	case DCON :
136716179Sralph 	case CALL :
136816179Sralph 	case UNARY CALL:
136916179Sralph 	case UNARY MUL:
137016179Sralph 		{  return( OTHER ); }
137116179Sralph 	case UNARY MINUS:
137232844Sdonn 		if( mt1 & MENU ) return( 0 );
137316179Sralph 		if( mt1 & MDBI ) return( TYPL );
137416179Sralph 		break;
137516179Sralph 
137616179Sralph 	case COMPL:
137732844Sdonn 		if( mt1 & MENU ) return( 0 );
137816179Sralph 		if( mt1 & MINT ) return( TYPL );
137916179Sralph 		break;
138016179Sralph 
138116179Sralph 	case UNARY AND:
138216179Sralph 		{  return( NCVT+OTHER ); }
138316179Sralph 	case INIT:
138416179Sralph 	case CM:
138516180Sralph 		return( 0 );
138616180Sralph 
138716179Sralph 	case NOT:
138816179Sralph 	case CBRANCH:
138916180Sralph 		if( mt1 & MSTR ) break;
139016180Sralph 		return( 0 );
139116180Sralph 
139216179Sralph 	case ANDAND:
139316179Sralph 	case OROR:
139416180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
139516179Sralph 		return( 0 );
139616179Sralph 
139716179Sralph 	case MUL:
139816179Sralph 	case DIV:
139916179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
140016179Sralph 		break;
140116179Sralph 
140216179Sralph 	case MOD:
140316179Sralph 	case AND:
140416179Sralph 	case OR:
140516179Sralph 	case ER:
140616179Sralph 		if( mt12 & MINT ) return( TYMATCH );
140716179Sralph 		break;
140816179Sralph 
140916179Sralph 	case LS:
141016179Sralph 	case RS:
141116179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
141216179Sralph 		break;
141316179Sralph 
141416179Sralph 	case EQ:
141516179Sralph 	case NE:
141616179Sralph 	case LT:
141716179Sralph 	case LE:
141816179Sralph 	case GT:
141916179Sralph 	case GE:
142032844Sdonn 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
142132844Sdonn 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
142216179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
142316179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
142416179Sralph 		else break;
142516179Sralph 
142616179Sralph 	case QUEST:
142716179Sralph 	case COMOP:
142816179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
142916179Sralph 		return( TYPR );
143016179Sralph 
143116179Sralph 	case STREF:
143216179Sralph 		return( NCVTR+OTHER );
143316179Sralph 
143416179Sralph 	case FORCE:
143516179Sralph 		return( TYPL );
143616179Sralph 
143716179Sralph 	case COLON:
143832844Sdonn 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
143932844Sdonn 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
144016179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
144116179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
144216179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
144316179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
144432845Sdonn 		else if( mt12 == MVOID ) return( NCVT+TYPL );
144516179Sralph 		break;
144616179Sralph 
144716179Sralph 	case ASSIGN:
144816179Sralph 	case RETURN:
144916179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
145032844Sdonn 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
145116179Sralph 	case CAST:
145232846Sdonn 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
145332844Sdonn 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
145432846Sdonn 		else if( mt2 == MVOID &&
145518436Smckusick 		        ( p->in.right->in.op == CALL ||
145618436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
145716179Sralph 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
145816179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
145916179Sralph 		break;
146016179Sralph 
146116179Sralph 	case ASG LS:
146216179Sralph 	case ASG RS:
146316179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
146416179Sralph 		break;
146516179Sralph 
146616179Sralph 	case ASG MUL:
146716179Sralph 	case ASG DIV:
146816179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
146916179Sralph 		break;
147016179Sralph 
147116179Sralph 	case ASG MOD:
147216179Sralph 	case ASG AND:
147316179Sralph 	case ASG OR:
147416179Sralph 	case ASG ER:
147516179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
147616179Sralph 		break;
147716179Sralph 
147816179Sralph 	case ASG PLUS:
147916179Sralph 	case ASG MINUS:
148016179Sralph 	case INCR:
148116179Sralph 	case DECR:
148216179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
148316179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
148416179Sralph 		break;
148516179Sralph 
148616179Sralph 	case MINUS:
148716179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
148816179Sralph 		if( mt2 & MPTR ) break;
148916179Sralph 	case PLUS:
149016179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
149116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
149216179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
149316179Sralph 
149416179Sralph 		}
149524408Smckusick 	if( mt12 == MSTR )
149624408Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
149724408Smckusick 	else
149824408Smckusick 		uerror( "operands of %s have incompatible types", opst[o] );
149916179Sralph 	return( NCVT );
150016179Sralph 	}
150116179Sralph 
150216179Sralph moditype( ty ) TWORD ty; {
150316179Sralph 
150416179Sralph 	switch( ty ){
150516179Sralph 
150616179Sralph 	case TVOID:
150717206Sralph 		return( MPTR );
150816179Sralph 	case UNDEF:
150924408Smckusick 		return( MVOID );
151016179Sralph 	case ENUMTY:
151116179Sralph 	case MOETY:
151232840Sdonn 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
151316179Sralph 
151416179Sralph 	case STRTY:
151516179Sralph 	case UNIONTY:
151616179Sralph 		return( MSTR );
151716179Sralph 
151816179Sralph 	case CHAR:
151916179Sralph 	case SHORT:
152016179Sralph 	case UCHAR:
152116179Sralph 	case USHORT:
152216179Sralph 		return( MINT|MPTI|MDBI );
152316179Sralph 	case UNSIGNED:
152416179Sralph 	case ULONG:
152516179Sralph 	case INT:
152616179Sralph 	case LONG:
152716179Sralph 		return( MINT|MDBI|MPTI );
152816179Sralph 	case FLOAT:
152916179Sralph 	case DOUBLE:
153016179Sralph 		return( MDBI );
153116179Sralph 	default:
153216179Sralph 		return( MPTR|MPTI );
153316179Sralph 
153416179Sralph 		}
153516179Sralph 	}
153616179Sralph 
153716179Sralph NODE *
153816179Sralph doszof( p )  register NODE *p; {
153916179Sralph 	/* do sizeof p */
154016179Sralph 	int i;
154116179Sralph 
154216179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
154316179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
154416179Sralph 
154516179Sralph 	tfree(p);
154616179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
154716179Sralph 	return( bcon( i ) );
154816179Sralph 	}
154916179Sralph 
155016179Sralph # ifndef BUG2
155116179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
155216179Sralph 	register ty;
155316179Sralph 
155416179Sralph 	*a = *b = down+1;
155516179Sralph 	while( down > 1 ){
155616179Sralph 		printf( "\t" );
155716179Sralph 		down -= 2;
155816179Sralph 		}
155916179Sralph 	if( down ) printf( "    " );
156016179Sralph 
156116179Sralph 	ty = optype( p->in.op );
156216179Sralph 
156316179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
156416179Sralph 	if( ty == LTYPE ){
156516179Sralph 		printf( CONFMT, p->tn.lval );
156616179Sralph 		printf( ", %d, ", p->tn.rval );
156716179Sralph 		}
156816179Sralph 	tprint( p->in.type );
156916179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
157016179Sralph 	}
157116179Sralph # endif
157216179Sralph 
1573*32850Sdonn #ifndef PRTDCON
157416179Sralph prtdcon( p ) register NODE *p; {
157517749Sralph 	int o = p->in.op, i;
157616179Sralph 
157717749Sralph 	if( o == DCON || o == FCON ){
157816179Sralph 		locctr( DATA );
157917749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
158016179Sralph 		deflab( i = getlab() );
158117749Sralph 		if( o == FCON )
158217749Sralph 			fincode( p->fpn.fval, SZFLOAT );
158317749Sralph 		else
158417749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
158516179Sralph 		p->tn.lval = 0;
158616179Sralph 		p->tn.rval = -i;
158717749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
158816179Sralph 		p->in.op = NAME;
158916179Sralph 		}
159016179Sralph 	}
1591*32850Sdonn #endif PRTDCON
159216179Sralph 
159316179Sralph 
159416179Sralph int edebug = 0;
159516179Sralph ecomp( p ) register NODE *p; {
159616179Sralph # ifndef BUG2
159716179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
159816179Sralph # endif
159916179Sralph 	if( !reached ){
160016179Sralph 		werror( "statement not reached" );
160116179Sralph 		reached = 1;
160216179Sralph 		}
160316179Sralph 	p = optim(p);
160416179Sralph 	walkf( p, prtdcon );
160516179Sralph 	locctr( PROG );
160616179Sralph 	ecode( p );
160716179Sralph 	tfree(p);
160816179Sralph 	}
160916179Sralph 
161016179Sralph # ifdef STDPRTREE
161116179Sralph # ifndef ONEPASS
161216179Sralph 
161316179Sralph prtree(p) register NODE *p; {
161416179Sralph 
161516179Sralph 	register struct symtab *q;
161616179Sralph 	register ty;
161716179Sralph 
161816179Sralph # ifdef MYPRTREE
161916179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
162016179Sralph #endif
162116179Sralph 
162216179Sralph 	ty = optype(p->in.op);
162316179Sralph 
162416179Sralph 	printf( "%d\t", p->in.op );
162516179Sralph 
162616179Sralph 	if( ty == LTYPE ) {
162716179Sralph 		printf( CONFMT, p->tn.lval );
162816179Sralph 		printf( "\t" );
162916179Sralph 		}
163016179Sralph 	if( ty != BITYPE ) {
163116179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
163216179Sralph 		else printf( "%d\t", p->tn.rval );
163316179Sralph 		}
163416179Sralph 
163516179Sralph 	printf( "%o\t", p->in.type );
163616179Sralph 
163716179Sralph 	/* handle special cases */
163816179Sralph 
163916179Sralph 	switch( p->in.op ){
164016179Sralph 
164116179Sralph 	case NAME:
164216179Sralph 	case ICON:
164316179Sralph 		/* print external name */
164416179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
164516179Sralph 		else if( p->tn.rval >= 0 ){
164616179Sralph 			q = &stab[p->tn.rval];
164716179Sralph 			printf(  "%s\n", exname(q->sname) );
164816179Sralph 			}
164916179Sralph 		else { /* label */
165016179Sralph 			printf( LABFMT, -p->tn.rval );
165116179Sralph 			}
165216179Sralph 		break;
165316179Sralph 
165416179Sralph 	case STARG:
165516179Sralph 	case STASG:
165616179Sralph 	case STCALL:
165716179Sralph 	case UNARY STCALL:
165816179Sralph 		/* print out size */
165916179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
166016179Sralph 
166116179Sralph 		/* note: p->in.left not a field... */
166216179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
166316179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
166416179Sralph 		break;
166516179Sralph 
166616179Sralph 	default:
166716179Sralph 		printf(  "\n" );
166816179Sralph 		}
166916179Sralph 
167016179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
167116179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
167216179Sralph 
167316179Sralph 	}
167416179Sralph 
167516179Sralph # else
167616179Sralph 
167716179Sralph p2tree(p) register NODE *p; {
167816179Sralph 	register ty;
167916179Sralph 
168016179Sralph # ifdef MYP2TREE
168116179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
168216179Sralph # endif
168316179Sralph 
168416179Sralph 	ty = optype(p->in.op);
168516179Sralph 
168616179Sralph 	switch( p->in.op ){
168716179Sralph 
168816179Sralph 	case NAME:
168916179Sralph 	case ICON:
169016179Sralph #ifndef FLEXNAMES
169116179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
169216179Sralph #else
169316179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
169416179Sralph #endif
169516179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
169616179Sralph 			register char *cp;
169716179Sralph 			register i;
169816179Sralph 			cp = exname( stab[p->tn.rval].sname );
169916179Sralph #ifndef FLEXNAMES
170016179Sralph 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
170116179Sralph #else
170216179Sralph 			p->in.name = tstr(cp);
170316179Sralph #endif
170416179Sralph 			}
170516179Sralph #ifndef FLEXNAMES
170616179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
170716179Sralph #else
170816179Sralph 		else {
170916179Sralph 			char temp[32];
171016179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
171116179Sralph 			p->in.name = tstr(temp);
171216179Sralph 		}
171316179Sralph #endif
171416179Sralph 		break;
171516179Sralph 
171616179Sralph 	case STARG:
171716179Sralph 	case STASG:
171816179Sralph 	case STCALL:
171916179Sralph 	case UNARY STCALL:
172016179Sralph 		/* set up size parameters */
172116179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
172216179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
172316179Sralph 		break;
172416179Sralph 
172516179Sralph 	case REG:
172616179Sralph 		rbusy( p->tn.rval, p->in.type );
172716179Sralph 	default:
172816179Sralph #ifndef FLEXNAMES
172916179Sralph 		p->in.name[0] = '\0';
173016179Sralph #else
173116179Sralph 		p->in.name = "";
173216179Sralph #endif
173316179Sralph 		}
173416179Sralph 
173516179Sralph 	p->in.rall = NOPREF;
173616179Sralph 
173716179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
173816179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
173916179Sralph 	}
174016179Sralph 
174116179Sralph # endif
174216179Sralph # endif
1743