xref: /csrg-svn/old/pcc/mip/trees.c (revision 32859)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.34 (Berkeley) 12/10/87";
3 #endif
4 
5 # include "pass1.h"
6 
7 # include <setjmp.h>
8 
9 int bdebug = 0;
10 int adebug = 0;
11 extern ddebug;
12 extern eprint();
13 
14 	    /* corrections when in violation of lint */
15 
16 /*	some special actions, used in finding the type of nodes */
17 # define NCVT 01
18 # define PUN 02
19 # define TYPL 04
20 # define TYPR 010
21 # define TYMATCH 040
22 # define LVAL 0100
23 # define CVTO 0200
24 # define CVTL 0400
25 # define CVTR 01000
26 # define PTMATCH 02000
27 # define OTHER 04000
28 # define NCVTR 010000
29 
30 #ifndef BUG1
31 printact(t, acts)
32 	NODE *t;
33 	int acts;
34 {
35 	static struct actions {
36 		int	a_bit;
37 		char	*a_name;
38 	} actions[] = {
39 		{ PUN,		"PUN" },
40 		{ CVTL,		"CVTL" },
41 		{ CVTR,		"CVTR" },
42 		{ TYPL,		"TYPL" },
43 		{ TYPR,		"TYPR" },
44 		{ TYMATCH,	"TYMATCH" },
45 		{ PTMATCH,	"PTMATCH" },
46 		{ LVAL,		"LVAL" },
47 		{ CVTO,		"CVTO" },
48 		{ NCVT,		"NCVT" },
49 		{ OTHER,	"OTHER" },
50 		{ NCVTR,	"NCVTR" },
51 		{ 0 }
52 	};
53 	register struct actions *p;
54 	char *sep = " ";
55 
56 	printf("actions");
57 	for (p = actions; p->a_name; p++)
58 		if (p->a_bit & acts) {
59 			printf("%s%s", sep, p->a_name);
60 			sep = "|";
61 		}
62 	if (!bdebug) {
63 		printf(" for:\n");
64 		fwalk(t, eprint, 0);
65 	} else
66 		putchar('\n');
67 }
68 #endif
69 
70 /* node conventions:
71 
72 	NAME:	rval>0 is stab index for external
73 		rval<0 is -inlabel number
74 		lval is offset in bits
75 	ICON:	lval has the value
76 		rval has the STAB index, or - label number,
77 			if a name whose address is in the constant
78 		rval = NONAME means no name
79 	REG:	rval is reg. identification cookie
80 
81 	*/
82 
83 NODE *
84 buildtree( o, l, r ) register NODE *l, *r; {
85 	register NODE *p, *q;
86 	register actions;
87 	register opty;
88 	register struct symtab *sp;
89 	register NODE *lr, *ll;
90 	NODE *fixargs();
91 	int i;
92 
93 # ifndef BUG1
94 	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
95 # endif
96 	opty = optype(o);
97 
98 	/* check for constants */
99 
100 	if( opty == UTYPE && l->in.op == ICON ){
101 
102 		switch( o ){
103 
104 		case NOT:
105 			if( hflag ) werror( "constant argument to NOT" );
106 		case UNARY MINUS:
107 		case COMPL:
108 			if( conval( l, o, l ) ) return(l);
109 			break;
110 
111 			}
112 		}
113 
114 	else if( o==UNARY MINUS && l->in.op==FCON ){
115 		l->fpn.fval = -l->fpn.fval;
116 		return(l);
117 		}
118 
119 	else if( o==UNARY MINUS && l->in.op==DCON ){
120 		l->dpn.dval = -l->dpn.dval;
121 		return(l);
122 		}
123 
124 	else if( o==QUEST && l->in.op==ICON ) {
125 		l->in.op = FREE;
126 		r->in.op = FREE;
127 		if( l->tn.lval ){
128 			tfree( r->in.right );
129 			return( r->in.left );
130 			}
131 		else {
132 			tfree( r->in.left );
133 			return( r->in.right );
134 			}
135 		}
136 
137 	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
138 
139 	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
140 
141 		switch( o ){
142 
143 		case ULT:
144 		case UGT:
145 		case ULE:
146 		case UGE:
147 		case LT:
148 		case GT:
149 		case LE:
150 		case GE:
151 		case EQ:
152 		case NE:
153 			if( l->in.type == ENUMTY && r->in.type == ENUMTY ){
154 				p = block( o, l, r, INT, 0, INT );
155 				chkpun( p );
156 				p->in.op = FREE;
157 				}
158 
159 		case ANDAND:
160 		case OROR:
161 		case CBRANCH:
162 
163 		ccwarn:
164 			if( hflag ) werror( "constant in conditional context" );
165 
166 		case PLUS:
167 		case MINUS:
168 		case MUL:
169 		case DIV:
170 		case MOD:
171 		case AND:
172 		case OR:
173 		case ER:
174 		case LS:
175 		case RS:
176 			if( conval( l, o, r ) ) {
177 				r->in.op = FREE;
178 				return(l);
179 				}
180 			break;
181 			}
182 		}
183 	else if (opty == BITYPE &&
184 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
185 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
186 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
187 				extern int fpe_count;
188 				extern jmp_buf gotfpe;
189 
190 				fpe_count = 0;
191 				if (setjmp(gotfpe))
192 					goto treatfpe;
193 				if (l->in.op == ICON)
194 					l->dpn.dval = l->tn.lval;
195 				else if (l->in.op == FCON)
196 					l->dpn.dval = l->fpn.fval;
197 				if (r->in.op == ICON)
198 					r->dpn.dval = r->tn.lval;
199 				else if (r->in.op == FCON)
200 					r->dpn.dval = r->fpn.fval;
201 				switch (o) {
202 
203 				case PLUS:
204 					l->dpn.dval += r->dpn.dval;
205 					break;
206 
207 				case MINUS:
208 					l->dpn.dval -= r->dpn.dval;
209 					break;
210 
211 				case MUL:
212 					l->dpn.dval *= r->dpn.dval;
213 					break;
214 
215 				case DIV:
216 					if (r->dpn.dval == 0)
217 						uerror("division by 0.");
218 					else
219 						l->dpn.dval /= r->dpn.dval;
220 					break;
221 					}
222 			treatfpe:
223 				if (fpe_count > 0) {
224 					uerror("floating point exception in constant expression");
225 					l->dpn.dval = 1.0; /* Fairly harmless */
226 					}
227 				fpe_count = -1;
228 				l->in.op = DCON;
229 				l->in.type = l->fn.csiz = DOUBLE;
230 				r->in.op = FREE;
231 				return (l);
232 			}
233 		}
234 
235 	/* it's real; we must make a new node */
236 
237 	p = block( o, l, r, INT, 0, INT );
238 
239 	actions = opact(p);
240 #ifndef	BUG1
241 	if (adebug)
242 		printact(p, actions);
243 #endif
244 
245 	if( actions&LVAL ){ /* check left descendent */
246 		if( notlval(p->in.left) ) {
247 			uerror( "illegal lvalue operand of assignment operator" );
248 			}
249 		}
250 
251 	if( actions & NCVTR ){
252 		p->in.left = pconvert( p->in.left );
253 		}
254 	else if( !(actions & NCVT ) ){
255 		switch( opty ){
256 
257 		case BITYPE:
258 			p->in.right = pconvert( p->in.right );
259 		case UTYPE:
260 			p->in.left = pconvert( p->in.left );
261 
262 			}
263 		}
264 
265 	if( (actions&PUN) && (o!=CAST||cflag) ){
266 		chkpun(p);
267 		}
268 
269 	if( actions & (TYPL|TYPR) ){
270 
271 		q = (actions&TYPL) ? p->in.left : p->in.right;
272 
273 		p->in.type = q->in.type;
274 		p->fn.cdim = q->fn.cdim;
275 		p->fn.csiz = q->fn.csiz;
276 		}
277 
278 	if( actions & CVTL ) p = convert( p, CVTL );
279 	if( actions & CVTR ) p = convert( p, CVTR );
280 	if( actions & TYMATCH ) p = tymatch(p);
281 	if( actions & PTMATCH ) p = ptmatch(p);
282 
283 	if( actions & OTHER ){
284 		l = p->in.left;
285 		r = p->in.right;
286 
287 		switch(o){
288 
289 		case NAME:
290 			sp = &stab[idname];
291 			if( sp->stype == UNDEF ){
292 #ifndef FLEXNAMES
293 				uerror( "%.8s undefined", sp->sname );
294 #else
295 				uerror( "%s undefined", sp->sname );
296 #endif
297 				/* make p look reasonable */
298 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
299 				p->tn.rval = idname;
300 				p->tn.lval = 0;
301 				defid( p, SNULL );
302 				break;
303 				}
304 			p->in.type = sp->stype;
305 			p->fn.cdim = sp->dimoff;
306 			p->fn.csiz = sp->sizoff;
307 			p->tn.lval = 0;
308 			p->tn.rval = idname;
309 			/* special case: MOETY is really an ICON... */
310 			if( p->in.type == MOETY ){
311 				p->tn.rval = NONAME;
312 				p->tn.lval = sp->offset;
313 				p->fn.cdim = 0;
314 				p->in.type = ENUMTY;
315 				p->in.op = ICON;
316 				}
317 			break;
318 
319 		case ICON:
320 			p->in.type = INT;
321 			p->fn.cdim = 0;
322 			p->fn.csiz = INT;
323 			break;
324 
325 		case STRING:
326 			p->in.op = NAME;
327 			p->in.type = CHAR+ARY;
328 			p->tn.lval = 0;
329 			p->tn.rval = NOLAB;
330 			p->fn.cdim = curdim;
331 			p->fn.csiz = CHAR;
332 			break;
333 
334 		case FCON:
335 			p->tn.lval = 0;
336 			p->tn.rval = 0;
337 			p->in.type = FLOAT;
338 			p->fn.cdim = 0;
339 			p->fn.csiz = FLOAT;
340 			break;
341 
342 		case DCON:
343 			p->tn.lval = 0;
344 			p->tn.rval = 0;
345 			p->in.type = DOUBLE;
346 			p->fn.cdim = 0;
347 			p->fn.csiz = DOUBLE;
348 			break;
349 
350 		case STREF:
351 			/* p->x turned into *(p+offset) */
352 			/* rhs must be a name; check correctness */
353 
354 			i = r->tn.rval;
355 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
356 				uerror( "member of structure or union required" );
357 				}else
358 			/* if this name is non-unique, find right one */
359 			if( stab[i].sflags & SNONUNIQ &&
360 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
361 				(l->fn.csiz +1) >= 0 ){
362 				/* nonunique name && structure defined */
363 				char * memnam, * tabnam;
364 				int j;
365 				int memi;
366 				j=dimtab[l->fn.csiz+1];
367 				for( ; (memi=dimtab[j]) >= 0; ++j ){
368 					tabnam = stab[memi].sname;
369 					memnam = stab[i].sname;
370 # ifndef BUG1
371 					if( ddebug>1 ){
372 #ifndef FLEXNAMES
373 						printf("member %.8s==%.8s?\n",
374 #else
375 						printf("member %s==%s?\n",
376 #endif
377 							memnam, tabnam);
378 						}
379 # endif
380 					if( stab[memi].sflags & SNONUNIQ ){
381 #ifndef FLEXNAMES
382 						register k;
383 						for( k=0; k<NCHNAM; ++k ){
384 							if(*memnam++!=*tabnam)
385 								goto next;
386 							if(!*tabnam++) break;
387 							}
388 #else
389 						if (memnam != tabnam)
390 							goto next;
391 #endif
392 						r->tn.rval = i = memi;
393 						break;
394 						}
395 					next: continue;
396 					}
397 				if( memi < 0 )
398 #ifndef FLEXNAMES
399 					uerror("illegal member use: %.8s",
400 #else
401 					uerror("illegal member use: %s",
402 #endif
403 						stab[i].sname);
404 				}
405 			else {
406 				register j;
407 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
408 					if( stab[i].sflags & SNONUNIQ ){
409 						uerror( "nonunique name demands struct/union or struct/union pointer" );
410 						}
411 					else werror( "struct/union or struct/union pointer required" );
412 					}
413 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
414 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
415 #ifndef FLEXNAMES
416 					werror( "illegal member use: %.8s", stab[i].sname );
417 #else
418 					werror( "illegal member use: %s", stab[i].sname );
419 #endif
420 					}
421 				}
422 
423 			p = stref( p );
424 			break;
425 
426 		case UNARY MUL:
427 			if( l->in.op == UNARY AND ){
428 				p->in.op = l->in.op = FREE;
429 				p = l->in.left;
430 				}
431 			if( !ISPTR(l->in.type))uerror("illegal indirection");
432 			p->in.type = DECREF(l->in.type);
433 			p->fn.cdim = l->fn.cdim;
434 			p->fn.csiz = l->fn.csiz;
435 			break;
436 
437 		case UNARY AND:
438 			switch( l->in.op ){
439 
440 			case UNARY MUL:
441 				p->in.op = l->in.op = FREE;
442 				p = l->in.left;
443 			case NAME:
444 				p->in.type = INCREF( l->in.type );
445 				p->fn.cdim = l->fn.cdim;
446 				p->fn.csiz = l->fn.csiz;
447 				break;
448 
449 			case COMOP:
450 				lr = buildtree( UNARY AND, l->in.right, NIL );
451 				p->in.op = l->in.op = FREE;
452 				p = buildtree( COMOP, l->in.left, lr );
453 				break;
454 
455 			case QUEST:
456 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
457 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
458 				p->in.op = l->in.op = l->in.right->in.op = FREE;
459 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
460 				break;
461 
462 # ifdef ADDROREG
463 			case OREG:
464 				/* OREG was built in clocal()
465 				 * for an auto or formal parameter
466 				 * now its address is being taken
467 				 * local code must unwind it
468 				 * back to PLUS/MINUS REG ICON
469 				 * according to local conventions
470 				 */
471 				{
472 				extern NODE * addroreg();
473 				p->in.op = FREE;
474 				p = addroreg( l );
475 				}
476 				break;
477 
478 # endif
479 			default:
480 				uerror( "unacceptable operand of &" );
481 				break;
482 				}
483 			break;
484 
485 		case LS:
486 		case RS:
487 		case ASG LS:
488 		case ASG RS:
489 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
490 				p->in.right = makety(p->in.right, INT, 0, INT );
491 			break;
492 
493 		case RETURN:
494 		case ASSIGN:
495 		case CAST:
496 			/* structure assignment */
497 			/* take the addresses of the two sides; then make an
498 			/* operator using STASG and
499 			/* the addresses of left and right */
500 
501 			{
502 				register TWORD t;
503 				register d, s;
504 
505 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
506 
507 				r = buildtree( UNARY AND, r, NIL );
508 				t = r->in.type;
509 				d = r->fn.cdim;
510 				s = r->fn.csiz;
511 
512 				l = block( STASG, l, r, t, d, s );
513 
514 				if( o == RETURN ){
515 					p->in.op = FREE;
516 					p = l;
517 					break;
518 					}
519 
520 				p->in.op = UNARY MUL;
521 				p->in.left = l;
522 				p->in.right = NIL;
523 				break;
524 				}
525 		case COLON:
526 			/* structure colon */
527 
528 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
529 			break;
530 
531 		case CALL:
532 			p->in.right = r = fixargs( p->in.right );
533 		case UNARY CALL:
534 			if( !ISPTR(l->in.type)) uerror("illegal function");
535 			p->in.type = DECREF(l->in.type);
536 			if( !ISFTN(p->in.type)) uerror("illegal function");
537 			p->in.type = DECREF( p->in.type );
538 			p->fn.cdim = l->fn.cdim;
539 			p->fn.csiz = l->fn.csiz;
540 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
541 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
542 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
543 				p->in.op += (FORTCALL-CALL);
544 				}
545 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
546 				/* function returning structure */
547 				/*  make function really return ptr to str., with * */
548 
549 				p->in.op += STCALL-CALL;
550 				p->in.type = INCREF( p->in.type );
551 				p = buildtree( UNARY MUL, p, NIL );
552 
553 				}
554 			break;
555 
556 		default:
557 			cerror( "other code %d", o );
558 			}
559 
560 		}
561 
562 	if( actions & CVTO ) p = oconvert(p);
563 	p = clocal(p);
564 
565 # ifndef BUG1
566 	if( bdebug ) fwalk( p, eprint, 0 );
567 # endif
568 
569 	return(p);
570 
571 	}
572 
573 int fpe_count = -1;
574 jmp_buf gotfpe;
575 
576 fpe() {
577 	if (fpe_count < 0)
578 		cerror("floating point exception");
579 	++fpe_count;
580 	longjmp(gotfpe, 1);
581 	}
582 
583 /*
584  * Rewrite arguments in a function call.
585  * Structure arguments are massaged, single
586  * precision floating point constants are
587  * cast to double (to eliminate convert code).
588  */
589 NODE *
590 fixargs( p ) register NODE *p;  {
591 	int o = p->in.op;
592 
593 	if( o == CM ){
594 		p->in.left = fixargs( p->in.left );
595 		p->in.right = fixargs( p->in.right );
596 		return( p );
597 		}
598 
599 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
600 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
601 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
602 		p = clocal(p);
603 		}
604 	else if( o == FCON )
605 		p = makety(p, DOUBLE, 0, 0);
606 	return( p );
607 	}
608 
609 chkstr( i, j, type ) TWORD type; {
610 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
611 	/* i has been checked to contain a MOS or MOU */
612 	/* j is the index in dimtab of the members... */
613 	int k, kk;
614 
615 	extern int ddebug;
616 
617 # ifndef BUG1
618 #ifndef FLEXNAMES
619 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
620 #else
621 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
622 #endif
623 # endif
624 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
625 	else {
626 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
627 			if( kk >= SYMTSZ ){
628 				cerror( "gummy structure" );
629 				return(1);
630 				}
631 			if( kk == i ) return( 1 );
632 			switch( stab[kk].stype ){
633 
634 			case STRTY:
635 			case UNIONTY:
636 				if( type == STRTY ) continue;  /* no recursive looking for strs */
637 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
638 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
639 					werror(
640 #ifndef FLEXNAMES
641 					"illegal member use: perhaps %.8s.%.8s?",
642 #else
643 					"illegal member use: perhaps %s.%s?",
644 #endif
645 					stab[kk].sname, stab[i].sname );
646 					return(1);
647 					}
648 				}
649 			}
650 		}
651 	return( 0 );
652 	}
653 
654 conval( p, o, q ) register NODE *p, *q; {
655 	/* apply the op o to the lval part of p; if binary, rhs is val */
656 	/* works only on integer constants */
657 	NODE *r;
658 	int i, u;
659 	CONSZ val;
660 	TWORD utype;
661 
662 	val = q->tn.lval;
663 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
664 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
665 
666 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
667 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
668 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
669 
670 	/* usual type conversions -- handle casts of constants */
671 #define	ISLONG(t)	((t) == LONG || (t) == ULONG)
672 	if (ISLONG(p->in.type) || ISLONG(q->in.type))
673 		utype = u ? ULONG : LONG;
674 	else
675 		utype = u ? UNSIGNED : INT;
676 	if( !ISPTR(p->in.type) && p->in.type != utype )
677 		p = makety(p, utype, 0, (int)utype);
678 	if( q->in.type != utype )
679 		q = makety(q, utype, 0, (int)utype);
680 
681 	switch( o ){
682 
683 	case PLUS:
684 		p->tn.lval += val;
685 		if( p->tn.rval == NONAME ){
686 			p->tn.rval = q->tn.rval;
687 			p->in.type = q->in.type;
688 			}
689 		break;
690 	case MINUS:
691 		p->tn.lval -= val;
692 		break;
693 	case MUL:
694 		p->tn.lval *= val;
695 		break;
696 	case DIV:
697 		if( val == 0 ) uerror( "division by 0" );
698 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
699 		else p->tn.lval /= val;
700 		break;
701 	case MOD:
702 		if( val == 0 ) uerror( "division by 0" );
703 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
704 		else p->tn.lval %= val;
705 		break;
706 	case AND:
707 		p->tn.lval &= val;
708 		break;
709 	case OR:
710 		p->tn.lval |= val;
711 		break;
712 	case ER:
713 		p->tn.lval ^= val;
714 		break;
715 	case LS:
716 		i = val;
717 		p->tn.lval = p->tn.lval << i;
718 		break;
719 	case RS:
720 		i = val;
721 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
722 		else p->tn.lval = p->tn.lval >> i;
723 		break;
724 
725 	case UNARY MINUS:
726 		p->tn.lval = - p->tn.lval;
727 		break;
728 	case COMPL:
729 		p->tn.lval = ~p->tn.lval;
730 		break;
731 	case NOT:
732 		p->tn.lval = !p->tn.lval;
733 		break;
734 	case LT:
735 		p->tn.lval = p->tn.lval < val;
736 		break;
737 	case LE:
738 		p->tn.lval = p->tn.lval <= val;
739 		break;
740 	case GT:
741 		p->tn.lval = p->tn.lval > val;
742 		break;
743 	case GE:
744 		p->tn.lval = p->tn.lval >= val;
745 		break;
746 	case ULT:
747 		p->tn.lval = p->tn.lval < (unsigned) val;
748 		break;
749 	case ULE:
750 		p->tn.lval = p->tn.lval <= (unsigned) val;
751 		break;
752 	case UGT:
753 		p->tn.lval = p->tn.lval > (unsigned) val;
754 		break;
755 	case UGE:
756 		p->tn.lval = p->tn.lval >= (unsigned) val;
757 		break;
758 	case EQ:
759 		p->tn.lval = p->tn.lval == val;
760 		break;
761 	case NE:
762 		p->tn.lval = p->tn.lval != val;
763 		break;
764 	default:
765 		return(0);
766 		}
767 	return(1);
768 	}
769 
770 chkpun(p) register NODE *p; {
771 
772 	/* checks p for the existance of a pun */
773 
774 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
775 
776 	/* one case is when enumerations are used: this applies only to lint */
777 	/* in the other case, one operand is a pointer, the other integer type */
778 	/* we check that this integer is in fact a constant zero... */
779 
780 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
781 	/* this falls out, because the LHS is never 0 */
782 
783 	register NODE *q;
784 	register t1, t2;
785 	register d1, d2;
786 	int ref1, ref2;
787 
788 	t1 = p->in.left->in.type;
789 	t2 = p->in.right->in.type;
790 
791 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
792 		/* rob pike says this is obnoxious...
793 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
794 			werror( "comparison of enums" ); */
795 		if( t1==ENUMTY && t2==ENUMTY ) {
796 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
797 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
798 			return;
799 			}
800 		if ( t1 == ENUMTY ) t1 = INT;
801 		if ( t2 == ENUMTY ) t2 = INT;
802 		}
803 
804 	ref1 = ISPTR(t1) || ISARY(t1);
805 	ref2 = ISPTR(t2) || ISARY(t2);
806 
807 	if( ref1 ^ ref2 ){
808 		if( ref1 ) q = p->in.right;
809 		else q = p->in.left;
810 		if( q->in.op != ICON || q->tn.lval != 0 ){
811 			werror( "illegal combination of pointer and integer, op %s",
812 				opst[p->in.op] );
813 			}
814 		}
815 	else if( ref1 ){
816 		if( t1 == t2 ) {
817 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
818 				werror( "illegal structure pointer combination" );
819 				return;
820 				}
821 			d1 = p->in.left->fn.cdim;
822 			d2 = p->in.right->fn.cdim;
823 			for( ;; ){
824 				if( ISARY(t1) ){
825 					if( dimtab[d1] != dimtab[d2] ){
826 						werror( "illegal array size combination" );
827 						return;
828 						}
829 					++d1;
830 					++d2;
831 					}
832 				else if( !ISPTR(t1) ) break;
833 				t1 = DECREF(t1);
834 				}
835 			}
836 		else
837 			werror( "illegal pointer combination" );
838 		}
839 
840 	}
841 
842 NODE *
843 stref( p ) register NODE *p; {
844 
845 	TWORD t;
846 	int d, s, dsc, align;
847 	OFFSZ off;
848 	register struct symtab *q;
849 
850 	/* make p->x */
851 	/* this is also used to reference automatic variables */
852 
853 	q = &stab[p->in.right->tn.rval];
854 	p->in.right->in.op = FREE;
855 	p->in.op = FREE;
856 	p = pconvert( p->in.left );
857 
858 	/* make p look like ptr to x */
859 
860 	if( !ISPTR(p->in.type)){
861 		p->in.type = PTR+UNIONTY;
862 		}
863 
864 	t = INCREF( q->stype );
865 	d = q->dimoff;
866 	s = q->sizoff;
867 
868 	p = makety( p, t, d, s );
869 
870 	/* compute the offset to be added */
871 
872 	off = q->offset;
873 	dsc = q->sclass;
874 
875 	if( dsc & FIELD ) {  /* normalize offset */
876 		align = ALINT;
877 		s = INT;
878 		off = (off/align)*align;
879 		}
880 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
881 
882 	p = buildtree( UNARY MUL, p, NIL );
883 
884 	/* if field, build field info */
885 
886 	if( dsc & FIELD ){
887 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
888 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
889 		}
890 
891 	return( clocal(p) );
892 	}
893 
894 notlval(p) register NODE *p; {
895 
896 	/* return 0 if p an lvalue, 1 otherwise */
897 
898 	again:
899 
900 	switch( p->in.op ){
901 
902 	case FLD:
903 		p = p->in.left;
904 		goto again;
905 
906 	case UNARY MUL:
907 		/* fix the &(a=b) bug, given that a and b are structures */
908 		if( p->in.left->in.op == STASG ) return( 1 );
909 		/* and the f().a bug, given that f returns a structure */
910 		if( p->in.left->in.op == UNARY STCALL ||
911 		    p->in.left->in.op == STCALL ) return( 1 );
912 	case NAME:
913 	case OREG:
914 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
915 	case REG:
916 		return(0);
917 
918 	default:
919 		return(1);
920 
921 		}
922 
923 	}
924 
925 NODE *
926 bcon( i ){ /* make a constant node with value i */
927 	register NODE *p;
928 
929 	p = block( ICON, NIL, NIL, INT, 0, INT );
930 	p->tn.lval = i;
931 	p->tn.rval = NONAME;
932 	return( clocal(p) );
933 	}
934 
935 NODE *
936 bpsize(p) register NODE *p; {
937 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
938 	}
939 
940 OFFSZ
941 psize( p ) NODE *p; {
942 	/* p is a node of type pointer; psize returns the
943 	   size of the thing pointed to */
944 
945 	if( !ISPTR(p->in.type) ){
946 		uerror( "pointer required");
947 		return( SZINT );
948 		}
949 	/* note: no pointers to fields */
950 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
951 	}
952 
953 NODE *
954 convert( p, f )  register NODE *p; {
955 	/*  convert an operand of p
956 	    f is either CVTL or CVTR
957 	    operand has type int, and is converted by the size of the other side
958 	    */
959 
960 	register NODE *q, *r;
961 
962 	q = (f==CVTL)?p->in.left:p->in.right;
963 
964 	r = block( PMCONV,
965 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
966 	r = clocal(r);
967 	if( f == CVTL )
968 		p->in.left = r;
969 	else
970 		p->in.right = r;
971 	return(p);
972 
973 	}
974 
975 #ifndef econvert
976 econvert( p ) register NODE *p; {
977 
978 	/* change enums to ints, or appropriate types */
979 
980 	register TWORD ty;
981 
982 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
983 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
984 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
985 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
986 		else ty = LONG;
987 		ty = ctype( ty );
988 		p->fn.csiz = ty;
989 		MODTYPE(p->in.type,ty);
990 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
991 		}
992 	}
993 #endif
994 
995 NODE *
996 pconvert( p ) register NODE *p; {
997 
998 	/* if p should be changed into a pointer, do so */
999 
1000 	if( ISARY( p->in.type) ){
1001 		p->in.type = DECREF( p->in.type );
1002 		++p->fn.cdim;
1003 		return( buildtree( UNARY AND, p, NIL ) );
1004 		}
1005 	if( ISFTN( p->in.type) )
1006 		return( buildtree( UNARY AND, p, NIL ) );
1007 
1008 	return( p );
1009 	}
1010 
1011 NODE *
1012 oconvert(p) register NODE *p; {
1013 	/* convert the result itself: used for pointer and unsigned */
1014 
1015 	switch(p->in.op) {
1016 
1017 	case LE:
1018 	case LT:
1019 	case GE:
1020 	case GT:
1021 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
1022 	case EQ:
1023 	case NE:
1024 		return( p );
1025 
1026 	case MINUS:
1027 		return(  clocal( block( PVCONV,
1028 			p, bpsize(p->in.left), INT, 0, INT ) ) );
1029 		}
1030 
1031 	cerror( "illegal oconvert: %d", p->in.op );
1032 
1033 	return(p);
1034 	}
1035 
1036 NODE *
1037 ptmatch(p)  register NODE *p; {
1038 
1039 	/* makes the operands of p agree; they are
1040 	   either pointers or integers, by this time */
1041 	/* with MINUS, the sizes must be the same */
1042 	/* with COLON, the types must be the same */
1043 
1044 	TWORD t1, t2, t;
1045 	int o, d2, d, s2, s;
1046 
1047 	o = p->in.op;
1048 	t = t1 = p->in.left->in.type;
1049 	t2 = p->in.right->in.type;
1050 	d = p->in.left->fn.cdim;
1051 	d2 = p->in.right->fn.cdim;
1052 	s = p->in.left->fn.csiz;
1053 	s2 = p->in.right->fn.csiz;
1054 
1055 	switch( o ){
1056 
1057 	case ASSIGN:
1058 	case RETURN:
1059 	case CAST:
1060 		{  break; }
1061 
1062 	case MINUS:
1063 		{  if( psize(p->in.left) != psize(p->in.right) ){
1064 			uerror( "illegal pointer subtraction");
1065 			}
1066 		   break;
1067 		   }
1068 	case COLON:
1069 		{  if( t1 != t2 ) uerror( "illegal types in :");
1070 		   break;
1071 		   }
1072 	default:  /* must work harder: relationals or comparisons */
1073 
1074 		if( !ISPTR(t1) ){
1075 			t = t2;
1076 			d = d2;
1077 			s = s2;
1078 			break;
1079 			}
1080 		if( !ISPTR(t2) ){
1081 			break;
1082 			}
1083 
1084 		/* both are pointers */
1085 		if( talign(t2,s2) < talign(t,s) ){
1086 			t = t2;
1087 			s = s2;
1088 			}
1089 		break;
1090 		}
1091 
1092 	p->in.left = makety( p->in.left, t, d, s );
1093 	p->in.right = makety( p->in.right, t, d, s );
1094 	if( o!=MINUS && !logop(o) ){
1095 
1096 		p->in.type = t;
1097 		p->fn.cdim = d;
1098 		p->fn.csiz = s;
1099 		}
1100 
1101 	return(clocal(p));
1102 	}
1103 
1104 int tdebug = 0;
1105 
1106 NODE *
1107 tymatch(p)  register NODE *p; {
1108 
1109 	/* satisfy the types of various arithmetic binary ops */
1110 
1111 	/* rules are:
1112 		if assignment, type of LHS
1113 		if any float or doubles, make double
1114 		if any longs, make long
1115 		otherwise, make int
1116 		if either operand is unsigned, the result is...
1117 	*/
1118 
1119 	register TWORD t1, t2, t, tu;
1120 	register o, u;
1121 
1122 	o = p->in.op;
1123 
1124 	t1 = p->in.left->in.type;
1125 	t2 = p->in.right->in.type;
1126 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
1127 		uerror("void type illegal in expression");
1128 
1129 	u = 0;
1130 	if( ISUNSIGNED(t1) ){
1131 		u = 1;
1132 		t1 = DEUNSIGN(t1);
1133 		}
1134 	if( ISUNSIGNED(t2) ){
1135 		u = 1;
1136 		t2 = DEUNSIGN(t2);
1137 		}
1138 
1139 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1140 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1141 
1142 #ifdef SPRECC
1143 	if( t1 == DOUBLE || t2 == DOUBLE )
1144 		t = DOUBLE;
1145 	else if( t1 == FLOAT || t2 == FLOAT )
1146 		t = FLOAT;
1147 #else
1148 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
1149 		t = DOUBLE;
1150 #endif
1151 	else if( t1==LONG || t2==LONG ) t = LONG;
1152 	else t = INT;
1153 
1154 	if( o == ASSIGN || o == CAST || o == RETURN )
1155 	{
1156 		tu = p->in.left->in.type;
1157 		t = t1;
1158 		}
1159 	else {
1160 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1161 		}
1162 
1163 	/* because expressions have values that are at least as wide
1164 	   as INT or UNSIGNED, the only conversions needed
1165 	   are those involving FLOAT/DOUBLE, and those
1166 	   from LONG to INT and ULONG to UNSIGNED */
1167 
1168 	if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
1169 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
1170 
1171 	if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
1172 		if ( tu == ENUMTY ) {/* always asgop */
1173 			p->in.right = makety( p->in.right, INT, 0, INT );
1174 			p->in.right->in.type = tu;
1175 			p->in.right->fn.cdim = p->in.left->fn.cdim;
1176 			p->in.right->fn.csiz = p->in.left->fn.csiz;
1177 			}
1178 		else
1179 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
1180 
1181 	if( asgop(o) ){
1182 		p->in.type = p->in.left->in.type;
1183 		p->fn.cdim = p->in.left->fn.cdim;
1184 		p->fn.csiz = p->in.left->fn.csiz;
1185 		}
1186 	else if( !logop(o) ){
1187 		p->in.type = tu;
1188 		p->fn.cdim = 0;
1189 		p->fn.csiz = t;
1190 		}
1191 
1192 # ifndef BUG1
1193 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1194 # endif
1195 
1196 	return(p);
1197 	}
1198 
1199 NODE *
1200 makety( p, t, d, s ) register NODE *p; TWORD t; {
1201 	/* make p into type t by inserting a conversion */
1202 
1203 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1204 	if( t == p->in.type ){
1205 		p->fn.cdim = d;
1206 		p->fn.csiz = s;
1207 		return( p );
1208 		}
1209 
1210 	if( t & TMASK ){
1211 		/* non-simple type */
1212 		return( block( PCONV, p, NIL, t, d, s ) );
1213 		}
1214 
1215 	if( p->in.op == ICON ){
1216 		if (t == DOUBLE) {
1217 			p->in.op = DCON;
1218 			if (ISUNSIGNED(p->in.type))
1219 				p->dpn.dval = (unsigned CONSZ) p->tn.lval;
1220 			else
1221 				p->dpn.dval = p->tn.lval;
1222 			p->in.type = p->fn.csiz = t;
1223 			return (clocal(p));
1224 		}
1225 		if (t == FLOAT) {
1226 			p->in.op = FCON;
1227 			if( ISUNSIGNED(p->in.type) ){
1228 				p->fpn.fval = (unsigned CONSZ) p->tn.lval;
1229 				}
1230 			else {
1231 				p->fpn.fval = p->tn.lval;
1232 				}
1233 
1234 			p->in.type = p->fn.csiz = t;
1235 			return( clocal(p) );
1236 			}
1237 		}
1238 	else if (p->in.op == FCON && t == DOUBLE) {
1239 		double db;
1240 
1241 		p->in.op = DCON;
1242 		db = p->fpn.fval;
1243 		p->dpn.dval = db;
1244 		p->in.type = p->fn.csiz = t;
1245 		return (clocal(p));
1246 	} else if (p->in.op == DCON && t == FLOAT) {
1247 		float fl;
1248 
1249 		p->in.op = FCON;
1250 		fl = p->dpn.dval;
1251 #ifdef notdef
1252 		if (fl != p->dpn.dval)
1253 			werror("float conversion loses precision");
1254 #endif
1255 		p->fpn.fval = fl;
1256 		p->in.type = p->fn.csiz = t;
1257 		return (clocal(p));
1258 	}
1259 
1260 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
1261 
1262 	}
1263 
1264 NODE *
1265 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1266 
1267 	register NODE *p;
1268 
1269 	p = talloc();
1270 	p->in.op = o;
1271 	p->in.left = l;
1272 	p->in.right = r;
1273 	p->in.type = t;
1274 	p->fn.cdim = d;
1275 	p->fn.csiz = s;
1276 	return(p);
1277 	}
1278 
1279 icons(p) register NODE *p; {
1280 	/* if p is an integer constant, return its value */
1281 	int val;
1282 
1283 	if( p->in.op != ICON ){
1284 		uerror( "constant expected");
1285 		val = 1;
1286 		}
1287 	else {
1288 		val = p->tn.lval;
1289 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1290 		}
1291 	tfree( p );
1292 	return(val);
1293 	}
1294 
1295 /* 	the intent of this table is to examine the
1296 	operators, and to check them for
1297 	correctness.
1298 
1299 	The table is searched for the op and the
1300 	modified type (where this is one of the
1301 	types INT (includes char and short), LONG,
1302 	DOUBLE (includes FLOAT), and POINTER
1303 
1304 	The default action is to make the node type integer
1305 
1306 	The actions taken include:
1307 		PUN	  check for puns
1308 		CVTL	  convert the left operand
1309 		CVTR	  convert the right operand
1310 		TYPL	  the type is determined by the left operand
1311 		TYPR	  the type is determined by the right operand
1312 		TYMATCH	  force type of left and right to match, by inserting conversions
1313 		PTMATCH	  like TYMATCH, but for pointers
1314 		LVAL	  left operand must be lval
1315 		CVTO	  convert the op
1316 		NCVT	  do not convert the operands
1317 		OTHER	  handled by code
1318 		NCVTR	  convert the left operand, not the right...
1319 
1320 	*/
1321 
1322 # define MINT 01  /* integer */
1323 # define MDBI 02   /* integer or double */
1324 # define MSTR 04  /* structure */
1325 # define MPTR 010  /* pointer */
1326 # define MPTI 020  /* pointer or integer */
1327 # define MENU 040 /* enumeration variable or member */
1328 # define MVOID 0100000 /* void type */
1329 
1330 opact( p )  NODE *p; {
1331 
1332 	register mt12, mt1, mt2, o;
1333 
1334 	mt1 = mt2 = mt12 = 0;
1335 
1336 	switch( optype(o=p->in.op) ){
1337 
1338 	case BITYPE:
1339 		mt2 = moditype( p->in.right->in.type );
1340 	case UTYPE:
1341 		mt1 = moditype( p->in.left->in.type );
1342 		break;
1343 
1344 		}
1345 
1346 	if( ((mt1 | mt2) & MVOID) &&
1347 	    o != COMOP &&
1348 	    o != COLON &&
1349 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
1350 	    !(o == CAST && (mt1 & MVOID)) ){
1351 		/* if lhs of RETURN is void, grammar will complain */
1352 		if( o != RETURN )
1353 			uerror( "value of void expression used" );
1354 		return( NCVT );
1355 		}
1356 	mt12 = mt1 & mt2;
1357 
1358 	switch( o ){
1359 
1360 	case NAME :
1361 	case STRING :
1362 	case ICON :
1363 	case FCON :
1364 	case DCON :
1365 	case CALL :
1366 	case UNARY CALL:
1367 	case UNARY MUL:
1368 		{  return( OTHER ); }
1369 	case UNARY MINUS:
1370 		if( mt1 & MENU ) return( 0 );
1371 		if( mt1 & MDBI ) return( TYPL );
1372 		break;
1373 
1374 	case COMPL:
1375 		if( mt1 & MENU ) return( 0 );
1376 		if( mt1 & MINT ) return( TYPL );
1377 		break;
1378 
1379 	case UNARY AND:
1380 		{  return( NCVT+OTHER ); }
1381 	case INIT:
1382 	case CM:
1383 		return( 0 );
1384 
1385 	case NOT:
1386 	case CBRANCH:
1387 		if( mt1 & MSTR ) break;
1388 		return( 0 );
1389 
1390 	case ANDAND:
1391 	case OROR:
1392 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
1393 		return( 0 );
1394 
1395 	case MUL:
1396 	case DIV:
1397 		if( mt12 & MDBI ) return( TYMATCH );
1398 		break;
1399 
1400 	case MOD:
1401 	case AND:
1402 	case OR:
1403 	case ER:
1404 		if( mt12 & MINT ) return( TYMATCH );
1405 		break;
1406 
1407 	case LS:
1408 	case RS:
1409 		if( mt12 & MINT ) return( TYMATCH+OTHER );
1410 		break;
1411 
1412 	case EQ:
1413 	case NE:
1414 	case LT:
1415 	case LE:
1416 	case GT:
1417 	case GE:
1418 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
1419 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
1420 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
1421 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
1422 		else break;
1423 
1424 	case QUEST:
1425 	case COMOP:
1426 		if( mt2&MENU ) return( TYPR+NCVTR );
1427 		return( TYPR );
1428 
1429 	case STREF:
1430 		return( NCVTR+OTHER );
1431 
1432 	case FORCE:
1433 		return( TYPL );
1434 
1435 	case COLON:
1436 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
1437 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
1438 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1439 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1440 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1441 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1442 		else if( mt12 == MVOID ) return( NCVT+TYPL );
1443 		break;
1444 
1445 	case ASSIGN:
1446 	case RETURN:
1447 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1448 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
1449 	case CAST:
1450 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
1451 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
1452 		else if( mt2 == MVOID &&
1453 		        ( p->in.right->in.op == CALL ||
1454 			  p->in.right->in.op == UNARY CALL)) break;
1455 		else if( (mt1 & MPTR) && (mt2 & MPTI) )
1456 			return( LVAL+PTMATCH+PUN );
1457 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1458 		break;
1459 
1460 	case ASG LS:
1461 	case ASG RS:
1462 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1463 		break;
1464 
1465 	case ASG MUL:
1466 	case ASG DIV:
1467 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
1468 		break;
1469 
1470 	case ASG MOD:
1471 	case ASG AND:
1472 	case ASG OR:
1473 	case ASG ER:
1474 		if( mt12 & MINT ) return( LVAL+TYMATCH );
1475 		break;
1476 
1477 	case ASG PLUS:
1478 	case ASG MINUS:
1479 	case INCR:
1480 	case DECR:
1481 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
1482 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1483 		break;
1484 
1485 	case MINUS:
1486 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1487 		if( mt2 & MPTR ) break;
1488 	case PLUS:
1489 		if( mt12 & MDBI ) return( TYMATCH );
1490 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1491 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1492 
1493 		}
1494 	if( mt12 == MSTR )
1495 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1496 	else
1497 		uerror( "operands of %s have incompatible types", opst[o] );
1498 	return( NCVT );
1499 	}
1500 
1501 moditype( ty ) TWORD ty; {
1502 
1503 	switch( ty ){
1504 
1505 	case UNDEF:
1506 		return( MVOID );
1507 	case ENUMTY:
1508 	case MOETY:
1509 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
1510 
1511 	case STRTY:
1512 	case UNIONTY:
1513 		return( MSTR );
1514 
1515 	case CHAR:
1516 	case SHORT:
1517 	case UCHAR:
1518 	case USHORT:
1519 		return( MINT|MPTI|MDBI );
1520 	case UNSIGNED:
1521 	case ULONG:
1522 	case INT:
1523 	case LONG:
1524 		return( MINT|MDBI|MPTI );
1525 	case FLOAT:
1526 	case DOUBLE:
1527 		return( MDBI );
1528 	default:
1529 		return( MPTR|MPTI );
1530 
1531 		}
1532 	}
1533 
1534 NODE *
1535 doszof( p )  register NODE *p; {
1536 	/* do sizeof p */
1537 	int i;
1538 
1539 	/* whatever is the meaning of this if it is a bitfield? */
1540 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1541 
1542 	tfree(p);
1543 	if( i <= 0 ) werror( "sizeof returns 0" );
1544 	return( bcon( i ) );
1545 	}
1546 
1547 # ifndef BUG2
1548 eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1549 	register ty;
1550 
1551 	*a = *b = down+1;
1552 	while( down > 1 ){
1553 		printf( "\t" );
1554 		down -= 2;
1555 		}
1556 	if( down ) printf( "    " );
1557 
1558 	ty = optype( p->in.op );
1559 
1560 	printf("%o) %s, ", p, opst[p->in.op] );
1561 	if( ty == LTYPE ){
1562 		printf( CONFMT, p->tn.lval );
1563 		printf( ", %d, ", p->tn.rval );
1564 		}
1565 	tprint( p->in.type );
1566 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1567 	}
1568 # endif
1569 
1570 #ifndef PRTDCON
1571 prtdcon( p ) register NODE *p; {
1572 	int o = p->in.op, i;
1573 
1574 	if( o == DCON || o == FCON ){
1575 		(void) locctr( DATA );
1576 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1577 		deflab( i = getlab() );
1578 		if( o == FCON )
1579 			fincode( p->fpn.fval, SZFLOAT );
1580 		else
1581 			fincode( p->dpn.dval, SZDOUBLE );
1582 		p->tn.lval = 0;
1583 		p->tn.rval = -i;
1584 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1585 		p->in.op = NAME;
1586 		}
1587 	}
1588 #endif PRTDCON
1589 
1590 
1591 int edebug = 0;
1592 ecomp( p ) register NODE *p; {
1593 # ifndef BUG2
1594 	if( edebug ) fwalk( p, eprint, 0 );
1595 # endif
1596 	if( !reached ){
1597 		werror( "statement not reached" );
1598 		reached = 1;
1599 		}
1600 	p = optim(p);
1601 	walkf( p, prtdcon );
1602 	(void) locctr( PROG );
1603 	ecode( p );
1604 	tfree(p);
1605 	}
1606 
1607 # ifdef STDPRTREE
1608 # ifndef ONEPASS
1609 
1610 prtree(p) register NODE *p; {
1611 
1612 	register struct symtab *q;
1613 	register ty;
1614 
1615 # ifdef MYPRTREE
1616 	MYPRTREE(p);  /* local action can be taken here; then return... */
1617 #endif
1618 
1619 	ty = optype(p->in.op);
1620 
1621 	printf( "%d\t", p->in.op );
1622 
1623 	if( ty == LTYPE ) {
1624 		printf( CONFMT, p->tn.lval );
1625 		printf( "\t" );
1626 		}
1627 	if( ty != BITYPE ) {
1628 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1629 		else printf( "%d\t", p->tn.rval );
1630 		}
1631 
1632 	printf( "%o\t", p->in.type );
1633 
1634 	/* handle special cases */
1635 
1636 	switch( p->in.op ){
1637 
1638 	case NAME:
1639 	case ICON:
1640 		/* print external name */
1641 		if( p->tn.rval == NONAME ) printf( "\n" );
1642 		else if( p->tn.rval >= 0 ){
1643 			q = &stab[p->tn.rval];
1644 			printf(  "%s\n", exname(q->sname) );
1645 			}
1646 		else { /* label */
1647 			printf( LABFMT, -p->tn.rval );
1648 			}
1649 		break;
1650 
1651 	case STARG:
1652 	case STASG:
1653 	case STCALL:
1654 	case UNARY STCALL:
1655 		/* print out size */
1656 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1657 
1658 		/* note: p->in.left not a field... */
1659 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1660 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1661 		break;
1662 
1663 	default:
1664 		printf(  "\n" );
1665 		}
1666 
1667 	if( ty != LTYPE ) prtree( p->in.left );
1668 	if( ty == BITYPE ) prtree( p->in.right );
1669 
1670 	}
1671 
1672 # else
1673 
1674 p2tree(p) register NODE *p; {
1675 	register ty;
1676 
1677 # ifdef MYP2TREE
1678 	MYP2TREE(p);  /* local action can be taken here; then return... */
1679 # endif
1680 
1681 	ty = optype(p->in.op);
1682 
1683 	switch( p->in.op ){
1684 
1685 	case NAME:
1686 	case ICON:
1687 #ifndef FLEXNAMES
1688 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1689 #else
1690 		if( p->tn.rval == NONAME ) p->in.name = "";
1691 #endif
1692 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1693 			register char *cp;
1694 			cp = exname( stab[p->tn.rval].sname );
1695 #ifndef FLEXNAMES
1696 			{
1697 				register i;
1698 				for( i=0; i<NCHNAM; ++i )
1699 					p->in.name[i] = *cp++;
1700 			}
1701 #else
1702 			p->in.name = tstr(cp);
1703 #endif
1704 			}
1705 #ifndef FLEXNAMES
1706 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1707 #else
1708 		else {
1709 			char temp[32];
1710 			sprintf( temp, LABFMT, -p->tn.rval );
1711 			p->in.name = tstr(temp);
1712 		}
1713 #endif
1714 		break;
1715 
1716 	case STARG:
1717 	case STASG:
1718 	case STCALL:
1719 	case UNARY STCALL:
1720 		/* set up size parameters */
1721 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1722 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1723 		break;
1724 
1725 	case REG:
1726 		rbusy( p->tn.rval, p->in.type );
1727 	default:
1728 #ifndef FLEXNAMES
1729 		p->in.name[0] = '\0';
1730 #else
1731 		p->in.name = "";
1732 #endif
1733 		}
1734 
1735 	p->in.rall = NOPREF;
1736 
1737 	if( ty != LTYPE ) p2tree( p->in.left );
1738 	if( ty == BITYPE ) p2tree( p->in.right );
1739 	}
1740 
1741 # endif
1742 # endif
1743