* symtab.c (lookup_symtab): Removed.
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 50a0ef6ea07f9be3344865c612c90d1b53022e77..237006f208ccaf847e66ec558faa88011dcf0a06 100644 (file)
@@ -1,5 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
-   Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -36,6 +37,7 @@
 #include "demangle.h"
 #include "inferior.h"
 #include "linespec.h"
+#include "filenames.h"         /* for FILENAME_CMP */
 
 #include "obstack.h"
 
@@ -44,6 +46,7 @@
 #include "gdb_string.h"
 #include "gdb_stat.h"
 #include <ctype.h>
+#include "cp-abi.h"
 
 /* Prototype for one function in parser-defs.h,
    instead of including that entire file. */
@@ -76,8 +79,6 @@ static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
                                                     const char *, int,
                                                     namespace_enum);
 
-static struct symtab *lookup_symtab_1 (char *);
-
 static struct symbol *lookup_symbol_aux (const char *name, const
                                         struct block *block, const
                                         namespace_enum namespace, int
@@ -134,12 +135,11 @@ cplusplus_hint (char *name)
    psymtabs.  *If* there is no '/' in the name, a match after a '/'
    in the symtab filename will also work.  */
 
-static struct symtab *
-lookup_symtab_1 (char *name)
+struct symtab *
+lookup_symtab (const char *name)
 {
   register struct symtab *s;
   register struct partial_symtab *ps;
-  register char *slash;
   register struct objfile *objfile;
 
 got_symtab:
@@ -147,23 +147,15 @@ got_symtab:
   /* First, search for an exact match */
 
   ALL_SYMTABS (objfile, s)
-    if (STREQ (name, s->filename))
-    return s;
-
-  slash = strchr (name, '/');
+    if (FILENAME_CMP (name, s->filename) == 0)
+      return s;
 
   /* Now, search for a matching tail (only if name doesn't have any dirs) */
 
-  if (!slash)
+  if (lbasename (name) == name)
     ALL_SYMTABS (objfile, s)
     {
-      char *p = s->filename;
-      char *tail = strrchr (p, '/');
-
-      if (tail)
-       p = tail + 1;
-
-      if (STREQ (p, name))
+      if (FILENAME_CMP (lbasename (s->filename), name) == 0)
        return s;
     }
 
@@ -194,55 +186,19 @@ got_symtab:
   goto got_symtab;
 }
 
-/* Lookup the symbol table of a source file named NAME.  Try a couple
-   of variations if the first lookup doesn't work.  */
-
-struct symtab *
-lookup_symtab (char *name)
-{
-  register struct symtab *s;
-#if 0
-  register char *copy;
-#endif
-
-  s = lookup_symtab_1 (name);
-  if (s)
-    return s;
-
-#if 0
-  /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab
-     "tree.c".  */
-
-  /* If name not found as specified, see if adding ".c" helps.  */
-  /* Why is this?  Is it just a user convenience?  (If so, it's pretty
-     questionable in the presence of C++, FORTRAN, etc.).  It's not in
-     the GDB manual.  */
-
-  copy = (char *) alloca (strlen (name) + 3);
-  strcpy (copy, name);
-  strcat (copy, ".c");
-  s = lookup_symtab_1 (copy);
-  if (s)
-    return s;
-#endif /* 0 */
-
-  /* We didn't find anything; die.  */
-  return 0;
-}
-
 /* Lookup the partial symbol table of a source file named NAME.
    *If* there is no '/' in the name, a match after a '/'
    in the psymtab filename will also work.  */
 
 struct partial_symtab *
-lookup_partial_symtab (char *name)
+lookup_partial_symtab (const char *name)
 {
   register struct partial_symtab *pst;
   register struct objfile *objfile;
 
   ALL_PSYMTABS (objfile, pst)
   {
-    if (STREQ (name, pst->filename))
+    if (FILENAME_CMP (name, pst->filename) == 0)
       {
        return (pst);
       }
@@ -250,16 +206,10 @@ lookup_partial_symtab (char *name)
 
   /* Now, search for a matching tail (only if name doesn't have any dirs) */
 
-  if (!strchr (name, '/'))
+  if (lbasename (name) == name)
     ALL_PSYMTABS (objfile, pst)
     {
-      char *p = pst->filename;
-      char *tail = strrchr (p, '/');
-
-      if (tail)
-       p = tail + 1;
-
-      if (STREQ (p, name))
+      if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
        return (pst);
     }
 
@@ -287,20 +237,17 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
   int is_full_physname_constructor;
 
   int is_constructor;
-  int is_destructor = DESTRUCTOR_PREFIX_P (physname);
+  int is_destructor = is_destructor_name (physname);
   /* Need a new type prefix.  */
   char *const_prefix = method->is_const ? "C" : "";
   char *volatile_prefix = method->is_volatile ? "V" : "";
   char buf[20];
   int len = (newname == NULL ? 0 : strlen (newname));
 
-  if (OPNAME_PREFIX_P (field_name))
+  if (is_operator_name (field_name))
     return xstrdup (physname);
 
-  is_full_physname_constructor =
-    ((physname[0] == '_' && physname[1] == '_' &&
-      (isdigit (physname[2]) || physname[2] == 'Q' || physname[2] == 't'))
-     || (strncmp (physname, "__ct", 4) == 0));
+  is_full_physname_constructor = is_constructor_name (physname);
 
   is_constructor =
     is_full_physname_constructor || (newname && STREQ (field_name, newname));
@@ -1173,7 +1120,7 @@ find_main_psymtab (void)
 
   ALL_PSYMTABS (objfile, pst)
   {
-    if (lookup_partial_symbol (pst, "main", 1, VAR_NAMESPACE))
+    if (lookup_partial_symbol (pst, main_name (), 1, VAR_NAMESPACE))
       {
        return (pst);
       }
@@ -1758,11 +1705,18 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
        {
          best = prev;
          best_symtab = s;
-         /* If another line is in the linetable, and its PC is closer
-            than the best_end we currently have, take it as best_end.  */
-         if (i < len && (best_end == 0 || best_end > item->pc))
-           best_end = item->pc;
+
+         /* Discard BEST_END if it's before the PC of the current BEST.  */
+         if (best_end <= best->pc)
+           best_end = 0;
        }
+
+      /* If another line (denoted by ITEM) is in the linetable and its
+         PC is after BEST's PC, but before the current BEST_END, then
+        use ITEM's PC as the new best_end.  */
+      if (best && i < len && item->pc > best->pc
+          && (best_end == 0 || best_end > item->pc))
+       best_end = item->pc;
     }
 
   if (!best_symtab)
@@ -2161,50 +2115,72 @@ operator_chars (char *p, char **end)
 }
 \f
 
-/* 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.  */
-static void
-output_source_filename (char *name, int *first)
+/* If FILE is not already in the table of files, 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.  */
+static int
+filename_seen (const char *file, int add, int *first)
 {
-  /* Table of files printed so far.  Since a single source file can
-     result in several partial symbol tables, we need to avoid printing
-     it more than once.  Note: if some of the psymtabs are read in and
-     some are not, it gets printed both under "Source files for which
-     symbols have been read" and "Source files for which symbols will
-     be read in on demand".  I consider this a reasonable way to deal
-     with the situation.  I'm not sure whether this can also happen for
-     symtabs; it doesn't hurt to check.  */
-  static char **tab = NULL;
+  /* 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;
-
-  char **p;
+  const char **p;
 
   if (*first)
     {
       if (tab == NULL)
-       tab = (char **) xmalloc (tab_alloc_size * sizeof (*tab));
+       tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
       tab_cur_size = 0;
     }
 
-  /* Is NAME in tab?  */
+  /* Is FILE in tab?  */
   for (p = tab; p < tab + tab_cur_size; p++)
-    if (STREQ (*p, name))
-      /* Yes; don't print it again.  */
-      return;
-  /* No; add it to tab.  */
-  if (tab_cur_size == tab_alloc_size)
+    if (strcmp (*p, file) == 0)
+      return 1;
+
+  /* No; maybe add it to tab.  */
+  if (add)
     {
-      tab_alloc_size *= 2;
-      tab = (char **) xrealloc ((char *) tab, tab_alloc_size * sizeof (*tab));
+      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;
     }
-  tab[tab_cur_size++] = name;
 
+  return 0;
+}
+
+/* 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.  */
+static void
+output_source_filename (char *name, int *first)
+{
+  /* Since a single source file can result in several partial symbol
+     tables, we need to avoid printing it more than once.  Note: if
+     some of the psymtabs are read in and some are not, it gets
+     printed both under "Source files for which symbols have been
+     read" and "Source files for which symbols will be read in on
+     demand".  I consider this a reasonable way to deal with the
+     situation.  I'm not sure whether this can also happen for
+     symtabs; it doesn't hurt to check.  */
+
+  /* Was NAME already seen?  */
+  if (filename_seen (name, 1, first))
+    {
+      /* Yes; don't print it again.  */
+      return;
+    }
+  /* No; print it and reset *FIRST.  */
   if (*first)
     {
       *first = 0;
@@ -2262,7 +2238,7 @@ file_matches (char *file, char *files[], int nfiles)
     {
       for (i = 0; i < nfiles; i++)
        {
-         if (strcmp (files[i], basename (file)) == 0)
+         if (strcmp (files[i], lbasename (file)) == 0)
            return 1;
        }
     }
@@ -2652,9 +2628,17 @@ print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym,
 static void
 print_msymbol_info (struct minimal_symbol *msymbol)
 {
-  printf_filtered ("   %08lx  %s\n",
-                  (unsigned long) SYMBOL_VALUE_ADDRESS (msymbol),
-                  SYMBOL_SOURCE_NAME (msymbol));
+  char *tmp;
+
+  if (TARGET_ADDR_BIT <= 32)
+    tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
+                                          & (CORE_ADDR) 0xffffffff,
+                                          "08l");
+  else
+    tmp = longest_local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
+                                          "016l");
+  printf_filtered ("%s  %s\n",
+                  tmp, SYMBOL_SOURCE_NAME (msymbol));
 }
 
 /* This is the guts of the commands "info functions", "info types", and
@@ -2836,17 +2820,6 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len,
       return;
     }
 
-  /* Clip any symbol names that we've already considered.  (This is a
-     time optimization)  */
-
-  for (i = 0; i < return_val_index; ++i)
-    {
-      if (STREQ (symname, return_val[i]))
-       {
-         return;
-       }
-    }
-
   /* We have a match for a completion, so add SYMNAME to the current list
      of matches. Note that the name is moved to freshly malloc'd space. */
 
@@ -2872,19 +2845,6 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len,
        strcat (new, symname);
       }
 
-    /* Recheck for duplicates if we intend to add a modified symbol.  */
-    if (word != sym_text)
-      {
-       for (i = 0; i < return_val_index; ++i)
-         {
-           if (STREQ (new, return_val[i]))
-             {
-               xfree (new);
-               return;
-             }
-         }
-      }
-
     if (return_val_index + 3 > return_val_size)
       {
        newsize = (return_val_size *= 2) * sizeof (char *);
@@ -2895,9 +2855,9 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len,
   }
 }
 
