* c-exp.y (block, variable, name_not_typename, lex_one_token,
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 5eb7ced18709f732fedbec272bcad3421ea2ab64..97f114fc34f331c46eb609ac15820161ca69a490 100644 (file)
@@ -33,7 +33,6 @@
 #include "language.h"
 #include "demangle.h"
 #include "inferior.h"
-#include "linespec.h"
 #include "source.h"
 #include "filenames.h"         /* for FILENAME_CMP */
 #include "objc-lang.h"
@@ -63,6 +62,7 @@
 #include "macroscope.h"
 
 #include "psymtab.h"
+#include "parser-defs.h"
 
 /* Prototypes for local functions */
 
@@ -76,15 +76,13 @@ static void variables_info (char *, int);
 
 static void sources_info (char *, int);
 
-static void output_source_filename (const char *, int *);
-
 static int find_line_common (struct linetable *, int, int *, int);
 
 static struct symbol *lookup_symbol_aux (const char *name,
                                         const struct block *block,
                                         const domain_enum domain,
                                         enum language language,
-                                        int *is_a_field_of_this);
+                                        struct field_of_this_result *is_a_field_of_this);
 
 static
 struct symbol *lookup_symbol_aux_local (const char *name,
@@ -95,8 +93,7 @@ struct symbol *lookup_symbol_aux_local (const char *name,
 static
 struct symbol *lookup_symbol_aux_symtabs (int block_index,
                                          const char *name,
-                                         const domain_enum domain,
-                                         struct objfile *exclude_objfile);
+                                         const domain_enum domain);
 
 static
 struct symbol *lookup_symbol_aux_quick (struct objfile *objfile,
@@ -110,6 +107,9 @@ void _initialize_symtab (void);
 
 /* */
 
+/* When non-zero, print debugging messages related to symtab creation.  */
+int symtab_create_debug = 0;
+
 /* Non-zero if a file may be known by two different basenames.
    This is the uncommon case, and significantly slows down gdb.
    Default set to "off" to not slow down the common case.  */
@@ -243,7 +243,7 @@ iterate_over_some_symtabs (const char *name,
 
     if (real_path != NULL)
       {
-        char *fullname = symtab_to_fullname (s);
+        const char *fullname = symtab_to_fullname (s);
 
         if (fullname != NULL)
           {
@@ -403,19 +403,20 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
 
   if (len == 0)
     {
-      sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+      xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
     }
   else if (physname[0] == 't' || physname[0] == 'Q')
     {
       /* The physname for template and qualified methods already includes
          the class name.  */
-      sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+      xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
       newname = NULL;
       len = 0;
     }
   else
     {
-      sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+      xsnprintf (buf, sizeof (buf), "__%s%s%d", const_prefix,
+                volatile_prefix, len);
     }
   mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
                      + strlen (buf) + len + strlen (physname) + 1);
@@ -1224,7 +1225,7 @@ demangle_for_lookup (const char *name, enum language lang,
 struct symbol *
 lookup_symbol_in_language (const char *name, const struct block *block,
                           const domain_enum domain, enum language lang,
-                          int *is_a_field_of_this)
+                          struct field_of_this_result *is_a_field_of_this)
 {
   const char *modified_name;
   struct symbol *returnval;
@@ -1242,7 +1243,8 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 
 struct symbol *
 lookup_symbol (const char *name, const struct block *block,
-              domain_enum domain, int *is_a_field_of_this)
+              domain_enum domain,
+              struct field_of_this_result *is_a_field_of_this)
 {
   return lookup_symbol_in_language (name, block, domain,
                                    current_language->la_language,
@@ -1277,24 +1279,68 @@ lookup_language_this (const struct language_defn *lang,
   return NULL;
 }
 
+/* Given TYPE, a structure/union,
+   return 1 if the component named NAME from the ultimate target
+   structure/union is defined, otherwise, return 0.  */
+
+static int
+check_field (struct type *type, const char *name,
+            struct field_of_this_result *is_a_field_of_this)
+{
+  int i;
+
+  /* The type may be a stub.  */
+  CHECK_TYPEDEF (type);
+
+  for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+    {
+      const char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+      if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
+       {
+         is_a_field_of_this->type = type;
+         is_a_field_of_this->field = &TYPE_FIELD (type, i);
+         return 1;
+       }
+    }
+
+  /* C++: If it was not found as a data field, then try to return it
+     as a pointer to a method.  */
+
+  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+    {
+      if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0)
+       {
+         is_a_field_of_this->type = type;
+         is_a_field_of_this->fn_field = &TYPE_FN_FIELDLIST (type, i);
+         return 1;
+       }
+    }
+
+  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+    if (check_field (TYPE_BASECLASS (type, i), name, is_a_field_of_this))
+      return 1;
+
+  return 0;
+}
+
 /* Behave like lookup_symbol except that NAME is the natural name
    (e.g., demangled name) of the symbol that we're looking for.  */
 
 static struct symbol *
 lookup_symbol_aux (const char *name, const struct block *block,
                   const domain_enum domain, enum language language,
-                  int *is_a_field_of_this)
+                  struct field_of_this_result *is_a_field_of_this)
 {
   struct symbol *sym;
   const struct language_defn *langdef;
 
   /* Make sure we do something sensible with is_a_field_of_this, since
      the callers that set this parameter to some non-null value will
-     certainly use it later and expect it to be either 0 or 1.
-     If we don't set it, the contents of is_a_field_of_this are
-     undefined.  */
+     certainly use it later.  If we don't set it, the contents of
+     is_a_field_of_this are undefined.  */
   if (is_a_field_of_this != NULL)
-    *is_a_field_of_this = 0;
+    memset (is_a_field_of_this, 0, sizeof (*is_a_field_of_this));
 
   /* Search specified block and its superiors.  Don't search
      STATIC_BLOCK or GLOBAL_BLOCK.  */
@@ -1328,11 +1374,8 @@ lookup_symbol_aux (const char *name, const struct block *block,
            error (_("Internal error: `%s' is not an aggregate"),
                   langdef->la_name_of_this);
 
-         if (check_field (t, name))
-           {
-             *is_a_field_of_this = 1;
-             return NULL;
-           }
+         if (check_field (t, name, is_a_field_of_this))
+           return NULL;
        }
     }
 
@@ -1360,7 +1403,7 @@ lookup_static_symbol_aux (const char *name, const domain_enum domain)
   struct objfile *objfile;
   struct symbol *sym;
 
-  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain, NULL);
+  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain);
   if (sym != NULL)
     return sym;
 
@@ -1478,17 +1521,17 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
        objfile = objfile_separate_debug_iterate (main_objfile, objfile))
     {
       /* Go through symtabs.  */
-      ALL_OBJFILE_SYMTABS (objfile, s)
-        {
-          bv = BLOCKVECTOR (s);
-          block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-          sym = lookup_block_symbol (block, name, domain);
-          if (sym)
-            {
-              block_found = block;
-              return fixup_symbol_section (sym, (struct objfile *)objfile);
-            }
-        }
+      ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+       {
+         bv = BLOCKVECTOR (s);
+         block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+         sym = lookup_block_symbol (block, name, domain);
+         if (sym)
+           {
+             block_found = block;
+             return fixup_symbol_section (sym, (struct objfile *)objfile);
+           }
+       }
 
       sym = lookup_symbol_aux_quick ((struct objfile *) objfile, GLOBAL_BLOCK,
                                     name, domain);
@@ -1517,48 +1560,83 @@ lookup_symbol_aux_objfile (struct objfile *objfile, int block_index,
     objfile->sf->qf->pre_expand_symtabs_matching (objfile, block_index,
                                                  name, domain);
 
-  ALL_OBJFILE_SYMTABS (objfile, s)
-    if (s->primary)
-      {
-       bv = BLOCKVECTOR (s);
-       block = BLOCKVECTOR_BLOCK (bv, block_index);
-       sym = lookup_block_symbol (block, name, domain);
-       if (sym)
-         {
-           block_found = block;
-           return fixup_symbol_section (sym, objfile);
-         }
-      }
+  ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+    {
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, block_index);
+      sym = lookup_block_symbol (block, name, domain);
+      if (sym)
+       {
+         block_found = block;
+         return fixup_symbol_section (sym, objfile);
+       }
+    }
 
   return NULL;
 }
 
 /* Same as lookup_symbol_aux_objfile, except that it searches all
-   objfiles except for EXCLUDE_OBJFILE.  Return the first match found.
-
-   If EXCLUDE_OBJFILE is NULL, then all objfiles are searched.  */
+   objfiles.  Return the first match found.  */
 
 static struct symbol *
 lookup_symbol_aux_symtabs (int block_index, const char *name,
-                          const domain_enum domain,
-                          struct objfile *exclude_objfile)
+                          const domain_enum domain)
 {
   struct symbol *sym;
   struct objfile *objfile;
 
   ALL_OBJFILES (objfile)
   {
-    if (objfile != exclude_objfile)
-      {
-       sym = lookup_symbol_aux_objfile (objfile, block_index, name, domain);
-       if (sym)
-         return sym;
-      }
+    sym = lookup_symbol_aux_objfile (objfile, block_index, name, domain);
+    if (sym)
+      return sym;
   }
 
   return NULL;
 }
 
