2012-12-14 Yufeng Zhang <yufeng.zhang@arm.com>
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 46d119a5239a46952cabd25a0896be934ec3105c..1b0b35bcd7c765d8038e2b39cfb931d7ea830e78 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,8 +76,6 @@ 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,
@@ -245,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)
           {
@@ -405,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);
@@ -1770,7 +1769,7 @@ lookup_symbol_global (const char *name,
   lookup_data.name = name;
   lookup_data.domain = domain;
   gdbarch_iterate_over_objfiles_in_search_order
-    (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch,
+    (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (),
      lookup_symbol_global_iterator_cb, &lookup_data, objfile);
 
   return lookup_data.result;
@@ -2151,6 +2150,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;
@@ -2813,7 +2814,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;
 
@@ -3106,57 +3107,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
@@ -3168,20 +3205,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);
@@ -3201,31 +3234,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
@@ -3740,10 +3781,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)
     {
@@ -3753,7 +3795,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);
@@ -4162,7 +4204,8 @@ expand_partial_symbol_name (const char *name, void *user_data)
 
 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
@@ -4269,13 +4312,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
@@ -4292,10 +4340,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
@@ -4308,13 +4363,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.  */
@@ -4325,7 +4383,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);
       }
   }
 
@@ -4335,11 +4396,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;
 
@@ -4367,9 +4434,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
 }
 
 VEC (char_ptr) *
-default_make_symbol_completion_list (char *text, char *word)
+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 vector of all symbols (regardless of class) which begin by
@@ -4379,7 +4447,21 @@ default_make_symbol_completion_list (char *text, char *word)
 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
@@ -4544,7 +4626,7 @@ 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;
@@ -4561,7 +4643,7 @@ 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
@@ -4573,7 +4655,7 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
       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);
     }
@@ -4589,23 +4671,27 @@ make_source_files_completion_list (char *text, char *word)
 {
   struct symtab *s;
   struct objfile *objfile;
-  int first = 1;
   size_t text_len = strlen (text);
   VEC (char_ptr) *list = NULL;
   const char *base_name;
   struct add_partial_filename_data datum;
-  struct cleanup *back_to;
+  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
@@ -4620,19 +4706,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);
        }
     }
 
-  datum.first = &first;
+  datum.filename_seen_cache = filename_seen_cache;
   datum.text = text;
   datum.word = word;
   datum.text_len = text_len;
   datum.list = &list;
   map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
                                0 /*need_fullname*/);
+
+  do_cleanups (cache_cleanup);
   discard_cleanups (back_to);
 
   return list;
@@ -4821,27 +4909,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;
This page took 0.03033 seconds and 4 git commands to generate.