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