xref: /csrg-svn/old/pcc/mip/trees.c (revision 32853)
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c	4.28 (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 ) return( LVAL+PTMATCH+PUN );
1462 		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
1463 		break;
1464 
1465 	case ASG LS:
1466 	case ASG RS:
1467 		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
1468 		break;
1469 
1470 	case ASG MUL:
1471 	case ASG DIV:
1472 		if( mt12 & MDBI ) return( LVAL+TYMATCH );
1473 		break;
1474 
1475 	case ASG MOD:
1476 	case ASG AND:
1477 	case ASG OR:
1478 	case ASG ER:
1479 		if( mt12 & MINT ) return( LVAL+TYMATCH );
1480 		break;
1481 
1482 	case ASG PLUS:
1483 	case ASG MINUS:
1484 	case INCR:
1485 	case DECR:
1486 		if( mt12 & MDBI ) return( TYMATCH+LVAL );
1487 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
1488 		break;
1489 
1490 	case MINUS:
1491 		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
1492 		if( mt2 & MPTR ) break;
1493 	case PLUS:
1494 		if( mt12 & MDBI ) return( TYMATCH );
1495 		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
1496 		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
1497 
1498 		}
1499 	if( mt12 == MSTR )
1500 		uerror( "%s is not a permitted struct/union operation", opst[o] );
1501 	else
1502 		uerror( "operands of %s have incompatible types", opst[o] );
1503 	return( NCVT );
1504 	}
1505 
1506 moditype( ty ) TWORD ty; {
1507 
1508 	switch( ty ){
1509 
1510 	case TVOID:
1511 		return( MPTR );
1512 	case UNDEF:
1513 		return( MVOID );
1514 	case ENUMTY:
1515 	case MOETY:
1516 		return( MENU|MINT|MDBI|MPTI );  /* enums are ints */
1517 
1518 	case STRTY:
1519 	case UNIONTY:
1520 		return( MSTR );
1521 
1522 	case CHAR:
1523 	case SHORT:
1524 	case UCHAR:
1525 	case USHORT:
1526 		return( MINT|MPTI|MDBI );
1527 	case UNSIGNED:
1528 	case ULONG:
1529 	case INT:
1530 	case LONG:
1531 		return( MINT|MDBI|MPTI );
1532 	case FLOAT:
1533 	case DOUBLE:
1534 		return( MDBI );
1535 	default:
1536 		return( MPTR|MPTI );
1537 
1538 		}
1539 	}
1540 
1541 NODE *
1542 doszof( p )  register NODE *p; {
1543 	/* do sizeof p */
1544 	int i;
1545 
1546 	/* whatever is the meaning of this if it is a bitfield? */
1547 	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
1548 
1549 	tfree(p);
1550 	if( i <= 0 ) werror( "sizeof returns 0" );
1551 	return( bcon( i ) );
1552 	}
1553 
1554 # ifndef BUG2
1555 eprint( p, down, a, b ) register NODE *p; int *a, *b; {
1556 	register ty;
1557 
1558 	*a = *b = down+1;
1559 	while( down > 1 ){
1560 		printf( "\t" );
1561 		down -= 2;
1562 		}
1563 	if( down ) printf( "    " );
1564 
1565 	ty = optype( p->in.op );
1566 
1567 	printf("%o) %s, ", p, opst[p->in.op] );
1568 	if( ty == LTYPE ){
1569 		printf( CONFMT, p->tn.lval );
1570 		printf( ", %d, ", p->tn.rval );
1571 		}
1572 	tprint( p->in.type );
1573 	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
1574 	}
1575 # endif
1576 
1577 #ifndef PRTDCON
1578 prtdcon( p ) register NODE *p; {
1579 	int o = p->in.op, i;
1580 
1581 	if( o == DCON || o == FCON ){
1582 		(void) locctr( DATA );
1583 		defalign( o == DCON ? ALDOUBLE : ALFLOAT );
1584 		deflab( i = getlab() );
1585 		if( o == FCON )
1586 			fincode( p->fpn.fval, SZFLOAT );
1587 		else
1588 			fincode( p->dpn.dval, SZDOUBLE );
1589 		p->tn.lval = 0;
1590 		p->tn.rval = -i;
1591 		p->in.type = (o == DCON ? DOUBLE : FLOAT);
1592 		p->in.op = NAME;
1593 		}
1594 	}
1595 #endif PRTDCON
1596 
1597 
1598 int edebug = 0;
1599 ecomp( p ) register NODE *p; {
1600 # ifndef BUG2
1601 	if( edebug ) fwalk( p, eprint, 0 );
1602 # endif
1603 	if( !reached ){
1604 		werror( "statement not reached" );
1605 		reached = 1;
1606 		}
1607 	p = optim(p);
1608 	walkf( p, prtdcon );
1609 	(void) locctr( PROG );
1610 	ecode( p );
1611 	tfree(p);
1612 	}
1613 
1614 # ifdef STDPRTREE
1615 # ifndef ONEPASS
1616 
1617 prtree(p) register NODE *p; {
1618 
1619 	register struct symtab *q;
1620 	register ty;
1621 
1622 # ifdef MYPRTREE
1623 	MYPRTREE(p);  /* local action can be taken here; then return... */
1624 #endif
1625 
1626 	ty = optype(p->in.op);
1627 
1628 	printf( "%d\t", p->in.op );
1629 
1630 	if( ty == LTYPE ) {
1631 		printf( CONFMT, p->tn.lval );
1632 		printf( "\t" );
1633 		}
1634 	if( ty != BITYPE ) {
1635 		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
1636 		else printf( "%d\t", p->tn.rval );
1637 		}
1638 
1639 	printf( "%o\t", p->in.type );
1640 
1641 	/* handle special cases */
1642 
1643 	switch( p->in.op ){
1644 
1645 	case NAME:
1646 	case ICON:
1647 		/* print external name */
1648 		if( p->tn.rval == NONAME ) printf( "\n" );
1649 		else if( p->tn.rval >= 0 ){
1650 			q = &stab[p->tn.rval];
1651 			printf(  "%s\n", exname(q->sname) );
1652 			}
1653 		else { /* label */
1654 			printf( LABFMT, -p->tn.rval );
1655 			}
1656 		break;
1657 
1658 	case STARG:
1659 	case STASG:
1660 	case STCALL:
1661 	case UNARY STCALL:
1662 		/* print out size */
1663 		/* use lhs size, in order to avoid hassles with the structure `.' operator */
1664 
1665 		/* note: p->in.left not a field... */
1666 		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
1667 		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
1668 		break;
1669 
1670 	default:
1671 		printf(  "\n" );
1672 		}
1673 
1674 	if( ty != LTYPE ) prtree( p->in.left );
1675 	if( ty == BITYPE ) prtree( p->in.right );
1676 
1677 	}
1678 
1679 # else
1680 
1681 p2tree(p) register NODE *p; {
1682 	register ty;
1683 
1684 # ifdef MYP2TREE
1685 	MYP2TREE(p);  /* local action can be taken here; then return... */
1686 # endif
1687 
1688 	ty = optype(p->in.op);
1689 
1690 	switch( p->in.op ){
1691 
1692 	case NAME:
1693 	case ICON:
1694 #ifndef FLEXNAMES
1695 		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
1696 #else
1697 		if( p->tn.rval == NONAME ) p->in.name = "";
1698 #endif
1699 		else if( p->tn.rval >= 0 ){ /* copy name from exname */
1700 			register char *cp;
1701 			cp = exname( stab[p->tn.rval].sname );
1702 #ifndef FLEXNAMES
1703 			{
1704 				register i;
1705 				for( i=0; i<NCHNAM; ++i )
1706 					p->in.name[i] = *cp++;
1707 			}
1708 #else
1709 			p->in.name = tstr(cp);
1710 #endif
1711 			}
1712 #ifndef FLEXNAMES
1713 		else sprintf( p->in.name, LABFMT, -p->tn.rval );
1714 #else
1715 		else {
1716 			char temp[32];
1717 			sprintf( temp, LABFMT, -p->tn.rval );
1718 			p->in.name = tstr(temp);
1719 		}
1720 #endif
1721 		break;
1722 
1723 	case STARG:
1724 	case STASG:
1725 	case STCALL:
1726 	case UNARY STCALL:
1727 		/* set up size parameters */
1728 		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
1729 		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
1730 		break;
1731 
1732 	case REG:
1733 		rbusy( p->tn.rval, p->in.type );
1734 	default:
1735 #ifndef FLEXNAMES
1736 		p->in.name[0] = '\0';
1737 #else
1738 		p->in.name = "";
1739 #endif
1740 		}
1741 
1742 	p->in.rall = NOPREF;
1743 
1744 	if( ty != LTYPE ) p2tree( p->in.left );
1745 	if( ty == BITYPE ) p2tree( p->in.right );
1746 	}
1747 
1748 # endif
1749 # endif
1750