|
|
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.