|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)lval.c 5.2 (Berkeley) 7/26/85"; ! 9: #endif not lint ! 10: ! 11: #include "whoami.h" ! 12: #include "0.h" ! 13: #include "tree.h" ! 14: #include "opcode.h" ! 15: #include "objfmt.h" ! 16: #include "tree_ty.h" ! 17: #ifdef PC ! 18: # include "pc.h" ! 19: # include <pcc.h> ! 20: #endif PC ! 21: ! 22: extern int flagwas; ! 23: /* ! 24: * Lvalue computes the address ! 25: * of a qualified name and ! 26: * leaves it on the stack. ! 27: * for pc, it can be asked for either an lvalue or an rvalue. ! 28: * the semantics are the same, only the code is different. ! 29: */ ! 30: /*ARGSUSED*/ ! 31: struct nl * ! 32: lvalue(var, modflag , required ) ! 33: struct tnode *var; ! 34: int modflag; ! 35: int required; ! 36: { ! 37: #ifdef OBJ ! 38: register struct nl *p; ! 39: struct nl *firstp, *lastp; ! 40: register struct tnode *c, *co; ! 41: int f, o, s; ! 42: /* ! 43: * Note that the local optimizations ! 44: * done here for offsets would more ! 45: * appropriately be done in put. ! 46: */ ! 47: struct tnode tr; /* T_FIELD */ ! 48: struct tnode *tr_ptr; ! 49: struct tnode l_node; ! 50: #endif ! 51: ! 52: if (var == TR_NIL) { ! 53: return (NLNIL); ! 54: } ! 55: if (nowexp(var)) { ! 56: return (NLNIL); ! 57: } ! 58: if (var->tag != T_VAR) { ! 59: error("Variable required"); /* Pass mesgs down from pt of call ? */ ! 60: return (NLNIL); ! 61: } ! 62: # ifdef PC ! 63: /* ! 64: * pc requires a whole different control flow ! 65: */ ! 66: return pclvalue( var , modflag , required ); ! 67: # endif PC ! 68: # ifdef OBJ ! 69: /* ! 70: * pi uses the rest of the function ! 71: */ ! 72: firstp = p = lookup(var->var_node.cptr); ! 73: if (p == NLNIL) { ! 74: return (NLNIL); ! 75: } ! 76: c = var->var_node.qual; ! 77: if ((modflag & NOUSE) && !lptr(c)) { ! 78: p->nl_flags = flagwas; ! 79: } ! 80: if (modflag & MOD) { ! 81: p->nl_flags |= NMOD; ! 82: } ! 83: /* ! 84: * Only possibilities for p->class here ! 85: * are the named classes, i.e. CONST, TYPE ! 86: * VAR, PROC, FUNC, REF, or a WITHPTR. ! 87: */ ! 88: tr_ptr = &l_node; ! 89: switch (p->class) { ! 90: case WITHPTR: ! 91: /* ! 92: * Construct the tree implied by ! 93: * the with statement ! 94: */ ! 95: l_node.tag = T_LISTPP; ! 96: ! 97: /* the cast has got to go but until the node is figured ! 98: out it stays */ ! 99: ! 100: tr_ptr->list_node.list = (&tr); ! 101: tr_ptr->list_node.next = var->var_node.qual; ! 102: tr.tag = T_FIELD; ! 103: tr.field_node.id_ptr = var->var_node.cptr; ! 104: c = tr_ptr; /* c is a ptr to a tnode */ ! 105: # ifdef PTREE ! 106: /* ! 107: * mung var->fields to say which field this T_VAR is ! 108: * for VarCopy ! 109: */ ! 110: ! 111: /* problem! reclook returns struct nl* */ ! 112: ! 113: var->var_node.fields = reclook( p -> type , ! 114: var->var_node.line_no ); ! 115: # endif ! 116: /* and fall through */ ! 117: case REF: ! 118: /* ! 119: * Obtain the indirect word ! 120: * of the WITHPTR or REF ! 121: * as the base of our lvalue ! 122: */ ! 123: (void) put(2, PTR_RV | bn << 8+INDX , (int)p->value[0] ); ! 124: f = 0; /* have an lv on stack */ ! 125: o = 0; ! 126: break; ! 127: case VAR: ! 128: if (p->type->class != CRANGE) { ! 129: f = 1; /* no lv on stack yet */ ! 130: o = p->value[0]; ! 131: } else { ! 132: error("Conformant array bound %s found where variable required", p->symbol); ! 133: return(NLNIL); ! 134: } ! 135: break; ! 136: default: ! 137: error("%s %s found where variable required", classes[p->class], p->symbol); ! 138: return (NLNIL); ! 139: } ! 140: /* ! 141: * Loop and handle each ! 142: * qualification on the name ! 143: */ ! 144: if (c == TR_NIL && (modflag&ASGN) && ( p->value[NL_FORV] & FORVAR ) ) { ! 145: error("Can't modify the for variable %s in the range of the loop", p->symbol); ! 146: return (NLNIL); ! 147: } ! 148: s = 0; /* subscripts seen */ ! 149: for (; c != TR_NIL; c = c->list_node.next) { ! 150: co = c->list_node.list; /* co is a ptr to a tnode */ ! 151: if (co == TR_NIL) { ! 152: return (NLNIL); ! 153: } ! 154: lastp = p; ! 155: p = p->type; ! 156: if (p == NLNIL) { ! 157: return (NLNIL); ! 158: } ! 159: /* ! 160: * If we haven't seen enough subscripts, and the next ! 161: * qualification isn't array reference, then it's an error. ! 162: */ ! 163: if (s && co->tag != T_ARY) { ! 164: error("Too few subscripts (%d given, %d required)", ! 165: s, p->value[0]); ! 166: } ! 167: switch (co->tag) { ! 168: case T_PTR: ! 169: /* ! 170: * Pointer qualification. ! 171: */ ! 172: lastp->nl_flags |= NUSED; ! 173: if (p->class != PTR && p->class != FILET) { ! 174: error("^ allowed only on files and pointers, not on %ss", nameof(p)); ! 175: goto bad; ! 176: } ! 177: if (f) { ! 178: if (p->class == FILET && bn != 0) ! 179: (void) put(2, O_LV | bn <<8+INDX , o ); ! 180: else ! 181: /* ! 182: * this is the indirection from ! 183: * the address of the pointer ! 184: * to the pointer itself. ! 185: * kirk sez: ! 186: * fnil doesn't want this. ! 187: * and does it itself for files ! 188: * since only it knows where the ! 189: * actual window is. ! 190: * but i have to do this for ! 191: * regular pointers. ! 192: * This is further complicated by ! 193: * the fact that global variables ! 194: * are referenced through pointers ! 195: * on the stack. Thus an RV on a ! 196: * global variable is the same as ! 197: * an LV of a non-global one ?!? ! 198: */ ! 199: (void) put(2, PTR_RV | bn <<8+INDX , o ); ! 200: } else { ! 201: if (o) { ! 202: (void) put(2, O_OFF, o); ! 203: } ! 204: if (p->class != FILET || bn == 0) ! 205: (void) put(1, PTR_IND); ! 206: } ! 207: /* ! 208: * Pointer cannot be ! 209: * nil and file cannot ! 210: * be at end-of-file. ! 211: */ ! 212: (void) put(1, p->class == FILET ? O_FNIL : O_NIL); ! 213: f = o = 0; ! 214: continue; ! 215: case T_ARGL: ! 216: if (p->class != ARRAY) { ! 217: if (lastp == firstp) { ! 218: error("%s is a %s, not a function", var->var_node.cptr, classes[firstp->class]); ! 219: } else { ! 220: error("Illegal function qualificiation"); ! 221: } ! 222: return (NLNIL); ! 223: } ! 224: recovered(); ! 225: error("Pascal uses [] for subscripting, not ()"); ! 226: case T_ARY: ! 227: if (p->class != ARRAY) { ! 228: error("Subscripting allowed only on arrays, not on %ss", nameof(p)); ! 229: goto bad; ! 230: } ! 231: if (f) { ! 232: if (bn == 0) ! 233: /* ! 234: * global variables are ! 235: * referenced through pointers ! 236: * on the stack ! 237: */ ! 238: (void) put(2, PTR_RV | bn<<8+INDX, o); ! 239: else ! 240: (void) put(2, O_LV | bn<<8+INDX, o); ! 241: } else { ! 242: if (o) { ! 243: (void) put(2, O_OFF, o); ! 244: } ! 245: } ! 246: switch(s = arycod(p,co->ary_node.expr_list,s)) { ! 247: /* ! 248: * This is the number of subscripts seen ! 249: */ ! 250: case 0: ! 251: return (NLNIL); ! 252: case -1: ! 253: goto bad; ! 254: } ! 255: if (s == p->value[0]) { ! 256: s = 0; ! 257: } else { ! 258: p = lastp; ! 259: } ! 260: f = o = 0; ! 261: continue; ! 262: case T_FIELD: ! 263: /* ! 264: * Field names are just ! 265: * an offset with some ! 266: * semantic checking. ! 267: */ ! 268: if (p->class != RECORD) { ! 269: error(". allowed only on records, not on %ss", nameof(p)); ! 270: goto bad; ! 271: } ! 272: /* must define the field node!! */ ! 273: if (co->field_node.id_ptr == NIL) { ! 274: return (NLNIL); ! 275: } ! 276: p = reclook(p, co->field_node.id_ptr); ! 277: if (p == NLNIL) { ! 278: error("%s is not a field in this record", co->field_node.id_ptr); ! 279: goto bad; ! 280: } ! 281: # ifdef PTREE ! 282: /* ! 283: * mung co[3] to indicate which field ! 284: * this is for SelCopy ! 285: */ ! 286: co->field_node.nl_entry = p; ! 287: # endif ! 288: if (modflag & MOD) { ! 289: p->nl_flags |= NMOD; ! 290: } ! 291: if ((modflag & NOUSE) == 0 || ! 292: lptr(c->list_node.next)) { ! 293: /* figure out what kind of node c is !! */ ! 294: p->nl_flags |= NUSED; ! 295: } ! 296: o += p->value[0]; ! 297: continue; ! 298: default: ! 299: panic("lval2"); ! 300: } ! 301: } ! 302: if (s) { ! 303: error("Too few subscripts (%d given, %d required)", ! 304: s, p->type->value[0]); ! 305: return NLNIL; ! 306: } ! 307: if (f) { ! 308: if (bn == 0) ! 309: /* ! 310: * global variables are referenced through ! 311: * pointers on the stack ! 312: */ ! 313: (void) put(2, PTR_RV | bn<<8+INDX, o); ! 314: else ! 315: (void) put(2, O_LV | bn<<8+INDX, o); ! 316: } else { ! 317: if (o) { ! 318: (void) put(2, O_OFF, o); ! 319: } ! 320: } ! 321: return (p->type); ! 322: bad: ! 323: cerror("Error occurred on qualification of %s", var->var_node.cptr); ! 324: return (NLNIL); ! 325: # endif OBJ ! 326: } ! 327: ! 328: int lptr(c) ! 329: register struct tnode *c; ! 330: { ! 331: register struct tnode *co; ! 332: ! 333: for (; c != TR_NIL; c = c->list_node.next) { ! 334: co = c->list_node.list; ! 335: if (co == TR_NIL) { ! 336: return (NIL); ! 337: } ! 338: switch (co->tag) { ! 339: ! 340: case T_PTR: ! 341: return (1); ! 342: case T_ARGL: ! 343: return (0); ! 344: case T_ARY: ! 345: case T_FIELD: ! 346: continue; ! 347: default: ! 348: panic("lptr"); ! 349: } ! 350: } ! 351: return (0); ! 352: } ! 353: ! 354: /* ! 355: * Arycod does the ! 356: * code generation ! 357: * for subscripting. ! 358: * n is the number of ! 359: * subscripts already seen ! 360: * (CLN 09/13/83) ! 361: */ ! 362: int arycod(np, el, n) ! 363: struct nl *np; ! 364: struct tnode *el; ! 365: int n; ! 366: { ! 367: register struct nl *p, *ap; ! 368: long sub; ! 369: bool constsub; ! 370: extern bool constval(); ! 371: int i, d; /* v, v1; these aren't used */ ! 372: int w; ! 373: ! 374: p = np; ! 375: if (el == TR_NIL) { ! 376: return (0); ! 377: } ! 378: d = p->value[0]; ! 379: for (i = 1; i <= n; i++) { ! 380: p = p->chain; ! 381: } ! 382: /* ! 383: * Check each subscript ! 384: */ ! 385: for (i = n+1; i <= d; i++) { ! 386: if (el == TR_NIL) { ! 387: return (i-1); ! 388: } ! 389: p = p->chain; ! 390: if (p == NLNIL) ! 391: return (0); ! 392: if ((p->class != CRANGE) && ! 393: (constsub = constval(el->list_node.list))) { ! 394: ap = con.ctype; ! 395: sub = con.crval; ! 396: if (sub < p->range[0] || sub > p->range[1]) { ! 397: error("Subscript value of %D is out of range", (char *) sub); ! 398: return (0); ! 399: } ! 400: sub -= p->range[0]; ! 401: } else { ! 402: # ifdef PC ! 403: precheck( p , "_SUBSC" , "_SUBSCZ" ); ! 404: # endif PC ! 405: ap = rvalue(el->list_node.list, NLNIL , RREQ ); ! 406: if (ap == NIL) { ! 407: return (0); ! 408: } ! 409: # ifdef PC ! 410: postcheck(p, ap); ! 411: sconv(p2type(ap),PCCT_INT); ! 412: # endif PC ! 413: } ! 414: if (incompat(ap, p->type, el->list_node.list)) { ! 415: cerror("Array index type incompatible with declared index type"); ! 416: if (d != 1) { ! 417: cerror("Error occurred on index number %d", (char *) i); ! 418: } ! 419: return (-1); ! 420: } ! 421: if (p->class == CRANGE) { ! 422: constsub = FALSE; ! 423: } else { ! 424: w = aryconst(np, i); ! 425: } ! 426: # ifdef OBJ ! 427: if (constsub) { ! 428: sub *= w; ! 429: if (sub != 0) { ! 430: w = bytes(sub, sub); ! 431: (void) put(2, w <= 2 ? O_CON2 : O_CON4, sub); ! 432: (void) gen(NIL, T_ADD, sizeof(char *), w); ! 433: } ! 434: el = el->list_node.next; ! 435: continue; ! 436: } ! 437: if (p->class == CRANGE) { ! 438: putcbnds(p, 0); ! 439: putcbnds(p, 1); ! 440: putcbnds(p, 2); ! 441: } else if (opt('t') == 0) { ! 442: switch (w) { ! 443: case 8: ! 444: w = 6; ! 445: case 4: ! 446: case 2: ! 447: case 1: ! 448: (void) put(2, (width(ap) != 4 ? O_INX2P2 : O_INX4P2) | (w & ~1) << 7, ( short ) p->range[0]); ! 449: el = el->list_node.next; ! 450: continue; ! 451: } ! 452: } ! 453: if (p->class == CRANGE) { ! 454: if (width(p) == 4) { ! 455: put(1, width(ap) != 4 ? O_VINX42 : O_VINX4); ! 456: } else { ! 457: put(1, width(ap) != 4 ? O_VINX2 : O_VINX24); ! 458: } ! 459: } else { ! 460: put(4, width(ap) != 4 ? O_INX2 : O_INX4, w, ! 461: (short)p->range[0], (short)(p->range[1])); ! 462: } ! 463: el = el->list_node.next; ! 464: continue; ! 465: # endif OBJ ! 466: # ifdef PC ! 467: /* ! 468: * subtract off the lower bound ! 469: */ ! 470: if (constsub) { ! 471: sub *= w; ! 472: if (sub != 0) { ! 473: putleaf( PCC_ICON , (int) sub , 0 , PCCT_INT , (char *) 0 ); ! 474: putop(PCC_PLUS, PCCM_ADDTYPE(p2type(np->type), PCCTM_PTR)); ! 475: } ! 476: el = el->list_node.next; ! 477: continue; ! 478: } ! 479: if (p->class == CRANGE) { ! 480: /* ! 481: * if conformant array, subtract off lower bound ! 482: */ ! 483: ap = p->nptr[0]; ! 484: putRV(ap->symbol, (ap->nl_block & 037), ap->value[0], ! 485: ap->extra_flags, p2type( ap ) ); ! 486: putop( PCC_MINUS, PCCT_INT ); ! 487: /* ! 488: * and multiply by the width of the elements ! 489: */ ! 490: ap = p->nptr[2]; ! 491: putRV( 0 , (ap->nl_block & 037), ap->value[0], ! 492: ap->extra_flags, p2type( ap ) ); ! 493: putop( PCC_MUL , PCCT_INT ); ! 494: } else { ! 495: if ( p -> range[ 0 ] != 0 ) { ! 496: putleaf( PCC_ICON , (int) p -> range[0] , 0 , PCCT_INT , (char *) 0 ); ! 497: putop( PCC_MINUS , PCCT_INT ); ! 498: } ! 499: /* ! 500: * multiply by the width of the elements ! 501: */ ! 502: if ( w != 1 ) { ! 503: putleaf( PCC_ICON , w , 0 , PCCT_INT , (char *) 0 ); ! 504: putop( PCC_MUL , PCCT_INT ); ! 505: } ! 506: } ! 507: /* ! 508: * and add it to the base address ! 509: */ ! 510: putop( PCC_PLUS , PCCM_ADDTYPE( p2type( np -> type ) , PCCTM_PTR ) ); ! 511: el = el->list_node.next; ! 512: # endif PC ! 513: } ! 514: if (el != TR_NIL) { ! 515: if (np->type->class != ARRAY) { ! 516: do { ! 517: el = el->list_node.next; ! 518: i++; ! 519: } while (el != TR_NIL); ! 520: error("Too many subscripts (%d given, %d required)", (char *) (i-1), (char *) d); ! 521: return (-1); ! 522: } else { ! 523: return(arycod(np->type, el, d)); ! 524: } ! 525: } ! 526: return (d); ! 527: } ! 528: ! 529: #ifdef OBJ ! 530: /* ! 531: * Put out the conformant array bounds (lower bound, upper bound or width) ! 532: * for conformant array type ctype. ! 533: * The value of i determines which is being put ! 534: * i = 0: lower bound, i=1: upper bound, i=2: width ! 535: */ ! 536: putcbnds(ctype, i) ! 537: struct nl *ctype; ! 538: int i; ! 539: { ! 540: switch(width(ctype->type)) { ! 541: case 1: ! 542: put(2, O_RV1 | (ctype->nl_block & 037) << 8+INDX, ! 543: (int)ctype->nptr[i]->value[0]); ! 544: break; ! 545: case 2: ! 546: put(2, O_RV2 | (ctype->nl_block & 037) << 8+INDX, ! 547: (int)ctype->nptr[i]->value[0]); ! 548: break; ! 549: case 4: ! 550: default: ! 551: put(2, O_RV4 | (ctype->nl_block & 037) << 8+INDX, ! 552: (int)ctype->nptr[i]->value[0]); ! 553: } ! 554: } ! 555: #endif OBJ
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.