1: #ifndef lint
2: static char *sccsid ="@(#)trees.c 4.10 (Berkeley) 1/8/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 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