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