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