+/* Wrapper around lookup_symbol_aux_objfile for search_symbols.
+   Look up LINKAGE_NAME in DOMAIN in the global and static blocks of OBJFILE
+   and all related objfiles.  */
+
+static struct symbol *
+lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
+                                           const char *linkage_name,
+                                           domain_enum domain)
+{
+  enum language lang = current_language->la_language;
+  const char *modified_name;
+  struct cleanup *cleanup = demangle_for_lookup (linkage_name, lang,
+                                                &modified_name);
+  struct objfile *main_objfile, *cur_objfile;
+
+  if (objfile->separate_debug_objfile_backlink)
+    main_objfile = objfile->separate_debug_objfile_backlink;
+  else
+    main_objfile = objfile;
+
+  for (cur_objfile = main_objfile;
+       cur_objfile;
+       cur_objfile = objfile_separate_debug_iterate (main_objfile, cur_objfile))
+    {
+      struct symbol *sym;
+
+      sym = lookup_symbol_aux_objfile (cur_objfile, GLOBAL_BLOCK,
+                                      modified_name, domain);
+      if (sym == NULL)
+       sym = lookup_symbol_aux_objfile (cur_objfile, STATIC_BLOCK,
+                                        modified_name, domain);
+      if (sym != NULL)
+       {
+         do_cleanups (cleanup);
+         return sym;
+       }
+    }
+
+  do_cleanups (cleanup);
+  return NULL;
+}
+
 /* A helper function for lookup_symbol_aux that interfaces with the
    "quick" symbol table functions.  */
 
