|
|
1.1 ! root 1: /* ! 2: * C compiler. ! 3: * Expressions et al. ! 4: */ ! 5: #ifdef vax ! 6: #include "INC$LIB:cc0.h" ! 7: #else ! 8: #include "cc0.h" ! 9: #endif ! 10: ! 11: #define LOW 0 ! 12: #define HIGH 0177 ! 13: #define INARGS 0200 ! 14: ! 15: #define bcvint(p) bconvert((p), T_INT, NULL, NULL, NULL) ! 16: ! 17: static char csmsg1[] = "structure \"%s\" does not contain member \"%s\""; ! 18: static char csmsg2[] = "union \"%s\" does not contain member \"%s\""; ! 19: static char tclash[] = "type clash"; ! 20: ! 21: /* ! 22: * Read a tree. ! 23: * This is the top level routine that is called by the user. ! 24: * The mysterious call to "build" with opcode "NOP" is to get any function or ! 25: * array name conversions applied, even if the top of the tree is a term. ! 26: * Ditto for getting types converted to computables. ! 27: */ ! 28: TREE * ! 29: expr() ! 30: { ! 31: if (notvariant(VCPP)) { ! 32: bput(LINE); ! 33: iput((ival_t) line); ! 34: } ! 35: return (build(NOP, tree(LOW), NULL)); ! 36: } ! 37: ! 38: /* ! 39: * Read in a tree. ! 40: * The "n" argument is a firewall precedence. ! 41: * You continue reading until the precedence of the operator ! 42: * in the input is less than the priority "n". ! 43: * The "INARGS" flag is or'ed into the priority to indicate ! 44: * that the expression is an argument list, and that "," is special. ! 45: * Passing it in this unconventional way lets you pass a single ! 46: * parameter to "tree". ! 47: */ ! 48: TREE * ! 49: tree(n) ! 50: { ! 51: register TREE *lp, *rp; ! 52: register SYM *sp; ! 53: DIM *dp; ! 54: TREE *tp, *fp; ! 55: int c, d, op, p, isarray, isinargs; ! 56: ! 57: isinargs = 0; ! 58: if ((n&INARGS) != 0) { ! 59: ++isinargs; ! 60: n &= ~INARGS; ! 61: } ! 62: lp = term(); ! 63: for (;;) { ! 64: switch (s) { ! 65: ! 66: case LPAREN: ! 67: lex(); ! 68: rp = NULL; ! 69: if (s != RPAREN) ! 70: rp = tree(LOW|INARGS); ! 71: mustbe(RPAREN); ! 72: lp = build(CALL, lp, rp); ! 73: break; ! 74: ! 75: case LBRACK: ! 76: lex(); ! 77: lp = build(ADD, lp, tree(LOW)); ! 78: adjust(lp, lp->t_type, lp->t_dp, lp->t_ip); ! 79: lp = build(STAR, lp, NULL); ! 80: mustbe(RBRACK); ! 81: break; ! 82: ! 83: case DOT: ! 84: case ARROW: ! 85: lp = build((s==DOT?ADDR:NOP), lp, NULL); ! 86: if (lex() != ID) { ! 87: cerror("missing member"); ! 88: break; ! 89: } ! 90: sp = moslookup(lp); ! 91: if (bitcompat(T_PTR, tltype(lp)) == 0) ! 92: cerror("left side of \"%s\" not usable", ! 93: s==DOT?".":"->"); ! 94: if (sp==NULL || ((c=sp->s_class)!=C_MOS && c!=C_MOU)) { ! 95: cerror("member \"%s\" is not defined", id); ! 96: sp = fakedef(SL_MOS); ! 97: } else if (isvariant(VSMEMB)) ! 98: csmemb(lp, sp); ! 99: lex(); ! 100: tp = talloc(); ! 101: tp->t_op = ADD; ! 102: tp->t_lp = lp; ! 103: tp->t_rp = bicon(sp->s_value); ! 104: lp = tp; ! 105: isarray = 0; ! 106: dp = sp->s_dp; ! 107: if (dp!=NULL && dp->d_type==D_ARRAY) { ! 108: ++isarray; ! 109: dp = tdalloc(dp->d_dp, D_MOSAR, dp->d_bound); ! 110: } else ! 111: dp = tdalloc(dp, D_PTR, (sizeof_t)0); ! 112: adjust(lp, sp->s_type, dp, sp->s_ip); ! 113: if (!isarray) ! 114: lp = build(STAR, lp, NULL); ! 115: if (sp->s_width != 0) { ! 116: fp = talloc(); ! 117: fp->t_op = FIELD; ! 118: fp->t_type = lp->t_type; ! 119: fp->t_lp = lp; ! 120: fp->t_width = sp->s_width; ! 121: fp->t_base = sp->s_offset; ! 122: lp = fp; ! 123: } ! 124: break; ! 125: ! 126: case INCBEF: ! 127: case DECBEF: ! 128: op = s+INCAFT-INCBEF; ! 129: lex(); ! 130: lp = build(op, lp, bicon(1)); ! 131: break; ! 132: ! 133: default: ! 134: if ((s==COMMA && ininit!=0 && isinargs==0) ! 135: || (s==COLON)) ! 136: goto out; ! 137: if (s<MIOBASE || s>=MDOBASE) ! 138: goto out; ! 139: d = opdope[s-MIOBASE]; ! 140: if ((p=(d&PRIO)) == 0) ! 141: goto out; ! 142: if (p<n || ((d&RAS)==0 && p==n)) ! 143: goto out; ! 144: if ((op = s) == QUEST) { ! 145: lex(); ! 146: rp = tree(LOW); ! 147: mustbe(COLON); ! 148: rp = build(COLON, rp, tree(--p)); ! 149: lp = build(QUEST, lp, rp); ! 150: break; ! 151: } ! 152: if (op==COMMA && isinargs!=0) ! 153: op = ARGLST; ! 154: lex(); ! 155: lp = build(op, lp, tree(p)); ! 156: } ! 157: } ! 158: out: ! 159: return (lp); ! 160: } ! 161: ! 162: /* ! 163: * Check that a structure member is ! 164: * indeed a member of the left hand structure. ! 165: * If the member is untagged, don't object to any clash. ! 166: * The structure declaration reader sets the S_TAG bit ! 167: * in the flags word of all tagged structures. ! 168: */ ! 169: csmemb(lp, sp) ! 170: TREE *lp; ! 171: SYM *sp; ! 172: { ! 173: register INFO *ip; ! 174: register SYM *tsp; ! 175: register int type; ! 176: char *msg; ! 177: int i; ! 178: ! 179: type = lp->t_type; ! 180: if (lp->t_dp==NULL || lp->t_dp->d_type!=D_PTR ! 181: || type<T_STRUCT || type>T_FUNION) { ! 182: cstrict("potentially nonportable structure access"); ! 183: return; ! 184: } ! 185: if ((type==T_STRUCT || type==T_UNION) && (sp->s_flag&S_TAG)!=0) { ! 186: ip = lp->t_ip; ! 187: if (ip != NULL) { ! 188: for (i=0; i<ip->i_nsp && ip->i_sp[i]!=sp; ++i) ! 189: ; ! 190: if (i >= ip->i_nsp) { ! 191: tsp = taglookup(ip); ! 192: if (tsp != NULL) { ! 193: msg = csmsg1; ! 194: if (tsp->s_class == C_UTAG) ! 195: msg = csmsg2; ! 196: cstrict(msg, tsp->s_id, sp->s_id); ! 197: } ! 198: } ! 199: } ! 200: } ! 201: } ! 202: ! 203: /* ! 204: * Read a term. ! 205: * Handle all of the leaf nodes and the unary operations here. ! 206: */ ! 207: TREE * ! 208: term() ! 209: { ! 210: register TREE *tp; ! 211: register SYM *sp; ! 212: register int op; ! 213: TREE *cp; ! 214: DIM *dp; ! 215: int tt, lt, n; ! 216: ! 217: switch (op = s) { ! 218: ! 219: case ICON: ! 220: tp = bicon(ival); ! 221: tp->t_type = tval; ! 222: lex(); ! 223: break; ! 224: ! 225: case LCON: ! 226: tp = talloc(); ! 227: tp->t_op = LCON; ! 228: tp->t_type = tval; ! 229: tp->t_lval = lval; ! 230: lex(); ! 231: break; ! 232: ! 233: case DCON: ! 234: tp = talloc(); ! 235: tp->t_op = DCON; ! 236: tp->t_type = tval; ! 237: copy((char *)tp->t_dval, (char *)dval, sizeof(dval_t)); ! 238: lex(); ! 239: break; ! 240: ! 241: case STRING: ! 242: tp = bstring(); ! 243: break; ! 244: ! 245: case ID: ! 246: if ((sp=reflookup(SL_VAR)) == NULL) { ! 247: /* ! 248: * An undefined name followed by a "(" is declared ! 249: * to be a function that returns an integer. ! 250: * So says the manual. ! 251: */ ! 252: TOK *tp; ! 253: tp = idp; ! 254: if (spnextis('(')) { ! 255: setid(tp->t_id); ! 256: sp = deflookup(SL_VAR, 0); ! 257: dp = tackdim(NULL, D_FUNC, 0); ! 258: sp = declare(sp, C_CXT, T_INT, dp, NULL, 0); ! 259: } else ! 260: setid(tp->t_id); ! 261: if (sp == NULL) { ! 262: cerror("identifier \"%s\" is not defined", id); ! 263: sp = fakedef(SL_VAR); ! 264: } ! 265: } ! 266: tp = bid(sp); ! 267: lex(); ! 268: break; ! 269: ! 270: case LPAREN: ! 271: lex(); ! 272: if ((cp=cast()) != NULL) { ! 273: if (cp->t_type==T_FLOAT && cp->t_dp==NULL) ! 274: cp->t_type = T_DOUBLE; ! 275: cp->t_lp = build(NOP, tree(HIGH), NULL); ! 276: tt = tltype(cp); ! 277: lt = tltype(cp->t_lp); ! 278: if (tt == T_STRUCT) ! 279: cerror("cannot cast to structure or union"); ! 280: if (lt == T_STRUCT) ! 281: cerror("cannot cast structure or union"); ! 282: if (tt == T_PTR && isfloat(lt)) ! 283: cerror("cannot cast double to pointer"); ! 284: if (isfloat(tt) && lt == T_PTR) ! 285: cerror("cannot cast pointer to double"); ! 286: if (bitcompat(tt, lt)) { ! 287: tp = cp->t_lp; ! 288: adjust(tp, cp->t_type, cp->t_dp, cp->t_ip); ! 289: if (tp->t_op == CONVERT && tp->t_rp == NULL) ! 290: tp->t_op = CAST; ! 291: } else ! 292: tp = cp; ! 293: break; ! 294: } ! 295: n = ininit; ! 296: ininit = 0; ! 297: tp = tree(LOW); ! 298: ininit = n; ! 299: mustbe(RPAREN); ! 300: break; ! 301: ! 302: case SIZEOF: ! 303: lex(); ! 304: if (s == LPAREN) { ! 305: lex(); ! 306: if ((tp=cast()) == NULL) { ! 307: tp = tree(LOW); ! 308: mustbe(RPAREN); ! 309: } ! 310: } else ! 311: tp = tree(HIGH); ! 312: tp = build(SIZEOF, tp, NULL); ! 313: break; ! 314: ! 315: case NOT: ! 316: lex(); ! 317: tp = build(EQ, tree(HIGH), bicon(0)); ! 318: break; ! 319: ! 320: case SUB: ! 321: op = NEG; ! 322: goto unary; ! 323: case ADD: /* Unary plus == no rearrangement FIX.ME */ ! 324: lex(); ! 325: tp = tree(HIGH); /* ignored for present */ ! 326: break; ! 327: op = POS; ! 328: goto unary; ! 329: case MUL: ! 330: op = STAR; ! 331: goto unary; ! 332: case AND: ! 333: op = ADDR; ! 334: goto unary; ! 335: case COM: ! 336: unary: ! 337: lex(); ! 338: tp = build(op, tree(HIGH), NULL); ! 339: break; ! 340: ! 341: case INCBEF: ! 342: case DECBEF: ! 343: lex(); ! 344: tp = build(op, tree(HIGH), bicon(1)); ! 345: break; ! 346: ! 347: default: ! 348: cerror("error in expression syntax"); ! 349: while (s!=EOF && s!=SEMI && s!=LBRACE && s!=RBRACE) ! 350: skip(); ! 351: return (bicon(0)); ! 352: } ! 353: return (tp); ! 354: } ! 355: ! 356: /* ! 357: * Given an operator "op" and left and right subtrees "lp" and "rp", ! 358: * build a tree node, folding any constant expressions ! 359: * that can be folded, supplying any required type conversions. ! 360: * All of the conversions that are possible are added; ! 361: * the routine "transform" may remove some of them. ! 362: */ ! 363: TREE * ! 364: build(op, lp, rp) ! 365: TREE *lp; ! 366: TREE *rp; ! 367: { ! 368: TREE *tp, *gtp, gt; ! 369: DIM *dp; ! 370: int rt, lt, d, cv; ! 371: sizeof_t ll, lr; ! 372: ! 373: if (op == SIZEOF) ! 374: return (bzcon(tsize(lp))); ! 375: rt = T_NONE; ! 376: if (rp != NULL) { ! 377: chmos(rp); ! 378: rp = chfun(charray(rp)); ! 379: rt = tltype(rp); ! 380: } ! 381: chmos(lp); ! 382: lp = charray(lp); ! 383: if (op!=ADDR && op!=CALL) ! 384: lp = chfun(lp); ! 385: lt = tltype(lp); ! 386: if (op == NOP) ! 387: goto conversion; ! 388: /* ! 389: * Make sure that the operands are ! 390: * suitable as operands of the specified operation. ! 391: * Look mainly at the type, although some consideration ! 392: * is made of storage class. ! 393: */ ! 394: if ((op!=COMMA && rt==T_VOID) || ! 395: (op!=COMMA && op!=COLON && lt==T_VOID)) { ! 396: cerror("illegal operation on \"void\" type"); ! 397: lt = T_INT; ! 398: rt = T_INT; ! 399: } ! 400: if (op==ADDR && lp->t_op==REG) ! 401: cerror("cannot apply unary '&' to a register variable"); ! 402: if (op==ADDR && lp->t_op==FIELD) ! 403: cerror("cannot apply unary '&' to a bit field"); ! 404: if (op==ADDR && lp->t_op==GID && lp->t_seg==SALIEN) ! 405: cerror("cannot apply unary '&' to an alien function"); ! 406: d = opdope[op-MIOBASE]; ! 407: if ((d&RLVL) != 0 ! 408: && (lp->t_op<=DCON ! 409: || (lp->t_op>=MIOBASE && lp->t_op!=STAR && lp->t_op!=FIELD ! 410: && (lp->t_op!=CALL || lp->t_type!=T_STRUCT || lp->t_dp!=NULL) ! 411: ))) ! 412: cerror("lvalue required"); ! 413: if ((d&NFLT)!=0 && (isfloat(lt) || isfloat(rt))) ! 414: cerror("illegal use of floating point"); ! 415: if (((d&NPTL)!=0 && lt==T_PTR) || ((d&NPTR)!=0 && rt==T_PTR)) ! 416: cerror("illegal use of a pointer"); ! 417: if (((d&NSTL)!=0 && lt==T_STRUCT) || ((d&NSTR)!=0 && rt==T_STRUCT)) ! 418: cerror("illegal use of a structure or union"); ! 419: if ((d&RTOL) != 0) ! 420: truth(lp); ! 421: if ((d&RTOR) != 0) ! 422: truth(rp); ! 423: /* ! 424: * The operation may just fold away to nothing. ! 425: * If so, return a pointer to the new, constant tree node. ! 426: */ ! 427: if ((tp=fold0(op, lp, rp)) != NULL) ! 428: return (tp); ! 429: /* ! 430: * Insert conversion nodes. ! 431: */ ! 432: conversion: ! 433: gt.t_op = CONVERT; ! 434: gt.t_dp = NULL; ! 435: gt.t_ip = NULL; ! 436: switch (op) { ! 437: ! 438: case QUEST: ! 439: if (rp->t_op != COLON) ! 440: cerror("mismatched conditional"); ! 441: ! 442: case COMMA: ! 443: case ARGLST: ! 444: gt.t_type = rp->t_type; ! 445: gt.t_dp = rp->t_dp; ! 446: gt.t_ip = rp->t_ip; ! 447: break; ! 448: ! 449: case ANDAND: ! 450: case OROR: ! 451: case NOT: ! 452: gt.t_type = T_INT; ! 453: break; ! 454: ! 455: case CALL: ! 456: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_FUNC) ! 457: gt.t_dp = dp->d_dp; ! 458: else ! 459: cerror("call of non function"); ! 460: if (rp != NULL && rp->t_op != ARGLST) { ! 461: rp = build(NOP, rp, NULL); ! 462: rt = tltype(rp); ! 463: } ! 464: gt.t_type = lp->t_type; ! 465: gt.t_ip = lp->t_ip; ! 466: break; ! 467: ! 468: case STAR: ! 469: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_PTR) ! 470: gt.t_dp = dp->d_dp; ! 471: else ! 472: cerror("indirection through non pointer"); ! 473: gt.t_type = lp->t_type; ! 474: gt.t_ip = lp->t_ip; ! 475: break; ! 476: ! 477: case ADDR: ! 478: gt.t_type = lp->t_type; ! 479: gt.t_dp = tdalloc(lp->t_dp, D_PTR, (sizeof_t)0); ! 480: gt.t_ip = lp->t_ip; ! 481: break; ! 482: ! 483: default: ! 484: if (rt == T_NONE) ! 485: rt = lt; ! 486: cv = cvdope[13*(lt-T_CHAR) + rt - T_CHAR]; ! 487: if (noconvert(op, lt, rt)) ! 488: cv &= ~(CVL|CVR|CVRA|CARA); ! 489: gt.t_type = cv&GOAL; ! 490: gt.t_rp = NULL; ! 491: if ((cv&(GTL|GTR)) != 0) { ! 492: gtp = ((cv>L)!=0) ? lp : rp; ! 493: gt.t_type = gtp->t_type; ! 494: gt.t_dp = gtp->t_dp; ! 495: gt.t_ip = gtp->t_ip; ! 496: if ((cv&(CVL|CVR|CVRA)) != 0) ! 497: gt.t_rp = bzcon(psize(gtp)); ! 498: } ! 499: if (gt.t_type == T_NONE && op!=NOP && lt!=T_VOID) ! 500: cerror(tclash); ! 501: if ((d&ASGN) != 0) { ! 502: gt.t_type = lp->t_type; ! 503: gt.t_dp = lp->t_dp; ! 504: gt.t_ip = lp->t_ip; ! 505: if (gt.t_dp == NULL) { ! 506: if (gt.t_type==T_CHAR ! 507: || gt.t_type==T_UCHAR ! 508: || gt.t_type==T_SHORT ! 509: || gt.t_type==T_ENUM ! 510: || gt.t_type==T_FENUM) ! 511: gt.t_type = T_INT; ! 512: if (gt.t_type == T_USHORT) ! 513: gt.t_type = T_UINT; ! 514: if (gt.t_type == T_FLOAT) ! 515: gt.t_type = T_DOUBLE; ! 516: } ! 517: if (op==ASHL || op==ASHR) { ! 518: if (bitcompat(T_INT, rt) == 0) ! 519: rp = bcvint(rp); ! 520: } else if ((cv&CVRA) != 0) { ! 521: rp = bcvt(rp, >); ! 522: } else if ((cv&CARA) != 0) { ! 523: gt.t_op = CAST; ! 524: gt.t_rp = NULL; ! 525: rp = bcvt(rp, >); ! 526: } ! 527: } else { ! 528: if (op>=INCBEF && op<=DECAFT) ! 529: cv &= ~CVL; ! 530: if (op == COLON && lt != rt) { ! 531: if (lt == T_PTR) ! 532: if (iszero(rp)) { ! 533: gt.t_op = CAST; ! 534: gt.t_rp = NULL; ! 535: } else ! 536: cerror(tclash); ! 537: else if (rt == T_PTR) ! 538: if (iszero(lp)) { ! 539: gt.t_op = CAST; ! 540: gt.t_rp = NULL; ! 541: } else ! 542: cerror(tclash); ! 543: } ! 544: if ((cv&CVL) != 0) ! 545: lp = bcvt(lp, >); ! 546: if (op==SHL || op==SHR) { ! 547: if (bitcompat(T_INT, rt) == 0) ! 548: rp = bcvint(rp); ! 549: gt.t_type = lp->t_type; ! 550: gt.t_dp = lp->t_dp; ! 551: gt.t_ip = lp->t_ip; ! 552: } else if (rp!=NULL && (cv&CVR)!=0) ! 553: rp = bcvt(rp, >); ! 554: if ((cv&UREL)!=0 && (op>=GT && op<=LT)) ! 555: op += UGT-GT; ! 556: if (op>=EQ && op<=ULT) { ! 557: gt.t_type = T_INT; ! 558: gt.t_dp = gt.t_ip = NULL; ! 559: } ! 560: } ! 561: } ! 562: if (op==NOP) ! 563: return (lp); ! 564: tp = talloc(); ! 565: tp->t_op = op; ! 566: tp->t_type = gt.t_type; ! 567: tp->t_dp = gt.t_dp; ! 568: tp->t_ip = gt.t_ip; ! 569: tp->t_lp = lp; ! 570: tp->t_rp = rp; ! 571: if (lt==T_PTR && rt==T_PTR) { ! 572: if (op == ADD) ! 573: cerror("cannot add pointers"); ! 574: if (op == SUB) { ! 575: if ((ll=psize(lp)) != (lr=psize(rp))) ! 576: cerror("illegal subtraction of pointers"); ! 577: tp = bconvert(tp, T_INT, NULL, NULL, bzcon(ll)); ! 578: } ! 579: } ! 580: if (op==ASSIGN && lt==T_STRUCT && rt==T_STRUCT) { ! 581: notbook(); ! 582: if ((ll=tsize(lp)) != (lr=tsize(rp))) ! 583: cerror("illegal structure assignment"); ! 584: } ! 585: if (isvariant(VSPVAL) && lt != rt ! 586: && ((lt==T_PTR && !iszero(rp)) || (rt==T_PTR && !iszero(lp)))) { ! 587: if (op == ASSIGN) ! 588: cstrict("integer pointer pun"); ! 589: else if (op >= EQ && op <= ULT) ! 590: cstrict("integer pointer comparison"); ! 591: } ! 592: return (tp); ! 593: } ! 594: ! 595: /* ! 596: * If the first entry in the dimensions of tree "tp" is a ! 597: * MOS array, stomp it into the pointer it truly is. ! 598: */ ! 599: chmos(tp) ! 600: TREE *tp; ! 601: { ! 602: register struct dim *dp; ! 603: ! 604: if ((dp = tp->t_dp)!=NULL && dp->d_type==D_MOSAR) { ! 605: dp->d_type = D_PTR; ! 606: dp->d_bound = 0; ! 607: } ! 608: } ! 609: ! 610: /* ! 611: * Read constant expression. ! 612: * Call the standard expression reader, and make sure that ! 613: * the folder has squashed it down to nothing. ! 614: * Return the value. ! 615: */ ! 616: iconexpr() ! 617: { ! 618: register TREE *tp; ! 619: ! 620: tp = expr(); ! 621: while (tp->t_op == CAST || tp->t_op == CONVERT) ! 622: tp = tp->t_lp; ! 623: if (tp->t_op == ICON) ! 624: return tp->t_ival; ! 625: if (tp->t_op == LCON && (ival_t)tp->t_lval == tp->t_lval) ! 626: return tp->t_lval; ! 627: if (tp->t_op == ZCON && (ival_t)tp->t_zval == tp->t_zval) ! 628: return tp->t_zval; ! 629: cerror("int constant expression required"); ! 630: return (0); ! 631: } ! 632: ! 633: /* ! 634: * Check for floating point. ! 635: */ ! 636: isfloat(t) ! 637: register int t; ! 638: { ! 639: if (t==T_FLOAT || t==T_DOUBLE) ! 640: return (1); ! 641: return (0); ! 642: } ! 643: ! 644: /* ! 645: * Look for a constant zero of integral type. ! 646: */ ! 647: iszero(tp) ! 648: register TREE *tp; ! 649: { ! 650: register int op; ! 651: ! 652: if (tp != NULL) { ! 653: while ((op = tp->t_op) == CONVERT || op == CAST) ! 654: tp = tp->t_lp; ! 655: if (op == ICON && tp->t_ival == 0) ! 656: return (1); ! 657: if (op == LCON && tp->t_lval == 0L) ! 658: return (1); ! 659: } ! 660: return (0); ! 661: } ! 662: ! 663: /* ! 664: * Build a conversion node. ! 665: * Used by build and stat when bcvt is unsuitable. ! 666: */ ! 667: TREE * ! 668: bconvert(lp, gt, gdp, gip, rp) ! 669: TREE *lp, *rp; ! 670: DIM *gdp; ! 671: INFO *gip; ! 672: { ! 673: TREE t; ! 674: ! 675: t.t_op = CONVERT; ! 676: t.t_type = gt; ! 677: t.t_dp = gdp; ! 678: t.t_ip = gip; ! 679: t.t_rp = rp; ! 680: return (bcvt(lp, &t)); ! 681: } ! 682: ! 683: /* ! 684: * Build a conversion or cast node. ! 685: */ ! 686: TREE * ! 687: bcvt(lp, gtp) ! 688: TREE *lp, *gtp; ! 689: { ! 690: register TREE *tp; ! 691: ! 692: tp = lp; ! 693: tp = talloc(); ! 694: tp->t_op = gtp->t_op; ! 695: tp->t_type = gtp->t_type; ! 696: tp->t_dp = gtp->t_dp; ! 697: tp->t_ip = gtp->t_ip; ! 698: tp->t_lp = lp; ! 699: tp->t_rp = gtp->t_rp; ! 700: return (tp); ! 701: } ! 702: ! 703: /* ! 704: * Given a pointer to its symbol table node, ! 705: * return a pointer to the tree node for an identifier. ! 706: * Enumeration tags get changed into integer constants here. ! 707: */ ! 708: TREE * ! 709: bid(sp) ! 710: register SYM *sp; ! 711: { ! 712: register TREE *tp; ! 713: ! 714: sp->s_flag |= S_USED; ! 715: if (sp->s_class == C_MOE) ! 716: return (bicon(sp->s_value)); ! 717: tp = talloc(); ! 718: switch (sp->s_class) { ! 719: ! 720: case C_AUTO: ! 721: tp->t_op = AID; ! 722: tp->t_offs = sp->s_value; ! 723: break; ! 724: ! 725: case C_PAUTO: ! 726: tp->t_op = PID; ! 727: tp->t_offs = sp->s_value; ! 728: break; ! 729: ! 730: case C_SIN: ! 731: tp->t_op = LID; ! 732: tp->t_seg = sp->s_seg; ! 733: tp->t_label = sp->s_value; ! 734: break; ! 735: ! 736: case C_REG: ! 737: tp->t_op = REG; ! 738: tp->t_reg = sp->s_value; ! 739: break; ! 740: ! 741: case C_GDEF: ! 742: case C_GREF: ! 743: case C_CXT: ! 744: case C_SEX: ! 745: tp->t_op = GID; ! 746: tp->t_seg = sp->s_seg; ! 747: tp->t_sp = sp; ! 748: break; ! 749: ! 750: default: ! 751: cerror("identifier \"%s\" not usable", sp->s_id); ! 752: tp->t_op = ICON; ! 753: tp->t_type = T_INT; ! 754: return (tp); ! 755: } ! 756: tp->t_type = sp->s_type; ! 757: tp->t_dp = sp->s_dp; ! 758: tp->t_ip = sp->s_ip; ! 759: return (tp); ! 760: } ! 761: ! 762: /* ! 763: * Build ICON tree node. ! 764: */ ! 765: TREE * ! 766: bicon(n) ! 767: { ! 768: register TREE *tp; ! 769: ! 770: tp = talloc(); ! 771: tp->t_op = ICON; ! 772: tp->t_type = T_INT; ! 773: tp->t_ival = n; ! 774: return (tp); ! 775: } ! 776: ! 777: TREE * ! 778: bzcon(n) ! 779: sizeof_t n; ! 780: { ! 781: register TREE *tp; ! 782: ! 783: tp = talloc(); ! 784: tp->t_op = ZCON; ! 785: tp->t_type = T_UINT; ! 786: tp->t_zval = n; ! 787: return (tp); ! 788: } ! 789: ! 790: /* ! 791: * Read in a string and hide it in the string section. ! 792: * Return a pointer to a local identifier node; ! 793: * the local identifier is planted at the start of the string. ! 794: * The type of the node is set to array of char. ! 795: */ ! 796: static ! 797: TREE * ! 798: bstring() ! 799: { ! 800: register TREE *tp; ! 801: register int c, nbb, nbs; ! 802: int old, lab, adj; ! 803: char bb[11]; ! 804: ! 805: old = newseg(SSTRN); ! 806: lab = here(); ! 807: nbb = nbs = adj = 0; ! 808: again: ! 809: instring = '"'; ! 810: while ((c=getmap('\"')) >= 0) { ! 811: ++nbs; ! 812: if (nbb >= 10) { /* Leave space for NUL */ ! 813: bsflush(bb, nbb); ! 814: nbb = 0; ! 815: } ! 816: bb[nbb++] = c; ! 817: } ! 818: instring = 0; ! 819: if (lex() == STRING) { /* e.g. "Hello " "world" */ ! 820: ++adj; ! 821: goto again; ! 822: } ! 823: bb[nbb++] = 0; ! 824: bsflush(bb, nbb); ! 825: if (adj) ! 826: notbook(); ! 827: newseg(old); ! 828: tp = talloc(); ! 829: tp->t_op = LID; ! 830: tp->t_type = T_CHAR; ! 831: tp->t_dp = tdalloc(NULL, D_ARRAY, (sizeof_t)nbs+1); ! 832: tp->t_label = lab; ! 833: tp->t_seg = SSTRN; ! 834: return (tp); ! 835: } ! 836: ! 837: /* ! 838: * Dump out the string buffer. ! 839: */ ! 840: bsflush(bb, nbb) ! 841: register unsigned char *bb; ! 842: register int nbb; ! 843: { ! 844: bput(IBLOCK); ! 845: bput(nbb); ! 846: while (nbb--) ! 847: bput(*bb++); ! 848: } ! 849: ! 850: /* ! 851: * Make all the types and dims in a tree agree with the viewpoint at the top. ! 852: * This is used by casts and the code that builds up structure access trees. ! 853: */ ! 854: adjust(tp, t, dp, ip) ! 855: register TREE *tp; ! 856: register DIM *dp; ! 857: INFO *ip; ! 858: { ! 859: register int op; ! 860: ! 861: again: ! 862: tp->t_type = t; ! 863: tp->t_dp = dp; ! 864: tp->t_ip = ip; ! 865: if ((op = tp->t_op) == ADDR) { ! 866: if (dp==NULL || (dp->d_type!=D_PTR && dp->d_type!=D_MOSAR)) ! 867: return; ! 868: dp = dp->d_dp; ! 869: tp = tp->t_lp; ! 870: goto again; ! 871: } ! 872: if (op == STAR) { ! 873: dp = tdalloc(dp, D_PTR, (sizeof_t)0); ! 874: tp = tp->t_lp; ! 875: goto again; ! 876: } ! 877: if (dp!=NULL && dp->d_type==D_MOSAR) ! 878: dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0); ! 879: if (op==CAST && bitcompat(tltype(tp), tltype(tp->t_lp))) { ! 880: tp = tp->t_lp; ! 881: goto again; ! 882: } ! 883: } ! 884: ! 885: /* ! 886: * If the tree "tp" is a pointer, ! 887: * return the size of the item to which the pointer points; ! 888: * if it is not a pointer, return 1. ! 889: */ ! 890: sizeof_t psize(tp) ! 891: register TREE *tp; ! 892: { ! 893: register DIM *dp; ! 894: register sizeof_t n; ! 895: ! 896: dp = tp->t_dp; ! 897: if (dp==NULL || dp->d_type!=D_PTR) ! 898: return (1); ! 899: tp->t_dp = dp->d_dp; ! 900: n = tsize(tp); ! 901: tp->t_dp = dp; ! 902: return (n); ! 903: } ! 904: ! 905: /* ! 906: * Check if a tree has type "function returning ...". ! 907: * If it does, modify the tree to add the free "address of". ! 908: */ ! 909: TREE * ! 910: chfun(tp) ! 911: register TREE *tp; ! 912: { ! 913: register DIM *dp; ! 914: ! 915: dp = tp->t_dp; ! 916: if (dp!=NULL && dp->d_type==D_FUNC) { ! 917: tp = build(ADDR, tp, NULL); ! 918: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip); ! 919: } ! 920: return (tp); ! 921: } ! 922: ! 923: /* ! 924: * Check for arrays. ! 925: * Add the free '&' operation. ! 926: * We build the node ourselves (rather than calling build) ! 927: * to avoid a recursive call to this routine on ! 928: * a multidimensional structure. ! 929: */ ! 930: TREE * ! 931: charray(tp) ! 932: register TREE *tp; ! 933: { ! 934: register TREE *ap; ! 935: register DIM *dp; ! 936: ! 937: dp = tp->t_dp; ! 938: if (dp!=NULL && dp->d_type==D_ARRAY) { ! 939: ap = talloc(); ! 940: ap->t_op = ADDR; ! 941: ap->t_type = tp->t_type; ! 942: ap->t_dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0); ! 943: ap->t_ip = tp->t_ip; ! 944: ap->t_lp = tp; ! 945: tp = ap; ! 946: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip); ! 947: } ! 948: return (tp); ! 949: } ! 950: ! 951: /* ! 952: * Given a tree node, get a type for the tree that is ! 953: * usable for indexing into the type conversion tables. ! 954: * All non-scalars are pointers. ! 955: * All structures and unions are structures. ! 956: * All enumerations are set right. ! 957: */ ! 958: tltype(tp) ! 959: register TREE *tp; ! 960: { ! 961: register int type; ! 962: ! 963: if (tp->t_dp != NULL) ! 964: return (T_PTR); ! 965: if ((type=tp->t_type) == T_FENUM) ! 966: return (T_INT); ! 967: if (type == T_ENUM) ! 968: return (tp->t_ip->i_type); ! 969: if (type > T_VOID) ! 970: return (T_STRUCT); ! 971: return (type); ! 972: } ! 973: ! 974: /* ! 975: * Check if two linear types are "bit compatable". ! 976: */ ! 977: bitcompat(t1, t2) ! 978: { ! 979: return (noconvert(CAST, t1, t2)); ! 980: } ! 981: ! 982: /* ! 983: * Allocate a new dim structure in the tree area. ! 984: * Used to create pointers in the tree. ! 985: */ ! 986: DIM * ! 987: tdalloc(p, t, b) ! 988: DIM *p; ! 989: int t; ! 990: sizeof_t b; ! 991: { ! 992: register DIM *dp; ! 993: ! 994: dp = (struct dim *) talloc(); ! 995: dp->d_dp = p; ! 996: dp->d_type = t; ! 997: dp->d_bound = b; ! 998: return (dp); ! 999: } ! 1000: ! 1001: /* ! 1002: * Output a tree. ! 1003: */ ! 1004: tput(why, lab, tp) ! 1005: register why; ! 1006: register TREE *tp; ! 1007: { ! 1008: tp = transform(tp, why, -1); ! 1009: bput(why); ! 1010: if (why==TEXPR || why==FEXPR) ! 1011: iput((ival_t) lab); ! 1012: tput1(tp); ! 1013: } ! 1014: ! 1015: /* ! 1016: * Output a tree, part II. ! 1017: */ ! 1018: tput1(tp) ! 1019: register TREE *tp; ! 1020: { ! 1021: register int op; ! 1022: ! 1023: if (tp == NULL) { ! 1024: iput((ival_t) NIL); ! 1025: return; ! 1026: } ! 1027: op = tp->t_op; ! 1028: iput((ival_t) op); ! 1029: bput(tp->t_type); ! 1030: if (tp->t_type == BLK) ! 1031: iput((ival_t)tp->t_ip->i_size); ! 1032: switch (op) { ! 1033: ! 1034: case ICON: ! 1035: iput((ival_t) tp->t_ival); ! 1036: break; ! 1037: ! 1038: case LCON: ! 1039: lput(tp->t_lval); ! 1040: break; ! 1041: ! 1042: case ZCON: ! 1043: zput(tp->t_zval); ! 1044: break; ! 1045: ! 1046: case DCON: ! 1047: dput(tp->t_dval); /* An array */ ! 1048: break; ! 1049: ! 1050: case AID: ! 1051: case PID: ! 1052: case LID: ! 1053: case GID: ! 1054: zput(tp->t_offs); ! 1055: if (op==LID || op==GID) { ! 1056: bput(tp->t_seg); ! 1057: if (op == LID) ! 1058: iput((ival_t) tp->t_label); ! 1059: else ! 1060: nput(tp->t_sp->s_id); ! 1061: } ! 1062: break; ! 1063: ! 1064: case REG: ! 1065: iput((ival_t) tp->t_reg); ! 1066: break; ! 1067: ! 1068: case FIELD: ! 1069: bput(tp->t_width); ! 1070: bput(tp->t_base); ! 1071: tput1(tp->t_lp); ! 1072: break; ! 1073: ! 1074: default: ! 1075: tput1(tp->t_lp); ! 1076: tput1(tp->t_rp); ! 1077: } ! 1078: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.