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