dictionary.c revision 1.5 1 1.1 christos /* Routines for name->symbol lookups in GDB.
2 1.1 christos
3 1.3 christos Copyright (C) 2003-2015 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos Contributed by David Carlton <carlton (at) bactrian.org> and by Kealia,
6 1.1 christos Inc.
7 1.1 christos
8 1.1 christos This file is part of GDB.
9 1.1 christos
10 1.1 christos This program is free software; you can redistribute it and/or modify
11 1.1 christos it under the terms of the GNU General Public License as published by
12 1.1 christos the Free Software Foundation; either version 3 of the License, or
13 1.1 christos (at your option) any later version.
14 1.1 christos
15 1.1 christos This program is distributed in the hope that it will be useful,
16 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
17 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 1.1 christos GNU General Public License for more details.
19 1.1 christos
20 1.1 christos You should have received a copy of the GNU General Public License
21 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 1.1 christos
23 1.1 christos #include "defs.h"
24 1.1 christos #include <ctype.h>
25 1.1 christos #include "gdb_obstack.h"
26 1.1 christos #include "symtab.h"
27 1.1 christos #include "buildsym.h"
28 1.1 christos #include "dictionary.h"
29 1.1 christos
30 1.1 christos /* This file implements dictionaries, which are tables that associate
31 1.1 christos symbols to names. They are represented by an opaque type 'struct
32 1.1 christos dictionary'. That type has various internal implementations, which
33 1.1 christos you can choose between depending on what properties you need
34 1.1 christos (e.g. fast lookup, order-preserving, expandable).
35 1.1 christos
36 1.1 christos Each dictionary starts with a 'virtual function table' that
37 1.1 christos contains the functions that actually implement the various
38 1.1 christos operations that dictionaries provide. (Note, however, that, for
39 1.1 christos the sake of client code, we also provide some functions that can be
40 1.1 christos implemented generically in terms of the functions in the vtable.)
41 1.1 christos
42 1.1 christos To add a new dictionary implementation <impl>, what you should do
43 1.1 christos is:
44 1.1 christos
45 1.1 christos * Add a new element DICT_<IMPL> to dict_type.
46 1.1 christos
47 1.1 christos * Create a new structure dictionary_<impl>. If your new
48 1.1 christos implementation is a variant of an existing one, make sure that
49 1.1 christos their structs have the same initial data members. Define accessor
50 1.1 christos macros for your new data members.
51 1.1 christos
52 1.1 christos * Implement all the functions in dict_vector as static functions,
53 1.1 christos whose name is the same as the corresponding member of dict_vector
54 1.1 christos plus _<impl>. You don't have to do this for those members where
55 1.1 christos you can reuse existing generic functions
56 1.1 christos (e.g. add_symbol_nonexpandable, free_obstack) or in the case where
57 1.1 christos your new implementation is a variant of an existing implementation
58 1.1 christos and where the variant doesn't affect the member function in
59 1.1 christos question.
60 1.1 christos
61 1.1 christos * Define a static const struct dict_vector dict_<impl>_vector.
62 1.1 christos
63 1.1 christos * Define a function dict_create_<impl> to create these
64 1.1 christos gizmos. Add its declaration to dictionary.h.
65 1.1 christos
66 1.1 christos To add a new operation <op> on all existing implementations, what
67 1.1 christos you should do is:
68 1.1 christos
69 1.1 christos * Add a new member <op> to struct dict_vector.
70 1.1 christos
71 1.1 christos * If there is useful generic behavior <op>, define a static
72 1.1 christos function <op>_something_informative that implements that behavior.
73 1.1 christos (E.g. add_symbol_nonexpandable, free_obstack.)
74 1.1 christos
75 1.1 christos * For every implementation <impl> that should have its own specific
76 1.1 christos behavior for <op>, define a static function <op>_<impl>
77 1.1 christos implementing it.
78 1.1 christos
79 1.1 christos * Modify all existing dict_vector_<impl>'s to include the appropriate
80 1.1 christos member.
81 1.1 christos
82 1.1 christos * Define a function dict_<op> that looks up <op> in the dict_vector
83 1.1 christos and calls the appropriate function. Add a declaration for
84 1.1 christos dict_<op> to dictionary.h. */
85 1.1 christos
86 1.1 christos /* An enum representing the various implementations of dictionaries.
87 1.1 christos Used only for debugging. */
88 1.1 christos
89 1.1 christos enum dict_type
90 1.1 christos {
91 1.1 christos /* Symbols are stored in a fixed-size hash table. */
92 1.1 christos DICT_HASHED,
93 1.1 christos /* Symbols are stored in an expandable hash table. */
94 1.1 christos DICT_HASHED_EXPANDABLE,
95 1.1 christos /* Symbols are stored in a fixed-size array. */
96 1.1 christos DICT_LINEAR,
97 1.1 christos /* Symbols are stored in an expandable array. */
98 1.1 christos DICT_LINEAR_EXPANDABLE
99 1.1 christos };
100 1.1 christos
101 1.1 christos /* The virtual function table. */
102 1.1 christos
103 1.1 christos struct dict_vector
104 1.1 christos {
105 1.1 christos /* The type of the dictionary. This is only here to make debugging
106 1.1 christos a bit easier; it's not actually used. */
107 1.1 christos enum dict_type type;
108 1.1 christos /* The function to free a dictionary. */
109 1.1 christos void (*free) (struct dictionary *dict);
110 1.1 christos /* Add a symbol to a dictionary, if possible. */
111 1.1 christos void (*add_symbol) (struct dictionary *dict, struct symbol *sym);
112 1.1 christos /* Iterator functions. */
113 1.1 christos struct symbol *(*iterator_first) (const struct dictionary *dict,
114 1.1 christos struct dict_iterator *iterator);
115 1.1 christos struct symbol *(*iterator_next) (struct dict_iterator *iterator);
116 1.1 christos /* Functions to iterate over symbols with a given name. */
117 1.1 christos struct symbol *(*iter_match_first) (const struct dictionary *dict,
118 1.1 christos const char *name,
119 1.1 christos symbol_compare_ftype *equiv,
120 1.1 christos struct dict_iterator *iterator);
121 1.1 christos struct symbol *(*iter_match_next) (const char *name,
122 1.1 christos symbol_compare_ftype *equiv,
123 1.1 christos struct dict_iterator *iterator);
124 1.1 christos /* A size function, for maint print symtabs. */
125 1.1 christos int (*size) (const struct dictionary *dict);
126 1.1 christos };
127 1.1 christos
128 1.1 christos /* Now comes the structs used to store the data for different
129 1.1 christos implementations. If two implementations have data in common, put
130 1.1 christos the common data at the top of their structs, ordered in the same
131 1.1 christos way. */
132 1.1 christos
133 1.1 christos struct dictionary_hashed
134 1.1 christos {
135 1.1 christos int nbuckets;
136 1.1 christos struct symbol **buckets;
137 1.1 christos };
138 1.1 christos
139 1.1 christos struct dictionary_hashed_expandable
140 1.1 christos {
141 1.1 christos /* How many buckets we currently have. */
142 1.1 christos int nbuckets;
143 1.1 christos struct symbol **buckets;
144 1.1 christos /* How many syms we currently have; we need this so we will know
145 1.1 christos when to add more buckets. */
146 1.1 christos int nsyms;
147 1.1 christos };
148 1.1 christos
149 1.1 christos struct dictionary_linear
150 1.1 christos {
151 1.1 christos int nsyms;
152 1.1 christos struct symbol **syms;
153 1.1 christos };
154 1.1 christos
155 1.1 christos struct dictionary_linear_expandable
156 1.1 christos {
157 1.1 christos /* How many symbols we currently have. */
158 1.1 christos int nsyms;
159 1.1 christos struct symbol **syms;
160 1.1 christos /* How many symbols we can store before needing to reallocate. */
161 1.1 christos int capacity;
162 1.1 christos };
163 1.1 christos
164 1.1 christos /* And now, the star of our show. */
165 1.1 christos
166 1.1 christos struct dictionary
167 1.1 christos {
168 1.1 christos const struct dict_vector *vector;
169 1.1 christos union
170 1.1 christos {
171 1.1 christos struct dictionary_hashed hashed;
172 1.1 christos struct dictionary_hashed_expandable hashed_expandable;
173 1.1 christos struct dictionary_linear linear;
174 1.1 christos struct dictionary_linear_expandable linear_expandable;
175 1.1 christos }
176 1.1 christos data;
177 1.1 christos };
178 1.1 christos
179 1.1 christos /* Accessor macros. */
180 1.1 christos
181 1.1 christos #define DICT_VECTOR(d) (d)->vector
182 1.1 christos
183 1.1 christos /* These can be used for DICT_HASHED_EXPANDABLE, too. */
184 1.1 christos
185 1.1 christos #define DICT_HASHED_NBUCKETS(d) (d)->data.hashed.nbuckets
186 1.1 christos #define DICT_HASHED_BUCKETS(d) (d)->data.hashed.buckets
187 1.1 christos #define DICT_HASHED_BUCKET(d,i) DICT_HASHED_BUCKETS (d) [i]
188 1.1 christos
189 1.1 christos #define DICT_HASHED_EXPANDABLE_NSYMS(d) (d)->data.hashed_expandable.nsyms
190 1.1 christos
191 1.1 christos /* These can be used for DICT_LINEAR_EXPANDABLEs, too. */
192 1.1 christos
193 1.1 christos #define DICT_LINEAR_NSYMS(d) (d)->data.linear.nsyms
194 1.1 christos #define DICT_LINEAR_SYMS(d) (d)->data.linear.syms
195 1.1 christos #define DICT_LINEAR_SYM(d,i) DICT_LINEAR_SYMS (d) [i]
196 1.1 christos
197 1.1 christos #define DICT_LINEAR_EXPANDABLE_CAPACITY(d) \
198 1.1 christos (d)->data.linear_expandable.capacity
199 1.1 christos
200 1.1 christos /* The initial size of a DICT_*_EXPANDABLE dictionary. */
201 1.1 christos
202 1.1 christos #define DICT_EXPANDABLE_INITIAL_CAPACITY 10
203 1.1 christos
204 1.1 christos /* This calculates the number of buckets we'll use in a hashtable,
205 1.1 christos given the number of symbols that it will contain. */
206 1.1 christos
207 1.1 christos #define DICT_HASHTABLE_SIZE(n) ((n)/5 + 1)
208 1.1 christos
209 1.1 christos /* Accessor macros for dict_iterators; they're here rather than
210 1.1 christos dictionary.h because code elsewhere should treat dict_iterators as
211 1.1 christos opaque. */
212 1.1 christos
213 1.1 christos /* The dictionary that the iterator is associated to. */
214 1.1 christos #define DICT_ITERATOR_DICT(iter) (iter)->dict
215 1.1 christos /* For linear dictionaries, the index of the last symbol returned; for
216 1.1 christos hashed dictionaries, the bucket of the last symbol returned. */
217 1.1 christos #define DICT_ITERATOR_INDEX(iter) (iter)->index
218 1.1 christos /* For hashed dictionaries, this points to the last symbol returned;
219 1.1 christos otherwise, this is unused. */
220 1.1 christos #define DICT_ITERATOR_CURRENT(iter) (iter)->current
221 1.1 christos
222 1.1 christos /* Declarations of functions for vectors. */
223 1.1 christos
224 1.1 christos /* Functions that might work across a range of dictionary types. */
225 1.1 christos
226 1.1 christos static void add_symbol_nonexpandable (struct dictionary *dict,
227 1.1 christos struct symbol *sym);
228 1.1 christos
229 1.1 christos static void free_obstack (struct dictionary *dict);
230 1.1 christos
231 1.1 christos /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE
232 1.1 christos dictionaries. */
233 1.1 christos
234 1.1 christos static struct symbol *iterator_first_hashed (const struct dictionary *dict,
235 1.1 christos struct dict_iterator *iterator);
236 1.1 christos
237 1.1 christos static struct symbol *iterator_next_hashed (struct dict_iterator *iterator);
238 1.1 christos
239 1.1 christos static struct symbol *iter_match_first_hashed (const struct dictionary *dict,
240 1.1 christos const char *name,
241 1.1 christos symbol_compare_ftype *compare,
242 1.1 christos struct dict_iterator *iterator);
243 1.1 christos
244 1.1 christos static struct symbol *iter_match_next_hashed (const char *name,
245 1.1 christos symbol_compare_ftype *compare,
246 1.1 christos struct dict_iterator *iterator);
247 1.1 christos
248 1.1 christos static unsigned int dict_hash (const char *string);
249 1.1 christos
250 1.1 christos /* Functions only for DICT_HASHED. */
251 1.1 christos
252 1.1 christos static int size_hashed (const struct dictionary *dict);
253 1.1 christos
254 1.1 christos /* Functions only for DICT_HASHED_EXPANDABLE. */
255 1.1 christos
256 1.1 christos static void free_hashed_expandable (struct dictionary *dict);
257 1.1 christos
258 1.1 christos static void add_symbol_hashed_expandable (struct dictionary *dict,
259 1.1 christos struct symbol *sym);
260 1.1 christos
261 1.1 christos static int size_hashed_expandable (const struct dictionary *dict);
262 1.1 christos
263 1.1 christos /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE
264 1.1 christos dictionaries. */
265 1.1 christos
266 1.1 christos static struct symbol *iterator_first_linear (const struct dictionary *dict,
267 1.1 christos struct dict_iterator *iterator);
268 1.1 christos
269 1.1 christos static struct symbol *iterator_next_linear (struct dict_iterator *iterator);
270 1.1 christos
271 1.1 christos static struct symbol *iter_match_first_linear (const struct dictionary *dict,
272 1.1 christos const char *name,
273 1.1 christos symbol_compare_ftype *compare,
274 1.1 christos struct dict_iterator *iterator);
275 1.1 christos
276 1.1 christos static struct symbol *iter_match_next_linear (const char *name,
277 1.1 christos symbol_compare_ftype *compare,
278 1.1 christos struct dict_iterator *iterator);
279 1.1 christos
280 1.1 christos static int size_linear (const struct dictionary *dict);
281 1.1 christos
282 1.1 christos /* Functions only for DICT_LINEAR_EXPANDABLE. */
283 1.1 christos
284 1.1 christos static void free_linear_expandable (struct dictionary *dict);
285 1.1 christos
286 1.1 christos static void add_symbol_linear_expandable (struct dictionary *dict,
287 1.1 christos struct symbol *sym);
288 1.1 christos
289 1.1 christos /* Various vectors that we'll actually use. */
290 1.1 christos
291 1.1 christos static const struct dict_vector dict_hashed_vector =
292 1.1 christos {
293 1.1 christos DICT_HASHED, /* type */
294 1.1 christos free_obstack, /* free */
295 1.1 christos add_symbol_nonexpandable, /* add_symbol */
296 1.1 christos iterator_first_hashed, /* iterator_first */
297 1.1 christos iterator_next_hashed, /* iterator_next */
298 1.1 christos iter_match_first_hashed, /* iter_name_first */
299 1.1 christos iter_match_next_hashed, /* iter_name_next */
300 1.1 christos size_hashed, /* size */
301 1.1 christos };
302 1.1 christos
303 1.1 christos static const struct dict_vector dict_hashed_expandable_vector =
304 1.1 christos {
305 1.1 christos DICT_HASHED_EXPANDABLE, /* type */
306 1.1 christos free_hashed_expandable, /* free */
307 1.1 christos add_symbol_hashed_expandable, /* add_symbol */
308 1.1 christos iterator_first_hashed, /* iterator_first */
309 1.1 christos iterator_next_hashed, /* iterator_next */
310 1.1 christos iter_match_first_hashed, /* iter_name_first */
311 1.1 christos iter_match_next_hashed, /* iter_name_next */
312 1.1 christos size_hashed_expandable, /* size */
313 1.1 christos };
314 1.1 christos
315 1.1 christos static const struct dict_vector dict_linear_vector =
316 1.1 christos {
317 1.1 christos DICT_LINEAR, /* type */
318 1.1 christos free_obstack, /* free */
319 1.1 christos add_symbol_nonexpandable, /* add_symbol */
320 1.1 christos iterator_first_linear, /* iterator_first */
321 1.1 christos iterator_next_linear, /* iterator_next */
322 1.1 christos iter_match_first_linear, /* iter_name_first */
323 1.1 christos iter_match_next_linear, /* iter_name_next */
324 1.1 christos size_linear, /* size */
325 1.1 christos };
326 1.1 christos
327 1.1 christos static const struct dict_vector dict_linear_expandable_vector =
328 1.1 christos {
329 1.1 christos DICT_LINEAR_EXPANDABLE, /* type */
330 1.1 christos free_linear_expandable, /* free */
331 1.1 christos add_symbol_linear_expandable, /* add_symbol */
332 1.1 christos iterator_first_linear, /* iterator_first */
333 1.1 christos iterator_next_linear, /* iterator_next */
334 1.1 christos iter_match_first_linear, /* iter_name_first */
335 1.1 christos iter_match_next_linear, /* iter_name_next */
336 1.1 christos size_linear, /* size */
337 1.1 christos };
338 1.1 christos
339 1.1 christos /* Declarations of helper functions (i.e. ones that don't go into
340 1.1 christos vectors). */
341 1.1 christos
342 1.1 christos static struct symbol *iterator_hashed_advance (struct dict_iterator *iter);
343 1.1 christos
344 1.1 christos static void insert_symbol_hashed (struct dictionary *dict,
345 1.1 christos struct symbol *sym);
346 1.1 christos
347 1.1 christos static void expand_hashtable (struct dictionary *dict);
348 1.1 christos
349 1.1 christos /* The creation functions. */
350 1.1 christos
351 1.1 christos /* Create a dictionary implemented via a fixed-size hashtable. All
352 1.1 christos memory it uses is allocated on OBSTACK; the environment is
353 1.1 christos initialized from SYMBOL_LIST. */
354 1.1 christos
355 1.1 christos struct dictionary *
356 1.1 christos dict_create_hashed (struct obstack *obstack,
357 1.1 christos const struct pending *symbol_list)
358 1.1 christos {
359 1.1 christos struct dictionary *retval;
360 1.1 christos int nsyms = 0, nbuckets, i;
361 1.1 christos struct symbol **buckets;
362 1.1 christos const struct pending *list_counter;
363 1.1 christos
364 1.1 christos retval = obstack_alloc (obstack, sizeof (struct dictionary));
365 1.1 christos DICT_VECTOR (retval) = &dict_hashed_vector;
366 1.1 christos
367 1.1 christos /* Calculate the number of symbols, and allocate space for them. */
368 1.1 christos for (list_counter = symbol_list;
369 1.1 christos list_counter != NULL;
370 1.1 christos list_counter = list_counter->next)
371 1.1 christos {
372 1.1 christos nsyms += list_counter->nsyms;
373 1.1 christos }
374 1.1 christos nbuckets = DICT_HASHTABLE_SIZE (nsyms);
375 1.1 christos DICT_HASHED_NBUCKETS (retval) = nbuckets;
376 1.1 christos buckets = obstack_alloc (obstack, nbuckets * sizeof (struct symbol *));
377 1.1 christos memset (buckets, 0, nbuckets * sizeof (struct symbol *));
378 1.1 christos DICT_HASHED_BUCKETS (retval) = buckets;
379 1.1 christos
380 1.1 christos /* Now fill the buckets. */
381 1.1 christos for (list_counter = symbol_list;
382 1.1 christos list_counter != NULL;
383 1.1 christos list_counter = list_counter->next)
384 1.1 christos {
385 1.1 christos for (i = list_counter->nsyms - 1; i >= 0; --i)
386 1.1 christos {
387 1.1 christos insert_symbol_hashed (retval, list_counter->symbol[i]);
388 1.1 christos }
389 1.1 christos }
390 1.1 christos
391 1.1 christos return retval;
392 1.1 christos }
393 1.1 christos
394 1.1 christos /* Create a dictionary implemented via a hashtable that grows as
395 1.1 christos necessary. The dictionary is initially empty; to add symbols to
396 1.1 christos it, call dict_add_symbol(). Call dict_free() when you're done with
397 1.1 christos it. */
398 1.1 christos
399 1.1 christos extern struct dictionary *
400 1.1 christos dict_create_hashed_expandable (void)
401 1.1 christos {
402 1.1 christos struct dictionary *retval;
403 1.1 christos
404 1.1 christos retval = xmalloc (sizeof (struct dictionary));
405 1.1 christos DICT_VECTOR (retval) = &dict_hashed_expandable_vector;
406 1.1 christos DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
407 1.1 christos DICT_HASHED_BUCKETS (retval) = xcalloc (DICT_EXPANDABLE_INITIAL_CAPACITY,
408 1.1 christos sizeof (struct symbol *));
409 1.1 christos DICT_HASHED_EXPANDABLE_NSYMS (retval) = 0;
410 1.1 christos
411 1.1 christos return retval;
412 1.1 christos }
413 1.1 christos
414 1.1 christos /* Create a dictionary implemented via a fixed-size array. All memory
415 1.1 christos it uses is allocated on OBSTACK; the environment is initialized
416 1.1 christos from the SYMBOL_LIST. The symbols are ordered in the same order
417 1.1 christos that they're found in SYMBOL_LIST. */
418 1.1 christos
419 1.1 christos struct dictionary *
420 1.1 christos dict_create_linear (struct obstack *obstack,
421 1.1 christos const struct pending *symbol_list)
422 1.1 christos {
423 1.1 christos struct dictionary *retval;
424 1.1 christos int nsyms = 0, i, j;
425 1.1 christos struct symbol **syms;
426 1.1 christos const struct pending *list_counter;
427 1.1 christos
428 1.1 christos retval = obstack_alloc (obstack, sizeof (struct dictionary));
429 1.1 christos DICT_VECTOR (retval) = &dict_linear_vector;
430 1.1 christos
431 1.1 christos /* Calculate the number of symbols, and allocate space for them. */
432 1.1 christos for (list_counter = symbol_list;
433 1.1 christos list_counter != NULL;
434 1.1 christos list_counter = list_counter->next)
435 1.1 christos {
436 1.1 christos nsyms += list_counter->nsyms;
437 1.1 christos }
438 1.1 christos DICT_LINEAR_NSYMS (retval) = nsyms;
439 1.1 christos syms = obstack_alloc (obstack, nsyms * sizeof (struct symbol *));
440 1.1 christos DICT_LINEAR_SYMS (retval) = syms;
441 1.1 christos
442 1.1 christos /* Now fill in the symbols. Start filling in from the back, so as
443 1.1 christos to preserve the original order of the symbols. */
444 1.1 christos for (list_counter = symbol_list, j = nsyms - 1;
445 1.1 christos list_counter != NULL;
446 1.1 christos list_counter = list_counter->next)
447 1.1 christos {
448 1.1 christos for (i = list_counter->nsyms - 1;
449 1.1 christos i >= 0;
450 1.1 christos --i, --j)
451 1.1 christos {
452 1.1 christos syms[j] = list_counter->symbol[i];
453 1.1 christos }
454 1.1 christos }
455 1.1 christos
456 1.1 christos return retval;
457 1.1 christos }
458 1.1 christos
459 1.1 christos /* Create a dictionary implemented via an array that grows as
460 1.1 christos necessary. The dictionary is initially empty; to add symbols to
461 1.1 christos it, call dict_add_symbol(). Call dict_free() when you're done with
462 1.1 christos it. */
463 1.1 christos
464 1.1 christos struct dictionary *
465 1.1 christos dict_create_linear_expandable (void)
466 1.1 christos {
467 1.1 christos struct dictionary *retval;
468 1.1 christos
469 1.1 christos retval = xmalloc (sizeof (struct dictionary));
470 1.1 christos DICT_VECTOR (retval) = &dict_linear_expandable_vector;
471 1.1 christos DICT_LINEAR_NSYMS (retval) = 0;
472 1.1 christos DICT_LINEAR_EXPANDABLE_CAPACITY (retval)
473 1.1 christos = DICT_EXPANDABLE_INITIAL_CAPACITY;
474 1.1 christos DICT_LINEAR_SYMS (retval)
475 1.1 christos = xmalloc (DICT_LINEAR_EXPANDABLE_CAPACITY (retval)
476 1.1 christos * sizeof (struct symbol *));
477 1.1 christos
478 1.1 christos return retval;
479 1.1 christos }
480 1.1 christos
481 1.1 christos /* The functions providing the dictionary interface. */
482 1.1 christos
483 1.1 christos /* Free the memory used by a dictionary that's not on an obstack. (If
484 1.1 christos any.) */
485 1.1 christos
486 1.1 christos void
487 1.1 christos dict_free (struct dictionary *dict)
488 1.1 christos {
489 1.1 christos (DICT_VECTOR (dict))->free (dict);
490 1.1 christos }
491 1.1 christos
492 1.1 christos /* Add SYM to DICT. DICT had better be expandable. */
493 1.1 christos
494 1.1 christos void
495 1.1 christos dict_add_symbol (struct dictionary *dict, struct symbol *sym)
496 1.1 christos {
497 1.1 christos (DICT_VECTOR (dict))->add_symbol (dict, sym);
498 1.1 christos }
499 1.1 christos
500 1.1 christos /* Utility to add a list of symbols to a dictionary.
501 1.1 christos DICT must be an expandable dictionary. */
502 1.1 christos
503 1.1 christos void
504 1.1 christos dict_add_pending (struct dictionary *dict, const struct pending *symbol_list)
505 1.1 christos {
506 1.1 christos const struct pending *list;
507 1.1 christos int i;
508 1.1 christos
509 1.1 christos for (list = symbol_list; list != NULL; list = list->next)
510 1.1 christos {
511 1.1 christos for (i = 0; i < list->nsyms; ++i)
512 1.1 christos dict_add_symbol (dict, list->symbol[i]);
513 1.1 christos }
514 1.1 christos }
515 1.1 christos
516 1.1 christos /* Initialize ITERATOR to point at the first symbol in DICT, and
517 1.1 christos return that first symbol, or NULL if DICT is empty. */
518 1.1 christos
519 1.1 christos struct symbol *
520 1.1 christos dict_iterator_first (const struct dictionary *dict,
521 1.1 christos struct dict_iterator *iterator)
522 1.1 christos {
523 1.1 christos return (DICT_VECTOR (dict))->iterator_first (dict, iterator);
524 1.1 christos }
525 1.1 christos
526 1.1 christos /* Advance ITERATOR, and return the next symbol, or NULL if there are
527 1.1 christos no more symbols. */
528 1.1 christos
529 1.1 christos struct symbol *
530 1.1 christos dict_iterator_next (struct dict_iterator *iterator)
531 1.1 christos {
532 1.1 christos return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator)))
533 1.1 christos ->iterator_next (iterator);
534 1.1 christos }
535 1.1 christos
536 1.1 christos struct symbol *
537 1.1 christos dict_iter_name_first (const struct dictionary *dict,
538 1.1 christos const char *name,
539 1.1 christos struct dict_iterator *iterator)
540 1.1 christos {
541 1.1 christos return dict_iter_match_first (dict, name, strcmp_iw, iterator);
542 1.1 christos }
543 1.1 christos
544 1.1 christos struct symbol *
545 1.1 christos dict_iter_name_next (const char *name, struct dict_iterator *iterator)
546 1.1 christos {
547 1.1 christos return dict_iter_match_next (name, strcmp_iw, iterator);
548 1.1 christos }
549 1.1 christos
550 1.1 christos struct symbol *
551 1.1 christos dict_iter_match_first (const struct dictionary *dict,
552 1.1 christos const char *name, symbol_compare_ftype *compare,
553 1.1 christos struct dict_iterator *iterator)
554 1.1 christos {
555 1.1 christos return (DICT_VECTOR (dict))->iter_match_first (dict, name,
556 1.1 christos compare, iterator);
557 1.1 christos }
558 1.1 christos
559 1.1 christos struct symbol *
560 1.1 christos dict_iter_match_next (const char *name, symbol_compare_ftype *compare,
561 1.1 christos struct dict_iterator *iterator)
562 1.1 christos {
563 1.1 christos return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator)))
564 1.1 christos ->iter_match_next (name, compare, iterator);
565 1.1 christos }
566 1.1 christos
567 1.1 christos int
568 1.1 christos dict_size (const struct dictionary *dict)
569 1.1 christos {
570 1.1 christos return (DICT_VECTOR (dict))->size (dict);
571 1.1 christos }
572 1.1 christos
573 1.1 christos /* Now come functions (well, one function, currently) that are
574 1.1 christos implemented generically by means of the vtable. Typically, they're
575 1.1 christos rarely used. */
576 1.1 christos
577 1.1 christos /* Test to see if DICT is empty. */
578 1.1 christos
579 1.1 christos int
580 1.1 christos dict_empty (struct dictionary *dict)
581 1.1 christos {
582 1.1 christos struct dict_iterator iter;
583 1.1 christos
584 1.1 christos return (dict_iterator_first (dict, &iter) == NULL);
585 1.1 christos }
586 1.1 christos
587 1.1 christos
588 1.1 christos /* The functions implementing the dictionary interface. */
589 1.1 christos
590 1.1 christos /* Generic functions, where appropriate. */
591 1.1 christos
592 1.1 christos static void
593 1.1 christos free_obstack (struct dictionary *dict)
594 1.1 christos {
595 1.1 christos /* Do nothing! */
596 1.1 christos }
597 1.1 christos
598 1.1 christos static void
599 1.1 christos add_symbol_nonexpandable (struct dictionary *dict, struct symbol *sym)
600 1.1 christos {
601 1.1 christos internal_error (__FILE__, __LINE__,
602 1.1 christos _("dict_add_symbol: non-expandable dictionary"));
603 1.1 christos }
604 1.1 christos
605 1.1 christos /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE. */
606 1.1 christos
607 1.1 christos static struct symbol *
608 1.1 christos iterator_first_hashed (const struct dictionary *dict,
609 1.1 christos struct dict_iterator *iterator)
610 1.1 christos {
611 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
612 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1;
613 1.1 christos return iterator_hashed_advance (iterator);
614 1.1 christos }
615 1.1 christos
616 1.1 christos static struct symbol *
617 1.1 christos iterator_next_hashed (struct dict_iterator *iterator)
618 1.1 christos {
619 1.1 christos struct symbol *next;
620 1.1 christos
621 1.1 christos next = DICT_ITERATOR_CURRENT (iterator)->hash_next;
622 1.1 christos
623 1.1 christos if (next == NULL)
624 1.1 christos return iterator_hashed_advance (iterator);
625 1.1 christos else
626 1.1 christos {
627 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next;
628 1.1 christos return next;
629 1.1 christos }
630 1.1 christos }
631 1.1 christos
632 1.1 christos static struct symbol *
633 1.1 christos iterator_hashed_advance (struct dict_iterator *iterator)
634 1.1 christos {
635 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
636 1.1 christos int nbuckets = DICT_HASHED_NBUCKETS (dict);
637 1.1 christos int i;
638 1.1 christos
639 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nbuckets; ++i)
640 1.1 christos {
641 1.1 christos struct symbol *sym = DICT_HASHED_BUCKET (dict, i);
642 1.1 christos
643 1.1 christos if (sym != NULL)
644 1.1 christos {
645 1.1 christos DICT_ITERATOR_INDEX (iterator) = i;
646 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym;
647 1.1 christos return sym;
648 1.1 christos }
649 1.1 christos }
650 1.1 christos
651 1.1 christos return NULL;
652 1.1 christos }
653 1.1 christos
654 1.1 christos static struct symbol *
655 1.1 christos iter_match_first_hashed (const struct dictionary *dict, const char *name,
656 1.1 christos symbol_compare_ftype *compare,
657 1.1 christos struct dict_iterator *iterator)
658 1.1 christos {
659 1.1 christos unsigned int hash_index = dict_hash (name) % DICT_HASHED_NBUCKETS (dict);
660 1.1 christos struct symbol *sym;
661 1.1 christos
662 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
663 1.1 christos
664 1.1 christos /* Loop through the symbols in the given bucket, breaking when SYM
665 1.1 christos first matches. If SYM never matches, it will be set to NULL;
666 1.1 christos either way, we have the right return value. */
667 1.1 christos
668 1.1 christos for (sym = DICT_HASHED_BUCKET (dict, hash_index);
669 1.1 christos sym != NULL;
670 1.1 christos sym = sym->hash_next)
671 1.1 christos {
672 1.1 christos /* Warning: the order of arguments to compare matters! */
673 1.1 christos if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0)
674 1.1 christos {
675 1.1 christos break;
676 1.1 christos }
677 1.1 christos
678 1.1 christos }
679 1.1 christos
680 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym;
681 1.1 christos return sym;
682 1.1 christos }
683 1.1 christos
684 1.1 christos static struct symbol *
685 1.1 christos iter_match_next_hashed (const char *name, symbol_compare_ftype *compare,
686 1.1 christos struct dict_iterator *iterator)
687 1.1 christos {
688 1.1 christos struct symbol *next;
689 1.1 christos
690 1.1 christos for (next = DICT_ITERATOR_CURRENT (iterator)->hash_next;
691 1.1 christos next != NULL;
692 1.1 christos next = next->hash_next)
693 1.1 christos {
694 1.1 christos if (compare (SYMBOL_SEARCH_NAME (next), name) == 0)
695 1.1 christos break;
696 1.1 christos }
697 1.1 christos
698 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next;
699 1.1 christos
700 1.1 christos return next;
701 1.1 christos }
702 1.1 christos
703 1.1 christos /* Insert SYM into DICT. */
704 1.1 christos
705 1.1 christos static void
706 1.1 christos insert_symbol_hashed (struct dictionary *dict,
707 1.1 christos struct symbol *sym)
708 1.1 christos {
709 1.1 christos unsigned int hash_index;
710 1.1 christos struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
711 1.1 christos
712 1.1 christos hash_index =
713 1.1 christos dict_hash (SYMBOL_SEARCH_NAME (sym)) % DICT_HASHED_NBUCKETS (dict);
714 1.1 christos sym->hash_next = buckets[hash_index];
715 1.1 christos buckets[hash_index] = sym;
716 1.1 christos }
717 1.1 christos
718 1.1 christos static int
719 1.1 christos size_hashed (const struct dictionary *dict)
720 1.1 christos {
721 1.1 christos return DICT_HASHED_NBUCKETS (dict);
722 1.1 christos }
723 1.1 christos
724 1.1 christos /* Functions only for DICT_HASHED_EXPANDABLE. */
725 1.1 christos
726 1.1 christos static void
727 1.1 christos free_hashed_expandable (struct dictionary *dict)
728 1.1 christos {
729 1.1 christos xfree (DICT_HASHED_BUCKETS (dict));
730 1.1 christos xfree (dict);
731 1.1 christos }
732 1.1 christos
733 1.1 christos static void
734 1.1 christos add_symbol_hashed_expandable (struct dictionary *dict,
735 1.1 christos struct symbol *sym)
736 1.1 christos {
737 1.1 christos int nsyms = ++DICT_HASHED_EXPANDABLE_NSYMS (dict);
738 1.1 christos
739 1.1 christos if (DICT_HASHTABLE_SIZE (nsyms) > DICT_HASHED_NBUCKETS (dict))
740 1.1 christos expand_hashtable (dict);
741 1.1 christos
742 1.1 christos insert_symbol_hashed (dict, sym);
743 1.1 christos DICT_HASHED_EXPANDABLE_NSYMS (dict) = nsyms;
744 1.1 christos }
745 1.1 christos
746 1.1 christos static int
747 1.1 christos size_hashed_expandable (const struct dictionary *dict)
748 1.1 christos {
749 1.1 christos return DICT_HASHED_EXPANDABLE_NSYMS (dict);
750 1.1 christos }
751 1.1 christos
752 1.1 christos static void
753 1.1 christos expand_hashtable (struct dictionary *dict)
754 1.1 christos {
755 1.1 christos int old_nbuckets = DICT_HASHED_NBUCKETS (dict);
756 1.1 christos struct symbol **old_buckets = DICT_HASHED_BUCKETS (dict);
757 1.1 christos int new_nbuckets = 2*old_nbuckets + 1;
758 1.1 christos struct symbol **new_buckets = xcalloc (new_nbuckets,
759 1.1 christos sizeof (struct symbol *));
760 1.1 christos int i;
761 1.1 christos
762 1.1 christos DICT_HASHED_NBUCKETS (dict) = new_nbuckets;
763 1.1 christos DICT_HASHED_BUCKETS (dict) = new_buckets;
764 1.1 christos
765 1.1 christos for (i = 0; i < old_nbuckets; ++i)
766 1.1 christos {
767 1.1 christos struct symbol *sym, *next_sym;
768 1.1 christos
769 1.1 christos sym = old_buckets[i];
770 1.1 christos if (sym != NULL)
771 1.1 christos {
772 1.1 christos for (next_sym = sym->hash_next;
773 1.1 christos next_sym != NULL;
774 1.1 christos next_sym = sym->hash_next)
775 1.1 christos {
776 1.1 christos insert_symbol_hashed (dict, sym);
777 1.1 christos sym = next_sym;
778 1.1 christos }
779 1.1 christos
780 1.1 christos insert_symbol_hashed (dict, sym);
781 1.1 christos }
782 1.1 christos }
783 1.1 christos
784 1.1 christos xfree (old_buckets);
785 1.1 christos }
786 1.1 christos
787 1.1 christos /* Produce an unsigned hash value from STRING0 that is consistent
788 1.1 christos with strcmp_iw, strcmp, and, at least on Ada symbols, wild_match.
789 1.1 christos That is, two identifiers equivalent according to any of those three
790 1.1 christos comparison operators hash to the same value. */
791 1.1 christos
792 1.1 christos static unsigned int
793 1.1 christos dict_hash (const char *string0)
794 1.1 christos {
795 1.1 christos /* The Ada-encoded version of a name P1.P2...Pn has either the form
796 1.1 christos P1__P2__...Pn<suffix> or _ada_P1__P2__...Pn<suffix> (where the Pi
797 1.1 christos are lower-cased identifiers). The <suffix> (which can be empty)
798 1.1 christos encodes additional information about the denoted entity. This
799 1.1 christos routine hashes such names to msymbol_hash_iw(Pn). It actually
800 1.1 christos does this for a superset of both valid Pi and of <suffix>, but
801 1.1 christos in other cases it simply returns msymbol_hash_iw(STRING0). */
802 1.1 christos
803 1.1 christos const char *string;
804 1.1 christos unsigned int hash;
805 1.1 christos
806 1.1 christos string = string0;
807 1.1 christos if (*string == '_')
808 1.1 christos {
809 1.5 christos if (startswith (string, "_ada_"))
810 1.1 christos string += 5;
811 1.1 christos else
812 1.1 christos return msymbol_hash_iw (string0);
813 1.1 christos }
814 1.1 christos
815 1.1 christos hash = 0;
816 1.1 christos while (*string)
817 1.1 christos {
818 1.1 christos /* Ignore "TKB" suffixes.
819 1.1 christos
820 1.1 christos These are used by Ada for subprograms implementing a task body.
821 1.1 christos For instance for a task T inside package Pck, the name of the
822 1.1 christos subprogram implementing T's body is `pck__tTKB'. We need to
823 1.1 christos ignore the "TKB" suffix because searches for this task body
824 1.1 christos subprogram are going to be performed using `pck__t' (the encoded
825 1.1 christos version of the natural name `pck.t'). */
826 1.1 christos if (strcmp (string, "TKB") == 0)
827 1.1 christos return hash;
828 1.1 christos
829 1.1 christos switch (*string)
830 1.1 christos {
831 1.1 christos case '$':
832 1.1 christos case '.':
833 1.1 christos case 'X':
834 1.1 christos if (string0 == string)
835 1.1 christos return msymbol_hash_iw (string0);
836 1.1 christos else
837 1.1 christos return hash;
838 1.1 christos case ' ':
839 1.1 christos case '(':
840 1.1 christos return msymbol_hash_iw (string0);
841 1.1 christos case '_':
842 1.1 christos if (string[1] == '_' && string != string0)
843 1.1 christos {
844 1.1 christos int c = string[2];
845 1.1 christos
846 1.1 christos if ((c < 'a' || c > 'z') && c != 'O')
847 1.1 christos return hash;
848 1.1 christos hash = 0;
849 1.1 christos string += 2;
850 1.1 christos break;
851 1.1 christos }
852 1.1 christos /* FALL THROUGH */
853 1.1 christos default:
854 1.1 christos hash = SYMBOL_HASH_NEXT (hash, *string);
855 1.1 christos string += 1;
856 1.1 christos break;
857 1.1 christos }
858 1.1 christos }
859 1.1 christos return hash;
860 1.1 christos }
861 1.1 christos
862 1.1 christos /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE. */
863 1.1 christos
864 1.1 christos static struct symbol *
865 1.1 christos iterator_first_linear (const struct dictionary *dict,
866 1.1 christos struct dict_iterator *iterator)
867 1.1 christos {
868 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
869 1.1 christos DICT_ITERATOR_INDEX (iterator) = 0;
870 1.1 christos return DICT_LINEAR_NSYMS (dict) ? DICT_LINEAR_SYM (dict, 0) : NULL;
871 1.1 christos }
872 1.1 christos
873 1.1 christos static struct symbol *
874 1.1 christos iterator_next_linear (struct dict_iterator *iterator)
875 1.1 christos {
876 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
877 1.1 christos
878 1.1 christos if (++DICT_ITERATOR_INDEX (iterator) >= DICT_LINEAR_NSYMS (dict))
879 1.1 christos return NULL;
880 1.1 christos else
881 1.1 christos return DICT_LINEAR_SYM (dict, DICT_ITERATOR_INDEX (iterator));
882 1.1 christos }
883 1.1 christos
884 1.1 christos static struct symbol *
885 1.1 christos iter_match_first_linear (const struct dictionary *dict,
886 1.1 christos const char *name, symbol_compare_ftype *compare,
887 1.1 christos struct dict_iterator *iterator)
888 1.1 christos {
889 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
890 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1;
891 1.1 christos
892 1.1 christos return iter_match_next_linear (name, compare, iterator);
893 1.1 christos }
894 1.1 christos
895 1.1 christos static struct symbol *
896 1.1 christos iter_match_next_linear (const char *name, symbol_compare_ftype *compare,
897 1.1 christos struct dict_iterator *iterator)
898 1.1 christos {
899 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
900 1.1 christos int i, nsyms = DICT_LINEAR_NSYMS (dict);
901 1.1 christos struct symbol *sym, *retval = NULL;
902 1.1 christos
903 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nsyms; ++i)
904 1.1 christos {
905 1.1 christos sym = DICT_LINEAR_SYM (dict, i);
906 1.1 christos if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0)
907 1.1 christos {
908 1.1 christos retval = sym;
909 1.1 christos break;
910 1.1 christos }
911 1.1 christos }
912 1.1 christos
913 1.1 christos DICT_ITERATOR_INDEX (iterator) = i;
914 1.1 christos
915 1.1 christos return retval;
916 1.1 christos }
917 1.1 christos
918 1.1 christos static int
919 1.1 christos size_linear (const struct dictionary *dict)
920 1.1 christos {
921 1.1 christos return DICT_LINEAR_NSYMS (dict);
922 1.1 christos }
923 1.1 christos
924 1.1 christos /* Functions only for DICT_LINEAR_EXPANDABLE. */
925 1.1 christos
926 1.1 christos static void
927 1.1 christos free_linear_expandable (struct dictionary *dict)
928 1.1 christos {
929 1.1 christos xfree (DICT_LINEAR_SYMS (dict));
930 1.1 christos xfree (dict);
931 1.1 christos }
932 1.1 christos
933 1.1 christos
934 1.1 christos static void
935 1.1 christos add_symbol_linear_expandable (struct dictionary *dict,
936 1.1 christos struct symbol *sym)
937 1.1 christos {
938 1.1 christos int nsyms = ++DICT_LINEAR_NSYMS (dict);
939 1.1 christos
940 1.1 christos /* Do we have enough room? If not, grow it. */
941 1.1 christos if (nsyms > DICT_LINEAR_EXPANDABLE_CAPACITY (dict))
942 1.1 christos {
943 1.1 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict) *= 2;
944 1.1 christos DICT_LINEAR_SYMS (dict)
945 1.1 christos = xrealloc (DICT_LINEAR_SYMS (dict),
946 1.1 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict)
947 1.1 christos * sizeof (struct symbol *));
948 1.1 christos }
949 1.1 christos
950 1.1 christos DICT_LINEAR_SYM (dict, nsyms - 1) = sym;
951 1.1 christos }
952