xref: /csrg-svn/old/pcc/mip/trees.c (revision 17206)
1*17206Sralph static char *sccsid ="@(#)trees.c	4.4 (Berkeley) 09/20/84";
216179Sralph # include "mfile1"
316179Sralph 
416179Sralph 	    /* corrections when in violation of lint */
516179Sralph 
616179Sralph /*	some special actions, used in finding the type of nodes */
716179Sralph # define NCVT 01
816179Sralph # define PUN 02
916179Sralph # define TYPL 04
1016179Sralph # define TYPR 010
1116179Sralph # define TYMATCH 040
1216179Sralph # define LVAL 0100
1316179Sralph # define CVTO 0200
1416179Sralph # define CVTL 0400
1516179Sralph # define CVTR 01000
1616179Sralph # define PTMATCH 02000
1716179Sralph # define OTHER 04000
1816179Sralph # define NCVTR 010000
1916179Sralph 
2016179Sralph /* node conventions:
2116179Sralph 
2216179Sralph 	NAME:	rval>0 is stab index for external
2316179Sralph 		rval<0 is -inlabel number
2416179Sralph 		lval is offset in bits
2516179Sralph 	ICON:	lval has the value
2616179Sralph 		rval has the STAB index, or - label number,
2716179Sralph 			if a name whose address is in the constant
2816179Sralph 		rval = NONAME means no name
2916179Sralph 	REG:	rval is reg. identification cookie
3016179Sralph 
3116179Sralph 	*/
3216179Sralph 
3316179Sralph int bdebug = 0;
3416179Sralph extern ddebug;
3516179Sralph 
3616179Sralph NODE *
3716179Sralph buildtree( o, l, r ) register NODE *l, *r; {
3816179Sralph 	register NODE *p, *q;
3916179Sralph 	register actions;
4016179Sralph 	register opty;
4116179Sralph 	register struct symtab *sp;
4216179Sralph 	register NODE *lr, *ll;
4316179Sralph 	int i;
4416179Sralph 	extern int eprint();
4516179Sralph 
4616179Sralph # ifndef BUG1
4716179Sralph 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
4816179Sralph # endif
4916179Sralph 	opty = optype(o);
5016179Sralph 
5116179Sralph 	/* check for constants */
5216179Sralph 
5316179Sralph 	if( opty == UTYPE && l->in.op == ICON ){
5416179Sralph 
5516179Sralph 		switch( o ){
5616179Sralph 
5716179Sralph 		case NOT:
5816179Sralph 			if( hflag ) werror( "constant argument to NOT" );
5916179Sralph 		case UNARY MINUS:
6016179Sralph 		case COMPL:
6116179Sralph 			if( conval( l, o, l ) ) return(l);
6216179Sralph 			break;
6316179Sralph 
6416179Sralph 			}
6516179Sralph 		}
6616179Sralph 
6716179Sralph 	else if( o==UNARY MINUS && l->in.op==FCON ){
6816179Sralph 		l->fpn.dval = -l->fpn.dval;
6916179Sralph 		return(l);
7016179Sralph 		}
7116179Sralph 
7216179Sralph 	else if( o==QUEST && l->in.op==ICON ) {
7316179Sralph 		l->in.op = FREE;
7416179Sralph 		r->in.op = FREE;
7516179Sralph 		if( l->tn.lval ){
7616179Sralph 			tfree( r->in.right );
7716179Sralph 			return( r->in.left );
7816179Sralph 			}
7916179Sralph 		else {
8016179Sralph 			tfree( r->in.left );
8116179Sralph 			return( r->in.right );
8216179Sralph 			}
8316179Sralph 		}
8416179Sralph 
8516179Sralph 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
8616179Sralph 
8716179Sralph 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
8816179Sralph 
8916179Sralph 		switch( o ){
9016179Sralph 
9116179Sralph 		case ULT:
9216179Sralph 		case UGT:
9316179Sralph 		case ULE:
9416179Sralph 		case UGE:
9516179Sralph 		case LT:
9616179Sralph 		case GT:
9716179Sralph 		case LE:
9816179Sralph 		case GE:
9916179Sralph 		case EQ:
10016179Sralph 		case NE:
10116179Sralph 		case ANDAND:
10216179Sralph 		case OROR:
10316179Sralph 		case CBRANCH:
10416179Sralph 
10516179Sralph 		ccwarn:
10616179Sralph 			if( hflag ) werror( "constant in conditional context" );
10716179Sralph 
10816179Sralph 		case PLUS:
10916179Sralph 		case MINUS:
11016179Sralph 		case MUL:
11116179Sralph 		case DIV:
11216179Sralph 		case MOD:
11316179Sralph 		case AND:
11416179Sralph 		case OR:
11516179Sralph 		case ER:
11616179Sralph 		case LS:
11716179Sralph 		case RS:
11816179Sralph 			if( conval( l, o, r ) ) {
11916179Sralph 				r->in.op = FREE;
12016179Sralph 				return(l);
12116179Sralph 				}
12216179Sralph 			break;
12316179Sralph 			}
12416179Sralph 		}
12516179Sralph 
12616179Sralph 	else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) &&
12716179Sralph 		(r->in.op==FCON||r->in.op==ICON) ){
12816179Sralph 		switch(o){
12916179Sralph 		case PLUS:
13016179Sralph 		case MINUS:
13116179Sralph 		case MUL:
13216179Sralph 		case DIV:
13316179Sralph 			if( l->in.op == ICON ){
13416179Sralph 				l->fpn.dval = l->tn.lval;
13516179Sralph 				}
13616179Sralph 			if( r->in.op == ICON ){
13716179Sralph 				r->fpn.dval = r->tn.lval;
13816179Sralph 				}
13916179Sralph 			l->in.op = FCON;
14016179Sralph 			l->in.type = l->fn.csiz = DOUBLE;
14116179Sralph 			r->in.op = FREE;
14216179Sralph 			switch(o){
14316179Sralph 			case PLUS:
14416179Sralph 				l->fpn.dval += r->fpn.dval;
14516179Sralph 				return(l);
14616179Sralph 			case MINUS:
14716179Sralph 				l->fpn.dval -= r->fpn.dval;
14816179Sralph 				return(l);
14916179Sralph 			case MUL:
15016179Sralph 				l->fpn.dval *= r->fpn.dval;
15116179Sralph 				return(l);
15216179Sralph 			case DIV:
15316179Sralph 				if( r->fpn.dval == 0 ) uerror( "division by 0." );
15416179Sralph 				else l->fpn.dval /= r->fpn.dval;
15516179Sralph 				return(l);
15616179Sralph 				}
15716179Sralph 			}
15816179Sralph 		}
15916179Sralph 
16016179Sralph 	/* its real; we must make a new node */
16116179Sralph 
16216179Sralph 	p = block( o, l, r, INT, 0, INT );
16316179Sralph 
16416179Sralph 	actions = opact(p);
16516179Sralph 
16616179Sralph 	if( actions&LVAL ){ /* check left descendent */
16716179Sralph 		if( notlval(p->in.left) ) {
16816179Sralph 			uerror( "illegal lhs of assignment operator" );
16916179Sralph 			}
17016179Sralph 		}
17116179Sralph 
17216179Sralph 	if( actions & NCVTR ){
17316179Sralph 		p->in.left = pconvert( p->in.left );
17416179Sralph 		}
17516179Sralph 	else if( !(actions & NCVT ) ){
17616179Sralph 		switch( opty ){
17716179Sralph 
17816179Sralph 		case BITYPE:
17916179Sralph 			p->in.right = pconvert( p->in.right );
18016179Sralph 		case UTYPE:
18116179Sralph 			p->in.left = pconvert( p->in.left );
18216179Sralph 
18316179Sralph 			}
18416179Sralph 		}
18516179Sralph 
18616179Sralph 	if( (actions&PUN) && (o!=CAST||cflag) ){
18716179Sralph 		chkpun(p);
18816179Sralph 		}
18916179Sralph 
19016179Sralph 	if( actions & (TYPL|TYPR) ){
19116179Sralph 
19216179Sralph 		q = (actions&TYPL) ? p->in.left : p->in.right;
19316179Sralph 
19416179Sralph 		p->in.type = q->in.type;
19516179Sralph 		p->fn.cdim = q->fn.cdim;
19616179Sralph 		p->fn.csiz = q->fn.csiz;
19716179Sralph 		}
19816179Sralph 
19916179Sralph 	if( actions & CVTL ) p = convert( p, CVTL );
20016179Sralph 	if( actions & CVTR ) p = convert( p, CVTR );
20116179Sralph 	if( actions & TYMATCH ) p = tymatch(p);
20216179Sralph 	if( actions & PTMATCH ) p = ptmatch(p);
20316179Sralph 
20416179Sralph 	if( actions & OTHER ){
20516179Sralph 		l = p->in.left;
20616179Sralph 		r = p->in.right;
20716179Sralph 
20816179Sralph 		switch(o){
20916179Sralph 
21016179Sralph 		case NAME:
21116179Sralph 			sp = &stab[idname];
21216179Sralph 			if( sp->stype == UNDEF ){
21316179Sralph #ifndef FLEXNAMES
21416179Sralph 				uerror( "%.8s undefined", sp->sname );
21516179Sralph #else
21616179Sralph 				uerror( "%s undefined", sp->sname );
21716179Sralph #endif
21816179Sralph 				/* make p look reasonable */
21916179Sralph 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
22016179Sralph 				p->tn.rval = idname;
22116179Sralph 				p->tn.lval = 0;
22216179Sralph 				defid( p, SNULL );
22316179Sralph 				break;
22416179Sralph 				}
22516179Sralph 			p->in.type = sp->stype;
22616179Sralph 			p->fn.cdim = sp->dimoff;
22716179Sralph 			p->fn.csiz = sp->sizoff;
22816179Sralph 			p->tn.lval = 0;
22916179Sralph 			p->tn.rval = idname;
23016179Sralph 			/* special case: MOETY is really an ICON... */
23116179Sralph 			if( p->in.type == MOETY ){
23216179Sralph 				p->tn.rval = NONAME;
23316179Sralph 				p->tn.lval = sp->offset;
23416179Sralph 				p->fn.cdim = 0;
23516179Sralph 				p->in.type = ENUMTY;
23616179Sralph 				p->in.op = ICON;
23716179Sralph 				}
23816179Sralph 			break;
23916179Sralph 
24016179Sralph 		case ICON:
24116179Sralph 			p->in.type = INT;
24216179Sralph 			p->fn.cdim = 0;
24316179Sralph 			p->fn.csiz = INT;
24416179Sralph 			break;
24516179Sralph 
24616179Sralph 		case STRING:
24716179Sralph 			p->in.op = NAME;
24816179Sralph 			p->in.type = CHAR+ARY;
24916179Sralph 			p->tn.lval = 0;
25016179Sralph 			p->tn.rval = NOLAB;
25116179Sralph 			p->fn.cdim = curdim;
25216179Sralph 			p->fn.csiz = CHAR;
25316179Sralph 			break;
25416179Sralph 
25516179Sralph 		case FCON:
25616179Sralph 			p->tn.lval = 0;
25716179Sralph 			p->tn.rval = 0;
25816179Sralph 			p->in.type = DOUBLE;
25916179Sralph 			p->fn.cdim = 0;
26016179Sralph 			p->fn.csiz = DOUBLE;
26116179Sralph 			break;
26216179Sralph 
26316179Sralph 		case STREF:
26416179Sralph 			/* p->x turned into *(p+offset) */
26516179Sralph 			/* rhs must be a name; check correctness */
26616179Sralph 
26716179Sralph 			i = r->tn.rval;
26816179Sralph 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
26916179Sralph 				uerror( "member of structure or union required" );
27016179Sralph 				}else
27116179Sralph 			/* if this name is non-unique, find right one */
27216179Sralph 			if( stab[i].sflags & SNONUNIQ &&
27316179Sralph 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
27416179Sralph 				(l->fn.csiz +1) >= 0 ){
27516179Sralph 				/* nonunique name && structure defined */
27616179Sralph 				char * memnam, * tabnam;
27716179Sralph 				register k;
27816179Sralph 				int j;
27916179Sralph 				int memi;
28016179Sralph 				j=dimtab[l->fn.csiz+1];
28116179Sralph 				for( ; (memi=dimtab[j]) >= 0; ++j ){
28216179Sralph 					tabnam = stab[memi].sname;
28316179Sralph 					memnam = stab[i].sname;
28416179Sralph # ifndef BUG1
28516179Sralph 					if( ddebug>1 ){
28616179Sralph #ifndef FLEXNAMES
28716179Sralph 						printf("member %.8s==%.8s?\n",
28816179Sralph #else
28916179Sralph 						printf("member %s==%s?\n",
29016179Sralph #endif
29116179Sralph 							memnam, tabnam);
29216179Sralph 						}
29316179Sralph # endif
29416179Sralph 					if( stab[memi].sflags & SNONUNIQ ){
29516179Sralph #ifndef FLEXNAMES
29616179Sralph 						for( k=0; k<NCHNAM; ++k ){
29716179Sralph 							if(*memnam++!=*tabnam)
29816179Sralph 								goto next;
29916179Sralph 							if(!*tabnam++) break;
30016179Sralph 							}
30116179Sralph #else
30216179Sralph 						if (memnam != tabnam)
30316179Sralph 							goto next;
30416179Sralph #endif
30516179Sralph 						r->tn.rval = i = memi;
30616179Sralph 						break;
30716179Sralph 						}
30816179Sralph 					next: continue;
30916179Sralph 					}
31016179Sralph 				if( memi < 0 )
31116179Sralph #ifndef FLEXNAMES
31216179Sralph 					uerror("illegal member use: %.8s",
31316179Sralph #else
31416179Sralph 					uerror("illegal member use: %s",
31516179Sralph #endif
31616179Sralph 						stab[i].sname);
31716179Sralph 				}
31816179Sralph 			else {
31916179Sralph 				register j;
32016179Sralph 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
32116179Sralph 					if( stab[i].sflags & SNONUNIQ ){
32216179Sralph 						uerror( "nonunique name demands struct/union or struct/union pointer" );
32316179Sralph 						}
32416179Sralph 					else werror( "struct/union or struct/union pointer required" );
32516179Sralph 					}
32616179Sralph 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
32716179Sralph 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
32816179Sralph #ifndef FLEXNAMES
32916179Sralph 					werror( "illegal member use: %.8s", stab[i].sname );
33016179Sralph #else
33116179Sralph 					werror( "illegal member use: %s", stab[i].sname );
33216179Sralph #endif
33316179Sralph 					}
33416179Sralph 				}
33516179Sralph 
33616179Sralph 			p = stref( p );
33716179Sralph 			break;
33816179Sralph 
33916179Sralph 		case UNARY MUL:
34016179Sralph 			if( l->in.op == UNARY AND ){
34116179Sralph 				p->in.op = l->in.op = FREE;
34216179Sralph 				p = l->in.left;
34316179Sralph 				}
34416179Sralph 			if( !ISPTR(l->in.type))uerror("illegal indirection");
34516179Sralph 			p->in.type = DECREF(l->in.type);
34616179Sralph 			p->fn.cdim = l->fn.cdim;
34716179Sralph 			p->fn.csiz = l->fn.csiz;
34816179Sralph 			break;
34916179Sralph 
35016179Sralph 		case UNARY AND:
35116179Sralph 			switch( l->in.op ){
35216179Sralph 
35316179Sralph 			case UNARY MUL:
35416179Sralph 				p->in.op = l->in.op = FREE;
35516179Sralph 				p = l->in.left;
35616179Sralph 			case NAME:
35716179Sralph 				p->in.type = INCREF( l->in.type );
35816179Sralph 				p->fn.cdim = l->fn.cdim;
35916179Sralph 				p->fn.csiz = l->fn.csiz;
36016179Sralph 				break;
36116179Sralph 
36216179Sralph 			case COMOP:
36316179Sralph 				lr = buildtree( UNARY AND, l->in.right, NIL );
36416179Sralph 				p->in.op = l->in.op = FREE;
36516179Sralph 				p = buildtree( COMOP, l->in.left, lr );
36616179Sralph 				break;
36716179Sralph 
36816179Sralph 			case QUEST:
36916179Sralph 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
37016179Sralph 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
37116179Sralph 				p->in.op = l->in.op = l->in.right->in.op = FREE;
37216179Sralph 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
37316179Sralph 				break;
37416179Sralph 
37516179Sralph # ifdef ADDROREG
37616179Sralph 			case OREG:
37716179Sralph 				/* OREG was built in clocal()
37816179Sralph 				 * for an auto or formal parameter
37916179Sralph 				 * now its address is being taken
38016179Sralph 				 * local code must unwind it
38116179Sralph 				 * back to PLUS/MINUS REG ICON
38216179Sralph 				 * according to local conventions
38316179Sralph 				 */
38416179Sralph 				{
38516179Sralph 				extern NODE * addroreg();
38616179Sralph 				p->in.op = FREE;
38716179Sralph 				p = addroreg( l );
38816179Sralph 				}
38916179Sralph 				break;
39016179Sralph 
39116179Sralph # endif
39216179Sralph 			default:
39316179Sralph 				uerror( "unacceptable operand of &" );
39416179Sralph 				break;
39516179Sralph 				}
39616179Sralph 			break;
39716179Sralph 
39816179Sralph 		case LS:
39916179Sralph 		case RS:
40016179Sralph 		case ASG LS:
40116179Sralph 		case ASG RS:
40216179Sralph 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
40316179Sralph 				p->in.right = makety(p->in.right, INT, 0, INT );
40416179Sralph 			break;
40516179Sralph 
40616179Sralph 		case RETURN:
40716179Sralph 		case ASSIGN:
40816179Sralph 		case CAST:
40916179Sralph 			/* structure assignment */
41016179Sralph 			/* take the addresses of the two sides; then make an
41116179Sralph 			/* operator using STASG and
41216179Sralph 			/* the addresses of left and right */
41316179Sralph 
41416179Sralph 			{
41516179Sralph 				register TWORD t;
41616179Sralph 				register d, s;
41716179Sralph 
41816179Sralph 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
41916179Sralph 
42016179Sralph 				r = buildtree( UNARY AND, r, NIL );
42116179Sralph 				t = r->in.type;
42216179Sralph 				d = r->fn.cdim;
42316179Sralph 				s = r->fn.csiz;
42416179Sralph 
42516179Sralph 				l = block( STASG, l, r, t, d, s );
42616179Sralph 
42716179Sralph 				if( o == RETURN ){
42816179Sralph 					p->in.op = FREE;
42916179Sralph 					p = l;
43016179Sralph 					break;
43116179Sralph 					}
43216179Sralph 
43316179Sralph 				p->in.op = UNARY MUL;
43416179Sralph 				p->in.left = l;
43516179Sralph 				p->in.right = NIL;
43616179Sralph 				break;
43716179Sralph 				}
43816179Sralph 		case COLON:
43916179Sralph 			/* structure colon */
44016179Sralph 
44116179Sralph 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
44216179Sralph 			break;
44316179Sralph 
44416179Sralph 		case CALL:
44516179Sralph 			p->in.right = r = strargs( p->in.right );
44616179Sralph 		case UNARY CALL:
44716179Sralph 			if( !ISPTR(l->in.type)) uerror("illegal function");
44816179Sralph 			p->in.type = DECREF(l->in.type);
44916179Sralph 			if( !ISFTN(p->in.type)) uerror("illegal function");
45016179Sralph 			p->in.type = DECREF( p->in.type );
45116179Sralph 			p->fn.cdim = l->fn.cdim;
45216179Sralph 			p->fn.csiz = l->fn.csiz;
45316179Sralph 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
45416179Sralph 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
45516179Sralph 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
45616179Sralph 				p->in.op += (FORTCALL-CALL);
45716179Sralph 				}
45816179Sralph 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
45916179Sralph 				/* function returning structure */
46016179Sralph 				/*  make function really return ptr to str., with * */
46116179Sralph 
46216179Sralph 				p->in.op += STCALL-CALL;
46316179Sralph 				p->in.type = INCREF( p->in.type );
46416179Sralph 				p = buildtree( UNARY MUL, p, NIL );
46516179Sralph 
46616179Sralph 				}
46716179Sralph 			break;
46816179Sralph 
46916179Sralph 		default:
47016179Sralph 			cerror( "other code %d", o );
47116179Sralph 			}
47216179Sralph 
47316179Sralph 		}
47416179Sralph 
47516179Sralph 	if( actions & CVTO ) p = oconvert(p);
47616179Sralph 	p = clocal(p);
47716179Sralph 
47816179Sralph # ifndef BUG1
47916179Sralph 	if( bdebug ) fwalk( p, eprint, 0 );
48016179Sralph # endif
48116179Sralph 
48216179Sralph 	return(p);
48316179Sralph 
48416179Sralph 	}
48516179Sralph 
48616179Sralph NODE *
48716179Sralph strargs( p ) register NODE *p;  { /* rewrite structure flavored arguments */
48816179Sralph 
48916179Sralph 	if( p->in.op == CM ){
49016179Sralph 		p->in.left = strargs( p->in.left );
49116179Sralph 		p->in.right = strargs( p->in.right );
49216179Sralph 		return( p );
49316179Sralph 		}
49416179Sralph 
49516179Sralph 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
49616179Sralph 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
49716179Sralph 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
49816179Sralph 		p = clocal(p);
49916179Sralph 		}
50016179Sralph 	return( p );
50116179Sralph 	}
50216179Sralph 
50316179Sralph chkstr( i, j, type ) TWORD type; {
50416179Sralph 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
50516179Sralph 	/* i has been checked to contain a MOS or MOU */
50616179Sralph 	/* j is the index in dimtab of the members... */
50716179Sralph 	int k, kk;
50816179Sralph 
50916179Sralph 	extern int ddebug;
51016179Sralph 
51116179Sralph # ifndef BUG1
51216179Sralph #ifndef FLEXNAMES
51316179Sralph 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
51416179Sralph #else
51516179Sralph 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
51616179Sralph #endif
51716179Sralph # endif
51816179Sralph 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
51916179Sralph 	else {
52016179Sralph 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
52116179Sralph 			if( kk >= SYMTSZ ){
52216179Sralph 				cerror( "gummy structure" );
52316179Sralph 				return(1);
52416179Sralph 				}
52516179Sralph 			if( kk == i ) return( 1 );
52616179Sralph 			switch( stab[kk].stype ){
52716179Sralph 
52816179Sralph 			case STRTY:
52916179Sralph 			case UNIONTY:
53016179Sralph 				if( type == STRTY ) continue;  /* no recursive looking for strs */
53116179Sralph 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
53216179Sralph 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
53316179Sralph 					werror(
53416179Sralph #ifndef FLEXNAMES
53516179Sralph 					"illegal member use: perhaps %.8s.%.8s?",
53616179Sralph #else
53716179Sralph 					"illegal member use: perhaps %s.%s?",
53816179Sralph #endif
53916179Sralph 					stab[kk].sname, stab[i].sname );
54016179Sralph 					return(1);
54116179Sralph 					}
54216179Sralph 				}
54316179Sralph 			}
54416179Sralph 		}
54516179Sralph 	return( 0 );
54616179Sralph 	}
54716179Sralph 
54816179Sralph conval( p, o, q ) register NODE *p, *q; {
54916179Sralph 	/* apply the op o to the lval part of p; if binary, rhs is val */
55016179Sralph 	int i, u;
55116179Sralph 	CONSZ val;
55216179Sralph 
55316179Sralph 	val = q->tn.lval;
55416179Sralph 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
55516179Sralph 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
55616179Sralph 
55716179Sralph 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
55816179Sralph 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
55916179Sralph 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
56016179Sralph 
56116179Sralph 	switch( o ){
56216179Sralph 
56316179Sralph 	case PLUS:
56416179Sralph 		p->tn.lval += val;
56516179Sralph 		if( p->tn.rval == NONAME ){
56616179Sralph 			p->tn.rval = q->tn.rval;
56716179Sralph 			p->in.type = q->in.type;
56816179Sralph 			}
56916179Sralph 		break;
57016179Sralph 	case MINUS:
57116179Sralph 		p->tn.lval -= val;
57216179Sralph 		break;
57316179Sralph 	case MUL:
57416179Sralph 		p->tn.lval *= val;
57516179Sralph 		break;
57616179Sralph 	case DIV:
57716179Sralph 		if( val == 0 ) uerror( "division by 0" );
57816179Sralph 		else p->tn.lval /= val;
57916179Sralph 		break;
58016179Sralph 	case MOD:
58116179Sralph 		if( val == 0 ) uerror( "division by 0" );
58216179Sralph 		else p->tn.lval %= val;
58316179Sralph 		break;
58416179Sralph 	case AND:
58516179Sralph 		p->tn.lval &= val;
58616179Sralph 		break;
58716179Sralph 	case OR:
58816179Sralph 		p->tn.lval |= val;
58916179Sralph 		break;
59016179Sralph 	case ER:
59116179Sralph 		p->tn.lval ^=  val;
59216179Sralph 		break;
59316179Sralph 	case LS:
59416179Sralph 		i = val;
59516179Sralph 		p->tn.lval = p->tn.lval << i;
59616179Sralph 		break;
59716179Sralph 	case RS:
59816179Sralph 		i = val;
59916179Sralph 		p->tn.lval = p->tn.lval >> i;
60016179Sralph 		break;
60116179Sralph 
60216179Sralph 	case UNARY MINUS:
60316179Sralph 		p->tn.lval = - p->tn.lval;
60416179Sralph 		break;
60516179Sralph 	case COMPL:
60616179Sralph 		p->tn.lval = ~p->tn.lval;
60716179Sralph 		break;
60816179Sralph 	case NOT:
60916179Sralph 		p->tn.lval = !p->tn.lval;
61016179Sralph 		break;
61116179Sralph 	case LT:
61216179Sralph 		p->tn.lval = p->tn.lval < val;
61316179Sralph 		break;
61416179Sralph 	case LE:
61516179Sralph 		p->tn.lval = p->tn.lval <= val;
61616179Sralph 		break;
61716179Sralph 	case GT:
61816179Sralph 		p->tn.lval = p->tn.lval > val;
61916179Sralph 		break;
62016179Sralph 	case GE:
62116179Sralph 		p->tn.lval = p->tn.lval >= val;
62216179Sralph 		break;
62316179Sralph 	case ULT:
62416179Sralph 		p->tn.lval = (p->tn.lval-val)<0;
62516179Sralph 		break;
62616179Sralph 	case ULE:
62716179Sralph 		p->tn.lval = (p->tn.lval-val)<=0;
62816179Sralph 		break;
62916179Sralph 	case UGE:
63016179Sralph 		p->tn.lval = (p->tn.lval-val)>=0;
63116179Sralph 		break;
63216179Sralph 	case UGT:
63316179Sralph 		p->tn.lval = (p->tn.lval-val)>0;
63416179Sralph 		break;
63516179Sralph 	case EQ:
63616179Sralph 		p->tn.lval = p->tn.lval == val;
63716179Sralph 		break;
63816179Sralph 	case NE:
63916179Sralph 		p->tn.lval = p->tn.lval != val;
64016179Sralph 		break;
64116179Sralph 	default:
64216179Sralph 		return(0);
64316179Sralph 		}
64416179Sralph 	return(1);
64516179Sralph 	}
64616179Sralph 
64716179Sralph chkpun(p) register NODE *p; {
64816179Sralph 
64916179Sralph 	/* checks p for the existance of a pun */
65016179Sralph 
65116179Sralph 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
65216179Sralph 
65316179Sralph 	/* one case is when enumerations are used: this applies only to lint */
65416179Sralph 	/* in the other case, one operand is a pointer, the other integer type */
65516179Sralph 	/* we check that this integer is in fact a constant zero... */
65616179Sralph 
65716179Sralph 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
65816179Sralph 	/* this falls out, because the LHS is never 0 */
65916179Sralph 
66016179Sralph 	register NODE *q;
66116179Sralph 	register t1, t2;
66216179Sralph 	register d1, d2;
66316179Sralph 
66416179Sralph 	t1 = p->in.left->in.type;
66516179Sralph 	t2 = p->in.right->in.type;
66616179Sralph 
66716179Sralph 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
66816179Sralph 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
66916179Sralph 			uerror( "illegal comparison of enums" );
67016179Sralph 			return;
67116179Sralph 			}
67216179Sralph 		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
67316179Sralph 		werror( "enumeration type clash, operator %s", opst[p->in.op] );
67416179Sralph 		return;
67516179Sralph 		}
67616179Sralph 
67716179Sralph 	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
67816179Sralph 	else q = p->in.left;
67916179Sralph 
68016179Sralph 	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
68116179Sralph 		if( q->in.op != ICON || q->tn.lval != 0 ){
68216179Sralph 			werror( "illegal combination of pointer and integer, op %s",
68316179Sralph 				opst[p->in.op] );
68416179Sralph 			}
68516179Sralph 		}
68616179Sralph 	else {
68716179Sralph 		d1 = p->in.left->fn.cdim;
68816179Sralph 		d2 = p->in.right->fn.cdim;
68916179Sralph 		for( ;; ){
69016179Sralph 			if( t1 == t2 ) {;
69116179Sralph 				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
69216179Sralph 					werror( "illegal structure pointer combination" );
69316179Sralph 					}
69416179Sralph 				return;
69516179Sralph 				}
69616179Sralph 			if( ISARY(t1) || ISPTR(t1) ){
69716179Sralph 				if( !ISARY(t2) && !ISPTR(t2) ) break;
69816179Sralph 				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
69916179Sralph 					werror( "illegal array size combination" );
70016179Sralph 					return;
70116179Sralph 					}
70216179Sralph 				if( ISARY(t1) ) ++d1;
70316179Sralph 				if( ISARY(t2) ) ++d2;
70416179Sralph 				}
70516179Sralph 			else break;
70616179Sralph 			t1 = DECREF(t1);
70716179Sralph 			t2 = DECREF(t2);
70816179Sralph 			}
70916179Sralph 		werror( "illegal pointer combination" );
71016179Sralph 		}
71116179Sralph 
71216179Sralph 	}
71316179Sralph 
71416179Sralph NODE *
71516179Sralph stref( p ) register NODE *p; {
71616179Sralph 
71716179Sralph 	TWORD t;
71816179Sralph 	int d, s, dsc, align;
71916179Sralph 	OFFSZ off;
72016179Sralph 	register struct symtab *q;
72116179Sralph 
72216179Sralph 	/* make p->x */
72316179Sralph 	/* this is also used to reference automatic variables */
72416179Sralph 
72516179Sralph 	q = &stab[p->in.right->tn.rval];
72616179Sralph 	p->in.right->in.op = FREE;
72716179Sralph 	p->in.op = FREE;
72816179Sralph 	p = pconvert( p->in.left );
72916179Sralph 
73016179Sralph 	/* make p look like ptr to x */
73116179Sralph 
73216179Sralph 	if( !ISPTR(p->in.type)){
73316179Sralph 		p->in.type = PTR+UNIONTY;
73416179Sralph 		}
73516179Sralph 
73616179Sralph 	t = INCREF( q->stype );
73716179Sralph 	d = q->dimoff;
73816179Sralph 	s = q->sizoff;
73916179Sralph 
74016179Sralph 	p = makety( p, t, d, s );
74116179Sralph 
74216179Sralph 	/* compute the offset to be added */
74316179Sralph 
74416179Sralph 	off = q->offset;
74516179Sralph 	dsc = q->sclass;
74616179Sralph 
74716179Sralph 	if( dsc & FIELD ) {  /* normalize offset */
74816179Sralph 		align = ALINT;
74916179Sralph 		s = INT;
75016179Sralph 		off = (off/align)*align;
75116179Sralph 		}
75216179Sralph 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
75316179Sralph 
75416179Sralph 	p = buildtree( UNARY MUL, p, NIL );
75516179Sralph 
75616179Sralph 	/* if field, build field info */
75716179Sralph 
75816179Sralph 	if( dsc & FIELD ){
75916179Sralph 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
76016179Sralph 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
76116179Sralph 		}
76216179Sralph 
76316179Sralph 	return( clocal(p) );
76416179Sralph 	}
76516179Sralph 
76616179Sralph notlval(p) register NODE *p; {
76716179Sralph 
76816179Sralph 	/* return 0 if p an lvalue, 1 otherwise */
76916179Sralph 
77016179Sralph 	again:
77116179Sralph 
77216179Sralph 	switch( p->in.op ){
77316179Sralph 
77416179Sralph 	case FLD:
77516179Sralph 		p = p->in.left;
77616179Sralph 		goto again;
77716179Sralph 
77816179Sralph 	case UNARY MUL:
77916179Sralph 		/* fix the &(a=b) bug, given that a and b are structures */
78016179Sralph 		if( p->in.left->in.op == STASG ) return( 1 );
78116179Sralph 		/* and the f().a bug, given that f returns a structure */
78216179Sralph 		if( p->in.left->in.op == UNARY STCALL ||
78316179Sralph 		    p->in.left->in.op == STCALL ) return( 1 );
78416179Sralph 	case NAME:
78516179Sralph 	case OREG:
78616179Sralph 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
78716179Sralph 	case REG:
78816179Sralph 		return(0);
78916179Sralph 
79016179Sralph 	default:
79116179Sralph 		return(1);
79216179Sralph 
79316179Sralph 		}
79416179Sralph 
79516179Sralph 	}
79616179Sralph 
79716179Sralph NODE *
79816179Sralph bcon( i ){ /* make a constant node with value i */
79916179Sralph 	register NODE *p;
80016179Sralph 
80116179Sralph 	p = block( ICON, NIL, NIL, INT, 0, INT );
80216179Sralph 	p->tn.lval = i;
80316179Sralph 	p->tn.rval = NONAME;
80416179Sralph 	return( clocal(p) );
80516179Sralph 	}
80616179Sralph 
80716179Sralph NODE *
80816179Sralph bpsize(p) register NODE *p; {
80916179Sralph 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
81016179Sralph 	}
81116179Sralph 
81216179Sralph OFFSZ
81316179Sralph psize( p ) NODE *p; {
81416179Sralph 	/* p is a node of type pointer; psize returns the
81516179Sralph 	   size of the thing pointed to */
81616179Sralph 
81716179Sralph 	if( !ISPTR(p->in.type) ){
81816179Sralph 		uerror( "pointer required");
81916179Sralph 		return( SZINT );
82016179Sralph 		}
82116179Sralph 	/* note: no pointers to fields */
82216179Sralph 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
82316179Sralph 	}
82416179Sralph 
82516179Sralph NODE *
82616179Sralph convert( p, f )  register NODE *p; {
82716179Sralph 	/*  convert an operand of p
82816179Sralph 	    f is either CVTL or CVTR
82916179Sralph 	    operand has type int, and is converted by the size of the other side
83016179Sralph 	    */
83116179Sralph 
83216179Sralph 	register NODE *q, *r;
83316179Sralph 
83416179Sralph 	q = (f==CVTL)?p->in.left:p->in.right;
83516179Sralph 
83616179Sralph 	r = block( PMCONV,
83716179Sralph 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
83816179Sralph 	r = clocal(r);
83916179Sralph 	if( f == CVTL )
84016179Sralph 		p->in.left = r;
84116179Sralph 	else
84216179Sralph 		p->in.right = r;
84316179Sralph 	return(p);
84416179Sralph 
84516179Sralph 	}
84616179Sralph 
84716179Sralph econvert( p ) register NODE *p; {
84816179Sralph 
84916179Sralph 	/* change enums to ints, or appropriate types */
85016179Sralph 
85116179Sralph 	register TWORD ty;
85216179Sralph 
85316179Sralph 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
85416179Sralph 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
85516179Sralph 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
85616179Sralph 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
85716179Sralph 		else ty = LONG;
85816179Sralph 		ty = ctype( ty );
85916179Sralph 		p->fn.csiz = ty;
86016179Sralph 		MODTYPE(p->in.type,ty);
86116179Sralph 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
86216179Sralph 		}
86316179Sralph 	}
86416179Sralph 
86516179Sralph NODE *
86616179Sralph pconvert( p ) register NODE *p; {
86716179Sralph 
86816179Sralph 	/* if p should be changed into a pointer, do so */
86916179Sralph 
87016179Sralph 	if( ISARY( p->in.type) ){
87116179Sralph 		p->in.type = DECREF( p->in.type );
87216179Sralph 		++p->fn.cdim;
87316179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
87416179Sralph 		}
87516179Sralph 	if( ISFTN( p->in.type) )
87616179Sralph 		return( buildtree( UNARY AND, p, NIL ) );
87716179Sralph 
87816179Sralph 	return( p );
87916179Sralph 	}
88016179Sralph 
88116179Sralph NODE *
88216179Sralph oconvert(p) register NODE *p; {
88316179Sralph 	/* convert the result itself: used for pointer and unsigned */
88416179Sralph 
88516179Sralph 	switch(p->in.op) {
88616179Sralph 
88716179Sralph 	case LE:
88816179Sralph 	case LT:
88916179Sralph 	case GE:
89016179Sralph 	case GT:
89116179Sralph 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
89216179Sralph 	case EQ:
89316179Sralph 	case NE:
89416179Sralph 		return( p );
89516179Sralph 
89616179Sralph 	case MINUS:
89716179Sralph 		return(  clocal( block( PVCONV,
89816179Sralph 			p, bpsize(p->in.left), INT, 0, INT ) ) );
89916179Sralph 		}
90016179Sralph 
90116179Sralph 	cerror( "illegal oconvert: %d", p->in.op );
90216179Sralph 
90316179Sralph 	return(p);
90416179Sralph 	}
90516179Sralph 
90616179Sralph NODE *
90716179Sralph ptmatch(p)  register NODE *p; {
90816179Sralph 
90916179Sralph 	/* makes the operands of p agree; they are
91016179Sralph 	   either pointers or integers, by this time */
91116179Sralph 	/* with MINUS, the sizes must be the same */
91216179Sralph 	/* with COLON, the types must be the same */
91316179Sralph 
91416179Sralph 	TWORD t1, t2, t;
91516179Sralph 	int o, d2, d, s2, s;
91616179Sralph 
91716179Sralph 	o = p->in.op;
91816179Sralph 	t = t1 = p->in.left->in.type;
91916179Sralph 	t2 = p->in.right->in.type;
92016179Sralph 	d = p->in.left->fn.cdim;
92116179Sralph 	d2 = p->in.right->fn.cdim;
92216179Sralph 	s = p->in.left->fn.csiz;
92316179Sralph 	s2 = p->in.right->fn.csiz;
92416179Sralph 
92516179Sralph 	switch( o ){
92616179Sralph 
92716179Sralph 	case ASSIGN:
92816179Sralph 	case RETURN:
92916179Sralph 	case CAST:
93016179Sralph 		{  break; }
93116179Sralph 
93216179Sralph 	case MINUS:
93316179Sralph 		{  if( psize(p->in.left) != psize(p->in.right) ){
93416179Sralph 			uerror( "illegal pointer subtraction");
93516179Sralph 			}
93616179Sralph 		   break;
93716179Sralph 		   }
93816179Sralph 	case COLON:
93916179Sralph 		{  if( t1 != t2 ) uerror( "illegal types in :");
94016179Sralph 		   break;
94116179Sralph 		   }
94216179Sralph 	default:  /* must work harder: relationals or comparisons */
94316179Sralph 
94416179Sralph 		if( !ISPTR(t1) ){
94516179Sralph 			t = t2;
94616179Sralph 			d = d2;
94716179Sralph 			s = s2;
94816179Sralph 			break;
94916179Sralph 			}
95016179Sralph 		if( !ISPTR(t2) ){
95116179Sralph 			break;
95216179Sralph 			}
95316179Sralph 
95416179Sralph 		/* both are pointers */
95516179Sralph 		if( talign(t2,s2) < talign(t,s) ){
95616179Sralph 			t = t2;
95716179Sralph 			s = s2;
95816179Sralph 			}
95916179Sralph 		break;
96016179Sralph 		}
96116179Sralph 
96216179Sralph 	p->in.left = makety( p->in.left, t, d, s );
96316179Sralph 	p->in.right = makety( p->in.right, t, d, s );
96416179Sralph 	if( o!=MINUS && !logop(o) ){
96516179Sralph 
96616179Sralph 		p->in.type = t;
96716179Sralph 		p->fn.cdim = d;
96816179Sralph 		p->fn.csiz = s;
96916179Sralph 		}
97016179Sralph 
97116179Sralph 	return(clocal(p));
97216179Sralph 	}
97316179Sralph 
97416179Sralph int tdebug = 0;
97516179Sralph 
97616179Sralph NODE *
97716179Sralph tymatch(p)  register NODE *p; {
97816179Sralph 
97916179Sralph 	/* satisfy the types of various arithmetic binary ops */
98016179Sralph 
98116179Sralph 	/* rules are:
98216179Sralph 		if assignment, op, type of LHS
98316179Sralph 		if any float or doubles, make double
98416179Sralph 		if any longs, make long
98516179Sralph 		otherwise, make int
98616179Sralph 		if either operand is unsigned, the result is...
98716179Sralph 	*/
98816179Sralph 
98916179Sralph 	register TWORD t1, t2, t, tu;
99016179Sralph 	register o, u;
99116179Sralph 
99216179Sralph 	o = p->in.op;
99316179Sralph 
99416179Sralph 	t1 = p->in.left->in.type;
99516179Sralph 	t2 = p->in.right->in.type;
99616179Sralph 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
99716179Sralph 		uerror("void type illegal in expression");
99816179Sralph 
99916179Sralph 	u = 0;
100016179Sralph 	if( ISUNSIGNED(t1) ){
100116179Sralph 		u = 1;
100216179Sralph 		t1 = DEUNSIGN(t1);
100316179Sralph 		}
100416179Sralph 	if( ISUNSIGNED(t2) ){
100516179Sralph 		u = 1;
100616179Sralph 		t2 = DEUNSIGN(t2);
100716179Sralph 		}
100816179Sralph 
100916179Sralph 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
101016179Sralph 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
101116179Sralph 
101216179Sralph 	if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
101316179Sralph 	else if( t1==LONG || t2==LONG ) t = LONG;
101416179Sralph 	else t = INT;
101516179Sralph 
101616179Sralph 	if( asgop(o) ){
101716179Sralph 		tu = p->in.left->in.type;
101816179Sralph 		t = t1;
101916179Sralph 		}
102016179Sralph 	else {
102116179Sralph 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
102216179Sralph 		}
102316179Sralph 
102416179Sralph 	/* because expressions have values that are at least as wide
102516179Sralph 	   as INT or UNSIGNED, the only conversions needed
102616179Sralph 	   are those involving FLOAT/DOUBLE, and those
102716179Sralph 	   from LONG to INT and ULONG to UNSIGNED */
102816179Sralph 
102916179Sralph 	if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );
103016179Sralph 
103116179Sralph 	if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );
103216179Sralph 
103316179Sralph 	if( asgop(o) ){
103416179Sralph 		p->in.type = p->in.left->in.type;
103516179Sralph 		p->fn.cdim = p->in.left->fn.cdim;
103616179Sralph 		p->fn.csiz = p->in.left->fn.csiz;
103716179Sralph 		}
103816179Sralph 	else if( !logop(o) ){
103916179Sralph 		p->in.type = tu;
104016179Sralph 		p->fn.cdim = 0;
104116179Sralph 		p->fn.csiz = t;
104216179Sralph 		}
104316179Sralph 
104416179Sralph # ifndef BUG1
104516179Sralph 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
104616179Sralph # endif
104716179Sralph 
104816179Sralph 	return(p);
104916179Sralph 	}
105016179Sralph 
105116179Sralph NODE *
105216179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; {
105316179Sralph 	/* make p into type t by inserting a conversion */
105416179Sralph 
105516179Sralph 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
105616179Sralph 	if( t == p->in.type ){
105716179Sralph 		p->fn.cdim = d;
105816179Sralph 		p->fn.csiz = s;
105916179Sralph 		return( p );
106016179Sralph 		}
106116179Sralph 
106216179Sralph 	if( t & TMASK ){
106316179Sralph 		/* non-simple type */
106417049Sralph 		return( clocal( block( PCONV, p, NIL, t, d, s ) ) );
106516179Sralph 		}
106616179Sralph 
106716179Sralph 	if( p->in.op == ICON ){
106816179Sralph 		if( t==DOUBLE||t==FLOAT ){
106916179Sralph 			p->in.op = FCON;
107016179Sralph 			if( ISUNSIGNED(p->in.type) ){
107116179Sralph 				p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
107216179Sralph 				}
107316179Sralph 			else {
107416179Sralph 				p->fpn.dval = p->tn.lval;
107516179Sralph 				}
107616179Sralph 
107716179Sralph 			p->in.type = p->fn.csiz = t;
107816179Sralph 			return( clocal(p) );
107916179Sralph 			}
108016179Sralph 		}
108116179Sralph 
108217049Sralph 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
108316179Sralph 
108416179Sralph 	}
108516179Sralph 
108616179Sralph NODE *
108716179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
108816179Sralph 
108916179Sralph 	register NODE *p;
109016179Sralph 
109116179Sralph 	p = talloc();
109216179Sralph 	p->in.op = o;
109316179Sralph 	p->in.left = l;
109416179Sralph 	p->in.right = r;
109516179Sralph 	p->in.type = t;
109616179Sralph 	p->fn.cdim = d;
109716179Sralph 	p->fn.csiz = s;
109816179Sralph 	return(p);
109916179Sralph 	}
110016179Sralph 
110116179Sralph icons(p) register NODE *p; {
110216179Sralph 	/* if p is an integer constant, return its value */
110316179Sralph 	int val;
110416179Sralph 
110516179Sralph 	if( p->in.op != ICON ){
110616179Sralph 		uerror( "constant expected");
110716179Sralph 		val = 1;
110816179Sralph 		}
110916179Sralph 	else {
111016179Sralph 		val = p->tn.lval;
111116179Sralph 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
111216179Sralph 		}
111316179Sralph 	tfree( p );
111416179Sralph 	return(val);
111516179Sralph 	}
111616179Sralph 
111716179Sralph /* 	the intent of this table is to examine the
111816179Sralph 	operators, and to check them for
111916179Sralph 	correctness.
112016179Sralph 
112116179Sralph 	The table is searched for the op and the
112216179Sralph 	modified type (where this is one of the
112316179Sralph 	types INT (includes char and short), LONG,
112416179Sralph 	DOUBLE (includes FLOAT), and POINTER
112516179Sralph 
112616179Sralph 	The default action is to make the node type integer
112716179Sralph 
112816179Sralph 	The actions taken include:
112916179Sralph 		PUN	  check for puns
113016179Sralph 		CVTL	  convert the left operand
113116179Sralph 		CVTR	  convert the right operand
113216179Sralph 		TYPL	  the type is determined by the left operand
113316179Sralph 		TYPR	  the type is determined by the right operand
113416179Sralph 		TYMATCH	  force type of left and right to match, by inserting conversions
113516179Sralph 		PTMATCH	  like TYMATCH, but for pointers
113616179Sralph 		LVAL	  left operand must be lval
113716179Sralph 		CVTO	  convert the op
113816179Sralph 		NCVT	  do not convert the operands
113916179Sralph 		OTHER	  handled by code
114016179Sralph 		NCVTR	  convert the left operand, not the right...
114116179Sralph 
114216179Sralph 	*/
114316179Sralph 
114416179Sralph # define MINT 01  /* integer */
114516179Sralph # define MDBI 02   /* integer or double */
114616179Sralph # define MSTR 04  /* structure */
114716179Sralph # define MPTR 010  /* pointer */
114816179Sralph # define MPTI 020  /* pointer or integer */
114916179Sralph # define MENU 040 /* enumeration variable or member */
115016179Sralph 
115116179Sralph opact( p )  NODE *p; {
115216179Sralph 
115316179Sralph 	register mt12, mt1, mt2, o;
115416179Sralph 
115516179Sralph 	mt12 = 0;
115616179Sralph 
115716179Sralph 	switch( optype(o=p->in.op) ){
115816179Sralph 
115916179Sralph 	case BITYPE:
116016179Sralph 		mt12=mt2 = moditype( p->in.right->in.type );
116116179Sralph 	case UTYPE:
116216179Sralph 		mt12 &= (mt1 = moditype( p->in.left->in.type ));
116316179Sralph 
116416179Sralph 		}
116516179Sralph 
116616179Sralph 	switch( o ){
116716179Sralph 
116816179Sralph 	case NAME :
116916179Sralph 	case STRING :
117016179Sralph 	case ICON :
117116179Sralph 	case FCON :
117216179Sralph 	case CALL :
117316179Sralph 	case UNARY CALL:
117416179Sralph 	case UNARY MUL:
117516179Sralph 		{  return( OTHER ); }
117616179Sralph 	case UNARY MINUS:
117716179Sralph 		if( mt1 & MDBI ) return( TYPL );
117816179Sralph 		break;
117916179Sralph 
118016179Sralph 	case COMPL:
118116179Sralph 		if( mt1 & MINT ) return( TYPL );
118216179Sralph 		break;
118316179Sralph 
118416179Sralph 	case UNARY AND:
118516179Sralph 		{  return( NCVT+OTHER ); }
118616179Sralph 	case INIT:
118716179Sralph 	case CM:
118816180Sralph 		return( 0 );
118916180Sralph 
119016179Sralph 	case NOT:
119116179Sralph 	case CBRANCH:
119216180Sralph 		if( mt1 & MSTR ) break;
119316180Sralph 		return( 0 );
119416180Sralph 
119516179Sralph 	case ANDAND:
119616179Sralph 	case OROR:
119716180Sralph 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
119816179Sralph 		return( 0 );
119916179Sralph 
120016179Sralph 	case MUL:
120116179Sralph 	case DIV:
120216179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
120316179Sralph 		break;
120416179Sralph 
120516179Sralph 	case MOD:
120616179Sralph 	case AND:
120716179Sralph 	case OR:
120816179Sralph 	case ER:
120916179Sralph 		if( mt12 & MINT ) return( TYMATCH );
121016179Sralph 		break;
121116179Sralph 
121216179Sralph 	case LS:
121316179Sralph 	case RS:
121416179Sralph 		if( mt12 & MINT ) return( TYMATCH+OTHER );
121516179Sralph 		break;
121616179Sralph 
121716179Sralph 	case EQ:
121816179Sralph 	case NE:
121916179Sralph 	case LT:
122016179Sralph 	case LE:
122116179Sralph 	case GT:
122216179Sralph 	case GE:
122316179Sralph 		if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
122416179Sralph 		if( mt12 & MDBI ) return( TYMATCH+CVTO );
122516179Sralph 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
122616179Sralph 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
122716179Sralph 		else break;
122816179Sralph 
122916179Sralph 	case QUEST:
123016179Sralph 	case COMOP:
123116179Sralph 		if( mt2&MENU ) return( TYPR+NCVTR );
123216179Sralph 		return( TYPR );
123316179Sralph 
123416179Sralph 	case STREF:
123516179Sralph 		return( NCVTR+OTHER );
123616179Sralph 
123716179Sralph 	case FORCE:
123816179Sralph 		return( TYPL );
123916179Sralph 
124016179Sralph 	case COLON:
124116179Sralph 		if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
124216179Sralph 		else if( mt12 & MDBI ) return( TYMATCH );
124316179Sralph 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
124416179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
124516179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
124616179Sralph 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
124716179Sralph 		break;
124816179Sralph 
124916179Sralph 	case ASSIGN:
125016179Sralph 	case RETURN:
125116179Sralph 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
125216179Sralph 	case CAST:
125316179Sralph 		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
125416179Sralph 		if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
125516179Sralph 		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
125616179Sralph 		else if( mt12 == 0 ) break;
125716179Sralph 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
125816179Sralph 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
125916179Sralph 		break;
126016179Sralph 
126116179Sralph 	case ASG LS:
126216179Sralph 	case ASG RS:
126316179Sralph 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
126416179Sralph 		break;
126516179Sralph 
126616179Sralph 	case ASG MUL:
126716179Sralph 	case ASG DIV:
126816179Sralph 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
126916179Sralph 		break;
127016179Sralph 
127116179Sralph 	case ASG MOD:
127216179Sralph 	case ASG AND:
127316179Sralph 	case ASG OR:
127416179Sralph 	case ASG ER:
127516179Sralph 		if( mt12 & MINT ) return( LVAL+TYMATCH );
127616179Sralph 		break;
127716179Sralph 
127816179Sralph 	case ASG PLUS:
127916179Sralph 	case ASG MINUS:
128016179Sralph 	case INCR:
128116179Sralph 	case DECR:
128216179Sralph 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
128316179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
128416179Sralph 		break;
128516179Sralph 
128616179Sralph 	case MINUS:
128716179Sralph 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
128816179Sralph 		if( mt2 & MPTR ) break;
128916179Sralph 	case PLUS:
129016179Sralph 		if( mt12 & MDBI ) return( TYMATCH );
129116179Sralph 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
129216179Sralph 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
129316179Sralph 
129416179Sralph 		}
129516179Sralph 	uerror( "operands of %s have incompatible types", opst[o] );
129616179Sralph 	return( NCVT );
129716179Sralph 	}
129816179Sralph 
129916179Sralph moditype( ty ) TWORD ty; {
130016179Sralph 
130116179Sralph 	switch( ty ){
130216179Sralph 
130316179Sralph 	case TVOID:
1304*17206Sralph 		return( MPTR );
130516179Sralph 	case UNDEF:
130616179Sralph 		return(0); /* type is void */
130716179Sralph 	case ENUMTY:
130816179Sralph 	case MOETY:
130916179Sralph 		return( MENU );
131016179Sralph 
131116179Sralph 	case STRTY:
131216179Sralph 	case UNIONTY:
131316179Sralph 		return( MSTR );
131416179Sralph 
131516179Sralph 	case CHAR:
131616179Sralph 	case SHORT:
131716179Sralph 	case UCHAR:
131816179Sralph 	case USHORT:
131916179Sralph 		return( MINT|MPTI|MDBI );
132016179Sralph 	case UNSIGNED:
132116179Sralph 	case ULONG:
132216179Sralph 	case INT:
132316179Sralph 	case LONG:
132416179Sralph 		return( MINT|MDBI|MPTI );
132516179Sralph 	case FLOAT:
132616179Sralph 	case DOUBLE:
132716179Sralph 		return( MDBI );
132816179Sralph 	default:
132916179Sralph 		return( MPTR|MPTI );
133016179Sralph 
133116179Sralph 		}
133216179Sralph 	}
133316179Sralph 
133416179Sralph NODE *
133516179Sralph doszof( p )  register NODE *p; {
133616179Sralph 	/* do sizeof p */
133716179Sralph 	int i;
133816179Sralph 
133916179Sralph 	/* whatever is the meaning of this if it is a bitfield? */
134016179Sralph 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
134116179Sralph 
134216179Sralph 	tfree(p);
134316179Sralph 	if( i <= 0 ) werror( "sizeof returns 0" );
134416179Sralph 	return( bcon( i ) );
134516179Sralph 	}
134616179Sralph 
134716179Sralph # ifndef BUG2
134816179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
134916179Sralph 	register ty;
135016179Sralph 
135116179Sralph 	*a = *b = down+1;
135216179Sralph 	while( down > 1 ){
135316179Sralph 		printf( "\t" );
135416179Sralph 		down -= 2;
135516179Sralph 		}
135616179Sralph 	if( down ) printf( "    " );
135716179Sralph 
135816179Sralph 	ty = optype( p->in.op );
135916179Sralph 
136016179Sralph 	printf("%o) %s, ", p, opst[p->in.op] );
136116179Sralph 	if( ty == LTYPE ){
136216179Sralph 		printf( CONFMT, p->tn.lval );
136316179Sralph 		printf( ", %d, ", p->tn.rval );
136416179Sralph 		}
136516179Sralph 	tprint( p->in.type );
136616179Sralph 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
136716179Sralph 	}
136816179Sralph # endif
136916179Sralph 
137016179Sralph prtdcon( p ) register NODE *p; {
137116179Sralph 	int i;
137216179Sralph 
137316179Sralph 	if( p->in.op == FCON ){
137416179Sralph 		locctr( DATA );
137516179Sralph 		defalign( ALDOUBLE );
137616179Sralph 		deflab( i = getlab() );
137716179Sralph 		fincode( p->fpn.dval, SZDOUBLE );
137816179Sralph 		p->tn.lval = 0;
137916179Sralph 		p->tn.rval = -i;
138016179Sralph 		p->in.type = DOUBLE;
138116179Sralph 		p->in.op = NAME;
138216179Sralph 		}
138316179Sralph 	}
138416179Sralph 
138516179Sralph 
138616179Sralph int edebug = 0;
138716179Sralph ecomp( p ) register NODE *p; {
138816179Sralph # ifndef BUG2
138916179Sralph 	if( edebug ) fwalk( p, eprint, 0 );
139016179Sralph # endif
139116179Sralph 	if( !reached ){
139216179Sralph 		werror( "statement not reached" );
139316179Sralph 		reached = 1;
139416179Sralph 		}
139516179Sralph 	p = optim(p);
139616179Sralph 	walkf( p, prtdcon );
139716179Sralph 	locctr( PROG );
139816179Sralph 	ecode( p );
139916179Sralph 	tfree(p);
140016179Sralph 	}
140116179Sralph 
140216179Sralph # ifdef STDPRTREE
140316179Sralph # ifndef ONEPASS
140416179Sralph 
140516179Sralph prtree(p) register NODE *p; {
140616179Sralph 
140716179Sralph 	register struct symtab *q;
140816179Sralph 	register ty;
140916179Sralph 
141016179Sralph # ifdef MYPRTREE
141116179Sralph 	MYPRTREE(p);  /* local action can be taken here; then return... */
141216179Sralph #endif
141316179Sralph 
141416179Sralph 	ty = optype(p->in.op);
141516179Sralph 
141616179Sralph 	printf( "%d\t", p->in.op );
141716179Sralph 
141816179Sralph 	if( ty == LTYPE ) {
141916179Sralph 		printf( CONFMT, p->tn.lval );
142016179Sralph 		printf( "\t" );
142116179Sralph 		}
142216179Sralph 	if( ty != BITYPE ) {
142316179Sralph 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
142416179Sralph 		else printf( "%d\t", p->tn.rval );
142516179Sralph 		}
142616179Sralph 
142716179Sralph 	printf( "%o\t", p->in.type );
142816179Sralph 
142916179Sralph 	/* handle special cases */
143016179Sralph 
143116179Sralph 	switch( p->in.op ){
143216179Sralph 
143316179Sralph 	case NAME:
143416179Sralph 	case ICON:
143516179Sralph 		/* print external name */
143616179Sralph 		if( p->tn.rval == NONAME ) printf( "\n" );
143716179Sralph 		else if( p->tn.rval >= 0 ){
143816179Sralph 			q = &stab[p->tn.rval];
143916179Sralph 			printf(  "%s\n", exname(q->sname) );
144016179Sralph 			}
144116179Sralph 		else { /* label */
144216179Sralph 			printf( LABFMT, -p->tn.rval );
144316179Sralph 			}
144416179Sralph 		break;
144516179Sralph 
144616179Sralph 	case STARG:
144716179Sralph 	case STASG:
144816179Sralph 	case STCALL:
144916179Sralph 	case UNARY STCALL:
145016179Sralph 		/* print out size */
145116179Sralph 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
145216179Sralph 
145316179Sralph 		/* note: p->in.left not a field... */
145416179Sralph 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
145516179Sralph 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
145616179Sralph 		break;
145716179Sralph 
145816179Sralph 	default:
145916179Sralph 		printf(  "\n" );
146016179Sralph 		}
146116179Sralph 
146216179Sralph 	if( ty != LTYPE ) prtree( p->in.left );
146316179Sralph 	if( ty == BITYPE ) prtree( p->in.right );
146416179Sralph 
146516179Sralph 	}
146616179Sralph 
146716179Sralph # else
146816179Sralph 
146916179Sralph p2tree(p) register NODE *p; {
147016179Sralph 	register ty;
147116179Sralph 
147216179Sralph # ifdef MYP2TREE
147316179Sralph 	MYP2TREE(p);  /* local action can be taken here; then return... */
147416179Sralph # endif
147516179Sralph 
147616179Sralph 	ty = optype(p->in.op);
147716179Sralph 
147816179Sralph 	switch( p->in.op ){
147916179Sralph 
148016179Sralph 	case NAME:
148116179Sralph 	case ICON:
148216179Sralph #ifndef FLEXNAMES
148316179Sralph 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
148416179Sralph #else
148516179Sralph 		if( p->tn.rval == NONAME ) p->in.name = "";
148616179Sralph #endif
148716179Sralph 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
148816179Sralph 			register char *cp;
148916179Sralph 			register i;
149016179Sralph 			cp = exname( stab[p->tn.rval].sname );
149116179Sralph #ifndef FLEXNAMES
149216179Sralph 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
149316179Sralph #else
149416179Sralph 			p->in.name = tstr(cp);
149516179Sralph #endif
149616179Sralph 			}
149716179Sralph #ifndef FLEXNAMES
149816179Sralph 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
149916179Sralph #else
150016179Sralph 		else {
150116179Sralph 			char temp[32];
150216179Sralph 			sprintf( temp, LABFMT, -p->tn.rval );
150316179Sralph 			p->in.name = tstr(temp);
150416179Sralph 		}
150516179Sralph #endif
150616179Sralph 		break;
150716179Sralph 
150816179Sralph 	case STARG:
150916179Sralph 	case STASG:
151016179Sralph 	case STCALL:
151116179Sralph 	case UNARY STCALL:
151216179Sralph 		/* set up size parameters */
151316179Sralph 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
151416179Sralph 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
151516179Sralph 		break;
151616179Sralph 
151716179Sralph 	case REG:
151816179Sralph 		rbusy( p->tn.rval, p->in.type );
151916179Sralph 	default:
152016179Sralph #ifndef FLEXNAMES
152116179Sralph 		p->in.name[0] = '\0';
152216179Sralph #else
152316179Sralph 		p->in.name = "";
152416179Sralph #endif
152516179Sralph 		}
152616179Sralph 
152716179Sralph 	p->in.rall = NOPREF;
152816179Sralph 
152916179Sralph 	if( ty != LTYPE ) p2tree( p->in.left );
153016179Sralph 	if( ty == BITYPE ) p2tree( p->in.right );
153116179Sralph 	}
153216179Sralph 
153316179Sralph # endif
153416179Sralph # endif
1535