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