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