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