xref: /csrg-svn/old/pcc/mip/trees.c (revision 29889)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.11 (Berkeley) 10/15/86";
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-val)<0;
729 		break;
730 	case ULE:
731 		p->tn.lval = (p->tn.lval-val)<=0;
732 		break;
733 	case UGE:
734 		p->tn.lval = (p->tn.lval-val)>=0;
735 		break;
736 	case UGT:
737 		p->tn.lval = (p->tn.lval-val)>0;
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 NODE *
1509 doszof( p )  register NODE *p; {
1510 	/* do sizeof p */
1511 	int i;
1512 
1513 	/* whatever is the meaning of this if it is a bitfield? */
1514 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1515 
1516 	tfree(p);
1517 	if( i <= 0 ) werror( "sizeof returns 0" );
1518 	return( bcon( i ) );
1519 	}
1520 
1521 # ifndef BUG2
1522 eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1523 	register ty;
1524 
1525 	*a = *b = down+1;
1526 	while( down > 1 ){
1527 		printf( "\t" );
1528 		down -= 2;
1529 		}
1530 	if( down ) printf( "    " );
1531 
1532 	ty = optype( p->in.op );
1533 
1534 	printf("%o) %s, ", p, opst[p->in.op] );
1535 	if( ty == LTYPE ){
1536 		printf( CONFMT, p->tn.lval );
1537 		printf( ", %d, ", p->tn.rval );
1538 		}
1539 	tprint( p->in.type );
1540 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1541 	}
1542 # endif
1543 
1544 #ifndef PRTDCON
1545 prtdcon( p ) register NODE *p; {
1546 	int o = p->in.op, i;
1547 
1548 	if( o == DCON || o == FCON ){
1549 		locctr( DATA );
1550 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1551 		deflab( i = getlab() );
1552 		if( o == FCON )
1553 			fincode( p->fpn.fval, SZFLOAT );
1554 		else
1555 			fincode( p->dpn.dval, SZDOUBLE );
1556 		p->tn.lval = 0;
1557 		p->tn.rval = -i;
1558 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1559 		p->in.op = NAME;
1560 		}
1561 	}
1562 #endif PRTDCON
1563 
1564 
1565 int edebug = 0;
1566 ecomp( p ) register NODE *p; {
1567 # ifndef BUG2
1568 	if( edebug ) fwalk( p, eprint, 0 );
1569 # endif
1570 	if( !reached ){
1571 		werror( "statement not reached" );
1572 		reached = 1;
1573 		}
1574 	p = optim(p);
1575 	walkf( p, prtdcon );
1576 	locctr( PROG );
1577 	ecode( p );
1578 	tfree(p);
1579 	}
1580 
1581 # ifdef STDPRTREE
1582 # ifndef ONEPASS
1583 
1584 prtree(p) register NODE *p; {
1585 
1586 	register struct symtab *q;
1587 	register ty;
1588 
1589 # ifdef MYPRTREE
1590 	MYPRTREE(p);  /* local action can be taken here; then return... */
1591 #endif
1592 
1593 	ty = optype(p->in.op);
1594 
1595 	printf( "%d\t", p->in.op );
1596 
1597 	if( ty == LTYPE ) {
1598 		printf( CONFMT, p->tn.lval );
1599 		printf( "\t" );
1600 		}
1601 	if( ty != BITYPE ) {
1602 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1603 		else printf( "%d\t", p->tn.rval );
1604 		}
1605 
1606 	printf( "%o\t", p->in.type );
1607 
1608 	/* handle special cases */
1609 
1610 	switch( p->in.op ){
1611 
1612 	case NAME:
1613 	case ICON:
1614 		/* print external name */
1615 		if( p->tn.rval == NONAME ) printf( "\n" );
1616 		else if( p->tn.rval >= 0 ){
1617 			q = &stab[p->tn.rval];
1618 			printf(  "%s\n", exname(q->sname) );
1619 			}
1620 		else { /* label */
1621 			printf( LABFMT, -p->tn.rval );
1622 			}
1623 		break;
1624 
1625 	case STARG:
1626 	case STASG:
1627 	case STCALL:
1628 	case UNARY STCALL:
1629 		/* print out size */
1630 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1631 
1632 		/* note: p->in.left not a field... */
1633 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1634 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1635 		break;
1636 
1637 	default:
1638 		printf(  "\n" );
1639 		}
1640 
1641 	if( ty != LTYPE ) prtree( p->in.left );
1642 	if( ty == BITYPE ) prtree( p->in.right );
1643 
1644 	}
1645 
1646 # else
1647 
1648 p2tree(p) register NODE *p; {
1649 	register ty;
1650 
1651 # ifdef MYP2TREE
1652 	MYP2TREE(p);  /* local action can be taken here; then return... */
1653 # endif
1654 
1655 	ty = optype(p->in.op);
1656 
1657 	switch( p->in.op ){
1658 
1659 	case NAME:
1660 	case ICON:
1661 #ifndef FLEXNAMES
1662 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1663 #else
1664 		if( p->tn.rval == NONAME ) p->in.name = "";
1665 #endif
1666 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1667 			register char *cp;
1668 			register i;
1669 			cp = exname( stab[p->tn.rval].sname );
1670 #ifndef FLEXNAMES
1671 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1672 #else
1673 			p->in.name = tstr(cp);
1674 #endif
1675 			}
1676 #ifndef FLEXNAMES
1677 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1678 #else
1679 		else {
1680 			char temp[32];
1681 			sprintf( temp, LABFMT, -p->tn.rval );
1682 			p->in.name = tstr(temp);
1683 		}
1684 #endif
1685 		break;
1686 
1687 	case STARG:
1688 	case STASG:
1689 	case STCALL:
1690 	case UNARY STCALL:
1691 		/* set up size parameters */
1692 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1693 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1694 		break;
1695 
1696 	case REG:
1697 		rbusy( p->tn.rval, p->in.type );
1698 	default:
1699 #ifndef FLEXNAMES
1700 		p->in.name[0] = '\0';
1701 #else
1702 		p->in.name = "";
1703 #endif
1704 		}
1705 
1706 	p->in.rall = NOPREF;
1707 
1708 	if( ty != LTYPE ) p2tree( p->in.left );
1709 	if( ty == BITYPE ) p2tree( p->in.right );
1710 	}
1711 
1712 # endif
1713 # endif
1714