1 1.1 christos /* Routines for name->symbol lookups in GDB. 2 1.1 christos 3 1.11 christos Copyright (C) 2003-2024 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 <ctype.h> 24 1.10 christos #include "gdbsupport/gdb_obstack.h" 25 1.1 christos #include "symtab.h" 26 1.1 christos #include "buildsym.h" 27 1.1 christos #include "dictionary.h" 28 1.11 christos #include "gdbsupport/gdb-safe-ctype.h" 29 1.8 christos #include <unordered_map> 30 1.9 christos #include "language.h" 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.9 christos static 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.9 christos static 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.9 christos static 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.9 christos static 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 511 1.1 christos /* The functions implementing the dictionary interface. */ 512 1.1 christos 513 1.1 christos /* Generic functions, where appropriate. */ 514 1.1 christos 515 1.1 christos static void 516 1.1 christos free_obstack (struct dictionary *dict) 517 1.1 christos { 518 1.1 christos /* Do nothing! */ 519 1.1 christos } 520 1.1 christos 521 1.1 christos static void 522 1.1 christos add_symbol_nonexpandable (struct dictionary *dict, struct symbol *sym) 523 1.1 christos { 524 1.10 christos internal_error (_("dict_add_symbol: non-expandable dictionary")); 525 1.1 christos } 526 1.1 christos 527 1.1 christos /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE. */ 528 1.1 christos 529 1.1 christos static struct symbol * 530 1.1 christos iterator_first_hashed (const struct dictionary *dict, 531 1.1 christos struct dict_iterator *iterator) 532 1.1 christos { 533 1.1 christos DICT_ITERATOR_DICT (iterator) = dict; 534 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1; 535 1.1 christos return iterator_hashed_advance (iterator); 536 1.1 christos } 537 1.1 christos 538 1.1 christos static struct symbol * 539 1.1 christos iterator_next_hashed (struct dict_iterator *iterator) 540 1.1 christos { 541 1.1 christos struct symbol *next; 542 1.1 christos 543 1.1 christos next = DICT_ITERATOR_CURRENT (iterator)->hash_next; 544 1.1 christos 545 1.1 christos if (next == NULL) 546 1.1 christos return iterator_hashed_advance (iterator); 547 1.1 christos else 548 1.1 christos { 549 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next; 550 1.1 christos return next; 551 1.1 christos } 552 1.1 christos } 553 1.1 christos 554 1.1 christos static struct symbol * 555 1.1 christos iterator_hashed_advance (struct dict_iterator *iterator) 556 1.1 christos { 557 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); 558 1.1 christos int nbuckets = DICT_HASHED_NBUCKETS (dict); 559 1.1 christos int i; 560 1.1 christos 561 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nbuckets; ++i) 562 1.1 christos { 563 1.1 christos struct symbol *sym = DICT_HASHED_BUCKET (dict, i); 564 1.1 christos 565 1.1 christos if (sym != NULL) 566 1.1 christos { 567 1.1 christos DICT_ITERATOR_INDEX (iterator) = i; 568 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym; 569 1.1 christos return sym; 570 1.1 christos } 571 1.1 christos } 572 1.1 christos 573 1.1 christos return NULL; 574 1.1 christos } 575 1.1 christos 576 1.1 christos static struct symbol * 577 1.8 christos iter_match_first_hashed (const struct dictionary *dict, 578 1.8 christos const lookup_name_info &name, 579 1.1 christos struct dict_iterator *iterator) 580 1.1 christos { 581 1.8 christos const language_defn *lang = DICT_LANGUAGE (dict); 582 1.8 christos unsigned int hash_index = (name.search_name_hash (lang->la_language) 583 1.8 christos % DICT_HASHED_NBUCKETS (dict)); 584 1.8 christos symbol_name_matcher_ftype *matches_name 585 1.9 christos = lang->get_symbol_name_matcher (name); 586 1.1 christos struct symbol *sym; 587 1.1 christos 588 1.1 christos DICT_ITERATOR_DICT (iterator) = dict; 589 1.1 christos 590 1.1 christos /* Loop through the symbols in the given bucket, breaking when SYM 591 1.1 christos first matches. If SYM never matches, it will be set to NULL; 592 1.1 christos either way, we have the right return value. */ 593 1.1 christos 594 1.1 christos for (sym = DICT_HASHED_BUCKET (dict, hash_index); 595 1.1 christos sym != NULL; 596 1.1 christos sym = sym->hash_next) 597 1.1 christos { 598 1.1 christos /* Warning: the order of arguments to compare matters! */ 599 1.9 christos if (matches_name (sym->search_name (), name, NULL)) 600 1.8 christos break; 601 1.1 christos } 602 1.1 christos 603 1.1 christos DICT_ITERATOR_CURRENT (iterator) = sym; 604 1.1 christos return sym; 605 1.1 christos } 606 1.1 christos 607 1.1 christos static struct symbol * 608 1.8 christos iter_match_next_hashed (const lookup_name_info &name, 609 1.1 christos struct dict_iterator *iterator) 610 1.1 christos { 611 1.8 christos const language_defn *lang = DICT_LANGUAGE (DICT_ITERATOR_DICT (iterator)); 612 1.8 christos symbol_name_matcher_ftype *matches_name 613 1.9 christos = lang->get_symbol_name_matcher (name); 614 1.1 christos struct symbol *next; 615 1.1 christos 616 1.1 christos for (next = DICT_ITERATOR_CURRENT (iterator)->hash_next; 617 1.1 christos next != NULL; 618 1.1 christos next = next->hash_next) 619 1.1 christos { 620 1.9 christos if (matches_name (next->search_name (), name, NULL)) 621 1.1 christos break; 622 1.1 christos } 623 1.1 christos 624 1.1 christos DICT_ITERATOR_CURRENT (iterator) = next; 625 1.1 christos 626 1.1 christos return next; 627 1.1 christos } 628 1.1 christos 629 1.1 christos /* Insert SYM into DICT. */ 630 1.1 christos 631 1.1 christos static void 632 1.1 christos insert_symbol_hashed (struct dictionary *dict, 633 1.1 christos struct symbol *sym) 634 1.1 christos { 635 1.1 christos unsigned int hash_index; 636 1.8 christos unsigned int hash; 637 1.1 christos struct symbol **buckets = DICT_HASHED_BUCKETS (dict); 638 1.1 christos 639 1.8 christos /* We don't want to insert a symbol into a dictionary of a different 640 1.8 christos language. The two may not use the same hashing algorithm. */ 641 1.9 christos gdb_assert (sym->language () == DICT_LANGUAGE (dict)->la_language); 642 1.8 christos 643 1.9 christos hash = search_name_hash (sym->language (), sym->search_name ()); 644 1.8 christos hash_index = hash % DICT_HASHED_NBUCKETS (dict); 645 1.1 christos sym->hash_next = buckets[hash_index]; 646 1.1 christos buckets[hash_index] = sym; 647 1.1 christos } 648 1.1 christos 649 1.1 christos static int 650 1.1 christos size_hashed (const struct dictionary *dict) 651 1.1 christos { 652 1.11 christos int nbuckets = DICT_HASHED_NBUCKETS (dict); 653 1.11 christos int total = 0; 654 1.11 christos 655 1.11 christos for (int i = 0; i < nbuckets; ++i) 656 1.11 christos { 657 1.11 christos for (struct symbol *sym = DICT_HASHED_BUCKET (dict, i); 658 1.11 christos sym != nullptr; 659 1.11 christos sym = sym->hash_next) 660 1.11 christos total++; 661 1.11 christos } 662 1.11 christos 663 1.11 christos return total; 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.9 christos language_defn::search_name_hash (const char *string0) const 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.10 christos if (c == 'B' && string[3] == '_') 774 1.10 christos { 775 1.10 christos for (string += 4; ISDIGIT (*string); ++string) 776 1.10 christos ; 777 1.10 christos continue; 778 1.10 christos } 779 1.10 christos 780 1.1 christos if ((c < 'a' || c > 'z') && c != 'O') 781 1.1 christos return hash; 782 1.1 christos hash = 0; 783 1.1 christos string += 2; 784 1.8 christos continue; 785 1.1 christos } 786 1.8 christos break; 787 1.8 christos case 'T': 788 1.8 christos /* Ignore "TKB" suffixes. 789 1.8 christos 790 1.8 christos These are used by Ada for subprograms implementing a task body. 791 1.8 christos For instance for a task T inside package Pck, the name of the 792 1.8 christos subprogram implementing T's body is `pck__tTKB'. We need to 793 1.8 christos ignore the "TKB" suffix because searches for this task body 794 1.8 christos subprogram are going to be performed using `pck__t' (the encoded 795 1.8 christos version of the natural name `pck.t'). */ 796 1.8 christos if (strcmp (string, "TKB") == 0) 797 1.8 christos return hash; 798 1.1 christos break; 799 1.1 christos } 800 1.8 christos 801 1.8 christos hash = SYMBOL_HASH_NEXT (hash, *string); 802 1.8 christos string += 1; 803 1.1 christos } 804 1.1 christos return hash; 805 1.1 christos } 806 1.1 christos 807 1.1 christos /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE. */ 808 1.1 christos 809 1.1 christos static struct symbol * 810 1.1 christos iterator_first_linear (const struct dictionary *dict, 811 1.1 christos struct dict_iterator *iterator) 812 1.1 christos { 813 1.1 christos DICT_ITERATOR_DICT (iterator) = dict; 814 1.1 christos DICT_ITERATOR_INDEX (iterator) = 0; 815 1.1 christos return DICT_LINEAR_NSYMS (dict) ? DICT_LINEAR_SYM (dict, 0) : NULL; 816 1.1 christos } 817 1.1 christos 818 1.1 christos static struct symbol * 819 1.1 christos iterator_next_linear (struct dict_iterator *iterator) 820 1.1 christos { 821 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); 822 1.1 christos 823 1.1 christos if (++DICT_ITERATOR_INDEX (iterator) >= DICT_LINEAR_NSYMS (dict)) 824 1.1 christos return NULL; 825 1.1 christos else 826 1.1 christos return DICT_LINEAR_SYM (dict, DICT_ITERATOR_INDEX (iterator)); 827 1.1 christos } 828 1.1 christos 829 1.1 christos static struct symbol * 830 1.1 christos iter_match_first_linear (const struct dictionary *dict, 831 1.8 christos const lookup_name_info &name, 832 1.1 christos struct dict_iterator *iterator) 833 1.1 christos { 834 1.1 christos DICT_ITERATOR_DICT (iterator) = dict; 835 1.1 christos DICT_ITERATOR_INDEX (iterator) = -1; 836 1.1 christos 837 1.8 christos return iter_match_next_linear (name, iterator); 838 1.1 christos } 839 1.1 christos 840 1.1 christos static struct symbol * 841 1.8 christos iter_match_next_linear (const lookup_name_info &name, 842 1.1 christos struct dict_iterator *iterator) 843 1.1 christos { 844 1.1 christos const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); 845 1.8 christos const language_defn *lang = DICT_LANGUAGE (dict); 846 1.8 christos symbol_name_matcher_ftype *matches_name 847 1.9 christos = lang->get_symbol_name_matcher (name); 848 1.8 christos 849 1.1 christos int i, nsyms = DICT_LINEAR_NSYMS (dict); 850 1.1 christos struct symbol *sym, *retval = NULL; 851 1.1 christos 852 1.1 christos for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nsyms; ++i) 853 1.1 christos { 854 1.1 christos sym = DICT_LINEAR_SYM (dict, i); 855 1.8 christos 856 1.9 christos if (matches_name (sym->search_name (), name, NULL)) 857 1.1 christos { 858 1.1 christos retval = sym; 859 1.1 christos break; 860 1.1 christos } 861 1.1 christos } 862 1.1 christos 863 1.1 christos DICT_ITERATOR_INDEX (iterator) = i; 864 1.1 christos 865 1.1 christos return retval; 866 1.1 christos } 867 1.1 christos 868 1.1 christos static int 869 1.1 christos size_linear (const struct dictionary *dict) 870 1.1 christos { 871 1.1 christos return DICT_LINEAR_NSYMS (dict); 872 1.1 christos } 873 1.1 christos 874 1.1 christos /* Functions only for DICT_LINEAR_EXPANDABLE. */ 875 1.1 christos 876 1.1 christos static void 877 1.1 christos free_linear_expandable (struct dictionary *dict) 878 1.1 christos { 879 1.1 christos xfree (DICT_LINEAR_SYMS (dict)); 880 1.1 christos xfree (dict); 881 1.1 christos } 882 1.1 christos 883 1.1 christos 884 1.1 christos static void 885 1.1 christos add_symbol_linear_expandable (struct dictionary *dict, 886 1.1 christos struct symbol *sym) 887 1.1 christos { 888 1.1 christos int nsyms = ++DICT_LINEAR_NSYMS (dict); 889 1.1 christos 890 1.1 christos /* Do we have enough room? If not, grow it. */ 891 1.1 christos if (nsyms > DICT_LINEAR_EXPANDABLE_CAPACITY (dict)) 892 1.1 christos { 893 1.1 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict) *= 2; 894 1.1 christos DICT_LINEAR_SYMS (dict) 895 1.6 christos = XRESIZEVEC (struct symbol *, DICT_LINEAR_SYMS (dict), 896 1.6 christos DICT_LINEAR_EXPANDABLE_CAPACITY (dict)); 897 1.1 christos } 898 1.1 christos 899 1.1 christos DICT_LINEAR_SYM (dict, nsyms - 1) = sym; 900 1.1 christos } 901 1.8 christos 902 1.8 christos /* Multi-language dictionary support. */ 903 1.8 christos 904 1.8 christos /* The structure describing a multi-language dictionary. */ 905 1.8 christos 906 1.8 christos struct multidictionary 907 1.8 christos { 908 1.8 christos /* An array of dictionaries, one per language. All dictionaries 909 1.8 christos must be of the same type. This should be free'd for expandable 910 1.8 christos dictionary types. */ 911 1.8 christos struct dictionary **dictionaries; 912 1.8 christos 913 1.8 christos /* The number of language dictionaries currently allocated. 914 1.8 christos Only used for expandable dictionaries. */ 915 1.8 christos unsigned short n_allocated_dictionaries; 916 1.8 christos }; 917 1.8 christos 918 1.8 christos /* A hasher for enum language. Injecting this into std is a convenience 919 1.8 christos when using unordered_map with C++11. */ 920 1.8 christos 921 1.8 christos namespace std 922 1.8 christos { 923 1.8 christos template<> struct hash<enum language> 924 1.8 christos { 925 1.8 christos typedef enum language argument_type; 926 1.8 christos typedef std::size_t result_type; 927 1.8 christos 928 1.8 christos result_type operator() (const argument_type &l) const noexcept 929 1.8 christos { 930 1.8 christos return static_cast<result_type> (l); 931 1.8 christos } 932 1.8 christos }; 933 1.8 christos } /* namespace std */ 934 1.8 christos 935 1.8 christos /* A helper function to collate symbols on the pending list by language. */ 936 1.8 christos 937 1.8 christos static std::unordered_map<enum language, std::vector<symbol *>> 938 1.8 christos collate_pending_symbols_by_language (const struct pending *symbol_list) 939 1.8 christos { 940 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms; 941 1.8 christos 942 1.9 christos for (const pending *list_counter = symbol_list; 943 1.8 christos list_counter != nullptr; list_counter = list_counter->next) 944 1.8 christos { 945 1.8 christos for (int i = list_counter->nsyms - 1; i >= 0; --i) 946 1.8 christos { 947 1.9 christos enum language language = list_counter->symbol[i]->language (); 948 1.8 christos nsyms[language].push_back (list_counter->symbol[i]); 949 1.8 christos } 950 1.8 christos } 951 1.8 christos 952 1.8 christos return nsyms; 953 1.8 christos } 954 1.8 christos 955 1.8 christos /* See dictionary.h. */ 956 1.8 christos 957 1.8 christos struct multidictionary * 958 1.8 christos mdict_create_hashed (struct obstack *obstack, 959 1.8 christos const struct pending *symbol_list) 960 1.8 christos { 961 1.8 christos struct multidictionary *retval 962 1.8 christos = XOBNEW (obstack, struct multidictionary); 963 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms 964 1.8 christos = collate_pending_symbols_by_language (symbol_list); 965 1.8 christos 966 1.8 christos /* Loop over all languages and create/populate dictionaries. */ 967 1.8 christos retval->dictionaries 968 1.8 christos = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); 969 1.8 christos retval->n_allocated_dictionaries = nsyms.size (); 970 1.8 christos 971 1.8 christos int idx = 0; 972 1.8 christos for (const auto &pair : nsyms) 973 1.8 christos { 974 1.8 christos enum language language = pair.first; 975 1.8 christos std::vector<symbol *> symlist = pair.second; 976 1.8 christos 977 1.8 christos retval->dictionaries[idx++] 978 1.8 christos = dict_create_hashed (obstack, language, symlist); 979 1.8 christos } 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_hashed_expandable (enum language language) 988 1.8 christos { 989 1.8 christos struct multidictionary *retval = XNEW (struct multidictionary); 990 1.8 christos 991 1.8 christos /* We have no symbol list to populate, but we create an empty 992 1.8 christos dictionary of the requested language to populate later. */ 993 1.8 christos retval->n_allocated_dictionaries = 1; 994 1.8 christos retval->dictionaries = XNEW (struct dictionary *); 995 1.8 christos retval->dictionaries[0] = dict_create_hashed_expandable (language); 996 1.8 christos 997 1.8 christos return retval; 998 1.8 christos } 999 1.8 christos 1000 1.8 christos /* See dictionary.h. */ 1001 1.8 christos 1002 1.8 christos struct multidictionary * 1003 1.8 christos mdict_create_linear (struct obstack *obstack, 1004 1.8 christos const struct pending *symbol_list) 1005 1.8 christos { 1006 1.8 christos struct multidictionary *retval 1007 1.8 christos = XOBNEW (obstack, struct multidictionary); 1008 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms 1009 1.8 christos = collate_pending_symbols_by_language (symbol_list); 1010 1.8 christos 1011 1.8 christos /* Loop over all languages and create/populate dictionaries. */ 1012 1.8 christos retval->dictionaries 1013 1.8 christos = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); 1014 1.8 christos retval->n_allocated_dictionaries = nsyms.size (); 1015 1.8 christos 1016 1.8 christos int idx = 0; 1017 1.8 christos for (const auto &pair : nsyms) 1018 1.8 christos { 1019 1.8 christos enum language language = pair.first; 1020 1.8 christos std::vector<symbol *> symlist = pair.second; 1021 1.8 christos 1022 1.8 christos retval->dictionaries[idx++] 1023 1.8 christos = dict_create_linear (obstack, language, symlist); 1024 1.8 christos } 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 struct multidictionary * 1032 1.8 christos mdict_create_linear_expandable (enum language language) 1033 1.8 christos { 1034 1.8 christos struct multidictionary *retval = XNEW (struct multidictionary); 1035 1.8 christos 1036 1.8 christos /* We have no symbol list to populate, but we create an empty 1037 1.8 christos dictionary to populate later. */ 1038 1.8 christos retval->n_allocated_dictionaries = 1; 1039 1.8 christos retval->dictionaries = XNEW (struct dictionary *); 1040 1.8 christos retval->dictionaries[0] = dict_create_linear_expandable (language); 1041 1.8 christos 1042 1.8 christos return retval; 1043 1.8 christos } 1044 1.8 christos 1045 1.8 christos /* See dictionary.h. */ 1046 1.8 christos 1047 1.8 christos void 1048 1.8 christos mdict_free (struct multidictionary *mdict) 1049 1.8 christos { 1050 1.8 christos /* Grab the type of dictionary being used. */ 1051 1.8 christos enum dict_type type = mdict->dictionaries[0]->vector->type; 1052 1.8 christos 1053 1.8 christos /* Loop over all dictionaries and free them. */ 1054 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) 1055 1.8 christos dict_free (mdict->dictionaries[idx]); 1056 1.8 christos 1057 1.8 christos /* Free the dictionary list, if needed. */ 1058 1.8 christos switch (type) 1059 1.8 christos { 1060 1.8 christos case DICT_HASHED: 1061 1.8 christos case DICT_LINEAR: 1062 1.8 christos /* Memory was allocated on an obstack when created. */ 1063 1.8 christos break; 1064 1.8 christos 1065 1.8 christos case DICT_HASHED_EXPANDABLE: 1066 1.8 christos case DICT_LINEAR_EXPANDABLE: 1067 1.8 christos xfree (mdict->dictionaries); 1068 1.8 christos break; 1069 1.8 christos } 1070 1.8 christos } 1071 1.8 christos 1072 1.8 christos /* Helper function to find the dictionary associated with LANGUAGE 1073 1.8 christos or NULL if there is no dictionary of that language. */ 1074 1.8 christos 1075 1.8 christos static struct dictionary * 1076 1.8 christos find_language_dictionary (const struct multidictionary *mdict, 1077 1.8 christos enum language language) 1078 1.8 christos { 1079 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) 1080 1.8 christos { 1081 1.8 christos if (DICT_LANGUAGE (mdict->dictionaries[idx])->la_language == language) 1082 1.8 christos return mdict->dictionaries[idx]; 1083 1.8 christos } 1084 1.8 christos 1085 1.8 christos return nullptr; 1086 1.8 christos } 1087 1.8 christos 1088 1.8 christos /* Create a new language dictionary for LANGUAGE and add it to the 1089 1.8 christos multidictionary MDICT's list of dictionaries. If MDICT is not 1090 1.8 christos based on expandable dictionaries, this function throws an 1091 1.8 christos internal error. */ 1092 1.8 christos 1093 1.8 christos static struct dictionary * 1094 1.8 christos create_new_language_dictionary (struct multidictionary *mdict, 1095 1.8 christos enum language language) 1096 1.8 christos { 1097 1.8 christos struct dictionary *retval = nullptr; 1098 1.8 christos 1099 1.8 christos /* We use the first dictionary entry to decide what create function 1100 1.8 christos to call. Not optimal but sufficient. */ 1101 1.8 christos gdb_assert (mdict->dictionaries[0] != nullptr); 1102 1.8 christos switch (mdict->dictionaries[0]->vector->type) 1103 1.8 christos { 1104 1.8 christos case DICT_HASHED: 1105 1.8 christos case DICT_LINEAR: 1106 1.10 christos internal_error (_("create_new_language_dictionary: attempted to expand " 1107 1.8 christos "non-expandable multidictionary")); 1108 1.8 christos 1109 1.8 christos case DICT_HASHED_EXPANDABLE: 1110 1.8 christos retval = dict_create_hashed_expandable (language); 1111 1.8 christos break; 1112 1.8 christos 1113 1.8 christos case DICT_LINEAR_EXPANDABLE: 1114 1.8 christos retval = dict_create_linear_expandable (language); 1115 1.8 christos break; 1116 1.8 christos } 1117 1.8 christos 1118 1.8 christos /* Grow the dictionary vector and save the new dictionary. */ 1119 1.8 christos mdict->dictionaries 1120 1.8 christos = (struct dictionary **) xrealloc (mdict->dictionaries, 1121 1.8 christos (++mdict->n_allocated_dictionaries 1122 1.8 christos * sizeof (struct dictionary *))); 1123 1.8 christos mdict->dictionaries[mdict->n_allocated_dictionaries - 1] = retval; 1124 1.8 christos 1125 1.8 christos return retval; 1126 1.8 christos } 1127 1.8 christos 1128 1.8 christos /* See dictionary.h. */ 1129 1.8 christos 1130 1.8 christos void 1131 1.8 christos mdict_add_symbol (struct multidictionary *mdict, struct symbol *sym) 1132 1.8 christos { 1133 1.8 christos struct dictionary *dict 1134 1.9 christos = find_language_dictionary (mdict, sym->language ()); 1135 1.8 christos 1136 1.8 christos if (dict == nullptr) 1137 1.8 christos { 1138 1.8 christos /* SYM is of a new language that we haven't previously seen. 1139 1.8 christos Create a new dictionary for it. */ 1140 1.9 christos dict = create_new_language_dictionary (mdict, sym->language ()); 1141 1.8 christos } 1142 1.8 christos 1143 1.8 christos dict_add_symbol (dict, sym); 1144 1.8 christos } 1145 1.8 christos 1146 1.8 christos /* See dictionary.h. */ 1147 1.8 christos 1148 1.8 christos void 1149 1.8 christos mdict_add_pending (struct multidictionary *mdict, 1150 1.8 christos const struct pending *symbol_list) 1151 1.8 christos { 1152 1.8 christos std::unordered_map<enum language, std::vector<symbol *>> nsyms 1153 1.8 christos = collate_pending_symbols_by_language (symbol_list); 1154 1.8 christos 1155 1.8 christos for (const auto &pair : nsyms) 1156 1.8 christos { 1157 1.8 christos enum language language = pair.first; 1158 1.8 christos std::vector<symbol *> symlist = pair.second; 1159 1.8 christos struct dictionary *dict = find_language_dictionary (mdict, language); 1160 1.8 christos 1161 1.8 christos if (dict == nullptr) 1162 1.8 christos { 1163 1.8 christos /* The language was not previously seen. Create a new dictionary 1164 1.8 christos for it. */ 1165 1.8 christos dict = create_new_language_dictionary (mdict, language); 1166 1.8 christos } 1167 1.8 christos 1168 1.8 christos dict_add_pending (dict, symlist); 1169 1.8 christos } 1170 1.8 christos } 1171 1.8 christos 1172 1.8 christos /* See dictionary.h. */ 1173 1.8 christos 1174 1.8 christos struct symbol * 1175 1.8 christos mdict_iterator_first (const multidictionary *mdict, 1176 1.8 christos struct mdict_iterator *miterator) 1177 1.8 christos { 1178 1.8 christos miterator->mdict = mdict; 1179 1.8 christos miterator->current_idx = 0; 1180 1.8 christos 1181 1.8 christos for (unsigned short idx = miterator->current_idx; 1182 1.8 christos idx < mdict->n_allocated_dictionaries; ++idx) 1183 1.8 christos { 1184 1.8 christos struct symbol *result 1185 1.8 christos = dict_iterator_first (mdict->dictionaries[idx], &miterator->iterator); 1186 1.8 christos 1187 1.8 christos if (result != nullptr) 1188 1.8 christos { 1189 1.8 christos miterator->current_idx = idx; 1190 1.8 christos return result; 1191 1.8 christos } 1192 1.8 christos } 1193 1.8 christos 1194 1.8 christos return nullptr; 1195 1.8 christos } 1196 1.8 christos 1197 1.8 christos /* See dictionary.h. */ 1198 1.8 christos 1199 1.8 christos struct symbol * 1200 1.8 christos mdict_iterator_next (struct mdict_iterator *miterator) 1201 1.8 christos { 1202 1.8 christos struct symbol *result = dict_iterator_next (&miterator->iterator); 1203 1.8 christos 1204 1.8 christos if (result != nullptr) 1205 1.8 christos return result; 1206 1.8 christos 1207 1.8 christos /* The current dictionary had no matches -- move to the next 1208 1.8 christos dictionary, if any. */ 1209 1.8 christos for (unsigned short idx = ++miterator->current_idx; 1210 1.8 christos idx < miterator->mdict->n_allocated_dictionaries; ++idx) 1211 1.8 christos { 1212 1.8 christos result 1213 1.8 christos = dict_iterator_first (miterator->mdict->dictionaries[idx], 1214 1.8 christos &miterator->iterator); 1215 1.8 christos if (result != nullptr) 1216 1.8 christos { 1217 1.8 christos miterator->current_idx = idx; 1218 1.8 christos return result; 1219 1.8 christos } 1220 1.8 christos } 1221 1.8 christos 1222 1.8 christos return nullptr; 1223 1.8 christos } 1224 1.8 christos 1225 1.8 christos /* See dictionary.h. */ 1226 1.8 christos 1227 1.8 christos struct symbol * 1228 1.8 christos mdict_iter_match_first (const struct multidictionary *mdict, 1229 1.8 christos const lookup_name_info &name, 1230 1.8 christos struct mdict_iterator *miterator) 1231 1.8 christos { 1232 1.8 christos miterator->mdict = mdict; 1233 1.8 christos miterator->current_idx = 0; 1234 1.8 christos 1235 1.8 christos for (unsigned short idx = miterator->current_idx; 1236 1.8 christos idx < mdict->n_allocated_dictionaries; ++idx) 1237 1.8 christos { 1238 1.8 christos struct symbol *result 1239 1.8 christos = dict_iter_match_first (mdict->dictionaries[idx], name, 1240 1.8 christos &miterator->iterator); 1241 1.8 christos 1242 1.8 christos if (result != nullptr) 1243 1.8 christos return result; 1244 1.8 christos } 1245 1.8 christos 1246 1.8 christos return nullptr; 1247 1.8 christos } 1248 1.8 christos 1249 1.8 christos /* See dictionary.h. */ 1250 1.8 christos 1251 1.8 christos struct symbol * 1252 1.8 christos mdict_iter_match_next (const lookup_name_info &name, 1253 1.8 christos struct mdict_iterator *miterator) 1254 1.8 christos { 1255 1.8 christos /* Search the current dictionary. */ 1256 1.8 christos struct symbol *result = dict_iter_match_next (name, &miterator->iterator); 1257 1.8 christos 1258 1.8 christos if (result != nullptr) 1259 1.8 christos return result; 1260 1.8 christos 1261 1.8 christos /* The current dictionary had no matches -- move to the next 1262 1.8 christos dictionary, if any. */ 1263 1.8 christos for (unsigned short idx = ++miterator->current_idx; 1264 1.8 christos idx < miterator->mdict->n_allocated_dictionaries; ++idx) 1265 1.8 christos { 1266 1.8 christos result 1267 1.8 christos = dict_iter_match_first (miterator->mdict->dictionaries[idx], 1268 1.8 christos name, &miterator->iterator); 1269 1.8 christos if (result != nullptr) 1270 1.8 christos { 1271 1.8 christos miterator->current_idx = idx; 1272 1.8 christos return result; 1273 1.8 christos } 1274 1.8 christos } 1275 1.8 christos 1276 1.8 christos return nullptr; 1277 1.8 christos } 1278 1.8 christos 1279 1.8 christos /* See dictionary.h. */ 1280 1.8 christos 1281 1.8 christos int 1282 1.8 christos mdict_size (const struct multidictionary *mdict) 1283 1.8 christos { 1284 1.8 christos int size = 0; 1285 1.8 christos 1286 1.8 christos for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) 1287 1.8 christos size += dict_size (mdict->dictionaries[idx]); 1288 1.8 christos 1289 1.8 christos return size; 1290 1.8 christos } 1291