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