|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)lval.c 1.10 10/24/83"; ! 4: ! 5: #include "whoami.h" ! 6: #include "0.h" ! 7: #include "tree.h" ! 8: #include "opcode.h" ! 9: #include "objfmt.h" ! 10: #ifdef PC ! 11: # include "pc.h" ! 12: # include "pcops.h" ! 13: #endif PC ! 14: ! 15: extern int flagwas; ! 16: /* ! 17: * Lvalue computes the address ! 18: * of a qualified name and ! 19: * leaves it on the stack. ! 20: * for pc, it can be asked for either an lvalue or an rvalue. ! 21: * the semantics are the same, only the code is different. ! 22: */ ! 23: struct nl * ! 24: lvalue(r, modflag , required ) ! 25: int *r, modflag; ! 26: int required; ! 27: { ! 28: register struct nl *p; ! 29: struct nl *firstp, *lastp; ! 30: register *c, *co; ! 31: int f, o; ! 32: /* ! 33: * Note that the local optimizations ! 34: * done here for offsets would more ! 35: * appropriately be done in put. ! 36: */ ! 37: int tr[2], trp[3]; ! 38: ! 39: if (r == NIL) { ! 40: return (NIL); ! 41: } ! 42: if (nowexp(r)) { ! 43: return (NIL); ! 44: } ! 45: if (r[0] != T_VAR) { ! 46: error("Variable required"); /* Pass mesgs down from pt of call ? */ ! 47: return (NIL); ! 48: } ! 49: # ifdef PC ! 50: /* ! 51: * pc requires a whole different control flow ! 52: */ ! 53: return pclvalue( r , modflag , required ); ! 54: # endif PC ! 55: # ifdef OBJ ! 56: /* ! 57: * pi uses the rest of the function ! 58: */ ! 59: firstp = p = lookup(r[2]); ! 60: if (p == NIL) { ! 61: return (NIL); ! 62: } ! 63: c = r[3]; ! 64: if ((modflag & NOUSE) && !lptr(c)) { ! 65: p->nl_flags = flagwas; ! 66: } ! 67: if (modflag & MOD) { ! 68: p->nl_flags |= NMOD; ! 69: } ! 70: /* ! 71: * Only possibilities for p->class here ! 72: * are the named classes, i.e. CONST, TYPE ! 73: * VAR, PROC, FUNC, REF, or a WITHPTR. ! 74: */ ! 75: switch (p->class) { ! 76: case WITHPTR: ! 77: /* ! 78: * Construct the tree implied by ! 79: * the with statement ! 80: */ ! 81: trp[0] = T_LISTPP; ! 82: trp[1] = tr; ! 83: trp[2] = r[3]; ! 84: tr[0] = T_FIELD; ! 85: tr[1] = r[2]; ! 86: c = trp; ! 87: # ifdef PTREE ! 88: /* ! 89: * mung r[4] to say which field this T_VAR is ! 90: * for VarCopy ! 91: */ ! 92: r[4] = reclook( p -> type , r[2] ); ! 93: # endif ! 94: /* and fall through */ ! 95: case REF: ! 96: /* ! 97: * Obtain the indirect word ! 98: * of the WITHPTR or REF ! 99: * as the base of our lvalue ! 100: */ ! 101: put(2, PTR_RV | bn << 8+INDX , (int)p->value[0] ); ! 102: f = 0; /* have an lv on stack */ ! 103: o = 0; ! 104: break; ! 105: case VAR: ! 106: f = 1; /* no lv on stack yet */ ! 107: o = p->value[0]; ! 108: break; ! 109: default: ! 110: error("%s %s found where variable required", classes[p->class], p->symbol); ! 111: return (NIL); ! 112: } ! 113: /* ! 114: * Loop and handle each ! 115: * qualification on the name ! 116: */ ! 117: if (c == NIL && (modflag&ASGN) && ( p->value[NL_FORV] & FORVAR ) ) { ! 118: error("Can't modify the for variable %s in the range of the loop", p->symbol); ! 119: return (NIL); ! 120: } ! 121: for (; c != NIL; c = c[2]) { ! 122: co = c[1]; ! 123: if (co == NIL) { ! 124: return (NIL); ! 125: } ! 126: lastp = p; ! 127: p = p->type; ! 128: if (p == NIL) { ! 129: return (NIL); ! 130: } ! 131: switch (co[0]) { ! 132: case T_PTR: ! 133: /* ! 134: * Pointer qualification. ! 135: */ ! 136: lastp->nl_flags |= NUSED; ! 137: if (p->class != PTR && p->class != FILET) { ! 138: error("^ allowed only on files and pointers, not on %ss", nameof(p)); ! 139: goto bad; ! 140: } ! 141: if (f) { ! 142: if (p->class == FILET && bn != 0) ! 143: put(2, O_LV | bn <<8+INDX , o ); ! 144: else ! 145: /* ! 146: * this is the indirection from ! 147: * the address of the pointer ! 148: * to the pointer itself. ! 149: * kirk sez: ! 150: * fnil doesn't want this. ! 151: * and does it itself for files ! 152: * since only it knows where the ! 153: * actual window is. ! 154: * but i have to do this for ! 155: * regular pointers. ! 156: * This is further complicated by ! 157: * the fact that global variables ! 158: * are referenced through pointers ! 159: * on the stack. Thus an RV on a ! 160: * global variable is the same as ! 161: * an LV of a non-global one ?!? ! 162: */ ! 163: put(2, PTR_RV | bn <<8+INDX , o ); ! 164: } else { ! 165: if (o) { ! 166: put(2, O_OFF, o); ! 167: } ! 168: if (p->class != FILET || bn == 0) ! 169: put(1, PTR_IND); ! 170: } ! 171: /* ! 172: * Pointer cannot be ! 173: * nil and file cannot ! 174: * be at end-of-file. ! 175: */ ! 176: put(1, p->class == FILET ? O_FNIL : O_NIL); ! 177: f = o = 0; ! 178: continue; ! 179: case T_ARGL: ! 180: if (p->class != ARRAY) { ! 181: if (lastp == firstp) { ! 182: error("%s is a %s, not a function", r[2], classes[firstp->class]); ! 183: } else { ! 184: error("Illegal function qualificiation"); ! 185: } ! 186: return (NIL); ! 187: } ! 188: recovered(); ! 189: error("Pascal uses [] for subscripting, not ()"); ! 190: case T_ARY: ! 191: if (p->class != ARRAY) { ! 192: error("Subscripting allowed only on arrays, not on %ss", nameof(p)); ! 193: goto bad; ! 194: } ! 195: if (f) { ! 196: if (bn == 0) ! 197: /* ! 198: * global variables are ! 199: * referenced through pointers ! 200: * on the stack ! 201: */ ! 202: put(2, PTR_RV | bn<<8+INDX, o); ! 203: else ! 204: put(2, O_LV | bn<<8+INDX, o); ! 205: } else { ! 206: if (o) { ! 207: put(2, O_OFF, o); ! 208: } ! 209: } ! 210: switch (arycod(p, co[1])) { ! 211: case 0: ! 212: return (NIL); ! 213: case -1: ! 214: goto bad; ! 215: } ! 216: f = o = 0; ! 217: continue; ! 218: case T_FIELD: ! 219: /* ! 220: * Field names are just ! 221: * an offset with some ! 222: * semantic checking. ! 223: */ ! 224: if (p->class != RECORD) { ! 225: error(". allowed only on records, not on %ss", nameof(p)); ! 226: goto bad; ! 227: } ! 228: if (co[1] == NIL) { ! 229: return (NIL); ! 230: } ! 231: p = reclook(p, co[1]); ! 232: if (p == NIL) { ! 233: error("%s is not a field in this record", co[1]); ! 234: goto bad; ! 235: } ! 236: # ifdef PTREE ! 237: /* ! 238: * mung co[3] to indicate which field ! 239: * this is for SelCopy ! 240: */ ! 241: co[3] = p; ! 242: # endif ! 243: if (modflag & MOD) { ! 244: p->nl_flags |= NMOD; ! 245: } ! 246: if ((modflag & NOUSE) == 0 || lptr(c[2])) { ! 247: p->nl_flags |= NUSED; ! 248: } ! 249: o += p->value[0]; ! 250: continue; ! 251: default: ! 252: panic("lval2"); ! 253: } ! 254: } ! 255: if (f) { ! 256: if (bn == 0) ! 257: /* ! 258: * global variables are referenced through ! 259: * pointers on the stack ! 260: */ ! 261: put(2, PTR_RV | bn<<8+INDX, o); ! 262: else ! 263: put(2, O_LV | bn<<8+INDX, o); ! 264: } else { ! 265: if (o) { ! 266: put(2, O_OFF, o); ! 267: } ! 268: } ! 269: return (p->type); ! 270: bad: ! 271: cerror("Error occurred on qualification of %s", r[2]); ! 272: return (NIL); ! 273: # endif OBJ ! 274: } ! 275: ! 276: lptr(c) ! 277: register int *c; ! 278: { ! 279: register int *co; ! 280: ! 281: for (; c != NIL; c = c[2]) { ! 282: co = c[1]; ! 283: if (co == NIL) { ! 284: return (NIL); ! 285: } ! 286: switch (co[0]) { ! 287: ! 288: case T_PTR: ! 289: return (1); ! 290: case T_ARGL: ! 291: return (0); ! 292: case T_ARY: ! 293: case T_FIELD: ! 294: continue; ! 295: default: ! 296: panic("lptr"); ! 297: } ! 298: } ! 299: return (0); ! 300: } ! 301: ! 302: /* ! 303: * Arycod does the ! 304: * code generation ! 305: * for subscripting. ! 306: */ ! 307: arycod(np, el) ! 308: struct nl *np; ! 309: int *el; ! 310: { ! 311: register struct nl *p, *ap; ! 312: long sub; ! 313: bool constsub; ! 314: int i, d, v, v1; ! 315: int w; ! 316: ! 317: p = np; ! 318: if (el == NIL) { ! 319: return (0); ! 320: } ! 321: d = p->value[0]; ! 322: /* ! 323: * Check each subscript ! 324: */ ! 325: for (i = 1; i <= d; i++) { ! 326: if (el == NIL) { ! 327: error("Too few subscripts (%d given, %d required)", i-1, d); ! 328: return (-1); ! 329: } ! 330: p = p->chain; ! 331: if (constsub = constval(el[1])) { ! 332: ap = con.ctype; ! 333: sub = con.crval; ! 334: if (sub < p->range[0] || sub > p->range[1]) { ! 335: error("Subscript value of %D is out of range", sub); ! 336: return (0); ! 337: } ! 338: sub -= p->range[0]; ! 339: } else { ! 340: # ifdef PC ! 341: precheck( p , "_SUBSC" , "_SUBSCZ" ); ! 342: # endif PC ! 343: ap = rvalue(el[1], NLNIL , RREQ ); ! 344: if (ap == NIL) { ! 345: return (0); ! 346: } ! 347: # ifdef PC ! 348: postcheck(p, ap); ! 349: sconv(p2type(ap),P2INT); ! 350: # endif PC ! 351: } ! 352: if (incompat(ap, p->type, el[1])) { ! 353: cerror("Array index type incompatible with declared index type"); ! 354: if (d != 1) { ! 355: cerror("Error occurred on index number %d", i); ! 356: } ! 357: return (-1); ! 358: } ! 359: w = aryconst(np, i); ! 360: # ifdef OBJ ! 361: if (constsub) { ! 362: sub *= w; ! 363: if (sub != 0) { ! 364: w = bytes(sub, sub); ! 365: put(2, w <= 2 ? O_CON2 : O_CON4, sub); ! 366: gen(NIL, T_ADD, sizeof(char *), w); ! 367: } ! 368: el = el[2]; ! 369: continue; ! 370: } ! 371: if (opt('t') == 0) { ! 372: switch (w) { ! 373: case 8: ! 374: w = 6; ! 375: case 4: ! 376: case 2: ! 377: case 1: ! 378: put(2, (width(ap) != 4 ? O_INX2P2 : O_INX4P2) | (w & ~1) << 7, ( short ) p->range[0]); ! 379: el = el[2]; ! 380: continue; ! 381: } ! 382: } ! 383: put(4, width(ap) != 4 ? O_INX2 : O_INX4, w, ! 384: (short)p->range[0], (short)(p->range[1])); ! 385: el = el[2]; ! 386: continue; ! 387: # endif OBJ ! 388: # ifdef PC ! 389: /* ! 390: * subtract off the lower bound ! 391: */ ! 392: if (constsub) { ! 393: sub *= w; ! 394: if (sub != 0) { ! 395: putleaf( P2ICON , sub , 0 , P2INT , 0 ); ! 396: putop(P2PLUS, ADDTYPE(p2type(np->type), P2PTR)); ! 397: } ! 398: el = el[2]; ! 399: continue; ! 400: } ! 401: if ( p -> range[ 0 ] != 0 ) { ! 402: putleaf( P2ICON , p -> range[0] , 0 , P2INT , 0 ); ! 403: putop( P2MINUS , P2INT ); ! 404: } ! 405: /* ! 406: * multiply by the width of the elements ! 407: */ ! 408: if ( w != 1 ) { ! 409: putleaf( P2ICON , w , 0 , P2INT , 0 ); ! 410: putop( P2MUL , P2INT ); ! 411: } ! 412: /* ! 413: * and add it to the base address ! 414: */ ! 415: putop( P2PLUS , ADDTYPE( p2type( np -> type ) , P2PTR ) ); ! 416: # endif PC ! 417: el = el[2]; ! 418: } ! 419: if (el != NIL) { ! 420: do { ! 421: el = el[2]; ! 422: i++; ! 423: } while (el != NIL); ! 424: error("Too many subscripts (%d given, %d required)", i-1, d); ! 425: return (-1); ! 426: } ! 427: return (1); ! 428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.