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