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