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