xref: /csrg-svn/old/pcc/mip/trees.c (revision 32840)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.15 (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 				chkpun( p );
155 
156 		case ANDAND:
157 		case OROR:
158 		case CBRANCH:
159 
160 		ccwarn:
161 			if( hflag ) werror( "constant in conditional context" );
162 
163 		case PLUS:
164 		case MINUS:
165 		case MUL:
166 		case DIV:
167 		case MOD:
168 		case AND:
169 		case OR:
170 		case ER:
171 		case LS:
172 		case RS:
173 			if( conval( l, o, r ) ) {
174 				r->in.op = FREE;
175 				return(l);
176 				}
177 			break;
178 			}
179 		}
180 	else if (opty == BITYPE &&
181 		(l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
182 		(r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
183 			if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
184 				extern int fpe_count;
185 				extern jmp_buf gotfpe;
186 
187 				fpe_count = 0;
188 				if (setjmp(gotfpe))
189 					goto treatfpe;
190 				if (l->in.op == ICON)
191 					l->dpn.dval = l->tn.lval;
192 				else if (l->in.op == FCON)
193 					l->dpn.dval = l->fpn.fval;
194 				if (r->in.op == ICON)
195 					r->dpn.dval = r->tn.lval;
196 				else if (r->in.op == FCON)
197 					r->dpn.dval = r->fpn.fval;
198 				switch (o) {
199 
200 				case PLUS:
201 					l->dpn.dval += r->dpn.dval;
202 					break;
203 
204 				case MINUS:
205 					l->dpn.dval -= r->dpn.dval;
206 					break;
207 
208 				case MUL:
209 					l->dpn.dval *= r->dpn.dval;
210 					break;
211 
212 				case DIV:
213 					if (r->dpn.dval == 0)
214 						uerror("division by 0.");
215 					else
216 						l->dpn.dval /= r->dpn.dval;
217 					break;
218 					}
219 			treatfpe:
220 				if (fpe_count > 0) {
221 					uerror("floating point exception in constant expression");
222 					l->dpn.dval = 1.0; /* Fairly harmless */
223 					}
224 				fpe_count = -1;
225 				l->in.op = DCON;
226 				l->in.type = l->fn.csiz = DOUBLE;
227 				r->in.op = FREE;
228 				return (l);
229 			}
230 		}
231 
232 	/* it's real; we must make a new node */
233 
234 	p = block( o, l, r, INT, 0, INT );
235 
236 	actions = opact(p);
237 #ifndef	BUG1
238 	if (adebug)
239 		printact(p, actions);
240 #endif
241 
242 	if( actions&LVAL ){ /* check left descendent */
243 		if( notlval(p->in.left) ) {
244 			uerror( "illegal lhs of assignment operator" );
245 			}
246 		}
247 
248 	if( actions & NCVTR ){
249 		p->in.left = pconvert( p->in.left );
250 		}
251 	else if( !(actions & NCVT ) ){
252 		switch( opty ){
253 
254 		case BITYPE:
255 			p->in.right = pconvert( p->in.right );
256 		case UTYPE:
257 			p->in.left = pconvert( p->in.left );
258 
259 			}
260 		}
261 
262 	if( (actions&PUN) && (o!=CAST||cflag) ){
263 		chkpun(p);
264 		}
265 
266 	if( actions & (TYPL|TYPR) ){
267 
268 		q = (actions&TYPL) ? p->in.left : p->in.right;
269 
270 		p->in.type = q->in.type;
271 		p->fn.cdim = q->fn.cdim;
272 		p->fn.csiz = q->fn.csiz;
273 		}
274 
275 	if( actions & CVTL ) p = convert( p, CVTL );
276 	if( actions & CVTR ) p = convert( p, CVTR );
277 	if( actions & TYMATCH ) p = tymatch(p);
278 	if( actions & PTMATCH ) p = ptmatch(p);
279 
280 	if( actions & OTHER ){
281 		l = p->in.left;
282 		r = p->in.right;
283 
284 		switch(o){
285 
286 		case NAME:
287 			sp = &stab[idname];
288 			if( sp->stype == UNDEF ){
289 #ifndef FLEXNAMES
290 				uerror( "%.8s undefined", sp->sname );
291 #else
292 				uerror( "%s undefined", sp->sname );
293 #endif
294 				/* make p look reasonable */
295 				p->in.type = p->fn.cdim = p->fn.csiz = INT;
296 				p->tn.rval = idname;
297 				p->tn.lval = 0;
298 				defid( p, SNULL );
299 				break;
300 				}
301 			p->in.type = sp->stype;
302 			p->fn.cdim = sp->dimoff;
303 			p->fn.csiz = sp->sizoff;
304 			p->tn.lval = 0;
305 			p->tn.rval = idname;
306 			/* special case: MOETY is really an ICON... */
307 			if( p->in.type == MOETY ){
308 				p->tn.rval = NONAME;
309 				p->tn.lval = sp->offset;
310 				p->fn.cdim = 0;
311 				p->in.type = ENUMTY;
312 				p->in.op = ICON;
313 				}
314 			break;
315 
316 		case ICON:
317 			p->in.type = INT;
318 			p->fn.cdim = 0;
319 			p->fn.csiz = INT;
320 			break;
321 
322 		case STRING:
323 			p->in.op = NAME;
324 			p->in.type = CHAR+ARY;
325 			p->tn.lval = 0;
326 			p->tn.rval = NOLAB;
327 			p->fn.cdim = curdim;
328 			p->fn.csiz = CHAR;
329 			break;
330 
331 		case FCON:
332 			p->tn.lval = 0;
333 			p->tn.rval = 0;
334 			p->in.type = FLOAT;
335 			p->fn.cdim = 0;
336 			p->fn.csiz = FLOAT;
337 			break;
338 
339 		case DCON:
340 			p->tn.lval = 0;
341 			p->tn.rval = 0;
342 			p->in.type = DOUBLE;
343 			p->fn.cdim = 0;
344 			p->fn.csiz = DOUBLE;
345 			break;
346 
347 		case STREF:
348 			/* p->x turned into *(p+offset) */
349 			/* rhs must be a name; check correctness */
350 
351 			i = r->tn.rval;
352 			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
353 				uerror( "member of structure or union required" );
354 				}else
355 			/* if this name is non-unique, find right one */
356 			if( stab[i].sflags & SNONUNIQ &&
357 				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
358 				(l->fn.csiz +1) >= 0 ){
359 				/* nonunique name && structure defined */
360 				char * memnam, * tabnam;
361 				register k;
362 				int j;
363 				int memi;
364 				j=dimtab[l->fn.csiz+1];
365 				for( ; (memi=dimtab[j]) >= 0; ++j ){
366 					tabnam = stab[memi].sname;
367 					memnam = stab[i].sname;
368 # ifndef BUG1
369 					if( ddebug>1 ){
370 #ifndef FLEXNAMES
371 						printf("member %.8s==%.8s?\n",
372 #else
373 						printf("member %s==%s?\n",
374 #endif
375 							memnam, tabnam);
376 						}
377 # endif
378 					if( stab[memi].sflags & SNONUNIQ ){
379 #ifndef FLEXNAMES
380 						for( k=0; k<NCHNAM; ++k ){
381 							if(*memnam++!=*tabnam)
382 								goto next;
383 							if(!*tabnam++) break;
384 							}
385 #else
386 						if (memnam != tabnam)
387 							goto next;
388 #endif
389 						r->tn.rval = i = memi;
390 						break;
391 						}
392 					next: continue;
393 					}
394 				if( memi < 0 )
395 #ifndef FLEXNAMES
396 					uerror("illegal member use: %.8s",
397 #else
398 					uerror("illegal member use: %s",
399 #endif
400 						stab[i].sname);
401 				}
402 			else {
403 				register j;
404 				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
405 					if( stab[i].sflags & SNONUNIQ ){
406 						uerror( "nonunique name demands struct/union or struct/union pointer" );
407 						}
408 					else werror( "struct/union or struct/union pointer required" );
409 					}
410 				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
411 				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
412 #ifndef FLEXNAMES
413 					werror( "illegal member use: %.8s", stab[i].sname );
414 #else
415 					werror( "illegal member use: %s", stab[i].sname );
416 #endif
417 					}
418 				}
419 
420 			p = stref( p );
421 			break;
422 
423 		case UNARY MUL:
424 			if( l->in.op == UNARY AND ){
425 				p->in.op = l->in.op = FREE;
426 				p = l->in.left;
427 				}
428 			if( !ISPTR(l->in.type))uerror("illegal indirection");
429 			p->in.type = DECREF(l->in.type);
430 			p->fn.cdim = l->fn.cdim;
431 			p->fn.csiz = l->fn.csiz;
432 			break;
433 
434 		case UNARY AND:
435 			switch( l->in.op ){
436 
437 			case UNARY MUL:
438 				p->in.op = l->in.op = FREE;
439 				p = l->in.left;
440 			case NAME:
441 				p->in.type = INCREF( l->in.type );
442 				p->fn.cdim = l->fn.cdim;
443 				p->fn.csiz = l->fn.csiz;
444 				break;
445 
446 			case COMOP:
447 				lr = buildtree( UNARY AND, l->in.right, NIL );
448 				p->in.op = l->in.op = FREE;
449 				p = buildtree( COMOP, l->in.left, lr );
450 				break;
451 
452 			case QUEST:
453 				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
454 				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
455 				p->in.op = l->in.op = l->in.right->in.op = FREE;
456 				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
457 				break;
458 
459 # ifdef ADDROREG
460 			case OREG:
461 				/* OREG was built in clocal()
462 				 * for an auto or formal parameter
463 				 * now its address is being taken
464 				 * local code must unwind it
465 				 * back to PLUS/MINUS REG ICON
466 				 * according to local conventions
467 				 */
468 				{
469 				extern NODE * addroreg();
470 				p->in.op = FREE;
471 				p = addroreg( l );
472 				}
473 				break;
474 
475 # endif
476 			default:
477 				uerror( "unacceptable operand of &" );
478 				break;
479 				}
480 			break;
481 
482 		case LS:
483 		case RS:
484 		case ASG LS:
485 		case ASG RS:
486 			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
487 				p->in.right = makety(p->in.right, INT, 0, INT );
488 			break;
489 
490 		case RETURN:
491 		case ASSIGN:
492 		case CAST:
493 			/* structure assignment */
494 			/* take the addresses of the two sides; then make an
495 			/* operator using STASG and
496 			/* the addresses of left and right */
497 
498 			{
499 				register TWORD t;
500 				register d, s;
501 
502 				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
503 
504 				r = buildtree( UNARY AND, r, NIL );
505 				t = r->in.type;
506 				d = r->fn.cdim;
507 				s = r->fn.csiz;
508 
509 				l = block( STASG, l, r, t, d, s );
510 
511 				if( o == RETURN ){
512 					p->in.op = FREE;
513 					p = l;
514 					break;
515 					}
516 
517 				p->in.op = UNARY MUL;
518 				p->in.left = l;
519 				p->in.right = NIL;
520 				break;
521 				}
522 		case COLON:
523 			/* structure colon */
524 
525 			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
526 			break;
527 
528 		case CALL:
529 			p->in.right = r = fixargs( p->in.right );
530 		case UNARY CALL:
531 			if( !ISPTR(l->in.type)) uerror("illegal function");
532 			p->in.type = DECREF(l->in.type);
533 			if( !ISFTN(p->in.type)) uerror("illegal function");
534 			p->in.type = DECREF( p->in.type );
535 			p->fn.cdim = l->fn.cdim;
536 			p->fn.csiz = l->fn.csiz;
537 			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
538 				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
539 				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
540 				p->in.op += (FORTCALL-CALL);
541 				}
542 			if( p->in.type == STRTY || p->in.type == UNIONTY ){
543 				/* function returning structure */
544 				/*  make function really return ptr to str., with * */
545 
546 				p->in.op += STCALL-CALL;
547 				p->in.type = INCREF( p->in.type );
548 				p = buildtree( UNARY MUL, p, NIL );
549 
550 				}
551 			break;
552 
553 		default:
554 			cerror( "other code %d", o );
555 			}
556 
557 		}
558 
559 	if( actions & CVTO ) p = oconvert(p);
560 	p = clocal(p);
561 
562 # ifndef BUG1
563 	if( bdebug ) fwalk( p, eprint, 0 );
564 # endif
565 
566 	return(p);
567 
568 	}
569 
570 int fpe_count = -1;
571 jmp_buf gotfpe;
572 
573 fpe() {
574 	if (fpe_count < 0)
575 		cerror("floating point exception");
576 	++fpe_count;
577 	longjmp(gotfpe, 1);
578 	}
579 
580 /*
581  * Rewrite arguments in a function call.
582  * Structure arguments are massaged, single
583  * precision floating point constants are
584  * cast to double (to eliminate convert code).
585  */
586 NODE *
587 fixargs( p ) register NODE *p;  {
588 	int o = p->in.op;
589 
590 	if( o == CM ){
591 		p->in.left = fixargs( p->in.left );
592 		p->in.right = fixargs( p->in.right );
593 		return( p );
594 		}
595 
596 	if( p->in.type == STRTY || p->in.type == UNIONTY ){
597 		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
598 		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
599 		p = clocal(p);
600 		}
601 	else if( o == FCON )
602 		p = makety(p, DOUBLE, 0, 0);
603 	return( p );
604 	}
605 
606 chkstr( i, j, type ) TWORD type; {
607 	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
608 	/* i has been checked to contain a MOS or MOU */
609 	/* j is the index in dimtab of the members... */
610 	int k, kk;
611 
612 	extern int ddebug;
613 
614 # ifndef BUG1
615 #ifndef FLEXNAMES
616 	if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
617 #else
618 	if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
619 #endif
620 # endif
621 	if( (k = j) < 0 ) uerror( "undefined structure or union" );
622 	else {
623 		for( ; (kk = dimtab[k] ) >= 0; ++k ){
624 			if( kk >= SYMTSZ ){
625 				cerror( "gummy structure" );
626 				return(1);
627 				}
628 			if( kk == i ) return( 1 );
629 			switch( stab[kk].stype ){
630 
631 			case STRTY:
632 			case UNIONTY:
633 				if( type == STRTY ) continue;  /* no recursive looking for strs */
634 				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
635 					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
636 					werror(
637 #ifndef FLEXNAMES
638 					"illegal member use: perhaps %.8s.%.8s?",
639 #else
640 					"illegal member use: perhaps %s.%s?",
641 #endif
642 					stab[kk].sname, stab[i].sname );
643 					return(1);
644 					}
645 				}
646 			}
647 		}
648 	return( 0 );
649 	}
650 
651 conval( p, o, q ) register NODE *p, *q; {
652 	/* apply the op o to the lval part of p; if binary, rhs is val */
653 	int i, u;
654 	CONSZ val;
655 
656 	val = q->tn.lval;
657 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
658 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
659 
660 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
661 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
662 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
663 
664 	switch( o ){
665 
666 	case PLUS:
667 		p->tn.lval += val;
668 		if( p->tn.rval == NONAME ){
669 			p->tn.rval = q->tn.rval;
670 			p->in.type = q->in.type;
671 			}
672 		break;
673 	case MINUS:
674 		p->tn.lval -= val;
675 		break;
676 	case MUL:
677 		p->tn.lval *= val;
678 		break;
679 	case DIV:
680 		if( val == 0 ) uerror( "division by 0" );
681 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
682 		else p->tn.lval /= val;
683 		break;
684 	case MOD:
685 		if( val == 0 ) uerror( "division by 0" );
686 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
687 		else p->tn.lval %= val;
688 		break;
689 	case AND:
690 		p->tn.lval &= val;
691 		break;
692 	case OR:
693 		p->tn.lval |= val;
694 		break;
695 	case ER:
696 		p->tn.lval ^= val;
697 		break;
698 	case LS:
699 		i = val;
700 		p->tn.lval = p->tn.lval << i;
701 		break;
702 	case RS:
703 		i = val;
704 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
705 		else p->tn.lval = p->tn.lval >> i;
706 		break;
707 
708 	case UNARY MINUS:
709 		p->tn.lval = - p->tn.lval;
710 		break;
711 	case COMPL:
712 		p->tn.lval = ~p->tn.lval;
713 		break;
714 	case NOT:
715 		p->tn.lval = !p->tn.lval;
716 		break;
717 	case LT:
718 		p->tn.lval = p->tn.lval < val;
719 		break;
720 	case LE:
721 		p->tn.lval = p->tn.lval <= val;
722 		break;
723 	case GT:
724 		p->tn.lval = p->tn.lval > val;
725 		break;
726 	case GE:
727 		p->tn.lval = p->tn.lval >= val;
728 		break;
729 	case ULT:
730 		p->tn.lval = (p->tn.lval-val)<0;
731 		break;
732 	case ULE:
733 		p->tn.lval = (p->tn.lval-val)<=0;
734 		break;
735 	case UGE:
736 		p->tn.lval = (p->tn.lval-val)>=0;
737 		break;
738 	case UGT:
739 		p->tn.lval = (p->tn.lval-val)>0;
740 		break;
741 	case EQ:
742 		p->tn.lval = p->tn.lval == val;
743 		break;
744 	case NE:
745 		p->tn.lval = p->tn.lval != val;
746 		break;
747 	default:
748 		return(0);
749 		}
750 	return(1);
751 	}
752 
753 chkpun(p) register NODE *p; {
754 
755 	/* checks p for the existance of a pun */
756 
757 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
758 
759 	/* one case is when enumerations are used: this applies only to lint */
760 	/* in the other case, one operand is a pointer, the other integer type */
761 	/* we check that this integer is in fact a constant zero... */
762 
763 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
764 	/* this falls out, because the LHS is never 0 */
765 
766 	register NODE *q;
767 	register t1, t2;
768 	register d1, d2;
769 
770 	t1 = p->in.left->in.type;
771 	t2 = p->in.right->in.type;
772 
773 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
774 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
775 			werror( "comparison of enums" );
776 		if( t1==ENUMTY && t2==ENUMTY &&
777 		    p->in.left->fn.csiz!=p->in.right->fn.csiz )
778 			werror( "enumeration type clash, operator %s", opst[p->in.op] );
779 		return;
780 		}
781 
782 	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
783 	else q = p->in.left;
784 
785 	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
786 		if( q->in.op != ICON || q->tn.lval != 0 ){
787 			werror( "illegal combination of pointer and integer, op %s",
788 				opst[p->in.op] );
789 			}
790 		}
791 	else {
792 		d1 = p->in.left->fn.cdim;
793 		d2 = p->in.right->fn.cdim;
794 		for( ;; ){
795 			if( t1 == t2 ) {;
796 				if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
797 					werror( "illegal structure pointer combination" );
798 					}
799 				return;
800 				}
801 			if( ISARY(t1) || ISPTR(t1) ){
802 				if( !ISARY(t2) && !ISPTR(t2) ) break;
803 				if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
804 					werror( "illegal array size combination" );
805 					return;
806 					}
807 				if( ISARY(t1) ) ++d1;
808 				if( ISARY(t2) ) ++d2;
809 				}
810 			else break;
811 			t1 = DECREF(t1);
812 			t2 = DECREF(t2);
813 			}
814 		werror( "illegal pointer combination" );
815 		}
816 
817 	}
818 
819 NODE *
820 stref( p ) register NODE *p; {
821 
822 	TWORD t;
823 	int d, s, dsc, align;
824 	OFFSZ off;
825 	register struct symtab *q;
826 
827 	/* make p->x */
828 	/* this is also used to reference automatic variables */
829 
830 	q = &stab[p->in.right->tn.rval];
831 	p->in.right->in.op = FREE;
832 	p->in.op = FREE;
833 	p = pconvert( p->in.left );
834 
835 	/* make p look like ptr to x */
836 
837 	if( !ISPTR(p->in.type)){
838 		p->in.type = PTR+UNIONTY;
839 		}
840 
841 	t = INCREF( q->stype );
842 	d = q->dimoff;
843 	s = q->sizoff;
844 
845 	p = makety( p, t, d, s );
846 
847 	/* compute the offset to be added */
848 
849 	off = q->offset;
850 	dsc = q->sclass;
851 
852 	if( dsc & FIELD ) {  /* normalize offset */
853 		align = ALINT;
854 		s = INT;
855 		off = (off/align)*align;
856 		}
857 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
858 
859 	p = buildtree( UNARY MUL, p, NIL );
860 
861 	/* if field, build field info */
862 
863 	if( dsc & FIELD ){
864 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
865 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
866 		}
867 
868 	return( clocal(p) );
869 	}
870 
871 notlval(p) register NODE *p; {
872 
873 	/* return 0 if p an lvalue, 1 otherwise */
874 
875 	again:
876 
877 	switch( p->in.op ){
878 
879 	case FLD:
880 		p = p->in.left;
881 		goto again;
882 
883 	case UNARY MUL:
884 		/* fix the &(a=b) bug, given that a and b are structures */
885 		if( p->in.left->in.op == STASG ) return( 1 );
886 		/* and the f().a bug, given that f returns a structure */
887 		if( p->in.left->in.op == UNARY STCALL ||
888 		    p->in.left->in.op == STCALL ) return( 1 );
889 	case NAME:
890 	case OREG:
891 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
892 	case REG:
893 		return(0);
894 
895 	default:
896 		return(1);
897 
898 		}
899 
900 	}
901 
902 NODE *
903 bcon( i ){ /* make a constant node with value i */
904 	register NODE *p;
905 
906 	p = block( ICON, NIL, NIL, INT, 0, INT );
907 	p->tn.lval = i;
908 	p->tn.rval = NONAME;
909 	return( clocal(p) );
910 	}
911 
912 NODE *
913 bpsize(p) register NODE *p; {
914 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
915 	}
916 
917 OFFSZ
918 psize( p ) NODE *p; {
919 	/* p is a node of type pointer; psize returns the
920 	   size of the thing pointed to */
921 
922 	if( !ISPTR(p->in.type) ){
923 		uerror( "pointer required");
924 		return( SZINT );
925 		}
926 	/* note: no pointers to fields */
927 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
928 	}
929 
930 NODE *
931 convert( p, f )  register NODE *p; {
932 	/*  convert an operand of p
933 	    f is either CVTL or CVTR
934 	    operand has type int, and is converted by the size of the other side
935 	    */
936 
937 	register NODE *q, *r;
938 
939 	q = (f==CVTL)?p->in.left:p->in.right;
940 
941 	r = block( PMCONV,
942 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
943 	r = clocal(r);
944 	if( f == CVTL )
945 		p->in.left = r;
946 	else
947 		p->in.right = r;
948 	return(p);
949 
950 	}
951 
952 #ifndef econvert
953 econvert( p ) register NODE *p; {
954 
955 	/* change enums to ints, or appropriate types */
956 
957 	register TWORD ty;
958 
959 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
960 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
961 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
962 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
963 		else ty = LONG;
964 		ty = ctype( ty );
965 		p->fn.csiz = ty;
966 		MODTYPE(p->in.type,ty);
967 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
968 		}
969 	}
970 #endif
971 
972 NODE *
973 pconvert( p ) register NODE *p; {
974 
975 	/* if p should be changed into a pointer, do so */
976 
977 	if( ISARY( p->in.type) ){
978 		p->in.type = DECREF( p->in.type );
979 		++p->fn.cdim;
980 		return( buildtree( UNARY AND, p, NIL ) );
981 		}
982 	if( ISFTN( p->in.type) )
983 		return( buildtree( UNARY AND, p, NIL ) );
984 
985 	return( p );
986 	}
987 
988 NODE *
989 oconvert(p) register NODE *p; {
990 	/* convert the result itself: used for pointer and unsigned */
991 
992 	switch(p->in.op) {
993 
994 	case LE:
995 	case LT:
996 	case GE:
997 	case GT:
998 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
999 	case EQ:
1000 	case NE:
1001 		return( p );
1002 
1003 	case MINUS:
1004 		return(  clocal( block( PVCONV,
1005 			p, bpsize(p->in.left), INT, 0, INT ) ) );
1006 		}
1007 
1008 	cerror( "illegal oconvert: %d", p->in.op );
1009 
1010 	return(p);
1011 	}
1012 
1013 NODE *
1014 ptmatch(p)  register NODE *p; {
1015 
1016 	/* makes the operands of p agree; they are
1017 	   either pointers or integers, by this time */
1018 	/* with MINUS, the sizes must be the same */
1019 	/* with COLON, the types must be the same */
1020 
1021 	TWORD t1, t2, t;
1022 	int o, d2, d, s2, s;
1023 
1024 	o = p->in.op;
1025 	t = t1 = p->in.left->in.type;
1026 	t2 = p->in.right->in.type;
1027 	d = p->in.left->fn.cdim;
1028 	d2 = p->in.right->fn.cdim;
1029 	s = p->in.left->fn.csiz;
1030 	s2 = p->in.right->fn.csiz;
1031 
1032 	switch( o ){
1033 
1034 	case ASSIGN:
1035 	case RETURN:
1036 	case CAST:
1037 		{  break; }
1038 
1039 	case MINUS:
1040 		{  if( psize(p->in.left) != psize(p->in.right) ){
1041 			uerror( "illegal pointer subtraction");
1042 			}
1043 		   break;
1044 		   }
1045 	case COLON:
1046 		{  if( t1 != t2 ) uerror( "illegal types in :");
1047 		   break;
1048 		   }
1049 	default:  /* must work harder: relationals or comparisons */
1050 
1051 		if( !ISPTR(t1) ){
1052 			t = t2;
1053 			d = d2;
1054 			s = s2;
1055 			break;
1056 			}
1057 		if( !ISPTR(t2) ){
1058 			break;
1059 			}
1060 
1061 		/* both are pointers */
1062 		if( talign(t2,s2) < talign(t,s) ){
1063 			t = t2;
1064 			s = s2;
1065 			}
1066 		break;
1067 		}
1068 
1069 	p->in.left = makety( p->in.left, t, d, s );
1070 	p->in.right = makety( p->in.right, t, d, s );
1071 	if( o!=MINUS && !logop(o) ){
1072 
1073 		p->in.type = t;
1074 		p->fn.cdim = d;
1075 		p->fn.csiz = s;
1076 		}
1077 
1078 	return(clocal(p));
1079 	}
1080 
1081 int tdebug = 0;
1082 
1083 NODE *
1084 tymatch(p)  register NODE *p; {
1085 
1086 	/* satisfy the types of various arithmetic binary ops */
1087 
1088 	/* rules are:
1089 		if assignment, type of LHS
1090 		if any float or doubles, make double
1091 		if any longs, make long
1092 		otherwise, make int
1093 		if either operand is unsigned, the result is...
1094 	*/
1095 
1096 	register TWORD t1, t2, t, tu;
1097 	register o, u;
1098 
1099 	o = p->in.op;
1100 
1101 	t1 = p->in.left->in.type;
1102 	t2 = p->in.right->in.type;
1103 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
1104 		uerror("void type illegal in expression");
1105 
1106 	u = 0;
1107 	if( ISUNSIGNED(t1) ){
1108 		u = 1;
1109 		t1 = DEUNSIGN(t1);
1110 		}
1111 	if( ISUNSIGNED(t2) ){
1112 		u = 1;
1113 		t2 = DEUNSIGN(t2);
1114 		}
1115 
1116 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1117 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1118 
1119 #ifdef SPRECC
1120 	if( t1 == DOUBLE || t2 == DOUBLE )
1121 		t = DOUBLE;
1122 	else if( t1 == FLOAT || t2 == FLOAT )
1123 		t = FLOAT;
1124 #else
1125 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
1126 		t = DOUBLE;
1127 #endif
1128 	else if( t1==LONG || t2==LONG ) t = LONG;
1129 	else t = INT;
1130 
1131 	if( o == ASSIGN || o == CAST || o == RETURN ){
1132 		tu = p->in.left->in.type;
1133 		t = t1;
1134 		}
1135 	else {
1136 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1137 		}
1138 
1139 	/* because expressions have values that are at least as wide
1140 	   as INT or UNSIGNED, the only conversions needed
1141 	   are those involving FLOAT/DOUBLE, and those
1142 	   from LONG to INT and ULONG to UNSIGNED */
1143 
1144 	if( t != t1 && ! asgop(o) )
1145 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
1146 
1147 	if( t != t2 || o==CAST)
1148 		if ( tu == ENUMTY ) {/* always asgop */
1149 			p->in.right = makety( p->in.right, INT, 0, INT );
1150 			p->in.right->in.type = tu;
1151 			p->in.right->fn.cdim = p->in.left->fn.cdim;
1152 			p->in.right->fn.csiz = p->in.left->fn.csiz;
1153 			}
1154 		else
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 		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
1422 	case CAST:
1423 		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
1424 		else if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
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|MINT|MDBI|MPTI );  /* enums are ints */
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 prtdcon( p ) register NODE *p; {
1545 	int o = p->in.op, i;
1546 
1547 	if( o == DCON || o == FCON ){
1548 		locctr( DATA );
1549 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1550 		deflab( i = getlab() );
1551 		if( o == FCON )
1552 			fincode( p->fpn.fval, SZFLOAT );
1553 		else
1554 			fincode( p->dpn.dval, SZDOUBLE );
1555 		p->tn.lval = 0;
1556 		p->tn.rval = -i;
1557 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1558 		p->in.op = NAME;
1559 		}
1560 	}
1561 
1562 
1563 int edebug = 0;
1564 ecomp( p ) register NODE *p; {
1565 # ifndef BUG2
1566 	if( edebug ) fwalk( p, eprint, 0 );
1567 # endif
1568 	if( !reached ){
1569 		werror( "statement not reached" );
1570 		reached = 1;
1571 		}
1572 	p = optim(p);
1573 	walkf( p, prtdcon );
1574 	locctr( PROG );
1575 	ecode( p );
1576 	tfree(p);
1577 	}
1578 
1579 # ifdef STDPRTREE
1580 # ifndef ONEPASS
1581 
1582 prtree(p) register NODE *p; {
1583 
1584 	register struct symtab *q;
1585 	register ty;
1586 
1587 # ifdef MYPRTREE
1588 	MYPRTREE(p);  /* local action can be taken here; then return... */
1589 #endif
1590 
1591 	ty = optype(p->in.op);
1592 
1593 	printf( "%d\t", p->in.op );
1594 
1595 	if( ty == LTYPE ) {
1596 		printf( CONFMT, p->tn.lval );
1597 		printf( "\t" );
1598 		}
1599 	if( ty != BITYPE ) {
1600 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1601 		else printf( "%d\t", p->tn.rval );
1602 		}
1603 
1604 	printf( "%o\t", p->in.type );
1605 
1606 	/* handle special cases */
1607 
1608 	switch( p->in.op ){
1609 
1610 	case NAME:
1611 	case ICON:
1612 		/* print external name */
1613 		if( p->tn.rval == NONAME ) printf( "\n" );
1614 		else if( p->tn.rval >= 0 ){
1615 			q = &stab[p->tn.rval];
1616 			printf(  "%s\n", exname(q->sname) );
1617 			}
1618 		else { /* label */
1619 			printf( LABFMT, -p->tn.rval );
1620 			}
1621 		break;
1622 
1623 	case STARG:
1624 	case STASG:
1625 	case STCALL:
1626 	case UNARY STCALL:
1627 		/* print out size */
1628 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1629 
1630 		/* note: p->in.left not a field... */
1631 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1632 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1633 		break;
1634 
1635 	default:
1636 		printf(  "\n" );
1637 		}
1638 
1639 	if( ty != LTYPE ) prtree( p->in.left );
1640 	if( ty == BITYPE ) prtree( p->in.right );
1641 
1642 	}
1643 
1644 # else
1645 
1646 p2tree(p) register NODE *p; {
1647 	register ty;
1648 
1649 # ifdef MYP2TREE
1650 	MYP2TREE(p);  /* local action can be taken here; then return... */
1651 # endif
1652 
1653 	ty = optype(p->in.op);
1654 
1655 	switch( p->in.op ){
1656 
1657 	case NAME:
1658 	case ICON:
1659 #ifndef FLEXNAMES
1660 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1661 #else
1662 		if( p->tn.rval == NONAME ) p->in.name = "";
1663 #endif
1664 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1665 			register char *cp;
1666 			register i;
1667 			cp = exname( stab[p->tn.rval].sname );
1668 #ifndef FLEXNAMES
1669 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1670 #else
1671 			p->in.name = tstr(cp);
1672 #endif
1673 			}
1674 #ifndef FLEXNAMES
1675 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1676 #else
1677 		else {
1678 			char temp[32];
1679 			sprintf( temp, LABFMT, -p->tn.rval );
1680 			p->in.name = tstr(temp);
1681 		}
1682 #endif
1683 		break;
1684 
1685 	case STARG:
1686 	case STASG:
1687 	case STCALL:
1688 	case UNARY STCALL:
1689 		/* set up size parameters */
1690 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1691 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1692 		break;
1693 
1694 	case REG:
1695 		rbusy( p->tn.rval, p->in.type );
1696 	default:
1697 #ifndef FLEXNAMES
1698 		p->in.name[0] = '\0';
1699 #else
1700 		p->in.name = "";
1701 #endif
1702 		}
1703 
1704 	p->in.rall = NOPREF;
1705 
1706 	if( ty != LTYPE ) p2tree( p->in.left );
1707 	if( ty == BITYPE ) p2tree( p->in.right );
1708 	}
1709 
1710 # endif
1711 # endif
1712