@@ -1670,6 +1748,46 @@ lookup_symbol_static (const char *name,
     return NULL;
 }
 
+/* Private data to be used with lookup_symbol_global_iterator_cb.  */
+
+struct global_sym_lookup_data
+{
+  /* The name of the symbol we are searching for.  */
+  const char *name;
+
+  /* The domain to use for our search.  */
+  domain_enum domain;
+
+  /* The field where the callback should store the symbol if found.
+     It should be initialized to NULL before the search is started.  */
+  struct symbol *result;
+};
+
+/* A callback function for gdbarch_iterate_over_objfiles_in_search_order.
+   It searches by name for a symbol in the GLOBAL_BLOCK of the given
+   OBJFILE.  The arguments for the search are passed via CB_DATA,
+   which in reality is a pointer to struct global_sym_lookup_data.  */
+
+static int
+lookup_symbol_global_iterator_cb (struct objfile *objfile,
+                                 void *cb_data)
+{
+  struct global_sym_lookup_data *data =
+    (struct global_sym_lookup_data *) cb_data;
+
+  gdb_assert (data->result == NULL);
+
+  data->result = lookup_symbol_aux_objfile (objfile, GLOBAL_BLOCK,
+                                           data->name, data->domain);
+  if (data->result == NULL)
+    data->result = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK,
+                                           data->name, data->domain);
+
+  /* If we found a match, tell the iterator to stop.  Otherwise,
+     keep going.  */
+  return (data->result != NULL);
+}
+
 /* Lookup a symbol in all files' global blocks (searching psymtabs if
    necessary).  */
 
@@ -1679,49 +1797,24 @@ lookup_symbol_global (const char *name,
                      const domain_enum domain)
 {
   struct symbol *sym = NULL;
-  struct objfile *block_objfile = NULL;
   struct objfile *objfile = NULL;
+  struct global_sym_lookup_data lookup_data;
 
   /* Call library-specific lookup procedure.  */
-  block_objfile = lookup_objfile_from_block (block);
-  if (block_objfile != NULL)
-    sym = solib_global_lookup (block_objfile, name, domain);
+  objfile = lookup_objfile_from_block (block);
+  if (objfile != NULL)
+    sym = solib_global_lookup (objfile, name, domain);
   if (sym != NULL)
     return sym;
 
-  /* If BLOCK_OBJFILE is not NULL, then search this objfile first.
-     In case the global symbol is defined in multiple objfiles,
-     we have a better chance of finding the most relevant symbol.  */
-
-  if (block_objfile != NULL)
-    {
-      sym = lookup_symbol_aux_objfile (block_objfile, GLOBAL_BLOCK,
-                                      name, domain);
-      if (sym == NULL)
-       sym = lookup_symbol_aux_quick (block_objfile, GLOBAL_BLOCK,
-                                      name, domain);
-      if (sym != NULL)
-       return sym;
-    }
-
-  /* Symbol not found in the BLOCK_OBJFILE, so try all the other
-     objfiles, starting with symtabs first, and then partial symtabs.  */
+  memset (&lookup_data, 0, sizeof (lookup_data));
+  lookup_data.name = name;
+  lookup_data.domain = domain;
+  gdbarch_iterate_over_objfiles_in_search_order
+    (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (),
+     lookup_symbol_global_iterator_cb, &lookup_data, objfile);
 
-  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain, block_objfile);
-  if (sym != NULL)
-    return sym;
-
-  ALL_OBJFILES (objfile)
-  {
-    if (objfile != block_objfile)
-      {
-       sym = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK, name, domain);
-       if (sym)
-         return sym;
-      }
-  }
-
-  return NULL;
+  return lookup_data.result;
 }
 
 int
@@ -1829,17 +1922,16 @@ basic_lookup_transparent_type (const char *name)
                                                    GLOBAL_BLOCK,
                                                    name, STRUCT_DOMAIN);
 
-    ALL_OBJFILE_SYMTABS (objfile, s)
-      if (s->primary)
-       {
-         bv = BLOCKVECTOR (s);
-         block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-         sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
-         if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
-           {
-             return SYMBOL_TYPE (sym);
-           }
-       }
+    ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+      {
+       bv = BLOCKVECTOR (s);
+       block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+       sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
+       if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+         {
+           return SYMBOL_TYPE (sym);
+         }
+      }
   }
 
   ALL_OBJFILES (objfile)
@@ -1862,7 +1954,7 @@ basic_lookup_transparent_type (const char *name)
       objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK,
                                                    name, STRUCT_DOMAIN);
 
