|
|
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 November 1978 ! 8: */ ! 9: ! 10: #include "whoami" ! 11: #include "0.h" ! 12: #include "tree.h" ! 13: ! 14: int cntstat; ! 15: short cnts = 2; ! 16: #include "opcode.h" ! 17: ! 18: /* ! 19: * Statement list ! 20: */ ! 21: statlist(r) ! 22: int *r; ! 23: { ! 24: register *sl; ! 25: ! 26: for (sl=r; sl != NIL; sl=sl[2]) ! 27: statement(sl[1]); ! 28: } ! 29: ! 30: /* ! 31: * Statement ! 32: */ ! 33: statement(r) ! 34: int *r; ! 35: { ! 36: register *s; ! 37: register struct nl *snlp; ! 38: ! 39: s = r; ! 40: snlp = nlp; ! 41: top: ! 42: if (cntstat) { ! 43: cntstat = 0; ! 44: putcnt(); ! 45: } ! 46: if (s == NIL) ! 47: return; ! 48: line = s[1]; ! 49: if (s[0] == T_LABEL) { ! 50: labeled(s[2]); ! 51: s = s[3]; ! 52: noreach = 0; ! 53: cntstat = 1; ! 54: goto top; ! 55: } ! 56: if (noreach) { ! 57: noreach = 0; ! 58: warning(); ! 59: error("Unreachable statement"); ! 60: } ! 61: switch (s[0]) { ! 62: case T_PCALL: ! 63: putline(); ! 64: proc(s); ! 65: break; ! 66: case T_ASGN: ! 67: putline(); ! 68: asgnop(s); ! 69: break; ! 70: case T_GOTO: ! 71: putline(); ! 72: gotoop(s[2]); ! 73: noreach = 1; ! 74: cntstat = 1; ! 75: break; ! 76: default: ! 77: level++; ! 78: switch (s[0]) { ! 79: default: ! 80: panic("stat"); ! 81: case T_IF: ! 82: case T_IFEL: ! 83: ifop(s); ! 84: break; ! 85: case T_WHILE: ! 86: whilop(s); ! 87: noreach = 0; ! 88: break; ! 89: case T_REPEAT: ! 90: repop(s); ! 91: break; ! 92: case T_FORU: ! 93: case T_FORD: ! 94: forop(s); ! 95: noreach = 0; ! 96: break; ! 97: case T_BLOCK: ! 98: statlist(s[2]); ! 99: break; ! 100: case T_CASE: ! 101: putline(); ! 102: caseop(s); ! 103: break; ! 104: case T_WITH: ! 105: withop(s); ! 106: break; ! 107: case T_ASRT: ! 108: putline(); ! 109: asrtop(s); ! 110: break; ! 111: } ! 112: --level; ! 113: if (gotos[cbn]) ! 114: ungoto(); ! 115: break; ! 116: } ! 117: /* ! 118: * Free the temporary name list entries defined in ! 119: * expressions, e.g. STRs, and WITHPTRs from withs. ! 120: */ ! 121: nlfree(snlp); ! 122: } ! 123: ! 124: ungoto() ! 125: { ! 126: register struct nl *p; ! 127: ! 128: for (p = gotos[cbn]; p != NIL; p = p->chain) ! 129: if ((p->nl_flags & NFORWD) != 0) { ! 130: if (p->value[NL_GOLEV] != NOTYET) ! 131: if (p->value[NL_GOLEV] > level) ! 132: p->value[NL_GOLEV] = level; ! 133: } else ! 134: if (p->value[NL_GOLEV] != DEAD) ! 135: if (p->value[NL_GOLEV] > level) ! 136: p->value[NL_GOLEV] = DEAD; ! 137: } ! 138: ! 139: putcnt() ! 140: { ! 141: ! 142: if (monflg == 0) ! 143: return; ! 144: cnts++; ! 145: put2(O_COUNT, cnts); ! 146: } ! 147: ! 148: putline() ! 149: { ! 150: ! 151: # ifdef OBJ ! 152: if (opt('p') != 0) ! 153: put2(O_LINO, line); ! 154: # endif ! 155: } ! 156: ! 157: /* ! 158: * With varlist do stat ! 159: * ! 160: * With statement requires an extra word ! 161: * in automatic storage for each level of withing. ! 162: * These indirect pointers are initialized here, and ! 163: * the scoping effect of the with statement occurs ! 164: * because lookup examines the field names of the records ! 165: * associated with the WITHPTRs on the withlist. ! 166: */ ! 167: withop(s) ! 168: int *s; ! 169: { ! 170: register *p; ! 171: register struct nl *r; ! 172: int i; ! 173: int *swl; ! 174: long soffset; ! 175: ! 176: putline(); ! 177: swl = withlist; ! 178: soffset = sizes[cbn].om_off; ! 179: for (p = s[2]; p != NIL; p = p[2]) { ! 180: sizes[cbn].om_off -= sizeof ( int * ); ! 181: # ifdef PPC ! 182: putlbracket(); ! 183: # endif ! 184: put2(O_LV | cbn <<9, i = sizes[cbn].om_off); ! 185: r = lvalue(p[1], MOD); ! 186: if (r == NIL) ! 187: continue; ! 188: if (r->class != RECORD) { ! 189: error("Variable in with statement refers to %s, not to a record", nameof(r)); ! 190: continue; ! 191: } ! 192: r = defnl(0, WITHPTR, r, i); ! 193: r->nl_next = withlist; ! 194: withlist = r; ! 195: # ifdef VAX ! 196: put1 ( O_AS4 ); ! 197: # endif ! 198: # ifdef PDP11 ! 199: put1(O_AS2); ! 200: # endif ! 201: } ! 202: if (sizes[cbn].om_off < sizes[cbn].om_max) ! 203: sizes[cbn].om_max = sizes[cbn].om_off; ! 204: statement(s[3]); ! 205: sizes[cbn].om_off = soffset; ! 206: # ifdef PPC ! 207: putlbracket(); ! 208: # endif ! 209: withlist = swl; ! 210: } ! 211: ! 212: extern flagwas; ! 213: /* ! 214: * var := expr ! 215: */ ! 216: asgnop(r) ! 217: int *r; ! 218: { ! 219: register struct nl *p; ! 220: register *av; ! 221: ! 222: if (r == NIL) ! 223: return (NIL); ! 224: /* ! 225: * Asgnop's only function is ! 226: * to handle function variable ! 227: * assignments. All other assignment ! 228: * stuff is handled by asgnop1. ! 229: */ ! 230: av = r[2]; ! 231: if (av != NIL && av[0] == T_VAR && av[3] == NIL) { ! 232: p = lookup1(av[2]); ! 233: if (p != NIL) ! 234: p->nl_flags = flagwas; ! 235: if (p != NIL && p->class == FVAR) { ! 236: /* ! 237: * Give asgnop1 the func ! 238: * which is the chain of ! 239: * the FVAR. ! 240: */ ! 241: p->nl_flags |= NUSED|NMOD; ! 242: p = p->chain; ! 243: if (p == NIL) { ! 244: rvalue(r[3], NIL); ! 245: return; ! 246: } ! 247: put2(O_LV | bn << 9, p->value[NL_OFFS]); ! 248: if (isa(p->type, "i") && width(p->type) == 1) ! 249: asgnop1(r, nl+T2INT); ! 250: else ! 251: asgnop1(r, p->type); ! 252: return; ! 253: } ! 254: } ! 255: asgnop1(r, NIL); ! 256: } ! 257: ! 258: /* ! 259: * Asgnop1 handles all assignments. ! 260: * If p is not nil then we are assigning ! 261: * to a function variable, otherwise ! 262: * we look the variable up ourselves. ! 263: */ ! 264: struct nl * ! 265: asgnop1(r, p) ! 266: int *r; ! 267: register struct nl *p; ! 268: { ! 269: register struct nl *p1; ! 270: ! 271: if (r == NIL) ! 272: return (NIL); ! 273: if (p == NIL) { ! 274: p = lvalue(r[2], MOD|ASGN|NOUSE); ! 275: if (p == NIL) { ! 276: rvalue(r[3], NIL); ! 277: return (NIL); ! 278: } ! 279: } ! 280: p1 = rvalue(r[3], p); ! 281: if (p1 == NIL) ! 282: return (NIL); ! 283: if (incompat(p1, p, r[3])) { ! 284: cerror("Type of expression clashed with type of variable in assignment"); ! 285: return (NIL); ! 286: } ! 287: switch (classify(p)) { ! 288: case TBOOL: ! 289: case TCHAR: ! 290: case TINT: ! 291: case TSCAL: ! 292: rangechk(p, p1); ! 293: case TDOUBLE: ! 294: case TPTR: ! 295: gen(O_AS2, O_AS2, width(p), width(p1)); ! 296: break; ! 297: default: ! 298: put2(O_AS, width(p)); ! 299: } ! 300: # ifdef PPC ! 301: putexpr(); ! 302: # endif ! 303: return (p); /* Used by for statement */ ! 304: } ! 305: ! 306: /* ! 307: * for var := expr [down]to expr do stat ! 308: */ ! 309: forop(r) ! 310: int *r; ! 311: { ! 312: register struct nl *t1, *t2; ! 313: int l1, l2, l3; ! 314: long soffset; ! 315: register op; ! 316: struct nl *p; ! 317: int *rr, goc, i; ! 318: ! 319: p = NIL; ! 320: goc = gocnt; ! 321: if (r == NIL) ! 322: goto aloha; ! 323: putline(); ! 324: /* ! 325: * Start with assignment ! 326: * of initial value to for variable ! 327: */ ! 328: t1 = asgnop1(r[2], NIL); ! 329: if (t1 == NIL) { ! 330: rvalue(r[3], NIL); ! 331: statement(r[4]); ! 332: goto aloha; ! 333: } ! 334: rr = r[2]; /* Assignment */ ! 335: rr = rr[2]; /* Lhs variable */ ! 336: if (rr[3] != NIL) { ! 337: error("For variable must be unqualified"); ! 338: rvalue(r[3], NIL); ! 339: statement(r[4]); ! 340: goto aloha; ! 341: } ! 342: p = lookup(rr[2]); ! 343: p->value[NL_FORV] = 1; ! 344: if (isnta(t1, "bcis")) { ! 345: error("For variables cannot be %ss", nameof(t1)); ! 346: statement(r[4]); ! 347: goto aloha; ! 348: } ! 349: /* ! 350: * Allocate automatic ! 351: * space for limit variable ! 352: */ ! 353: sizes[cbn].om_off -= 4; ! 354: # ifdef PPC ! 355: putlbracket(); ! 356: # endif ! 357: if (sizes[cbn].om_off < sizes[cbn].om_max) ! 358: sizes[cbn].om_max = sizes[cbn].om_off; ! 359: i = sizes[cbn].om_off; ! 360: /* ! 361: * Initialize the limit variable ! 362: */ ! 363: put2(O_LV | cbn<<9, i); ! 364: t2 = rvalue(r[3], NIL); ! 365: if (incompat(t2, t1, r[3])) { ! 366: cerror("Limit type clashed with index type in 'for' statement"); ! 367: statement(r[4]); ! 368: goto aloha; ! 369: } ! 370: put1(width(t2) <= 2 ? O_AS24 : O_AS4); ! 371: # ifdef PPC ! 372: putexpr(); ! 373: # endif ! 374: /* ! 375: * See if we can skip the loop altogether ! 376: */ ! 377: rr = r[2]; ! 378: if (rr != NIL) ! 379: rvalue(rr[2], NIL); ! 380: put2(O_RV4 | cbn<<9, i); ! 381: gen(NIL, r[0] == T_FORU ? T_LE : T_GE, width(t1), 4); ! 382: /* ! 383: * L1 will be patched to skip the body of the loop. ! 384: * L2 marks the top of the loop when we go around. ! 385: */ ! 386: put2(O_IF, (l1 = getlab())); ! 387: putlab(l2 = getlab()); ! 388: putcnt(); ! 389: statement(r[4]); ! 390: /* ! 391: * now we see if we get to go again ! 392: */ ! 393: if (opt('t') == 0) { ! 394: /* ! 395: * Easy if we dont have to test ! 396: */ ! 397: put2(O_RV4 | cbn<<9, i); ! 398: if (rr != NIL) ! 399: lvalue(rr[2], MOD); ! 400: put2((r[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(t1) >> 1), l2); ! 401: } else { ! 402: line = r[1]; ! 403: putline(); ! 404: if (rr != NIL) ! 405: rvalue(rr[2], NIL); ! 406: put2(O_RV4 | cbn << 9, i); ! 407: gen(NIL, (r[0] == T_FORU ? T_LT : T_GT), width(t1), 4); ! 408: l3 = put2(O_IF, getlab()); ! 409: lvalue((int *) rr[2], MOD); ! 410: rvalue(rr[2], NIL); ! 411: put2(O_CON2, 1); ! 412: t2 = gen(NIL, r[0] == T_FORU ? T_ADD: T_SUB, width(t1), 2); ! 413: rangechk(t1, t2); /* The point of all this */ ! 414: gen(O_AS2, O_AS2, width(t1), width(t2)); ! 415: put2(O_TRA, l2); ! 416: patch(l3); ! 417: } ! 418: sizes[cbn].om_off += 4; ! 419: # ifdef PPC ! 420: putlbracket(); ! 421: # endif ! 422: patch(l1); ! 423: aloha: ! 424: noreach = 0; ! 425: if (p != NIL) ! 426: p->value[NL_FORV] = 0; ! 427: if (goc != gocnt) ! 428: putcnt(); ! 429: } ! 430: ! 431: /* ! 432: * if expr then stat [ else stat ] ! 433: */ ! 434: ifop(r) ! 435: int *r; ! 436: { ! 437: register struct nl *p; ! 438: register l1, l2; ! 439: int nr, goc; ! 440: ! 441: goc = gocnt; ! 442: if (r == NIL) ! 443: return; ! 444: putline(); ! 445: p = rvalue(r[2], NIL); ! 446: if (p == NIL) { ! 447: statement(r[3]); ! 448: noreach = 0; ! 449: statement(r[4]); ! 450: noreach = 0; ! 451: return; ! 452: } ! 453: if (isnta(p, "b")) { ! 454: error("Type of expression in if statement must be Boolean, not %s", nameof(p)); ! 455: statement(r[3]); ! 456: noreach = 0; ! 457: statement(r[4]); ! 458: noreach = 0; ! 459: return; ! 460: } ! 461: l1 = put2(O_IF, getlab()); ! 462: putcnt(); ! 463: statement(r[3]); ! 464: nr = noreach; ! 465: if (r[4] != NIL) { ! 466: /* ! 467: * else stat ! 468: */ ! 469: --level; ! 470: ungoto(); ! 471: ++level; ! 472: l2 = put2(O_TRA, getlab()); ! 473: patch(l1); ! 474: noreach = 0; ! 475: statement(r[4]); ! 476: noreach &= nr; ! 477: l1 = l2; ! 478: } else ! 479: noreach = 0; ! 480: patch(l1); ! 481: if (goc != gocnt) ! 482: putcnt(); ! 483: } ! 484: ! 485: /* ! 486: * while expr do stat ! 487: */ ! 488: whilop(r) ! 489: int *r; ! 490: { ! 491: register struct nl *p; ! 492: register l1, l2; ! 493: int goc; ! 494: ! 495: goc = gocnt; ! 496: if (r == NIL) ! 497: return; ! 498: putlab(l1 = getlab()); ! 499: putline(); ! 500: p = rvalue(r[2], NIL); ! 501: if (p == NIL) { ! 502: statement(r[3]); ! 503: noreach = 0; ! 504: return; ! 505: } ! 506: if (isnta(p, "b")) { ! 507: error("Type of expression in while statement must be Boolean, not %s", nameof(p)); ! 508: statement(r[3]); ! 509: noreach = 0; ! 510: return; ! 511: } ! 512: put2(O_IF, (l2 = getlab())); ! 513: putcnt(); ! 514: statement(r[3]); ! 515: put2(O_TRA, l1); ! 516: patch(l2); ! 517: if (goc != gocnt) ! 518: putcnt(); ! 519: } ! 520: ! 521: /* ! 522: * repeat stat* until expr ! 523: */ ! 524: repop(r) ! 525: int *r; ! 526: { ! 527: register struct nl *p; ! 528: register l; ! 529: int goc; ! 530: ! 531: goc = gocnt; ! 532: if (r == NIL) ! 533: return; ! 534: l = putlab(getlab()); ! 535: putcnt(); ! 536: statlist(r[2]); ! 537: line = r[1]; ! 538: p = rvalue(r[3], NIL); ! 539: if (p == NIL) ! 540: return; ! 541: if (isnta(p,"b")) { ! 542: error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); ! 543: return; ! 544: } ! 545: put2(O_IF, l); ! 546: if (goc != gocnt) ! 547: putcnt(); ! 548: } ! 549: ! 550: /* ! 551: * assert expr ! 552: */ ! 553: asrtop(r) ! 554: register int *r; ! 555: { ! 556: register struct nl *q; ! 557: ! 558: if (opt('s')) { ! 559: standard(); ! 560: error("Assert statement is non-standard"); ! 561: } ! 562: if (!opt('t')) ! 563: return; ! 564: r = r[2]; ! 565: q = rvalue((int *) r, NLNIL); ! 566: if (q == NIL) ! 567: return; ! 568: if (isnta(q, "b")) ! 569: error("Assert expression must be Boolean, not %ss", nameof(q)); ! 570: put1(O_ASRT); ! 571: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.