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: /* 94: * Bug fix, because copying type is not enough, 95: * i.e. t = (t, t) + 1; 96: * Original code was: 97: * case SEQNC: 98: * t = t2; 99: * case COMMA: 100: */ 101: case SEQNC: 102: *cp++ = block(op, t2, p2->t.subsp, p2->t.strp, p1, p2); 103: return; 104: 105: case COMMA: 106: case LOGAND: 107: case LOGOR: 108: *cp++ = block(op, t, p2->t.subsp, p2->t.strp, p1, p2); 109: return; 110: 111: case EXCLA: 112: t1 = INT; 113: break; 114: 115: case CALL: 116: if ((t1&XTYPE) == PTR && (decref(t1)&XTYPE) == FUNC) { 117: /* 118: * Modification to allow calling a function via a 119: * pointer to a function ("f") without explicitly 120: * dereferencing the pointer. That is: f(...) is now 121: * legal as well as (*f)(...). The insistence that 122: * decref(t1) be FUNC prevents pointers to pointers to 123: * functions and so on from being automatically 124: * dereferenced which would be incorrect and introduce 125: * porting problems. Note that for purity FUNC's 126: * should really always be referenced (as in pcc) and 127: * that the new notation is actually more consistent 128: * with the rest of C ... 129: */ 130: *cp++ = p1; 131: build(STAR); 132: *cp++ = p2; 133: build(CALL); 134: return; 135: } 136: if ((t1&XTYPE) != FUNC) 137: error("Call of non-function"); 138: *cp++ = block(CALL,decref(t1),p1->t.subsp,p1->t.strp,p1,p2); 139: return; 140: 141: case STAR: 142: if ((t1&XTYPE) == FUNC) 143: error("Illegal indirection"); 144: *cp++ = block(STAR, decref(t1), p1->t.subsp, p1->t.strp, p1, TNULL); 145: return; 146: 147: case AMPER: 148: if (p1->t.op==NAME || p1->t.op==STAR) { 149: *cp++ = block(op,incref(p1->t.type),p1->t.subsp,p1->t.strp,p1,TNULL); 150: return; 151: } 152: error("Illegal lvalue"); 153: break; 154: 155: /* 156: * a.b goes to (&a)->b 157: */ 158: case DOT: 159: if (p1->t.op==CALL && t1==STRUCT) { 160: t1 = incref(t1); 161: setype(p1, t1, p1); 162: } else { 163: *cp++ = p1; 164: build(AMPER); 165: p1 = *--cp; 166: } 167: 168: /* 169: * In a->b, a is given the type ptr-to-structure element; 170: * then the offset is added in without conversion; 171: * then * is tacked on to access the member. 172: */ 173: case ARROW: 174: if (p2->t.op!=NAME || p2->t.tr1->n.hclass!=MOS) { 175: error("Illegal structure ref"); 176: *cp++ = p1; 177: return; 178: } 179: p2 = structident(p1, p2); 180: t2 = p2->n.htype; 181: if (t2==INT && p2->t.tr1->n.hflag&FFIELD) 182: t2 = UNSIGN; 183: t = incref(t2); 184: chkw(p1, -1); 185: setype(p1, t, p2); 186: *cp++ = block(PLUS, t, p2->t.subsp, p2->t.strp, 187: p1, cblock(p2->t.tr1->n.hoffset)); 188: build(STAR); 189: if (p2->t.tr1->n.hflag&FFIELD) 190: *cp++ = block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL, 191: *--cp, p2->t.tr1->n.hstrp); 192: return; 193: } 194: if ((dope&LVALUE)!=0) 195: chklval(p1); 196: if ((dope&LWORD)!=0) 197: chkw(p1, LONG); 198: if ((dope&RWORD)!=0) 199: chkw(p2, LONG); 200: if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) { 201: error("Illegal use of void object"); 202: t = t1 = t2 = INT; 203: } 204: if ((dope&BINARY)==0) { 205: if (op==ITOF) 206: t1 = DOUBLE; 207: else if (op==FTOI) 208: t1 = INT; 209: if (!fold(op, p1, (union tree *)NULL)) 210: *cp++ = block(op, t1, p1->t.subsp, p1->t.strp, p1,TNULL); 211: return; 212: } 213: cvn = 0; 214: if (t1==STRUCT || t2==STRUCT) { 215: if (t1!=t2 || p1->t.strp != p2->t.strp) 216: error("Incompatible structures"); 217: cvn = 0; 218: } else 219: cvn = cvtab[lintyp(t1)][lintyp(t2)]; 220: leftc = (cvn>>4)&017; 221: cvn &= 017; 222: t = leftc? t2:t1; 223: if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN)) 224: t = UNSIGN; 225: if (dope&ASSGOP || op==CAST) { 226: /* 227: * Weird "lhs op= rhs" requiring a temporary to evaluate as 228: * "lhs = lhs op rhs" so lhs can be converted up for the 229: * operation and then the result converted back down for 230: * the assignment. As a special sub case, "(int) op= (long)" 231: * doesn't require a temporary except for /= and %= ... 232: */ 233: if (leftc && op>=ASPLUS && op<=ASXOR 234: && (leftc!=LTI || op==ASDIV || op==ASMOD)) { 235: assignop(op, p1, p2); 236: return; 237: } 238: t = t1; 239: if (op==ASSIGN) { 240: if (cvn==PTI) { 241: if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->t.strp!=p2->t.strp)) 242: werror("mixed pointer assignment"); 243: cvn = leftc = 0; 244: } if ((cvn==ITP || cvn==LTP) 245: && (p2->t.op!=CON || p2->c.value!=0) 246: && (p2->t.op!=LCON || p2->l.lvalue!=0)) { 247: /* 248: * Allow "i = p" and "p = i" with a warning, where 249: * i is some form of integer (not 0) and p is a 250: * pointer. Note that in both this patch and the 251: * similar one for "?:" below, code from the CAST 252: * immediately below and the illegal conversion 253: * check farther below is simply stolen. It would 254: * require either a recursive call to build or a 255: * fairly large rewrite to eliminate the 256: * duplication. 257: */ 258: werror("illegal combination of pointer and integer, op ="); 259: if (cvn==ITP) 260: cvn = leftc = 0; 261: else 262: if (leftc==0) 263: cvn = LTI; 264: else { 265: cvn = ITL; 266: leftc = 0; 267: } 268: } 269: } else if (op==CAST) { 270: if (cvn==ITP||cvn==PTI) 271: cvn = leftc = 0; 272: else if (cvn==LTP) { 273: if (leftc==0) 274: cvn = LTI; 275: else { 276: cvn = ITL; 277: leftc = 0; 278: } 279: } 280: } 281: if (leftc) 282: cvn = leftc; 283: leftc = 0; 284: } else if (op==COLON || op==MAX || op==MIN) { 285: if (t1>=PTR && t1==t2) 286: cvn = 0; 287: if (op!=COLON && (t1>=PTR || t2>=PTR)) 288: op += MAXP-MAX; 289: /* 290: * Allow "e ? i : p" and "e ? p : i" with warning. 291: */ 292: if (op==COLON && (cvn==ITP || cvn==LTP)) { 293: p3 = leftc? p1: p2; 294: if ((p3->t.op!=CON || p3->c.value!=0) 295: && (p3->t.op!=LCON || p3->l.lvalue!=0)) { 296: werror("illegal combination of pointer and integer, op :"); 297: if (cvn==ITP) 298: cvn = leftc = 0; 299: else 300: if (leftc==0) 301: cvn = LTI; 302: else { 303: cvn = ITL; 304: leftc = 0; 305: } 306: } 307: } 308: } else if (dope&RELAT) { 309: if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t1==UNLONG||t2==UNSIGN||t2==UNLONG) 310: && (t==INT||t==CHAR||t==UNSIGN||t==UNLONG))) 311: op += LESSEQP-LESSEQ; 312: if (cvn==ITP || cvn==PTI) 313: cvn = 0; 314: } 315: if (cvn==PTI) { 316: cvn = 0; 317: if (op==MINUS) { 318: pcvn++; 319: p1 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, TNULL); 320: p2 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, TNULL); 321: t = LONG; 322: } else { 323: if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR))) 324: cvn = XX; 325: } 326: } 327: if (cvn) { 328: if ((cvn==ITP || cvn==LTP) && (opdope[op]&PCVOK)==0) { 329: p3 = leftc? p1: p2; 330: if ((p3->t.op!=CON || p3->c.value!=0) 331: && (p3->t.op!=LCON || p3->l.lvalue!=0)) 332: cvn = XX; 333: else 334: cvn = 0; 335: } 336: t1 = plength(p1); 337: t2 = plength(p2); 338: if (cvn==XX || (cvn==PTI&&t1!=t2)) 339: error("Illegal conversion"); 340: else if (leftc) 341: p1 = convert(p1, t, cvn, t2); 342: else 343: p2 = convert(p2, t, cvn, t1); 344: } 345: if (dope&RELAT) 346: t = INT; 347: if (t==FLOAT) 348: t = DOUBLE; 349: if (t==CHAR) 350: t = INT; 351: if (op==CAST) { 352: if (t!=DOUBLE && (t!=INT || p2->t.type!=CHAR || p2->t.type!=UNCHAR)) { 353: p2->t.type = t; 354: p2->t.subsp = p1->t.subsp; 355: p2->t.strp = p1->t.strp; 356: } 357: if (t==INT && p1->t.type==CHAR) 358: p2 = block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, TNULL); 359: *cp++ = p2; 360: return; 361: } 362: if (pcvn) 363: t2 = plength(p1->t.tr1); 364: if (fold(op, p1, p2)==0) { 365: p3 = leftc?p2:p1; 366: *cp++ = block(op, t, p3->t.subsp, p3->t.strp, p1, p2); 367: } 368: if (pcvn) { 369: p1 = *--cp; 370: *cp++ = convert(p1, 0, PTI, t2); 371: } 372: } 373: 374: union tree * 375: structident(p1, p2) 376: register union tree *p1, *p2; 377: { 378: register struct nmlist *np; 379: int vartypes = 0, namesame = 1; 380: 381: np = (struct nmlist *)p2->t.tr1; 382: for (;;) { 383: if (namesame && p1->t.type==STRUCT+PTR && p1->t.strp == np->sparent) { 384: p2->t.type = np->htype; 385: p2->t.strp = np->hstrp; 386: p2->t.subsp = np->hsubsp; 387: p2->t.tr1 = (union tree *)np; 388: return(p2); 389: } 390: np = np->nextnm; 391: if (np==NULL) 392: break; 393: namesame = 0; 394: if (strcmp(p2->t.tr1->n.name, np->name) != 0) 395: continue; 396: if ((p2->t.tr1->n.hflag&FKIND) != (np->hflag&FMOS)) 397: continue; 398: namesame = 1; 399: if (p2->t.tr1->n.htype==np->htype && p2->t.tr1->n.hoffset==np->hoffset) 400: continue; 401: vartypes++; 402: } 403: if (vartypes) 404: error("Ambiguous structure reference for %s",p2->t.tr1->n.name); 405: else 406: werror("%s not member of cited struct/union",p2->t.tr1->n.name); 407: return(p2); 408: } 409: 410: /* 411: * Generate the appropriate conversion operator. 412: */ 413: union tree * 414: convert(p, t, cvn, len) 415: union tree *p; 416: { 417: register int op; 418: 419: if (cvn==0) 420: return(p); 421: op = cvntab[cvn]; 422: if (opdope[op]&BINARY) { 423: if (len==0) 424: error("Illegal conversion"); 425: return(block(op, t, (int *)NULL, (union str *)NULL, p, cblock(len))); 426: } 427: return(block(op, t, (int *)NULL, (union str *)NULL, p, TNULL)); 428: } 429: 430: /* 431: * Traverse an expression tree, adjust things 432: * so the types of things in it are consistent 433: * with the view that its top node has 434: * type at. 435: * Used with structure references. 436: */ 437: setype(p, t, newp) 438: register union tree *p, *newp; 439: register t; 440: { 441: for (;; p = p->t.tr1) { 442: p->t.subsp = newp->t.subsp; 443: p->t.strp = newp->t.strp; 444: p->t.type = t; 445: if (p->t.op==AMPER) 446: t = decref(t); 447: else if (p->t.op==STAR) 448: t = incref(t); 449: else if (p->t.op!=PLUS) 450: break; 451: } 452: } 453: 454: /* 455: * A mention of a function name is turned into 456: * a pointer to that function. 457: */ 458: union tree * 459: chkfun(p) 460: register union tree *p; 461: { 462: register int t; 463: 464: if (((t = p->t.type)&XTYPE)==FUNC && p->t.op!=ETYPE) 465: return(block(AMPER,incref(t),p->t.subsp,p->t.strp,p,TNULL)); 466: return(p); 467: } 468: 469: /* 470: * A mention of an array is turned into 471: * a pointer to the base of the array. 472: */ 473: union tree * 474: disarray(p) 475: register union tree *p; 476: { 477: register int t; 478: 479: if (p==NULL) 480: return(p); 481: /* check array & not MOS and not typer */ 482: if (((t = p->t.type)&XTYPE)!=ARRAY 483: || p->t.op==NAME && p->t.tr1->n.hclass==MOS 484: || p->t.op==ETYPE) 485: return(p); 486: p->t.subsp++; 487: *cp++ = p; 488: setype(p, decref(t), p); 489: build(AMPER); 490: return(*--cp); 491: } 492: 493: /* 494: * make sure that p is a ptr to a node 495: * with type int or char or 'okt.' 496: * okt might be nonexistent or 'long' 497: * (e.g. for <<). 498: */ 499: chkw(p, okt) 500: union tree *p; 501: { 502: register int t = p->t.type; 503: 504: if (t == UNLONG) 505: t = LONG; 506: if (t!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt) 507: error("Illegal type of operand"); 508: return; 509: } 510: 511: /* 512: *'linearize' a type for looking up in the 513: * conversion table 514: */ 515: lintyp(t) 516: { 517: switch(t) { 518: 519: case INT: 520: case CHAR: 521: case UNSIGN: 522: case UNCHAR: 523: return(0); 524: 525: case FLOAT: 526: case DOUBLE: 527: return(1); 528: 529: case UNLONG: 530: case LONG: 531: return(2); 532: 533: default: 534: return(3); 535: } 536: } 537: 538: /* 539: * Report an error. 540: */ 541: 542: extern int Wflag = 0; /* Non-zero means do not print warnings */ 543: 544: /* VARARGS1 */ 545: werror(s, p1, p2, p3, p4, p5, p6) 546: char *s; 547: { 548: if (Wflag) 549: return; 550: if (filename[0]) 551: fprintf(stderr, "%s:", filename); 552: fprintf(stderr, "%d: warning: ", line); 553: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); 554: fprintf(stderr, "\n"); 555: } 556: 557: /* VARARGS1 */ 558: error(s, p1, p2, p3, p4, p5, p6) 559: char *s; 560: { 561: nerror++; 562: if (filename[0]) 563: fprintf(stderr, "%s:", filename); 564: fprintf(stderr, "%d: ", line); 565: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); 566: fprintf(stderr, "\n"); 567: } 568: 569: /* 570: * Generate a node in an expression tree, 571: * setting the operator, type, dimen/struct table ptrs, 572: * and the operands. 573: */ 574: union tree * 575: block(op, t, subs, str, p1,p2) 576: int *subs; 577: union str *str; 578: union tree *p1, *p2; 579: { 580: register union tree *p; 581: 582: p = (union tree *)Tblock(sizeof(struct tnode)); 583: p->t.op = op; 584: p->t.type = t; 585: p->t.subsp = subs; 586: p->t.strp = str; 587: p->t.tr1 = p1; 588: if (opdope[op]&BINARY) 589: p->t.tr2 = p2; 590: else 591: p->t.tr2 = NULL; 592: return(p); 593: } 594: 595: union tree * 596: nblock(ds) 597: register struct nmlist *ds; 598: { 599: return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, (union tree *)ds, TNULL)); 600: } 601: 602: /* 603: * Generate a block for a constant 604: */ 605: union tree * 606: cblock(v) 607: { 608: register union tree *p; 609: 610: p = (union tree *)Tblock(sizeof(struct cnode)); 611: p->c.op = CON; 612: p->c.type = INT; 613: p->c.subsp = NULL; 614: p->c.strp = NULL; 615: p->c.value = v; 616: return(p); 617: } 618: 619: /* 620: * A block for a float constant 621: */ 622: union tree * 623: fblock(t, string) 624: char *string; 625: { 626: register union tree *p; 627: 628: p = (union tree *)Tblock(sizeof(struct fnode)); 629: p->f.op = FCON; 630: p->f.type = t; 631: p->f.subsp = NULL; 632: p->f.strp = NULL; 633: p->f.cstr = string; 634: return(p); 635: } 636: 637: /* 638: * Assign a block for use in the 639: * expression tree. 640: */ 641: char * 642: Tblock(n) 643: { 644: register char *p; 645: 646: p = treebase; 647: if (p==NULL) { 648: error("c0 internal error: Tblock"); 649: exit(1); 650: } 651: if ((treebase += n) >= coremax) { 652: if (sbrk(1024) == (char *)-1) { 653: error("Out of space"); 654: exit(1); 655: } 656: coremax += 1024; 657: } 658: return(p); 659: } 660: 661: char * 662: starttree() 663: { 664: register char *st; 665: 666: st = treebase; 667: if (st==NULL) 668: treebot = treebase = locbase+DCLSLOP; 669: return(st); 670: } 671: 672: endtree(tp) 673: char *tp; 674: { 675: treebase = tp; 676: if (tp==NULL) 677: treebot = NULL; 678: } 679: 680: /* 681: * Assign a block for use in a declaration 682: */ 683: char * 684: Dblock(n) 685: { 686: register char *p; 687: 688: p = locbase; 689: locbase += n; 690: if (treebot && locbase > treebot) { 691: error("Too much declaring in an expression"); 692: exit(1); 693: } 694: if (locbase > coremax) { 695: if (sbrk(1024) == (char *)-1) { 696: error("out of space"); 697: exit(1); 698: } 699: coremax += 1024; 700: } 701: return(p); 702: } 703: 704: /* 705: * Check that a tree can be used as an lvalue. 706: */ 707: chklval(p) 708: register union tree *p; 709: { 710: if (p->t.op==FSEL) 711: p = p->t.tr1; 712: if (p->t.op!=NAME && p->t.op!=STAR) 713: error("Lvalue required"); 714: } 715: 716: /* 717: * reduce some forms of `constant op constant' 718: * to a constant. More of this is done in the next pass 719: * but this is used to allow constant expressions 720: * to be used in switches and array bounds. 721: */ 722: fold(op, p1, p2) 723: register union tree *p1; 724: union tree *p2; 725: { 726: register int v1, v2; 727: int unsignf; 728: 729: if (p1->t.op!=CON) 730: return(0); 731: unsignf = p1->c.type==UNSIGN; 732: unsignf |= p1->c.type==UNLONG; 733: if (op==QUEST) { 734: if (p2->t.tr1->t.op==CON && p2->t.tr2->t.op==CON) { 735: p1->c.value = p1->c.value? p2->t.tr1->c.value: p2->t.tr2->c.value; 736: *cp++ = p1; 737: p1->t.type = p2->t.type; 738: return(1); 739: } 740: return(0); 741: } 742: if (p2) { 743: if (p2->t.op!=CON) 744: return(0); 745: v2 = p2->c.value; 746: unsignf |= p2->c.type==UNSIGN; 747: unsignf |= p2->c.type==UNLONG; 748: } 749: v1 = p1->c.value; 750: switch (op) { 751: 752: case PLUS: 753: v1 += v2; 754: break; 755: 756: case MINUS: 757: v1 -= v2; 758: break; 759: 760: case TIMES: 761: v1 *= v2; 762: break; 763: 764: case DIVIDE: 765: if (v2==0) 766: goto divchk; 767: if (unsignf) { 768: if (v2==1) 769: break; 770: if (v2<0) { 771: v1 = (unsigned)v1 >= (unsigned)v2; 772: break; 773: } 774: v1 = (unsigned)v1 / v2; 775: break; 776: } 777: v1 /= v2; 778: break; 779: 780: case MOD: 781: if (v2==0) 782: goto divchk; 783: if (unsignf) { 784: if (v2==1) { 785: v1 = 0; 786: break; 787: } 788: if (v2<0) { 789: if ((unsigned)v1 >= (unsigned)v2) 790: v1 -= v2; 791: break; 792: } 793: v1 = (unsigned)v1 % v2; 794: break; 795: } 796: v1 %= v2; 797: break; 798: 799: case AND: 800: v1 &= v2; 801: break; 802: 803: case OR: 804: v1 |= v2; 805: break; 806: 807: case EXOR: 808: v1 ^= v2; 809: break; 810: 811: case NEG: 812: v1 = - v1; 813: break; 814: 815: case COMPL: 816: v1 = ~ v1; 817: break; 818: 819: case LSHIFT: 820: v1 <<= v2; 821: break; 822: 823: case RSHIFT: 824: if (unsignf) { 825: v1 = (unsigned)v1 >> v2; 826: break; 827: } 828: v1 >>= v2; 829: break; 830: 831: case EQUAL: 832: v1 = v1==v2; 833: break; 834: 835: case NEQUAL: 836: v1 = v1!=v2; 837: break; 838: 839: case LESS: 840: v1 = v1<v2; 841: break; 842: 843: case GREAT: 844: v1 = v1>v2; 845: break; 846: 847: case LESSEQ: 848: v1 = v1<=v2; 849: break; 850: 851: case GREATEQ: 852: v1 = v1>=v2; 853: break; 854: 855: case LESSP: 856: v1 = (unsigned)v1<v2; 857: break; 858: 859: case GREATP: 860: v1 = (unsigned)v1>v2; 861: break; 862: 863: case LESSEQP: 864: v1 = (unsigned)v1<=v2; 865: break; 866: 867: case GREATQP: 868: v1 = (unsigned)v1>=v2; 869: break; 870: 871: divchk: 872: error("Divide check"); 873: nerror--; 874: default: 875: return(0); 876: } 877: p1->c.value = v1; 878: *cp++ = p1; 879: if (unsignf) 880: p1->t.type = UNSIGN; 881: return(1); 882: } 883: 884: /* 885: * Compile an expression expected to have constant value, 886: * for example an array bound or a case value. 887: */ 888: conexp() 889: { 890: register union tree *t; 891: 892: initflg++; 893: if (t = tree(1)) 894: if (t->t.op != CON) 895: error("Constant required"); 896: initflg--; 897: return(t->c.value); 898: } 899: 900: /* 901: * Handle peculiar assignment ops that need a temporary. 902: */ 903: assignop(op, p1, p2) 904: register union tree *p1, *p2; 905: { 906: register struct nmlist *np; 907: 908: op += PLUS - ASPLUS; 909: if (p1->t.op==NAME) { 910: *cp++ = p1; 911: *cp++ = p1; 912: *cp++ = p2; 913: build(op); 914: build(ASSIGN); 915: return; 916: } 917: np = gentemp(incref(p1->t.type)); 918: *cp++ = nblock(np); 919: *cp++ = p1; 920: build(AMPER); 921: build(ASSIGN); 922: *cp++ = nblock(np); 923: build(STAR); 924: *cp++ = nblock(np); 925: build(STAR); 926: *cp++ = p2; 927: build(op); 928: build(ASSIGN); 929: build(SEQNC); 930: } 931: 932: /* 933: * Generate an automatic temporary for 934: * use in certain assignment ops 935: */ 936: struct nmlist * 937: gentemp(type) 938: { 939: register struct nmlist *tp; 940: 941: tp = (struct nmlist *)Tblock(sizeof(struct nmlist)); 942: tp->hclass = AUTO; 943: tp->htype = type; 944: tp->hflag = 0; 945: tp->hsubsp = NULL; 946: tp->hstrp = NULL; 947: tp->hblklev = blklev; 948: autolen -= rlength((union tree *)tp); 949: tp->hoffset = autolen; 950: if (autolen < maxauto) 951: maxauto = autolen; 952: return(tp); 953: }