xref: /csrg-svn/old/pcc/mip/trees.c (revision 34092)
117749Sralph #ifndef lint
2*34092Sbostic static char *sccsid ="@(#)trees.c	4.35 (Berkeley) 04/24/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 
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:
15332851Sdonn 			if( l->in.type == ENUMTY && r->in.type == ENUMTY ){
15432851Sdonn 				p = block( o, l, r, INT, 0, INT );
15532840Sdonn 				chkpun( p );
15632851Sdonn 				p->in.op = FREE;
15732851Sdonn 				}
15832840Sdonn 
15916179Sralph 		case ANDAND:
16016179Sralph 		case OROR:
16116179Sralph 		case CBRANCH:
16216179Sralph 
16316179Sralph 		ccwarn:
16416179Sralph 			if( hflag ) werror( "constant in conditional context" );
16516179Sralph 
16616179Sralph 		case PLUS:
16716179Sralph 		case MINUS:
16816179Sralph 		case MUL:
16916179Sralph 		case DIV:
17016179Sralph 		case MOD:
17116179Sralph 		case AND:
17216179Sralph 		case OR:
17316179Sralph 		case ER:
17416179Sralph 		case LS:
17516179Sralph 		case RS:
17616179Sralph 			if( conval( l, o, r ) ) {
17716179Sralph 				r->in.op = FREE;
17816179Sralph 				return(l);
17916179Sralph 				}
18016179Sralph 			break;
18116179Sralph 			}
18216179Sralph 		}
18324408Smckusick 	else if (opty == BITYPE &&
18424408Smckusick 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
18524408Smckusick 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
18624408Smckusick 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
18724408Smckusick 				extern int fpe_count;
18824408Smckusick 				extern jmp_buf gotfpe;
18916179Sralph 
19024408Smckusick 				fpe_count = 0;
19124408Smckusick 				if (setjmp(gotfpe))
19224408Smckusick 					goto treatfpe;
19317749Sralph 				if (l->in.op == ICON)
19417749Sralph 					l->dpn.dval = l->tn.lval;
19524408Smckusick 				else if (l->in.op == FCON)
19624408Smckusick 					l->dpn.dval = l->fpn.fval;
19717749Sralph 				if (r->in.op == ICON)
19817749Sralph 					r->dpn.dval = r->tn.lval;
19924408Smckusick 				else if (r->in.op == FCON)
20024408Smckusick 					r->dpn.dval = r->fpn.fval;
20117749Sralph 				switch (o) {
20217749Sralph 
20317749Sralph 				case PLUS:
20417749Sralph 					l->dpn.dval += r->dpn.dval;
20524408Smckusick 					break;
20617749Sralph 
20717749Sralph 				case MINUS:
20817749Sralph 					l->dpn.dval -= r->dpn.dval;
20924408Smckusick 					break;
21017749Sralph 
21117749Sralph 				case MUL:
21217749Sralph 					l->dpn.dval *= r->dpn.dval;
21324408Smckusick 					break;
21417749Sralph 
21517749Sralph 				case DIV:
21617749Sralph 					if (r->dpn.dval == 0)
21717749Sralph 						uerror("division by 0.");
21817749Sralph 					else
21917749Sralph 						l->dpn.dval /= r->dpn.dval;
22024408Smckusick 					break;
22124408Smckusick 					}
22224408Smckusick 			treatfpe:
22324408Smckusick 				if (fpe_count > 0) {
22424408Smckusick 					uerror("floating point exception in constant expression");
22524408Smckusick 					l->dpn.dval = 1.0; /* Fairly harmless */
22624408Smckusick 					}
22724408Smckusick 				fpe_count = -1;
22824408Smckusick 				l->in.op = DCON;
22924408Smckusick 				l->in.type = l->fn.csiz = DOUBLE;
23024408Smckusick 				r->in.op = FREE;
23124408Smckusick 				return (l);
23216179Sralph 			}
23324408Smckusick 		}
23416179Sralph 
23524408Smckusick 	/* it's real; we must make a new node */
23616179Sralph 
23716179Sralph 	p = block( o, l, r, INT, 0, INT );
23816179Sralph 
23916179Sralph 	actions = opact(p);
24017749Sralph #ifndef	BUG1
24117749Sralph 	if (adebug)
24217749Sralph 		printact(p, actions);
24317749Sralph #endif
24416179Sralph 
24516179Sralph 	if( actions&LVAL ){ /* check left descendent */
24616179Sralph 		if( notlval(p->in.left) ) {
24732849Sdonn 			uerror( "illegal lvalue operand of assignment operator" );
24816179Sralph 			}
24916179Sralph 		}
25016179Sralph 
25116179Sralph 	if( actions & NCVTR ){
25216179Sralph 		p->in.left = pconvert( p->in.left );
25316179Sralph 		}
25416179Sralph 	else if( !(actions & NCVT ) ){
25516179Sralph 		switch( opty ){
25616179Sralph 
25716179Sralph 		case BITYPE:
25816179Sralph 			p->in.right = pconvert( p->in.right );
25916179Sralph 		case UTYPE:
26016179Sralph 			p->in.left = pconvert( p->in.left );
26116179Sralph 
26216179Sralph 			}
26316179Sralph 		}
26416179Sralph 
26516179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
26616179Sralph 		chkpun(p);
26716179Sralph 		}
26816179Sralph 
26916179Sralph 	if( actions & (TYPL|TYPR) ){
27016179Sralph 
27116179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
27216179Sralph 
27316179Sralph 		p->in.type = q->in.type;
27416179Sralph 		p->fn.cdim = q->fn.cdim;
27516179Sralph 		p->fn.csiz = q->fn.csiz;
27616179Sralph 		}
27716179Sralph 
27816179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
27916179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
28016179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
28116179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
28216179Sralph 
28316179Sralph 	if( actions & OTHER ){
28416179Sralph 		l = p->in.left;
28516179Sralph 		r = p->in.right;
28616179Sralph 
28716179Sralph 		switch(o){
28816179Sralph 
28916179Sralph 		case NAME:
29016179Sralph 			sp = &stab[idname];
29116179Sralph 			if( sp->stype == UNDEF ){
29216179Sralph #ifndef FLEXNAMES
29316179Sralph 				uerror( "%.8s undefined", sp->sname );
29416179Sralph #else
29516179Sralph 				uerror( "%s undefined", sp->sname );
29616179Sralph #endif
29716179Sralph 				/* make p look reasonable */
29816179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
29916179Sralph 				p->tn.rval = idname;
30016179Sralph 				p->tn.lval = 0;
30116179Sralph 				defid( p, SNULL );
30216179Sralph 				break;
30316179Sralph 				}
30416179Sralph 			p->in.type = sp->stype;
30516179Sralph 			p->fn.cdim = sp->dimoff;
30616179Sralph 			p->fn.csiz = sp->sizoff;
30716179Sralph 			p->tn.lval = 0;
30816179Sralph 			p->tn.rval = idname;
30916179Sralph 			/* special case: MOETY is really an ICON... */
31016179Sralph 			if( p->in.type == MOETY ){
31116179Sralph 				p->tn.rval = NONAME;
31216179Sralph 				p->tn.lval = sp->offset;
31316179Sralph 				p->fn.cdim = 0;
31416179Sralph 				p->in.type = ENUMTY;
31516179Sralph 				p->in.op = ICON;
31616179Sralph 				}
31716179Sralph 			break;
31816179Sralph 
31916179Sralph 		case ICON:
32016179Sralph 			p->in.type = INT;
32116179Sralph 			p->fn.cdim = 0;
32216179Sralph 			p->fn.csiz = INT;
32316179Sralph 			break;
32416179Sralph 
32516179Sralph 		case STRING:
32616179Sralph 			p->in.op = NAME;
32716179Sralph 			p->in.type = CHAR+ARY;
32816179Sralph 			p->tn.lval = 0;
32916179Sralph 			p->tn.rval = NOLAB;
33016179Sralph 			p->fn.cdim = curdim;
33116179Sralph 			p->fn.csiz = CHAR;
33216179Sralph 			break;
33316179Sralph 
33416179Sralph 		case FCON:
33516179Sralph 			p->tn.lval = 0;
33616179Sralph 			p->tn.rval = 0;
33717749Sralph 			p->in.type = FLOAT;
33817749Sralph 			p->fn.cdim = 0;
33917749Sralph 			p->fn.csiz = FLOAT;
34017749Sralph 			break;
34117749Sralph 
34217749Sralph 		case DCON:
34317749Sralph 			p->tn.lval = 0;
34417749Sralph 			p->tn.rval = 0;
34516179Sralph 			p->in.type = DOUBLE;
34616179Sralph 			p->fn.cdim = 0;
34716179Sralph 			p->fn.csiz = DOUBLE;
34816179Sralph 			break;
34916179Sralph 
35016179Sralph 		case STREF:
35116179Sralph 			/* p->x turned into *(p+offset) */
35216179Sralph 			/* rhs must be a name; check correctness */
35316179Sralph 
35416179Sralph 			i = r->tn.rval;
35516179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
35616179Sralph 				uerror( "member of structure or union required" );
35716179Sralph 				}else
35816179Sralph 			/* if this name is non-unique, find right one */
35916179Sralph 			if( stab[i].sflags & SNONUNIQ &&
36016179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
36116179Sralph 				(l->fn.csiz +1) >= 0 ){
36216179Sralph 				/* nonunique name && structure defined */
36316179Sralph 				char * memnam, * tabnam;
36416179Sralph 				int j;
36516179Sralph 				int memi;
36616179Sralph 				j=dimtab[l->fn.csiz+1];
36716179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
36816179Sralph 					tabnam = stab[memi].sname;
36916179Sralph 					memnam = stab[i].sname;
37016179Sralph # ifndef BUG1
37116179Sralph 					if( ddebug>1 ){
37216179Sralph #ifndef FLEXNAMES
37316179Sralph 						printf("member %.8s==%.8s?\n",
37416179Sralph #else
37516179Sralph 						printf("member %s==%s?\n",
37616179Sralph #endif
37716179Sralph 							memnam, tabnam);
37816179Sralph 						}
37916179Sralph # endif
38016179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
38116179Sralph #ifndef FLEXNAMES
38232851Sdonn 						register k;
38316179Sralph 						for( k=0; k<NCHNAM; ++k ){
38416179Sralph 							if(*memnam++!=*tabnam)
38516179Sralph 								goto next;
38616179Sralph 							if(!*tabnam++) break;
38716179Sralph 							}
38816179Sralph #else
38916179Sralph 						if (memnam != tabnam)
39016179Sralph 							goto next;
39116179Sralph #endif
39216179Sralph 						r->tn.rval = i = memi;
39316179Sralph 						break;
39416179Sralph 						}
39516179Sralph 					next: continue;
39616179Sralph 					}
39716179Sralph 				if( memi < 0 )
39816179Sralph #ifndef FLEXNAMES
39916179Sralph 					uerror("illegal member use: %.8s",
40016179Sralph #else
40116179Sralph 					uerror("illegal member use: %s",
40216179Sralph #endif
40316179Sralph 						stab[i].sname);
40416179Sralph 				}
40516179Sralph 			else {
40616179Sralph 				register j;
40716179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
40816179Sralph 					if( stab[i].sflags & SNONUNIQ ){
40916179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
41016179Sralph 						}
41116179Sralph 					else werror( "struct/union or struct/union pointer required" );
41216179Sralph 					}
41316179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
41416179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
41516179Sralph #ifndef FLEXNAMES
41616179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
41716179Sralph #else
41816179Sralph 					werror( "illegal member use: %s", stab[i].sname );
41916179Sralph #endif
42016179Sralph 					}
42116179Sralph 				}
42216179Sralph 
42316179Sralph 			p = stref( p );
42416179Sralph 			break;
42516179Sralph 
42616179Sralph 		case UNARY MUL:
42716179Sralph 			if( l->in.op == UNARY AND ){
42816179Sralph 				p->in.op = l->in.op = FREE;
42916179Sralph 				p = l->in.left;
43016179Sralph 				}
43116179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
43216179Sralph 			p->in.type = DECREF(l->in.type);
43316179Sralph 			p->fn.cdim = l->fn.cdim;
43416179Sralph 			p->fn.csiz = l->fn.csiz;
43516179Sralph 			break;
43616179Sralph 
43716179Sralph 		case UNARY AND:
43816179Sralph 			switch( l->in.op ){
43916179Sralph 
44016179Sralph 			case UNARY MUL:
44116179Sralph 				p->in.op = l->in.op = FREE;
44216179Sralph 				p = l->in.left;
44316179Sralph 			case NAME:
44416179Sralph 				p->in.type = INCREF( l->in.type );
44516179Sralph 				p->fn.cdim = l->fn.cdim;
44616179Sralph 				p->fn.csiz = l->fn.csiz;
44716179Sralph 				break;
44816179Sralph 
44916179Sralph 			case COMOP:
45016179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
45116179Sralph 				p->in.op = l->in.op = FREE;
45216179Sralph 				p = buildtree( COMOP, l->in.left, lr );
45316179Sralph 				break;
45416179Sralph 
45516179Sralph 			case QUEST:
45616179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
45716179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
45816179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
45916179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
46016179Sralph 				break;
46116179Sralph 
46216179Sralph # ifdef ADDROREG
46316179Sralph 			case OREG:
46416179Sralph 				/* OREG was built in clocal()
46516179Sralph 				 * for an auto or formal parameter
46616179Sralph 				 * now its address is being taken
46716179Sralph 				 * local code must unwind it
46816179Sralph 				 * back to PLUS/MINUS REG ICON
46916179Sralph 				 * according to local conventions
47016179Sralph 				 */
47116179Sralph 				{
47216179Sralph 				extern NODE * addroreg();
47316179Sralph 				p->in.op = FREE;
47416179Sralph 				p = addroreg( l );
47516179Sralph 				}
47616179Sralph 				break;
47716179Sralph 
47816179Sralph # endif
47916179Sralph 			default:
48016179Sralph 				uerror( "unacceptable operand of &" );
48116179Sralph 				break;
48216179Sralph 				}
48316179Sralph 			break;
48416179Sralph 
48516179Sralph 		case LS:
48616179Sralph 		case RS:
48716179Sralph 		case ASG LS:
48816179Sralph 		case ASG RS:
48916179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
49016179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
49116179Sralph 			break;
49216179Sralph 
49316179Sralph 		case RETURN:
49416179Sralph 		case ASSIGN:
49516179Sralph 		case CAST:
49616179Sralph 			/* structure assignment */
49716179Sralph 			/* take the addresses of the two sides; then make an
49816179Sralph 			/* operator using STASG and
49916179Sralph 			/* the addresses of left and right */
50016179Sralph 
50116179Sralph 			{
50216179Sralph 				register TWORD t;
50316179Sralph 				register d, s;
50416179Sralph 
50516179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
50616179Sralph 
50716179Sralph 				r = buildtree( UNARY AND, r, NIL );
50816179Sralph 				t = r->in.type;
50916179Sralph 				d = r->fn.cdim;
51016179Sralph 				s = r->fn.csiz;
51116179Sralph 
51216179Sralph 				l = block( STASG, l, r, t, d, s );
51316179Sralph 
51416179Sralph 				if( o == RETURN ){
51516179Sralph 					p->in.op = FREE;
51616179Sralph 					p = l;
51716179Sralph 					break;
51816179Sralph 					}
51916179Sralph 
52016179Sralph 				p->in.op = UNARY MUL;
52116179Sralph 				p->in.left = l;
52216179Sralph 				p->in.right = NIL;
52316179Sralph 				break;
52416179Sralph 				}
52516179Sralph 		case COLON:
52616179Sralph 			/* structure colon */
52716179Sralph 
52816179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
52916179Sralph 			break;
53016179Sralph 
53116179Sralph 		case CALL:
53217749Sralph 			p->in.right = r = fixargs( p->in.right );
53316179Sralph 		case UNARY CALL:
53416179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
53516179Sralph 			p->in.type = DECREF(l->in.type);
53616179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
53716179Sralph 			p->in.type = DECREF( p->in.type );
53816179Sralph 			p->fn.cdim = l->fn.cdim;
53916179Sralph 			p->fn.csiz = l->fn.csiz;
54016179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
54116179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
54216179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
54316179Sralph 				p->in.op += (FORTCALL-CALL);
54416179Sralph 				}
54516179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
54616179Sralph 				/* function returning structure */
54716179Sralph 				/*  make function really return ptr to str., with * */
54816179Sralph 
54916179Sralph 				p->in.op += STCALL-CALL;
55016179Sralph 				p->in.type = INCREF( p->in.type );
55116179Sralph 				p = buildtree( UNARY MUL, p, NIL );
55216179Sralph 
55316179Sralph 				}
55416179Sralph 			break;
55516179Sralph 
55616179Sralph 		default:
55716179Sralph 			cerror( "other code %d", o );
55816179Sralph 			}
55916179Sralph 
56016179Sralph 		}
56116179Sralph 
56216179Sralph 	if( actions & CVTO ) p = oconvert(p);
56316179Sralph 	p = clocal(p);
56416179Sralph 
56516179Sralph # ifndef BUG1
56616179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
56716179Sralph # endif
56816179Sralph 
56916179Sralph 	return(p);
57016179Sralph 
57116179Sralph 	}
57216179Sralph 
57324408Smckusick int fpe_count = -1;
57424408Smckusick jmp_buf gotfpe;
57524408Smckusick 
57624408Smckusick fpe() {
57724408Smckusick 	if (fpe_count < 0)
57824408Smckusick 		cerror("floating point exception");
57924408Smckusick 	++fpe_count;
58024408Smckusick 	longjmp(gotfpe, 1);
58124408Smckusick 	}
58224408Smckusick 
58317749Sralph /*
58417749Sralph  * Rewrite arguments in a function call.
58517749Sralph  * Structure arguments are massaged, single
58617749Sralph  * precision floating point constants are
58717749Sralph  * cast to double (to eliminate convert code).
58817749Sralph  */
58916179Sralph NODE *
59017749Sralph fixargs( p ) register NODE *p;  {
59117749Sralph 	int o = p->in.op;
59216179Sralph 
59317749Sralph 	if( o == CM ){
59417749Sralph 		p->in.left = fixargs( p->in.left );
59517749Sralph 		p->in.right = fixargs( p->in.right );
59616179Sralph 		return( p );
59716179Sralph 		}
59816179Sralph 
59916179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
60016179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
60116179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
60216179Sralph 		p = clocal(p);
60316179Sralph 		}
60417749Sralph 	else if( o == FCON )
60517749Sralph 		p = makety(p, DOUBLE, 0, 0);
60616179Sralph 	return( p );
60716179Sralph 	}
60816179Sralph 
60916179Sralph chkstr( i, j, type ) TWORD type; {
61016179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
61116179Sralph 	/* i has been checked to contain a MOS or MOU */
61216179Sralph 	/* j is the index in dimtab of the members... */
61316179Sralph 	int k, kk;
61416179Sralph 
61516179Sralph 	extern int ddebug;
61616179Sralph 
61716179Sralph # ifndef BUG1
61816179Sralph #ifndef FLEXNAMES
61916179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
62016179Sralph #else
62116179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
62216179Sralph #endif
62316179Sralph # endif
62416179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
62516179Sralph 	else {
62616179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
62716179Sralph 			if( kk >= SYMTSZ ){
62816179Sralph 				cerror( "gummy structure" );
62916179Sralph 				return(1);
63016179Sralph 				}
63116179Sralph 			if( kk == i ) return( 1 );
63216179Sralph 			switch( stab[kk].stype ){
63316179Sralph 
63416179Sralph 			case STRTY:
63516179Sralph 			case UNIONTY:
63616179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
63716179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
63816179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
63916179Sralph 					werror(
64016179Sralph #ifndef FLEXNAMES
64116179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
64216179Sralph #else
64316179Sralph 					"illegal member use: perhaps %s.%s?",
64416179Sralph #endif
64516179Sralph 					stab[kk].sname, stab[i].sname );
64616179Sralph 					return(1);
64716179Sralph 					}
64816179Sralph 				}
64916179Sralph 			}
65016179Sralph 		}
65116179Sralph 	return( 0 );
65216179Sralph 	}
65316179Sralph 
65416179Sralph conval( p, o, q ) register NODE *p, *q; {
65516179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
65632842Sdonn 	/* works only on integer constants */
65732842Sdonn 	NODE *r;
65816179Sralph 	int i, u;
65916179Sralph 	CONSZ val;
66032857Sdonn 	TWORD utype;
66116179Sralph 
66216179Sralph 	val = q->tn.lval;
66316179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
66416179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
66516179Sralph 
66616179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
66716179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
66816179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
66916179Sralph 
67032857Sdonn 	/* usual type conversions -- handle casts of constants */
67132859Sdonn #define	ISLONG(t)	((t) == LONG || (t) == ULONG)
67232859Sdonn 	if (ISLONG(p->in.type) || ISLONG(q->in.type))
67332859Sdonn 		utype = u ? ULONG : LONG;
67432859Sdonn 	else
67532859Sdonn 		utype = u ? UNSIGNED : INT;
67632857Sdonn 	if( !ISPTR(p->in.type) && p->in.type != utype )
67732857Sdonn 		p = makety(p, utype, 0, (int)utype);
67832857Sdonn 	if( q->in.type != utype )
67932857Sdonn 		q = makety(q, utype, 0, (int)utype);
68032842Sdonn 
68116179Sralph 	switch( o ){
68216179Sralph 
68316179Sralph 	case PLUS:
68416179Sralph 		p->tn.lval += val;
68516179Sralph 		if( p->tn.rval == NONAME ){
68616179Sralph 			p->tn.rval = q->tn.rval;
68716179Sralph 			p->in.type = q->in.type;
68816179Sralph 			}
68916179Sralph 		break;
69016179Sralph 	case MINUS:
69116179Sralph 		p->tn.lval -= val;
69216179Sralph 		break;
69316179Sralph 	case MUL:
69432840Sdonn 		p->tn.lval *= val;
69516179Sralph 		break;
69616179Sralph 	case DIV:
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 MOD:
70216179Sralph 		if( val == 0 ) uerror( "division by 0" );
70317749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
70416179Sralph 		else p->tn.lval %= val;
70516179Sralph 		break;
70616179Sralph 	case AND:
70716179Sralph 		p->tn.lval &= val;
70816179Sralph 		break;
70916179Sralph 	case OR:
71016179Sralph 		p->tn.lval |= val;
71116179Sralph 		break;
71216179Sralph 	case ER:
71317749Sralph 		p->tn.lval ^= val;
71416179Sralph 		break;
71516179Sralph 	case LS:
71616179Sralph 		i = val;
71716179Sralph 		p->tn.lval = p->tn.lval << i;
71816179Sralph 		break;
71916179Sralph 	case RS:
72016179Sralph 		i = val;
72117749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
72217749Sralph 		else p->tn.lval = p->tn.lval >> i;
72316179Sralph 		break;
72416179Sralph 
72516179Sralph 	case UNARY MINUS:
72616179Sralph 		p->tn.lval = - p->tn.lval;
72716179Sralph 		break;
72816179Sralph 	case COMPL:
72916179Sralph 		p->tn.lval = ~p->tn.lval;
73016179Sralph 		break;
73116179Sralph 	case NOT:
73216179Sralph 		p->tn.lval = !p->tn.lval;
73316179Sralph 		break;
73416179Sralph 	case LT:
73516179Sralph 		p->tn.lval = p->tn.lval < val;
73616179Sralph 		break;
73716179Sralph 	case LE:
73816179Sralph 		p->tn.lval = p->tn.lval <= val;
73916179Sralph 		break;
74016179Sralph 	case GT:
74116179Sralph 		p->tn.lval = p->tn.lval > val;
74216179Sralph 		break;
74316179Sralph 	case GE:
74416179Sralph 		p->tn.lval = p->tn.lval >= val;
74516179Sralph 		break;
74616179Sralph 	case ULT:
74732848Sdonn 		p->tn.lval = p->tn.lval < (unsigned) val;
74816179Sralph 		break;
74916179Sralph 	case ULE:
75032848Sdonn 		p->tn.lval = p->tn.lval <= (unsigned) val;
75116179Sralph 		break;
75232848Sdonn 	case UGT:
75332848Sdonn 		p->tn.lval = p->tn.lval > (unsigned) val;
75432848Sdonn 		break;
75532840Sdonn 	case UGE:
75632848Sdonn 		p->tn.lval = p->tn.lval >= (unsigned) val;
75732840Sdonn 		break;
75816179Sralph 	case EQ:
75916179Sralph 		p->tn.lval = p->tn.lval == val;
76016179Sralph 		break;
76116179Sralph 	case NE:
76216179Sralph 		p->tn.lval = p->tn.lval != val;
76316179Sralph 		break;
76416179Sralph 	default:
76516179Sralph 		return(0);
76616179Sralph 		}
76716179Sralph 	return(1);
76816179Sralph 	}
76916179Sralph 
77016179Sralph chkpun(p) register NODE *p; {
77116179Sralph 
77216179Sralph 	/* checks p for the existance of a pun */
77316179Sralph 
77416179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
77516179Sralph 
77616179Sralph 	/* one case is when enumerations are used: this applies only to lint */
77716179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
77816179Sralph 	/* we check that this integer is in fact a constant zero... */
77916179Sralph 
78016179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
78116179Sralph 	/* this falls out, because the LHS is never 0 */
78216179Sralph 
78316179Sralph 	register NODE *q;
78416179Sralph 	register t1, t2;
78516179Sralph 	register d1, d2;
78632844Sdonn 	int ref1, ref2;
78716179Sralph 
78816179Sralph 	t1 = p->in.left->in.type;
78916179Sralph 	t2 = p->in.right->in.type;
79016179Sralph 
79116179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
79232841Sdonn 		/* rob pike says this is obnoxious...
79332840Sdonn 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
79432841Sdonn 			werror( "comparison of enums" ); */
79532841Sdonn 		if( t1==ENUMTY && t2==ENUMTY ) {
79632841Sdonn 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
79732841Sdonn 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
79832841Sdonn 			return;
79932841Sdonn 			}
80032841Sdonn 		if ( t1 == ENUMTY ) t1 = INT;
80132841Sdonn 		if ( t2 == ENUMTY ) t2 = INT;
80216179Sralph 		}
80316179Sralph 
80432844Sdonn 	ref1 = ISPTR(t1) || ISARY(t1);
80532844Sdonn 	ref2 = ISPTR(t2) || ISARY(t2);
80616179Sralph 
80732844Sdonn 	if( ref1 ^ ref2 ){
80832844Sdonn 		if( ref1 ) q = p->in.right;
80932844Sdonn 		else q = p->in.left;
81016179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
81116179Sralph 			werror( "illegal combination of pointer and integer, op %s",
81216179Sralph 				opst[p->in.op] );
81316179Sralph 			}
81416179Sralph 		}
81532844Sdonn 	else if( ref1 ){
81632843Sdonn 		if( t1 == t2 ) {
81732843Sdonn 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
81832843Sdonn 				werror( "illegal structure pointer combination" );
81916179Sralph 				return;
82016179Sralph 				}
82132843Sdonn 			d1 = p->in.left->fn.cdim;
82232843Sdonn 			d2 = p->in.right->fn.cdim;
82332843Sdonn 			for( ;; ){
82432843Sdonn 				if( ISARY(t1) ){
82532843Sdonn 					if( dimtab[d1] != dimtab[d2] ){
82632843Sdonn 						werror( "illegal array size combination" );
82732843Sdonn 						return;
82832843Sdonn 						}
82932843Sdonn 					++d1;
83032843Sdonn 					++d2;
83116179Sralph 					}
83232843Sdonn 				else if( !ISPTR(t1) ) break;
83332843Sdonn 				t1 = DECREF(t1);
83416179Sralph 				}
83516179Sralph 			}
83632843Sdonn 		else
83732843Sdonn 			werror( "illegal pointer combination" );
83816179Sralph 		}
83916179Sralph 
84016179Sralph 	}
84116179Sralph 
84216179Sralph NODE *
84316179Sralph stref( p ) register NODE *p; {
84416179Sralph 
84516179Sralph 	TWORD t;
84616179Sralph 	int d, s, dsc, align;
84716179Sralph 	OFFSZ off;
84816179Sralph 	register struct symtab *q;
84916179Sralph 
85016179Sralph 	/* make p->x */
85116179Sralph 	/* this is also used to reference automatic variables */
85216179Sralph 
85316179Sralph 	q = &stab[p->in.right->tn.rval];
85416179Sralph 	p->in.right->in.op = FREE;
85516179Sralph 	p->in.op = FREE;
85616179Sralph 	p = pconvert( p->in.left );
85716179Sralph 
85816179Sralph 	/* make p look like ptr to x */
85916179Sralph 
86016179Sralph 	if( !ISPTR(p->in.type)){
86116179Sralph 		p->in.type = PTR+UNIONTY;
86216179Sralph 		}
86316179Sralph 
86416179Sralph 	t = INCREF( q->stype );
86516179Sralph 	d = q->dimoff;
86616179Sralph 	s = q->sizoff;
86716179Sralph 
86816179Sralph 	p = makety( p, t, d, s );
86916179Sralph 
87016179Sralph 	/* compute the offset to be added */
87116179Sralph 
87216179Sralph 	off = q->offset;
87316179Sralph 	dsc = q->sclass;
87416179Sralph 
87516179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
87616179Sralph 		align = ALINT;
87716179Sralph 		s = INT;
87816179Sralph 		off = (off/align)*align;
87916179Sralph 		}
88016179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
88116179Sralph 
88216179Sralph 	p = buildtree( UNARY MUL, p, NIL );
88316179Sralph 
88416179Sralph 	/* if field, build field info */
88516179Sralph 
88616179Sralph 	if( dsc & FIELD ){
88716179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
88816179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
88916179Sralph 		}
89016179Sralph 
89116179Sralph 	return( clocal(p) );
89216179Sralph 	}
89316179Sralph 
89416179Sralph notlval(p) register NODE *p; {
89516179Sralph 
89616179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
89716179Sralph 
89816179Sralph 	again:
89916179Sralph 
90016179Sralph 	switch( p->in.op ){
90116179Sralph 
90216179Sralph 	case FLD:
90316179Sralph 		p = p->in.left;
90416179Sralph 		goto again;
90516179Sralph 
90616179Sralph 	case UNARY MUL:
90716179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
90816179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
90916179Sralph 		/* and the f().a bug, given that f returns a structure */
91016179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
91116179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
91216179Sralph 	case NAME:
91316179Sralph 	case OREG:
91416179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
91516179Sralph 	case REG:
91616179Sralph 		return(0);
91716179Sralph 
91816179Sralph 	default:
91916179Sralph 		return(1);
92016179Sralph 
92116179Sralph 		}
92216179Sralph 
92316179Sralph 	}
92416179Sralph 
92516179Sralph NODE *
92616179Sralph bcon( i ){ /* make a constant node with value i */
92716179Sralph 	register NODE *p;
92816179Sralph 
92916179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
93016179Sralph 	p->tn.lval = i;
93116179Sralph 	p->tn.rval = NONAME;
93216179Sralph 	return( clocal(p) );
93316179Sralph 	}
93416179Sralph 
93516179Sralph NODE *
93616179Sralph bpsize(p) register NODE *p; {
93716179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
93816179Sralph 	}
93916179Sralph 
94016179Sralph OFFSZ
94116179Sralph psize( p ) NODE *p; {
94216179Sralph 	/* p is a node of type pointer; psize returns the
94316179Sralph 	   size of the thing pointed to */
94416179Sralph 
94516179Sralph 	if( !ISPTR(p->in.type) ){
94616179Sralph 		uerror( "pointer required");
94716179Sralph 		return( SZINT );
94816179Sralph 		}
94916179Sralph 	/* note: no pointers to fields */
95016179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
95116179Sralph 	}
95216179Sralph 
95316179Sralph NODE *
95416179Sralph convert( p, f )  register NODE *p; {
95516179Sralph 	/*  convert an operand of p
95616179Sralph 	    f is either CVTL or CVTR
95716179Sralph 	    operand has type int, and is converted by the size of the other side
95816179Sralph 	    */
95916179Sralph 
96016179Sralph 	register NODE *q, *r;
96116179Sralph 
96216179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
96316179Sralph 
96416179Sralph 	r = block( PMCONV,
96516179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
96616179Sralph 	r = clocal(r);
96716179Sralph 	if( f == CVTL )
96816179Sralph 		p->in.left = r;
96916179Sralph 	else
97016179Sralph 		p->in.right = r;
97116179Sralph 	return(p);
97216179Sralph 
97316179Sralph 	}
97416179Sralph 
97525750Sdonn #ifndef econvert
97616179Sralph econvert( p ) register NODE *p; {
97716179Sralph 
97816179Sralph 	/* change enums to ints, or appropriate types */
97916179Sralph 
98016179Sralph 	register TWORD ty;
98116179Sralph 
98216179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
98316179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
98416179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
98516179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
98616179Sralph 		else ty = LONG;
98716179Sralph 		ty = ctype( ty );
98816179Sralph 		p->fn.csiz = ty;
98916179Sralph 		MODTYPE(p->in.type,ty);
99016179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
99116179Sralph 		}
99216179Sralph 	}
99325750Sdonn #endif
99416179Sralph 
99516179Sralph NODE *
99616179Sralph pconvert( p ) register NODE *p; {
99716179Sralph 
99816179Sralph 	/* if p should be changed into a pointer, do so */
99916179Sralph 
100016179Sralph 	if( ISARY( p->in.type) ){
100116179Sralph 		p->in.type = DECREF( p->in.type );
100216179Sralph 		++p->fn.cdim;
100316179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
100416179Sralph 		}
100516179Sralph 	if( ISFTN( p->in.type) )
100616179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
100716179Sralph 
100816179Sralph 	return( p );
100916179Sralph 	}
101016179Sralph 
101116179Sralph NODE *
101216179Sralph oconvert(p) register NODE *p; {
101316179Sralph 	/* convert the result itself: used for pointer and unsigned */
101416179Sralph 
101516179Sralph 	switch(p->in.op) {
101616179Sralph 
101716179Sralph 	case LE:
101816179Sralph 	case LT:
101916179Sralph 	case GE:
102016179Sralph 	case GT:
102116179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
102216179Sralph 	case EQ:
102316179Sralph 	case NE:
102416179Sralph 		return( p );
102516179Sralph 
102616179Sralph 	case MINUS:
102716179Sralph 		return(  clocal( block( PVCONV,
102816179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
102916179Sralph 		}
103016179Sralph 
103116179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
103216179Sralph 
103316179Sralph 	return(p);
103416179Sralph 	}
103516179Sralph 
103616179Sralph NODE *
103716179Sralph ptmatch(p)  register NODE *p; {
103816179Sralph 
103916179Sralph 	/* makes the operands of p agree; they are
104016179Sralph 	   either pointers or integers, by this time */
104116179Sralph 	/* with MINUS, the sizes must be the same */
104216179Sralph 	/* with COLON, the types must be the same */
104316179Sralph 
104416179Sralph 	TWORD t1, t2, t;
104516179Sralph 	int o, d2, d, s2, s;
104616179Sralph 
104716179Sralph 	o = p->in.op;
104816179Sralph 	t = t1 = p->in.left->in.type;
104916179Sralph 	t2 = p->in.right->in.type;
105016179Sralph 	d = p->in.left->fn.cdim;
105116179Sralph 	d2 = p->in.right->fn.cdim;
105216179Sralph 	s = p->in.left->fn.csiz;
105316179Sralph 	s2 = p->in.right->fn.csiz;
105416179Sralph 
105516179Sralph 	switch( o ){
105616179Sralph 
105716179Sralph 	case ASSIGN:
105816179Sralph 	case RETURN:
105916179Sralph 	case CAST:
106016179Sralph 		{  break; }
106116179Sralph 
106216179Sralph 	case MINUS:
106316179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
106416179Sralph 			uerror( "illegal pointer subtraction");
106516179Sralph 			}
106616179Sralph 		   break;
106716179Sralph 		   }
106816179Sralph 	case COLON:
106916179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
107016179Sralph 		   break;
107116179Sralph 		   }
107216179Sralph 	default:  /* must work harder: relationals or comparisons */
107316179Sralph 
107416179Sralph 		if( !ISPTR(t1) ){
107516179Sralph 			t = t2;
107616179Sralph 			d = d2;
107716179Sralph 			s = s2;
107816179Sralph 			break;
107916179Sralph 			}
108016179Sralph 		if( !ISPTR(t2) ){
108116179Sralph 			break;
108216179Sralph 			}
108316179Sralph 
108416179Sralph 		/* both are pointers */
108516179Sralph 		if( talign(t2,s2) < talign(t,s) ){
108616179Sralph 			t = t2;
108716179Sralph 			s = s2;
108816179Sralph 			}
108916179Sralph 		break;
109016179Sralph 		}
109116179Sralph 
109216179Sralph 	p->in.left = makety( p->in.left, t, d, s );
109316179Sralph 	p->in.right = makety( p->in.right, t, d, s );
109416179Sralph 	if( o!=MINUS && !logop(o) ){
109516179Sralph 
109616179Sralph 		p->in.type = t;
109716179Sralph 		p->fn.cdim = d;
109816179Sralph 		p->fn.csiz = s;
109916179Sralph 		}
110016179Sralph 
110116179Sralph 	return(clocal(p));
110216179Sralph 	}
110316179Sralph 
110416179Sralph int tdebug = 0;
110516179Sralph 
110616179Sralph NODE *
110716179Sralph tymatch(p)  register NODE *p; {
110816179Sralph 
110916179Sralph 	/* satisfy the types of various arithmetic binary ops */
111016179Sralph 
111116179Sralph 	/* rules are:
111225750Sdonn 		if assignment, type of LHS
111316179Sralph 		if any float or doubles, make double
111416179Sralph 		if any longs, make long
111516179Sralph 		otherwise, make int
111616179Sralph 		if either operand is unsigned, the result is...
111716179Sralph 	*/
111816179Sralph 
111916179Sralph 	register TWORD t1, t2, t, tu;
112016179Sralph 	register o, u;
112116179Sralph 
112216179Sralph 	o = p->in.op;
112316179Sralph 
112416179Sralph 	t1 = p->in.left->in.type;
112516179Sralph 	t2 = p->in.right->in.type;
112616179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
112716179Sralph 		uerror("void type illegal in expression");
112816179Sralph 
112916179Sralph 	u = 0;
113016179Sralph 	if( ISUNSIGNED(t1) ){
113116179Sralph 		u = 1;
113216179Sralph 		t1 = DEUNSIGN(t1);
113316179Sralph 		}
113416179Sralph 	if( ISUNSIGNED(t2) ){
113516179Sralph 		u = 1;
113616179Sralph 		t2 = DEUNSIGN(t2);
113716179Sralph 		}
113816179Sralph 
113916179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
114016179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
114116179Sralph 
114217749Sralph #ifdef SPRECC
114317749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
114417749Sralph 		t = DOUBLE;
114517749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
114617749Sralph 		t = FLOAT;
114717749Sralph #else
114817749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
114917749Sralph 		t = DOUBLE;
115017749Sralph #endif
115116179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
115216179Sralph 	else t = INT;
115316179Sralph 
115432853Sdonn 	if( o == ASSIGN || o == CAST || o == RETURN )
115532853Sdonn 	{
115616179Sralph 		tu = p->in.left->in.type;
115716179Sralph 		t = t1;
115816179Sralph 		}
115916179Sralph 	else {
116016179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
116116179Sralph 		}
116216179Sralph 
116316179Sralph 	/* because expressions have values that are at least as wide
116416179Sralph 	   as INT or UNSIGNED, the only conversions needed
116516179Sralph 	   are those involving FLOAT/DOUBLE, and those
116616179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
116716179Sralph 
116832858Sdonn 	if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
116925750Sdonn 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
117016179Sralph 
117132858Sdonn 	if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
117232840Sdonn 		if ( tu == ENUMTY ) {/* always asgop */
117332840Sdonn 			p->in.right = makety( p->in.right, INT, 0, INT );
117432840Sdonn 			p->in.right->in.type = tu;
117532840Sdonn 			p->in.right->fn.cdim = p->in.left->fn.cdim;
117632840Sdonn 			p->in.right->fn.csiz = p->in.left->fn.csiz;
117732840Sdonn 			}
117832840Sdonn 		else
117932840Sdonn 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
118016179Sralph 
118116179Sralph 	if( asgop(o) ){
118216179Sralph 		p->in.type = p->in.left->in.type;
118316179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
118416179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
118516179Sralph 		}
118616179Sralph 	else if( !logop(o) ){
118716179Sralph 		p->in.type = tu;
118816179Sralph 		p->fn.cdim = 0;
118916179Sralph 		p->fn.csiz = t;
119016179Sralph 		}
119116179Sralph 
119216179Sralph # ifndef BUG1
119316179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
119416179Sralph # endif
119516179Sralph 
119616179Sralph 	return(p);
119716179Sralph 	}
119816179Sralph 
119916179Sralph NODE *
120016179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
120116179Sralph 	/* make p into type t by inserting a conversion */
120216179Sralph 
120316179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
120416179Sralph 	if( t == p->in.type ){
120516179Sralph 		p->fn.cdim = d;
120616179Sralph 		p->fn.csiz = s;
120716179Sralph 		return( p );
120816179Sralph 		}
120916179Sralph 
121016179Sralph 	if( t & TMASK ){
121116179Sralph 		/* non-simple type */
121217228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
121316179Sralph 		}
121416179Sralph 
121516179Sralph 	if( p->in.op == ICON ){
121617749Sralph 		if (t == DOUBLE) {
121717749Sralph 			p->in.op = DCON;
121817749Sralph 			if (ISUNSIGNED(p->in.type))
1219*34092Sbostic 				p->dpn.dval = (U_CONSZ) p->tn.lval;
122017749Sralph 			else
122117749Sralph 				p->dpn.dval = p->tn.lval;
122217749Sralph 			p->in.type = p->fn.csiz = t;
122317749Sralph 			return (clocal(p));
122417749Sralph 		}
122517749Sralph 		if (t == FLOAT) {
122616179Sralph 			p->in.op = FCON;
122716179Sralph 			if( ISUNSIGNED(p->in.type) ){
1228*34092Sbostic 				p->fpn.fval = (U_CONSZ) p->tn.lval;
122916179Sralph 				}
123016179Sralph 			else {
123117749Sralph 				p->fpn.fval = p->tn.lval;
123216179Sralph 				}
123316179Sralph 
123416179Sralph 			p->in.type = p->fn.csiz = t;
123516179Sralph 			return( clocal(p) );
123616179Sralph 			}
123716179Sralph 		}
123817749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
123917749Sralph 		double db;
124016179Sralph 
124117749Sralph 		p->in.op = DCON;
124217749Sralph 		db = p->fpn.fval;
124317749Sralph 		p->dpn.dval = db;
124417749Sralph 		p->in.type = p->fn.csiz = t;
124517749Sralph 		return (clocal(p));
124617749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
124717749Sralph 		float fl;
124817749Sralph 
124917749Sralph 		p->in.op = FCON;
125017749Sralph 		fl = p->dpn.dval;
125117749Sralph #ifdef notdef
125217749Sralph 		if (fl != p->dpn.dval)
125317749Sralph 			werror("float conversion loses precision");
125417749Sralph #endif
125517749Sralph 		p->fpn.fval = fl;
125617749Sralph 		p->in.type = p->fn.csiz = t;
125717749Sralph 		return (clocal(p));
125817749Sralph 	}
125917749Sralph 
126017049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
126116179Sralph 
126216179Sralph 	}
126316179Sralph 
126416179Sralph NODE *
126516179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
126616179Sralph 
126716179Sralph 	register NODE *p;
126816179Sralph 
126916179Sralph 	p = talloc();
127016179Sralph 	p->in.op = o;
127116179Sralph 	p->in.left = l;
127216179Sralph 	p->in.right = r;
127316179Sralph 	p->in.type = t;
127416179Sralph 	p->fn.cdim = d;
127516179Sralph 	p->fn.csiz = s;
127616179Sralph 	return(p);
127716179Sralph 	}
127816179Sralph 
127916179Sralph icons(p) register NODE *p; {
128016179Sralph 	/* if p is an integer constant, return its value */
128116179Sralph 	int val;
128216179Sralph 
128316179Sralph 	if( p->in.op != ICON ){
128416179Sralph 		uerror( "constant expected");
128516179Sralph 		val = 1;
128616179Sralph 		}
128716179Sralph 	else {
128816179Sralph 		val = p->tn.lval;
128916179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
129016179Sralph 		}
129116179Sralph 	tfree( p );
129216179Sralph 	return(val);
129316179Sralph 	}
129416179Sralph 
129516179Sralph /* 	the intent of this table is to examine the
129616179Sralph 	operators, and to check them for
129716179Sralph 	correctness.
129816179Sralph 
129916179Sralph 	The table is searched for the op and the
130016179Sralph 	modified type (where this is one of the
130116179Sralph 	types INT (includes char and short), LONG,
130216179Sralph 	DOUBLE (includes FLOAT), and POINTER
130316179Sralph 
130416179Sralph 	The default action is to make the node type integer
130516179Sralph 
130616179Sralph 	The actions taken include:
130716179Sralph 		PUN	  check for puns
130816179Sralph 		CVTL	  convert the left operand
130916179Sralph 		CVTR	  convert the right operand
131016179Sralph 		TYPL	  the type is determined by the left operand
131116179Sralph 		TYPR	  the type is determined by the right operand
131216179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
131316179Sralph 		PTMATCH	  like TYMATCH, but for pointers
131416179Sralph 		LVAL	  left operand must be lval
131516179Sralph 		CVTO	  convert the op
131616179Sralph 		NCVT	  do not convert the operands
131716179Sralph 		OTHER	  handled by code
131816179Sralph 		NCVTR	  convert the left operand, not the right...
131916179Sralph 
132016179Sralph 	*/
132116179Sralph 
132216179Sralph # define MINT 01  /* integer */
132316179Sralph # define MDBI 02   /* integer or double */
132416179Sralph # define MSTR 04  /* structure */
132516179Sralph # define MPTR 010  /* pointer */
132616179Sralph # define MPTI 020  /* pointer or integer */
132716179Sralph # define MENU 040 /* enumeration variable or member */
132824408Smckusick # define MVOID 0100000 /* void type */
132916179Sralph 
133016179Sralph opact( p )  NODE *p; {
133116179Sralph 
133216179Sralph 	register mt12, mt1, mt2, o;
133316179Sralph 
133424408Smckusick 	mt1 = mt2 = mt12 = 0;
133516179Sralph 
133616179Sralph 	switch( optype(o=p->in.op) ){
133716179Sralph 
133816179Sralph 	case BITYPE:
133924408Smckusick 		mt2 = moditype( p->in.right->in.type );
134016179Sralph 	case UTYPE:
134124408Smckusick 		mt1 = moditype( p->in.left->in.type );
134224408Smckusick 		break;
134316179Sralph 
134416179Sralph 		}
134516179Sralph 
134624408Smckusick 	if( ((mt1 | mt2) & MVOID) &&
134724408Smckusick 	    o != COMOP &&
134832845Sdonn 	    o != COLON &&
134932845Sdonn 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
135024408Smckusick 	    !(o == CAST && (mt1 & MVOID)) ){
135124408Smckusick 		/* if lhs of RETURN is void, grammar will complain */
135224408Smckusick 		if( o != RETURN )
135324408Smckusick 			uerror( "value of void expression used" );
135424408Smckusick 		return( NCVT );
135524408Smckusick 		}
135624408Smckusick 	mt12 = mt1 & mt2;
135724408Smckusick 
135816179Sralph 	switch( o ){
135916179Sralph 
136016179Sralph 	case NAME :
136116179Sralph 	case STRING :
136216179Sralph 	case ICON :
136316179Sralph 	case FCON :
136417749Sralph 	case DCON :
136516179Sralph 	case CALL :
136616179Sralph 	case UNARY CALL:
136716179Sralph 	case UNARY MUL:
136816179Sralph 		{  return( OTHER ); }
136916179Sralph 	case UNARY MINUS:
137032844Sdonn 		if( mt1 & MENU ) return( 0 );
137116179Sralph 		if( mt1 & MDBI ) return( TYPL );
137216179Sralph 		break;
137316179Sralph 
137416179Sralph 	case COMPL:
137532844Sdonn 		if( mt1 & MENU ) return( 0 );
137616179Sralph 		if( mt1 & MINT ) return( TYPL );
137716179Sralph 		break;
137816179Sralph 
137916179Sralph 	case UNARY AND:
138016179Sralph 		{  return( NCVT+OTHER ); }
138116179Sralph 	case INIT:
138216179Sralph 	case CM:
138316180Sralph 		return( 0 );
138416180Sralph 
138516179Sralph 	case NOT:
138616179Sralph 	case CBRANCH:
138716180Sralph 		if( mt1 & MSTR ) break;
138816180Sralph 		return( 0 );
138916180Sralph 
139016179Sralph 	case ANDAND:
139116179Sralph 	case OROR:
139216180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
139316179Sralph 		return( 0 );
139416179Sralph 
139516179Sralph 	case MUL:
139616179Sralph 	case DIV:
139716179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
139816179Sralph 		break;
139916179Sralph 
140016179Sralph 	case MOD:
140116179Sralph 	case AND:
140216179Sralph 	case OR:
140316179Sralph 	case ER:
140416179Sralph 		if( mt12 & MINT ) return( TYMATCH );
140516179Sralph 		break;
140616179Sralph 
140716179Sralph 	case LS:
140816179Sralph 	case RS:
140916179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
141016179Sralph 		break;
141116179Sralph 
141216179Sralph 	case EQ:
141316179Sralph 	case NE:
141416179Sralph 	case LT:
141516179Sralph 	case LE:
141616179Sralph 	case GT:
141716179Sralph 	case GE:
141832844Sdonn 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
141932844Sdonn 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
142016179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
142116179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
142216179Sralph 		else break;
142316179Sralph 
142416179Sralph 	case QUEST:
142516179Sralph 	case COMOP:
142616179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
142716179Sralph 		return( TYPR );
142816179Sralph 
142916179Sralph 	case STREF:
143016179Sralph 		return( NCVTR+OTHER );
143116179Sralph 
143216179Sralph 	case FORCE:
143316179Sralph 		return( TYPL );
143416179Sralph 
143516179Sralph 	case COLON:
143632844Sdonn 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
143732844Sdonn 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
143816179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
143916179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
144016179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
144116179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
144232845Sdonn 		else if( mt12 == MVOID ) return( NCVT+TYPL );
144316179Sralph 		break;
144416179Sralph 
144516179Sralph 	case ASSIGN:
144616179Sralph 	case RETURN:
144716179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
144832844Sdonn 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
144916179Sralph 	case CAST:
145032846Sdonn 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
145132844Sdonn 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
145232846Sdonn 		else if( mt2 == MVOID &&
145318436Smckusick 		        ( p->in.right->in.op == CALL ||
145418436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
145532854Sdonn 		else if( (mt1 & MPTR) && (mt2 & MPTI) )
145632854Sdonn 			return( LVAL+PTMATCH+PUN );
145716179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
145816179Sralph 		break;
145916179Sralph 
146016179Sralph 	case ASG LS:
146116179Sralph 	case ASG RS:
146216179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
146316179Sralph 		break;
146416179Sralph 
146516179Sralph 	case ASG MUL:
146616179Sralph 	case ASG DIV:
146716179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
146816179Sralph 		break;
146916179Sralph 
147016179Sralph 	case ASG MOD:
147116179Sralph 	case ASG AND:
147216179Sralph 	case ASG OR:
147316179Sralph 	case ASG ER:
147416179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
147516179Sralph 		break;
147616179Sralph 
147716179Sralph 	case ASG PLUS:
147816179Sralph 	case ASG MINUS:
147916179Sralph 	case INCR:
148016179Sralph 	case DECR:
148116179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
148216179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
148316179Sralph 		break;
148416179Sralph 
148516179Sralph 	case MINUS:
148616179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
148716179Sralph 		if( mt2 & MPTR ) break;
148816179Sralph 	case PLUS:
148916179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
149016179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
149116179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
149216179Sralph 
149316179Sralph 		}
149424408Smckusick 	if( mt12 == MSTR )
149524408Smckusick 		uerror( "%s is not a permitted struct/union operation", opst[o] );
149624408Smckusick 	else
149724408Smckusick 		uerror( "operands of %s have incompatible types", opst[o] );
149816179Sralph 	return( NCVT );
149916179Sralph 	}
150016179Sralph 
150116179Sralph moditype( ty ) TWORD ty; {
150216179Sralph 
150316179Sralph 	switch( ty ){
150416179Sralph 
150516179Sralph 	case UNDEF:
150624408Smckusick 		return( MVOID );
150716179Sralph 	case ENUMTY:
150816179Sralph 	case MOETY:
150932840Sdonn 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
151016179Sralph 
151116179Sralph 	case STRTY:
151216179Sralph 	case UNIONTY:
151316179Sralph 		return( MSTR );
151416179Sralph 
151516179Sralph 	case CHAR:
151616179Sralph 	case SHORT:
151716179Sralph 	case UCHAR:
151816179Sralph 	case USHORT:
151916179Sralph 		return( MINT|MPTI|MDBI );
152016179Sralph 	case UNSIGNED:
152116179Sralph 	case ULONG:
152216179Sralph 	case INT:
152316179Sralph 	case LONG:
152416179Sralph 		return( MINT|MDBI|MPTI );
152516179Sralph 	case FLOAT:
152616179Sralph 	case DOUBLE:
152716179Sralph 		return( MDBI );
152816179Sralph 	default:
152916179Sralph 		return( MPTR|MPTI );
153016179Sralph 
153116179Sralph 		}
153216179Sralph 	}
153316179Sralph 
153416179Sralph NODE *
153516179Sralph doszof( p )  register NODE *p; {
153616179Sralph 	/* do sizeof p */
153716179Sralph 	int i;
153816179Sralph 
153916179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
154016179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
154116179Sralph 
154216179Sralph 	tfree(p);
154316179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
154416179Sralph 	return( bcon( i ) );
154516179Sralph 	}
154616179Sralph 
154716179Sralph # ifndef BUG2
154816179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
154916179Sralph 	register ty;
155016179Sralph 
155116179Sralph 	*a = *b = down+1;
155216179Sralph 	while( down > 1 ){
155316179Sralph 		printf( "\t" );
155416179Sralph 		down -= 2;
155516179Sralph 		}
155616179Sralph 	if( down ) printf( "    " );
155716179Sralph 
155816179Sralph 	ty = optype( p->in.op );
155916179Sralph 
156016179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
156116179Sralph 	if( ty == LTYPE ){
156216179Sralph 		printf( CONFMT, p->tn.lval );
156316179Sralph 		printf( ", %d, ", p->tn.rval );
156416179Sralph 		}
156516179Sralph 	tprint( p->in.type );
156616179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
156716179Sralph 	}
156816179Sralph # endif
156916179Sralph 
157032850Sdonn #ifndef PRTDCON
157116179Sralph prtdcon( p ) register NODE *p; {
157217749Sralph 	int o = p->in.op, i;
157316179Sralph 
157417749Sralph 	if( o == DCON || o == FCON ){
157532852Sdonn 		(void) locctr( DATA );
157617749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
157716179Sralph 		deflab( i = getlab() );
157817749Sralph 		if( o == FCON )
157917749Sralph 			fincode( p->fpn.fval, SZFLOAT );
158017749Sralph 		else
158117749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
158216179Sralph 		p->tn.lval = 0;
158316179Sralph 		p->tn.rval = -i;
158417749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
158516179Sralph 		p->in.op = NAME;
158616179Sralph 		}
158716179Sralph 	}
158832850Sdonn #endif PRTDCON
158916179Sralph 
159016179Sralph 
159116179Sralph int edebug = 0;
159216179Sralph ecomp( p ) register NODE *p; {
159316179Sralph # ifndef BUG2
159416179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
159516179Sralph # endif
159616179Sralph 	if( !reached ){
159716179Sralph 		werror( "statement not reached" );
159816179Sralph 		reached = 1;
159916179Sralph 		}
160016179Sralph 	p = optim(p);
160116179Sralph 	walkf( p, prtdcon );
160232852Sdonn 	(void) locctr( PROG );
160316179Sralph 	ecode( p );
160416179Sralph 	tfree(p);
160516179Sralph 	}
160616179Sralph 
160716179Sralph # ifdef STDPRTREE
160816179Sralph # ifndef ONEPASS
160916179Sralph 
161016179Sralph prtree(p) register NODE *p; {
161116179Sralph 
161216179Sralph 	register struct symtab *q;
161316179Sralph 	register ty;
161416179Sralph 
161516179Sralph # ifdef MYPRTREE
161616179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
161716179Sralph #endif
161816179Sralph 
161916179Sralph 	ty = optype(p->in.op);
162016179Sralph 
162116179Sralph 	printf( "%d\t", p->in.op );
162216179Sralph 
162316179Sralph 	if( ty == LTYPE ) {
162416179Sralph 		printf( CONFMT, p->tn.lval );
162516179Sralph 		printf( "\t" );
162616179Sralph 		}
162716179Sralph 	if( ty != BITYPE ) {
162816179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
162916179Sralph 		else printf( "%d\t", p->tn.rval );
163016179Sralph 		}
163116179Sralph 
163216179Sralph 	printf( "%o\t", p->in.type );
163316179Sralph 
163416179Sralph 	/* handle special cases */
163516179Sralph 
163616179Sralph 	switch( p->in.op ){
163716179Sralph 
163816179Sralph 	case NAME:
163916179Sralph 	case ICON:
164016179Sralph 		/* print external name */
164116179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
164216179Sralph 		else if( p->tn.rval >= 0 ){
164316179Sralph 			q = &stab[p->tn.rval];
164416179Sralph 			printf(  "%s\n", exname(q->sname) );
164516179Sralph 			}
164616179Sralph 		else { /* label */
164716179Sralph 			printf( LABFMT, -p->tn.rval );
164816179Sralph 			}
164916179Sralph 		break;
165016179Sralph 
165116179Sralph 	case STARG:
165216179Sralph 	case STASG:
165316179Sralph 	case STCALL:
165416179Sralph 	case UNARY STCALL:
165516179Sralph 		/* print out size */
165616179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
165716179Sralph 
165816179Sralph 		/* note: p->in.left not a field... */
165916179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
166016179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
166116179Sralph 		break;
166216179Sralph 
166316179Sralph 	default:
166416179Sralph 		printf(  "\n" );
166516179Sralph 		}
166616179Sralph 
166716179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
166816179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
166916179Sralph 
167016179Sralph 	}
167116179Sralph 
167216179Sralph # else
167316179Sralph 
167416179Sralph p2tree(p) register NODE *p; {
167516179Sralph 	register ty;
167616179Sralph 
167716179Sralph # ifdef MYP2TREE
167816179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
167916179Sralph # endif
168016179Sralph 
168116179Sralph 	ty = optype(p->in.op);
168216179Sralph 
168316179Sralph 	switch( p->in.op ){
168416179Sralph 
168516179Sralph 	case NAME:
168616179Sralph 	case ICON:
168716179Sralph #ifndef FLEXNAMES
168816179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
168916179Sralph #else
169016179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
169116179Sralph #endif
169216179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
169316179Sralph 			register char *cp;
169416179Sralph 			cp = exname( stab[p->tn.rval].sname );
169516179Sralph #ifndef FLEXNAMES
169632852Sdonn 			{
169732852Sdonn 				register i;
169832852Sdonn 				for( i=0; i<NCHNAM; ++i )
169932852Sdonn 					p->in.name[i] = *cp++;
170032852Sdonn 			}
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