X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdictionary.c;h=da44946a98c09762863b794fa97e8cdd07743a28;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=3802000763710e6f2c26e4924d9b02edf1277619;hpb=de4f826b0f698dc2858f6eda71f2613a89579c50;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dictionary.c b/gdb/dictionary.c index 3802000763..da44946a98 100644 --- a/gdb/dictionary.c +++ b/gdb/dictionary.c @@ -1,6 +1,6 @@ /* Routines for name->symbol lookups in GDB. - Copyright 2003 Free Software Foundation, Inc. + Copyright (C) 2003-2020 Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -9,25 +9,26 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at - your option) any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" +#include #include "gdb_obstack.h" #include "symtab.h" #include "buildsym.h" -#include "gdb_assert.h" #include "dictionary.h" +#include "safe-ctype.h" +#include +#include "language.h" /* This file implements dictionaries, which are tables that associate symbols to names. They are represented by an opaque type 'struct @@ -83,9 +84,7 @@ * Define a function dict_ that looks up in the dict_vector and calls the appropriate function. Add a declaration for - dict_ to dictionary.h. - -*/ + dict_ to dictionary.h. */ /* An enum representing the various implementations of dictionaries. Used only for debugging. */ @@ -99,7 +98,7 @@ enum dict_type /* Symbols are stored in a fixed-size array. */ DICT_LINEAR, /* Symbols are stored in an expandable array. */ - DICT_LINEAR_EXPANDABLE, + DICT_LINEAR_EXPANDABLE }; /* The virtual function table. */ @@ -118,11 +117,11 @@ struct dict_vector struct dict_iterator *iterator); struct symbol *(*iterator_next) (struct dict_iterator *iterator); /* Functions to iterate over symbols with a given name. */ - struct symbol *(*iter_name_first) (const struct dictionary *dict, - const char *name, + struct symbol *(*iter_match_first) (const struct dictionary *dict, + const lookup_name_info &name, + struct dict_iterator *iterator); + struct symbol *(*iter_match_next) (const lookup_name_info &name, struct dict_iterator *iterator); - struct symbol *(*iter_name_next) (const char *name, - struct dict_iterator *iterator); /* A size function, for maint print symtabs. */ int (*size) (const struct dictionary *dict); }; @@ -167,6 +166,7 @@ struct dictionary_linear_expandable struct dictionary { + const struct language_defn *language; const struct dict_vector *vector; union { @@ -181,6 +181,7 @@ struct dictionary /* Accessor macros. */ #define DICT_VECTOR(d) (d)->vector +#define DICT_LANGUAGE(d) (d)->language /* These can be used for DICT_HASHED_EXPANDABLE, too. */ @@ -238,12 +239,12 @@ static struct symbol *iterator_first_hashed (const struct dictionary *dict, static struct symbol *iterator_next_hashed (struct dict_iterator *iterator); -static struct symbol *iter_name_first_hashed (const struct dictionary *dict, - const char *name, +static struct symbol *iter_match_first_hashed (const struct dictionary *dict, + const lookup_name_info &name, struct dict_iterator *iterator); -static struct symbol *iter_name_next_hashed (const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_next_hashed (const lookup_name_info &name, + struct dict_iterator *iterator); /* Functions only for DICT_HASHED. */ @@ -266,12 +267,12 @@ static struct symbol *iterator_first_linear (const struct dictionary *dict, static struct symbol *iterator_next_linear (struct dict_iterator *iterator); -static struct symbol *iter_name_first_linear (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_first_linear (const struct dictionary *dict, + const lookup_name_info &name, + struct dict_iterator *iterator); -static struct symbol *iter_name_next_linear (const char *name, - struct dict_iterator *iterator); +static struct symbol *iter_match_next_linear (const lookup_name_info &name, + struct dict_iterator *iterator); static int size_linear (const struct dictionary *dict); @@ -289,10 +290,10 @@ static const struct dict_vector dict_hashed_vector = DICT_HASHED, /* type */ free_obstack, /* free */ add_symbol_nonexpandable, /* add_symbol */ - iterator_first_hashed, /* iteractor_first */ + iterator_first_hashed, /* iterator_first */ iterator_next_hashed, /* iterator_next */ - iter_name_first_hashed, /* iter_name_first */ - iter_name_next_hashed, /* iter_name_next */ + iter_match_first_hashed, /* iter_name_first */ + iter_match_next_hashed, /* iter_name_next */ size_hashed, /* size */ }; @@ -301,10 +302,10 @@ static const struct dict_vector dict_hashed_expandable_vector = DICT_HASHED_EXPANDABLE, /* type */ free_hashed_expandable, /* free */ add_symbol_hashed_expandable, /* add_symbol */ - iterator_first_hashed, /* iteractor_first */ + iterator_first_hashed, /* iterator_first */ iterator_next_hashed, /* iterator_next */ - iter_name_first_hashed, /* iter_name_first */ - iter_name_next_hashed, /* iter_name_next */ + iter_match_first_hashed, /* iter_name_first */ + iter_match_next_hashed, /* iter_name_next */ size_hashed_expandable, /* size */ }; @@ -313,10 +314,10 @@ static const struct dict_vector dict_linear_vector = DICT_LINEAR, /* type */ free_obstack, /* free */ add_symbol_nonexpandable, /* add_symbol */ - iterator_first_linear, /* iteractor_first */ + iterator_first_linear, /* iterator_first */ iterator_next_linear, /* iterator_next */ - iter_name_first_linear, /* iter_name_first */ - iter_name_next_linear, /* iter_name_next */ + iter_match_first_linear, /* iter_name_first */ + iter_match_next_linear, /* iter_name_next */ size_linear, /* size */ }; @@ -325,10 +326,10 @@ static const struct dict_vector dict_linear_expandable_vector = DICT_LINEAR_EXPANDABLE, /* type */ free_linear_expandable, /* free */ add_symbol_linear_expandable, /* add_symbol */ - iterator_first_linear, /* iteractor_first */ + iterator_first_linear, /* iterator_first */ iterator_next_linear, /* iterator_next */ - iter_name_first_linear, /* iter_name_first */ - iter_name_next_linear, /* iter_name_next */ + iter_match_first_linear, /* iter_name_first */ + iter_match_next_linear, /* iter_name_next */ size_linear, /* size */ }; @@ -344,132 +345,88 @@ static void expand_hashtable (struct dictionary *dict); /* The creation functions. */ -/* Create a dictionary implemented via a fixed-size hashtable. All - memory it uses is allocated on OBSTACK; the environment is - initialized from SYMBOL_LIST. */ +/* Create a hashed dictionary of a given language. */ -struct dictionary * +static struct dictionary * dict_create_hashed (struct obstack *obstack, - const struct pending *symbol_list) + enum language language, + const std::vector &symbol_list) { - struct dictionary *retval; - int nsyms = 0, nbuckets, i; - struct symbol **buckets; - const struct pending *list_counter; - - retval = obstack_alloc (obstack, sizeof (struct dictionary)); + /* Allocate the dictionary. */ + struct dictionary *retval = XOBNEW (obstack, struct dictionary); DICT_VECTOR (retval) = &dict_hashed_vector; + DICT_LANGUAGE (retval) = language_def (language); - /* Calculate the number of symbols, and allocate space for them. */ - for (list_counter = symbol_list; - list_counter != NULL; - list_counter = list_counter->next) - { - nsyms += list_counter->nsyms; - } - nbuckets = DICT_HASHTABLE_SIZE (nsyms); + /* Allocate space for symbols. */ + int nsyms = symbol_list.size (); + int nbuckets = DICT_HASHTABLE_SIZE (nsyms); DICT_HASHED_NBUCKETS (retval) = nbuckets; - buckets = obstack_alloc (obstack, nbuckets * sizeof (struct symbol *)); + struct symbol **buckets = XOBNEWVEC (obstack, struct symbol *, nbuckets); memset (buckets, 0, nbuckets * sizeof (struct symbol *)); DICT_HASHED_BUCKETS (retval) = buckets; /* Now fill the buckets. */ - for (list_counter = symbol_list; - list_counter != NULL; - list_counter = list_counter->next) - { - for (i = list_counter->nsyms - 1; i >= 0; --i) - { - insert_symbol_hashed (retval, list_counter->symbol[i]); - } - } + for (const auto &sym : symbol_list) + insert_symbol_hashed (retval, sym); return retval; } -/* Create a dictionary implemented via a hashtable that grows as - necessary. The dictionary is initially empty; to add symbols to - it, call dict_add_symbol(). Call dict_free() when you're done with - it. */ +/* Create an expandable hashed dictionary of a given language. */ -extern struct dictionary * -dict_create_hashed_expandable (void) +static struct dictionary * +dict_create_hashed_expandable (enum language language) { - struct dictionary *retval; + struct dictionary *retval = XNEW (struct dictionary); - retval = xmalloc (sizeof (struct dictionary)); DICT_VECTOR (retval) = &dict_hashed_expandable_vector; + DICT_LANGUAGE (retval) = language_def (language); DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY; - DICT_HASHED_BUCKETS (retval) = xcalloc (DICT_EXPANDABLE_INITIAL_CAPACITY, - sizeof (struct symbol *)); + DICT_HASHED_BUCKETS (retval) = XCNEWVEC (struct symbol *, + DICT_EXPANDABLE_INITIAL_CAPACITY); DICT_HASHED_EXPANDABLE_NSYMS (retval) = 0; return retval; } -/* Create a dictionary implemented via a fixed-size array. All memory - it uses is allocated on OBSTACK; the environment is initialized - from the SYMBOL_LIST. The symbols are ordered in the same order - that they're found in SYMBOL_LIST. */ +/* Create a linear dictionary of a given language. */ -struct dictionary * +static struct dictionary * dict_create_linear (struct obstack *obstack, - const struct pending *symbol_list) + enum language language, + const std::vector &symbol_list) { - struct dictionary *retval; - int nsyms = 0, i, j; - struct symbol **syms; - const struct pending *list_counter; - - retval = obstack_alloc (obstack, sizeof (struct dictionary)); + struct dictionary *retval = XOBNEW (obstack, struct dictionary); DICT_VECTOR (retval) = &dict_linear_vector; + DICT_LANGUAGE (retval) = language_def (language); - /* Calculate the number of symbols, and allocate space for them. */ - for (list_counter = symbol_list; - list_counter != NULL; - list_counter = list_counter->next) - { - nsyms += list_counter->nsyms; - } + /* Allocate space for symbols. */ + int nsyms = symbol_list.size (); DICT_LINEAR_NSYMS (retval) = nsyms; - syms = obstack_alloc (obstack, nsyms * sizeof (struct symbol *)); + struct symbol **syms = XOBNEWVEC (obstack, struct symbol *, nsyms); DICT_LINEAR_SYMS (retval) = syms; - /* Now fill in the symbols. Start filling in from the back, so as - to preserve the original order of the symbols. */ - for (list_counter = symbol_list, j = nsyms - 1; - list_counter != NULL; - list_counter = list_counter->next) - { - for (i = list_counter->nsyms - 1; - i >= 0; - --i, --j) - { - syms[j] = list_counter->symbol[i]; - } - } + /* Now fill in the symbols. */ + int idx = nsyms - 1; + for (const auto &sym : symbol_list) + syms[idx--] = sym; return retval; } -/* Create a dictionary implemented via an array that grows as - necessary. The dictionary is initially empty; to add symbols to - it, call dict_add_symbol(). Call dict_free() when you're done with - it. */ +/* Create an expandable linear dictionary of a given language. */ -struct dictionary * -dict_create_linear_expandable (void) +static struct dictionary * +dict_create_linear_expandable (enum language language) { - struct dictionary *retval; + struct dictionary *retval = XNEW (struct dictionary); - retval = xmalloc (sizeof (struct dictionary)); DICT_VECTOR (retval) = &dict_linear_expandable_vector; + DICT_LANGUAGE (retval) = language_def (language); DICT_LINEAR_NSYMS (retval) = 0; - DICT_LINEAR_EXPANDABLE_CAPACITY (retval) - = DICT_EXPANDABLE_INITIAL_CAPACITY; + DICT_LINEAR_EXPANDABLE_CAPACITY (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY; DICT_LINEAR_SYMS (retval) - = xmalloc (DICT_LINEAR_EXPANDABLE_CAPACITY (retval) - * sizeof (struct symbol *)); + = XNEWVEC (struct symbol *, DICT_LINEAR_EXPANDABLE_CAPACITY (retval)); return retval; } @@ -479,7 +436,7 @@ dict_create_linear_expandable (void) /* Free the memory used by a dictionary that's not on an obstack. (If any.) */ -void +static void dict_free (struct dictionary *dict) { (DICT_VECTOR (dict))->free (dict); @@ -487,16 +444,28 @@ dict_free (struct dictionary *dict) /* Add SYM to DICT. DICT had better be expandable. */ -void +static void dict_add_symbol (struct dictionary *dict, struct symbol *sym) { (DICT_VECTOR (dict))->add_symbol (dict, sym); } +/* Utility to add a list of symbols to a dictionary. + DICT must be an expandable dictionary. */ + +static void +dict_add_pending (struct dictionary *dict, + const std::vector &symbol_list) +{ + /* Preserve ordering by reversing the list. */ + for (auto sym = symbol_list.rbegin (); sym != symbol_list.rend (); ++sym) + dict_add_symbol (dict, *sym); +} + /* Initialize ITERATOR to point at the first symbol in DICT, and return that first symbol, or NULL if DICT is empty. */ -struct symbol * +static struct symbol * dict_iterator_first (const struct dictionary *dict, struct dict_iterator *iterator) { @@ -506,29 +475,30 @@ dict_iterator_first (const struct dictionary *dict, /* Advance ITERATOR, and return the next symbol, or NULL if there are no more symbols. */ -struct symbol * +static struct symbol * dict_iterator_next (struct dict_iterator *iterator) { return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator))) ->iterator_next (iterator); } -struct symbol * -dict_iter_name_first (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator) +static struct symbol * +dict_iter_match_first (const struct dictionary *dict, + const lookup_name_info &name, + struct dict_iterator *iterator) { - return (DICT_VECTOR (dict))->iter_name_first (dict, name, iterator); + return (DICT_VECTOR (dict))->iter_match_first (dict, name, iterator); } -struct symbol * -dict_iter_name_next (const char *name, struct dict_iterator *iterator) +static struct symbol * +dict_iter_match_next (const lookup_name_info &name, + struct dict_iterator *iterator) { return (DICT_VECTOR (DICT_ITERATOR_DICT (iterator))) - ->iter_name_next (name, iterator); + ->iter_match_next (name, iterator); } -int +static int dict_size (const struct dictionary *dict) { return (DICT_VECTOR (dict))->size (dict); @@ -538,16 +508,6 @@ dict_size (const struct dictionary *dict) implemented generically by means of the vtable. Typically, they're rarely used. */ -/* Test to see if DICT is empty. */ - -int -dict_empty (struct dictionary *dict) -{ - struct dict_iterator iter; - - return (dict_iterator_first (dict, &iter) == NULL); -} - /* The functions implementing the dictionary interface. */ @@ -563,7 +523,7 @@ static void add_symbol_nonexpandable (struct dictionary *dict, struct symbol *sym) { internal_error (__FILE__, __LINE__, - "dict_add_symbol: non-expandable dictionary"); + _("dict_add_symbol: non-expandable dictionary")); } /* Functions for DICT_HASHED and DICT_HASHED_EXPANDABLE. */ @@ -580,7 +540,6 @@ iterator_first_hashed (const struct dictionary *dict, static struct symbol * iterator_next_hashed (struct dict_iterator *iterator) { - const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); struct symbol *next; next = DICT_ITERATOR_CURRENT (iterator)->hash_next; @@ -617,12 +576,15 @@ iterator_hashed_advance (struct dict_iterator *iterator) } static struct symbol * -iter_name_first_hashed (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator) +iter_match_first_hashed (const struct dictionary *dict, + const lookup_name_info &name, + struct dict_iterator *iterator) { - unsigned int hash_index - = msymbol_hash_iw (name) % DICT_HASHED_NBUCKETS (dict); + const language_defn *lang = DICT_LANGUAGE (dict); + unsigned int hash_index = (name.search_name_hash (lang->la_language) + % DICT_HASHED_NBUCKETS (dict)); + symbol_name_matcher_ftype *matches_name + = get_symbol_name_matcher (lang, name); struct symbol *sym; DICT_ITERATOR_DICT (iterator) = dict; @@ -635,12 +597,9 @@ iter_name_first_hashed (const struct dictionary *dict, sym != NULL; sym = sym->hash_next) { - /* Warning: the order of arguments to strcmp_iw matters! */ - if (strcmp_iw (SYMBOL_NATURAL_NAME (sym), name) == 0) - { - break; - } - + /* Warning: the order of arguments to compare matters! */ + if (matches_name (sym->search_name (), name, NULL)) + break; } DICT_ITERATOR_CURRENT (iterator) = sym; @@ -648,15 +607,19 @@ iter_name_first_hashed (const struct dictionary *dict, } static struct symbol * -iter_name_next_hashed (const char *name, struct dict_iterator *iterator) +iter_match_next_hashed (const lookup_name_info &name, + struct dict_iterator *iterator) { + const language_defn *lang = DICT_LANGUAGE (DICT_ITERATOR_DICT (iterator)); + symbol_name_matcher_ftype *matches_name + = get_symbol_name_matcher (lang, name); struct symbol *next; for (next = DICT_ITERATOR_CURRENT (iterator)->hash_next; next != NULL; next = next->hash_next) { - if (strcmp_iw (SYMBOL_NATURAL_NAME (next), name) == 0) + if (matches_name (next->search_name (), name, NULL)) break; } @@ -672,10 +635,15 @@ insert_symbol_hashed (struct dictionary *dict, struct symbol *sym) { unsigned int hash_index; + unsigned int hash; struct symbol **buckets = DICT_HASHED_BUCKETS (dict); - hash_index = (msymbol_hash_iw (SYMBOL_NATURAL_NAME (sym)) - % DICT_HASHED_NBUCKETS (dict)); + /* We don't want to insert a symbol into a dictionary of a different + language. The two may not use the same hashing algorithm. */ + gdb_assert (sym->language () == DICT_LANGUAGE (dict)->la_language); + + hash = search_name_hash (sym->language (), sym->search_name ()); + hash_index = hash % DICT_HASHED_NBUCKETS (dict); sym->hash_next = buckets[hash_index]; buckets[hash_index] = sym; } @@ -719,33 +687,107 @@ expand_hashtable (struct dictionary *dict) { int old_nbuckets = DICT_HASHED_NBUCKETS (dict); struct symbol **old_buckets = DICT_HASHED_BUCKETS (dict); - int new_nbuckets = 2*old_nbuckets + 1; - struct symbol **new_buckets = xcalloc (new_nbuckets, - sizeof (struct symbol *)); + int new_nbuckets = 2 * old_nbuckets + 1; + struct symbol **new_buckets = XCNEWVEC (struct symbol *, new_nbuckets); int i; DICT_HASHED_NBUCKETS (dict) = new_nbuckets; DICT_HASHED_BUCKETS (dict) = new_buckets; - for (i = 0; i < old_nbuckets; ++i) { - struct symbol *sym, *next_sym; - - sym = old_buckets[i]; - if (sym != NULL) { - for (next_sym = sym->hash_next; - next_sym != NULL; - next_sym = sym->hash_next) { - insert_symbol_hashed (dict, sym); - sym = next_sym; - } + for (i = 0; i < old_nbuckets; ++i) + { + struct symbol *sym, *next_sym; - insert_symbol_hashed (dict, sym); + sym = old_buckets[i]; + if (sym != NULL) + { + for (next_sym = sym->hash_next; + next_sym != NULL; + next_sym = sym->hash_next) + { + insert_symbol_hashed (dict, sym); + sym = next_sym; + } + + insert_symbol_hashed (dict, sym); + } } - } xfree (old_buckets); } +/* See dictionary.h. */ + +unsigned int +language_defn::search_name_hash (const char *string0) const +{ + /* The Ada-encoded version of a name P1.P2...Pn has either the form + P1__P2__...Pn or _ada_P1__P2__...Pn (where the Pi + are lower-cased identifiers). The (which can be empty) + encodes additional information about the denoted entity. This + routine hashes such names to msymbol_hash_iw(Pn). It actually + does this for a superset of both valid Pi and of , but + in other cases it simply returns msymbol_hash_iw(STRING0). */ + + const char *string; + unsigned int hash; + + string = string0; + if (*string == '_') + { + if (startswith (string, "_ada_")) + string += 5; + else + return msymbol_hash_iw (string0); + } + + hash = 0; + while (*string) + { + switch (*string) + { + case '$': + case '.': + case 'X': + if (string0 == string) + return msymbol_hash_iw (string0); + else + return hash; + case ' ': + case '(': + return msymbol_hash_iw (string0); + case '_': + if (string[1] == '_' && string != string0) + { + int c = string[2]; + + if ((c < 'a' || c > 'z') && c != 'O') + return hash; + hash = 0; + string += 2; + continue; + } + break; + case 'T': + /* Ignore "TKB" suffixes. + + These are used by Ada for subprograms implementing a task body. + For instance for a task T inside package Pck, the name of the + subprogram implementing T's body is `pck__tTKB'. We need to + ignore the "TKB" suffix because searches for this task body + subprogram are going to be performed using `pck__t' (the encoded + version of the natural name `pck.t'). */ + if (strcmp (string, "TKB") == 0) + return hash; + break; + } + + hash = SYMBOL_HASH_NEXT (hash, *string); + string += 1; + } + return hash; +} + /* Functions for DICT_LINEAR and DICT_LINEAR_EXPANDABLE. */ static struct symbol * @@ -769,27 +811,33 @@ iterator_next_linear (struct dict_iterator *iterator) } static struct symbol * -iter_name_first_linear (const struct dictionary *dict, - const char *name, - struct dict_iterator *iterator) +iter_match_first_linear (const struct dictionary *dict, + const lookup_name_info &name, + struct dict_iterator *iterator) { DICT_ITERATOR_DICT (iterator) = dict; DICT_ITERATOR_INDEX (iterator) = -1; - return iter_name_next_linear (name, iterator); + return iter_match_next_linear (name, iterator); } static struct symbol * -iter_name_next_linear (const char *name, struct dict_iterator *iterator) +iter_match_next_linear (const lookup_name_info &name, + struct dict_iterator *iterator) { const struct dictionary *dict = DICT_ITERATOR_DICT (iterator); + const language_defn *lang = DICT_LANGUAGE (dict); + symbol_name_matcher_ftype *matches_name + = get_symbol_name_matcher (lang, name); + int i, nsyms = DICT_LINEAR_NSYMS (dict); struct symbol *sym, *retval = NULL; for (i = DICT_ITERATOR_INDEX (iterator) + 1; i < nsyms; ++i) { sym = DICT_LINEAR_SYM (dict, i); - if (strcmp_iw (SYMBOL_NATURAL_NAME (sym), name) == 0) + + if (matches_name (sym->search_name (), name, NULL)) { retval = sym; break; @@ -824,13 +872,404 @@ add_symbol_linear_expandable (struct dictionary *dict, int nsyms = ++DICT_LINEAR_NSYMS (dict); /* Do we have enough room? If not, grow it. */ - if (nsyms > DICT_LINEAR_EXPANDABLE_CAPACITY (dict)) { - DICT_LINEAR_EXPANDABLE_CAPACITY (dict) *= 2; - DICT_LINEAR_SYMS (dict) - = xrealloc (DICT_LINEAR_SYMS (dict), - DICT_LINEAR_EXPANDABLE_CAPACITY (dict) - * sizeof (struct symbol *)); - } + if (nsyms > DICT_LINEAR_EXPANDABLE_CAPACITY (dict)) + { + DICT_LINEAR_EXPANDABLE_CAPACITY (dict) *= 2; + DICT_LINEAR_SYMS (dict) + = XRESIZEVEC (struct symbol *, DICT_LINEAR_SYMS (dict), + DICT_LINEAR_EXPANDABLE_CAPACITY (dict)); + } DICT_LINEAR_SYM (dict, nsyms - 1) = sym; } + +/* Multi-language dictionary support. */ + +/* The structure describing a multi-language dictionary. */ + +struct multidictionary +{ + /* An array of dictionaries, one per language. All dictionaries + must be of the same type. This should be free'd for expandable + dictionary types. */ + struct dictionary **dictionaries; + + /* The number of language dictionaries currently allocated. + Only used for expandable dictionaries. */ + unsigned short n_allocated_dictionaries; +}; + +/* A hasher for enum language. Injecting this into std is a convenience + when using unordered_map with C++11. */ + +namespace std +{ + template<> struct hash + { + typedef enum language argument_type; + typedef std::size_t result_type; + + result_type operator() (const argument_type &l) const noexcept + { + return static_cast (l); + } + }; +} /* namespace std */ + +/* A helper function to collate symbols on the pending list by language. */ + +static std::unordered_map> +collate_pending_symbols_by_language (const struct pending *symbol_list) +{ + std::unordered_map> nsyms; + + for (const pending *list_counter = symbol_list; + list_counter != nullptr; list_counter = list_counter->next) + { + for (int i = list_counter->nsyms - 1; i >= 0; --i) + { + enum language language = list_counter->symbol[i]->language (); + nsyms[language].push_back (list_counter->symbol[i]); + } + } + + return nsyms; +} + +/* See dictionary.h. */ + +struct multidictionary * +mdict_create_hashed (struct obstack *obstack, + const struct pending *symbol_list) +{ + struct multidictionary *retval + = XOBNEW (obstack, struct multidictionary); + std::unordered_map> nsyms + = collate_pending_symbols_by_language (symbol_list); + + /* Loop over all languages and create/populate dictionaries. */ + retval->dictionaries + = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); + retval->n_allocated_dictionaries = nsyms.size (); + + int idx = 0; + for (const auto &pair : nsyms) + { + enum language language = pair.first; + std::vector symlist = pair.second; + + retval->dictionaries[idx++] + = dict_create_hashed (obstack, language, symlist); + } + + return retval; +} + +/* See dictionary.h. */ + +struct multidictionary * +mdict_create_hashed_expandable (enum language language) +{ + struct multidictionary *retval = XNEW (struct multidictionary); + + /* We have no symbol list to populate, but we create an empty + dictionary of the requested language to populate later. */ + retval->n_allocated_dictionaries = 1; + retval->dictionaries = XNEW (struct dictionary *); + retval->dictionaries[0] = dict_create_hashed_expandable (language); + + return retval; +} + +/* See dictionary.h. */ + +struct multidictionary * +mdict_create_linear (struct obstack *obstack, + const struct pending *symbol_list) +{ + struct multidictionary *retval + = XOBNEW (obstack, struct multidictionary); + std::unordered_map> nsyms + = collate_pending_symbols_by_language (symbol_list); + + /* Loop over all languages and create/populate dictionaries. */ + retval->dictionaries + = XOBNEWVEC (obstack, struct dictionary *, nsyms.size ()); + retval->n_allocated_dictionaries = nsyms.size (); + + int idx = 0; + for (const auto &pair : nsyms) + { + enum language language = pair.first; + std::vector symlist = pair.second; + + retval->dictionaries[idx++] + = dict_create_linear (obstack, language, symlist); + } + + return retval; +} + +/* See dictionary.h. */ + +struct multidictionary * +mdict_create_linear_expandable (enum language language) +{ + struct multidictionary *retval = XNEW (struct multidictionary); + + /* We have no symbol list to populate, but we create an empty + dictionary to populate later. */ + retval->n_allocated_dictionaries = 1; + retval->dictionaries = XNEW (struct dictionary *); + retval->dictionaries[0] = dict_create_linear_expandable (language); + + return retval; +} + +/* See dictionary.h. */ + +void +mdict_free (struct multidictionary *mdict) +{ + /* Grab the type of dictionary being used. */ + enum dict_type type = mdict->dictionaries[0]->vector->type; + + /* Loop over all dictionaries and free them. */ + for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) + dict_free (mdict->dictionaries[idx]); + + /* Free the dictionary list, if needed. */ + switch (type) + { + case DICT_HASHED: + case DICT_LINEAR: + /* Memory was allocated on an obstack when created. */ + break; + + case DICT_HASHED_EXPANDABLE: + case DICT_LINEAR_EXPANDABLE: + xfree (mdict->dictionaries); + break; + } +} + +/* Helper function to find the dictionary associated with LANGUAGE + or NULL if there is no dictionary of that language. */ + +static struct dictionary * +find_language_dictionary (const struct multidictionary *mdict, + enum language language) +{ + for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) + { + if (DICT_LANGUAGE (mdict->dictionaries[idx])->la_language == language) + return mdict->dictionaries[idx]; + } + + return nullptr; +} + +/* Create a new language dictionary for LANGUAGE and add it to the + multidictionary MDICT's list of dictionaries. If MDICT is not + based on expandable dictionaries, this function throws an + internal error. */ + +static struct dictionary * +create_new_language_dictionary (struct multidictionary *mdict, + enum language language) +{ + struct dictionary *retval = nullptr; + + /* We use the first dictionary entry to decide what create function + to call. Not optimal but sufficient. */ + gdb_assert (mdict->dictionaries[0] != nullptr); + switch (mdict->dictionaries[0]->vector->type) + { + case DICT_HASHED: + case DICT_LINEAR: + internal_error (__FILE__, __LINE__, + _("create_new_language_dictionary: attempted to expand " + "non-expandable multidictionary")); + + case DICT_HASHED_EXPANDABLE: + retval = dict_create_hashed_expandable (language); + break; + + case DICT_LINEAR_EXPANDABLE: + retval = dict_create_linear_expandable (language); + break; + } + + /* Grow the dictionary vector and save the new dictionary. */ + mdict->dictionaries + = (struct dictionary **) xrealloc (mdict->dictionaries, + (++mdict->n_allocated_dictionaries + * sizeof (struct dictionary *))); + mdict->dictionaries[mdict->n_allocated_dictionaries - 1] = retval; + + return retval; +} + +/* See dictionary.h. */ + +void +mdict_add_symbol (struct multidictionary *mdict, struct symbol *sym) +{ + struct dictionary *dict + = find_language_dictionary (mdict, sym->language ()); + + if (dict == nullptr) + { + /* SYM is of a new language that we haven't previously seen. + Create a new dictionary for it. */ + dict = create_new_language_dictionary (mdict, sym->language ()); + } + + dict_add_symbol (dict, sym); +} + +/* See dictionary.h. */ + +void +mdict_add_pending (struct multidictionary *mdict, + const struct pending *symbol_list) +{ + std::unordered_map> nsyms + = collate_pending_symbols_by_language (symbol_list); + + for (const auto &pair : nsyms) + { + enum language language = pair.first; + std::vector symlist = pair.second; + struct dictionary *dict = find_language_dictionary (mdict, language); + + if (dict == nullptr) + { + /* The language was not previously seen. Create a new dictionary + for it. */ + dict = create_new_language_dictionary (mdict, language); + } + + dict_add_pending (dict, symlist); + } +} + +/* See dictionary.h. */ + +struct symbol * +mdict_iterator_first (const multidictionary *mdict, + struct mdict_iterator *miterator) +{ + miterator->mdict = mdict; + miterator->current_idx = 0; + + for (unsigned short idx = miterator->current_idx; + idx < mdict->n_allocated_dictionaries; ++idx) + { + struct symbol *result + = dict_iterator_first (mdict->dictionaries[idx], &miterator->iterator); + + if (result != nullptr) + { + miterator->current_idx = idx; + return result; + } + } + + return nullptr; +} + +/* See dictionary.h. */ + +struct symbol * +mdict_iterator_next (struct mdict_iterator *miterator) +{ + struct symbol *result = dict_iterator_next (&miterator->iterator); + + if (result != nullptr) + return result; + + /* The current dictionary had no matches -- move to the next + dictionary, if any. */ + for (unsigned short idx = ++miterator->current_idx; + idx < miterator->mdict->n_allocated_dictionaries; ++idx) + { + result + = dict_iterator_first (miterator->mdict->dictionaries[idx], + &miterator->iterator); + if (result != nullptr) + { + miterator->current_idx = idx; + return result; + } + } + + return nullptr; +} + +/* See dictionary.h. */ + +struct symbol * +mdict_iter_match_first (const struct multidictionary *mdict, + const lookup_name_info &name, + struct mdict_iterator *miterator) +{ + miterator->mdict = mdict; + miterator->current_idx = 0; + + for (unsigned short idx = miterator->current_idx; + idx < mdict->n_allocated_dictionaries; ++idx) + { + struct symbol *result + = dict_iter_match_first (mdict->dictionaries[idx], name, + &miterator->iterator); + + if (result != nullptr) + return result; + } + + return nullptr; +} + +/* See dictionary.h. */ + +struct symbol * +mdict_iter_match_next (const lookup_name_info &name, + struct mdict_iterator *miterator) +{ + /* Search the current dictionary. */ + struct symbol *result = dict_iter_match_next (name, &miterator->iterator); + + if (result != nullptr) + return result; + + /* The current dictionary had no matches -- move to the next + dictionary, if any. */ + for (unsigned short idx = ++miterator->current_idx; + idx < miterator->mdict->n_allocated_dictionaries; ++idx) + { + result + = dict_iter_match_first (miterator->mdict->dictionaries[idx], + name, &miterator->iterator); + if (result != nullptr) + { + miterator->current_idx = idx; + return result; + } + } + + return nullptr; +} + +/* See dictionary.h. */ + +int +mdict_size (const struct multidictionary *mdict) +{ + int size = 0; + + for (unsigned short idx = 0; idx < mdict->n_allocated_dictionaries; ++idx) + size += dict_size (mdict->dictionaries[idx]); + + return size; +}