|
|
1.1 root 1: /*ident "@(#)ctrans:src/table.c 1.1.1.4" */
2: /**************************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: table.c:
11:
12: *****************************************************************************/
13:
14: #include "cfront.h"
15:
16: char* keys[MAXTOK+1];
17: /*
18: keys[] holds the external form for tokens with fixed representation
19: illegal tokens and those with variable representation have 0 entries
20: */
21:
22: /*
23: the class table functions assume that new initializes store to 0
24: */
25:
26: table::table(short sz, Ptable nx, Pname n)
27: /*
28: create a symbol table with "size" entries
29: the scope of table is enclosed in the scope of "nx"
30:
31: both the vector of class name pointers and the hash table
32: are initialized containing all zeroes
33:
34: to simplify hashed lookup entries[0] is never used
35: so the size of "entries" must be "size+1" to hold "size" entries
36: */
37: {
38: base = TABLE;
39: t_name = n;
40: size = sz = (sz<=0) ? 2 : sz+1;
41: //fprintf(stderr,"table::table %d %s %d (%d %d)\n", this, (n)?n->string:"?", sz,(sz*3)/2);
42: entries = new Pname[sz];
43: hashsize = sz = (sz*3)/2;
44: hashtbl = new short[sz];
45: next = nx;
46: free_slot = 1;
47: }
48:
49:
50: Pname table::look(char* s, TOK k)
51: /*
52: look for "s" in table, ignore entries which are not of "k" type
53: look and insert MUST be the same lookup algorithm
54: */
55: {
56: Ptable t;
57: register char * p;
58: register char * q;
59: register int i;
60: Pname n;
61: int rr;
62:
63: // if (s == 0) error('i',"%d->look(0)",this);
64: // if (this == 0) error('i',"0->look(%s)",s);
65: // if (base != TABLE) error('i',"(%d,%d)->look(%s)",this,base,s);
66:
67: /* use simple hashing with linear search for overflow */
68:
69: p = s;
70: i = 0;
71: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
72: rr = (0<=i) ? i : -i;
73:
74: for (t=this; t; t=t->next) {
75: /* in this and all enclosing scopes look for name "s" */
76: Pname* np = t->entries;
77: int mx = t->hashsize;
78: short* hash = t->hashtbl;
79: int firsti = i = rr%mx;
80:
81: do {
82: if (hash[i] == 0) goto not_found;
83: n = np[hash[i]];
84: if (n == 0) error('i',"hashed lookup");
85: p = n->string; /* strcmp(n->n_string,s) */
86: q = s;
87: while (*p && *q)
88: if (*p++ != *q++) goto nxt;
89: if (*p == *q) goto found;
90: nxt:
91: if (mx <= ++i) i = 0; /* wrap around */
92: } while (i != firsti);
93:
94: found:
95: for (; n; n=n->n_tbl_list){ /* for all name "s"s look for a key match */
96: if (n->n_key == k) return n;
97: }
98:
99: not_found:;
100: }
101:
102: return 0; /* not found && no enclosing scope */
103: }
104:
105: bit Nold; /* non-zero if last insert() failed */
106:
107: Pname table::insert(Pname nx, TOK k)
108: /*
109: the lookup algorithm MUST be the same as look
110: if nx is found return the older entry otherwise a copy of nx;
111: Nold = (nx found) ? 1 : 0;
112: */
113: {
114: register char * p;
115: register int i;
116: Pname n;
117: Pname* np = entries;
118: Pname* link;
119: int firsti;
120: int mx = hashsize;
121: short* hash = hashtbl;
122: char* s = nx->string;
123:
124: if (s==0) error('i',"%p->insert(0,%k)",this,k);
125: nx->n_key = k;
126: if (nx->n_tbl_list || nx->n_table) error('i',"%n in two tables",nx);
127: /* use simple hashing with linear search for overflow */
128:
129: p = s;
130: i = 0;
131: while (*p) i += (i + *p++);
132: if (i<0) i = -i;
133: firsti = i = i%mx;
134:
135: do { /* look for name "s" */
136: if (hash[i] == 0) {
137: hash[i] = free_slot;
138: goto add_np;
139: }
140: n = np[hash[i]];
141: if (n == 0) error('i',"hashed lookup");
142: if (strcmp(n->string,s) == 0) goto found;
143: /*
144: p = n->string;
145: q = s;
146: while (*p && *q) if (*p++ != *q++) goto nxt;
147: if (*p == *q) goto found;
148: nxt:
149: */
150: if (mx <= ++i) i = 0; /* wrap around */
151: } while (i != firsti);
152:
153: error("N table full");
154:
155: found:
156:
157:
158: for(;;) {
159: if (n->n_key == k) { Nold = 1; return n; }
160:
161: if (n->n_tbl_list)
162: n = n->n_tbl_list;
163: else {
164: link = &(n->n_tbl_list);
165: goto re_allocate;
166: }
167: }
168:
169: add_np:
170: if (size <= free_slot) {
171: grow(2*size);
172: return insert(nx,k);
173: }
174:
175: link = &(np[free_slot++]);
176:
177: re_allocate:
178: {
179: Pname nw = new name;
180: *nw = *nx;
181: char* ps = new char[strlen(s)+1]; // copy string to safer store
182: strcpy(ps,s);
183: // Nstr++;
184: nw->string = ps;
185: nw->n_table = this;
186: *link = nw;
187: Nold = 0;
188: // Nname++;
189: return nw;
190: }
191: }
192:
193: void table::grow(int g)
194: {
195: short* hash;
196: register int j;
197: int mx;
198: register Pname* np;
199: Pname n;
200:
201: if (g <= free_slot) error('i',"table.grow(%d,%d)",g,free_slot);
202: if (g <= size) return;
203: //error('d',"grow %d %s %d->%d", this, (t_name)?t_name->string:"?", size, g+1);
204: size = mx = g+1;
205:
206: np = new Pname[mx];
207: for (j=0; j<free_slot; j++) np[j] = entries[j];
208: delete entries;
209: entries = np;
210:
211: delete hashtbl;
212: hashsize = mx = (g*3)/2;
213: hash = hashtbl = new short[mx];
214:
215: for (j=1; j<free_slot; j++) { /* rehash(np[j]); */
216: char * s = np[j]->string;
217: register char * p;
218: char * q;
219: register int i;
220: int firsti;
221:
222: p = s;
223: i = 0;
224: while (*p) i += (i + *p++);
225: if (i<0) i = -i;
226: firsti = i = i%mx;
227:
228: do { /* look for name "s" */
229: if (hash[i] == 0) {
230: hash[i] = j;
231: goto add_np;
232: }
233: n = np[hash[i]];
234: if (n == 0) error('i',"hashed lookup");
235: p = n->string; /* strcmp(n->n_string,s) */
236: q = s;
237: while (*p && *q) if (*p++ != *q++) goto nxt;
238: if (*p == *q) goto found;
239: nxt:
240: if (mx <= ++i) i = 0; /* wrap around */
241: } while (i != firsti);
242:
243: error('i',"rehash??");
244:
245: found:
246: error('i',"rehash failed");
247:
248: add_np:;
249: }
250: }
251:
252: Pclass Ebase;
253: Pclass Epriv; /* extra return values from lookc() */
254:
255: Pname table::get_mem(int i)
256: /*
257: return a pointer to the i'th entry, or 0 if it does not exist
258: */
259: {
260: return (i<=0 || free_slot<=i) ? 0 : entries[i];
261: }
262:
263: void new_key(char* s, TOK toknum, TOK yyclass)
264: /*
265: make "s" a new keyword with the representation (token) "toknum"
266: "yyclass" is the yacc token (for example new_key("int",INT,TYPE); )
267: "yyclass==0" means yyclass=toknum;
268: */
269: {
270: Pname n = new name(s);
271: Pname nn = ktbl->insert(n,0);
272: // if (Nold) error('i',"keyword %sD twice",s);
273: nn->base = toknum;
274: nn->syn_class = (yyclass) ? yyclass : toknum;
275: keys[(toknum==LOC)?yyclass:toknum] = s;
276: delete n;
277: }
278:
279: void table_delete(char* s, TOK k, int ll )
280: /*
281: deletes local class entry from keyword table
282: adjusts pointers if multiple entries
283: uses same lookup as table::look and table::insert
284: */
285: {
286: Ptable t = ktbl;
287: register char * p;
288: register char * q;
289: register int i;
290: Pname n;
291: int rr;
292:
293: p = s;
294: i = 0;
295: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
296: rr = (0<=i) ? i : -i;
297:
298: // error ('d', "table_delete: %s ll: %d", s, ll );
299:
300: Pname* np = t->entries;
301: int mx = t->hashsize;
302: short* hash = t->hashtbl;
303: int firsti = i = rr%mx;
304:
305: do {
306: if (hash[i] == 0) error('i',"table delete: not found: %s", s );
307: n = np[hash[i]];
308: if (n == 0) error('i',"table delete: hashed lookup");
309: p = n->string; /* strcmp(n->n_string,s) */
310: q = s;
311: // error( 'd', "table_delete: %s", p );
312: while (*p && *q)
313: if (*p++ != *q++) goto nxt;
314: if (*p == *q) goto found;
315: nxt:
316: if (mx <= ++i) i = 0; /* wrap around */
317: } while (i != firsti);
318:
319: found:
320: for (Pname prev = n; n; prev = n, n=n->n_tbl_list){
321: // error( 'd', "table_delete: found: %s %k lex: %d", n->string, n->n_key, n->lex_level );
322: if (n->n_key == k && n->lex_level == ll ) {
323: // error( 'd', "table_delete: prev: %d n: %d n->tbl_list: %d", prev, n, n->n_tbl_list);
324: if ( prev == n && n->n_tbl_list == 0 )
325: hash[i] = 0;
326: else
327: prev->n_tbl_list = n->n_tbl_list;
328: return;
329: }
330: }
331: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.