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