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