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