xref: /openbsd-src/gnu/usr.bin/binutils/gdb/dictionary.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
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