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