xref: /csrg-svn/old/pcc/mip/trees.c (revision 18436)
117749Sralph #ifndef lint
2*18436Smckusick static char *sccsid ="@(#)trees.c	4.8 (Berkeley) 03/19/85";
317749Sralph #endif
417749Sralph 
518396Sralph # include "pass1.h"
616179Sralph 
717749Sralph int bdebug = 0;
817749Sralph int adebug = 0;
917749Sralph extern ddebug;
1017749Sralph extern eprint();
1117749Sralph 
1216179Sralph 	    /* corrections when in violation of lint */
1316179Sralph 
1416179Sralph /*	some special actions, used in finding the type of nodes */
1516179Sralph # define NCVT 01
1616179Sralph # define PUN 02
1716179Sralph # define TYPL 04
1816179Sralph # define TYPR 010
1916179Sralph # define TYMATCH 040
2016179Sralph # define LVAL 0100
2116179Sralph # define CVTO 0200
2216179Sralph # define CVTL 0400
2316179Sralph # define CVTR 01000
2416179Sralph # define PTMATCH 02000
2516179Sralph # define OTHER 04000
2616179Sralph # define NCVTR 010000
2716179Sralph 
2817749Sralph #ifndef BUG1
2917749Sralph printact(t, acts)
3017749Sralph 	NODE *t;
3117749Sralph 	int acts;
3217749Sralph {
3317749Sralph 	static struct actions {
3417749Sralph 		int	a_bit;
3517749Sralph 		char	*a_name;
3617749Sralph 	} actions[] = {
3717749Sralph 		{ PUN,		"PUN" },
3817749Sralph 		{ CVTL,		"CVTL" },
3917749Sralph 		{ CVTR,		"CVTR" },
4017749Sralph 		{ TYPL,		"TYPL" },
4117749Sralph 		{ TYPR,		"TYPR" },
4217749Sralph 		{ TYMATCH,	"TYMATCH" },
4317749Sralph 		{ PTMATCH,	"PTMATCH" },
4417749Sralph 		{ LVAL,		"LVAL" },
4517749Sralph 		{ CVTO,		"CVTO" },
4617749Sralph 		{ NCVT,		"NCVT" },
4717749Sralph 		{ OTHER,	"OTHER" },
4817749Sralph 		{ NCVTR,	"NCVTR" },
4917749Sralph 		{ 0 }
5017749Sralph 	};
5117749Sralph 	register struct actions *p;
5217749Sralph 	char *sep = " ";
5317749Sralph 
5417749Sralph 	printf("actions");
5517749Sralph 	for (p = actions; p->a_name; p++)
5617749Sralph 		if (p->a_bit & acts) {
5717749Sralph 			printf("%s%s", sep, p->a_name);
5817749Sralph 			sep = "|";
5917749Sralph 		}
6017749Sralph 	if (!bdebug) {
6117749Sralph 		printf(" for:\n");
6217749Sralph 		fwalk(t, eprint, 0);
6317749Sralph 	} else
6417749Sralph 		putchar('\n');
6517749Sralph }
6617749Sralph #endif
6717749Sralph 
6816179Sralph /* node conventions:
6916179Sralph 
7016179Sralph 	NAME:	rval>0 is stab index for external
7116179Sralph 		rval<0 is -inlabel number
7216179Sralph 		lval is offset in bits
7316179Sralph 	ICON:	lval has the value
7416179Sralph 		rval has the STAB index, or - label number,
7516179Sralph 			if a name whose address is in the constant
7616179Sralph 		rval = NONAME means no name
7716179Sralph 	REG:	rval is reg. identification cookie
7816179Sralph 
7916179Sralph 	*/
8016179Sralph 
8116179Sralph NODE *
8216179Sralph buildtree( o, l, r ) register NODE *l, *r; {
8316179Sralph 	register NODE *p, *q;
8416179Sralph 	register actions;
8516179Sralph 	register opty;
8616179Sralph 	register struct symtab *sp;
8716179Sralph 	register NODE *lr, *ll;
8817749Sralph 	NODE *fixargs();
8916179Sralph 	int i;
9016179Sralph 
9116179Sralph # ifndef BUG1
9216179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9316179Sralph # endif
9416179Sralph 	opty = optype(o);
9516179Sralph 
9616179Sralph 	/* check for constants */
9716179Sralph 
9816179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
9916179Sralph 
10016179Sralph 		switch( o ){
10116179Sralph 
10216179Sralph 		case NOT:
10316179Sralph 			if( hflag ) werror( "constant argument to NOT" );
10416179Sralph 		case UNARY MINUS:
10516179Sralph 		case COMPL:
10616179Sralph 			if( conval( l, o, l ) ) return(l);
10716179Sralph 			break;
10816179Sralph 
10916179Sralph 			}
11016179Sralph 		}
11116179Sralph 
11216179Sralph 	else if( o==UNARY MINUS && l->in.op==FCON ){
11317749Sralph 		l->fpn.fval = -l->fpn.fval;
11416179Sralph 		return(l);
11516179Sralph 		}
11616179Sralph 
11717749Sralph 	else if( o==UNARY MINUS && l->in.op==DCON ){
11817749Sralph 		l->dpn.dval = -l->dpn.dval;
11917749Sralph 		return(l);
12017749Sralph 		}
12117749Sralph 
12216179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
12316179Sralph 		l->in.op = FREE;
12416179Sralph 		r->in.op = FREE;
12516179Sralph 		if( l->tn.lval ){
12616179Sralph 			tfree( r->in.right );
12716179Sralph 			return( r->in.left );
12816179Sralph 			}
12916179Sralph 		else {
13016179Sralph 			tfree( r->in.left );
13116179Sralph 			return( r->in.right );
13216179Sralph 			}
13316179Sralph 		}
13416179Sralph 
13516179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
13616179Sralph 
13716179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
13816179Sralph 
13916179Sralph 		switch( o ){
14016179Sralph 
14116179Sralph 		case ULT:
14216179Sralph 		case UGT:
14316179Sralph 		case ULE:
14416179Sralph 		case UGE:
14516179Sralph 		case LT:
14616179Sralph 		case GT:
14716179Sralph 		case LE:
14816179Sralph 		case GE:
14916179Sralph 		case EQ:
15016179Sralph 		case NE:
15116179Sralph 		case ANDAND:
15216179Sralph 		case OROR:
15316179Sralph 		case CBRANCH:
15416179Sralph 
15516179Sralph 		ccwarn:
15616179Sralph 			if( hflag ) werror( "constant in conditional context" );
15716179Sralph 
15816179Sralph 		case PLUS:
15916179Sralph 		case MINUS:
16016179Sralph 		case MUL:
16116179Sralph 		case DIV:
16216179Sralph 		case MOD:
16316179Sralph 		case AND:
16416179Sralph 		case OR:
16516179Sralph 		case ER:
16616179Sralph 		case LS:
16716179Sralph 		case RS:
16816179Sralph 			if( conval( l, o, r ) ) {
16916179Sralph 				r->in.op = FREE;
17016179Sralph 				return(l);
17116179Sralph 				}
17216179Sralph 			break;
17316179Sralph 			}
17416179Sralph 		}
17517749Sralph 	else if (opty == BITYPE) {
17617749Sralph 		if ((l->in.op == FCON || l->in.op == ICON) &&
17717749Sralph 		    (r->in.op == FCON || r->in.op == ICON))
17817749Sralph 			switch (o) {
17916179Sralph 
18017749Sralph 			case PLUS:
18117749Sralph 			case MINUS:
18217749Sralph 			case MUL:
18317749Sralph 			case DIV:
18417749Sralph 				if (l->in.op == ICON)
18517749Sralph 					l->fpn.fval = l->tn.lval;
18617749Sralph 				if (r->in.op == ICON)
18717749Sralph 					r->fpn.fval = r->tn.lval;
18817749Sralph 				l->in.op = FCON;
18917749Sralph 				l->in.type = l->fn.csiz = FLOAT;
19017749Sralph 				r->in.op = FREE;
19117749Sralph 				switch (o) {
19217749Sralph 
19317749Sralph 				case PLUS:
19417749Sralph 					l->fpn.fval += r->fpn.fval;
19517749Sralph 					return (l);
19617749Sralph 
19717749Sralph 				case MINUS:
19817749Sralph 					l->fpn.fval -= r->fpn.fval;
19917749Sralph 					return (l);
20017749Sralph 
20117749Sralph 				case MUL:
20217749Sralph 					l->fpn.fval *= r->fpn.fval;
20317749Sralph 					return (l);
20417749Sralph 
20517749Sralph 				case DIV:
20617749Sralph 					if (r->fpn.fval == 0)
20717749Sralph 						uerror("division by 0.");
20817749Sralph 					else
20917749Sralph 						l->fpn.fval /= r->fpn.fval;
21017749Sralph 					return (l);
21116179Sralph 				}
21217749Sralph 			}
21317749Sralph 		else if ((l->in.op == DCON || l->in.op == ICON) &&
21417749Sralph 		    (r->in.op == DCON || r->in.op == ICON))
21517749Sralph 			switch (o) {
21617749Sralph 
21716179Sralph 			case PLUS:
21816179Sralph 			case MINUS:
21916179Sralph 			case MUL:
22016179Sralph 			case DIV:
22117749Sralph 				if (l->in.op == ICON)
22217749Sralph 					l->dpn.dval = l->tn.lval;
22317749Sralph 				if (r->in.op == ICON)
22417749Sralph 					r->dpn.dval = r->tn.lval;
22517749Sralph 				l->in.op = DCON;
22617749Sralph 				l->in.type = l->fn.csiz = DOUBLE;
22717749Sralph 				r->in.op = FREE;
22817749Sralph 				switch (o) {
22917749Sralph 
23017749Sralph 				case PLUS:
23117749Sralph 					l->dpn.dval += r->dpn.dval;
23217749Sralph 					return (l);
23317749Sralph 
23417749Sralph 				case MINUS:
23517749Sralph 					l->dpn.dval -= r->dpn.dval;
23617749Sralph 					return (l);
23717749Sralph 
23817749Sralph 				case MUL:
23917749Sralph 					l->dpn.dval *= r->dpn.dval;
24017749Sralph 					return (l);
24117749Sralph 
24217749Sralph 				case DIV:
24317749Sralph 					if (r->dpn.dval == 0)
24417749Sralph 						uerror("division by 0.");
24517749Sralph 					else
24617749Sralph 						l->dpn.dval /= r->dpn.dval;
24717749Sralph 					return (l);
24816179Sralph 				}
24916179Sralph 			}
25017749Sralph 	}
25116179Sralph 
25216179Sralph 	/* its real; we must make a new node */
25316179Sralph 
25416179Sralph 	p = block( o, l, r, INT, 0, INT );
25516179Sralph 
25616179Sralph 	actions = opact(p);
25717749Sralph #ifndef	BUG1
25817749Sralph 	if (adebug)
25917749Sralph 		printact(p, actions);
26017749Sralph #endif
26116179Sralph 
26216179Sralph 	if( actions&LVAL ){ /* check left descendent */
26316179Sralph 		if( notlval(p->in.left) ) {
26416179Sralph 			uerror( "illegal lhs of assignment operator" );
26516179Sralph 			}
26616179Sralph 		}
26716179Sralph 
26816179Sralph 	if( actions & NCVTR ){
26916179Sralph 		p->in.left = pconvert( p->in.left );
27016179Sralph 		}
27116179Sralph 	else if( !(actions & NCVT ) ){
27216179Sralph 		switch( opty ){
27316179Sralph 
27416179Sralph 		case BITYPE:
27516179Sralph 			p->in.right = pconvert( p->in.right );
27616179Sralph 		case UTYPE:
27716179Sralph 			p->in.left = pconvert( p->in.left );
27816179Sralph 
27916179Sralph 			}
28016179Sralph 		}
28116179Sralph 
28216179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
28316179Sralph 		chkpun(p);
28416179Sralph 		}
28516179Sralph 
28616179Sralph 	if( actions & (TYPL|TYPR) ){
28716179Sralph 
28816179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
28916179Sralph 
29016179Sralph 		p->in.type = q->in.type;
29116179Sralph 		p->fn.cdim = q->fn.cdim;
29216179Sralph 		p->fn.csiz = q->fn.csiz;
29316179Sralph 		}
29416179Sralph 
29516179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
29616179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
29716179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
29816179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
29916179Sralph 
30016179Sralph 	if( actions & OTHER ){
30116179Sralph 		l = p->in.left;
30216179Sralph 		r = p->in.right;
30316179Sralph 
30416179Sralph 		switch(o){
30516179Sralph 
30616179Sralph 		case NAME:
30716179Sralph 			sp = &stab[idname];
30816179Sralph 			if( sp->stype == UNDEF ){
30916179Sralph #ifndef FLEXNAMES
31016179Sralph 				uerror( "%.8s undefined", sp->sname );
31116179Sralph #else
31216179Sralph 				uerror( "%s undefined", sp->sname );
31316179Sralph #endif
31416179Sralph 				/* make p look reasonable */
31516179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
31616179Sralph 				p->tn.rval = idname;
31716179Sralph 				p->tn.lval = 0;
31816179Sralph 				defid( p, SNULL );
31916179Sralph 				break;
32016179Sralph 				}
32116179Sralph 			p->in.type = sp->stype;
32216179Sralph 			p->fn.cdim = sp->dimoff;
32316179Sralph 			p->fn.csiz = sp->sizoff;
32416179Sralph 			p->tn.lval = 0;
32516179Sralph 			p->tn.rval = idname;
32616179Sralph 			/* special case: MOETY is really an ICON... */
32716179Sralph 			if( p->in.type == MOETY ){
32816179Sralph 				p->tn.rval = NONAME;
32916179Sralph 				p->tn.lval = sp->offset;
33016179Sralph 				p->fn.cdim = 0;
33116179Sralph 				p->in.type = ENUMTY;
33216179Sralph 				p->in.op = ICON;
33316179Sralph 				}
33416179Sralph 			break;
33516179Sralph 
33616179Sralph 		case ICON:
33716179Sralph 			p->in.type = INT;
33816179Sralph 			p->fn.cdim = 0;
33916179Sralph 			p->fn.csiz = INT;
34016179Sralph 			break;
34116179Sralph 
34216179Sralph 		case STRING:
34316179Sralph 			p->in.op = NAME;
34416179Sralph 			p->in.type = CHAR+ARY;
34516179Sralph 			p->tn.lval = 0;
34616179Sralph 			p->tn.rval = NOLAB;
34716179Sralph 			p->fn.cdim = curdim;
34816179Sralph 			p->fn.csiz = CHAR;
34916179Sralph 			break;
35016179Sralph 
35116179Sralph 		case FCON:
35216179Sralph 			p->tn.lval = 0;
35316179Sralph 			p->tn.rval = 0;
35417749Sralph 			p->in.type = FLOAT;
35517749Sralph 			p->fn.cdim = 0;
35617749Sralph 			p->fn.csiz = FLOAT;
35717749Sralph 			break;
35817749Sralph 
35917749Sralph 		case DCON:
36017749Sralph 			p->tn.lval = 0;
36117749Sralph 			p->tn.rval = 0;
36216179Sralph 			p->in.type = DOUBLE;
36316179Sralph 			p->fn.cdim = 0;
36416179Sralph 			p->fn.csiz = DOUBLE;
36516179Sralph 			break;
36616179Sralph 
36716179Sralph 		case STREF:
36816179Sralph 			/* p->x turned into *(p+offset) */
36916179Sralph 			/* rhs must be a name; check correctness */
37016179Sralph 
37116179Sralph 			i = r->tn.rval;
37216179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
37316179Sralph 				uerror( "member of structure or union required" );
37416179Sralph 				}else
37516179Sralph 			/* if this name is non-unique, find right one */
37616179Sralph 			if( stab[i].sflags & SNONUNIQ &&
37716179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
37816179Sralph 				(l->fn.csiz +1) >= 0 ){
37916179Sralph 				/* nonunique name && structure defined */
38016179Sralph 				char * memnam, * tabnam;
38116179Sralph 				register k;
38216179Sralph 				int j;
38316179Sralph 				int memi;
38416179Sralph 				j=dimtab[l->fn.csiz+1];
38516179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
38616179Sralph 					tabnam = stab[memi].sname;
38716179Sralph 					memnam = stab[i].sname;
38816179Sralph # ifndef BUG1
38916179Sralph 					if( ddebug>1 ){
39016179Sralph #ifndef FLEXNAMES
39116179Sralph 						printf("member %.8s==%.8s?\n",
39216179Sralph #else
39316179Sralph 						printf("member %s==%s?\n",
39416179Sralph #endif
39516179Sralph 							memnam, tabnam);
39616179Sralph 						}
39716179Sralph # endif
39816179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
39916179Sralph #ifndef FLEXNAMES
40016179Sralph 						for( k=0; k<NCHNAM; ++k ){
40116179Sralph 							if(*memnam++!=*tabnam)
40216179Sralph 								goto next;
40316179Sralph 							if(!*tabnam++) break;
40416179Sralph 							}
40516179Sralph #else
40616179Sralph 						if (memnam != tabnam)
40716179Sralph 							goto next;
40816179Sralph #endif
40916179Sralph 						r->tn.rval = i = memi;
41016179Sralph 						break;
41116179Sralph 						}
41216179Sralph 					next: continue;
41316179Sralph 					}
41416179Sralph 				if( memi < 0 )
41516179Sralph #ifndef FLEXNAMES
41616179Sralph 					uerror("illegal member use: %.8s",
41716179Sralph #else
41816179Sralph 					uerror("illegal member use: %s",
41916179Sralph #endif
42016179Sralph 						stab[i].sname);
42116179Sralph 				}
42216179Sralph 			else {
42316179Sralph 				register j;
42416179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
42516179Sralph 					if( stab[i].sflags & SNONUNIQ ){
42616179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
42716179Sralph 						}
42816179Sralph 					else werror( "struct/union or struct/union pointer required" );
42916179Sralph 					}
43016179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
43116179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
43216179Sralph #ifndef FLEXNAMES
43316179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
43416179Sralph #else
43516179Sralph 					werror( "illegal member use: %s", stab[i].sname );
43616179Sralph #endif
43716179Sralph 					}
43816179Sralph 				}
43916179Sralph 
44016179Sralph 			p = stref( p );
44116179Sralph 			break;
44216179Sralph 
44316179Sralph 		case UNARY MUL:
44416179Sralph 			if( l->in.op == UNARY AND ){
44516179Sralph 				p->in.op = l->in.op = FREE;
44616179Sralph 				p = l->in.left;
44716179Sralph 				}
44816179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
44916179Sralph 			p->in.type = DECREF(l->in.type);
45016179Sralph 			p->fn.cdim = l->fn.cdim;
45116179Sralph 			p->fn.csiz = l->fn.csiz;
45216179Sralph 			break;
45316179Sralph 
45416179Sralph 		case UNARY AND:
45516179Sralph 			switch( l->in.op ){
45616179Sralph 
45716179Sralph 			case UNARY MUL:
45816179Sralph 				p->in.op = l->in.op = FREE;
45916179Sralph 				p = l->in.left;
46016179Sralph 			case NAME:
46116179Sralph 				p->in.type = INCREF( l->in.type );
46216179Sralph 				p->fn.cdim = l->fn.cdim;
46316179Sralph 				p->fn.csiz = l->fn.csiz;
46416179Sralph 				break;
46516179Sralph 
46616179Sralph 			case COMOP:
46716179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
46816179Sralph 				p->in.op = l->in.op = FREE;
46916179Sralph 				p = buildtree( COMOP, l->in.left, lr );
47016179Sralph 				break;
47116179Sralph 
47216179Sralph 			case QUEST:
47316179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
47416179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
47516179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
47616179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
47716179Sralph 				break;
47816179Sralph 
47916179Sralph # ifdef ADDROREG
48016179Sralph 			case OREG:
48116179Sralph 				/* OREG was built in clocal()
48216179Sralph 				 * for an auto or formal parameter
48316179Sralph 				 * now its address is being taken
48416179Sralph 				 * local code must unwind it
48516179Sralph 				 * back to PLUS/MINUS REG ICON
48616179Sralph 				 * according to local conventions
48716179Sralph 				 */
48816179Sralph 				{
48916179Sralph 				extern NODE * addroreg();
49016179Sralph 				p->in.op = FREE;
49116179Sralph 				p = addroreg( l );
49216179Sralph 				}
49316179Sralph 				break;
49416179Sralph 
49516179Sralph # endif
49616179Sralph 			default:
49716179Sralph 				uerror( "unacceptable operand of &" );
49816179Sralph 				break;
49916179Sralph 				}
50016179Sralph 			break;
50116179Sralph 
50216179Sralph 		case LS:
50316179Sralph 		case RS:
50416179Sralph 		case ASG LS:
50516179Sralph 		case ASG RS:
50616179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
50716179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
50816179Sralph 			break;
50916179Sralph 
51016179Sralph 		case RETURN:
51116179Sralph 		case ASSIGN:
51216179Sralph 		case CAST:
51316179Sralph 			/* structure assignment */
51416179Sralph 			/* take the addresses of the two sides; then make an
51516179Sralph 			/* operator using STASG and
51616179Sralph 			/* the addresses of left and right */
51716179Sralph 
51816179Sralph 			{
51916179Sralph 				register TWORD t;
52016179Sralph 				register d, s;
52116179Sralph 
52216179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
52316179Sralph 
52416179Sralph 				r = buildtree( UNARY AND, r, NIL );
52516179Sralph 				t = r->in.type;
52616179Sralph 				d = r->fn.cdim;
52716179Sralph 				s = r->fn.csiz;
52816179Sralph 
52916179Sralph 				l = block( STASG, l, r, t, d, s );
53016179Sralph 
53116179Sralph 				if( o == RETURN ){
53216179Sralph 					p->in.op = FREE;
53316179Sralph 					p = l;
53416179Sralph 					break;
53516179Sralph 					}
53616179Sralph 
53716179Sralph 				p->in.op = UNARY MUL;
53816179Sralph 				p->in.left = l;
53916179Sralph 				p->in.right = NIL;
54016179Sralph 				break;
54116179Sralph 				}
54216179Sralph 		case COLON:
54316179Sralph 			/* structure colon */
54416179Sralph 
54516179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
54616179Sralph 			break;
54716179Sralph 
54816179Sralph 		case CALL:
54917749Sralph 			p->in.right = r = fixargs( p->in.right );
55016179Sralph 		case UNARY CALL:
55116179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
55216179Sralph 			p->in.type = DECREF(l->in.type);
55316179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
55416179Sralph 			p->in.type = DECREF( p->in.type );
55516179Sralph 			p->fn.cdim = l->fn.cdim;
55616179Sralph 			p->fn.csiz = l->fn.csiz;
55716179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
55816179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
55916179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
56016179Sralph 				p->in.op += (FORTCALL-CALL);
56116179Sralph 				}
56216179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
56316179Sralph 				/* function returning structure */
56416179Sralph 				/*  make function really return ptr to str., with * */
56516179Sralph 
56616179Sralph 				p->in.op += STCALL-CALL;
56716179Sralph 				p->in.type = INCREF( p->in.type );
56816179Sralph 				p = buildtree( UNARY MUL, p, NIL );
56916179Sralph 
57016179Sralph 				}
57116179Sralph 			break;
57216179Sralph 
57316179Sralph 		default:
57416179Sralph 			cerror( "other code %d", o );
57516179Sralph 			}
57616179Sralph 
57716179Sralph 		}
57816179Sralph 
57916179Sralph 	if( actions & CVTO ) p = oconvert(p);
58016179Sralph 	p = clocal(p);
58116179Sralph 
58216179Sralph # ifndef BUG1
58316179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
58416179Sralph # endif
58516179Sralph 
58616179Sralph 	return(p);
58716179Sralph 
58816179Sralph 	}
58916179Sralph 
59017749Sralph /*
59117749Sralph  * Rewrite arguments in a function call.
59217749Sralph  * Structure arguments are massaged, single
59317749Sralph  * precision floating point constants are
59417749Sralph  * cast to double (to eliminate convert code).
59517749Sralph  */
59616179Sralph NODE *
59717749Sralph fixargs( p ) register NODE *p;  {
59817749Sralph 	int o = p->in.op;
59916179Sralph 
60017749Sralph 	if( o == CM ){
60117749Sralph 		p->in.left = fixargs( p->in.left );
60217749Sralph 		p->in.right = fixargs( p->in.right );
60316179Sralph 		return( p );
60416179Sralph 		}
60516179Sralph 
60616179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
60716179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
60816179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
60916179Sralph 		p = clocal(p);
61016179Sralph 		}
61117749Sralph 	else if( o == FCON )
61217749Sralph 		p = makety(p, DOUBLE, 0, 0);
61316179Sralph 	return( p );
61416179Sralph 	}
61516179Sralph 
61616179Sralph chkstr( i, j, type ) TWORD type; {
61716179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
61816179Sralph 	/* i has been checked to contain a MOS or MOU */
61916179Sralph 	/* j is the index in dimtab of the members... */
62016179Sralph 	int k, kk;
62116179Sralph 
62216179Sralph 	extern int ddebug;
62316179Sralph 
62416179Sralph # ifndef BUG1
62516179Sralph #ifndef FLEXNAMES
62616179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
62716179Sralph #else
62816179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
62916179Sralph #endif
63016179Sralph # endif
63116179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
63216179Sralph 	else {
63316179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
63416179Sralph 			if( kk >= SYMTSZ ){
63516179Sralph 				cerror( "gummy structure" );
63616179Sralph 				return(1);
63716179Sralph 				}
63816179Sralph 			if( kk == i ) return( 1 );
63916179Sralph 			switch( stab[kk].stype ){
64016179Sralph 
64116179Sralph 			case STRTY:
64216179Sralph 			case UNIONTY:
64316179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
64416179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
64516179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
64616179Sralph 					werror(
64716179Sralph #ifndef FLEXNAMES
64816179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
64916179Sralph #else
65016179Sralph 					"illegal member use: perhaps %s.%s?",
65116179Sralph #endif
65216179Sralph 					stab[kk].sname, stab[i].sname );
65316179Sralph 					return(1);
65416179Sralph 					}
65516179Sralph 				}
65616179Sralph 			}
65716179Sralph 		}
65816179Sralph 	return( 0 );
65916179Sralph 	}
66016179Sralph 
66116179Sralph conval( p, o, q ) register NODE *p, *q; {
66216179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
66316179Sralph 	int i, u;
66416179Sralph 	CONSZ val;
66516179Sralph 
66616179Sralph 	val = q->tn.lval;
66716179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
66816179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
66916179Sralph 
67016179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
67116179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
67216179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
67316179Sralph 
67416179Sralph 	switch( o ){
67516179Sralph 
67616179Sralph 	case PLUS:
67716179Sralph 		p->tn.lval += val;
67816179Sralph 		if( p->tn.rval == NONAME ){
67916179Sralph 			p->tn.rval = q->tn.rval;
68016179Sralph 			p->in.type = q->in.type;
68116179Sralph 			}
68216179Sralph 		break;
68316179Sralph 	case MINUS:
68416179Sralph 		p->tn.lval -= val;
68516179Sralph 		break;
68616179Sralph 	case MUL:
68716179Sralph 		p->tn.lval *= val;
68816179Sralph 		break;
68916179Sralph 	case DIV:
69016179Sralph 		if( val == 0 ) uerror( "division by 0" );
69117749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
69216179Sralph 		else p->tn.lval /= val;
69316179Sralph 		break;
69416179Sralph 	case MOD:
69516179Sralph 		if( val == 0 ) uerror( "division by 0" );
69617749Sralph 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
69716179Sralph 		else p->tn.lval %= val;
69816179Sralph 		break;
69916179Sralph 	case AND:
70016179Sralph 		p->tn.lval &= val;
70116179Sralph 		break;
70216179Sralph 	case OR:
70316179Sralph 		p->tn.lval |= val;
70416179Sralph 		break;
70516179Sralph 	case ER:
70617749Sralph 		p->tn.lval ^= val;
70716179Sralph 		break;
70816179Sralph 	case LS:
70916179Sralph 		i = val;
71016179Sralph 		p->tn.lval = p->tn.lval << i;
71116179Sralph 		break;
71216179Sralph 	case RS:
71316179Sralph 		i = val;
71417749Sralph 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
71517749Sralph 		else p->tn.lval = p->tn.lval >> i;
71616179Sralph 		break;
71716179Sralph 
71816179Sralph 	case UNARY MINUS:
71916179Sralph 		p->tn.lval = - p->tn.lval;
72016179Sralph 		break;
72116179Sralph 	case COMPL:
72216179Sralph 		p->tn.lval = ~p->tn.lval;
72316179Sralph 		break;
72416179Sralph 	case NOT:
72516179Sralph 		p->tn.lval = !p->tn.lval;
72616179Sralph 		break;
72716179Sralph 	case LT:
72816179Sralph 		p->tn.lval = p->tn.lval < val;
72916179Sralph 		break;
73016179Sralph 	case LE:
73116179Sralph 		p->tn.lval = p->tn.lval <= val;
73216179Sralph 		break;
73316179Sralph 	case GT:
73416179Sralph 		p->tn.lval = p->tn.lval > val;
73516179Sralph 		break;
73616179Sralph 	case GE:
73716179Sralph 		p->tn.lval = p->tn.lval >= val;
73816179Sralph 		break;
73916179Sralph 	case ULT:
74016179Sralph 		p->tn.lval = (p->tn.lval-val)<0;
74116179Sralph 		break;
74216179Sralph 	case ULE:
74316179Sralph 		p->tn.lval = (p->tn.lval-val)<=0;
74416179Sralph 		break;
74516179Sralph 	case UGE:
74616179Sralph 		p->tn.lval = (p->tn.lval-val)>=0;
74716179Sralph 		break;
74816179Sralph 	case UGT:
74916179Sralph 		p->tn.lval = (p->tn.lval-val)>0;
75016179Sralph 		break;
75116179Sralph 	case EQ:
75216179Sralph 		p->tn.lval = p->tn.lval == val;
75316179Sralph 		break;
75416179Sralph 	case NE:
75516179Sralph 		p->tn.lval = p->tn.lval != val;
75616179Sralph 		break;
75716179Sralph 	default:
75816179Sralph 		return(0);
75916179Sralph 		}
76016179Sralph 	return(1);
76116179Sralph 	}
76216179Sralph 
76316179Sralph chkpun(p) register NODE *p; {
76416179Sralph 
76516179Sralph 	/* checks p for the existance of a pun */
76616179Sralph 
76716179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
76816179Sralph 
76916179Sralph 	/* one case is when enumerations are used: this applies only to lint */
77016179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
77116179Sralph 	/* we check that this integer is in fact a constant zero... */
77216179Sralph 
77316179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
77416179Sralph 	/* this falls out, because the LHS is never 0 */
77516179Sralph 
77616179Sralph 	register NODE *q;
77716179Sralph 	register t1, t2;
77816179Sralph 	register d1, d2;
77916179Sralph 
78016179Sralph 	t1 = p->in.left->in.type;
78116179Sralph 	t2 = p->in.right->in.type;
78216179Sralph 
78316179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
78416179Sralph 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
78516179Sralph 			uerror( "illegal comparison of enums" );
78616179Sralph 			return;
78716179Sralph 			}
78816179Sralph 		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
78916179Sralph 		werror( "enumeration type clash, operator %s", opst[p->in.op] );
79016179Sralph 		return;
79116179Sralph 		}
79216179Sralph 
79316179Sralph 	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
79416179Sralph 	else q = p->in.left;
79516179Sralph 
79616179Sralph 	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
79716179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
79816179Sralph 			werror( "illegal combination of pointer and integer, op %s",
79916179Sralph 				opst[p->in.op] );
80016179Sralph 			}
80116179Sralph 		}
80216179Sralph 	else {
80316179Sralph 		d1 = p->in.left->fn.cdim;
80416179Sralph 		d2 = p->in.right->fn.cdim;
80516179Sralph 		for( ;; ){
80616179Sralph 			if( t1 == t2 ) {;
80716179Sralph 				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
80816179Sralph 					werror( "illegal structure pointer combination" );
80916179Sralph 					}
81016179Sralph 				return;
81116179Sralph 				}
81216179Sralph 			if( ISARY(t1) || ISPTR(t1) ){
81316179Sralph 				if( !ISARY(t2) && !ISPTR(t2) ) break;
81416179Sralph 				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
81516179Sralph 					werror( "illegal array size combination" );
81616179Sralph 					return;
81716179Sralph 					}
81816179Sralph 				if( ISARY(t1) ) ++d1;
81916179Sralph 				if( ISARY(t2) ) ++d2;
82016179Sralph 				}
82116179Sralph 			else break;
82216179Sralph 			t1 = DECREF(t1);
82316179Sralph 			t2 = DECREF(t2);
82416179Sralph 			}
82516179Sralph 		werror( "illegal pointer combination" );
82616179Sralph 		}
82716179Sralph 
82816179Sralph 	}
82916179Sralph 
83016179Sralph NODE *
83116179Sralph stref( p ) register NODE *p; {
83216179Sralph 
83316179Sralph 	TWORD t;
83416179Sralph 	int d, s, dsc, align;
83516179Sralph 	OFFSZ off;
83616179Sralph 	register struct symtab *q;
83716179Sralph 
83816179Sralph 	/* make p->x */
83916179Sralph 	/* this is also used to reference automatic variables */
84016179Sralph 
84116179Sralph 	q = &stab[p->in.right->tn.rval];
84216179Sralph 	p->in.right->in.op = FREE;
84316179Sralph 	p->in.op = FREE;
84416179Sralph 	p = pconvert( p->in.left );
84516179Sralph 
84616179Sralph 	/* make p look like ptr to x */
84716179Sralph 
84816179Sralph 	if( !ISPTR(p->in.type)){
84916179Sralph 		p->in.type = PTR+UNIONTY;
85016179Sralph 		}
85116179Sralph 
85216179Sralph 	t = INCREF( q->stype );
85316179Sralph 	d = q->dimoff;
85416179Sralph 	s = q->sizoff;
85516179Sralph 
85616179Sralph 	p = makety( p, t, d, s );
85716179Sralph 
85816179Sralph 	/* compute the offset to be added */
85916179Sralph 
86016179Sralph 	off = q->offset;
86116179Sralph 	dsc = q->sclass;
86216179Sralph 
86316179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
86416179Sralph 		align = ALINT;
86516179Sralph 		s = INT;
86616179Sralph 		off = (off/align)*align;
86716179Sralph 		}
86816179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
86916179Sralph 
87016179Sralph 	p = buildtree( UNARY MUL, p, NIL );
87116179Sralph 
87216179Sralph 	/* if field, build field info */
87316179Sralph 
87416179Sralph 	if( dsc & FIELD ){
87516179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
87616179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
87716179Sralph 		}
87816179Sralph 
87916179Sralph 	return( clocal(p) );
88016179Sralph 	}
88116179Sralph 
88216179Sralph notlval(p) register NODE *p; {
88316179Sralph 
88416179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
88516179Sralph 
88616179Sralph 	again:
88716179Sralph 
88816179Sralph 	switch( p->in.op ){
88916179Sralph 
89016179Sralph 	case FLD:
89116179Sralph 		p = p->in.left;
89216179Sralph 		goto again;
89316179Sralph 
89416179Sralph 	case UNARY MUL:
89516179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
89616179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
89716179Sralph 		/* and the f().a bug, given that f returns a structure */
89816179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
89916179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
90016179Sralph 	case NAME:
90116179Sralph 	case OREG:
90216179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
90316179Sralph 	case REG:
90416179Sralph 		return(0);
90516179Sralph 
90616179Sralph 	default:
90716179Sralph 		return(1);
90816179Sralph 
90916179Sralph 		}
91016179Sralph 
91116179Sralph 	}
91216179Sralph 
91316179Sralph NODE *
91416179Sralph bcon( i ){ /* make a constant node with value i */
91516179Sralph 	register NODE *p;
91616179Sralph 
91716179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
91816179Sralph 	p->tn.lval = i;
91916179Sralph 	p->tn.rval = NONAME;
92016179Sralph 	return( clocal(p) );
92116179Sralph 	}
92216179Sralph 
92316179Sralph NODE *
92416179Sralph bpsize(p) register NODE *p; {
92516179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
92616179Sralph 	}
92716179Sralph 
92816179Sralph OFFSZ
92916179Sralph psize( p ) NODE *p; {
93016179Sralph 	/* p is a node of type pointer; psize returns the
93116179Sralph 	   size of the thing pointed to */
93216179Sralph 
93316179Sralph 	if( !ISPTR(p->in.type) ){
93416179Sralph 		uerror( "pointer required");
93516179Sralph 		return( SZINT );
93616179Sralph 		}
93716179Sralph 	/* note: no pointers to fields */
93816179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
93916179Sralph 	}
94016179Sralph 
94116179Sralph NODE *
94216179Sralph convert( p, f )  register NODE *p; {
94316179Sralph 	/*  convert an operand of p
94416179Sralph 	    f is either CVTL or CVTR
94516179Sralph 	    operand has type int, and is converted by the size of the other side
94616179Sralph 	    */
94716179Sralph 
94816179Sralph 	register NODE *q, *r;
94916179Sralph 
95016179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
95116179Sralph 
95216179Sralph 	r = block( PMCONV,
95316179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
95416179Sralph 	r = clocal(r);
95516179Sralph 	if( f == CVTL )
95616179Sralph 		p->in.left = r;
95716179Sralph 	else
95816179Sralph 		p->in.right = r;
95916179Sralph 	return(p);
96016179Sralph 
96116179Sralph 	}
96216179Sralph 
96316179Sralph econvert( p ) register NODE *p; {
96416179Sralph 
96516179Sralph 	/* change enums to ints, or appropriate types */
96616179Sralph 
96716179Sralph 	register TWORD ty;
96816179Sralph 
96916179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
97016179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
97116179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
97216179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
97316179Sralph 		else ty = LONG;
97416179Sralph 		ty = ctype( ty );
97516179Sralph 		p->fn.csiz = ty;
97616179Sralph 		MODTYPE(p->in.type,ty);
97716179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
97816179Sralph 		}
97916179Sralph 	}
98016179Sralph 
98116179Sralph NODE *
98216179Sralph pconvert( p ) register NODE *p; {
98316179Sralph 
98416179Sralph 	/* if p should be changed into a pointer, do so */
98516179Sralph 
98616179Sralph 	if( ISARY( p->in.type) ){
98716179Sralph 		p->in.type = DECREF( p->in.type );
98816179Sralph 		++p->fn.cdim;
98916179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
99016179Sralph 		}
99116179Sralph 	if( ISFTN( p->in.type) )
99216179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
99316179Sralph 
99416179Sralph 	return( p );
99516179Sralph 	}
99616179Sralph 
99716179Sralph NODE *
99816179Sralph oconvert(p) register NODE *p; {
99916179Sralph 	/* convert the result itself: used for pointer and unsigned */
100016179Sralph 
100116179Sralph 	switch(p->in.op) {
100216179Sralph 
100316179Sralph 	case LE:
100416179Sralph 	case LT:
100516179Sralph 	case GE:
100616179Sralph 	case GT:
100716179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
100816179Sralph 	case EQ:
100916179Sralph 	case NE:
101016179Sralph 		return( p );
101116179Sralph 
101216179Sralph 	case MINUS:
101316179Sralph 		return(  clocal( block( PVCONV,
101416179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
101516179Sralph 		}
101616179Sralph 
101716179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
101816179Sralph 
101916179Sralph 	return(p);
102016179Sralph 	}
102116179Sralph 
102216179Sralph NODE *
102316179Sralph ptmatch(p)  register NODE *p; {
102416179Sralph 
102516179Sralph 	/* makes the operands of p agree; they are
102616179Sralph 	   either pointers or integers, by this time */
102716179Sralph 	/* with MINUS, the sizes must be the same */
102816179Sralph 	/* with COLON, the types must be the same */
102916179Sralph 
103016179Sralph 	TWORD t1, t2, t;
103116179Sralph 	int o, d2, d, s2, s;
103216179Sralph 
103316179Sralph 	o = p->in.op;
103416179Sralph 	t = t1 = p->in.left->in.type;
103516179Sralph 	t2 = p->in.right->in.type;
103616179Sralph 	d = p->in.left->fn.cdim;
103716179Sralph 	d2 = p->in.right->fn.cdim;
103816179Sralph 	s = p->in.left->fn.csiz;
103916179Sralph 	s2 = p->in.right->fn.csiz;
104016179Sralph 
104116179Sralph 	switch( o ){
104216179Sralph 
104316179Sralph 	case ASSIGN:
104416179Sralph 	case RETURN:
104516179Sralph 	case CAST:
104616179Sralph 		{  break; }
104716179Sralph 
104816179Sralph 	case MINUS:
104916179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
105016179Sralph 			uerror( "illegal pointer subtraction");
105116179Sralph 			}
105216179Sralph 		   break;
105316179Sralph 		   }
105416179Sralph 	case COLON:
105516179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
105616179Sralph 		   break;
105716179Sralph 		   }
105816179Sralph 	default:  /* must work harder: relationals or comparisons */
105916179Sralph 
106016179Sralph 		if( !ISPTR(t1) ){
106116179Sralph 			t = t2;
106216179Sralph 			d = d2;
106316179Sralph 			s = s2;
106416179Sralph 			break;
106516179Sralph 			}
106616179Sralph 		if( !ISPTR(t2) ){
106716179Sralph 			break;
106816179Sralph 			}
106916179Sralph 
107016179Sralph 		/* both are pointers */
107116179Sralph 		if( talign(t2,s2) < talign(t,s) ){
107216179Sralph 			t = t2;
107316179Sralph 			s = s2;
107416179Sralph 			}
107516179Sralph 		break;
107616179Sralph 		}
107716179Sralph 
107816179Sralph 	p->in.left = makety( p->in.left, t, d, s );
107916179Sralph 	p->in.right = makety( p->in.right, t, d, s );
108016179Sralph 	if( o!=MINUS && !logop(o) ){
108116179Sralph 
108216179Sralph 		p->in.type = t;
108316179Sralph 		p->fn.cdim = d;
108416179Sralph 		p->fn.csiz = s;
108516179Sralph 		}
108616179Sralph 
108716179Sralph 	return(clocal(p));
108816179Sralph 	}
108916179Sralph 
109016179Sralph int tdebug = 0;
109116179Sralph 
109216179Sralph NODE *
109316179Sralph tymatch(p)  register NODE *p; {
109416179Sralph 
109516179Sralph 	/* satisfy the types of various arithmetic binary ops */
109616179Sralph 
109716179Sralph 	/* rules are:
109816179Sralph 		if assignment, op, type of LHS
109916179Sralph 		if any float or doubles, make double
110016179Sralph 		if any longs, make long
110116179Sralph 		otherwise, make int
110216179Sralph 		if either operand is unsigned, the result is...
110316179Sralph 	*/
110416179Sralph 
110516179Sralph 	register TWORD t1, t2, t, tu;
110616179Sralph 	register o, u;
110716179Sralph 
110816179Sralph 	o = p->in.op;
110916179Sralph 
111016179Sralph 	t1 = p->in.left->in.type;
111116179Sralph 	t2 = p->in.right->in.type;
111216179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
111316179Sralph 		uerror("void type illegal in expression");
111416179Sralph 
111516179Sralph 	u = 0;
111616179Sralph 	if( ISUNSIGNED(t1) ){
111716179Sralph 		u = 1;
111816179Sralph 		t1 = DEUNSIGN(t1);
111916179Sralph 		}
112016179Sralph 	if( ISUNSIGNED(t2) ){
112116179Sralph 		u = 1;
112216179Sralph 		t2 = DEUNSIGN(t2);
112316179Sralph 		}
112416179Sralph 
112516179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
112616179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
112716179Sralph 
112817749Sralph #ifdef SPRECC
112917749Sralph 	if( t1 == DOUBLE || t2 == DOUBLE )
113017749Sralph 		t = DOUBLE;
113117749Sralph 	else if( t1 == FLOAT || t2 == FLOAT )
113217749Sralph 		t = FLOAT;
113317749Sralph #else
113417749Sralph 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
113517749Sralph 		t = DOUBLE;
113617749Sralph #endif
113716179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
113816179Sralph 	else t = INT;
113916179Sralph 
114016179Sralph 	if( asgop(o) ){
114116179Sralph 		tu = p->in.left->in.type;
114216179Sralph 		t = t1;
114316179Sralph 		}
114416179Sralph 	else {
114516179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
114616179Sralph 		}
114716179Sralph 
114816179Sralph 	/* because expressions have values that are at least as wide
114916179Sralph 	   as INT or UNSIGNED, the only conversions needed
115016179Sralph 	   are those involving FLOAT/DOUBLE, and those
115116179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
115216179Sralph 
115316179Sralph 	if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
115416179Sralph 
115516179Sralph 	if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
115616179Sralph 
115716179Sralph 	if( asgop(o) ){
115816179Sralph 		p->in.type = p->in.left->in.type;
115916179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
116016179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
116116179Sralph 		}
116216179Sralph 	else if( !logop(o) ){
116316179Sralph 		p->in.type = tu;
116416179Sralph 		p->fn.cdim = 0;
116516179Sralph 		p->fn.csiz = t;
116616179Sralph 		}
116716179Sralph 
116816179Sralph # ifndef BUG1
116916179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
117016179Sralph # endif
117116179Sralph 
117216179Sralph 	return(p);
117316179Sralph 	}
117416179Sralph 
117516179Sralph NODE *
117616179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
117716179Sralph 	/* make p into type t by inserting a conversion */
117816179Sralph 
117916179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
118016179Sralph 	if( t == p->in.type ){
118116179Sralph 		p->fn.cdim = d;
118216179Sralph 		p->fn.csiz = s;
118316179Sralph 		return( p );
118416179Sralph 		}
118516179Sralph 
118616179Sralph 	if( t & TMASK ){
118716179Sralph 		/* non-simple type */
118817228Sralph 		return( block( PCONV, p, NIL, t, d, s ) );
118916179Sralph 		}
119016179Sralph 
119116179Sralph 	if( p->in.op == ICON ){
119217749Sralph 		if (t == DOUBLE) {
119317749Sralph 			p->in.op = DCON;
119417749Sralph 			if (ISUNSIGNED(p->in.type))
119517749Sralph 				p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
119617749Sralph 			else
119717749Sralph 				p->dpn.dval = p->tn.lval;
119817749Sralph 			p->in.type = p->fn.csiz = t;
119917749Sralph 			return (clocal(p));
120017749Sralph 		}
120117749Sralph 		if (t == FLOAT) {
120216179Sralph 			p->in.op = FCON;
120316179Sralph 			if( ISUNSIGNED(p->in.type) ){
120417749Sralph 				p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval;
120516179Sralph 				}
120616179Sralph 			else {
120717749Sralph 				p->fpn.fval = p->tn.lval;
120816179Sralph 				}
120916179Sralph 
121016179Sralph 			p->in.type = p->fn.csiz = t;
121116179Sralph 			return( clocal(p) );
121216179Sralph 			}
121316179Sralph 		}
121417749Sralph 	else if (p->in.op == FCON && t == DOUBLE) {
121517749Sralph 		double db;
121616179Sralph 
121717749Sralph 		p->in.op = DCON;
121817749Sralph 		db = p->fpn.fval;
121917749Sralph 		p->dpn.dval = db;
122017749Sralph 		p->in.type = p->fn.csiz = t;
122117749Sralph 		return (clocal(p));
122217749Sralph 	} else if (p->in.op == DCON && t == FLOAT) {
122317749Sralph 		float fl;
122417749Sralph 
122517749Sralph 		p->in.op = FCON;
122617749Sralph 		fl = p->dpn.dval;
122717749Sralph #ifdef notdef
122817749Sralph 		if (fl != p->dpn.dval)
122917749Sralph 			werror("float conversion loses precision");
123017749Sralph #endif
123117749Sralph 		p->fpn.fval = fl;
123217749Sralph 		p->in.type = p->fn.csiz = t;
123317749Sralph 		return (clocal(p));
123417749Sralph 	}
123517749Sralph 
123617049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
123716179Sralph 
123816179Sralph 	}
123916179Sralph 
124016179Sralph NODE *
124116179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
124216179Sralph 
124316179Sralph 	register NODE *p;
124416179Sralph 
124516179Sralph 	p = talloc();
124616179Sralph 	p->in.op = o;
124716179Sralph 	p->in.left = l;
124816179Sralph 	p->in.right = r;
124916179Sralph 	p->in.type = t;
125016179Sralph 	p->fn.cdim = d;
125116179Sralph 	p->fn.csiz = s;
125216179Sralph 	return(p);
125316179Sralph 	}
125416179Sralph 
125516179Sralph icons(p) register NODE *p; {
125616179Sralph 	/* if p is an integer constant, return its value */
125716179Sralph 	int val;
125816179Sralph 
125916179Sralph 	if( p->in.op != ICON ){
126016179Sralph 		uerror( "constant expected");
126116179Sralph 		val = 1;
126216179Sralph 		}
126316179Sralph 	else {
126416179Sralph 		val = p->tn.lval;
126516179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
126616179Sralph 		}
126716179Sralph 	tfree( p );
126816179Sralph 	return(val);
126916179Sralph 	}
127016179Sralph 
127116179Sralph /* 	the intent of this table is to examine the
127216179Sralph 	operators, and to check them for
127316179Sralph 	correctness.
127416179Sralph 
127516179Sralph 	The table is searched for the op and the
127616179Sralph 	modified type (where this is one of the
127716179Sralph 	types INT (includes char and short), LONG,
127816179Sralph 	DOUBLE (includes FLOAT), and POINTER
127916179Sralph 
128016179Sralph 	The default action is to make the node type integer
128116179Sralph 
128216179Sralph 	The actions taken include:
128316179Sralph 		PUN	  check for puns
128416179Sralph 		CVTL	  convert the left operand
128516179Sralph 		CVTR	  convert the right operand
128616179Sralph 		TYPL	  the type is determined by the left operand
128716179Sralph 		TYPR	  the type is determined by the right operand
128816179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
128916179Sralph 		PTMATCH	  like TYMATCH, but for pointers
129016179Sralph 		LVAL	  left operand must be lval
129116179Sralph 		CVTO	  convert the op
129216179Sralph 		NCVT	  do not convert the operands
129316179Sralph 		OTHER	  handled by code
129416179Sralph 		NCVTR	  convert the left operand, not the right...
129516179Sralph 
129616179Sralph 	*/
129716179Sralph 
129816179Sralph # define MINT 01  /* integer */
129916179Sralph # define MDBI 02   /* integer or double */
130016179Sralph # define MSTR 04  /* structure */
130116179Sralph # define MPTR 010  /* pointer */
130216179Sralph # define MPTI 020  /* pointer or integer */
130316179Sralph # define MENU 040 /* enumeration variable or member */
130416179Sralph 
130516179Sralph opact( p )  NODE *p; {
130616179Sralph 
130716179Sralph 	register mt12, mt1, mt2, o;
130816179Sralph 
130916179Sralph 	mt12 = 0;
131016179Sralph 
131116179Sralph 	switch( optype(o=p->in.op) ){
131216179Sralph 
131316179Sralph 	case BITYPE:
131416179Sralph 		mt12=mt2 = moditype( p->in.right->in.type );
131516179Sralph 	case UTYPE:
131616179Sralph 		mt12 &= (mt1 = moditype( p->in.left->in.type ));
131716179Sralph 
131816179Sralph 		}
131916179Sralph 
132016179Sralph 	switch( o ){
132116179Sralph 
132216179Sralph 	case NAME :
132316179Sralph 	case STRING :
132416179Sralph 	case ICON :
132516179Sralph 	case FCON :
132617749Sralph 	case DCON :
132716179Sralph 	case CALL :
132816179Sralph 	case UNARY CALL:
132916179Sralph 	case UNARY MUL:
133016179Sralph 		{  return( OTHER ); }
133116179Sralph 	case UNARY MINUS:
133216179Sralph 		if( mt1 & MDBI ) return( TYPL );
133316179Sralph 		break;
133416179Sralph 
133516179Sralph 	case COMPL:
133616179Sralph 		if( mt1 & MINT ) return( TYPL );
133716179Sralph 		break;
133816179Sralph 
133916179Sralph 	case UNARY AND:
134016179Sralph 		{  return( NCVT+OTHER ); }
134116179Sralph 	case INIT:
134216179Sralph 	case CM:
134316180Sralph 		return( 0 );
134416180Sralph 
134516179Sralph 	case NOT:
134616179Sralph 	case CBRANCH:
134716180Sralph 		if( mt1 & MSTR ) break;
134816180Sralph 		return( 0 );
134916180Sralph 
135016179Sralph 	case ANDAND:
135116179Sralph 	case OROR:
135216180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
135316179Sralph 		return( 0 );
135416179Sralph 
135516179Sralph 	case MUL:
135616179Sralph 	case DIV:
135716179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
135816179Sralph 		break;
135916179Sralph 
136016179Sralph 	case MOD:
136116179Sralph 	case AND:
136216179Sralph 	case OR:
136316179Sralph 	case ER:
136416179Sralph 		if( mt12 & MINT ) return( TYMATCH );
136516179Sralph 		break;
136616179Sralph 
136716179Sralph 	case LS:
136816179Sralph 	case RS:
136916179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
137016179Sralph 		break;
137116179Sralph 
137216179Sralph 	case EQ:
137316179Sralph 	case NE:
137416179Sralph 	case LT:
137516179Sralph 	case LE:
137616179Sralph 	case GT:
137716179Sralph 	case GE:
137816179Sralph 		if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
137916179Sralph 		if( mt12 & MDBI ) return( TYMATCH+CVTO );
138016179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
138116179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
138216179Sralph 		else break;
138316179Sralph 
138416179Sralph 	case QUEST:
138516179Sralph 	case COMOP:
138616179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
138716179Sralph 		return( TYPR );
138816179Sralph 
138916179Sralph 	case STREF:
139016179Sralph 		return( NCVTR+OTHER );
139116179Sralph 
139216179Sralph 	case FORCE:
139316179Sralph 		return( TYPL );
139416179Sralph 
139516179Sralph 	case COLON:
139616179Sralph 		if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
139716179Sralph 		else if( mt12 & MDBI ) return( TYMATCH );
139816179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
139916179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
140016179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
140116179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
140216179Sralph 		break;
140316179Sralph 
140416179Sralph 	case ASSIGN:
140516179Sralph 	case RETURN:
140616179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
140716179Sralph 	case CAST:
140816179Sralph 		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
140916179Sralph 		if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
141016179Sralph 		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1411*18436Smckusick 		else if( mt2 == 0 &&
1412*18436Smckusick 		        ( p->in.right->in.op == CALL ||
1413*18436Smckusick 			  p->in.right->in.op == UNARY CALL)) break;
141416179Sralph 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
141516179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
141616179Sralph 		break;
141716179Sralph 
141816179Sralph 	case ASG LS:
141916179Sralph 	case ASG RS:
142016179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
142116179Sralph 		break;
142216179Sralph 
142316179Sralph 	case ASG MUL:
142416179Sralph 	case ASG DIV:
142516179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
142616179Sralph 		break;
142716179Sralph 
142816179Sralph 	case ASG MOD:
142916179Sralph 	case ASG AND:
143016179Sralph 	case ASG OR:
143116179Sralph 	case ASG ER:
143216179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
143316179Sralph 		break;
143416179Sralph 
143516179Sralph 	case ASG PLUS:
143616179Sralph 	case ASG MINUS:
143716179Sralph 	case INCR:
143816179Sralph 	case DECR:
143916179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
144016179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
144116179Sralph 		break;
144216179Sralph 
144316179Sralph 	case MINUS:
144416179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
144516179Sralph 		if( mt2 & MPTR ) break;
144616179Sralph 	case PLUS:
144716179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
144816179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
144916179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
145016179Sralph 
145116179Sralph 		}
145216179Sralph 	uerror( "operands of %s have incompatible types", opst[o] );
145316179Sralph 	return( NCVT );
145416179Sralph 	}
145516179Sralph 
145616179Sralph moditype( ty ) TWORD ty; {
145716179Sralph 
145816179Sralph 	switch( ty ){
145916179Sralph 
146016179Sralph 	case TVOID:
146117206Sralph 		return( MPTR );
146216179Sralph 	case UNDEF:
146316179Sralph 		return(0); /* type is void */
146416179Sralph 	case ENUMTY:
146516179Sralph 	case MOETY:
146616179Sralph 		return( MENU );
146716179Sralph 
146816179Sralph 	case STRTY:
146916179Sralph 	case UNIONTY:
147016179Sralph 		return( MSTR );
147116179Sralph 
147216179Sralph 	case CHAR:
147316179Sralph 	case SHORT:
147416179Sralph 	case UCHAR:
147516179Sralph 	case USHORT:
147616179Sralph 		return( MINT|MPTI|MDBI );
147716179Sralph 	case UNSIGNED:
147816179Sralph 	case ULONG:
147916179Sralph 	case INT:
148016179Sralph 	case LONG:
148116179Sralph 		return( MINT|MDBI|MPTI );
148216179Sralph 	case FLOAT:
148316179Sralph 	case DOUBLE:
148416179Sralph 		return( MDBI );
148516179Sralph 	default:
148616179Sralph 		return( MPTR|MPTI );
148716179Sralph 
148816179Sralph 		}
148916179Sralph 	}
149016179Sralph 
149116179Sralph NODE *
149216179Sralph doszof( p )  register NODE *p; {
149316179Sralph 	/* do sizeof p */
149416179Sralph 	int i;
149516179Sralph 
149616179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
149716179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
149816179Sralph 
149916179Sralph 	tfree(p);
150016179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
150116179Sralph 	return( bcon( i ) );
150216179Sralph 	}
150316179Sralph 
150416179Sralph # ifndef BUG2
150516179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
150616179Sralph 	register ty;
150716179Sralph 
150816179Sralph 	*a = *b = down+1;
150916179Sralph 	while( down > 1 ){
151016179Sralph 		printf( "\t" );
151116179Sralph 		down -= 2;
151216179Sralph 		}
151316179Sralph 	if( down ) printf( "    " );
151416179Sralph 
151516179Sralph 	ty = optype( p->in.op );
151616179Sralph 
151716179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
151816179Sralph 	if( ty == LTYPE ){
151916179Sralph 		printf( CONFMT, p->tn.lval );
152016179Sralph 		printf( ", %d, ", p->tn.rval );
152116179Sralph 		}
152216179Sralph 	tprint( p->in.type );
152316179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
152416179Sralph 	}
152516179Sralph # endif
152616179Sralph 
152716179Sralph prtdcon( p ) register NODE *p; {
152817749Sralph 	int o = p->in.op, i;
152916179Sralph 
153017749Sralph 	if( o == DCON || o == FCON ){
153116179Sralph 		locctr( DATA );
153217749Sralph 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
153316179Sralph 		deflab( i = getlab() );
153417749Sralph 		if( o == FCON )
153517749Sralph 			fincode( p->fpn.fval, SZFLOAT );
153617749Sralph 		else
153717749Sralph 			fincode( p->dpn.dval, SZDOUBLE );
153816179Sralph 		p->tn.lval = 0;
153916179Sralph 		p->tn.rval = -i;
154017749Sralph 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
154116179Sralph 		p->in.op = NAME;
154216179Sralph 		}
154316179Sralph 	}
154416179Sralph 
154516179Sralph 
154616179Sralph int edebug = 0;
154716179Sralph ecomp( p ) register NODE *p; {
154816179Sralph # ifndef BUG2
154916179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
155016179Sralph # endif
155116179Sralph 	if( !reached ){
155216179Sralph 		werror( "statement not reached" );
155316179Sralph 		reached = 1;
155416179Sralph 		}
155516179Sralph 	p = optim(p);
155616179Sralph 	walkf( p, prtdcon );
155716179Sralph 	locctr( PROG );
155816179Sralph 	ecode( p );
155916179Sralph 	tfree(p);
156016179Sralph 	}
156116179Sralph 
156216179Sralph # ifdef STDPRTREE
156316179Sralph # ifndef ONEPASS
156416179Sralph 
156516179Sralph prtree(p) register NODE *p; {
156616179Sralph 
156716179Sralph 	register struct symtab *q;
156816179Sralph 	register ty;
156916179Sralph 
157016179Sralph # ifdef MYPRTREE
157116179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
157216179Sralph #endif
157316179Sralph 
157416179Sralph 	ty = optype(p->in.op);
157516179Sralph 
157616179Sralph 	printf( "%d\t", p->in.op );
157716179Sralph 
157816179Sralph 	if( ty == LTYPE ) {
157916179Sralph 		printf( CONFMT, p->tn.lval );
158016179Sralph 		printf( "\t" );
158116179Sralph 		}
158216179Sralph 	if( ty != BITYPE ) {
158316179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
158416179Sralph 		else printf( "%d\t", p->tn.rval );
158516179Sralph 		}
158616179Sralph 
158716179Sralph 	printf( "%o\t", p->in.type );
158816179Sralph 
158916179Sralph 	/* handle special cases */
159016179Sralph 
159116179Sralph 	switch( p->in.op ){
159216179Sralph 
159316179Sralph 	case NAME:
159416179Sralph 	case ICON:
159516179Sralph 		/* print external name */
159616179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
159716179Sralph 		else if( p->tn.rval >= 0 ){
159816179Sralph 			q = &stab[p->tn.rval];
159916179Sralph 			printf(  "%s\n", exname(q->sname) );
160016179Sralph 			}
160116179Sralph 		else { /* label */
160216179Sralph 			printf( LABFMT, -p->tn.rval );
160316179Sralph 			}
160416179Sralph 		break;
160516179Sralph 
160616179Sralph 	case STARG:
160716179Sralph 	case STASG:
160816179Sralph 	case STCALL:
160916179Sralph 	case UNARY STCALL:
161016179Sralph 		/* print out size */
161116179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
161216179Sralph 
161316179Sralph 		/* note: p->in.left not a field... */
161416179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
161516179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
161616179Sralph 		break;
161716179Sralph 
161816179Sralph 	default:
161916179Sralph 		printf(  "\n" );
162016179Sralph 		}
162116179Sralph 
162216179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
162316179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
162416179Sralph 
162516179Sralph 	}
162616179Sralph 
162716179Sralph # else
162816179Sralph 
162916179Sralph p2tree(p) register NODE *p; {
163016179Sralph 	register ty;
163116179Sralph 
163216179Sralph # ifdef MYP2TREE
163316179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
163416179Sralph # endif
163516179Sralph 
163616179Sralph 	ty = optype(p->in.op);
163716179Sralph 
163816179Sralph 	switch( p->in.op ){
163916179Sralph 
164016179Sralph 	case NAME:
164116179Sralph 	case ICON:
164216179Sralph #ifndef FLEXNAMES
164316179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
164416179Sralph #else
164516179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
164616179Sralph #endif
164716179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
164816179Sralph 			register char *cp;
164916179Sralph 			register i;
165016179Sralph 			cp = exname( stab[p->tn.rval].sname );
165116179Sralph #ifndef FLEXNAMES
165216179Sralph 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
165316179Sralph #else
165416179Sralph 			p->in.name = tstr(cp);
165516179Sralph #endif
165616179Sralph 			}
165716179Sralph #ifndef FLEXNAMES
165816179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
165916179Sralph #else
166016179Sralph 		else {
166116179Sralph 			char temp[32];
166216179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
166316179Sralph 			p->in.name = tstr(temp);
166416179Sralph 		}
166516179Sralph #endif
166616179Sralph 		break;
166716179Sralph 
166816179Sralph 	case STARG:
166916179Sralph 	case STASG:
167016179Sralph 	case STCALL:
167116179Sralph 	case UNARY STCALL:
167216179Sralph 		/* set up size parameters */
167316179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
167416179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
167516179Sralph 		break;
167616179Sralph 
167716179Sralph 	case REG:
167816179Sralph 		rbusy( p->tn.rval, p->in.type );
167916179Sralph 	default:
168016179Sralph #ifndef FLEXNAMES
168116179Sralph 		p->in.name[0] = '\0';
168216179Sralph #else
168316179Sralph 		p->in.name = "";
168416179Sralph #endif
168516179Sralph 		}
168616179Sralph 
168716179Sralph 	p->in.rall = NOPREF;
168816179Sralph 
168916179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
169016179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
169116179Sralph 	}
169216179Sralph 
169316179Sralph # endif
169416179Sralph # endif
1695