dictionary.c revision 1.8 1 1.1 christos /* Routines for name->symbol lookups in GDB.
2 1.1 christos
3 1.8 christos Copyright (C) 2003-2019 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.8 christos #include "safe-ctype.h"
30 1.8 christos #include <unordered_map>
31 1.1 christos
32 1.1 christos /* This file implements dictionaries, which are tables that associate
33 1.1 christos symbols to names. They are represented by an opaque type 'struct
34 1.1 christos dictionary'. That type has various internal implementations, which
35 1.1 christos you can choose between depending on what properties you need
36 1.1 christos (e.g. fast lookup, order-preserving, expandable).
37 1.1 christos
38 1.1 christos Each dictionary starts with a 'virtual function table' that
39 1.1 christos contains the functions that actually implement the various
40 1.1 christos operations that dictionaries provide. (Note, however, that, for
41 1.1 christos the sake of client code, we also provide some functions that can be
42 1.1 christos implemented generically in terms of the functions in the vtable.)
43 1.1 christos
44 1.1 christos To add a new dictionary implementation <impl>, what you should do
45 1.1 christos is:
46 1.1 christos
47 1.1 christos * Add a new element DICT_<IMPL> to dict_type.
48 1.1 christos
49 1.1 christos * Create a new structure dictionary_<impl>. If your new
50 1.1 christos implementation is a variant of an existing one, make sure that
51 1.1 christos their structs have the same initial data members. Define accessor
52 1.1 christos macros for your new data members.
53 1.1 christos
54 1.1 christos * Implement all the functions in dict_vector as static functions,
55 1.1 christos whose name is the same as the corresponding member of dict_vector
56 1.1 christos plus _<impl>. You don't have to do this for those members where
57 1.1 christos you can reuse existing generic functions
58 1.1 christos (e.g. add_symbol_nonexpandable, free_obstack) or in the case where
59 1.1 christos your new implementation is a variant of an existing implementation
60 1.1 christos and where the variant doesn't affect the member function in
61 1.1 christos question.
62 1.1 christos
63 1.1 christos * Define a static const struct dict_vector dict_<impl>_vector.
64 1.1 christos
65 1.1 christos * Define a function dict_create_<impl> to create these
66 1.1 christos gizmos. Add its declaration to dictionary.h.
67 1.1 christos
68 1.1 christos To add a new operation <op> on all existing implementations, what
69 1.1 christos you should do is:
70 1.1 christos
71 1.1 christos * Add a new member <op> to struct dict_vector.
72 1.1 christos
73 1.1 christos * If there is useful generic behavior <op>, define a static
74 1.1 christos function <op>_something_informative that implements that behavior.
75 1.1 christos (E.g. add_symbol_nonexpandable, free_obstack.)
76 1.1 christos
77 1.1 christos * For every implementation <impl> that should have its own specific
78 1.1 christos behavior for <op>, define a static function <op>_<impl>
79 1.1 christos implementing it.
80 1.1 christos
81 1.1 christos * Modify all existing dict_vector_<impl>'s to include the appropriate
82 1.1 christos member.
83 1.1 christos
84 1.1 christos * Define a function dict_<op> that looks up <op> in the dict_vector
85 1.1 christos and calls the appropriate function. Add a declaration for
86 1.1 christos dict_<op> to dictionary.h. */
87 1.1 christos
88 1.1 christos /* An enum representing the various implementations of dictionaries.
89 1.1 christos Used only for debugging. */
90 1.1 christos
91 1.1 christos enum dict_type
92 1.1 christos {
93 1.1 christos /* Symbols are stored in a fixed-size hash table. */
94 1.1 christos DICT_HASHED,
95 1.1 christos /* Symbols are stored in an expandable hash table. */
96 1.1 christos DICT_HASHED_EXPANDABLE,
97 1.1 christos /* Symbols are stored in a fixed-size array. */
98 1.1 christos DICT_LINEAR,
99 1.1 christos /* Symbols are stored in an expandable array. */
100 1.1 christos DICT_LINEAR_EXPANDABLE
101 1.1 christos };
102 1.1 christos
103 1.1 christos /* The virtual function table. */
104 1.1 christos
105 1.1 christos struct dict_vector
106 1.1 christos {
107 1.1 christos /* The type of the dictionary. This is only here to make debugging
108 1.1 christos a bit easier; it's not actually used. */
109 1.1 christos enum dict_type type;
110 1.1 christos /* The function to free a dictionary. */
111 1.1 christos void (*free) (struct dictionary *dict);
112 1.1 christos /* Add a symbol to a dictionary, if possible. */
113 1.1 christos void (*add_symbol) (struct dictionary *dict, struct symbol *sym);
114 1.1 christos /* Iterator functions. */
115 1.1 christos struct symbol *(*iterator_first) (const struct dictionary *dict,
116 1.1 christos struct dict_iterator *iterator);
117 1.1 christos struct symbol *(*iterator_next) (struct dict_iterator *iterator);
118 1.1 christos /* Functions to iterate over symbols with a given name. */
119 1.1 christos struct symbol *(*iter_match_first) (const struct dictionary *dict,
120 1.8 christos const lookup_name_info &name,
121 1.1 christos struct dict_iterator *iterator);
122 1.8 christos struct symbol *(*iter_match_next) (const lookup_name_info &name,
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.8 christos const struct language_defn *language;
169 1.1 christos const struct dict_vector *vector;
170 1.1 christos union
171 1.1 christos {
172 1.1 christos struct dictionary_hashed hashed;
173 1.1 christos struct dictionary_hashed_expandable hashed_expandable;
174 1.1 christos struct dictionary_linear linear;
175 1.1 christos struct dictionary_linear_expandable linear_expandable;
176 1.1 christos }
177 1.1 christos data;
178 1.1 christos };
179 1.1 christos
180 1.1 christos /* Accessor macros. */
181 1.1 christos
182 1.1 christos #define DICT_VECTOR(d) (d)->vector
183 1.8 christos #define DICT_LANGUAGE(d) (d)->language
184 1.1 christos
185 1.1 christos /* These can be used for DICT_HASHED_EXPANDABLE, too. */
186 1.1 christos
187 1.1 christos #define DICT_HASHED_NBUCKETS(d) (d)->data.hashed.nbuckets
188 1.1 christos #define DICT_HASHED_BUCKETS(d) (d)->data.hashed.buckets
189 1.1 christos #define DICT_HASHED_BUCKET(d,i) DICT_HASHED_BUCKETS (d) [i]
190 1.1 christos
191 1.1 christos #define DICT_HASHED_EXPANDABLE_NSYMS(d) (d)->data.hashed_expandable.nsyms
192 1.1 christos
193 1.1 christos /* These can be used for DICT_LINEAR_EXPANDABLEs, too. */
194 1.1 christos
195 1.1 christos #define DICT_LINEAR_NSYMS(d) (d)->data.linear.nsyms
196 1.1 christos #define DICT_LINEAR_SYMS(d) (d)->data.linear.syms
197 1.1 christos #define DICT_LINEAR_SYM(d,i) DICT_LINEAR_SYMS (d) [i]
198 1.1 christos
199 1.1 christos #define DICT_LINEAR_EXPANDABLE_CAPACITY(d) \
200 1.1 christos (d)->data.linear_expandable.capacity
201 1.1 christos
202 1.1 christos /* The initial size of a DICT_*_EXPANDABLE dictionary. */
203 1.1 christos
204 1.1 christos #define DICT_EXPANDABLE_INITIAL_CAPACITY 10
205 1.1 christos
206 1.1 christos /* This calculates the number of buckets we'll use in a hashtable,
207 1.1 christos given the number of symbols that it will contain. */
208 1.1 christos
209 1.1 christos #define DICT_HASHTABLE_SIZE(n) ((n)/5 + 1)
210 1.1 christos
211 1.1 christos /* Accessor macros for dict_iterators; they're here rather than
212 1.1 christos dictionary.h because code elsewhere should treat dict_iterators as
213 1.1 christos opaque. */
214 1.1 christos
215 1.1 christos /* The dictionary that the iterator is associated to. */
216 1.1 christos #define DICT_ITERATOR_DICT(iter) (iter)->dict
217 1.1 christos /* For linear dictionaries, the index of the last symbol returned; for
218 1.1 christos hashed dictionaries, the bucket of the last symbol returned. */
219 1.1 christos #define DICT_ITERATOR_INDEX(iter) (iter)->index
220 1.1 christos /* For hashed dictionaries, this points to the last symbol returned;
221 1.1 christos otherwise, this is unused. */
222 1.1 christos #define DICT_ITERATOR_CURRENT(iter) (iter)->current
223 1.1 christos
224 1.1 christos /* Declarations of functions for vectors. */
225 1.1 christos
226 1.1 christos /* Functions that might work across a range of dictionary types. */
227 1.1 christos
228 1.1 christos static void add_symbol_nonexpandable (struct dictionary *dict,
229 1.1 christos struct symbol *sym);
230 1.1 christos
231 1.1 christos static void free_obstack (struct dictionary *dict);
232 1.1 christos
233 1.1 christos /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE
234 1.1 christos dictionaries. */
235 1.1 christos
236 1.1 christos static struct symbol *iterator_first_hashed (const struct dictionary *dict,
237 1.1 christos struct dict_iterator *iterator);
238 1.1 christos
239 1.1 christos static struct symbol *iterator_next_hashed (struct dict_iterator *iterator);
240 1.1 christos
241 1.1 christos static struct symbol *iter_match_first_hashed (const struct dictionary *dict,
242 1.8 christos const lookup_name_info &name,
243 1.1 christos struct dict_iterator *iterator);
244 1.1 christos
245 1.8 christos static struct symbol *iter_match_next_hashed (const lookup_name_info &name,
246 1.1 christos struct dict_iterator *iterator);
247 1.1 christos
248 1.1 christos /* Functions only for DICT_HASHED. */
249 1.1 christos
250 1.1 christos static int size_hashed (const struct dictionary *dict);
251 1.1 christos
252 1.1 christos /* Functions only for DICT_HASHED_EXPANDABLE. */
253 1.1 christos
254 1.1 christos static void free_hashed_expandable (struct dictionary *dict);
255 1.1 christos
256 1.1 christos static void add_symbol_hashed_expandable (struct dictionary *dict,
257 1.1 christos struct symbol *sym);
258 1.1 christos
259 1.1 christos static int size_hashed_expandable (const struct dictionary *dict);
260 1.1 christos
261 1.1 christos /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE
262 1.1 christos dictionaries. */
263 1.1 christos
264 1.1 christos static struct symbol *iterator_first_linear (const struct dictionary *dict,
265 1.1 christos struct dict_iterator *iterator);
266 1.1 christos
267 1.1 christos static struct symbol *iterator_next_linear (struct dict_iterator *iterator);
268 1.1 christos
269 1.1 christos static struct symbol *iter_match_first_linear (const struct dictionary *dict,
270 1.8 christos const lookup_name_info &name,
271 1.1 christos struct dict_iterator *iterator);
272 1.1 christos
273 1.8 christos static struct symbol *iter_match_next_linear (const lookup_name_info &name,
274 1.1 christos struct dict_iterator *iterator);
275 1.1 christos
276 1.1 christos static int size_linear (const struct dictionary *dict);
277 1.1 christos
278 1.1 christos /* Functions only for DICT_LINEAR_EXPANDABLE. */
279 1.1 christos
280 1.1 christos static void free_linear_expandable (struct dictionary *dict);
281 1.1 christos
282 1.1 christos static void add_symbol_linear_expandable (struct dictionary *dict,
283 1.1 christos struct symbol *sym);
284 1.1 christos
285 1.1 christos /* Various vectors that we'll actually use. */
286 1.1 christos
287 1.1 christos static const struct dict_vector dict_hashed_vector =
288 1.1 christos {
289 1.1 christos DICT_HASHED, /* type */
290 1.1 christos free_obstack, /* free */
291 1.1 christos add_symbol_nonexpandable, /* add_symbol */
292 1.1 christos iterator_first_hashed, /* iterator_first */
293 1.1 christos iterator_next_hashed, /* iterator_next */
294 1.1 christos iter_match_first_hashed, /* iter_name_first */
295 1.1 christos iter_match_next_hashed, /* iter_name_next */
296 1.1 christos size_hashed, /* size */
297 1.1 christos };
298 1.1 christos
299 1.1 christos static const struct dict_vector dict_hashed_expandable_vector =
300 1.1 christos {
301 1.1 christos DICT_HASHED_EXPANDABLE, /* type */
302 1.1 christos free_hashed_expandable, /* free */
303 1.1 christos add_symbol_hashed_expandable, /* add_symbol */
304 1.1 christos iterator_first_hashed, /* iterator_first */
305 1.1 christos iterator_next_hashed, /* iterator_next */
306 1.1 christos iter_match_first_hashed, /* iter_name_first */
307 1.1 christos iter_match_next_hashed, /* iter_name_next */
308 1.1 christos size_hashed_expandable, /* size */
309 1.1 christos };
310 1.1 christos
311 1.1 christos static const struct dict_vector dict_linear_vector =
312 1.1 christos {
313 1.1 christos DICT_LINEAR, /* type */
314 1.1 christos free_obstack, /* free */
315 1.1 christos add_symbol_nonexpandable, /* add_symbol */
316 1.1 christos iterator_first_linear, /* iterator_first */
317 1.1 christos iterator_next_linear, /* iterator_next */
318 1.1 christos iter_match_first_linear, /* iter_name_first */
319 1.1 christos iter_match_next_linear, /* iter_name_next */
320 1.1 christos size_linear, /* size */
321 1.1 christos };
322 1.1 christos
323 1.1 christos static const struct dict_vector dict_linear_expandable_vector =
324 1.1 christos {
325 1.1 christos DICT_LINEAR_EXPANDABLE, /* type */
326 1.1 christos free_linear_expandable, /* free */
327 1.1 christos add_symbol_linear_expandable, /* add_symbol */
328 1.1 christos iterator_first_linear, /* iterator_first */
329 1.1 christos iterator_next_linear, /* iterator_next */
330 1.1 christos iter_match_first_linear, /* iter_name_first */
331 1.1 christos iter_match_next_linear, /* iter_name_next */
332 1.1 christos size_linear, /* size */
333 1.1 christos };
334 1.1 christos
335 1.1 christos /* Declarations of helper functions (i.e. ones that don't go into
336 1.1 christos vectors). */
337 1.1 christos
338 1.1 christos static struct symbol *iterator_hashed_advance (struct dict_iterator *iter);
339 1.1 christos
340 1.1 christos static void insert_symbol_hashed (struct dictionary *dict,
341 1.1 christos struct symbol *sym);
342 1.1 christos
343 1.1 christos static void expand_hashtable (struct dictionary *dict);
344 1.1 christos
345 1.1 christos /* The creation functions. */
346 1.1 christos
347 1.8 christos /* Create a hashed dictionary of a given language. */
348 1.1 christos
349 1.8 christos static struct dictionary *
350 1.1 christos dict_create_hashed (struct obstack *obstack,
351 1.8 christos enum language language,
352 1.8 christos const std::vector<symbol *> &symbol_list)
353 1.1 christos {
354 1.8 christos /* Allocate the dictionary. */
355 1.8 christos struct dictionary *retval = XOBNEW (obstack, struct dictionary);
356 1.1 christos DICT_VECTOR (retval) = &dict_hashed_vector;
357 1.8 christos DICT_LANGUAGE (retval) = language_def (language);
358 1.1 christos
359 1.8 christos /* Allocate space for symbols. */
360 1.8 christos int nsyms = symbol_list.size ();
361 1.8 christos int nbuckets = DICT_HASHTABLE_SIZE (nsyms);
362 1.1 christos DICT_HASHED_NBUCKETS (retval) = nbuckets;
363 1.8 christos struct symbol **buckets = XOBNEWVEC (obstack, struct symbol *, nbuckets);
364 1.1 christos memset (buckets, 0, nbuckets * sizeof (struct symbol *));
365 1.1 christos DICT_HASHED_BUCKETS (retval) = buckets;
366 1.1 christos
367 1.1 christos /* Now fill the buckets. */
368 1.8 christos for (const auto &sym : symbol_list)
369 1.8 christos insert_symbol_hashed (retval, sym);
370 1.1 christos
371 1.1 christos return retval;
372 1.1 christos }
373 1.1 christos
374 1.8 christos /* Create an expandable hashed dictionary of a given language. */
375 1.1 christos
376 1.8 christos static struct dictionary *
377 1.8 christos dict_create_hashed_expandable (enum language language)
378 1.1 christos {
379 1.6 christos struct dictionary *retval = XNEW (struct dictionary);
380 1.1 christos
381 1.1 christos DICT_VECTOR (retval) = &dict_hashed_expandable_vector;
382 1.8 christos DICT_LANGUAGE (retval) = language_def (language);
383 1.1 christos DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
384 1.6 christos DICT_HASHED_BUCKETS (retval) = XCNEWVEC (struct symbol *,
385 1.6 christos DICT_EXPANDABLE_INITIAL_CAPACITY);
386 1.1 christos DICT_HASHED_EXPANDABLE_NSYMS (retval) = 0;
387 1.1 christos
388 1.1 christos return retval;
389 1.1 christos }
390 1.1 christos
391 1.8 christos /* Create a linear dictionary of a given language. */
392 1.1 christos
393 1.8 christos static struct dictionary *
394 1.1 christos dict_create_linear (struct obstack *obstack,
395 1.8 christos enum language language,
396 1.8 christos const std::vector<symbol *> &symbol_list)
397 1.1 christos {
398 1.8 christos struct dictionary *retval = XOBNEW (obstack, struct dictionary);
399 1.1 christos DICT_VECTOR (retval) = &dict_linear_vector;
400 1.8 christos DICT_LANGUAGE (retval) = language_def (language);
401 1.1 christos
402 1.8 christos /* Allocate space for symbols. */
403 1.8 christos int nsyms = symbol_list.size ();
404 1.1 christos DICT_LINEAR_NSYMS (retval) = nsyms;
405 1.8 christos struct symbol **syms = XOBNEWVEC (obstack, struct symbol *, nsyms);
406 1.1 christos DICT_LINEAR_SYMS (retval) = syms;
407 1.1 christos
408 1.8 christos /* Now fill in the symbols. */
409 1.8 christos int idx = nsyms - 1;
410 1.8 christos for (const auto &sym : symbol_list)
411 1.8 christos syms[idx--] = sym;
412 1.1 christos
413 1.1 christos return retval;
414 1.1 christos }
415 1.1 christos
416 1.8 christos /* Create an expandable linear dictionary of a given language. */
417 1.1 christos
418 1.8 christos static struct dictionary *
419 1.8 christos dict_create_linear_expandable (enum language language)
420 1.1 christos {
421 1.6 christos struct dictionary *retval = XNEW (struct dictionary);
422 1.1 christos
423 1.1 christos DICT_VECTOR (retval) = &dict_linear_expandable_vector;
424 1.8 christos DICT_LANGUAGE (retval) = language_def (language);
425 1.1 christos DICT_LINEAR_NSYMS (retval) = 0;
426 1.6 christos DICT_LINEAR_EXPANDABLE_CAPACITY (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
427 1.1 christos DICT_LINEAR_SYMS (retval)
428 1.6 christos = XNEWVEC (struct symbol *, DICT_LINEAR_EXPANDABLE_CAPACITY (retval));
429 1.1 christos
430 1.1 christos return retval;
431 1.1 christos }
432 1.1 christos
433 1.1 christos /* The functions providing the dictionary interface. */
434 1.1 christos
435 1.1 christos /* Free the memory used by a dictionary that's not on an obstack. (If
436 1.1 christos any.) */
437 1.1 christos
438 1.8 christos static void
439 1.1 christos dict_free (struct dictionary *dict)
440 1.1 christos {
441 1.1 christos (DICT_VECTOR (dict))->free (dict);
442 1.1 christos }
443 1.1 christos
444 1.1 christos /* Add SYM to DICT. DICT had better be expandable. */
445 1.1 christos
446 1.8 christos static void
447 1.1 christos dict_add_symbol (struct dictionary *dict, struct symbol *sym)
448 1.1 christos {
449 1.1 christos (DICT_VECTOR (dict))->add_symbol (dict, sym);
450 1.1 christos }
451 1.1 christos
452 1.1 christos /* Utility to add a list of symbols to a dictionary.
453 1.1 christos DICT must be an expandable dictionary. */
454 1.1 christos
455 1.8 christos static void
456 1.8 christos dict_add_pending (struct dictionary *dict,
457 1.8 christos const std::vector<symbol *> &symbol_list)
458 1.1 christos {
459 1.8 christos /* Preserve ordering by reversing the list. */
460 1.8 christos for (auto sym = symbol_list.rbegin (); sym != symbol_list.rend (); ++sym)
461 1.8 christos dict_add_symbol (dict, *sym);
462 1.1 christos }
463 1.1 christos
464 1.1 christos /* Initialize ITERATOR to point at the first symbol in DICT, and
465 1.1 christos return that first symbol, or NULL if DICT is empty. */
466 1.1 christos
467 1.1 christos struct symbol *
468 1.1 christos dict_iterator_first (const struct dictionary *dict,
469 1.1 christos struct dict_iterator *iterator)
470 1.1 christos {
471 1.1 christos return (DICT_VECTOR (dict))->iterator_first (dict, iterator);
472 1.1 christos }
473 1.1 christos
474 1.1 christos /* Advance ITERATOR, and return the next symbol, or NULL if there are
475 1.1 christos no more symbols. */
476 1.1 christos
477 1.1 christos struct symbol *
478 1.1 christos dict_iterator_next (struct dict_iterator *iterator)
479 1.1 christos {
480 1.1 christos return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator)))
481 1.1 christos ->iterator_next (iterator);
482 1.1 christos }
483 1.1 christos
484 1.1 christos struct symbol *
485 1.1 christos dict_iter_match_first (const struct dictionary *dict,
486 1.8 christos const lookup_name_info &name,
487 1.1 christos struct dict_iterator *iterator)
488 1.1 christos {
489 1.8 christos return (DICT_VECTOR (dict))->iter_match_first (dict, name, iterator);
490 1.1 christos }
491 1.1 christos
492 1.1 christos struct symbol *
493 1.8 christos dict_iter_match_next (const lookup_name_info &name,
494 1.1 christos struct dict_iterator *iterator)
495 1.1 christos {
496 1.1 christos return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator)))
497 1.8 christos ->iter_match_next (name, iterator);
498 1.1 christos }
499 1.1 christos
500 1.8 christos static int
501 1.1 christos dict_size (const struct dictionary *dict)
502 1.1 christos {
503 1.1 christos return (DICT_VECTOR (dict))->size (dict);
504 1.1 christos }
505 1.1 christos
506 1.1 christos /* Now come functions (well, one function, currently) that are
507 1.1 christos implemented generically by means of the vtable. Typically, they're
508 1.1 christos rarely used. */
509 1.1 christos
510 1.1 christos /* Test to see if DICT is empty. */
511 1.1 christos
512 1.8 christos static int
513 1.1 christos dict_empty (struct dictionary *dict)
514 1.1 christos {
515 1.1 christos struct dict_iterator iter;
516 1.1 christos
517 1.1 christos return (dict_iterator_first (dict, &iter) == NULL);
518 1.1 christos }
519 1.1 christos
520 1.1 christos
521 1.1 christos /* The functions implementing the dictionary interface. */
522 1.1 christos
523 1.1 christos /* Generic functions, where appropriate. */
524 1.1 christos
525 1.1 christos static void
526 1.1 christos free_obstack (struct dictionary *dict)
527 1.1 christos {
528 1.1 christos /* Do nothing! */
529 1.1 christos }
530 1.1 christos
531 1.1 christos static void
532 1.1 christos add_symbol_nonexpandable (struct dictionary *dict, struct symbol *sym)
533 1.1 christos {
534 1.1 christos internal_error (__FILE__, __LINE__,
535 1.1 christos _("dict_add_symbol: non-expandable dictionary"));
536 1.1 christos }
537 1.1 christos
538 1.1 christos /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE. */
539 1.1 christos
540 1.1 christos static struct symbol *
541 1.1 christos iterator_first_hashed (const struct dictionary *dict,
542 1.1 christos struct dict_iterator *iterator)
543 1.1 christos {
544 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
545 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1;
546 1.1 christos return iterator_hashed_advance (iterator);
547 1.1 christos }
548 1.1 christos
549 1.1 christos static struct symbol *
550 1.1 christos iterator_next_hashed (struct dict_iterator *iterator)
551 1.1 christos {
552 1.1 christos struct symbol *next;
553 1.1 christos
554 1.1 christos next = DICT_ITERATOR_CURRENT (iterator)->hash_next;
555 1.1 christos
556 1.1 christos if (next == NULL)
557 1.1 christos return iterator_hashed_advance (iterator);
558 1.1 christos else
559 1.1 christos {
560 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next;
561 1.1 christos return next;
562 1.1 christos }
563 1.1 christos }
564 1.1 christos
565 1.1 christos static struct symbol *
566 1.1 christos iterator_hashed_advance (struct dict_iterator *iterator)
567 1.1 christos {
568 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
569 1.1 christos int nbuckets = DICT_HASHED_NBUCKETS (dict);
570 1.1 christos int i;
571 1.1 christos
572 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nbuckets; ++i)
573 1.1 christos {
574 1.1 christos struct symbol *sym = DICT_HASHED_BUCKET (dict, i);
575 1.1 christos
576 1.1 christos if (sym != NULL)
577 1.1 christos {
578 1.1 christos DICT_ITERATOR_INDEX (iterator) = i;
579 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym;
580 1.1 christos return sym;
581 1.1 christos }
582 1.1 christos }
583 1.1 christos
584 1.1 christos return NULL;
585 1.1 christos }
586 1.1 christos
587 1.1 christos static struct symbol *
588 1.8 christos iter_match_first_hashed (const struct dictionary *dict,
589 1.8 christos const lookup_name_info &name,
590 1.1 christos struct dict_iterator *iterator)
591 1.1 christos {
592 1.8 christos const language_defn *lang = DICT_LANGUAGE (dict);
593 1.8 christos unsigned int hash_index = (name.search_name_hash (lang->la_language)
594 1.8 christos % DICT_HASHED_NBUCKETS (dict));
595 1.8 christos symbol_name_matcher_ftype *matches_name
596 1.8 christos = get_symbol_name_matcher (lang, name);
597 1.1 christos struct symbol *sym;
598 1.1 christos
599 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
600 1.1 christos
601 1.1 christos /* Loop through the symbols in the given bucket, breaking when SYM
602 1.1 christos first matches. If SYM never matches, it will be set to NULL;
603 1.1 christos either way, we have the right return value. */
604 1.1 christos
605 1.1 christos for (sym = DICT_HASHED_BUCKET (dict, hash_index);
606 1.1 christos sym != NULL;
607 1.1 christos sym = sym->hash_next)
608 1.1 christos {
609 1.1 christos /* Warning: the order of arguments to compare matters! */
610 1.8 christos if (matches_name (SYMBOL_SEARCH_NAME (sym), name, NULL))
611 1.8 christos break;
612 1.1 christos }
613 1.1 christos
614 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym;
615 1.1 christos return sym;
616 1.1 christos }
617 1.1 christos
618 1.1 christos static struct symbol *
619 1.8 christos iter_match_next_hashed (const lookup_name_info &name,
620 1.1 christos struct dict_iterator *iterator)
621 1.1 christos {
622 1.8 christos const language_defn *lang = DICT_LANGUAGE (DICT_ITERATOR_DICT (iterator));
623 1.8 christos symbol_name_matcher_ftype *matches_name
624 1.8 christos = get_symbol_name_matcher (lang, name);
625 1.1 christos struct symbol *next;
626 1.1 christos
627 1.1 christos for (next = DICT_ITERATOR_CURRENT (iterator)->hash_next;
628 1.1 christos next != NULL;
629 1.1 christos next = next->hash_next)
630 1.1 christos {
631 1.8 christos if (matches_name (SYMBOL_SEARCH_NAME (next), name, NULL))
632 1.1 christos break;
633 1.1 christos }
634 1.1 christos
635 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next;
636 1.1 christos
637 1.1 christos return next;
638 1.1 christos }
639 1.1 christos
640 1.1 christos /* Insert SYM into DICT. */
641 1.1 christos
642 1.1 christos static void
643 1.1 christos insert_symbol_hashed (struct dictionary *dict,
644 1.1 christos struct symbol *sym)
645 1.1 christos {
646 1.1 christos unsigned int hash_index;
647 1.8 christos unsigned int hash;
648 1.1 christos struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
649 1.1 christos
650 1.8 christos /* We don't want to insert a symbol into a dictionary of a different
651 1.8 christos language. The two may not use the same hashing algorithm. */
652 1.8 christos gdb_assert (SYMBOL_LANGUAGE (sym) == DICT_LANGUAGE (dict)->la_language);
653 1.8 christos
654 1.8 christos hash = search_name_hash (SYMBOL_LANGUAGE (sym), SYMBOL_SEARCH_NAME (sym));
655 1.8 christos hash_index = hash % DICT_HASHED_NBUCKETS (dict);
656 1.1 christos sym->hash_next = buckets[hash_index];
657 1.1 christos buckets[hash_index] = sym;
658 1.1 christos }
659 1.1 christos
660 1.1 christos static int
661 1.1 christos size_hashed (const struct dictionary *dict)
662 1.1 christos {
663 1.1 christos return DICT_HASHED_NBUCKETS (dict);
664 1.1 christos }
665 1.1 christos
666 1.1 christos /* Functions only for DICT_HASHED_EXPANDABLE. */
667 1.1 christos
668 1.1 christos static void
669 1.1 christos free_hashed_expandable (struct dictionary *dict)
670 1.1 christos {
671 1.1 christos xfree (DICT_HASHED_BUCKETS (dict));
672 1.1 christos xfree (dict);
673 1.1 christos }
674 1.1 christos
675 1.1 christos static void
676 1.1 christos add_symbol_hashed_expandable (struct dictionary *dict,
677 1.1 christos struct symbol *sym)
678 1.1 christos {
679 1.1 christos int nsyms = ++DICT_HASHED_EXPANDABLE_NSYMS (dict);
680 1.1 christos
681 1.1 christos if (DICT_HASHTABLE_SIZE (nsyms) > DICT_HASHED_NBUCKETS (dict))
682 1.1 christos expand_hashtable (dict);
683 1.1 christos
684 1.1 christos insert_symbol_hashed (dict, sym);
685 1.1 christos DICT_HASHED_EXPANDABLE_NSYMS (dict) = nsyms;
686 1.1 christos }
687 1.1 christos
688 1.1 christos static int
689 1.1 christos size_hashed_expandable (const struct dictionary *dict)
690 1.1 christos {
691 1.1 christos return DICT_HASHED_EXPANDABLE_NSYMS (dict);
692 1.1 christos }
693 1.1 christos
694 1.1 christos static void
695 1.1 christos expand_hashtable (struct dictionary *dict)
696 1.1 christos {
697 1.1 christos int old_nbuckets = DICT_HASHED_NBUCKETS (dict);
698 1.1 christos struct symbol **old_buckets = DICT_HASHED_BUCKETS (dict);
699 1.6 christos int new_nbuckets = 2 * old_nbuckets + 1;
700 1.6 christos struct symbol **new_buckets = XCNEWVEC (struct symbol *, new_nbuckets);
701 1.1 christos int i;
702 1.1 christos
703 1.1 christos DICT_HASHED_NBUCKETS (dict) = new_nbuckets;
704 1.1 christos DICT_HASHED_BUCKETS (dict) = new_buckets;
705 1.1 christos
706 1.1 christos for (i = 0; i < old_nbuckets; ++i)
707 1.1 christos {
708 1.1 christos struct symbol *sym, *next_sym;
709 1.1 christos
710 1.1 christos sym = old_buckets[i];
711 1.1 christos if (sym != NULL)
712 1.1 christos {
713 1.1 christos for (next_sym = sym->hash_next;
714 1.1 christos next_sym != NULL;
715 1.1 christos next_sym = sym->hash_next)
716 1.1 christos {
717 1.1 christos insert_symbol_hashed (dict, sym);
718 1.1 christos sym = next_sym;
719 1.1 christos }
720 1.1 christos
721 1.1 christos insert_symbol_hashed (dict, sym);
722 1.1 christos }
723 1.1 christos }
724 1.1 christos
725 1.1 christos xfree (old_buckets);
726 1.1 christos }
727 1.1 christos
728 1.8 christos /* See dictionary.h. */
729 1.1 christos
730 1.8 christos unsigned int
731 1.8 christos default_search_name_hash (const char *string0)
732 1.1 christos {
733 1.1 christos /* The Ada-encoded version of a name P1.P2...Pn has either the form
734 1.1 christos P1__P2__...Pn<suffix> or _ada_P1__P2__...Pn<suffix> (where the Pi
735 1.1 christos are lower-cased identifiers). The <suffix> (which can be empty)
736 1.1 christos encodes additional information about the denoted entity. This
737 1.1 christos routine hashes such names to msymbol_hash_iw(Pn). It actually
738 1.1 christos does this for a superset of both valid Pi and of <suffix>, but
739 1.1 christos in other cases it simply returns msymbol_hash_iw(STRING0). */
740 1.1 christos
741 1.1 christos const char *string;
742 1.1 christos unsigned int hash;
743 1.1 christos
744 1.1 christos string = string0;
745 1.1 christos if (*string == '_')
746 1.1 christos {
747 1.5 christos if (startswith (string, "_ada_"))
748 1.1 christos string += 5;
749 1.1 christos else
750 1.1 christos return msymbol_hash_iw (string0);
751 1.1 christos }
752 1.1 christos
753 1.1 christos hash = 0;
754 1.1 christos while (*string)
755 1.1 christos {
756 1.1 christos switch (*string)
757 1.1 christos {
758 1.1 christos case '$':
759 1.1 christos case '.':
760 1.1 christos case 'X':
761 1.1 christos if (string0 == string)
762 1.1 christos return msymbol_hash_iw (string0);
763 1.1 christos else
764 1.1 christos return hash;
765 1.1 christos case ' ':
766 1.1 christos case '(':
767 1.1 christos return msymbol_hash_iw (string0);
768 1.1 christos case '_':
769 1.1 christos if (string[1] == '_' && string != string0)
770 1.1 christos {
771 1.1 christos int c = string[2];
772 1.1 christos
773 1.1 christos if ((c < 'a' || c > 'z') && c != 'O')
774 1.1 christos return hash;
775 1.1 christos hash = 0;
776 1.1 christos string += 2;
777 1.8 christos continue;
778 1.1 christos }
779 1.8 christos break;
780 1.8 christos case 'T':
781 1.8 christos /* Ignore "TKB" suffixes.
782 1.8 christos
783 1.8 christos These are used by Ada for subprograms implementing a task body.
784 1.8 christos For instance for a task T inside package Pck, the name of the
785 1.8 christos subprogram implementing T's body is `pck__tTKB'. We need to
786 1.8 christos ignore the "TKB" suffix because searches for this task body
787 1.8 christos subprogram are going to be performed using `pck__t' (the encoded
788 1.8 christos version of the natural name `pck.t'). */
789 1.8 christos if (strcmp (string, "TKB") == 0)
790 1.8 christos return hash;
791 1.1 christos break;
792 1.1 christos }
793 1.8 christos
794 1.8 christos hash = SYMBOL_HASH_NEXT (hash, *string);
795 1.8 christos string += 1;
796 1.1 christos }
797 1.1 christos return hash;
798 1.1 christos }
799 1.1 christos
800 1.1 christos /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE. */
801 1.1 christos
802 1.1 christos static struct symbol *
803 1.1 christos iterator_first_linear (const struct dictionary *dict,
804 1.1 christos struct dict_iterator *iterator)
805 1.1 christos {
806 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
807 1.1 christos DICT_ITERATOR_INDEX (iterator) = 0;
808 1.1 christos return DICT_LINEAR_NSYMS (dict) ? DICT_LINEAR_SYM (dict, 0) : NULL;
809 1.1 christos }
810 1.1 christos
811 1.1 christos static struct symbol *
812 1.1 christos iterator_next_linear (struct dict_iterator *iterator)
813 1.1 christos {
814 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
815 1.1 christos
816 1.1 christos if (++DICT_ITERATOR_INDEX (iterator) >= DICT_LINEAR_NSYMS (dict))
817 1.1 christos return NULL;
818 1.1 christos else
819 1.1 christos return DICT_LINEAR_SYM (dict, DICT_ITERATOR_INDEX (iterator));
820 1.1 christos }
821 1.1 christos
822 1.1 christos static struct symbol *
823 1.1 christos iter_match_first_linear (const struct dictionary *dict,
824 1.8 christos const lookup_name_info &name,
825 1.1 christos struct dict_iterator *iterator)
826 1.1 christos {
827 1.1 christos DICT_ITERATOR_DICT (iterator) = dict;
828 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1;
829 1.1 christos
830 1.8 christos return iter_match_next_linear (name, iterator);
831 1.1 christos }
832 1.1 christos
833 1.1 christos static struct symbol *
834 1.8 christos iter_match_next_linear (const lookup_name_info &name,
835 1.1 christos struct dict_iterator *iterator)
836 1.1 christos {
837 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator);
838 1.8 christos const language_defn *lang = DICT_LANGUAGE (dict);
839 1.8 christos symbol_name_matcher_ftype *matches_name
840 1.8 christos = get_symbol_name_matcher (lang, name);
841 1.8 christos
842 1.1 christos int i, nsyms = DICT_LINEAR_NSYMS (dict);
843 1.1 christos struct symbol *sym, *retval = NULL;
844 1.1 christos
845 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nsyms; ++i)
846 1.1 christos {
847 1.1 christos sym = DICT_LINEAR_SYM (dict, i);
848 1.8 christos
849 1.8 christos if (matches_name (SYMBOL_SEARCH_NAME (sym), name, NULL))
850 1.1 christos {
851 1.1 christos retval = sym;
852 1.1 christos break;
853 1.1 christos }
854 1.1 christos }
855 1.1 christos
856 1.1 christos DICT_ITERATOR_INDEX (iterator) = i;
857 1.1 christos
858 1.1 christos return retval;
859 1.1 christos }
860 1.1 christos
861 1.1 christos static int
862 1.1 christos size_linear (const struct dictionary *dict)
863 1.1 christos {
864 1.1 christos return DICT_LINEAR_NSYMS (dict);
865 1.1 christos }
866 1.1 christos
867 1.1 christos /* Functions only for DICT_LINEAR_EXPANDABLE. */
868 1.1 christos
869 1.1 christos static void
870 1.1 christos free_linear_expandable (struct dictionary *dict)
871 1.1 christos {
872 1.1 christos xfree (DICT_LINEAR_SYMS (dict));
873 1.1 christos xfree (dict);
874 1.1 christos }
875 1.1 christos
876 1.1 christos
877 1.1 christos static void
878 1.1 christos add_symbol_linear_expandable (struct dictionary *dict,
879 1.1 christos struct symbol *sym)
880 1.1 christos {
881 1.1 christos int nsyms = ++DICT_LINEAR_NSYMS (dict);
882 1.1 christos
883 1.1 christos /* Do we have enough room? If not, grow it. */
884 1.1 christos if (nsyms > DICT_LINEAR_EXPANDABLE_CAPACITY (dict))
885 1.1 christos {
886 1.1 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict) *= 2;
887 1.1 christos DICT_LINEAR_SYMS (dict)
888 1.6 christos = XRESIZEVEC (struct symbol *, DICT_LINEAR_SYMS (dict),
889 1.6 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict));
890 1.1 christos }
891 1.1 christos
892 1.1 christos DICT_LINEAR_SYM (dict, nsyms - 1) = sym;
893 1.1 christos }
894 1.8 christos
895 1.8 christos /* Multi-language dictionary support. */
896 1.8 christos
897 1.8 christos /* The structure describing a multi-language dictionary. */
898 1.8 christos
899 1.8 christos struct multidictionary
900 1.8 christos {
901 1.8 christos /* An array of dictionaries, one per language. All dictionaries
902 1.8 christos must be of the same type. This should be free'd for expandable
903 1.8 christos dictionary types. */
904 1.8 christos struct dictionary **dictionaries;
905 1.8 christos
906 1.8 christos /* The number of language dictionaries currently allocated.
907 1.8 christos Only used for expandable dictionaries. */
908 1.8 christos unsigned short n_allocated_dictionaries;
909 1.8 christos };
910 1.8 christos
911 1.8 christos /* A hasher for enum language. Injecting this into std is a convenience
912 1.8 christos when using unordered_map with C++11. */
913 1.8 christos
914 1.8 christos namespace std
915 1.8 christos {
916 1.8 christos template<> struct hash<enum language>
917 1.8 christos {
918 1.8 christos typedef enum language argument_type;
919 1.8 christos typedef std::size_t result_type;
920 1.8 christos
921 1.8 christos result_type operator() (const argument_type &l) const noexcept
922 1.8 christos {
923 1.8 christos return static_cast<result_type> (l);
924 1.8 christos }
925 1.8 christos };
926 1.8 christos } /* namespace std */
927 1.8 christos
928 1.8 christos /* A helper function to collate symbols on the pending list by language. */
929 1.8 christos
930 1.8 christos static std::unordered_map<enum language, std::vector<symbol *>>
931 1.8 christos collate_pending_symbols_by_language (const struct pending *symbol_list)
932 1.8 christos {
933 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms;
934 1.8 christos
935 1.8 christos for (const struct pending *list_counter = symbol_list;
936 1.8 christos list_counter != nullptr; list_counter = list_counter->next)
937 1.8 christos {
938 1.8 christos for (int i = list_counter->nsyms - 1; i >= 0; --i)
939 1.8 christos {
940 1.8 christos enum language language = SYMBOL_LANGUAGE (list_counter->symbol[i]);
941 1.8 christos nsyms[language].push_back (list_counter->symbol[i]);
942 1.8 christos }
943 1.8 christos }
944 1.8 christos
945 1.8 christos return nsyms;
946 1.8 christos }
947 1.8 christos
948 1.8 christos /* See dictionary.h. */
949 1.8 christos
950 1.8 christos struct multidictionary *
951 1.8 christos mdict_create_hashed (struct obstack *obstack,
952 1.8 christos const struct pending *symbol_list)
953 1.8 christos {
954 1.8 christos struct multidictionary *retval
955 1.8 christos = XOBNEW (obstack, struct multidictionary);
956 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms
957 1.8 christos = collate_pending_symbols_by_language (symbol_list);
958 1.8 christos
959 1.8 christos /* Loop over all languages and create/populate dictionaries. */
960 1.8 christos retval->dictionaries
961 1.8 christos = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ());
962 1.8 christos retval->n_allocated_dictionaries = nsyms.size ();
963 1.8 christos
964 1.8 christos int idx = 0;
965 1.8 christos for (const auto &pair : nsyms)
966 1.8 christos {
967 1.8 christos enum language language = pair.first;
968 1.8 christos std::vector<symbol *> symlist = pair.second;
969 1.8 christos
970 1.8 christos retval->dictionaries[idx++]
971 1.8 christos = dict_create_hashed (obstack, language, symlist);
972 1.8 christos }
973 1.8 christos
974 1.8 christos return retval;
975 1.8 christos }
976 1.8 christos
977 1.8 christos /* See dictionary.h. */
978 1.8 christos
979 1.8 christos struct multidictionary *
980 1.8 christos mdict_create_hashed_expandable (enum language language)
981 1.8 christos {
982 1.8 christos struct multidictionary *retval = XNEW (struct multidictionary);
983 1.8 christos
984 1.8 christos /* We have no symbol list to populate, but we create an empty
985 1.8 christos dictionary of the requested language to populate later. */
986 1.8 christos retval->n_allocated_dictionaries = 1;
987 1.8 christos retval->dictionaries = XNEW (struct dictionary *);
988 1.8 christos retval->dictionaries[0] = dict_create_hashed_expandable (language);
989 1.8 christos
990 1.8 christos return retval;
991 1.8 christos }
992 1.8 christos
993 1.8 christos /* See dictionary.h. */
994 1.8 christos
995 1.8 christos struct multidictionary *
996 1.8 christos mdict_create_linear (struct obstack *obstack,
997 1.8 christos const struct pending *symbol_list)
998 1.8 christos {
999 1.8 christos struct multidictionary *retval
1000 1.8 christos = XOBNEW (obstack, struct multidictionary);
1001 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms
1002 1.8 christos = collate_pending_symbols_by_language (symbol_list);
1003 1.8 christos
1004 1.8 christos /* Loop over all languages and create/populate dictionaries. */
1005 1.8 christos retval->dictionaries
1006 1.8 christos = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ());
1007 1.8 christos retval->n_allocated_dictionaries = nsyms.size ();
1008 1.8 christos
1009 1.8 christos int idx = 0;
1010 1.8 christos for (const auto &pair : nsyms)
1011 1.8 christos {
1012 1.8 christos enum language language = pair.first;
1013 1.8 christos std::vector<symbol *> symlist = pair.second;
1014 1.8 christos
1015 1.8 christos retval->dictionaries[idx++]
1016 1.8 christos = dict_create_linear (obstack, language, symlist);
1017 1.8 christos }
1018 1.8 christos
1019 1.8 christos return retval;
1020 1.8 christos }
1021 1.8 christos
1022 1.8 christos /* See dictionary.h. */
1023 1.8 christos
1024 1.8 christos struct multidictionary *
1025 1.8 christos mdict_create_linear_expandable (enum language language)
1026 1.8 christos {
1027 1.8 christos struct multidictionary *retval = XNEW (struct multidictionary);
1028 1.8 christos
1029 1.8 christos /* We have no symbol list to populate, but we create an empty
1030 1.8 christos dictionary to populate later. */
1031 1.8 christos retval->n_allocated_dictionaries = 1;
1032 1.8 christos retval->dictionaries = XNEW (struct dictionary *);
1033 1.8 christos retval->dictionaries[0] = dict_create_linear_expandable (language);
1034 1.8 christos
1035 1.8 christos return retval;
1036 1.8 christos }
1037 1.8 christos
1038 1.8 christos /* See dictionary.h. */
1039 1.8 christos
1040 1.8 christos void
1041 1.8 christos mdict_free (struct multidictionary *mdict)
1042 1.8 christos {
1043 1.8 christos /* Grab the type of dictionary being used. */
1044 1.8 christos enum dict_type type = mdict->dictionaries[0]->vector->type;
1045 1.8 christos
1046 1.8 christos /* Loop over all dictionaries and free them. */
1047 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx)
1048 1.8 christos dict_free (mdict->dictionaries[idx]);
1049 1.8 christos
1050 1.8 christos /* Free the dictionary list, if needed. */
1051 1.8 christos switch (type)
1052 1.8 christos {
1053 1.8 christos case DICT_HASHED:
1054 1.8 christos case DICT_LINEAR:
1055 1.8 christos /* Memory was allocated on an obstack when created. */
1056 1.8 christos break;
1057 1.8 christos
1058 1.8 christos case DICT_HASHED_EXPANDABLE:
1059 1.8 christos case DICT_LINEAR_EXPANDABLE:
1060 1.8 christos xfree (mdict->dictionaries);
1061 1.8 christos break;
1062 1.8 christos }
1063 1.8 christos }
1064 1.8 christos
1065 1.8 christos /* Helper function to find the dictionary associated with LANGUAGE
1066 1.8 christos or NULL if there is no dictionary of that language. */
1067 1.8 christos
1068 1.8 christos static struct dictionary *
1069 1.8 christos find_language_dictionary (const struct multidictionary *mdict,
1070 1.8 christos enum language language)
1071 1.8 christos {
1072 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx)
1073 1.8 christos {
1074 1.8 christos if (DICT_LANGUAGE (mdict->dictionaries[idx])->la_language == language)
1075 1.8 christos return mdict->dictionaries[idx];
1076 1.8 christos }
1077 1.8 christos
1078 1.8 christos return nullptr;
1079 1.8 christos }
1080 1.8 christos
1081 1.8 christos /* Create a new language dictionary for LANGUAGE and add it to the
1082 1.8 christos multidictionary MDICT's list of dictionaries. If MDICT is not
1083 1.8 christos based on expandable dictionaries, this function throws an
1084 1.8 christos internal error. */
1085 1.8 christos
1086 1.8 christos static struct dictionary *
1087 1.8 christos create_new_language_dictionary (struct multidictionary *mdict,
1088 1.8 christos enum language language)
1089 1.8 christos {
1090 1.8 christos struct dictionary *retval = nullptr;
1091 1.8 christos
1092 1.8 christos /* We use the first dictionary entry to decide what create function
1093 1.8 christos to call. Not optimal but sufficient. */
1094 1.8 christos gdb_assert (mdict->dictionaries[0] != nullptr);
1095 1.8 christos switch (mdict->dictionaries[0]->vector->type)
1096 1.8 christos {
1097 1.8 christos case DICT_HASHED:
1098 1.8 christos case DICT_LINEAR:
1099 1.8 christos internal_error (__FILE__, __LINE__,
1100 1.8 christos _("create_new_language_dictionary: attempted to expand "
1101 1.8 christos "non-expandable multidictionary"));
1102 1.8 christos
1103 1.8 christos case DICT_HASHED_EXPANDABLE:
1104 1.8 christos retval = dict_create_hashed_expandable (language);
1105 1.8 christos break;
1106 1.8 christos
1107 1.8 christos case DICT_LINEAR_EXPANDABLE:
1108 1.8 christos retval = dict_create_linear_expandable (language);
1109 1.8 christos break;
1110 1.8 christos }
1111 1.8 christos
1112 1.8 christos /* Grow the dictionary vector and save the new dictionary. */
1113 1.8 christos mdict->dictionaries
1114 1.8 christos = (struct dictionary **) xrealloc (mdict->dictionaries,
1115 1.8 christos (++mdict->n_allocated_dictionaries
1116 1.8 christos * sizeof (struct dictionary *)));
1117 1.8 christos mdict->dictionaries[mdict->n_allocated_dictionaries - 1] = retval;
1118 1.8 christos
1119 1.8 christos return retval;
1120 1.8 christos }
1121 1.8 christos
1122 1.8 christos /* See dictionary.h. */
1123 1.8 christos
1124 1.8 christos void
1125 1.8 christos mdict_add_symbol (struct multidictionary *mdict, struct symbol *sym)
1126 1.8 christos {
1127 1.8 christos struct dictionary *dict
1128 1.8 christos = find_language_dictionary (mdict, SYMBOL_LANGUAGE (sym));
1129 1.8 christos
1130 1.8 christos if (dict == nullptr)
1131 1.8 christos {
1132 1.8 christos /* SYM is of a new language that we haven't previously seen.
1133 1.8 christos Create a new dictionary for it. */
1134 1.8 christos dict = create_new_language_dictionary (mdict, SYMBOL_LANGUAGE (sym));
1135 1.8 christos }
1136 1.8 christos
1137 1.8 christos dict_add_symbol (dict, sym);
1138 1.8 christos }
1139 1.8 christos
1140 1.8 christos /* See dictionary.h. */
1141 1.8 christos
1142 1.8 christos void
1143 1.8 christos mdict_add_pending (struct multidictionary *mdict,
1144 1.8 christos const struct pending *symbol_list)
1145 1.8 christos {
1146 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms
1147 1.8 christos = collate_pending_symbols_by_language (symbol_list);
1148 1.8 christos
1149 1.8 christos for (const auto &pair : nsyms)
1150 1.8 christos {
1151 1.8 christos enum language language = pair.first;
1152 1.8 christos std::vector<symbol *> symlist = pair.second;
1153 1.8 christos struct dictionary *dict = find_language_dictionary (mdict, language);
1154 1.8 christos
1155 1.8 christos if (dict == nullptr)
1156 1.8 christos {
1157 1.8 christos /* The language was not previously seen. Create a new dictionary
1158 1.8 christos for it. */
1159 1.8 christos dict = create_new_language_dictionary (mdict, language);
1160 1.8 christos }
1161 1.8 christos
1162 1.8 christos dict_add_pending (dict, symlist);
1163 1.8 christos }
1164 1.8 christos }
1165 1.8 christos
1166 1.8 christos /* See dictionary.h. */
1167 1.8 christos
1168 1.8 christos struct symbol *
1169 1.8 christos mdict_iterator_first (const multidictionary *mdict,
1170 1.8 christos struct mdict_iterator *miterator)
1171 1.8 christos {
1172 1.8 christos miterator->mdict = mdict;
1173 1.8 christos miterator->current_idx = 0;
1174 1.8 christos
1175 1.8 christos for (unsigned short idx = miterator->current_idx;
1176 1.8 christos idx < mdict->n_allocated_dictionaries; ++idx)
1177 1.8 christos {
1178 1.8 christos struct symbol *result
1179 1.8 christos = dict_iterator_first (mdict->dictionaries[idx], &miterator->iterator);
1180 1.8 christos
1181 1.8 christos if (result != nullptr)
1182 1.8 christos {
1183 1.8 christos miterator->current_idx = idx;
1184 1.8 christos return result;
1185 1.8 christos }
1186 1.8 christos }
1187 1.8 christos
1188 1.8 christos return nullptr;
1189 1.8 christos }
1190 1.8 christos
1191 1.8 christos /* See dictionary.h. */
1192 1.8 christos
1193 1.8 christos struct symbol *
1194 1.8 christos mdict_iterator_next (struct mdict_iterator *miterator)
1195 1.8 christos {
1196 1.8 christos struct symbol *result = dict_iterator_next (&miterator->iterator);
1197 1.8 christos
1198 1.8 christos if (result != nullptr)
1199 1.8 christos return result;
1200 1.8 christos
1201 1.8 christos /* The current dictionary had no matches -- move to the next
1202 1.8 christos dictionary, if any. */
1203 1.8 christos for (unsigned short idx = ++miterator->current_idx;
1204 1.8 christos idx < miterator->mdict->n_allocated_dictionaries; ++idx)
1205 1.8 christos {
1206 1.8 christos result
1207 1.8 christos = dict_iterator_first (miterator->mdict->dictionaries[idx],
1208 1.8 christos &miterator->iterator);
1209 1.8 christos if (result != nullptr)
1210 1.8 christos {
1211 1.8 christos miterator->current_idx = idx;
1212 1.8 christos return result;
1213 1.8 christos }
1214 1.8 christos }
1215 1.8 christos
1216 1.8 christos return nullptr;
1217 1.8 christos }
1218 1.8 christos
1219 1.8 christos /* See dictionary.h. */
1220 1.8 christos
1221 1.8 christos struct symbol *
1222 1.8 christos mdict_iter_match_first (const struct multidictionary *mdict,
1223 1.8 christos const lookup_name_info &name,
1224 1.8 christos struct mdict_iterator *miterator)
1225 1.8 christos {
1226 1.8 christos miterator->mdict = mdict;
1227 1.8 christos miterator->current_idx = 0;
1228 1.8 christos
1229 1.8 christos for (unsigned short idx = miterator->current_idx;
1230 1.8 christos idx < mdict->n_allocated_dictionaries; ++idx)
1231 1.8 christos {
1232 1.8 christos struct symbol *result
1233 1.8 christos = dict_iter_match_first (mdict->dictionaries[idx], name,
1234 1.8 christos &miterator->iterator);
1235 1.8 christos
1236 1.8 christos if (result != nullptr)
1237 1.8 christos return result;
1238 1.8 christos }
1239 1.8 christos
1240 1.8 christos return nullptr;
1241 1.8 christos }
1242 1.8 christos
1243 1.8 christos /* See dictionary.h. */
1244 1.8 christos
1245 1.8 christos struct symbol *
1246 1.8 christos mdict_iter_match_next (const lookup_name_info &name,
1247 1.8 christos struct mdict_iterator *miterator)
1248 1.8 christos {
1249 1.8 christos /* Search the current dictionary. */
1250 1.8 christos struct symbol *result = dict_iter_match_next (name, &miterator->iterator);
1251 1.8 christos
1252 1.8 christos if (result != nullptr)
1253 1.8 christos return result;
1254 1.8 christos
1255 1.8 christos /* The current dictionary had no matches -- move to the next
1256 1.8 christos dictionary, if any. */
1257 1.8 christos for (unsigned short idx = ++miterator->current_idx;
1258 1.8 christos idx < miterator->mdict->n_allocated_dictionaries; ++idx)
1259 1.8 christos {
1260 1.8 christos result
1261 1.8 christos = dict_iter_match_first (miterator->mdict->dictionaries[idx],
1262 1.8 christos name, &miterator->iterator);
1263 1.8 christos if (result != nullptr)
1264 1.8 christos {
1265 1.8 christos miterator->current_idx = idx;
1266 1.8 christos return result;
1267 1.8 christos }
1268 1.8 christos }
1269 1.8 christos
1270 1.8 christos return nullptr;
1271 1.8 christos }
1272 1.8 christos
1273 1.8 christos /* See dictionary.h. */
1274 1.8 christos
1275 1.8 christos int
1276 1.8 christos mdict_size (const struct multidictionary *mdict)
1277 1.8 christos {
1278 1.8 christos int size = 0;
1279 1.8 christos
1280 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx)
1281 1.8 christos size += dict_size (mdict->dictionaries[idx]);
1282 1.8 christos
1283 1.8 christos return size;
1284 1.8 christos }
1285 1.8 christos
1286 1.8 christos /* See dictionary.h. */
1287 1.8 christos
1288 1.8 christos bool
1289 1.8 christos mdict_empty (const struct multidictionary *mdict)
1290 1.8 christos {
1291 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx)
1292 1.8 christos {
1293 1.8 christos if (!dict_empty (mdict->dictionaries[idx]))
1294 1.8 christos return false;
1295 1.8 christos }
1296 1.8 christos
1297 1.8 christos return true;
1298 1.8 christos }
1299