-    ALL_OBJFILE_SYMTABS (objfile, s)
+    ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
       {
        bv = BLOCKVECTOR (s);
        block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
@@ -2100,6 +2192,8 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
   if (best_s != NULL)
     return (best_s);
 
+  /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs).  */
+
   ALL_OBJFILES (objfile)
   {
     struct symtab *result;
@@ -2762,7 +2856,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
   struct block *b, *function_block;
   int force_skip, skip;
 
-  /* Do not change the SAL is PC was specified explicitly.  */
+  /* Do not change the SAL if PC was specified explicitly.  */
   if (sal->explicit_pc)
     return;
 
@@ -3055,57 +3149,93 @@ operator_chars (char *p, char **end)
 }
 \f
 
-/* If FILE is not already in the table of files, return zero;
+/* Cache to watch for file names already seen by filename_seen.  */
+
+struct filename_seen_cache
+{
+  /* Table of files seen so far.  */
+  htab_t tab;
+  /* Initial size of the table.  It automagically grows from here.  */
+#define INITIAL_FILENAME_SEEN_CACHE_SIZE 100
+};
+
+/* filename_seen_cache constructor.  */
+
+static struct filename_seen_cache *
+create_filename_seen_cache (void)
+{
+  struct filename_seen_cache *cache;
+
+  cache = XNEW (struct filename_seen_cache);
+  cache->tab = htab_create_alloc (INITIAL_FILENAME_SEEN_CACHE_SIZE,
+                                 filename_hash, filename_eq,
+                                 NULL, xcalloc, xfree);
+
+  return cache;
+}
+
+/* Empty the cache, but do not delete it.  */
+
+static void
+clear_filename_seen_cache (struct filename_seen_cache *cache)
+{
+  htab_empty (cache->tab);
+}
+
+/* filename_seen_cache destructor.
+   This takes a void * argument as it is generally used as a cleanup.  */
+
+static void
+delete_filename_seen_cache (void *ptr)
+{
+  struct filename_seen_cache *cache = ptr;
+
+  htab_delete (cache->tab);
+  xfree (cache);
+}
+
+/* If FILE is not already in the table of files in CACHE, return zero;
    otherwise return non-zero.  Optionally add FILE to the table if ADD
-   is non-zero.  If *FIRST is non-zero, forget the old table
-   contents.  */
+   is non-zero.
+
+   NOTE: We don't manage space for FILE, we assume FILE lives as long
+   as the caller needs.  */
 
 static int
-filename_seen (const char *file, int add, int *first)
+filename_seen (struct filename_seen_cache *cache, const char *file, int add)
 {
-  /* Table of files seen so far.  */
-  static const char **tab = NULL;
-  /* Allocated size of tab in elements.
-     Start with one 256-byte block (when using GNU malloc.c).
-     24 is the malloc overhead when range checking is in effect.  */
-  static int tab_alloc_size = (256 - 24) / sizeof (char *);
-  /* Current size of tab in elements.  */
-  static int tab_cur_size;
-  const char **p;
-
-  if (*first)
-    {
-      if (tab == NULL)
-       tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
-      tab_cur_size = 0;
-    }
+  void **slot;
 
   /* Is FILE in tab?  */
-  for (p = tab; p < tab + tab_cur_size; p++)
-    if (filename_cmp (*p, file) == 0)
-      return 1;
+  slot = htab_find_slot (cache->tab, file, add ? INSERT : NO_INSERT);
+  if (*slot != NULL)
+    return 1;
 
   /* No; maybe add it to tab.  */
   if (add)
-    {
-      if (tab_cur_size == tab_alloc_size)
-       {
-         tab_alloc_size *= 2;
-         tab = (const char **) xrealloc ((char *) tab,
-                                         tab_alloc_size * sizeof (*tab));
-       }
-      tab[tab_cur_size++] = file;
-    }
+    *slot = (char *) file;
 
   return 0;
 }
 
+/* Data structure to maintain printing state for output_source_filename.  */
+
+struct output_source_filename_data
+{
+  /* Cache of what we've seen so far.  */
+  struct filename_seen_cache *filename_seen_cache;
+
+  /* Flag of whether we're printing the first one.  */
+  int first;
+};
+
 /* Slave routine for sources_info.  Force line breaks at ,'s.
-   NAME is the name to print and *FIRST is nonzero if this is the first
-   name printed.  Set *FIRST to zero.  */
+   NAME is the name to print.
+   DATA contains the state for printing and watching for duplicates.  */
 
 static void