-/* 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 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.
 
    Problem: All of the symbols have to be copied because readline frees them.
    I'm not going to worry about this; hopefully there won't be that many.  */
@@ -2951,7 +2911,11 @@ make_symbol_completion_list (char *text, char *word)
     else if (quote_found == '"')
       /* A double-quoted string is never a symbol, nor does it make sense
          to complete it any other way.  */
-      return NULL;
+      {
+       return_val = (char **) xmalloc (sizeof (char *));
+       return_val[0] = NULL;
+       return return_val;
+      }
     else
       {
        /* It is not a quoted string.  Break it based on the characters
@@ -3083,6 +3047,277 @@ make_symbol_completion_list (char *text, char *word)
   return (return_val);
 }
 
+/* Like make_symbol_completion_list, but returns a list of symbols
+   defined in a source file FILE.  */
+
+char **
+make_file_symbol_completion_list (char *text, char *word, char *srcfile)
+{
+  register struct symbol *sym;
+  register struct symtab *s;
+  register struct block *b;
+  register int i;
+  /* The symbol we are completing on.  Points in same buffer as text.  */
+  char *sym_text;
+  /* Length of sym_text.  */
+  int sym_text_len;
+
+  /* Now look for the symbol we are supposed to complete on.
+     FIXME: This should be language-specific.  */
+  {
+    char *p;
+    char quote_found;
+    char *quote_pos = NULL;
+
+    /* First see if this is a quoted string.  */
+    quote_found = '\0';
+    for (p = text; *p != '\0'; ++p)
+      {
+       if (quote_found != '\0')
+         {
+           if (*p == quote_found)
+             /* Found close quote.  */
+             quote_found = '\0';
+           else if (*p == '\\' && p[1] == quote_found)
+             /* A backslash followed by the quote character
+                doesn't end the string.  */
+             ++p;
+         }
+       else if (*p == '\'' || *p == '"')
+         {
+           quote_found = *p;
+           quote_pos = p;
+         }
+      }
+    if (quote_found == '\'')
+      /* A string within single quotes can be a symbol, so complete on it.  */
+      sym_text = quote_pos + 1;
+    else if (quote_found == '"')
+      /* 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;
+      }
+    else
+      {
+       /* It is not a quoted string.  Break it based on the characters
+          which are in symbols.  */
+       while (p > text)
+         {
+           if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+             --p;
+           else
+             break;
+         }
+       sym_text = p;
+      }
+  }
+
+  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;
+
+  /* Find the symtab for SRCFILE (this loads it if it was not yet read
+     in).  */
+  s = lookup_symtab (srcfile);
+  if (s == NULL)
+    {
+      /* Maybe they typed the file with leading directories, while the
+        symbol tables record only its basename.  */
+      const char *tail = lbasename (srcfile);
+
+      if (tail > srcfile)
+       s = lookup_symtab (tail);
+    }
+
+  /* If we have no symtab for that file, return an empty list.  */
+  if (s == NULL)
+    return (return_val);
+
+  /* Go through this symtab and check the externs and statics for
+     symbols which match.  */
+
+  b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+  for (i = 0; i < BLOCK_NSYMS (b); i++)
+    {
+      sym = BLOCK_SYM (b, i);
+      COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+    }
+
+  b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+  for (i = 0; i < BLOCK_NSYMS (b); i++)
+    {
+      sym = BLOCK_SYM (b, i);
+      COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+    }
+
+  return (return_val);
+}
+
+/* A helper function for make_source_files_completion_list.  It adds
+   another file name to a list of possible completions, growing the
+   list as necessary.  */
+
+static void
+add_filename_to_list (const char *fname, char *text, char *word,
+                     char ***list, int *list_used, int *list_alloced)
+{
+  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.  */
+      new = xmalloc (fnlen + 5);
+      strcpy (new, fname);
+    }
+  else if (word > text)
+    {
+      /* Return some portion of fname.  */
+      new = xmalloc (fnlen + 5);
+      strcpy (new, fname + (word - text));
+    }
+  else
+    {
+      /* Return some of TEXT plus fname.  */
+      new = xmalloc (fnlen + (text - word) + 5);
+      strncpy (new, word, text - word);
+      new[text - word] = '\0';
+      strcat (new, fname);
+    }
+  (*list)[*list_used] = new;
+  (*list)[++*list_used] = NULL;
+}
+
+static int
+not_interesting_fname (const char *fname)
+{
+  static const char *illegal_aliens[] = {
+    "_globals_",       /* inserted by coff_symtab_read */
+    NULL
+  };
+  int i;
+
+  for (i = 0; illegal_aliens[i]; i++)
+    {
+      if (strcmp (fname, illegal_aliens[i]) == 0)
+       return 1;
+    }
+  return 0;
+}
+
+/* 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.  */
+
+char **
+make_source_files_completion_list (char *text, char *word)
+{
+  register struct symtab *s;
+  register struct partial_symtab *ps;
+  register 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 *));
+  const char *base_name;
+
+  list[0] = NULL;
+
+  if (!have_full_symbols () && !have_partial_symbols ())
+    return list;
+
+  ALL_SYMTABS (objfile, s)
+    {
+      if (not_interesting_fname (s->filename))
+       continue;
+      if (!filename_seen (s->filename, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+         && strncasecmp (s->filename, text, text_len) == 0
+#else
+         && strncmp (s->filename, text, text_len) == 0
+#endif
+         )
+       {
+         /* 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);
+       }
+      else
+       {
+         /* NOTE: We allow the user to type a base name when the
+            debug info records leading directories, but not the other
+            way around.  This is what subroutines of breakpoint
+            command do when they parse file names.  */
+         base_name = lbasename (s->filename);
+         if (base_name != s->filename
+             && !filename_seen (base_name, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+             && strncasecmp (base_name, text, text_len) == 0
+#else
+             && strncmp (base_name, text, text_len) == 0
+#endif
+             )
+           add_filename_to_list (base_name, text, word,
+                                 &list, &list_used, &list_alloced);
+       }
+    }
+
+  ALL_PSYMTABS (objfile, ps)
+    {
+      if (not_interesting_fname (ps->filename))
+       continue;
+      if (!ps->readin)
+       {
+         if (!filename_seen (ps->filename, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+             && strncasecmp (ps->filename, text, text_len) == 0
+#else
+             && strncmp (ps->filename, text, text_len) == 0
+#endif
+             )
+           {
+             /* This file matches for a completion; add it to the
+                current list of matches.  */
+             add_filename_to_list (ps->filename, text, word,
+                                   &list, &list_used, &list_alloced);
+
+           }
+         else
+           {
+             base_name = lbasename (ps->filename);
+             if (base_name != ps->filename
+                 && !filename_seen (base_name, 1, &first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+                 && strncasecmp (base_name, text, text_len) == 0
+#else
+                 && strncmp (base_name, text, text_len) == 0
+#endif
+                 )
+               add_filename_to_list (base_name, text, word,
+                                     &list, &list_used, &list_alloced);
+           }
+       }
+    }
+
+  return list;
+}
+
 /* Determine if PC is in the prologue of a function.  The prologue is the area
    between the first instruction of a function, and the first executable line.
    Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue.
@@ -3351,6 +3586,33 @@ decode_line_spec (char *string, int funfirstline)
   return sals;
 }
 
+/* Track MAIN */
+static char *name_of_main;
+
+void
+set_main_name (const char *name)
+{
+  if (name_of_main != NULL)
+    {
+      xfree (name_of_main);
+      name_of_main = NULL;
+    }
+  if (name != NULL)
+    {
+      name_of_main = xstrdup (name);
+    }
+}
+
+char *
+main_name (void)
+{
+  if (name_of_main != NULL)
+    return name_of_main;
+  else
+    return "main";
+}
+
+
 void
 _initialize_symtab (void)
 {
This page took 0.037969 seconds and 4 git commands to generate.