xref: /csrg-svn/old/pcc/mip/trees.c (revision 32850)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.25 (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 lvalue operand 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 	/* works only on integer constants */
654 	NODE *r;
655 	int i, u;
656 	CONSZ val;
657 
658 	val = q->tn.lval;
659 	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
660 	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
661 
662 	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
663 	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
664 	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
665 
666 	if( p->in.type != INT || q->in.type != INT ){
667 		/* will this always work if p == q and o is UTYPE? */
668 		r = block( o, p, q, INT, 0, INT );
669 		r = tymatch( r );
670 		p->in.type = r->in.type;
671 		p->fn.cdim = r->fn.cdim;
672 		p->fn.csiz = r->fn.csiz;
673 		r->in.op = FREE;
674 		}
675 
676 	switch( o ){
677 
678 	case PLUS:
679 		p->tn.lval += val;
680 		if( p->tn.rval == NONAME ){
681 			p->tn.rval = q->tn.rval;
682 			p->in.type = q->in.type;
683 			}
684 		break;
685 	case MINUS:
686 		p->tn.lval -= val;
687 		break;
688 	case MUL:
689 		p->tn.lval *= val;
690 		break;
691 	case DIV:
692 		if( val == 0 ) uerror( "division by 0" );
693 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
694 		else p->tn.lval /= val;
695 		break;
696 	case MOD:
697 		if( val == 0 ) uerror( "division by 0" );
698 		else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
699 		else p->tn.lval %= val;
700 		break;
701 	case AND:
702 		p->tn.lval &= val;
703 		break;
704 	case OR:
705 		p->tn.lval |= val;
706 		break;
707 	case ER:
708 		p->tn.lval ^= val;
709 		break;
710 	case LS:
711 		i = val;
712 		p->tn.lval = p->tn.lval << i;
713 		break;
714 	case RS:
715 		i = val;
716 		if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
717 		else p->tn.lval = p->tn.lval >> i;
718 		break;
719 
720 	case UNARY MINUS:
721 		p->tn.lval = - p->tn.lval;
722 		break;
723 	case COMPL:
724 		p->tn.lval = ~p->tn.lval;
725 		break;
726 	case NOT:
727 		p->tn.lval = !p->tn.lval;
728 		break;
729 	case LT:
730 		p->tn.lval = p->tn.lval < val;
731 		break;
732 	case LE:
733 		p->tn.lval = p->tn.lval <= val;
734 		break;
735 	case GT:
736 		p->tn.lval = p->tn.lval > val;
737 		break;
738 	case GE:
739 		p->tn.lval = p->tn.lval >= val;
740 		break;
741 	case ULT:
742 		p->tn.lval = p->tn.lval < (unsigned) val;
743 		break;
744 	case ULE:
745 		p->tn.lval = p->tn.lval <= (unsigned) val;
746 		break;
747 	case UGT:
748 		p->tn.lval = p->tn.lval > (unsigned) val;
749 		break;
750 	case UGE:
751 		p->tn.lval = p->tn.lval >= (unsigned) val;
752 		break;
753 	case EQ:
754 		p->tn.lval = p->tn.lval == val;
755 		break;
756 	case NE:
757 		p->tn.lval = p->tn.lval != val;
758 		break;
759 	default:
760 		return(0);
761 		}
762 	return(1);
763 	}
764 
765 chkpun(p) register NODE *p; {
766 
767 	/* checks p for the existance of a pun */
768 
769 	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
770 
771 	/* one case is when enumerations are used: this applies only to lint */
772 	/* in the other case, one operand is a pointer, the other integer type */
773 	/* we check that this integer is in fact a constant zero... */
774 
775 	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
776 	/* this falls out, because the LHS is never 0 */
777 
778 	register NODE *q;
779 	register t1, t2;
780 	register d1, d2;
781 	int ref1, ref2;
782 
783 	t1 = p->in.left->in.type;
784 	t2 = p->in.right->in.type;
785 
786 	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
787 		/* rob pike says this is obnoxious...
788 		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
789 			werror( "comparison of enums" ); */
790 		if( t1==ENUMTY && t2==ENUMTY ) {
791 			if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
792 				werror( "enumeration type clash, operator %s", opst[p->in.op] );
793 			return;
794 			}
795 		if ( t1 == ENUMTY ) t1 = INT;
796 		if ( t2 == ENUMTY ) t2 = INT;
797 		}
798 
799 	ref1 = ISPTR(t1) || ISARY(t1);
800 	ref2 = ISPTR(t2) || ISARY(t2);
801 
802 	if( ref1 ^ ref2 ){
803 		if( ref1 ) q = p->in.right;
804 		else q = p->in.left;
805 		if( q->in.op != ICON || q->tn.lval != 0 ){
806 			werror( "illegal combination of pointer and integer, op %s",
807 				opst[p->in.op] );
808 			}
809 		}
810 	else if( ref1 ){
811 		if( t1 == t2 ) {
812 			if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
813 				werror( "illegal structure pointer combination" );
814 				return;
815 				}
816 			d1 = p->in.left->fn.cdim;
817 			d2 = p->in.right->fn.cdim;
818 			for( ;; ){
819 				if( ISARY(t1) ){
820 					if( dimtab[d1] != dimtab[d2] ){
821 						werror( "illegal array size combination" );
822 						return;
823 						}
824 					++d1;
825 					++d2;
826 					}
827 				else if( !ISPTR(t1) ) break;
828 				t1 = DECREF(t1);
829 				}
830 			}
831 		else
832 			werror( "illegal pointer combination" );
833 		}
834 
835 	}
836 
837 NODE *
838 stref( p ) register NODE *p; {
839 
840 	TWORD t;
841 	int d, s, dsc, align;
842 	OFFSZ off;
843 	register struct symtab *q;
844 
845 	/* make p->x */
846 	/* this is also used to reference automatic variables */
847 
848 	q = &stab[p->in.right->tn.rval];
849 	p->in.right->in.op = FREE;
850 	p->in.op = FREE;
851 	p = pconvert( p->in.left );
852 
853 	/* make p look like ptr to x */
854 
855 	if( !ISPTR(p->in.type)){
856 		p->in.type = PTR+UNIONTY;
857 		}
858 
859 	t = INCREF( q->stype );
860 	d = q->dimoff;
861 	s = q->sizoff;
862 
863 	p = makety( p, t, d, s );
864 
865 	/* compute the offset to be added */
866 
867 	off = q->offset;
868 	dsc = q->sclass;
869 
870 	if( dsc & FIELD ) {  /* normalize offset */
871 		align = ALINT;
872 		s = INT;
873 		off = (off/align)*align;
874 		}
875 	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
876 
877 	p = buildtree( UNARY MUL, p, NIL );
878 
879 	/* if field, build field info */
880 
881 	if( dsc & FIELD ){
882 		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
883 		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
884 		}
885 
886 	return( clocal(p) );
887 	}
888 
889 notlval(p) register NODE *p; {
890 
891 	/* return 0 if p an lvalue, 1 otherwise */
892 
893 	again:
894 
895 	switch( p->in.op ){
896 
897 	case FLD:
898 		p = p->in.left;
899 		goto again;
900 
901 	case UNARY MUL:
902 		/* fix the &(a=b) bug, given that a and b are structures */
903 		if( p->in.left->in.op == STASG ) return( 1 );
904 		/* and the f().a bug, given that f returns a structure */
905 		if( p->in.left->in.op == UNARY STCALL ||
906 		    p->in.left->in.op == STCALL ) return( 1 );
907 	case NAME:
908 	case OREG:
909 		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
910 	case REG:
911 		return(0);
912 
913 	default:
914 		return(1);
915 
916 		}
917 
918 	}
919 
920 NODE *
921 bcon( i ){ /* make a constant node with value i */
922 	register NODE *p;
923 
924 	p = block( ICON, NIL, NIL, INT, 0, INT );
925 	p->tn.lval = i;
926 	p->tn.rval = NONAME;
927 	return( clocal(p) );
928 	}
929 
930 NODE *
931 bpsize(p) register NODE *p; {
932 	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
933 	}
934 
935 OFFSZ
936 psize( p ) NODE *p; {
937 	/* p is a node of type pointer; psize returns the
938 	   size of the thing pointed to */
939 
940 	if( !ISPTR(p->in.type) ){
941 		uerror( "pointer required");
942 		return( SZINT );
943 		}
944 	/* note: no pointers to fields */
945 	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
946 	}
947 
948 NODE *
949 convert( p, f )  register NODE *p; {
950 	/*  convert an operand of p
951 	    f is either CVTL or CVTR
952 	    operand has type int, and is converted by the size of the other side
953 	    */
954 
955 	register NODE *q, *r;
956 
957 	q = (f==CVTL)?p->in.left:p->in.right;
958 
959 	r = block( PMCONV,
960 		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
961 	r = clocal(r);
962 	if( f == CVTL )
963 		p->in.left = r;
964 	else
965 		p->in.right = r;
966 	return(p);
967 
968 	}
969 
970 #ifndef econvert
971 econvert( p ) register NODE *p; {
972 
973 	/* change enums to ints, or appropriate types */
974 
975 	register TWORD ty;
976 
977 	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
978 		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
979 		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
980 		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
981 		else ty = LONG;
982 		ty = ctype( ty );
983 		p->fn.csiz = ty;
984 		MODTYPE(p->in.type,ty);
985 		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
986 		}
987 	}
988 #endif
989 
990 NODE *
991 pconvert( p ) register NODE *p; {
992 
993 	/* if p should be changed into a pointer, do so */
994 
995 	if( ISARY( p->in.type) ){
996 		p->in.type = DECREF( p->in.type );
997 		++p->fn.cdim;
998 		return( buildtree( UNARY AND, p, NIL ) );
999 		}
1000 	if( ISFTN( p->in.type) )
1001 		return( buildtree( UNARY AND, p, NIL ) );
1002 
1003 	return( p );
1004 	}
1005 
1006 NODE *
1007 oconvert(p) register NODE *p; {
1008 	/* convert the result itself: used for pointer and unsigned */
1009 
1010 	switch(p->in.op) {
1011 
1012 	case LE:
1013 	case LT:
1014 	case GE:
1015 	case GT:
1016 		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
1017 	case EQ:
1018 	case NE:
1019 		return( p );
1020 
1021 	case MINUS:
1022 		return(  clocal( block( PVCONV,
1023 			p, bpsize(p->in.left), INT, 0, INT ) ) );
1024 		}
1025 
1026 	cerror( "illegal oconvert: %d", p->in.op );
1027 
1028 	return(p);
1029 	}
1030 
1031 NODE *
1032 ptmatch(p)  register NODE *p; {
1033 
1034 	/* makes the operands of p agree; they are
1035 	   either pointers or integers, by this time */
1036 	/* with MINUS, the sizes must be the same */
1037 	/* with COLON, the types must be the same */
1038 
1039 	TWORD t1, t2, t;
1040 	int o, d2, d, s2, s;
1041 
1042 	o = p->in.op;
1043 	t = t1 = p->in.left->in.type;
1044 	t2 = p->in.right->in.type;
1045 	d = p->in.left->fn.cdim;
1046 	d2 = p->in.right->fn.cdim;
1047 	s = p->in.left->fn.csiz;
1048 	s2 = p->in.right->fn.csiz;
1049 
1050 	switch( o ){
1051 
1052 	case ASSIGN:
1053 	case RETURN:
1054 	case CAST:
1055 		{  break; }
1056 
1057 	case MINUS:
1058 		{  if( psize(p->in.left) != psize(p->in.right) ){
1059 			uerror( "illegal pointer subtraction");
1060 			}
1061 		   break;
1062 		   }
1063 	case COLON:
1064 		{  if( t1 != t2 ) uerror( "illegal types in :");
1065 		   break;
1066 		   }
1067 	default:  /* must work harder: relationals or comparisons */
1068 
1069 		if( !ISPTR(t1) ){
1070 			t = t2;
1071 			d = d2;
1072 			s = s2;
1073 			break;
1074 			}
1075 		if( !ISPTR(t2) ){
1076 			break;
1077 			}
1078 
1079 		/* both are pointers */
1080 		if( talign(t2,s2) < talign(t,s) ){
1081 			t = t2;
1082 			s = s2;
1083 			}
1084 		break;
1085 		}
1086 
1087 	p->in.left = makety( p->in.left, t, d, s );
1088 	p->in.right = makety( p->in.right, t, d, s );
1089 	if( o!=MINUS && !logop(o) ){
1090 
1091 		p->in.type = t;
1092 		p->fn.cdim = d;
1093 		p->fn.csiz = s;
1094 		}
1095 
1096 	return(clocal(p));
1097 	}
1098 
1099 int tdebug = 0;
1100 
1101 NODE *
1102 tymatch(p)  register NODE *p; {
1103 
1104 	/* satisfy the types of various arithmetic binary ops */
1105 
1106 	/* rules are:
1107 		if assignment, type of LHS
1108 		if any float or doubles, make double
1109 		if any longs, make long
1110 		otherwise, make int
1111 		if either operand is unsigned, the result is...
1112 	*/
1113 
1114 	register TWORD t1, t2, t, tu;
1115 	register o, u;
1116 
1117 	o = p->in.op;
1118 
1119 	t1 = p->in.left->in.type;
1120 	t2 = p->in.right->in.type;
1121 	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
1122 		uerror("void type illegal in expression");
1123 
1124 	u = 0;
1125 	if( ISUNSIGNED(t1) ){
1126 		u = 1;
1127 		t1 = DEUNSIGN(t1);
1128 		}
1129 	if( ISUNSIGNED(t2) ){
1130 		u = 1;
1131 		t2 = DEUNSIGN(t2);
1132 		}
1133 
1134 	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
1135 	if( t2 == CHAR || t2 == SHORT ) t2 = INT;
1136 
1137 #ifdef SPRECC
1138 	if( t1 == DOUBLE || t2 == DOUBLE )
1139 		t = DOUBLE;
1140 	else if( t1 == FLOAT || t2 == FLOAT )
1141 		t = FLOAT;
1142 #else
1143 	if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
1144 		t = DOUBLE;
1145 #endif
1146 	else if( t1==LONG || t2==LONG ) t = LONG;
1147 	else t = INT;
1148 
1149 #ifdef tahoe
1150 	if( asgop(o) ){
1151 #else
1152 	if( o == ASSIGN || o == CAST || o == RETURN ){
1153 #endif
1154 		tu = p->in.left->in.type;
1155 		t = t1;
1156 		}
1157 	else {
1158 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1159 		}
1160 
1161 	/* because expressions have values that are at least as wide
1162 	   as INT or UNSIGNED, the only conversions needed
1163 	   are those involving FLOAT/DOUBLE, and those
1164 	   from LONG to INT and ULONG to UNSIGNED */
1165 
1166 #ifdef tahoe
1167 	if( t != t1 )
1168 #else
1169 	if( t != t1 && ! asgop(o) )
1170 #endif
1171 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
1172 
1173 	if( t != t2 || o==CAST)
1174 		if ( tu == ENUMTY ) {/* always asgop */
1175 			p->in.right = makety( p->in.right, INT, 0, INT );
1176 			p->in.right->in.type = tu;
1177 			p->in.right->fn.cdim = p->in.left->fn.cdim;
1178 			p->in.right->fn.csiz = p->in.left->fn.csiz;
1179 			}
1180 		else
1181 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
1182 
1183 	if( asgop(o) ){
1184 		p->in.type = p->in.left->in.type;
1185 		p->fn.cdim = p->in.left->fn.cdim;
1186 		p->fn.csiz = p->in.left->fn.csiz;
1187 		}
1188 	else if( !logop(o) ){
1189 		p->in.type = tu;
1190 		p->fn.cdim = 0;
1191 		p->fn.csiz = t;
1192 		}
1193 
1194 # ifndef BUG1
1195 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1196 # endif
1197 
1198 	return(p);
1199 	}
1200 
1201 NODE *
1202 makety( p, t, d, s ) register NODE *p; TWORD t; {
1203 	/* make p into type t by inserting a conversion */
1204 
1205 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1206 	if( t == p->in.type ){
1207 		p->fn.cdim = d;
1208 		p->fn.csiz = s;
1209 		return( p );
1210 		}
1211 
1212 	if( t & TMASK ){
1213 		/* non-simple type */
1214 		return( block( PCONV, p, NIL, t, d, s ) );
1215 		}
1216 
1217 	if( p->in.op == ICON ){
1218 		if (t == DOUBLE) {
1219 			p->in.op = DCON;
1220 			if (ISUNSIGNED(p->in.type))
1221 				p->dpn.dval = (unsigned CONSZ) p->tn.lval;
1222 			else
1223 				p->dpn.dval = p->tn.lval;
1224 			p->in.type = p->fn.csiz = t;
1225 			return (clocal(p));
1226 		}
1227 		if (t == FLOAT) {
1228 			p->in.op = FCON;
1229 			if( ISUNSIGNED(p->in.type) ){
1230 				p->fpn.fval = (unsigned CONSZ) p->tn.lval;
1231 				}
1232 			else {
1233 				p->fpn.fval = p->tn.lval;
1234 				}
1235 
1236 			p->in.type = p->fn.csiz = t;
1237 			return( clocal(p) );
1238 			}
1239 		}
1240 	else if (p->in.op == FCON && t == DOUBLE) {
1241 		double db;
1242 
1243 		p->in.op = DCON;
1244 		db = p->fpn.fval;
1245 		p->dpn.dval = db;
1246 		p->in.type = p->fn.csiz = t;
1247 		return (clocal(p));
1248 	} else if (p->in.op == DCON && t == FLOAT) {
1249 		float fl;
1250 
1251 		p->in.op = FCON;
1252 		fl = p->dpn.dval;
1253 #ifdef notdef
1254 		if (fl != p->dpn.dval)
1255 			werror("float conversion loses precision");
1256 #endif
1257 		p->fpn.fval = fl;
1258 		p->in.type = p->fn.csiz = t;
1259 		return (clocal(p));
1260 	}
1261 
1262 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
1263 
1264 	}
1265 
1266 NODE *
1267 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1268 
1269 	register NODE *p;
1270 
1271 	p = talloc();
1272 	p->in.op = o;
1273 	p->in.left = l;
1274 	p->in.right = r;
1275 	p->in.type = t;
1276 	p->fn.cdim = d;
1277 	p->fn.csiz = s;
1278 	return(p);
1279 	}
1280 
1281 icons(p) register NODE *p; {
1282 	/* if p is an integer constant, return its value */
1283 	int val;
1284 
1285 	if( p->in.op != ICON ){
1286 		uerror( "constant expected");
1287 		val = 1;
1288 		}
1289 	else {
1290 		val = p->tn.lval;
1291 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1292 		}
1293 	tfree( p );
1294 	return(val);
1295 	}
1296 
1297 /* 	the intent of this table is to examine the
1298 	operators, and to check them for
1299 	correctness.
1300 
1301 	The table is searched for the op and the
1302 	modified type (where this is one of the
1303 	types INT (includes char and short), LONG,
1304 	DOUBLE (includes FLOAT), and POINTER
1305 
1306 	The default action is to make the node type integer
1307 
1308 	The actions taken include:
1309 		PUN	  check for puns
1310 		CVTL	  convert the left operand
1311 		CVTR	  convert the right operand
1312 		TYPL	  the type is determined by the left operand
1313 		TYPR	  the type is determined by the right operand
1314 		TYMATCH	  force type of left and right to match, by inserting conversions
1315 		PTMATCH	  like TYMATCH, but for pointers
1316 		LVAL	  left operand must be lval
1317 		CVTO	  convert the op
1318 		NCVT	  do not convert the operands
1319 		OTHER	  handled by code
1320 		NCVTR	  convert the left operand, not the right...
1321 
1322 	*/
1323 
1324 # define MINT 01  /* integer */
1325 # define MDBI 02   /* integer or double */
1326 # define MSTR 04  /* structure */
1327 # define MPTR 010  /* pointer */
1328 # define MPTI 020  /* pointer or integer */
1329 # define MENU 040 /* enumeration variable or member */
1330 # define MVOID 0100000 /* void type */
1331 
1332 opact( p )  NODE *p; {
1333 
1334 	register mt12, mt1, mt2, o;
1335 
1336 	mt1 = mt2 = mt12 = 0;
1337 
1338 	switch( optype(o=p->in.op) ){
1339 
1340 	case BITYPE:
1341 		mt2 = moditype( p->in.right->in.type );
1342 	case UTYPE:
1343 		mt1 = moditype( p->in.left->in.type );
1344 		break;
1345 
1346 		}
1347 
1348 	if( ((mt1 | mt2) & MVOID) &&
1349 	    o != COMOP &&
1350 	    o != COLON &&
1351 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
1352 	    !(o == CAST && (mt1 & MVOID)) ){
1353 		/* if lhs of RETURN is void, grammar will complain */
1354 		if( o != RETURN )
1355 			uerror( "value of void expression used" );
1356 		return( NCVT );
1357 		}
1358 	mt12 = mt1 & mt2;
1359 
1360 	switch( o ){
1361 
1362 	case NAME :
1363 	case STRING :
1364 	case ICON :
1365 	case FCON :
1366 	case DCON :
1367 	case CALL :
1368 	case UNARY CALL:
1369 	case UNARY MUL:
1370 		{  return( OTHER ); }
1371 	case UNARY MINUS:
1372 		if( mt1 & MENU ) return( 0 );
1373 		if( mt1 & MDBI ) return( TYPL );
1374 		break;
1375 
1376 	case COMPL:
1377 		if( mt1 & MENU ) return( 0 );
1378 		if( mt1 & MINT ) return( TYPL );
1379 		break;
1380 
1381 	case UNARY AND:
1382 		{  return( NCVT+OTHER ); }
1383 	case INIT:
1384 	case CM:
1385 		return( 0 );
1386 
1387 	case NOT:
1388 	case CBRANCH:
1389 		if( mt1 & MSTR ) break;
1390 		return( 0 );
1391 
1392 	case ANDAND:
1393 	case OROR:
1394 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
1395 		return( 0 );
1396 
1397 	case MUL:
1398 	case DIV:
1399 		if( mt12 & MDBI ) return( TYMATCH );
1400 		break;
1401 
1402 	case MOD:
1403 	case AND:
1404 	case OR:
1405 	case ER:
1406 		if( mt12 & MINT ) return( TYMATCH );
1407 		break;
1408 
1409 	case LS:
1410 	case RS:
1411 		if( mt12 & MINT ) return( TYMATCH+OTHER );
1412 		break;
1413 
1414 	case EQ:
1415 	case NE:
1416 	case LT:
1417 	case LE:
1418 	case GT:
1419 	case GE:
1420 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
1421 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
1422 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
1423 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
1424 		else break;
1425 
1426 	case QUEST:
1427 	case COMOP:
1428 		if( mt2&MENU ) return( TYPR+NCVTR );
1429 		return( TYPR );
1430 
1431 	case STREF:
1432 		return( NCVTR+OTHER );
1433 
1434 	case FORCE:
1435 		return( TYPL );
1436 
1437 	case COLON:
1438 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
1439 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
1440 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1441 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1442 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1443 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1444 		else if( mt12 == MVOID ) return( NCVT+TYPL );
1445 		break;
1446 
1447 	case ASSIGN:
1448 	case RETURN:
1449 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1450 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
1451 	case CAST:
1452 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
1453 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
1454 		else if( mt2 == MVOID &&
1455 		        ( p->in.right->in.op == CALL ||
1456 			  p->in.right->in.op == UNARY CALL)) break;
1457 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1458 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1459 		break;
1460 
1461 	case ASG LS:
1462 	case ASG RS:
1463 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1464 		break;
1465 
1466 	case ASG MUL:
1467 	case ASG DIV:
1468 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
1469 		break;
1470 
1471 	case ASG MOD:
1472 	case ASG AND:
1473 	case ASG OR:
1474 	case ASG ER:
1475 		if( mt12 & MINT ) return( LVAL+TYMATCH );
1476 		break;
1477 
1478 	case ASG PLUS:
1479 	case ASG MINUS:
1480 	case INCR:
1481 	case DECR:
1482 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
1483 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1484 		break;
1485 
1486 	case MINUS:
1487 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1488 		if( mt2 & MPTR ) break;
1489 	case PLUS:
1490 		if( mt12 & MDBI ) return( TYMATCH );
1491 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1492 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1493 
1494 		}
1495 	if( mt12 == MSTR )
1496 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1497 	else
1498 		uerror( "operands of %s have incompatible types", opst[o] );
1499 	return( NCVT );
1500 	}
1501 
1502 moditype( ty ) TWORD ty; {
1503 
1504 	switch( ty ){
1505 
1506 	case TVOID:
1507 		return( MPTR );
1508 	case UNDEF:
1509 		return( MVOID );
1510 	case ENUMTY:
1511 	case MOETY:
1512 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
1513 
1514 	case STRTY:
1515 	case UNIONTY:
1516 		return( MSTR );
1517 
1518 	case CHAR:
1519 	case SHORT:
1520 	case UCHAR:
1521 	case USHORT:
1522 		return( MINT|MPTI|MDBI );
1523 	case UNSIGNED:
1524 	case ULONG:
1525 	case INT:
1526 	case LONG:
1527 		return( MINT|MDBI|MPTI );
1528 	case FLOAT:
1529 	case DOUBLE:
1530 		return( MDBI );
1531 	default:
1532 		return( MPTR|MPTI );
1533 
1534 		}
1535 	}
1536 
1537 NODE *
1538 doszof( p )  register NODE *p; {
1539 	/* do sizeof p */
1540 	int i;
1541 
1542 	/* whatever is the meaning of this if it is a bitfield? */
1543 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1544 
1545 	tfree(p);
1546 	if( i <= 0 ) werror( "sizeof returns 0" );
1547 	return( bcon( i ) );
1548 	}
1549 
1550 # ifndef BUG2
1551 eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1552 	register ty;
1553 
1554 	*a = *b = down+1;
1555 	while( down > 1 ){
1556 		printf( "\t" );
1557 		down -= 2;
1558 		}
1559 	if( down ) printf( "    " );
1560 
1561 	ty = optype( p->in.op );
1562 
1563 	printf("%o) %s, ", p, opst[p->in.op] );
1564 	if( ty == LTYPE ){
1565 		printf( CONFMT, p->tn.lval );
1566 		printf( ", %d, ", p->tn.rval );
1567 		}
1568 	tprint( p->in.type );
1569 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1570 	}
1571 # endif
1572 
1573 #ifndef PRTDCON
1574 prtdcon( p ) register NODE *p; {
1575 	int o = p->in.op, i;
1576 
1577 	if( o == DCON || o == FCON ){
1578 		locctr( DATA );
1579 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1580 		deflab( i = getlab() );
1581 		if( o == FCON )
1582 			fincode( p->fpn.fval, SZFLOAT );
1583 		else
1584 			fincode( p->dpn.dval, SZDOUBLE );
1585 		p->tn.lval = 0;
1586 		p->tn.rval = -i;
1587 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1588 		p->in.op = NAME;
1589 		}
1590 	}
1591 #endif PRTDCON
1592 
1593 
1594 int edebug = 0;
1595 ecomp( p ) register NODE *p; {
1596 # ifndef BUG2
1597 	if( edebug ) fwalk( p, eprint, 0 );
1598 # endif
1599 	if( !reached ){
1600 		werror( "statement not reached" );
1601 		reached = 1;
1602 		}
1603 	p = optim(p);
1604 	walkf( p, prtdcon );
1605 	locctr( PROG );
1606 	ecode( p );
1607 	tfree(p);
1608 	}
1609 
1610 # ifdef STDPRTREE
1611 # ifndef ONEPASS
1612 
1613 prtree(p) register NODE *p; {
1614 
1615 	register struct symtab *q;
1616 	register ty;
1617 
1618 # ifdef MYPRTREE
1619 	MYPRTREE(p);  /* local action can be taken here; then return... */
1620 #endif
1621 
1622 	ty = optype(p->in.op);
1623 
1624 	printf( "%d\t", p->in.op );
1625 
1626 	if( ty == LTYPE ) {
1627 		printf( CONFMT, p->tn.lval );
1628 		printf( "\t" );
1629 		}
1630 	if( ty != BITYPE ) {
1631 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1632 		else printf( "%d\t", p->tn.rval );
1633 		}
1634 
1635 	printf( "%o\t", p->in.type );
1636 
1637 	/* handle special cases */
1638 
1639 	switch( p->in.op ){
1640 
1641 	case NAME:
1642 	case ICON:
1643 		/* print external name */
1644 		if( p->tn.rval == NONAME ) printf( "\n" );
1645 		else if( p->tn.rval >= 0 ){
1646 			q = &stab[p->tn.rval];
1647 			printf(  "%s\n", exname(q->sname) );
1648 			}
1649 		else { /* label */
1650 			printf( LABFMT, -p->tn.rval );
1651 			}
1652 		break;
1653 
1654 	case STARG:
1655 	case STASG:
1656 	case STCALL:
1657 	case UNARY STCALL:
1658 		/* print out size */
1659 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1660 
1661 		/* note: p->in.left not a field... */
1662 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1663 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1664 		break;
1665 
1666 	default:
1667 		printf(  "\n" );
1668 		}
1669 
1670 	if( ty != LTYPE ) prtree( p->in.left );
1671 	if( ty == BITYPE ) prtree( p->in.right );
1672 
1673 	}
1674 
1675 # else
1676 
1677 p2tree(p) register NODE *p; {
1678 	register ty;
1679 
1680 # ifdef MYP2TREE
1681 	MYP2TREE(p);  /* local action can be taken here; then return... */
1682 # endif
1683 
1684 	ty = optype(p->in.op);
1685 
1686 	switch( p->in.op ){
1687 
1688 	case NAME:
1689 	case ICON:
1690 #ifndef FLEXNAMES
1691 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1692 #else
1693 		if( p->tn.rval == NONAME ) p->in.name = "";
1694 #endif
1695 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1696 			register char *cp;
1697 			register i;
1698 			cp = exname( stab[p->tn.rval].sname );
1699 #ifndef FLEXNAMES
1700 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1701 #else
1702 			p->in.name = tstr(cp);
1703 #endif
1704 			}
1705 #ifndef FLEXNAMES
1706 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1707 #else
1708 		else {
1709 			char temp[32];
1710 			sprintf( temp, LABFMT, -p->tn.rval );
1711 			p->in.name = tstr(temp);
1712 		}
1713 #endif
1714 		break;
1715 
1716 	case STARG:
1717 	case STASG:
1718 	case STCALL:
1719 	case UNARY STCALL:
1720 		/* set up size parameters */
1721 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1722 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1723 		break;
1724 
1725 	case REG:
1726 		rbusy( p->tn.rval, p->in.type );
1727 	default:
1728 #ifndef FLEXNAMES
1729 		p->in.name[0] = '\0';
1730 #else
1731 		p->in.name = "";
1732 #endif
1733 		}
1734 
1735 	p->in.rall = NOPREF;
1736 
1737 	if( ty != LTYPE ) p2tree( p->in.left );
1738 	if( ty == BITYPE ) p2tree( p->in.right );
1739 	}
1740 
1741 # endif
1742 # endif
1743