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