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: }