Home | History | Annotate | Line # | Download | only in gdb
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