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