|
|
1.1 ! root 1: /* ! 2: * C compiler ! 3: */ ! 4: ! 5: #include "c0.h" ! 6: ! 7: /* ! 8: * Called from tree, this routine takes the top 1, 2, or 3 ! 9: * operands on the expression stack, makes a new node with ! 10: * the operator op, and puts it on the stack. ! 11: * Essentially all the work is in inserting ! 12: * appropriate conversions. ! 13: */ ! 14: build(op) ! 15: { ! 16: register int t1; ! 17: int t2, t; ! 18: register union tree *p1, *p2, *p3; ! 19: int dope, leftc, cvn, pcvn; ! 20: ! 21: /* ! 22: * a[i] => *(a+i) ! 23: */ ! 24: if (op==LBRACK) { ! 25: build(PLUS); ! 26: op = STAR; ! 27: } ! 28: dope = opdope[op]; ! 29: t2 = INT; ! 30: if ((dope&BINARY)!=0) { ! 31: p2 = chkfun(disarray(*--cp)); ! 32: if (p2) ! 33: t2 = p2->t.type; ! 34: } ! 35: p1 = *--cp; ! 36: /* ! 37: * sizeof gets turned into a number here. ! 38: */ ! 39: if (op==SIZEOF) { ! 40: p1 = cblock(length(p1)); ! 41: p1->c.type = UNSIGN; ! 42: *cp++ = p1; ! 43: return; ! 44: } ! 45: if (op!=AMPER) { ! 46: p1 = disarray(p1); ! 47: if (op!=CALL) ! 48: p1 = chkfun(p1); ! 49: } ! 50: t1 = p1->t.type; ! 51: if (t1==CHAR) ! 52: t1 = INT; ! 53: else if (t1==UNCHAR) ! 54: t1 = UNSIGN; ! 55: if (t2==CHAR) ! 56: t2 = INT; ! 57: else if (t2==UNCHAR) ! 58: t2 = UNSIGN; ! 59: pcvn = 0; ! 60: t = INT; ! 61: switch (op) { ! 62: ! 63: case CAST: ! 64: if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY) ! 65: error("Disallowed conversion"); ! 66: if (p1->t.type==UNCHAR) { ! 67: *cp++ = block(ETYPE, UNSIGN, (int *)NULL, (union str *)NULL, ! 68: TNULL, TNULL); ! 69: *cp++ = p2; ! 70: build(CAST); ! 71: *cp++ = cblock(0377); ! 72: build(AND); ! 73: return; ! 74: } ! 75: if (p2->t.type==CHAR || p2->t.type==UNCHAR) ! 76: p2 = block(PLUS, t2, (int *)NULL, (union str *)NULL, ! 77: p2, cblock(0)); ! 78: break; ! 79: ! 80: /* end of expression */ ! 81: case 0: ! 82: *cp++ = p1; ! 83: return; ! 84: ! 85: /* no-conversion operators */ ! 86: case QUEST: ! 87: if (p2->t.op!=COLON) ! 88: error("Illegal conditional"); ! 89: else ! 90: if (fold(QUEST, p1, p2)) ! 91: return; ! 92: ! 93: case SEQNC: ! 94: t = t2; ! 95: ! 96: case COMMA: ! 97: case LOGAND: ! 98: case LOGOR: ! 99: *cp++ = block(op, t, p2->t.subsp, p2->t.strp, p1, p2); ! 100: return; ! 101: ! 102: case EXCLA: ! 103: t1 = INT; ! 104: break; ! 105: ! 106: case CALL: ! 107: if ((t1&XTYPE) != FUNC) ! 108: error("Call of non-function"); ! 109: *cp++ = block(CALL,decref(t1),p1->t.subsp,p1->t.strp,p1,p2); ! 110: return; ! 111: ! 112: case STAR: ! 113: if ((t1&XTYPE) == FUNC) ! 114: error("Illegal indirection"); ! 115: *cp++ = block(STAR, decref(t1), p1->t.subsp, p1->t.strp, p1, TNULL); ! 116: return; ! 117: ! 118: case AMPER: ! 119: if (p1->t.op==NAME || p1->t.op==STAR) { ! 120: *cp++ = block(op,incref(p1->t.type),p1->t.subsp,p1->t.strp,p1,TNULL); ! 121: return; ! 122: } ! 123: error("Illegal lvalue"); ! 124: break; ! 125: ! 126: /* ! 127: * a.b goes to (&a)->b ! 128: */ ! 129: case DOT: ! 130: if (p1->t.op==CALL && t1==STRUCT) { ! 131: t1 = incref(t1); ! 132: setype(p1, t1, p1); ! 133: } else { ! 134: *cp++ = p1; ! 135: build(AMPER); ! 136: p1 = *--cp; ! 137: } ! 138: ! 139: /* ! 140: * In a->b, a is given the type ptr-to-structure element; ! 141: * then the offset is added in without conversion; ! 142: * then * is tacked on to access the member. ! 143: */ ! 144: case ARROW: ! 145: if (p2->t.op!=NAME || p2->t.tr1->n.hclass!=MOS) { ! 146: error("Illegal structure ref"); ! 147: *cp++ = p1; ! 148: return; ! 149: } ! 150: p2 = structident(p1, p2); ! 151: t2 = p2->n.htype; ! 152: if (t2==INT && p2->t.tr1->n.hflag&FFIELD) ! 153: t2 = UNSIGN; ! 154: t = incref(t2); ! 155: chkw(p1, -1); ! 156: setype(p1, t, p2); ! 157: *cp++ = block(PLUS, t, p2->t.subsp, p2->t.strp, ! 158: p1, cblock(p2->t.tr1->n.hoffset)); ! 159: build(STAR); ! 160: if (p2->t.tr1->n.hflag&FFIELD) ! 161: *cp++ = block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL, ! 162: *--cp, p2->t.tr1->n.hstrp); ! 163: return; ! 164: } ! 165: if ((dope&LVALUE)!=0) ! 166: chklval(p1); ! 167: if ((dope&LWORD)!=0) ! 168: chkw(p1, LONG); ! 169: if ((dope&RWORD)!=0) ! 170: chkw(p2, LONG); ! 171: if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) { ! 172: error("Illegal use of void object"); ! 173: t = t1 = t2 = INT; ! 174: } ! 175: if ((dope&BINARY)==0) { ! 176: if (op==ITOF) ! 177: t1 = DOUBLE; ! 178: else if (op==FTOI) ! 179: t1 = INT; ! 180: if (!fold(op, p1, (union tree *)NULL)) ! 181: *cp++ = block(op, t1, p1->t.subsp, p1->t.strp, p1,TNULL); ! 182: return; ! 183: } ! 184: cvn = 0; ! 185: if (t1==STRUCT || t2==STRUCT) { ! 186: if (t1!=t2 || p1->t.strp != p2->t.strp) ! 187: error("Incompatible structures"); ! 188: cvn = 0; ! 189: } else ! 190: cvn = cvtab[lintyp(t1)][lintyp(t2)]; ! 191: leftc = (cvn>>4)&017; ! 192: cvn &= 017; ! 193: t = leftc? t2:t1; ! 194: if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN)) ! 195: t = UNSIGN; ! 196: if (dope&ASSGOP || op==CAST) { ! 197: if (leftc && (op>=ASPLUS && op<=ASXOR)) { ! 198: assignop(op, p1, p2); ! 199: return; ! 200: } ! 201: t = t1; ! 202: if (op==ASSIGN) { ! 203: if (cvn==PTI) { ! 204: if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->t.strp!=p2->t.strp)) { ! 205: error("Warning: mixed pointer assignment"); ! 206: nerror--; ! 207: } ! 208: cvn = leftc = 0; ! 209: } ! 210: } else if (op==CAST) { ! 211: if (cvn==ITP||cvn==PTI) ! 212: cvn = leftc = 0; ! 213: else if (cvn==LTP) { ! 214: if (leftc==0) ! 215: cvn = LTI; ! 216: else { ! 217: cvn = ITL; ! 218: leftc = 0; ! 219: } ! 220: } ! 221: } ! 222: if (leftc) ! 223: cvn = leftc; ! 224: leftc = 0; ! 225: } else if (op==COLON || op==MAX || op==MIN) { ! 226: if (t1>=PTR && t1==t2) ! 227: cvn = 0; ! 228: if (op!=COLON && (t1>=PTR || t2>=PTR)) ! 229: op += MAXP-MAX; ! 230: } else if (dope&RELAT) { ! 231: if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t2==UNSIGN) ! 232: && (t==INT||t==CHAR||t==UNSIGN))) ! 233: op += LESSEQP-LESSEQ; ! 234: if (cvn==ITP || cvn==PTI) ! 235: cvn = 0; ! 236: } ! 237: if (cvn==PTI) { ! 238: cvn = 0; ! 239: if (op==MINUS) { ! 240: pcvn++; ! 241: p1 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, TNULL); ! 242: p2 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, TNULL); ! 243: t = LONG; ! 244: } else { ! 245: if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR))) ! 246: cvn = XX; ! 247: } ! 248: } ! 249: if (cvn) { ! 250: if ((cvn==ITP || cvn==LTP) && (opdope[op]&PCVOK)==0) { ! 251: p3 = leftc? p1: p2; ! 252: if ((p3->t.op!=CON || p3->c.value!=0) ! 253: && (p3->t.op!=LCON || p3->l.lvalue!=0)) ! 254: cvn = XX; ! 255: else ! 256: cvn = 0; ! 257: } ! 258: t1 = plength(p1); ! 259: t2 = plength(p2); ! 260: if (cvn==XX || (cvn==PTI&&t1!=t2)) ! 261: error("Illegal conversion"); ! 262: else if (leftc) ! 263: p1 = convert(p1, t, cvn, t2); ! 264: else ! 265: p2 = convert(p2, t, cvn, t1); ! 266: } ! 267: if (dope&RELAT) ! 268: t = INT; ! 269: if (t==FLOAT) ! 270: t = DOUBLE; ! 271: if (t==CHAR) ! 272: t = INT; ! 273: if (op==CAST) { ! 274: if (t!=DOUBLE && (t!=INT || p2->t.type!=CHAR || p2->t.type!=UNCHAR)) { ! 275: p2->t.type = t; ! 276: p2->t.subsp = p1->t.subsp; ! 277: p2->t.strp = p1->t.strp; ! 278: } ! 279: if (t==INT && p1->t.type==CHAR) ! 280: p2 = block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, TNULL); ! 281: *cp++ = p2; ! 282: return; ! 283: } ! 284: if (pcvn) ! 285: t2 = plength(p1->t.tr1); ! 286: if (fold(op, p1, p2)==0) { ! 287: p3 = leftc?p2:p1; ! 288: *cp++ = block(op, t, p3->t.subsp, p3->t.strp, p1, p2); ! 289: } ! 290: if (pcvn) { ! 291: p1 = *--cp; ! 292: *cp++ = convert(p1, 0, PTI, t2); ! 293: } ! 294: } ! 295: ! 296: union tree * ! 297: structident(p1, p2) ! 298: register union tree *p1, *p2; ! 299: { ! 300: register struct nmlist *np; ! 301: int vartypes = 0, namesame = 1; ! 302: ! 303: np = (struct nmlist *)p2->t.tr1; ! 304: for (;;) { ! 305: if (namesame && p1->t.type==STRUCT+PTR && p1->t.strp == np->sparent) { ! 306: p2->t.type = np->htype; ! 307: p2->t.strp = np->hstrp; ! 308: p2->t.subsp = np->hsubsp; ! 309: p2->t.tr1 = (union tree *)np; ! 310: return(p2); ! 311: } ! 312: np = np->nextnm; ! 313: if (np==NULL) ! 314: break; ! 315: namesame = 0; ! 316: if (strncmp(p2->t.tr1->n.name, np->name, NCPS) != 0) ! 317: continue; ! 318: if ((p2->t.tr1->n.hflag&FKIND) != (np->hflag&FMOS)) ! 319: continue; ! 320: namesame = 1; ! 321: if (p2->t.tr1->n.htype==np->htype && p2->t.tr1->n.hoffset==np->hoffset) ! 322: continue; ! 323: vartypes++; ! 324: } ! 325: if (vartypes) ! 326: error("Ambiguous structure reference for %.8s", p2->t.tr1->n.name); ! 327: else { ! 328: error("Warning: %.8s not member of cited struct/union", p2->t.tr1->n.name); ! 329: nerror--; ! 330: } ! 331: return(p2); ! 332: } ! 333: ! 334: /* ! 335: * Generate the appropriate conversion operator. ! 336: */ ! 337: union tree * ! 338: convert(p, t, cvn, len) ! 339: union tree *p; ! 340: { ! 341: register int op; ! 342: ! 343: if (cvn==0) ! 344: return(p); ! 345: op = cvntab[cvn]; ! 346: if (opdope[op]&BINARY) { ! 347: if (len==0) ! 348: error("Illegal conversion"); ! 349: return(block(op, t, (int *)NULL, (union str *)NULL, p, cblock(len))); ! 350: } ! 351: return(block(op, t, (int *)NULL, (union str *)NULL, p, TNULL)); ! 352: } ! 353: ! 354: /* ! 355: * Traverse an expression tree, adjust things ! 356: * so the types of things in it are consistent ! 357: * with the view that its top node has ! 358: * type at. ! 359: * Used with structure references. ! 360: */ ! 361: setype(p, t, newp) ! 362: register union tree *p, *newp; ! 363: register t; ! 364: { ! 365: for (;; p = p->t.tr1) { ! 366: p->t.subsp = newp->t.subsp; ! 367: p->t.strp = newp->t.strp; ! 368: p->t.type = t; ! 369: if (p->t.op==AMPER) ! 370: t = decref(t); ! 371: else if (p->t.op==STAR) ! 372: t = incref(t); ! 373: else if (p->t.op!=PLUS) ! 374: break; ! 375: } ! 376: } ! 377: ! 378: /* ! 379: * A mention of a function name is turned into ! 380: * a pointer to that function. ! 381: */ ! 382: union tree * ! 383: chkfun(p) ! 384: register union tree *p; ! 385: { ! 386: register int t; ! 387: ! 388: if (((t = p->t.type)&XTYPE)==FUNC && p->t.op!=ETYPE) ! 389: return(block(AMPER,incref(t),p->t.subsp,p->t.strp,p,TNULL)); ! 390: return(p); ! 391: } ! 392: ! 393: /* ! 394: * A mention of an array is turned into ! 395: * a pointer to the base of the array. ! 396: */ ! 397: union tree * ! 398: disarray(p) ! 399: register union tree *p; ! 400: { ! 401: register int t; ! 402: ! 403: if (p==NULL) ! 404: return(p); ! 405: /* check array & not MOS and not typer */ ! 406: if (((t = p->t.type)&XTYPE)!=ARRAY ! 407: || p->t.op==NAME && p->t.tr1->n.hclass==MOS ! 408: || p->t.op==ETYPE) ! 409: return(p); ! 410: p->t.subsp++; ! 411: *cp++ = p; ! 412: setype(p, decref(t), p); ! 413: build(AMPER); ! 414: return(*--cp); ! 415: } ! 416: ! 417: /* ! 418: * make sure that p is a ptr to a node ! 419: * with type int or char or 'okt.' ! 420: * okt might be nonexistent or 'long' ! 421: * (e.g. for <<). ! 422: */ ! 423: chkw(p, okt) ! 424: union tree *p; ! 425: { ! 426: register int t; ! 427: ! 428: if ((t=p->t.type)!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt) ! 429: error("Illegal type of operand"); ! 430: return; ! 431: } ! 432: ! 433: /* ! 434: *'linearize' a type for looking up in the ! 435: * conversion table ! 436: */ ! 437: lintyp(t) ! 438: { ! 439: switch(t) { ! 440: ! 441: case INT: ! 442: case CHAR: ! 443: case UNSIGN: ! 444: case UNCHAR: ! 445: return(0); ! 446: ! 447: case FLOAT: ! 448: case DOUBLE: ! 449: return(1); ! 450: ! 451: case LONG: ! 452: return(2); ! 453: ! 454: default: ! 455: return(3); ! 456: } ! 457: } ! 458: ! 459: /* ! 460: * Report an error. ! 461: */ ! 462: /* VARARGS1 */ ! 463: error(s, p1, p2, p3, p4, p5, p6) ! 464: char *s; ! 465: { ! 466: nerror++; ! 467: if (filename[0]) ! 468: fprintf(stderr, "%s:", filename); ! 469: fprintf(stderr, "%d: ", line); ! 470: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); ! 471: fprintf(stderr, "\n"); ! 472: } ! 473: ! 474: /* ! 475: * Generate a node in an expression tree, ! 476: * setting the operator, type, dimen/struct table ptrs, ! 477: * and the operands. ! 478: */ ! 479: union tree * ! 480: block(op, t, subs, str, p1,p2) ! 481: int *subs; ! 482: union str *str; ! 483: union tree *p1, *p2; ! 484: { ! 485: register union tree *p; ! 486: ! 487: p = (union tree *)Tblock(sizeof(struct tnode)); ! 488: p->t.op = op; ! 489: p->t.type = t; ! 490: p->t.subsp = subs; ! 491: p->t.strp = str; ! 492: p->t.tr1 = p1; ! 493: if (opdope[op]&BINARY) ! 494: p->t.tr2 = p2; ! 495: else ! 496: p->t.tr2 = NULL; ! 497: return(p); ! 498: } ! 499: ! 500: union tree * ! 501: nblock(ds) ! 502: register struct nmlist *ds; ! 503: { ! 504: return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, (union tree *)ds, TNULL)); ! 505: } ! 506: ! 507: /* ! 508: * Generate a block for a constant ! 509: */ ! 510: union tree * ! 511: cblock(v) ! 512: { ! 513: register union tree *p; ! 514: ! 515: p = (union tree *)Tblock(sizeof(struct cnode)); ! 516: p->c.op = CON; ! 517: p->c.type = INT; ! 518: p->c.subsp = NULL; ! 519: p->c.strp = NULL; ! 520: p->c.value = v; ! 521: return(p); ! 522: } ! 523: ! 524: /* ! 525: * A block for a float constant ! 526: */ ! 527: union tree * ! 528: fblock(t, string) ! 529: char *string; ! 530: { ! 531: register union tree *p; ! 532: ! 533: p = (union tree *)Tblock(sizeof(struct fnode)); ! 534: p->f.op = FCON; ! 535: p->f.type = t; ! 536: p->f.subsp = NULL; ! 537: p->f.strp = NULL; ! 538: p->f.cstr = string; ! 539: return(p); ! 540: } ! 541: ! 542: /* ! 543: * Assign a block for use in the ! 544: * expression tree. ! 545: */ ! 546: char * ! 547: Tblock(n) ! 548: { ! 549: register char *p; ! 550: ! 551: p = treebase; ! 552: if (p==NULL) { ! 553: error("c0 internal error: tree not active"); ! 554: exit(1); ! 555: } ! 556: if ((treebase += n) >= coremax) { ! 557: if (sbrk(1024) == (char *)-1) { ! 558: error("Out of space"); ! 559: exit(1); ! 560: } ! 561: coremax += 1024; ! 562: } ! 563: return(p); ! 564: } ! 565: ! 566: char * ! 567: starttree() ! 568: { ! 569: register char *st; ! 570: ! 571: st = treebase; ! 572: if (st==NULL) ! 573: treebot = treebase = locbase+DCLSLOP; ! 574: return(st); ! 575: } ! 576: ! 577: endtree(tp) ! 578: char *tp; ! 579: { ! 580: treebase = tp; ! 581: if (tp==NULL) ! 582: treebot = NULL; ! 583: } ! 584: ! 585: /* ! 586: * Assign a block for use in a declaration ! 587: */ ! 588: char * ! 589: Dblock(n) ! 590: { ! 591: register char *p; ! 592: ! 593: p = locbase; ! 594: locbase += n; ! 595: if (treebot && locbase > treebot) { ! 596: error("Too much declaring in an expression"); ! 597: exit(1); ! 598: } ! 599: if (locbase > coremax) { ! 600: if (sbrk(1024) == (char *)-1) { ! 601: error("out of space"); ! 602: exit(1); ! 603: } ! 604: coremax += 1024; ! 605: } ! 606: return(p); ! 607: } ! 608: ! 609: /* ! 610: * Check that a tree can be used as an lvalue. ! 611: */ ! 612: chklval(p) ! 613: register union tree *p; ! 614: { ! 615: if (p->t.op==FSEL) ! 616: p = p->t.tr1; ! 617: if (p->t.op!=NAME && p->t.op!=STAR) ! 618: error("Lvalue required"); ! 619: } ! 620: ! 621: /* ! 622: * reduce some forms of `constant op constant' ! 623: * to a constant. More of this is done in the next pass ! 624: * but this is used to allow constant expressions ! 625: * to be used in switches and array bounds. ! 626: */ ! 627: fold(op, p1, p2) ! 628: register union tree *p1; ! 629: union tree *p2; ! 630: { ! 631: register int v1, v2; ! 632: int unsignf; ! 633: ! 634: if (p1->t.op!=CON) ! 635: return(0); ! 636: unsignf = p1->c.type==UNSIGN; ! 637: if (op==QUEST) { ! 638: if (p2->t.tr1->t.op==CON && p2->t.tr2->t.op==CON) { ! 639: p1->c.value = p1->c.value? p2->t.tr1->c.value: p2->t.tr2->c.value; ! 640: *cp++ = p1; ! 641: p1->t.type = p2->t.type; ! 642: return(1); ! 643: } ! 644: return(0); ! 645: } ! 646: if (p2) { ! 647: if (p2->t.op!=CON) ! 648: return(0); ! 649: v2 = p2->c.value; ! 650: unsignf |= p2->c.type==UNSIGN; ! 651: } ! 652: v1 = p1->c.value; ! 653: switch (op) { ! 654: ! 655: case PLUS: ! 656: v1 += v2; ! 657: break; ! 658: ! 659: case MINUS: ! 660: v1 -= v2; ! 661: break; ! 662: ! 663: case TIMES: ! 664: v1 *= v2; ! 665: break; ! 666: ! 667: case DIVIDE: ! 668: if (v2==0) ! 669: goto divchk; ! 670: if (unsignf) { ! 671: if (v2==1) ! 672: break; ! 673: if (v2<0) { ! 674: v1 = (unsigned)v1 >= (unsigned)v2; ! 675: break; ! 676: } ! 677: v1 = (unsigned)v1 / v2; ! 678: break; ! 679: } ! 680: v1 /= v2; ! 681: break; ! 682: ! 683: case MOD: ! 684: if (v2==0) ! 685: goto divchk; ! 686: if (unsignf) { ! 687: if (v2==1) { ! 688: v1 = 0; ! 689: break; ! 690: } ! 691: if (v2<0) { ! 692: if ((unsigned)v1 >= (unsigned)v2) ! 693: v1 -= v2; ! 694: break; ! 695: } ! 696: v1 = (unsigned)v1 % v2; ! 697: break; ! 698: } ! 699: v1 %= v2; ! 700: break; ! 701: ! 702: case AND: ! 703: v1 &= v2; ! 704: break; ! 705: ! 706: case OR: ! 707: v1 |= v2; ! 708: break; ! 709: ! 710: case EXOR: ! 711: v1 ^= v2; ! 712: break; ! 713: ! 714: case NEG: ! 715: v1 = - v1; ! 716: break; ! 717: ! 718: case COMPL: ! 719: v1 = ~ v1; ! 720: break; ! 721: ! 722: case LSHIFT: ! 723: v1 <<= v2; ! 724: break; ! 725: ! 726: case RSHIFT: ! 727: if (unsignf) { ! 728: v1 = (unsigned)v1 >> v2; ! 729: break; ! 730: } ! 731: v1 >>= v2; ! 732: break; ! 733: ! 734: case EQUAL: ! 735: v1 = v1==v2; ! 736: break; ! 737: ! 738: case NEQUAL: ! 739: v1 = v1!=v2; ! 740: break; ! 741: ! 742: case LESS: ! 743: v1 = v1<v2; ! 744: break; ! 745: ! 746: case GREAT: ! 747: v1 = v1>v2; ! 748: break; ! 749: ! 750: case LESSEQ: ! 751: v1 = v1<=v2; ! 752: break; ! 753: ! 754: case GREATEQ: ! 755: v1 = v1>=v2; ! 756: break; ! 757: ! 758: divchk: ! 759: error("Divide check"); ! 760: nerror--; ! 761: default: ! 762: return(0); ! 763: } ! 764: p1->c.value = v1; ! 765: *cp++ = p1; ! 766: if (unsignf) ! 767: p1->t.type = UNSIGN; ! 768: return(1); ! 769: } ! 770: ! 771: /* ! 772: * Compile an expression expected to have constant value, ! 773: * for example an array bound or a case value. ! 774: */ ! 775: conexp() ! 776: { ! 777: register union tree *t; ! 778: ! 779: initflg++; ! 780: if (t = tree(1)) ! 781: if (t->t.op != CON) ! 782: error("Constant required"); ! 783: initflg--; ! 784: return(t->c.value); ! 785: } ! 786: ! 787: /* ! 788: * Handle peculiar assignment ops that need a temporary. ! 789: */ ! 790: assignop(op, p1, p2) ! 791: register union tree *p1, *p2; ! 792: { ! 793: register struct nmlist *np; ! 794: ! 795: op += PLUS - ASPLUS; ! 796: if (p1->t.op==NAME) { ! 797: *cp++ = p1; ! 798: *cp++ = p1; ! 799: *cp++ = p2; ! 800: build(op); ! 801: build(ASSIGN); ! 802: return; ! 803: } ! 804: np = gentemp(incref(p1->t.type)); ! 805: *cp++ = nblock(np); ! 806: *cp++ = p1; ! 807: build(AMPER); ! 808: build(ASSIGN); ! 809: *cp++ = nblock(np); ! 810: build(STAR); ! 811: *cp++ = nblock(np); ! 812: build(STAR); ! 813: *cp++ = p2; ! 814: build(op); ! 815: build(ASSIGN); ! 816: build(SEQNC); ! 817: } ! 818: ! 819: /* ! 820: * Generate an automatic temporary for ! 821: * use in certain assignment ops ! 822: */ ! 823: struct nmlist * ! 824: gentemp(type) ! 825: { ! 826: register struct nmlist *tp; ! 827: ! 828: tp = (struct nmlist *)Tblock(sizeof(struct nmlist)); ! 829: tp->hclass = AUTO; ! 830: tp->htype = type; ! 831: tp->hflag = 0; ! 832: tp->hsubsp = NULL; ! 833: tp->hstrp = NULL; ! 834: tp->hblklev = blklev; ! 835: autolen -= rlength((union tree *)tp); ! 836: tp->hoffset = autolen; ! 837: if (autolen < maxauto) ! 838: maxauto = autolen; ! 839: return(tp); ! 840: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.