xref: /csrg-svn/old/pcc/mip/trees.c (revision 32848)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.23 (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 	/* 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 	if( o == ASSIGN || o == CAST || o == RETURN ){
1150 		tu = p->in.left->in.type;
1151 		t = t1;
1152 		}
1153 	else {
1154 		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
1155 		}
1156 
1157 	/* because expressions have values that are at least as wide
1158 	   as INT or UNSIGNED, the only conversions needed
1159 	   are those involving FLOAT/DOUBLE, and those
1160 	   from LONG to INT and ULONG to UNSIGNED */
1161 
1162 	if( t != t1 && ! asgop(o) )
1163 		p->in.left = makety( p->in.left, tu, 0, (int)tu );
1164 
1165 	if( t != t2 || o==CAST)
1166 		if ( tu == ENUMTY ) {/* always asgop */
1167 			p->in.right = makety( p->in.right, INT, 0, INT );
1168 			p->in.right->in.type = tu;
1169 			p->in.right->fn.cdim = p->in.left->fn.cdim;
1170 			p->in.right->fn.csiz = p->in.left->fn.csiz;
1171 			}
1172 		else
1173 			p->in.right = makety( p->in.right, tu, 0, (int)tu );
1174 
1175 	if( asgop(o) ){
1176 		p->in.type = p->in.left->in.type;
1177 		p->fn.cdim = p->in.left->fn.cdim;
1178 		p->fn.csiz = p->in.left->fn.csiz;
1179 		}
1180 	else if( !logop(o) ){
1181 		p->in.type = tu;
1182 		p->fn.cdim = 0;
1183 		p->fn.csiz = t;
1184 		}
1185 
1186 # ifndef BUG1
1187 	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
1188 # endif
1189 
1190 	return(p);
1191 	}
1192 
1193 NODE *
1194 makety( p, t, d, s ) register NODE *p; TWORD t; {
1195 	/* make p into type t by inserting a conversion */
1196 
1197 	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
1198 	if( t == p->in.type ){
1199 		p->fn.cdim = d;
1200 		p->fn.csiz = s;
1201 		return( p );
1202 		}
1203 
1204 	if( t & TMASK ){
1205 		/* non-simple type */
1206 		return( block( PCONV, p, NIL, t, d, s ) );
1207 		}
1208 
1209 	if( p->in.op == ICON ){
1210 		if (t == DOUBLE) {
1211 			p->in.op = DCON;
1212 			if (ISUNSIGNED(p->in.type))
1213 				p->dpn.dval = (unsigned CONSZ) p->tn.lval;
1214 			else
1215 				p->dpn.dval = p->tn.lval;
1216 			p->in.type = p->fn.csiz = t;
1217 			return (clocal(p));
1218 		}
1219 		if (t == FLOAT) {
1220 			p->in.op = FCON;
1221 			if( ISUNSIGNED(p->in.type) ){
1222 				p->fpn.fval = (unsigned CONSZ) p->tn.lval;
1223 				}
1224 			else {
1225 				p->fpn.fval = p->tn.lval;
1226 				}
1227 
1228 			p->in.type = p->fn.csiz = t;
1229 			return( clocal(p) );
1230 			}
1231 		}
1232 	else if (p->in.op == FCON && t == DOUBLE) {
1233 		double db;
1234 
1235 		p->in.op = DCON;
1236 		db = p->fpn.fval;
1237 		p->dpn.dval = db;
1238 		p->in.type = p->fn.csiz = t;
1239 		return (clocal(p));
1240 	} else if (p->in.op == DCON && t == FLOAT) {
1241 		float fl;
1242 
1243 		p->in.op = FCON;
1244 		fl = p->dpn.dval;
1245 #ifdef notdef
1246 		if (fl != p->dpn.dval)
1247 			werror("float conversion loses precision");
1248 #endif
1249 		p->fpn.fval = fl;
1250 		p->in.type = p->fn.csiz = t;
1251 		return (clocal(p));
1252 	}
1253 
1254 	return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
1255 
1256 	}
1257 
1258 NODE *
1259 block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
1260 
1261 	register NODE *p;
1262 
1263 	p = talloc();
1264 	p->in.op = o;
1265 	p->in.left = l;
1266 	p->in.right = r;
1267 	p->in.type = t;
1268 	p->fn.cdim = d;
1269 	p->fn.csiz = s;
1270 	return(p);
1271 	}
1272 
1273 icons(p) register NODE *p; {
1274 	/* if p is an integer constant, return its value */
1275 	int val;
1276 
1277 	if( p->in.op != ICON ){
1278 		uerror( "constant expected");
1279 		val = 1;
1280 		}
1281 	else {
1282 		val = p->tn.lval;
1283 		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
1284 		}
1285 	tfree( p );
1286 	return(val);
1287 	}
1288 
1289 /* 	the intent of this table is to examine the
1290 	operators, and to check them for
1291 	correctness.
1292 
1293 	The table is searched for the op and the
1294 	modified type (where this is one of the
1295 	types INT (includes char and short), LONG,
1296 	DOUBLE (includes FLOAT), and POINTER
1297 
1298 	The default action is to make the node type integer
1299 
1300 	The actions taken include:
1301 		PUN	  check for puns
1302 		CVTL	  convert the left operand
1303 		CVTR	  convert the right operand
1304 		TYPL	  the type is determined by the left operand
1305 		TYPR	  the type is determined by the right operand
1306 		TYMATCH	  force type of left and right to match, by inserting conversions
1307 		PTMATCH	  like TYMATCH, but for pointers
1308 		LVAL	  left operand must be lval
1309 		CVTO	  convert the op
1310 		NCVT	  do not convert the operands
1311 		OTHER	  handled by code
1312 		NCVTR	  convert the left operand, not the right...
1313 
1314 	*/
1315 
1316 # define MINT 01  /* integer */
1317 # define MDBI 02   /* integer or double */
1318 # define MSTR 04  /* structure */
1319 # define MPTR 010  /* pointer */
1320 # define MPTI 020  /* pointer or integer */
1321 # define MENU 040 /* enumeration variable or member */
1322 # define MVOID 0100000 /* void type */
1323 
1324 opact( p )  NODE *p; {
1325 
1326 	register mt12, mt1, mt2, o;
1327 
1328 	mt1 = mt2 = mt12 = 0;
1329 
1330 	switch( optype(o=p->in.op) ){
1331 
1332 	case BITYPE:
1333 		mt2 = moditype( p->in.right->in.type );
1334 	case UTYPE:
1335 		mt1 = moditype( p->in.left->in.type );
1336 		break;
1337 
1338 		}
1339 
1340 	if( ((mt1 | mt2) & MVOID) &&
1341 	    o != COMOP &&
1342 	    o != COLON &&
1343 	    !(o == QUEST && (mt1 & MVOID) == 0) &&
1344 	    !(o == CAST && (mt1 & MVOID)) ){
1345 		/* if lhs of RETURN is void, grammar will complain */
1346 		if( o != RETURN )
1347 			uerror( "value of void expression used" );
1348 		return( NCVT );
1349 		}
1350 	mt12 = mt1 & mt2;
1351 
1352 	switch( o ){
1353 
1354 	case NAME :
1355 	case STRING :
1356 	case ICON :
1357 	case FCON :
1358 	case DCON :
1359 	case CALL :
1360 	case UNARY CALL:
1361 	case UNARY MUL:
1362 		{  return( OTHER ); }
1363 	case UNARY MINUS:
1364 		if( mt1 & MENU ) return( 0 );
1365 		if( mt1 & MDBI ) return( TYPL );
1366 		break;
1367 
1368 	case COMPL:
1369 		if( mt1 & MENU ) return( 0 );
1370 		if( mt1 & MINT ) return( TYPL );
1371 		break;
1372 
1373 	case UNARY AND:
1374 		{  return( NCVT+OTHER ); }
1375 	case INIT:
1376 	case CM:
1377 		return( 0 );
1378 
1379 	case NOT:
1380 	case CBRANCH:
1381 		if( mt1 & MSTR ) break;
1382 		return( 0 );
1383 
1384 	case ANDAND:
1385 	case OROR:
1386 		if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
1387 		return( 0 );
1388 
1389 	case MUL:
1390 	case DIV:
1391 		if( mt12 & MDBI ) return( TYMATCH );
1392 		break;
1393 
1394 	case MOD:
1395 	case AND:
1396 	case OR:
1397 	case ER:
1398 		if( mt12 & MINT ) return( TYMATCH );
1399 		break;
1400 
1401 	case LS:
1402 	case RS:
1403 		if( mt12 & MINT ) return( TYMATCH+OTHER );
1404 		break;
1405 
1406 	case EQ:
1407 	case NE:
1408 	case LT:
1409 	case LE:
1410 	case GT:
1411 	case GE:
1412 		if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
1413 		if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
1414 		else if( mt12 & MPTR ) return( PTMATCH+PUN );
1415 		else if( mt12 & MPTI ) return( PTMATCH+PUN );
1416 		else break;
1417 
1418 	case QUEST:
1419 	case COMOP:
1420 		if( mt2&MENU ) return( TYPR+NCVTR );
1421 		return( TYPR );
1422 
1423 	case STREF:
1424 		return( NCVTR+OTHER );
1425 
1426 	case FORCE:
1427 		return( TYPL );
1428 
1429 	case COLON:
1430 		if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
1431 		else if( mt12 & MDBI ) return( NCVT+TYMATCH );
1432 		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
1433 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
1434 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
1435 		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
1436 		else if( mt12 == MVOID ) return( NCVT+TYPL );
1437 		break;
1438 
1439 	case ASSIGN:
1440 	case RETURN:
1441 		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
1442 		else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
1443 	case CAST:
1444 		if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
1445 		else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
1446 		else if( mt2 == MVOID &&
1447 		        ( p->in.right->in.op == CALL ||
1448 			  p->in.right->in.op == UNARY CALL)) break;
1449 		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
1450 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1451 		break;
1452 
1453 	case ASG LS:
1454 	case ASG RS:
1455 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1456 		break;
1457 
1458 	case ASG MUL:
1459 	case ASG DIV:
1460 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
1461 		break;
1462 
1463 	case ASG MOD:
1464 	case ASG AND:
1465 	case ASG OR:
1466 	case ASG ER:
1467 		if( mt12 & MINT ) return( LVAL+TYMATCH );
1468 		break;
1469 
1470 	case ASG PLUS:
1471 	case ASG MINUS:
1472 	case INCR:
1473 	case DECR:
1474 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
1475 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1476 		break;
1477 
1478 	case MINUS:
1479 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1480 		if( mt2 & MPTR ) break;
1481 	case PLUS:
1482 		if( mt12 & MDBI ) return( TYMATCH );
1483 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1484 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1485 
1486 		}
1487 	if( mt12 == MSTR )
1488 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1489 	else
1490 		uerror( "operands of %s have incompatible types", opst[o] );
1491 	return( NCVT );
1492 	}
1493 
1494 moditype( ty ) TWORD ty; {
1495 
1496 	switch( ty ){
1497 
1498 	case TVOID:
1499 		return( MPTR );
1500 	case UNDEF:
1501 		return( MVOID );
1502 	case ENUMTY:
1503 	case MOETY:
1504 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
1505 
1506 	case STRTY:
1507 	case UNIONTY:
1508 		return( MSTR );
1509 
1510 	case CHAR:
1511 	case SHORT:
1512 	case UCHAR:
1513 	case USHORT:
1514 		return( MINT|MPTI|MDBI );
1515 	case UNSIGNED:
1516 	case ULONG:
1517 	case INT:
1518 	case LONG:
1519 		return( MINT|MDBI|MPTI );
1520 	case FLOAT:
1521 	case DOUBLE:
1522 		return( MDBI );
1523 	default:
1524 		return( MPTR|MPTI );
1525 
1526 		}
1527 	}
1528 
1529 NODE *
1530 doszof( p )  register NODE *p; {
1531 	/* do sizeof p */
1532 	int i;
1533 
1534 	/* whatever is the meaning of this if it is a bitfield? */
1535 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1536 
1537 	tfree(p);
1538 	if( i <= 0 ) werror( "sizeof returns 0" );
1539 	return( bcon( i ) );
1540 	}
1541 
1542 # ifndef BUG2
1543 eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1544 	register ty;
1545 
1546 	*a = *b = down+1;
1547 	while( down > 1 ){
1548 		printf( "\t" );
1549 		down -= 2;
1550 		}
1551 	if( down ) printf( "    " );
1552 
1553 	ty = optype( p->in.op );
1554 
1555 	printf("%o) %s, ", p, opst[p->in.op] );
1556 	if( ty == LTYPE ){
1557 		printf( CONFMT, p->tn.lval );
1558 		printf( ", %d, ", p->tn.rval );
1559 		}
1560 	tprint( p->in.type );
1561 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1562 	}
1563 # endif
1564 
1565 prtdcon( p ) register NODE *p; {
1566 	int o = p->in.op, i;
1567 
1568 	if( o == DCON || o == FCON ){
1569 		locctr( DATA );
1570 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1571 		deflab( i = getlab() );
1572 		if( o == FCON )
1573 			fincode( p->fpn.fval, SZFLOAT );
1574 		else
1575 			fincode( p->dpn.dval, SZDOUBLE );
1576 		p->tn.lval = 0;
1577 		p->tn.rval = -i;
1578 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1579 		p->in.op = NAME;
1580 		}
1581 	}
1582 
1583 
1584 int edebug = 0;
1585 ecomp( p ) register NODE *p; {
1586 # ifndef BUG2
1587 	if( edebug ) fwalk( p, eprint, 0 );
1588 # endif
1589 	if( !reached ){
1590 		werror( "statement not reached" );
1591 		reached = 1;
1592 		}
1593 	p = optim(p);
1594 	walkf( p, prtdcon );
1595 	locctr( PROG );
1596 	ecode( p );
1597 	tfree(p);
1598 	}
1599 
1600 # ifdef STDPRTREE
1601 # ifndef ONEPASS
1602 
1603 prtree(p) register NODE *p; {
1604 
1605 	register struct symtab *q;
1606 	register ty;
1607 
1608 # ifdef MYPRTREE
1609 	MYPRTREE(p);  /* local action can be taken here; then return... */
1610 #endif
1611 
1612 	ty = optype(p->in.op);
1613 
1614 	printf( "%d\t", p->in.op );
1615 
1616 	if( ty == LTYPE ) {
1617 		printf( CONFMT, p->tn.lval );
1618 		printf( "\t" );
1619 		}
1620 	if( ty != BITYPE ) {
1621 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1622 		else printf( "%d\t", p->tn.rval );
1623 		}
1624 
1625 	printf( "%o\t", p->in.type );
1626 
1627 	/* handle special cases */
1628 
1629 	switch( p->in.op ){
1630 
1631 	case NAME:
1632 	case ICON:
1633 		/* print external name */
1634 		if( p->tn.rval == NONAME ) printf( "\n" );
1635 		else if( p->tn.rval >= 0 ){
1636 			q = &stab[p->tn.rval];
1637 			printf(  "%s\n", exname(q->sname) );
1638 			}
1639 		else { /* label */
1640 			printf( LABFMT, -p->tn.rval );
1641 			}
1642 		break;
1643 
1644 	case STARG:
1645 	case STASG:
1646 	case STCALL:
1647 	case UNARY STCALL:
1648 		/* print out size */
1649 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1650 
1651 		/* note: p->in.left not a field... */
1652 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1653 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1654 		break;
1655 
1656 	default:
1657 		printf(  "\n" );
1658 		}
1659 
1660 	if( ty != LTYPE ) prtree( p->in.left );
1661 	if( ty == BITYPE ) prtree( p->in.right );
1662 
1663 	}
1664 
1665 # else
1666 
1667 p2tree(p) register NODE *p; {
1668 	register ty;
1669 
1670 # ifdef MYP2TREE
1671 	MYP2TREE(p);  /* local action can be taken here; then return... */
1672 # endif
1673 
1674 	ty = optype(p->in.op);
1675 
1676 	switch( p->in.op ){
1677 
1678 	case NAME:
1679 	case ICON:
1680 #ifndef FLEXNAMES
1681 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1682 #else
1683 		if( p->tn.rval == NONAME ) p->in.name = "";
1684 #endif
1685 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1686 			register char *cp;
1687 			register i;
1688 			cp = exname( stab[p->tn.rval].sname );
1689 #ifndef FLEXNAMES
1690 			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
1691 #else
1692 			p->in.name = tstr(cp);
1693 #endif
1694 			}
1695 #ifndef FLEXNAMES
1696 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1697 #else
1698 		else {
1699 			char temp[32];
1700 			sprintf( temp, LABFMT, -p->tn.rval );
1701 			p->in.name = tstr(temp);
1702 		}
1703 #endif
1704 		break;
1705 
1706 	case STARG:
1707 	case STASG:
1708 	case STCALL:
1709 	case UNARY STCALL:
1710 		/* set up size parameters */
1711 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1712 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1713 		break;
1714 
1715 	case REG:
1716 		rbusy( p->tn.rval, p->in.type );
1717 	default:
1718 #ifndef FLEXNAMES
1719 		p->in.name[0] = '\0';
1720 #else
1721 		p->in.name = "";
1722 #endif
1723 		}
1724 
1725 	p->in.rall = NOPREF;
1726 
1727 	if( ty != LTYPE ) p2tree( p->in.left );
1728 	if( ty == BITYPE ) p2tree( p->in.right );
1729 	}
1730 
1731 # endif
1732 # endif
1733