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