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