|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: # ! 3: /* ! 4: * pi - Pascal interpreter code translator ! 5: * ! 6: * Charles Haley, Bill Joy UCB ! 7: * Version 1.2 Novmeber 1978 ! 8: */ ! 9: ! 10: #include "whoami" ! 11: #include "0.h" ! 12: #include "tree.h" ! 13: #include "opcode.h" ! 14: ! 15: extern char *opnames[]; ! 16: /* ! 17: * Rvalue - an expression. ! 18: * ! 19: * Contype is the type that the caller would prefer, nand is important ! 20: * if constant sets or constant strings are involved, the latter ! 21: * because of string padding. ! 22: */ ! 23: struct nl * ! 24: rvalue(r, contype) ! 25: int *r; ! 26: struct nl *contype; ! 27: { ! 28: register struct nl *p, *p1; ! 29: register struct nl *q; ! 30: int c, c1, *rt, w, g; ! 31: char *cp, *cp1, *opname; ! 32: long l; ! 33: double f; ! 34: ! 35: if (r == NIL) ! 36: return (NIL); ! 37: if (nowexp(r)) ! 38: return (NIL); ! 39: /* ! 40: * Pick up the name of the operation ! 41: * for future error messages. ! 42: */ ! 43: if (r[0] <= T_IN) ! 44: opname = opnames[r[0]]; ! 45: ! 46: /* ! 47: * The root of the tree tells us what sort of expression we have. ! 48: */ ! 49: switch (r[0]) { ! 50: ! 51: /* ! 52: * The constant nil ! 53: */ ! 54: case T_NIL: ! 55: put2(O_CON2, 0); ! 56: return (nl+TNIL); ! 57: ! 58: /* ! 59: * Function call with arguments. ! 60: */ ! 61: case T_FCALL: ! 62: return (funccod(r)); ! 63: ! 64: case T_VAR: ! 65: p = lookup(r[2]); ! 66: if (p == NIL || p->class == BADUSE) ! 67: return (NIL); ! 68: switch (p->class) { ! 69: case VAR: ! 70: /* ! 71: * If a variable is ! 72: * qualified then get ! 73: * the rvalue by a ! 74: * lvalue and an ind. ! 75: */ ! 76: if (r[3] != NIL) ! 77: goto ind; ! 78: q = p->type; ! 79: if (q == NIL) ! 80: return (NIL); ! 81: w = width(q); ! 82: switch (w) { ! 83: case 8: ! 84: w = 6; ! 85: case 4: ! 86: case 2: ! 87: case 1: ! 88: put2(O_RV1 + (w >> 1) | bn << 9 ! 89: , p->value[0]); ! 90: break; ! 91: default: ! 92: put3(O_RV | bn << 9, p->value[0], w); ! 93: } ! 94: return (q); ! 95: ! 96: case WITHPTR: ! 97: case REF: ! 98: /* ! 99: * A lvalue for these ! 100: * is actually what one ! 101: * might consider a rvalue. ! 102: */ ! 103: ind: ! 104: q = lvalue(r, NOMOD); ! 105: if (q == NIL) ! 106: return (NIL); ! 107: w = width(q); ! 108: switch (w) { ! 109: case 8: ! 110: w = 6; ! 111: case 4: ! 112: case 2: ! 113: case 1: ! 114: put1(O_IND1 + (w >> 1)); ! 115: break; ! 116: default: ! 117: put2(O_IND, w); ! 118: } ! 119: return (q); ! 120: ! 121: case CONST: ! 122: if (r[3] != NIL) { ! 123: error("%s is a constant and cannot be qualified", r[2]); ! 124: return (NIL); ! 125: } ! 126: q = p->type; ! 127: if (q == NIL) ! 128: return (NIL); ! 129: if (q == nl+TSTR) { ! 130: /* ! 131: * Find the size of the string ! 132: * constant if needed. ! 133: */ ! 134: cp = p->ptr[0]; ! 135: cstrng: ! 136: cp1 = cp; ! 137: for (c = 0; *cp++; c++) ! 138: continue; ! 139: if (contype != NIL && !opt('s')) { ! 140: if (width(contype) < c && classify(contype) == TSTR) { ! 141: error("Constant string too long"); ! 142: return (NIL); ! 143: } ! 144: c = width(contype); ! 145: } ! 146: put( 2 + (sizeof ( char * )/sizeof ( short )) , O_CONG, c, cp1); ! 147: /* ! 148: * Define the string temporarily ! 149: * so later people can know its ! 150: * width. ! 151: * cleaned out by stat. ! 152: */ ! 153: q = defnl(0, STR, 0, c); ! 154: q->type = q; ! 155: return (q); ! 156: } ! 157: if (q == nl+T1CHAR) { ! 158: put2(O_CONC, p->value[0]); ! 159: return (q); ! 160: } ! 161: /* ! 162: * Every other kind of constant here ! 163: */ ! 164: switch (width(q)) { ! 165: case 8: ! 166: #ifndef DEBUG ! 167: put(5, O_CON8, p->real); ! 168: #else ! 169: if (hp21mx) { ! 170: f = p->real; ! 171: conv(&f); ! 172: l = f.plong; ! 173: put( 3 , O_CON4, l); ! 174: } else ! 175: put(5, O_CON8, p->real); ! 176: #endif ! 177: break; ! 178: case 4: ! 179: put( 3 , O_CON4, p->range[0]); ! 180: break; ! 181: case 2: ! 182: put2(O_CON2, ( short ) p->range[0]); ! 183: break; ! 184: case 1: ! 185: put2(O_CON1, p->value[0]); ! 186: break; ! 187: default: ! 188: panic("rval"); ! 189: } ! 190: return (q); ! 191: ! 192: case FUNC: ! 193: /* ! 194: * Function call with no arguments. ! 195: */ ! 196: if (r[3]) { ! 197: error("Can't qualify a function result value"); ! 198: return (NIL); ! 199: } ! 200: return (funccod((int *) r)); ! 201: ! 202: case TYPE: ! 203: error("Type names (e.g. %s) allowed only in declarations", p->symbol); ! 204: return (NIL); ! 205: ! 206: case PROC: ! 207: error("Procedure %s found where expression required", p->symbol); ! 208: return (NIL); ! 209: default: ! 210: panic("rvid"); ! 211: } ! 212: /* ! 213: * Constant sets ! 214: */ ! 215: case T_CSET: ! 216: return (cset(r, contype, NIL)); ! 217: ! 218: /* ! 219: * Unary plus and minus ! 220: */ ! 221: case T_PLUS: ! 222: case T_MINUS: ! 223: q = rvalue(r[2], NIL); ! 224: if (q == NIL) ! 225: return (NIL); ! 226: if (isnta(q, "id")) { ! 227: error("Operand of %s must be integer or real, not %s", opname, nameof(q)); ! 228: return (NIL); ! 229: } ! 230: if (r[0] == T_MINUS) { ! 231: put1(O_NEG2 + (width(q) >> 2)); ! 232: return (isa(q, "d") ? q : nl+T4INT); ! 233: } ! 234: return (q); ! 235: ! 236: case T_NOT: ! 237: q = rvalue(r[2], NIL); ! 238: if (q == NIL) ! 239: return (NIL); ! 240: if (isnta(q, "b")) { ! 241: error("not must operate on a Boolean, not %s", nameof(q)); ! 242: return (NIL); ! 243: } ! 244: put1(O_NOT); ! 245: return (nl+T1BOOL); ! 246: ! 247: case T_AND: ! 248: case T_OR: ! 249: p = rvalue(r[2], NIL); ! 250: p1 = rvalue(r[3], NIL); ! 251: if (p == NIL || p1 == NIL) ! 252: return (NIL); ! 253: if (isnta(p, "b")) { ! 254: error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); ! 255: return (NIL); ! 256: } ! 257: if (isnta(p1, "b")) { ! 258: error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); ! 259: return (NIL); ! 260: } ! 261: put1(r[0] == T_AND ? O_AND : O_OR); ! 262: return (nl+T1BOOL); ! 263: ! 264: case T_DIVD: ! 265: p = rvalue(r[2], NIL); ! 266: p1 = rvalue(r[3], NIL); ! 267: if (p == NIL || p1 == NIL) ! 268: return (NIL); ! 269: if (isnta(p, "id")) { ! 270: error("Left operand of / must be integer or real, not %s", nameof(p)); ! 271: return (NIL); ! 272: } ! 273: if (isnta(p1, "id")) { ! 274: error("Right operand of / must be integer or real, not %s", nameof(p1)); ! 275: return (NIL); ! 276: } ! 277: return (gen(NIL, r[0], width(p), width(p1))); ! 278: ! 279: case T_MULT: ! 280: case T_SUB: ! 281: case T_ADD: ! 282: /* ! 283: * If the context hasn't told us ! 284: * the type and a constant set is ! 285: * present on the left we need to infer ! 286: * the type from the right if possible ! 287: * before generating left side code. ! 288: */ ! 289: if (contype == NIL && (rt = r[2]) != NIL && rt[1] == SAWCON) { ! 290: codeoff(); ! 291: contype = rvalue(r[3], NIL); ! 292: codeon(); ! 293: if (contype == NIL) ! 294: return (NIL); ! 295: } ! 296: p = rvalue(r[2], contype); ! 297: p1 = rvalue(r[3], p); ! 298: if (p == NIL || p1 == NIL) ! 299: return (NIL); ! 300: if (isa(p, "id") && isa(p1, "id")) ! 301: return (gen(NIL, r[0], width(p), width(p1))); ! 302: if (isa(p, "t") && isa(p1, "t")) { ! 303: if (p != p1) { ! 304: error("Set types of operands of %s must be identical", opname); ! 305: return (NIL); ! 306: } ! 307: gen(TSET, r[0], width(p), 0); ! 308: /* ! 309: * Note that set was filled in by the call ! 310: * to width above. ! 311: */ ! 312: if (r[0] == T_SUB) ! 313: put2(NIL, 0177777 << ((set.uprbp & 017) + 1)); ! 314: return (p); ! 315: } ! 316: if (isnta(p, "idt")) { ! 317: error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); ! 318: return (NIL); ! 319: } ! 320: if (isnta(p1, "idt")) { ! 321: error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); ! 322: return (NIL); ! 323: } ! 324: error("Cannot mix sets with integers and reals as operands of %s", opname); ! 325: return (NIL); ! 326: ! 327: case T_MOD: ! 328: case T_DIV: ! 329: p = rvalue(r[2], NIL); ! 330: p1 = rvalue(r[3], NIL); ! 331: if (p == NIL || p1 == NIL) ! 332: return (NIL); ! 333: if (isnta(p, "i")) { ! 334: error("Left operand of %s must be integer, not %s", opname, nameof(p)); ! 335: return (NIL); ! 336: } ! 337: if (isnta(p1, "i")) { ! 338: error("Right operand of %s must be integer, not %s", opname, nameof(p1)); ! 339: return (NIL); ! 340: } ! 341: return (gen(NIL, r[0], width(p), width(p1))); ! 342: ! 343: case T_EQ: ! 344: case T_NE: ! 345: case T_GE: ! 346: case T_LE: ! 347: case T_GT: ! 348: case T_LT: ! 349: /* ! 350: * Since there can be no, a priori, knowledge ! 351: * of the context type should a constant string ! 352: * or set arise, we must poke around to find such ! 353: * a type if possible. Since constant strings can ! 354: * always masquerade as identifiers, this is always ! 355: * necessary. ! 356: */ ! 357: codeoff(); ! 358: p1 = rvalue(r[3], NIL); ! 359: codeon(); ! 360: if (p1 == NIL) ! 361: return (NIL); ! 362: contype = p1; ! 363: if (p1 == nl+TSET || p1->class == STR) { ! 364: /* ! 365: * For constant strings we want ! 366: * the longest type so as to be ! 367: * able to do padding (more importantly ! 368: * avoiding truncation). For clarity, ! 369: * we get this length here. ! 370: */ ! 371: codeoff(); ! 372: p = rvalue(r[2], NIL); ! 373: codeon(); ! 374: if (p == NIL) ! 375: return (NIL); ! 376: if (p1 == nl+TSET || width(p) > width(p1)) ! 377: contype = p; ! 378: } ! 379: /* ! 380: * Now we generate code for ! 381: * the operands of the relational ! 382: * operation. ! 383: */ ! 384: p = rvalue(r[2], contype); ! 385: if (p == NIL) ! 386: return (NIL); ! 387: p1 = rvalue(r[3], p); ! 388: if (p1 == NIL) ! 389: return (NIL); ! 390: c = classify(p); ! 391: c1 = classify(p1); ! 392: if (nocomp(c) || nocomp(c1)) ! 393: return (NIL); ! 394: g = NIL; ! 395: switch (c) { ! 396: case TBOOL: ! 397: case TCHAR: ! 398: if (c != c1) ! 399: goto clash; ! 400: break; ! 401: case TINT: ! 402: case TDOUBLE: ! 403: if (c1 != TINT && c1 != TDOUBLE) ! 404: goto clash; ! 405: break; ! 406: case TSCAL: ! 407: if (c1 != TSCAL) ! 408: goto clash; ! 409: if (scalar(p) != scalar(p1)) ! 410: goto nonident; ! 411: break; ! 412: case TSET: ! 413: if (c1 != TSET) ! 414: goto clash; ! 415: if (p != p1) ! 416: goto nonident; ! 417: g = TSET; ! 418: break; ! 419: case TPTR: ! 420: case TNIL: ! 421: if (c1 != TPTR && c1 != TNIL) ! 422: goto clash; ! 423: if (r[0] != T_EQ && r[0] != T_NE) { ! 424: error("%s not allowed on pointers - only allow = and <>"); ! 425: return (NIL); ! 426: } ! 427: break; ! 428: case TSTR: ! 429: if (c1 != TSTR) ! 430: goto clash; ! 431: if (width(p) != width(p1)) { ! 432: error("Strings not same length in %s comparison", opname); ! 433: return (NIL); ! 434: } ! 435: g = TSTR; ! 436: break; ! 437: default: ! 438: panic("rval2"); ! 439: } ! 440: return (gen(g, r[0], width(p), width(p1))); ! 441: clash: ! 442: error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); ! 443: return (NIL); ! 444: nonident: ! 445: error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); ! 446: return (NIL); ! 447: ! 448: case T_IN: ! 449: rt = r[3]; ! 450: if (rt != NIL && rt[0] == T_CSET) ! 451: p1 = cset(rt, NLNIL, 1); ! 452: else { ! 453: p1 = rvalue(r[3], NIL); ! 454: rt = NIL; ! 455: } ! 456: if (p1 == nl+TSET) { ! 457: warning(); ! 458: error("... in [] makes little sense, since it is always false!"); ! 459: put1(O_CON1, 0); ! 460: return (nl+T1BOOL); ! 461: } ! 462: p = rvalue(r[2], NIL); ! 463: if (p == NIL || p1 == NIL) ! 464: return (NIL); ! 465: if (p1->class != SET) { ! 466: error("Right operand of 'in' must be a set, not %s", nameof(p1)); ! 467: return (NIL); ! 468: } ! 469: if (incompat(p, p1->type, r[2])) { ! 470: cerror("Index type clashed with set component type for 'in'"); ! 471: return (NIL); ! 472: } ! 473: convert(p, nl+T2INT); ! 474: setran(p1->type); ! 475: if (rt == NIL) ! 476: put4(O_IN, width(p1), set.lwrb, set.uprbp); ! 477: else ! 478: put1(O_INCT); ! 479: return (nl+T1BOOL); ! 480: ! 481: default: ! 482: if (r[2] == NIL) ! 483: return (NIL); ! 484: switch (r[0]) { ! 485: default: ! 486: panic("rval3"); ! 487: ! 488: ! 489: /* ! 490: * An octal number ! 491: */ ! 492: case T_BINT: ! 493: f = a8tol(r[2]); ! 494: goto conint; ! 495: ! 496: /* ! 497: * A decimal number ! 498: */ ! 499: case T_INT: ! 500: f = atof(r[2]); ! 501: conint: ! 502: if (f > MAXINT || f < MININT) { ! 503: error("Constant too large for this implementation"); ! 504: return (NIL); ! 505: } ! 506: l = f; ! 507: if (bytes(l, l) <= 2) { ! 508: put2(O_CON2, ( short ) l); ! 509: return (nl+T2INT); ! 510: } ! 511: put( 3 , O_CON4, l); ! 512: return (nl+T4INT); ! 513: ! 514: /* ! 515: * A floating point number ! 516: */ ! 517: case T_FINT: ! 518: put(5, O_CON8, atof(r[2])); ! 519: return (nl+TDOUBLE); ! 520: ! 521: /* ! 522: * Constant strings. Note that constant characters ! 523: * are constant strings of length one; there is ! 524: * no constant string of length one. ! 525: */ ! 526: case T_STRNG: ! 527: cp = r[2]; ! 528: if (cp[1] == 0) { ! 529: put2(O_CONC, cp[0]); ! 530: return (nl+T1CHAR); ! 531: } ! 532: goto cstrng; ! 533: } ! 534: ! 535: } ! 536: } ! 537: ! 538: /* ! 539: * Can a class appear ! 540: * in a comparison ? ! 541: */ ! 542: nocomp(c) ! 543: int c; ! 544: { ! 545: ! 546: switch (c) { ! 547: case TFILE: ! 548: case TARY: ! 549: case TREC: ! 550: error("%ss may not participate in comparisons", clnames[c]); ! 551: return (1); ! 552: } ! 553: return (NIL); ! 554: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.