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