|
|
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 = sfree; ! 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 sfree ! 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 sfree 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 = sfree; ! 59: hash = 0; ! 60: l = len; ! 61: while (l--) ! 62: hash += *s++; ! 63: l = len; ! 64: s = sfree; ! 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: sfree += 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: sfree += 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: int pc; ! 222: union { ! 223: long ival; ! 224: double rval; ! 225: char *sval; ! 226: } val; ! 227: { ! 228: register struct centry *p; ! 229: ! 230: if (n >= csize) ! 231: syserr("out of constant table space"); ! 232: if (nconst < n) ! 233: nconst = n; ! 234: p = &ctable[n]; ! 235: p->c_flag = flags; ! 236: p->c_pc = pc; ! 237: if (flags & F_INTLIT) { ! 238: p->c_val.ival = val.ival; ! 239: #ifdef LONGS ! 240: if (val.ival < (long)(short)MINSHORT | val.ival > (long)(short)MAXSHORT) ! 241: p->c_flag |= F_LONGLIT; ! 242: #endif LONGS ! 243: } ! 244: else if (flags & F_STRLIT) { ! 245: p->c_val.sval = val.sval; ! 246: p->c_length = len; ! 247: } ! 248: else if (flags & F_CSETLIT) { ! 249: p->c_val.sval = val.sval; ! 250: p->c_length = len; ! 251: } ! 252: else if (flags & F_REALLIT) ! 253: p->c_val.rval = val.rval; ! 254: else ! 255: fprintf(stderr, "putconst: bad flags: %06o %011o\n", flags, val.ival); ! 256: return (p); ! 257: } ! 258: ! 259: /* ! 260: * putfield - make a record/field table entry. ! 261: */ ! 262: putfield(fname, rnum, fnum) ! 263: char *fname; ! 264: int rnum, fnum; ! 265: { ! 266: register struct fentry *fp; ! 267: register struct rentry *rp, *rp2; ! 268: int hash; ! 269: extern struct fentry *flocate(), *alcfhead(); ! 270: extern struct rentry *alcfrec(); ! 271: ! 272: fp = flocate(fname); ! 273: if (fp == NULL) { /* create a field entry */ ! 274: nfields++; ! 275: hash = fhasher(fname); ! 276: fp = fhash[hash]; ! 277: fhash[hash] = alcfhead(fp, fname, nfields, alcfrec(NULL, rnum, fnum)); ! 278: return; ! 279: } ! 280: rp = fp->f_rlist; /* found field entry, look for */ ! 281: if (rp->r_recid > rnum) { /* spot in record list */ ! 282: fp->f_rlist = alcfrec(rp, rnum, fnum); ! 283: return; ! 284: } ! 285: while (rp->r_recid < rnum) { /* keep record list ascending */ ! 286: if (rp->r_link == NULL) { ! 287: rp->r_link = alcfrec(NULL, rnum, fnum); ! 288: return; ! 289: } ! 290: rp2 = rp; ! 291: rp = rp->r_link; ! 292: } ! 293: rp2->r_link = alcfrec(rp, rnum, fnum); ! 294: } ! 295: ! 296: /* ! 297: * glocate - lookup identifier in global symbol table, return NULL ! 298: * if not present. ! 299: */ ! 300: struct gentry *glocate(id) ! 301: char *id; ! 302: { ! 303: register struct gentry *p; ! 304: ! 305: p = ghash[ghasher(id)]; ! 306: while (p != NULL && p->g_name != id) ! 307: p = p->g_blink; ! 308: return (p); ! 309: } ! 310: ! 311: /* ! 312: * flocate - lookup identifier in field table. ! 313: */ ! 314: struct fentry *flocate(id) ! 315: char *id; ! 316: { ! 317: register struct fentry *p; ! 318: ! 319: p = fhash[fhasher(id)]; ! 320: while (p != NULL && p->f_name != id) ! 321: p = p->f_blink; ! 322: return (p); ! 323: } ! 324: ! 325: /* ! 326: * alcglob - create a new global symbol table entry. ! 327: */ ! 328: struct gentry *alcglob(blink, name, flag, nargs, procid) ! 329: struct gentry *blink; ! 330: char *name; ! 331: int flag; ! 332: int nargs; ! 333: int procid; ! 334: { ! 335: register struct gentry *gp; ! 336: ! 337: if (gfree >= >able[gsize]) ! 338: syserr("out of global symbol table space"); ! 339: gp = gfree++; ! 340: gp->g_blink = blink; ! 341: gp->g_name = name; ! 342: gp->g_flag = flag; ! 343: gp->g_nargs = nargs; ! 344: gp->g_procid = procid; ! 345: return (gp); ! 346: } ! 347: ! 348: /* ! 349: * alcfhead - allocate a field table header. ! 350: */ ! 351: struct fentry *alcfhead(blink, name, fid, rlist) ! 352: struct fentry *blink; ! 353: char *name; ! 354: int fid; ! 355: struct rentry *rlist; ! 356: { ! 357: register struct fentry *fp; ! 358: ! 359: if (ffree >= &ftable[fsize]) ! 360: syserr("out of field table space"); ! 361: fp = ffree++; ! 362: fp->f_blink = blink; ! 363: fp->f_name = name; ! 364: fp->f_fid = fid; ! 365: fp->f_rlist = rlist; ! 366: return (fp); ! 367: } ! 368: ! 369: /* ! 370: * alcfrec - allocate a field table record list element. ! 371: */ ! 372: struct rentry *alcfrec(link, rnum, fnum) ! 373: struct rentry *link; ! 374: int rnum, fnum; ! 375: { ! 376: register struct rentry *rp; ! 377: ! 378: if (rfree >= &rtable[rsize]) ! 379: syserr("out of field table space for record lists"); ! 380: rp = rfree++; ! 381: rp->r_link = link; ! 382: rp->r_recid = rnum; ! 383: rp->r_fnum = fnum; ! 384: return (rp); ! 385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.