-output_source_filename (const char *name, int *first)
+output_source_filename (const char *name,
+                       struct output_source_filename_data *data)
 {
   /* Since a single source file can result in several partial symbol
      tables, we need to avoid printing it more than once.  Note: if
@@ -3117,20 +3247,16 @@ output_source_filename (const char *name, int *first)
      symtabs; it doesn't hurt to check.  */
 
   /* Was NAME already seen?  */
-  if (filename_seen (name, 1, first))
+  if (filename_seen (data->filename_seen_cache, name, 1))
     {
       /* Yes; don't print it again.  */
       return;
     }
+
   /* No; print it and reset *FIRST.  */
-  if (*first)
-    {
-      *first = 0;
-    }
-  else
-    {
-      printf_filtered (", ");
-    }
+  if (! data->first)
+    printf_filtered (", ");
+  data->first = 0;
 
   wrap_here ("");
   fputs_filtered (name, gdb_stdout);
@@ -3150,31 +3276,39 @@ sources_info (char *ignore, int from_tty)
 {
   struct symtab *s;
   struct objfile *objfile;
-  int first;
+  struct output_source_filename_data data;
+  struct cleanup *cleanups;
 
   if (!have_full_symbols () && !have_partial_symbols ())
     {
       error (_("No symbol table is loaded.  Use the \"file\" command."));
     }
 
+  data.filename_seen_cache = create_filename_seen_cache ();
+  cleanups = make_cleanup (delete_filename_seen_cache,
+                          data.filename_seen_cache);
+
   printf_filtered ("Source files for which symbols have been read in:\n\n");
 
-  first = 1;
+  data.first = 1;
   ALL_SYMTABS (objfile, s)
   {
     const char *fullname = symtab_to_fullname (s);
 
-    output_source_filename (fullname ? fullname : s->filename, &first);
+    output_source_filename (fullname ? fullname : s->filename, &data);
   }
   printf_filtered ("\n\n");
 
   printf_filtered ("Source files for which symbols "
                   "will be read in on demand:\n\n");
 
-  first = 1;
-  map_partial_symbol_filenames (output_partial_symbol_filename, &first,
+  clear_filename_seen_cache (data.filename_seen_cache);
+  data.first = 1;
+  map_partial_symbol_filenames (output_partial_symbol_filename, &data,
                                1 /*need_fullname*/);
   printf_filtered ("\n");
+
+  do_cleanups (cleanups);
 }
 
 static int
@@ -3443,10 +3577,14 @@ search_symbols (char *regexp, enum search_domain kind,
      The symbol will then be found during the scan of symtabs below.
 
      For functions, find_pc_symtab should succeed if we have debug info
-     for the function, for variables we have to call lookup_symbol
-     to determine if the variable has debug info.
+     for the function, for variables we have to call
+     lookup_symbol_in_objfile_from_linkage_name to determine if the variable
+     has debug info.
      If the lookup fails, set found_misc so that we will rescan to print
-     any matching symbols without debug info.  */
+     any matching symbols without debug info.
+     We only search the objfile the msymbol came from, we no longer search
+     all objfiles.  In large programs (1000s of shared libs) searching all
+     objfiles is not worth the pain.  */
 
   if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
     {
@@ -3454,6 +3592,9 @@ search_symbols (char *regexp, enum search_domain kind,
       {
         QUIT;
 
+       if (msymbol->created_by_gdb)
+         continue;
+
        if (MSYMBOL_TYPE (msymbol) == ourtype
            || MSYMBOL_TYPE (msymbol) == ourtype2
            || MSYMBOL_TYPE (msymbol) == ourtype3
@@ -3463,21 +3604,15 @@ search_symbols (char *regexp, enum search_domain kind,
                || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
                            NULL, 0) == 0)
              {
-               if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
-                 {
-                   /* FIXME: carlton/2003-02-04: Given that the
-                      semantics of lookup_symbol keeps on changing
-                      slightly, it would be a nice idea if we had a
-                      function lookup_symbol_minsym that found the
-                      symbol associated to a given minimal symbol (if
-                      any).  */
-                   if (kind == FUNCTIONS_DOMAIN
-                       || lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
-                                         (struct block *) NULL,
-                                         VAR_DOMAIN, 0)
-                       == NULL)
-                     found_misc = 1;
-                 }
+               /* Note: An important side-effect of these lookup functions
+                  is to expand the symbol table if msymbol is found, for the
+                  benefit of the next loop on ALL_PRIMARY_SYMTABS.  */
+               if (kind == FUNCTIONS_DOMAIN
+                   ? find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)) == NULL
+                   : (lookup_symbol_in_objfile_from_linkage_name
+                      (objfile, SYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
+                      == NULL))
+                 found_misc = 1;
              }
          }
       }
@@ -3554,12 +3689,15 @@ search_symbols (char *regexp, enum search_domain kind,
   /* If there are no eyes, avoid all contact.  I mean, if there are
      no debug symbols, then print directly from the msymbol_vector.  */
 
-  if (found_misc || kind != FUNCTIONS_DOMAIN)
+  if (found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
     {
       ALL_MSYMBOLS (objfile, msymbol)
       {
         QUIT;
 
+       if (msymbol->created_by_gdb)
+         continue;
+
        if (MSYMBOL_TYPE (msymbol) == ourtype
            || MSYMBOL_TYPE (msymbol) == ourtype2
            || MSYMBOL_TYPE (msymbol) == ourtype3
@@ -3569,14 +3707,14 @@ search_symbols (char *regexp, enum search_domain kind,
                || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
                            NULL, 0) == 0)
              {
-               /* Functions:  Look up by address.  */
-               if (kind != FUNCTIONS_DOMAIN ||
-                   (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
+               /* For functions we can do a quick check of whether the
+                  symbol might be found via find_pc_symtab.  */
+               if (kind != FUNCTIONS_DOMAIN
+                   || find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)) == NULL)
                  {
-                   /* Variables/Absolutes:  Look up by name.  */
-                   if (lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
-                                      (struct block *) NULL, VAR_DOMAIN, 0)
-                        == NULL)
+                   if (lookup_symbol_in_objfile_from_linkage_name
+                       (objfile, SYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
+                       == NULL)
                      {
                        /* match */
                        psr = (struct symbol_search *)
@@ -3685,10 +3823,11 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
   search_symbols (regexp, kind, 0, (char **) NULL, &symbols);
   old_chain = make_cleanup_free_search_symbols (symbols);
 
-  printf_filtered (regexp
-                  ? "All %ss matching regular expression \"%s\":\n"
-                  : "All defined %ss:\n",
-                  classnames[kind], regexp);
+  if (regexp != NULL)
+    printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+                    classnames[kind], regexp);
+  else
+    printf_filtered (_("All defined %ss:\n"), classnames[kind]);
 
   for (p = symbols; p != NULL; p = p->next)
     {
@@ -3698,7 +3837,7 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
        {
          if (first)
            {
-             printf_filtered ("\nNon-debugging symbols:\n");
+             printf_filtered (_("\nNon-debugging symbols:\n"));
              first = 0;
            }
          print_msymbol_info (p->msymbol);
@@ -3874,17 +4013,14 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
 /* Free any memory associated with a completion list.  */
 
 static void
-free_completion_list (char ***list_ptr)
+free_completion_list (VEC (char_ptr) **list_ptr)
 {
-  int i = 0;
-  char **list = *list_ptr;
+  int i;
+  char *p;
 
-  while (list[i] != NULL)
-    {
-      xfree (list[i]);
-      i++;
-    }
-  xfree (list);
+  for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
+    xfree (p);
+  VEC_free (char_ptr, *list_ptr);
 }
 
 /* Callback for make_cleanup.  */
@@ -3897,9 +4033,7 @@ do_free_completion_list (void *list)
 
 /* Helper routine for make_symbol_completion_list.  */
 
-static int return_val_size;
-static int return_val_index;
-static char **return_val;
+static VEC (char_ptr) *return_val;
 
 #define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
       completion_list_add_name \
@@ -3946,13 +4080,7 @@ completion_list_add_name (const char *symname,
        strcat (new, symname);
       }
 
-    if (return_val_index + 3 > return_val_size)
-      {
-       newsize = (return_val_size *= 2) * sizeof (char *);
-       return_val = (char **) xrealloc ((char *) return_val, newsize);
-      }
-    return_val[return_val_index++] = new;
-    return_val[return_val_index] = NULL;
+    VEC_safe_push (char_ptr, return_val, new);
   }
 }
 
@@ -4116,9 +4244,10 @@ expand_partial_symbol_name (const char *name, void *user_data)
   return compare_symbol_name (name, datum->sym_text, datum->sym_text_len);
 }
 
-char **
+VEC (char_ptr) *
 default_make_symbol_completion_list_break_on (char *text, char *word,
-                                             const char *break_on)
+                                             const char *break_on,
+                                             enum type_code code)
 {
   /* Problem: All of the symbols have to be copied because readline
      frees them.  I'm not going to worry about this; hopefully there
@@ -4171,9 +4300,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
       {
-       return_val = (char **) xmalloc (sizeof (char *));
-       return_val[0] = NULL;
-       return return_val;
+       return NULL;
       }
     else
       {
@@ -4209,10 +4336,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
     }
   gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
 
-  return_val_size = 100;
-  return_val_index = 0;
-  return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
-  return_val[0] = NULL;
+  return_val = NULL;
   back_to = make_cleanup (do_free_completion_list, &return_val);
 
   datum.sym_text = sym_text;
@@ -4230,13 +4354,18 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
      anything that isn't a text symbol (everything else will be
      handled by the psymtab code above).  */
 
-  ALL_MSYMBOLS (objfile, msymbol)
-  {
-    QUIT;
-    COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+  if (code == TYPE_CODE_UNDEF)
+    {
+      ALL_MSYMBOLS (objfile, msymbol)
+       {
+         QUIT;
+         COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
+                                     word);
 
-    completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text, word);
-  }
+         completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
+                                      word);
+       }
+    }
 
   /* Search upwards from currently selected frame (so that we can
      complete on local vars).  Also catch fields of types defined in
@@ -4253,10 +4382,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
 
        ALL_BLOCK_SYMBOLS (b, iter, sym)
          {
-           COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
-                                       word);
-           completion_list_add_fields (sym, sym_text, sym_text_len, text,
-                                       word);
+           if (code == TYPE_CODE_UNDEF)
+             {
+               COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+                                           word);
+               completion_list_add_fields (sym, sym_text, sym_text_len, text,
+                                           word);
+             }
+           else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+                    && TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+             COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+                                         word);
          }
 
        /* Stop when we encounter an enclosing function.  Do not stop for
@@ -4269,13 +4405,16 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
 
   /* Add fields from the file's types; symbols will be added below.  */
 
-  if (surrounding_static_block != NULL)
-    ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
-      completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+  if (code == TYPE_CODE_UNDEF)
+    {
+      if (surrounding_static_block != NULL)
+       ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
+         completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
 
-  if (surrounding_global_block != NULL)
-      ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
-       completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+      if (surrounding_global_block != NULL)
+       ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
+         completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+    }
 
   /* Go through the symtabs and check the externs and statics for
      symbols which match.  */
@@ -4286,7 +4425,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
     b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
     ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
-       COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+       if (code == TYPE_CODE_UNDEF
+           || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+               && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+         COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
       }
   }
 
@@ -4296,11 +4438,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
     b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
     ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
-       COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+       if (code == TYPE_CODE_UNDEF
+           || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+               && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+         COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
       }
   }
 
-  if (current_language->la_macro_expansion == macro_expansion_c)
+  /* Skip macros if we are completing a struct tag -- arguable but
+     usually what is expected.  */
+  if (current_language->la_macro_expansion == macro_expansion_c
+      && code == TYPE_CODE_UNDEF)
     {
       struct macro_scope *scope;
 
@@ -4327,26 +4475,41 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
   return (return_val);
 }
 
-char **
-default_make_symbol_completion_list (char *text, char *word)
+VEC (char_ptr) *
+default_make_symbol_completion_list (char *text, char *word,
+                                    enum type_code code)
 {
-  return default_make_symbol_completion_list_break_on (text, word, "");
+  return default_make_symbol_completion_list_break_on (text, word, "", code);
 }
 
-/* Return a NULL terminated array of all symbols (regardless of class)
-   which begin by matching TEXT.  If the answer is no symbols, then
-   the return value is an array which contains only a NULL pointer.  */
+/* Return a vector of all symbols (regardless of class) which begin by
+   matching TEXT.  If the answer is no symbols, then the return value
+   is NULL.  */
 
-char **
+VEC (char_ptr) *
 make_symbol_completion_list (char *text, char *word)
 {
-  return current_language->la_make_symbol_completion_list (text, word);
+  return current_language->la_make_symbol_completion_list (text, word,
+                                                          TYPE_CODE_UNDEF);
+}
+
+/* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
+   symbols whose type code is CODE.  */
+
+VEC (char_ptr) *
+make_symbol_completion_type (char *text, char *word, enum type_code code)
+{
+  gdb_assert (code == TYPE_CODE_UNION
+             || code == TYPE_CODE_STRUCT
+             || code == TYPE_CODE_CLASS
+             || code == TYPE_CODE_ENUM);
+  return current_language->la_make_symbol_completion_list (text, word, code);
 }
 
 /* Like make_symbol_completion_list, but suitable for use as a
    completion function.  */
 
-char **
+VEC (char_ptr) *
 make_symbol_completion_list_fn (struct cmd_list_element *ignore,
                                char *text, char *word)
 {
@@ -4356,7 +4519,7 @@ make_symbol_completion_list_fn (struct cmd_list_element *ignore,
 /* Like make_symbol_completion_list, but returns a list of symbols
    defined in a source file FILE.  */
 
-char **
+VEC (char_ptr) *
 make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 {
   struct symbol *sym;
@@ -4402,9 +4565,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
       {
-       return_val = (char **) xmalloc (sizeof (char *));
-       return_val[0] = NULL;
-       return return_val;
+       return NULL;
       }
     else
       {
@@ -4415,10 +4576,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 
   sym_text_len = strlen (sym_text);
 
-  return_val_size = 10;
-  return_val_index = 0;
-  return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
-  return_val[0] = NULL;
+  return_val = NULL;
 
   /* Find the symtab for SRCFILE (this loads it if it was not yet read
      in).  */
@@ -4461,18 +4619,11 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
 
 static void
 add_filename_to_list (const char *fname, char *text, char *word,
-                     char ***list, int *list_used, int *list_alloced)
+                     VEC (char_ptr) **list)
 {
   char *new;
   size_t fnlen = strlen (fname);
 
-  if (*list_used + 1 >= *list_alloced)
-    {
-      *list_alloced *= 2;
-      *list = (char **) xrealloc ((char *) *list,
-                                 *list_alloced * sizeof (char *));
-    }
-
   if (word == text)
     {
       /* Return exactly fname.  */
@@ -4493,8 +4644,7 @@ add_filename_to_list (const char *fname, char *text, char *word,
       new[text - word] = '\0';
       strcat (new, fname);
     }
-  (*list)[*list_used] = new;
-  (*list)[++*list_used] = NULL;
+  VEC_safe_push (char_ptr, *list, new);
 }
 
 static int
@@ -4518,13 +4668,11 @@ not_interesting_fname (const char *fname)
    map_partial_symbol_filenames.  */
 struct add_partial_filename_data
 {
-  int *first;
+  struct filename_seen_cache *filename_seen_cache;
   char *text;
   char *word;
   int text_len;
-  char ***list;
-  int *list_used;
-  int *list_alloced;
+  VEC (char_ptr) **list;
 };
 
 /* A callback for map_partial_symbol_filenames.  */
@@ -4537,63 +4685,60 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
 
   if (not_interesting_fname (filename))
     return;
-  if (!filename_seen (filename, 1, data->first)
+  if (!filename_seen (data->filename_seen_cache, filename, 1)
       && filename_ncmp (filename, data->text, data->text_len) == 0)
     {
       /* This file matches for a completion; add it to the
         current list of matches.  */
-      add_filename_to_list (filename, data->text, data->word,
-                           data->list, data->list_used, data->list_alloced);
+      add_filename_to_list (filename, data->text, data->word, data->list);
     }
   else
     {
       const char *base_name = lbasename (filename);
 
       if (base_name != filename
-         && !filename_seen (base_name, 1, data->first)
+         && !filename_seen (data->filename_seen_cache, base_name, 1)
          && filename_ncmp (base_name, data->text, data->text_len) == 0)
-       add_filename_to_list (base_name, data->text, data->word,
-                             data->list, data->list_used, data->list_alloced);
+       add_filename_to_list (base_name, data->text, data->word, data->list);
     }
 }
 
-/* Return a NULL terminated array of all source files whose names
-   begin with matching TEXT.  The file names are looked up in the
-   symbol tables of this program.  If the answer is no matchess, then
-   the return value is an array which contains only a NULL pointer.  */
+/* Return a vector of all source files whose names begin with matching
+   TEXT.  The file names are looked up in the symbol tables of this
+   program.  If the answer is no matchess, then the return value is
+   NULL.  */
 
-char **
+VEC (char_ptr) *
 make_source_files_completion_list (char *text, char *word)
 {
   struct symtab *s;
   struct objfile *objfile;
-  int first = 1;
-  int list_alloced = 1;
-  int list_used = 0;
   size_t text_len = strlen (text);
-  char **list = (char **) xmalloc (list_alloced * sizeof (char *));
+  VEC (char_ptr) *list = NULL;
   const char *base_name;
   struct add_partial_filename_data datum;
-  struct cleanup *back_to;
-
-  list[0] = NULL;
+  struct filename_seen_cache *filename_seen_cache;
+  struct cleanup *back_to, *cache_cleanup;
 
   if (!have_full_symbols () && !have_partial_symbols ())
     return list;
 
   back_to = make_cleanup (do_free_completion_list, &list);
 
+  filename_seen_cache = create_filename_seen_cache ();
+  cache_cleanup = make_cleanup (delete_filename_seen_cache,
+                               filename_seen_cache);
+
   ALL_SYMTABS (objfile, s)
     {
       if (not_interesting_fname (s->filename))
        continue;
-      if (!filename_seen (s->filename, 1, &first)
+      if (!filename_seen (filename_seen_cache, s->filename, 1)
          && filename_ncmp (s->filename, text, text_len) == 0)
        {
          /* This file matches for a completion; add it to the current
             list of matches.  */
-         add_filename_to_list (s->filename, text, word,
-                               &list, &list_used, &list_alloced);
+         add_filename_to_list (s->filename, text, word, &list);
        }
       else
        {
@@ -4603,22 +4748,21 @@ make_source_files_completion_list (char *text, char *word)
             command do when they parse file names.  */
          base_name = lbasename (s->filename);
          if (base_name != s->filename
-             && !filename_seen (base_name, 1, &first)
+             && !filename_seen (filename_seen_cache, base_name, 1)
              && filename_ncmp (base_name, text, text_len) == 0)
-           add_filename_to_list (base_name, text, word,
-                                 &list, &list_used, &list_alloced);
+           add_filename_to_list (base_name, text, word, &list);
        }
     }
 
-  datum.first = &first;
+  datum.filename_seen_cache = filename_seen_cache;
   datum.text = text;
   datum.word = word;
   datum.text_len = text_len;
   datum.list = &list;
-  datum.list_used = &list_used;
-  datum.list_alloced = &list_alloced;
   map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
                                0 /*need_fullname*/);
+
+  do_cleanups (cache_cleanup);
   discard_cleanups (back_to);
 
   return list;
@@ -4807,27 +4951,6 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
     return prologue_sal.pc;
 }
 \f
-struct symtabs_and_lines
-decode_line_spec (char *string, int flags)
-{
-  struct symtabs_and_lines sals;
-  struct symtab_and_line cursal;
-
-  if (string == 0)
-    error (_("Empty line specification."));
-
-  /* We use whatever is set as the current source line.  We do not try
-     and get a default  or it will recursively call us!  */
-  cursal = get_current_source_symtab_and_line ();
-
-  sals = decode_line_1 (&string, flags,
-                       cursal.symtab, cursal.line);
-
-  if (*string)
-    error (_("Junk at end of line specification: %s"), string);
-  return sals;
-}
-
 /* Track MAIN */
 static char *name_of_main;
 enum language language_of_main = language_unknown;
@@ -5002,5 +5125,13 @@ one base name, and gdb will do file name comparisons more efficiently."),
                           NULL, NULL,
                           &setlist, &showlist);
 
+  add_setshow_boolean_cmd ("symtab-create", no_class, &symtab_create_debug,
+                          _("Set debugging of symbol table creation."),
+                          _("Show debugging of symbol table creation."), _("\
+When enabled, debugging messages are printed when building symbol tables."),
+                           NULL,
+                           NULL,
+                           &setdebuglist, &showdebuglist);
+
   observer_attach_executable_changed (symtab_observer_executable_changed);
 }
This page took 0.039048 seconds and 4 git commands to generate.