|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)pclval.c 1.4 6/1/81"; ! 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: /* ! 12: * and the rest of the file ! 13: */ ! 14: # include "pc.h" ! 15: # include "pcops.h" ! 16: ! 17: extern int flagwas; ! 18: /* ! 19: * pclvalue computes the address ! 20: * of a qualified name and ! 21: * leaves it on the stack. ! 22: * for pc, it can be asked for either an lvalue or an rvalue. ! 23: * the semantics are the same, only the code is different. ! 24: * for putting out calls to check for nil and fnil, ! 25: * we have to traverse the list of qualifications twice: ! 26: * once to put out the calls and once to put out the address to be checked. ! 27: */ ! 28: struct nl * ! 29: pclvalue( r , modflag , required ) ! 30: int *r; ! 31: int modflag; ! 32: int required; ! 33: { ! 34: register struct nl *p; ! 35: register *c, *co; ! 36: int f, o; ! 37: int tr[2], trp[3]; ! 38: struct nl *firstp; ! 39: struct nl *lastp; ! 40: char *firstsymbol; ! 41: char firstextra_flags; ! 42: int firstbn; ! 43: ! 44: if ( r == NIL ) { ! 45: return NIL; ! 46: } ! 47: if ( nowexp( r ) ) { ! 48: return NIL; ! 49: } ! 50: if ( r[0] != T_VAR ) { ! 51: error("Variable required"); /* Pass mesgs down from pt of call ? */ ! 52: return NIL; ! 53: } ! 54: firstp = p = lookup( r[2] ); ! 55: if ( p == NIL ) { ! 56: return NIL; ! 57: } ! 58: firstsymbol = p -> symbol; ! 59: firstbn = bn; ! 60: firstextra_flags = p -> extra_flags; ! 61: c = r[3]; ! 62: if ( ( modflag & NOUSE ) && ! lptr( c ) ) { ! 63: p -> nl_flags = flagwas; ! 64: } ! 65: if ( modflag & MOD ) { ! 66: p -> nl_flags |= NMOD; ! 67: } ! 68: /* ! 69: * Only possibilities for p -> class here ! 70: * are the named classes, i.e. CONST, TYPE ! 71: * VAR, PROC, FUNC, REF, or a WITHPTR. ! 72: */ ! 73: if ( p -> class == WITHPTR ) { ! 74: /* ! 75: * Construct the tree implied by ! 76: * the with statement ! 77: */ ! 78: trp[0] = T_LISTPP; ! 79: trp[1] = tr; ! 80: trp[2] = r[3]; ! 81: tr[0] = T_FIELD; ! 82: tr[1] = r[2]; ! 83: c = trp; ! 84: } ! 85: /* ! 86: * this not only puts out the names of functions to call ! 87: * but also does all the semantic checking of the qualifications. ! 88: */ ! 89: if ( ! nilfnil( p , c , modflag , firstp , r[2] ) ) { ! 90: return NIL; ! 91: } ! 92: switch (p -> class) { ! 93: case WITHPTR: ! 94: case REF: ! 95: /* ! 96: * Obtain the indirect word ! 97: * of the WITHPTR or REF ! 98: * as the base of our lvalue ! 99: */ ! 100: putRV( firstsymbol , firstbn , p -> value[ 0 ] , ! 101: firstextra_flags , p2type( p ) ); ! 102: firstsymbol = 0; ! 103: f = 0; /* have an lv on stack */ ! 104: o = 0; ! 105: break; ! 106: case VAR: ! 107: f = 1; /* no lv on stack yet */ ! 108: o = p -> value[0]; ! 109: break; ! 110: default: ! 111: error("%s %s found where variable required", classes[p -> class], p -> symbol); ! 112: return (NIL); ! 113: } ! 114: /* ! 115: * Loop and handle each ! 116: * qualification on the name ! 117: */ ! 118: if ( c == NIL && ! 119: ( modflag & ASGN ) && ! 120: ( p -> value[ NL_FORV ] & FORVAR ) ) { ! 121: error("Can't modify the for variable %s in the range of the loop", p -> symbol); ! 122: return (NIL); ! 123: } ! 124: for ( ; c != NIL ; c = c[2] ) { ! 125: co = c[1]; ! 126: if ( co == NIL ) { ! 127: return NIL; ! 128: } ! 129: lastp = p; ! 130: p = p -> type; ! 131: if ( p == NIL ) { ! 132: return NIL; ! 133: } ! 134: switch ( co[0] ) { ! 135: case T_PTR: ! 136: /* ! 137: * Pointer qualification. ! 138: */ ! 139: if ( f ) { ! 140: putLV( firstsymbol , firstbn , o , ! 141: firstextra_flags , p2type( p ) ); ! 142: firstsymbol = 0; ! 143: } else { ! 144: if (o) { ! 145: putleaf( P2ICON , o , 0 , P2INT ! 146: , 0 ); ! 147: putop( P2PLUS , P2PTR | P2CHAR ); ! 148: } ! 149: } ! 150: /* ! 151: * Pointer cannot be ! 152: * nil and file cannot ! 153: * be at end-of-file. ! 154: * the appropriate function name is ! 155: * already out there from nilfnil. ! 156: */ ! 157: if ( p -> class == PTR ) { ! 158: /* ! 159: * this is the indirection from ! 160: * the address of the pointer ! 161: * to the pointer itself. ! 162: * kirk sez: ! 163: * fnil doesn't want this. ! 164: * and does it itself for files ! 165: * since only it knows where the ! 166: * actual window is. ! 167: * but i have to do this for ! 168: * regular pointers. ! 169: */ ! 170: putop( P2UNARY P2MUL , p2type( p ) ); ! 171: if ( opt( 't' ) ) { ! 172: putop( P2CALL , P2INT ); ! 173: } ! 174: } else { ! 175: putop( P2CALL , P2INT ); ! 176: } ! 177: f = o = 0; ! 178: continue; ! 179: case T_ARGL: ! 180: case T_ARY: ! 181: if ( f ) { ! 182: putLV( firstsymbol , firstbn , o , ! 183: firstextra_flags , p2type( p ) ); ! 184: firstsymbol = 0; ! 185: } else { ! 186: if (o) { ! 187: putleaf( P2ICON , o , 0 , P2INT ! 188: , 0 ); ! 189: putop( P2PLUS , P2INT ); ! 190: } ! 191: } ! 192: arycod( p , co[1] ); ! 193: f = o = 0; ! 194: continue; ! 195: case T_FIELD: ! 196: /* ! 197: * Field names are just ! 198: * an offset with some ! 199: * semantic checking. ! 200: */ ! 201: p = reclook(p, co[1]); ! 202: o += p -> value[0]; ! 203: continue; ! 204: default: ! 205: panic("lval2"); ! 206: } ! 207: } ! 208: if (f) { ! 209: if ( required == LREQ ) { ! 210: putLV( firstsymbol , firstbn , o , ! 211: firstextra_flags , p2type( p -> type ) ); ! 212: } else { ! 213: putRV( firstsymbol , firstbn , o , ! 214: firstextra_flags , p2type( p -> type ) ); ! 215: } ! 216: } else { ! 217: if (o) { ! 218: putleaf( P2ICON , o , 0 , P2INT , 0 ); ! 219: putop( P2PLUS , P2INT ); ! 220: } ! 221: if ( required == RREQ ) { ! 222: putop( P2UNARY P2MUL , p2type( p -> type ) ); ! 223: } ! 224: } ! 225: return ( p -> type ); ! 226: } ! 227: ! 228: /* ! 229: * this recursively follows done a list of qualifications ! 230: * and puts out the beginnings of calls to fnil for files ! 231: * or nil for pointers (if checking is on) on the way back. ! 232: * this returns true or false. ! 233: */ ! 234: nilfnil( p , c , modflag , firstp , r2 ) ! 235: struct nl *p; ! 236: int *c; ! 237: int modflag; ! 238: struct nl *firstp; ! 239: char *r2; /* no, not r2-d2 */ ! 240: { ! 241: int *co; ! 242: struct nl *lastp; ! 243: int t; ! 244: ! 245: if ( c == NIL ) { ! 246: return TRUE; ! 247: } ! 248: co = (int *) ( c[1] ); ! 249: if ( co == NIL ) { ! 250: return FALSE; ! 251: } ! 252: lastp = p; ! 253: p = p -> type; ! 254: if ( p == NIL ) { ! 255: return FALSE; ! 256: } ! 257: switch ( co[0] ) { ! 258: case T_PTR: ! 259: /* ! 260: * Pointer qualification. ! 261: */ ! 262: lastp -> nl_flags |= NUSED; ! 263: if ( p -> class != PTR && p -> class != FILET) { ! 264: error("^ allowed only on files and pointers, not on %ss", nameof(p)); ! 265: goto bad; ! 266: } ! 267: break; ! 268: case T_ARGL: ! 269: if ( p -> class != ARRAY ) { ! 270: if ( lastp == firstp ) { ! 271: error("%s is a %s, not a function", r2, classes[firstp -> class]); ! 272: } else { ! 273: error("Illegal function qualificiation"); ! 274: } ! 275: return FALSE; ! 276: } ! 277: recovered(); ! 278: error("Pascal uses [] for subscripting, not ()"); ! 279: /* and fall through */ ! 280: case T_ARY: ! 281: if ( p -> class != ARRAY ) { ! 282: error("Subscripting allowed only on arrays, not on %ss", nameof(p)); ! 283: goto bad; ! 284: } ! 285: codeoff(); ! 286: t = arycod( p , co[1] ); ! 287: codeon(); ! 288: switch ( t ) { ! 289: case 0: ! 290: return FALSE; ! 291: case -1: ! 292: goto bad; ! 293: } ! 294: break; ! 295: case T_FIELD: ! 296: /* ! 297: * Field names are just ! 298: * an offset with some ! 299: * semantic checking. ! 300: */ ! 301: if ( p -> class != RECORD ) { ! 302: error(". allowed only on records, not on %ss", nameof(p)); ! 303: goto bad; ! 304: } ! 305: if ( co[1] == NIL ) { ! 306: return FALSE; ! 307: } ! 308: p = reclook( p , co[1] ); ! 309: if ( p == NIL ) { ! 310: error("%s is not a field in this record", co[1]); ! 311: goto bad; ! 312: } ! 313: if ( modflag & MOD ) { ! 314: p -> nl_flags |= NMOD; ! 315: } ! 316: if ( ( modflag & NOUSE ) == 0 || lptr( c[2] ) ) { ! 317: p -> nl_flags |= NUSED; ! 318: } ! 319: break; ! 320: default: ! 321: panic("nilfnil"); ! 322: } ! 323: /* ! 324: * recursive call, check the rest of the qualifications. ! 325: */ ! 326: if ( ! nilfnil( p , c[2] , modflag , firstp , r2 ) ) { ! 327: return FALSE; ! 328: } ! 329: /* ! 330: * the point of all this. ! 331: */ ! 332: if ( co[0] == T_PTR ) { ! 333: if ( p -> class == PTR ) { ! 334: if ( opt( 't' ) ) { ! 335: putleaf( P2ICON , 0 , 0 ! 336: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 337: , "_NIL" ); ! 338: } ! 339: } else { ! 340: putleaf( P2ICON , 0 , 0 ! 341: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 342: , "_FNIL" ); ! 343: } ! 344: } ! 345: return TRUE; ! 346: bad: ! 347: cerror("Error occurred on qualification of %s", r2); ! 348: return FALSE; ! 349: } ! 350: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.