|
|
1.1 ! root 1: /* ! 2: * Routines for symbol table manipulation. ! 3: */ ! 4: ! 5: #include "ilink.h" ! 6: ! 7: int dynoff; /* stack offset counter for locals */ ! 8: int argoff; /* stack offset counter for arguments */ ! 9: int static1; /* first static in procedure */ ! 10: int statics = 0; /* static variable counter */ ! 11: ! 12: int nlocal; /* number of locals in local table */ ! 13: int nconst; /* number of constants in constant table */ ! 14: int nfields = 0; /* number of fields in field table */ ! 15: ! 16: /* ! 17: * instalid - copy the string s to the start of the string free space ! 18: * and call putident with the length of the string. ! 19: */ ! 20: char *instalid(s) ! 21: char *s; ! 22: { ! 23: register int l; ! 24: register char *p1, *p2; ! 25: extern char *putident(); ! 26: ! 27: p1 = strfree; ! 28: p2 = s; ! 29: l = 1; ! 30: while (*p1++ = *p2++) ! 31: l++; ! 32: return putident(l); ! 33: } ! 34: ! 35: /* ! 36: * putident - install the identifier named by the string starting at strfree ! 37: * and extending for len bytes. The installation entails making an ! 38: * entry in the identifier hash table and then making an identifier ! 39: * table entry for it with alcident. A side effect of installation ! 40: * is the incrementing of strfree by the length of the string, thus ! 41: * "saving" it. ! 42: * ! 43: * Nothing is changed if the identifier has already been installed. ! 44: */ ! 45: char *putident(len) ! 46: int len; ! 47: { ! 48: register int hash; ! 49: register char *s; ! 50: register struct ientry *ip; ! 51: int l; ! 52: extern struct ientry *alcident(); ! 53: ! 54: /* ! 55: * Compute hash value by adding bytes and masking result with imask. ! 56: * (Recall that imask is ihsize-1.) ! 57: */ ! 58: s = strfree; ! 59: hash = 0; ! 60: l = len; ! 61: while (l--) ! 62: hash += *s++; ! 63: l = len; ! 64: s = strfree; ! 65: hash &= imask; ! 66: /* ! 67: * If the identifier hasn't been installed, install it. ! 68: */ ! 69: if ((ip = ihash[hash]) != NULL) { /* collision */ ! 70: for (;;) { /* work down i_blink chain until id is found or the ! 71: end of the chain is reached */ ! 72: if (l == ip->i_length && lexeq(l, s, ip->i_name)) ! 73: return (ip->i_name); /* id is already installed, return it */ ! 74: if (ip->i_blink == NULL) { /* end of chain */ ! 75: ip->i_blink = alcident(NULL, s, l); ! 76: strfree += l; ! 77: return s; ! 78: } ! 79: ip = ip->i_blink; ! 80: } ! 81: } ! 82: /* ! 83: * Hashed to an empty slot. ! 84: */ ! 85: ihash[hash] = alcident(NULL, s, l); ! 86: strfree += l; ! 87: return s; ! 88: } ! 89: ! 90: /* ! 91: * lexeq - compare two strings of given length. Returns non-zero if ! 92: * equal, zero if not equal. ! 93: */ ! 94: lexeq(l, s1, s2) ! 95: register int l; ! 96: register char *s1, *s2; ! 97: { ! 98: while (l--) ! 99: if (*s1++ != *s2++) ! 100: return 0; ! 101: return 1; ! 102: } ! 103: ! 104: /* ! 105: * alcident - get the next free identifier table entry, and fill it in with ! 106: * the specified values. ! 107: */ ! 108: struct ientry *alcident(blink, nam, len) ! 109: struct ientry *blink; ! 110: char *nam; ! 111: int len; ! 112: { ! 113: register struct ientry *ip; ! 114: ! 115: if (ifree >= &itable[isize]) ! 116: syserr("out of identifier table space"); ! 117: ip = ifree++; ! 118: ip->i_blink = blink; ! 119: ip->i_name = nam; ! 120: ip->i_length = len; ! 121: return ip; ! 122: } ! 123: ! 124: /* ! 125: * locinit - clear local symbol table. ! 126: */ ! 127: locinit() ! 128: { ! 129: dynoff = 0; ! 130: argoff = 0; ! 131: nlocal = -1; ! 132: nconst = -1; ! 133: static1 = statics; ! 134: } ! 135: ! 136: /* ! 137: * putloc - make a local symbol table entry. ! 138: */ ! 139: struct lentry *putloc(n, id, flags, imperror, procname) ! 140: int n; ! 141: char *id; ! 142: register int flags; ! 143: int imperror; ! 144: char *procname; ! 145: { ! 146: register struct lentry *lp; ! 147: register union { ! 148: struct gentry *gp; ! 149: int bn; ! 150: } p; ! 151: extern struct gentry *glocate(), *putglob(); ! 152: ! 153: if (n >= lsize) ! 154: syserr("out of local symbol table space."); ! 155: if (n > nlocal) ! 156: nlocal = n; ! 157: lp = <able[n]; ! 158: lp->l_name = id; ! 159: lp->l_flag = flags; ! 160: if (flags == 0) { /* undeclared */ ! 161: if ((p.gp = glocate(id)) != NULL) { /* check global */ ! 162: lp->l_flag = F_Global; ! 163: lp->l_val.global = p.gp; ! 164: } ! 165: else if ((p.bn = blocate(id)) != 0) { /* check builtin */ ! 166: lp->l_flag = F_Builtin; ! 167: lp->l_val.global = putglob(id, F_Builtin | F_Proc, -1, p.bn); ! 168: } ! 169: else { /* implicit local */ ! 170: if (imperror) ! 171: warn(id, "undeclared identifier, procedure ", procname); ! 172: lp->l_flag = F_Dynamic; ! 173: lp->l_val.offset = ++dynoff; ! 174: } ! 175: } ! 176: else if (flags & F_Global) { /* global variable */ ! 177: if ((p.gp = glocate(id)) == NULL) ! 178: syserr("putloc: global not in global table"); ! 179: lp->l_val.global = p.gp; ! 180: } ! 181: else if (flags & F_Argument) /* procedure argument */ ! 182: lp->l_val.offset = ++argoff; ! 183: else if (flags & F_Dynamic) /* local dynamic */ ! 184: lp->l_val.offset = ++dynoff; ! 185: else if (flags & F_Static) /* local static */ ! 186: lp->l_val.staticid = ++statics; ! 187: else ! 188: syserr("putloc: unknown flags"); ! 189: return lp; ! 190: } ! 191: ! 192: /* ! 193: * putglob - make a global symbol table entry. ! 194: */ ! 195: struct gentry *putglob(id, flags, nargs, procid) ! 196: char *id; ! 197: int flags; ! 198: int nargs; ! 199: int procid; ! 200: { ! 201: register struct gentry *p; ! 202: extern struct gentry *glocate(), *alcglob(); ! 203: ! 204: if ((p = glocate(id)) == NULL) { /* add to head of hash chain */ ! 205: p = ghash[ghasher(id)]; ! 206: ghash[ghasher(id)] = alcglob(p, id, flags, nargs, procid); ! 207: return ghash[ghasher(id)]; ! 208: } ! 209: p->g_flag |= flags; ! 210: p->g_nargs = nargs; ! 211: p->g_procid = procid; ! 212: return p; ! 213: } ! 214: ! 215: /* ! 216: * putconst - make a constant symbol table entry. ! 217: */ ! 218: struct centry *putconst(n, flags, len, pc, val) ! 219: int n; ! 220: int flags, len; ! 221: word pc; ! 222: union { ! 223: long ival; ! 224: double rval; ! 225: char *sval; ! 226: } val; ! 227: { ! 228: register struct centry *p; ! 229: #if IntSize == 16 ! 230: int minsh, maxsh; ! 231: ! 232: minsh = MinShort; ! 233: maxsh = MaxShort; ! 234: #endif IntSize == 16 ! 235: if (n >= csize) ! 236: syserr("out of constant table space"); ! 237: if (nconst < n) ! 238: nconst = n; ! 239: p = &ctable[n]; ! 240: p->c_flag = flags; ! 241: p->c_pc = pc; ! 242: if (flags & F_IntLit) { ! 243: p->c_val.ival = val.ival; ! 244: #if IntSize == 16 ! 245: if (val.ival < (long)minsh | val.ival > (long)maxsh) ! 246: p->c_flag |= F_LongLit; ! 247: #endif IntSize == 16 ! 248: } ! 249: else if (flags & F_StrLit) { ! 250: p->c_val.sval = val.sval; ! 251: p->c_length = len; ! 252: } ! 253: else if (flags & F_CsetLit) { ! 254: p->c_val.sval = val.sval; ! 255: p->c_length = len; ! 256: } ! 257: else if (flags & F_RealLit) ! 258: #ifdef Double ! 259: /* access real values one word at a time */ ! 260: { int *rp, *rq; ! 261: rp = (int *) &(p->c_val.rval); ! 262: rq = (int *) &(val.rval); ! 263: *rp++ = *rq++; ! 264: *rp = *rq; ! 265: } ! 266: #else Double ! 267: p->c_val.rval = val.rval; ! 268: #endif Double ! 269: else ! 270: fprintf(stderr, "putconst: bad flags: %06o %011lo\n", flags, val.ival); ! 271: return p; ! 272: } ! 273: ! 274: /* ! 275: * putfield - make a record/field table entry. ! 276: */ ! 277: putfield(fname, rnum, fnum) ! 278: char *fname; ! 279: int rnum, fnum; ! 280: { ! 281: register struct fentry *fp; ! 282: register struct rentry *rp, *rp2; ! 283: word hash; ! 284: extern struct fentry *flocate(), *alcfhead(); ! 285: extern struct rentry *alcfrec(); ! 286: ! 287: fp = flocate(fname); ! 288: if (fp == NULL) { /* create a field entry */ ! 289: nfields++; ! 290: hash = fhasher(fname); ! 291: fp = fhash[hash]; ! 292: fhash[hash] = alcfhead(fp, fname, nfields, alcfrec(NULL, rnum, fnum)); ! 293: return; ! 294: } ! 295: rp = fp->f_rlist; /* found field entry, look for */ ! 296: if (rp->r_recid > rnum) { /* spot in record list */ ! 297: fp->f_rlist = alcfrec(rp, rnum, fnum); ! 298: return; ! 299: } ! 300: while (rp->r_recid < rnum) { /* keep record list ascending */ ! 301: if (rp->r_link == NULL) { ! 302: rp->r_link = alcfrec(NULL, rnum, fnum); ! 303: return; ! 304: } ! 305: rp2 = rp; ! 306: rp = rp->r_link; ! 307: } ! 308: rp2->r_link = alcfrec(rp, rnum, fnum); ! 309: } ! 310: ! 311: /* ! 312: * glocate - lookup identifier in global symbol table, return NULL ! 313: * if not present. ! 314: */ ! 315: struct gentry *glocate(id) ! 316: char *id; ! 317: { ! 318: register struct gentry *p; ! 319: ! 320: p = ghash[ghasher(id)]; ! 321: while (p != NULL && p->g_name != id) ! 322: p = p->g_blink; ! 323: return p; ! 324: } ! 325: ! 326: /* ! 327: * flocate - lookup identifier in field table. ! 328: */ ! 329: struct fentry *flocate(id) ! 330: char *id; ! 331: { ! 332: register struct fentry *p; ! 333: ! 334: p = fhash[fhasher(id)]; ! 335: while (p != NULL && p->f_name != id) ! 336: p = p->f_blink; ! 337: return p; ! 338: } ! 339: ! 340: /* ! 341: * alcglob - create a new global symbol table entry. ! 342: */ ! 343: struct gentry *alcglob(blink, name, flag, nargs, procid) ! 344: struct gentry *blink; ! 345: char *name; ! 346: int flag; ! 347: int nargs; ! 348: int procid; ! 349: { ! 350: register struct gentry *gp; ! 351: ! 352: if (gfree >= >able[gsize]) ! 353: syserr("out of global symbol table space"); ! 354: gp = gfree++; ! 355: gp->g_blink = blink; ! 356: gp->g_name = name; ! 357: gp->g_flag = flag; ! 358: gp->g_nargs = nargs; ! 359: gp->g_procid = procid; ! 360: return gp; ! 361: } ! 362: ! 363: /* ! 364: * alcfhead - allocate a field table header. ! 365: */ ! 366: struct fentry *alcfhead(blink, name, fid, rlist) ! 367: struct fentry *blink; ! 368: char *name; ! 369: int fid; ! 370: struct rentry *rlist; ! 371: { ! 372: register struct fentry *fp; ! 373: ! 374: if (ffree >= &ftable[fsize]) ! 375: syserr("out of field table space"); ! 376: fp = ffree++; ! 377: fp->f_blink = blink; ! 378: fp->f_name = name; ! 379: fp->f_fid = fid; ! 380: fp->f_rlist = rlist; ! 381: return fp; ! 382: } ! 383: ! 384: /* ! 385: * alcfrec - allocate a field table record list element. ! 386: */ ! 387: struct rentry *alcfrec(link, rnum, fnum) ! 388: struct rentry *link; ! 389: int rnum, fnum; ! 390: { ! 391: register struct rentry *rp; ! 392: ! 393: if (rfree >= &rtable[rsize]) ! 394: syserr("out of field table space for record lists"); ! 395: rp = rfree++; ! 396: rp->r_link = link; ! 397: rp->r_recid = rnum; ! 398: rp->r_fnum = fnum; ! 399: return rp; ! 400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.