*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / symtab.c
index d39962ec03314d2e59f7ceb2921de27c6938a9f8..426326d1066f9e15730d69ada9b285695fbef852 100644 (file)
@@ -1,14 +1,14 @@
 /* Symbol table lookup for the GNU debugger, GDB.
 
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
-   Foundation, Inc.
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009,
+   2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "symtab.h"
 #include "demangle.h"
 #include "inferior.h"
 #include "linespec.h"
+#include "source.h"
 #include "filenames.h"         /* for FILENAME_CMP */
+#include "objc-lang.h"
+#include "ada-lang.h"
+#include "p-lang.h"
+#include "addrmap.h"
+
+#include "hashtab.h"
 
 #include "gdb_obstack.h"
+#include "block.h"
+#include "dictionary.h"
 
 #include <sys/types.h>
 #include <fcntl.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. */
-
-extern char *find_template_name_end (char *);
+#include "cp-support.h"
+#include "observer.h"
+#include "gdb_assert.h"
+#include "solist.h"
+#include "macrotab.h"
+#include "macroscope.h"
 
 /* Prototypes for local functions */
 
@@ -68,7 +76,7 @@ static void variables_info (char *, int);
 
 static void sources_info (char *, int);
 
-static void output_source_filename (char *, int *);
+static void output_source_filename (const char *, int *);
 
 static int find_line_common (struct linetable *, int, int *);
 
@@ -76,63 +84,74 @@ static int find_line_common (struct linetable *, int, int *);
 
 char *operator_chars (char *p, char **end);
 
-static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
-                                                    const char *, int,
-                                                    namespace_enum);
-
 static struct symbol *lookup_symbol_aux (const char *name,
-                                        const char *mangled_name,
+                                        const char *linkage_name,
                                         const struct block *block,
-                                        const namespace_enum namespace,
-                                        int *is_a_field_of_this,
-                                        struct symtab **symtab);
-
-
-static struct symbol *find_active_alias (struct symbol *sym, CORE_ADDR addr);
-
-/* This flag is used in hppa-tdep.c, and set in hp-symtab-read.c */
-/* Signals the presence of objects compiled by HP compilers */
-int hp_som_som_object_present = 0;
-
-static void fixup_section (struct general_symbol_info *, struct objfile *);
+                                        const domain_enum domain,
+                                        enum language language,
+                                        int *is_a_field_of_this);
+
+static
+struct symbol *lookup_symbol_aux_local (const char *name,
+                                       const char *linkage_name,
+                                       const struct block *block,
+                                       const domain_enum domain);
+
+static
+struct symbol *lookup_symbol_aux_symtabs (int block_index,
+                                         const char *name,
+                                         const char *linkage_name,
+                                         const domain_enum domain);
+
+static
+struct symbol *lookup_symbol_aux_psymtabs (int block_index,
+                                          const char *name,
+                                          const char *linkage_name,
+                                          const domain_enum domain);
 
 static int file_matches (char *, char **, int);
 
-static void print_symbol_info (namespace_enum,
+static void print_symbol_info (domain_enum,
                               struct symtab *, struct symbol *, int, char *);
 
 static void print_msymbol_info (struct minimal_symbol *);
 
-static void symtab_symbol_info (char *, namespace_enum, int);
-
-static void overload_list_add_symbol (struct symbol *sym, char *oload_name);
+static void symtab_symbol_info (char *, domain_enum, int);
 
 void _initialize_symtab (void);
 
 /* */
 
-/* The single non-language-specific builtin type */
-struct type *builtin_type_error;
-
-/* Block in which the most recently searched-for symbol was found.
-   Might be better to make this a parameter to lookup_symbol and 
-   value_of_this. */
+/* Allow the user to configure the debugger behavior with respect
+   to multiple-choice menus when more than one symbol matches during
+   a symbol lookup.  */
 
-const struct block *block_found;
+const char multiple_symbols_ask[] = "ask";
+const char multiple_symbols_all[] = "all";
+const char multiple_symbols_cancel[] = "cancel";
+static const char *multiple_symbols_modes[] =
+{
+  multiple_symbols_ask,
+  multiple_symbols_all,
+  multiple_symbols_cancel,
+  NULL
+};
+static const char *multiple_symbols_mode = multiple_symbols_all;
 
-/* While the C++ support is still in flux, issue a possibly helpful hint on
-   using the new command completion feature on single quoted demangled C++
-   symbols.  Remove when loose ends are cleaned up.   FIXME -fnf */
+/* Read-only accessor to AUTO_SELECT_MODE.  */
 
-static void
-cplusplus_hint (char *name)
+const char *
+multiple_symbols_select_mode (void)
 {
-  while (*name == '\'')
-    name++;
-  printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
-  printf_filtered ("(Note leading single quote.)\n");
+  return multiple_symbols_mode;
 }
 
+/* Block in which the most recently searched-for symbol was found.
+   Might be better to make this a parameter to lookup_symbol and
+   value_of_this. */
+
+const struct block *block_found;
+
 /* Check for a symtab of a specific name; first in symtabs, then in
    psymtabs.  *If* there is no '/' in the name, a match after a '/'
    in the symtab filename will also work.  */
@@ -140,9 +159,9 @@ cplusplus_hint (char *name)
 struct symtab *
 lookup_symtab (const char *name)
 {
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct objfile *objfile;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct objfile *objfile;
   char *real_path = NULL;
   char *full_path = NULL;
 
@@ -166,27 +185,31 @@ got_symtab:
       {
        return s;
       }
-      
+
     /* If the user gave us an absolute path, try to find the file in
        this symtab and use its absolute path.  */
-    
+
     if (full_path != NULL)
       {
-       const char *fp = symtab_to_filename (s);
-       if (FILENAME_CMP (full_path, fp) == 0)
-         {
-           return s;
-         }
+        const char *fp = symtab_to_fullname (s);
+        if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
+          {
+            return s;
+          }
       }
 
     if (real_path != NULL)
       {
-       char *rp = gdb_realpath (symtab_to_filename (s));
-        make_cleanup (xfree, rp);
-       if (FILENAME_CMP (real_path, rp) == 0)
-         {
-           return s;
-         }
+        char *fullname = symtab_to_fullname (s);
+        if (fullname != NULL)
+          {
+            char *rp = gdb_realpath (fullname);
+            make_cleanup (xfree, rp);
+            if (FILENAME_CMP (real_path, rp) == 0)
+              {
+                return s;
+              }
+          }
       }
   }
 
@@ -207,7 +230,7 @@ got_symtab:
     return (NULL);
 
   if (ps->readin)
-    error ("Internal: readin %s pst for `%s' found when no symtab found.",
+    error (_("Internal: readin %s pst for `%s' found when no symtab found."),
           ps->filename, name);
 
   s = PSYMTAB_TO_SYMTAB (ps);
@@ -233,8 +256,8 @@ got_symtab:
 struct partial_symtab *
 lookup_partial_symtab (const char *name)
 {
-  register struct partial_symtab *pst;
-  register struct objfile *objfile;
+  struct partial_symtab *pst;
+  struct objfile *objfile;
   char *full_path = NULL;
   char *real_path = NULL;
 
@@ -259,8 +282,7 @@ lookup_partial_symtab (const char *name)
        this symtab and use its absolute path.  */
     if (full_path != NULL)
       {
-       if (pst->fullname == NULL)
-         source_full_path_of (pst->filename, &pst->fullname);
+       psymtab_to_fullname (pst);
        if (pst->fullname != NULL
            && FILENAME_CMP (full_path, pst->fullname) == 0)
          {
@@ -271,8 +293,7 @@ lookup_partial_symtab (const char *name)
     if (real_path != NULL)
       {
         char *rp = NULL;
-       if (pst->fullname == NULL)
-         source_full_path_of (pst->filename, &pst->fullname);
+       psymtab_to_fullname (pst);
         if (pst->fullname != NULL)
           {
             rp = gdb_realpath (pst->fullname);
@@ -334,7 +355,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
   is_full_physname_constructor = is_constructor_name (physname);
 
   is_constructor =
-    is_full_physname_constructor || (newname && STREQ (field_name, newname));
+    is_full_physname_constructor || (newname && strcmp (field_name, newname) == 0);
 
   if (!is_destructor)
     is_destructor = (strncmp (physname, "__dt", 4) == 0);
@@ -384,93 +405,514 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
 }
 
 \f
-/* Initialize a symbol's mangled name.  */
+/* Initialize the language dependent portion of a symbol
+   depending upon the language for the symbol. */
+void
+symbol_init_language_specific (struct general_symbol_info *gsymbol,
+                              enum language language)
+{
+  gsymbol->language = language;
+  if (gsymbol->language == language_cplus
+      || gsymbol->language == language_java
+      || gsymbol->language == language_objc)
+    {
+      gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+    }
+  else
+    {
+      memset (&gsymbol->language_specific, 0,
+             sizeof (gsymbol->language_specific));
+    }
+}
+
+/* Functions to initialize a symbol's mangled name.  */
+
+/* Objects of this type are stored in the demangled name hash table.  */
+struct demangled_name_entry
+{
+  char *mangled;
+  char demangled[1];
+};
 
-/* Try to initialize the demangled name for a symbol, based on the
+/* Hash function for the demangled name hash.  */
+static hashval_t
+hash_demangled_name_entry (const void *data)
+{
+  const struct demangled_name_entry *e = data;
+  return htab_hash_string (e->mangled);
+}
+
+/* Equality function for the demangled name hash.  */
+static int
+eq_demangled_name_entry (const void *a, const void *b)
+{
+  const struct demangled_name_entry *da = a;
+  const struct demangled_name_entry *db = b;
+  return strcmp (da->mangled, db->mangled) == 0;
+}
+
+/* Create the hash table used for demangled names.  Each hash entry is
+   a pair of strings; one for the mangled name and one for the demangled
+   name.  The entry is hashed via just the mangled name.  */
+
+static void
+create_demangled_names_hash (struct objfile *objfile)
+{
+  /* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
+     The hash table code will round this up to the next prime number.
+     Choosing a much larger table size wastes memory, and saves only about
+     1% in symbol reading.  */
+
+  objfile->demangled_names_hash = htab_create_alloc
+    (256, hash_demangled_name_entry, eq_demangled_name_entry,
+     NULL, xcalloc, xfree);
+}
+
+/* Try to determine the demangled name for a symbol, based on the
    language of that symbol.  If the language is set to language_auto,
    it will attempt to find any demangling algorithm that works and
-   then set the language appropriately.  If no demangling of any kind
-   is found, the language is set back to language_unknown, so we can
-   avoid doing this work again the next time we encounter the symbol.
-   Any required space to store the name is obtained from the specified
-   obstack. */
+   then set the language appropriately.  The returned name is allocated
+   by the demangler and should be xfree'd.  */
 
-void
-symbol_init_demangled_name (struct general_symbol_info *gsymbol,
-                            struct obstack *obstack)
+static char *
+symbol_find_demangled_name (struct general_symbol_info *gsymbol,
+                           const char *mangled)
 {
-  char *mangled = gsymbol->name;
   char *demangled = NULL;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
+
+  if (gsymbol->language == language_objc
+      || gsymbol->language == language_auto)
+    {
+      demangled =
+       objc_demangle (mangled, 0);
+      if (demangled != NULL)
+       {
+         gsymbol->language = language_objc;
+         return demangled;
+       }
+    }
   if (gsymbol->language == language_cplus
       || gsymbol->language == language_auto)
     {
       demangled =
-        cplus_demangle (gsymbol->name, DMGL_PARAMS | DMGL_ANSI);
+        cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
       if (demangled != NULL)
-        {
-          gsymbol->language = language_cplus;
-          gsymbol->language_specific.cplus_specific.demangled_name =
-            obsavestring (demangled, strlen (demangled), obstack);
-          xfree (demangled);
-        }
-      else
-        {
-          gsymbol->language_specific.cplus_specific.demangled_name = NULL;
-        }
+       {
+         gsymbol->language = language_cplus;
+         return demangled;
+       }
     }
   if (gsymbol->language == language_java)
     {
       demangled =
-        cplus_demangle (gsymbol->name,
+        cplus_demangle (mangled,
                         DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
       if (demangled != NULL)
-        {
-          gsymbol->language = language_java;
-          gsymbol->language_specific.cplus_specific.demangled_name =
-            obsavestring (demangled, strlen (demangled), obstack);
-          xfree (demangled);
-        }
+       {
+         gsymbol->language = language_java;
+         return demangled;
+       }
+    }
+  return NULL;
+}
+
+/* Set both the mangled and demangled (if any) names for GSYMBOL based
+   on LINKAGE_NAME and LEN.  Ordinarily, NAME is copied onto the
+   objfile's obstack; but if COPY_NAME is 0 and if NAME is
+   NUL-terminated, then this function assumes that NAME is already
+   correctly saved (either permanently or with a lifetime tied to the
+   objfile), and it will not be copied.
+
+   The hash table corresponding to OBJFILE is used, and the memory
+   comes from that objfile's objfile_obstack.  LINKAGE_NAME is copied,
+   so the pointer can be discarded after calling this function.  */
+
+/* We have to be careful when dealing with Java names: when we run
+   into a Java minimal symbol, we don't know it's a Java symbol, so it
+   gets demangled as a C++ name.  This is unfortunate, but there's not
+   much we can do about it: but when demangling partial symbols and
+   regular symbols, we'd better not reuse the wrong demangled name.
+   (See PR gdb/1039.)  We solve this by putting a distinctive prefix
+   on Java names when storing them in the hash table.  */
+
+/* FIXME: carlton/2003-03-13: This is an unfortunate situation.  I
+   don't mind the Java prefix so much: different languages have
+   different demangling requirements, so it's only natural that we
+   need to keep language data around in our demangling cache.  But
+   it's not good that the minimal symbol has the wrong demangled name.
+   Unfortunately, I can't think of any easy solution to that
+   problem.  */
+
+#define JAVA_PREFIX "##JAVA$$"
+#define JAVA_PREFIX_LEN 8
+
+void
+symbol_set_names (struct general_symbol_info *gsymbol,
+                 const char *linkage_name, int len, int copy_name,
+                 struct objfile *objfile)
+{
+  struct demangled_name_entry **slot;
+  /* A 0-terminated copy of the linkage name.  */
+  const char *linkage_name_copy;
+  /* A copy of the linkage name that might have a special Java prefix
+     added to it, for use when looking names up in the hash table.  */
+  const char *lookup_name;
+  /* The length of lookup_name.  */
+  int lookup_len;
+  struct demangled_name_entry entry;
+
+  if (gsymbol->language == language_ada)
+    {
+      /* In Ada, we do the symbol lookups using the mangled name, so
+         we can save some space by not storing the demangled name.
+
+         As a side note, we have also observed some overlap between
+         the C++ mangling and Ada mangling, similarly to what has
+         been observed with Java.  Because we don't store the demangled
+         name with the symbol, we don't need to use the same trick
+         as Java.  */
+      if (!copy_name)
+       gsymbol->name = (char *) linkage_name;
       else
-        {
-          gsymbol->language_specific.cplus_specific.demangled_name = NULL;
-        }
+       {
+         gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
+         memcpy (gsymbol->name, linkage_name, len);
+         gsymbol->name[len] = '\0';
+       }
+      gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+
+      return;
     }
-#if 0
-  /* OBSOLETE if (demangled == NULL */
-  /* OBSOLETE     && (gsymbol->language == language_chill */
-  /* OBSOLETE         || gsymbol->language == language_auto)) */
-  /* OBSOLETE   { */
-  /* OBSOLETE     demangled = */
-  /* OBSOLETE       chill_demangle (gsymbol->name); */
-  /* OBSOLETE     if (demangled != NULL) */
-  /* OBSOLETE       { */
-  /* OBSOLETE         gsymbol->language = language_chill; */
-  /* OBSOLETE         gsymbol->language_specific.chill_specific.demangled_name = */
-  /* OBSOLETE           obsavestring (demangled, strlen (demangled), obstack); */
-  /* OBSOLETE         xfree (demangled); */
-  /* OBSOLETE       } */
-  /* OBSOLETE     else */
-  /* OBSOLETE       { */
-  /* OBSOLETE         gsymbol->language_specific.chill_specific.demangled_name = NULL; */
-  /* OBSOLETE       } */
-  /* OBSOLETE   } */
-#endif
+
+  if (objfile->demangled_names_hash == NULL)
+    create_demangled_names_hash (objfile);
+
+  /* The stabs reader generally provides names that are not
+     NUL-terminated; most of the other readers don't do this, so we
+     can just use the given copy, unless we're in the Java case.  */
+  if (gsymbol->language == language_java)
+    {
+      char *alloc_name;
+      lookup_len = len + JAVA_PREFIX_LEN;
+
+      alloc_name = alloca (lookup_len + 1);
+      memcpy (alloc_name, JAVA_PREFIX, JAVA_PREFIX_LEN);
+      memcpy (alloc_name + JAVA_PREFIX_LEN, linkage_name, len);
+      alloc_name[lookup_len] = '\0';
+
+      lookup_name = alloc_name;
+      linkage_name_copy = alloc_name + JAVA_PREFIX_LEN;
+    }
+  else if (linkage_name[len] != '\0')
+    {
+      char *alloc_name;
+      lookup_len = len;
+
+      alloc_name = alloca (lookup_len + 1);
+      memcpy (alloc_name, linkage_name, len);
+      alloc_name[lookup_len] = '\0';
+
+      lookup_name = alloc_name;
+      linkage_name_copy = alloc_name;
+    }
+  else
+    {
+      lookup_len = len;
+      lookup_name = linkage_name;
+      linkage_name_copy = linkage_name;
+    }
+
+  entry.mangled = (char *) lookup_name;
+  slot = ((struct demangled_name_entry **)
+         htab_find_slot (objfile->demangled_names_hash,
+                         &entry, INSERT));
+
+  /* If this name is not in the hash table, add it.  */
+  if (*slot == NULL)
+    {
+      char *demangled_name = symbol_find_demangled_name (gsymbol,
+                                                        linkage_name_copy);
+      int demangled_len = demangled_name ? strlen (demangled_name) : 0;
+
+      /* Suppose we have demangled_name==NULL, copy_name==0, and
+        lookup_name==linkage_name.  In this case, we already have the
+        mangled name saved, and we don't have a demangled name.  So,
+        you might think we could save a little space by not recording
+        this in the hash table at all.
+        
+        It turns out that it is actually important to still save such
+        an entry in the hash table, because storing this name gives
+        us better backache hit rates for partial symbols.  */
+      if (!copy_name && lookup_name == linkage_name)
+       {
+         *slot = obstack_alloc (&objfile->objfile_obstack,
+                                offsetof (struct demangled_name_entry,
+                                          demangled)
+                                + demangled_len + 1);
+         (*slot)->mangled = (char *) lookup_name;
+       }
+      else
+       {
+         /* If we must copy the mangled name, put it directly after
+            the demangled name so we can have a single
+            allocation.  */
+         *slot = obstack_alloc (&objfile->objfile_obstack,
+                                offsetof (struct demangled_name_entry,
+                                          demangled)
+                                + lookup_len + demangled_len + 2);
+         (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
+         strcpy ((*slot)->mangled, lookup_name);
+       }
+
+      if (demangled_name != NULL)
+       {
+         strcpy ((*slot)->demangled, demangled_name);
+         xfree (demangled_name);
+       }
+      else
+       (*slot)->demangled[0] = '\0';
+    }
+
+  gsymbol->name = (*slot)->mangled + lookup_len - len;
+  if ((*slot)->demangled[0] != '\0')
+    gsymbol->language_specific.cplus_specific.demangled_name
+      = (*slot)->demangled;
+  else
+    gsymbol->language_specific.cplus_specific.demangled_name = NULL;
+}
+
+/* Return the source code name of a symbol.  In languages where
+   demangling is necessary, this is the demangled name.  */
+
+char *
+symbol_natural_name (const struct general_symbol_info *gsymbol)
+{
+  switch (gsymbol->language)
+    {
+    case language_cplus:
+    case language_java:
+    case language_objc:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      break;
+    case language_ada:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      else
+       return ada_decode_symbol (gsymbol);
+      break;
+    default:
+      break;
+    }
+  return gsymbol->name;
 }
 
+/* Return the demangled name for a symbol based on the language for
+   that symbol.  If no demangled name exists, return NULL. */
+char *
+symbol_demangled_name (const struct general_symbol_info *gsymbol)
+{
+  switch (gsymbol->language)
+    {
+    case language_cplus:
+    case language_java:
+    case language_objc:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      break;
+    case language_ada:
+      if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
+       return gsymbol->language_specific.cplus_specific.demangled_name;
+      else
+       return ada_decode_symbol (gsymbol);
+      break;
+    default:
+      break;
+    }
+  return NULL;
+}
+
+/* Return the search name of a symbol---generally the demangled or
+   linkage name of the symbol, depending on how it will be searched for.
+   If there is no distinct demangled name, then returns the same value
+   (same pointer) as SYMBOL_LINKAGE_NAME. */
+char *
+symbol_search_name (const struct general_symbol_info *gsymbol)
+{
+  if (gsymbol->language == language_ada)
+    return gsymbol->name;
+  else
+    return symbol_natural_name (gsymbol);
+}
 
+/* Initialize the structure fields to zero values.  */
+void
+init_sal (struct symtab_and_line *sal)
+{
+  sal->pspace = NULL;
+  sal->symtab = 0;
+  sal->section = 0;
+  sal->line = 0;
+  sal->pc = 0;
+  sal->end = 0;
+  sal->explicit_pc = 0;
+  sal->explicit_line = 0;
+}
 \f
 
+/* Return 1 if the two sections are the same, or if they could
+   plausibly be copies of each other, one in an original object
+   file and another in a separated debug file.  */
 
-/* Find which partial symtab on contains PC and SECTION.  Return 0 if none.  */
+int
+matching_obj_sections (struct obj_section *obj_first,
+                      struct obj_section *obj_second)
+{
+  asection *first = obj_first? obj_first->the_bfd_section : NULL;
+  asection *second = obj_second? obj_second->the_bfd_section : NULL;
+  struct objfile *obj;
+
+  /* If they're the same section, then they match.  */
+  if (first == second)
+    return 1;
+
+  /* If either is NULL, give up.  */
+  if (first == NULL || second == NULL)
+    return 0;
+
+  /* This doesn't apply to absolute symbols.  */
+  if (first->owner == NULL || second->owner == NULL)
+    return 0;
+
+  /* If they're in the same object file, they must be different sections.  */
+  if (first->owner == second->owner)
+    return 0;
 
+  /* Check whether the two sections are potentially corresponding.  They must
+     have the same size, address, and name.  We can't compare section indexes,
+     which would be more reliable, because some sections may have been
+     stripped.  */
+  if (bfd_get_section_size (first) != bfd_get_section_size (second))
+    return 0;
+
+  /* In-memory addresses may start at a different offset, relativize them.  */
+  if (bfd_get_section_vma (first->owner, first)
+      - bfd_get_start_address (first->owner)
+      != bfd_get_section_vma (second->owner, second)
+        - bfd_get_start_address (second->owner))
+    return 0;
+
+  if (bfd_get_section_name (first->owner, first) == NULL
+      || bfd_get_section_name (second->owner, second) == NULL
+      || strcmp (bfd_get_section_name (first->owner, first),
+                bfd_get_section_name (second->owner, second)) != 0)
+    return 0;
+
+  /* Otherwise check that they are in corresponding objfiles.  */
+
+  ALL_OBJFILES (obj)
+    if (obj->obfd == first->owner)
+      break;
+  gdb_assert (obj != NULL);
+
+  if (obj->separate_debug_objfile != NULL
+      && obj->separate_debug_objfile->obfd == second->owner)
+    return 1;
+  if (obj->separate_debug_objfile_backlink != NULL
+      && obj->separate_debug_objfile_backlink->obfd == second->owner)
+    return 1;
+
+  return 0;
+}
+
+/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
+   We may find a different psymtab than PST.  See FIND_PC_SECT_PSYMTAB.  */
+
+static struct partial_symtab *
+find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section,
+                            struct partial_symtab *pst,
+                            struct minimal_symbol *msymbol)
+{
+  struct objfile *objfile = pst->objfile;
+  struct partial_symtab *tpst;
+  struct partial_symtab *best_pst = pst;
+  CORE_ADDR best_addr = pst->textlow;
+
+  /* An objfile that has its functions reordered might have
+     many partial symbol tables containing the PC, but
+     we want the partial symbol table that contains the
+     function containing the PC.  */
+  if (!(objfile->flags & OBJF_REORDERED) &&
+      section == 0)    /* can't validate section this way */
+    return pst;
+
+  if (msymbol == NULL)
+    return (pst);
+
+  /* The code range of partial symtabs sometimes overlap, so, in
+     the loop below, we need to check all partial symtabs and
+     find the one that fits better for the given PC address. We
+     select the partial symtab that contains a symbol whose
+     address is closest to the PC address.  By closest we mean
+     that find_pc_sect_symbol returns the symbol with address
+     that is closest and still less than the given PC.  */
+  for (tpst = pst; tpst != NULL; tpst = tpst->next)
+    {
+      if (pc >= tpst->textlow && pc < tpst->texthigh)
+       {
+         struct partial_symbol *p;
+         CORE_ADDR this_addr;
+
+         /* NOTE: This assumes that every psymbol has a
+            corresponding msymbol, which is not necessarily
+            true; the debug info might be much richer than the
+            object's symbol table.  */
+         p = find_pc_sect_psymbol (tpst, pc, section);
+         if (p != NULL
+             && SYMBOL_VALUE_ADDRESS (p)
+             == SYMBOL_VALUE_ADDRESS (msymbol))
+           return tpst;
+
+         /* Also accept the textlow value of a psymtab as a
+            "symbol", to provide some support for partial
+            symbol tables with line information but no debug
+            symbols (e.g. those produced by an assembler).  */
+         if (p != NULL)
+           this_addr = SYMBOL_VALUE_ADDRESS (p);
+         else
+           this_addr = tpst->textlow;
+
+         /* Check whether it is closer than our current
+            BEST_ADDR.  Since this symbol address is
+            necessarily lower or equal to PC, the symbol closer
+            to PC is the symbol which address is the highest.
+            This way we return the psymtab which contains such
+            best match symbol. This can help in cases where the
+            symbol information/debuginfo is not complete, like
+            for instance on IRIX6 with gcc, where no debug info
+            is emitted for statics. (See also the nodebug.exp
+            testcase.) */
+         if (this_addr > best_addr)
+           {
+             best_addr = this_addr;
+             best_pst = tpst;
+           }
+       }
+    }
+  return best_pst;
+}
+
+/* Find which partial symtab contains PC and SECTION.  Return 0 if
+   none.  We return the psymtab that contains a symbol whose address
+   exactly matches PC, or, if we cannot find an exact match, the
+   psymtab that contains a symbol whose address is closest to PC.  */
 struct partial_symtab *
-find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
+find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
 {
-  register struct partial_symtab *pst;
-  register struct objfile *objfile;
+  struct objfile *objfile;
   struct minimal_symbol *msymbol;
 
   /* If we know that this is not a text address, return failure.  This is
@@ -478,50 +920,80 @@ find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
      not include the data ranges.  */
   msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
   if (msymbol
-      && (msymbol->type == mst_data
-         || msymbol->type == mst_bss
-         || msymbol->type == mst_abs
-         || msymbol->type == mst_file_data
-         || msymbol->type == mst_file_bss))
+      && (MSYMBOL_TYPE (msymbol) == mst_data
+         || MSYMBOL_TYPE (msymbol) == mst_bss
+         || MSYMBOL_TYPE (msymbol) == mst_abs
+         || MSYMBOL_TYPE (msymbol) == mst_file_data
+         || MSYMBOL_TYPE (msymbol) == mst_file_bss))
     return NULL;
 
-  ALL_PSYMTABS (objfile, pst)
-  {
-    if (pc >= pst->textlow && pc < pst->texthigh)
-      {
-       struct partial_symtab *tpst;
-
-       /* An objfile that has its functions reordered might have
-          many partial symbol tables containing the PC, but
-          we want the partial symbol table that contains the
-          function containing the PC.  */
-       if (!(objfile->flags & OBJF_REORDERED) &&
-           section == 0)       /* can't validate section this way */
-         return (pst);
+  /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
+     than the later used TEXTLOW/TEXTHIGH one.  */
 
-       if (msymbol == NULL)
-         return (pst);
+  ALL_OBJFILES (objfile)
+    if (objfile->psymtabs_addrmap != NULL)
+      {
+       struct partial_symtab *pst;
 
-       for (tpst = pst; tpst != NULL; tpst = tpst->next)
+       pst = addrmap_find (objfile->psymtabs_addrmap, pc);
+       if (pst != NULL)
          {
-           if (pc >= tpst->textlow && pc < tpst->texthigh)
+           /* FIXME: addrmaps currently do not handle overlayed sections,
+              so fall back to the non-addrmap case if we're debugging
+              overlays and the addrmap returned the wrong section.  */
+           if (overlay_debugging && msymbol && section)
              {
                struct partial_symbol *p;
-
-               p = find_pc_sect_psymbol (tpst, pc, section);
-               if (p != NULL
-                   && SYMBOL_VALUE_ADDRESS (p)
-                   == SYMBOL_VALUE_ADDRESS (msymbol))
-                 return (tpst);
+               /* NOTE: This assumes that every psymbol has a
+                  corresponding msymbol, which is not necessarily
+                  true; the debug info might be much richer than the
+                  object's symbol table.  */
+               p = find_pc_sect_psymbol (pst, pc, section);
+               if (!p
+                   || SYMBOL_VALUE_ADDRESS (p)
+                      != SYMBOL_VALUE_ADDRESS (msymbol))
+                 continue;
              }
+
+           /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
+              PSYMTABS_ADDRMAP we used has already the best 1-byte
+              granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
+              a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
+              overlap.  */
+
+           return pst;
          }
-       return (pst);
       }
-  }
-  return (NULL);
+
+  /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
+     which still have no corresponding full SYMTABs read.  But it is not
+     present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
+     so far.  */
+
+  ALL_OBJFILES (objfile)
+    {
+      struct partial_symtab *pst;
+
+      /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
+        its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
+        debug info type in single OBJFILE.  */
+
+      ALL_OBJFILE_PSYMTABS (objfile, pst)
+       if (pc >= pst->textlow && pc < pst->texthigh)
+         {
+           struct partial_symtab *best_pst;
+
+           best_pst = find_pc_sect_psymtab_closer (pc, section, pst,
+                                                   msymbol);
+           if (best_pst != NULL)
+             return best_pst;
+         }
+    }
+
+  return NULL;
 }
 
-/* Find which partial symtab contains PC.  Return 0 if none. 
+/* Find which partial symtab contains PC.  Return 0 if none.
    Backward compatibility, no section */
 
 struct partial_symtab *
@@ -530,12 +1002,12 @@ find_pc_psymtab (CORE_ADDR pc)
   return find_pc_sect_psymtab (pc, find_pc_mapped_section (pc));
 }
 
-/* Find which partial symbol within a psymtab matches PC and SECTION.  
+/* Find which partial symbol within a psymtab matches PC and SECTION.
    Return 0 if none.  Check all psymtabs if PSYMTAB is 0.  */
 
 struct partial_symbol *
 find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
-                     asection *section)
+                     struct obj_section *section)
 {
   struct partial_symbol *best = NULL, *p, **pp;
   CORE_ADDR best_pc;
@@ -557,7 +1029,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
        pp++)
     {
       p = *pp;
-      if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
          && SYMBOL_CLASS (p) == LOC_BLOCK
          && pc >= SYMBOL_VALUE_ADDRESS (p)
          && (SYMBOL_VALUE_ADDRESS (p) > best_pc
@@ -567,7 +1039,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
          if (section)          /* match on a specific section */
            {
              fixup_psymbol_section (p, psymtab->objfile);
-             if (SYMBOL_BFD_SECTION (p) != section)
+             if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
                continue;
            }
          best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -581,7 +1053,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
        pp++)
     {
       p = *pp;
-      if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
          && SYMBOL_CLASS (p) == LOC_BLOCK
          && pc >= SYMBOL_VALUE_ADDRESS (p)
          && (SYMBOL_VALUE_ADDRESS (p) > best_pc
@@ -591,7 +1063,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
          if (section)          /* match on a specific section */
            {
              fixup_psymbol_section (p, psymtab->objfile);
-             if (SYMBOL_BFD_SECTION (p) != section)
+             if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
                continue;
            }
          best_pc = SYMBOL_VALUE_ADDRESS (p);
@@ -602,7 +1074,7 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
   return best;
 }
 
-/* Find which partial symbol within a psymtab matches PC.  Return 0 if none.  
+/* Find which partial symbol within a psymtab matches PC.  Return 0 if none.
    Check all psymtabs if PSYMTAB is 0.  Backwards compatibility, no section. */
 
 struct partial_symbol *
@@ -615,28 +1087,115 @@ find_pc_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc)
    out of the minimal symbols and stash that in the debug symbol.  */
 
 static void
-fixup_section (struct general_symbol_info *ginfo, struct objfile *objfile)
+fixup_section (struct general_symbol_info *ginfo,
+              CORE_ADDR addr, struct objfile *objfile)
 {
   struct minimal_symbol *msym;
-  msym = lookup_minimal_symbol (ginfo->name, NULL, objfile);
 
+  /* First, check whether a minimal symbol with the same name exists
+     and points to the same address.  The address check is required
+     e.g. on PowerPC64, where the minimal symbol for a function will
+     point to the function descriptor, while the debug symbol will
+     point to the actual function code.  */
+  msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->name, objfile);
   if (msym)
     {
-      ginfo->bfd_section = SYMBOL_BFD_SECTION (msym);
+      ginfo->obj_section = SYMBOL_OBJ_SECTION (msym);
       ginfo->section = SYMBOL_SECTION (msym);
     }
+  else
+    {
+      /* Static, function-local variables do appear in the linker
+        (minimal) symbols, but are frequently given names that won't
+        be found via lookup_minimal_symbol().  E.g., it has been
+        observed in frv-uclinux (ELF) executables that a static,
+        function-local variable named "foo" might appear in the
+        linker symbols as "foo.6" or "foo.3".  Thus, there is no
+        point in attempting to extend the lookup-by-name mechanism to
+        handle this case due to the fact that there can be multiple
+        names.
+
+        So, instead, search the section table when lookup by name has
+        failed.  The ``addr'' and ``endaddr'' fields may have already
+        been relocated.  If so, the relocation offset (i.e. the
+        ANOFFSET value) needs to be subtracted from these values when
+        performing the comparison.  We unconditionally subtract it,
+        because, when no relocation has been performed, the ANOFFSET
+        value will simply be zero.
+
+        The address of the symbol whose section we're fixing up HAS
+        NOT BEEN adjusted (relocated) yet.  It can't have been since
+        the section isn't yet known and knowing the section is
+        necessary in order to add the correct relocation value.  In
+        other words, we wouldn't even be in this function (attempting
+        to compute the section) if it were already known.
+
+        Note that it is possible to search the minimal symbols
+        (subtracting the relocation value if necessary) to find the
+        matching minimal symbol, but this is overkill and much less
+        efficient.  It is not necessary to find the matching minimal
+        symbol, only its section.
+
+        Note that this technique (of doing a section table search)
+        can fail when unrelocated section addresses overlap.  For
+        this reason, we still attempt a lookup by name prior to doing
+        a search of the section table.  */
+
+      struct obj_section *s;
+      ALL_OBJFILE_OSECTIONS (objfile, s)
+       {
+         int idx = s->the_bfd_section->index;
+         CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx);
+
+         if (obj_section_addr (s) - offset <= addr
+             && addr < obj_section_endaddr (s) - offset)
+           {
+             ginfo->obj_section = s;
+             ginfo->section = idx;
+             return;
+           }
+       }
+    }
 }
 
 struct symbol *
 fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
 {
+  CORE_ADDR addr;
+
   if (!sym)
     return NULL;
 
-  if (SYMBOL_BFD_SECTION (sym))
+  if (SYMBOL_OBJ_SECTION (sym))
     return sym;
 
-  fixup_section (&sym->ginfo, objfile);
+  /* We either have an OBJFILE, or we can get at it from the sym's
+     symtab.  Anything else is a bug.  */
+  gdb_assert (objfile || SYMBOL_SYMTAB (sym));
+
+  if (objfile == NULL)
+    objfile = SYMBOL_SYMTAB (sym)->objfile;
+
+  /* We should have an objfile by now.  */
+  gdb_assert (objfile);
+
+  switch (SYMBOL_CLASS (sym))
+    {
+    case LOC_STATIC:
+    case LOC_LABEL:
+      addr = SYMBOL_VALUE_ADDRESS (sym);
+      break;
+    case LOC_BLOCK:
+      addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+      break;
+
+    default:
+      /* Nothing else will be listed in the minsyms -- no use looking
+        it up.  */
+      return sym;
+    }
+
+  fixup_section (&sym->ginfo, addr, objfile);
 
   return sym;
 }
@@ -644,25 +1203,40 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
 struct partial_symbol *
 fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
 {
+  CORE_ADDR addr;
+
   if (!psym)
     return NULL;
 
-  if (SYMBOL_BFD_SECTION (psym))
+  if (SYMBOL_OBJ_SECTION (psym))
     return psym;
 
-  fixup_section (&psym->ginfo, objfile);
+  gdb_assert (objfile);
+
+  switch (SYMBOL_CLASS (psym))
+    {
+    case LOC_STATIC:
+    case LOC_LABEL:
+    case LOC_BLOCK:
+      addr = SYMBOL_VALUE_ADDRESS (psym);
+      break;
+    default:
+      /* Nothing else will be listed in the minsyms -- no use looking
+        it up.  */
+      return psym;
+    }
+
+  fixup_section (&psym->ginfo, addr, objfile);
 
   return psym;
 }
 
 /* Find the definition for a specified symbol name NAME
-   in namespace NAMESPACE, visible from lexical block BLOCK.
+   in domain DOMAIN, visible from lexical block BLOCK.
    Returns the struct symbol pointer, or zero if no symbol is found.
-   If SYMTAB is non-NULL, store the symbol table in which the
-   symbol was found there, or NULL if not found.
    C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
    NAME is a field of the current implied argument `this'.  If so set
-   *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. 
+   *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
    BLOCK_FOUND is set to the block in which NAME is found (in the case of
    a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
 
@@ -670,35 +1244,57 @@ fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
    attractive to put in some QUIT's (though I'm not really sure
    whether it can run long enough to be really important).  But there
    are a few calls for which it would appear to be bad news to quit
-   out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and
-   nindy_frame_chain_valid in nindy-tdep.c.  (Note that there is C++
-   code below which can error(), but that probably doesn't affect
-   these calls since they are looking for a known variable and thus
-   can probably assume it will never hit the C++ code).  */
+   out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c.  (Note
+   that there is C++ code below which can error(), but that probably
+   doesn't affect these calls since they are looking for a known
+   variable and thus can probably assume it will never hit the C++
+   code).  */
 
 struct symbol *
-lookup_symbol (const char *name, const struct block *block,
-              const namespace_enum namespace, int *is_a_field_of_this,
-              struct symtab **symtab)
+lookup_symbol_in_language (const char *name, const struct block *block,
+                          const domain_enum domain, enum language lang,
+                          int *is_a_field_of_this)
 {
   char *demangled_name = NULL;
   const char *modified_name = NULL;
   const char *mangled_name = NULL;
-  int needtofreename = 0;
   struct symbol *returnval;
+  struct cleanup *cleanup = make_cleanup (null_cleanup, 0);
 
   modified_name = name;
 
-  /* If we are using C++ language, demangle the name before doing a lookup, so
+  /* If we are using C++ or Java, demangle the name before doing a lookup, so
      we can always binary search. */
-  if (current_language->la_language == language_cplus)
+  if (lang == language_cplus)
     {
       demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
       if (demangled_name)
        {
          mangled_name = name;
          modified_name = demangled_name;
-         needtofreename = 1;
+         make_cleanup (xfree, demangled_name);
+       }
+      else
+       {
+         /* If we were given a non-mangled name, canonicalize it
+            according to the language (so far only for C++).  */
+         demangled_name = cp_canonicalize_string (name);
+         if (demangled_name)
+           {
+             modified_name = demangled_name;
+             make_cleanup (xfree, demangled_name);
+           }
+       }
+    }
+  else if (lang == language_java)
+    {
+      demangled_name = cplus_demangle (name,
+                                      DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
+      if (demangled_name)
+       {
+         mangled_name = name;
+         modified_name = demangled_name;
+         make_cleanup (xfree, demangled_name);
        }
     }
 
@@ -716,389 +1312,460 @@ lookup_symbol (const char *name, const struct block *block,
     }
 
   returnval = lookup_symbol_aux (modified_name, mangled_name, block,
-                                namespace, is_a_field_of_this, symtab);
-  if (needtofreename)
-    xfree (demangled_name);
+                                domain, lang, is_a_field_of_this);
+  do_cleanups (cleanup);
 
-  return returnval;     
+  return returnval;
 }
 
+/* Behave like lookup_symbol_in_language, but performed with the
+   current language.  */
+
+struct symbol *
+lookup_symbol (const char *name, const struct block *block,
+              domain_enum domain, int *is_a_field_of_this)
+{
+  return lookup_symbol_in_language (name, block, domain,
+                                   current_language->la_language,
+                                   is_a_field_of_this);
+}
+
+/* Behave like lookup_symbol except that NAME is the natural name
+   of the symbol that we're looking for and, if LINKAGE_NAME is
+   non-NULL, ensure that the symbol's linkage name matches as
+   well.  */
+
 static struct symbol *
-lookup_symbol_aux (const char *name, const char *mangled_name,
-                  const struct block *block, const namespace_enum namespace,
-                  int *is_a_field_of_this, struct symtab **symtab)
+lookup_symbol_aux (const char *name, const char *linkage_name,
+                  const struct block *block, const domain_enum domain,
+                  enum language language, int *is_a_field_of_this)
 {
-  register struct symbol *sym;
-  register struct symtab *s = NULL;
-  register struct partial_symtab *ps;
-  register struct blockvector *bv;
-  register struct objfile *objfile = NULL;
-  register struct block *b;
-  register struct minimal_symbol *msymbol;
+  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.  */
+  if (is_a_field_of_this != NULL)
+    *is_a_field_of_this = 0;
+
+  /* Search specified block and its superiors.  Don't search
+     STATIC_BLOCK or GLOBAL_BLOCK.  */
+
+  sym = lookup_symbol_aux_local (name, linkage_name, block, domain);
+  if (sym != NULL)
+    return sym;
 
+  /* If requested to do so by the caller and if appropriate for LANGUAGE,
+     check to see if NAME is a field of `this'. */
 
-  /* Search specified block and its superiors.  */
+  langdef = language_def (language);
 
-  while (block != 0)
+  if (langdef->la_name_of_this != NULL && is_a_field_of_this != NULL
+      && block != NULL)
     {
-      sym = lookup_block_symbol (block, name, mangled_name, namespace);
+      struct symbol *sym = NULL;
+      /* 'this' is only defined in the function's block, so find the
+        enclosing function block.  */
+      for (; block && !BLOCK_FUNCTION (block);
+          block = BLOCK_SUPERBLOCK (block));
+
+      if (block && !dict_empty (BLOCK_DICT (block)))
+       sym = lookup_block_symbol (block, langdef->la_name_of_this,
+                                  NULL, VAR_DOMAIN);
       if (sym)
        {
-         block_found = block;
-         if (symtab != NULL)
+         struct type *t = sym->type;
+
+         /* I'm not really sure that type of this can ever
+            be typedefed; just be safe.  */
+         CHECK_TYPEDEF (t);
+         if (TYPE_CODE (t) == TYPE_CODE_PTR
+             || TYPE_CODE (t) == TYPE_CODE_REF)
+           t = TYPE_TARGET_TYPE (t);
+
+         if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+             && TYPE_CODE (t) != TYPE_CODE_UNION)
+           error (_("Internal error: `%s' is not an aggregate"),
+                  langdef->la_name_of_this);
+
+         if (check_field (t, name))
            {
-             /* Search the list of symtabs for one which contains the
-                address of the start of this block.  */
-             ALL_SYMTABS (objfile, s)
-             {
-               bv = BLOCKVECTOR (s);
-               b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-               if (BLOCK_START (b) <= BLOCK_START (block)
-                   && BLOCK_END (b) > BLOCK_START (block))
-                 goto found;
-             }
-           found:
-             *symtab = s;
+             *is_a_field_of_this = 1;
+             return NULL;
            }
-
-         return fixup_symbol_section (sym, objfile);
        }
-      block = BLOCK_SUPERBLOCK (block);
     }
 
-  /* FIXME: this code is never executed--block is always NULL at this
-     point.  What is it trying to do, anyway?  We already should have
-     checked the STATIC_BLOCK above (it is the superblock of top-level
-     blocks).  Why is VAR_NAMESPACE special-cased?  */
-  /* Don't need to mess with the psymtabs; if we have a block,
-     that file is read in.  If we don't, then we deal later with
-     all the psymtab stuff that needs checking.  */
-  /* Note (RT): The following never-executed code looks unnecessary to me also.
-   * If we change the code to use the original (passed-in)
-   * value of 'block', we could cause it to execute, but then what
-   * would it do? The STATIC_BLOCK of the symtab containing the passed-in
-   * 'block' was already searched by the above code. And the STATIC_BLOCK's
-   * of *other* symtabs (those files not containing 'block' lexically)
-   * should not contain 'block' address-wise. So we wouldn't expect this
-   * code to find any 'sym''s that were not found above. I vote for 
-   * deleting the following paragraph of code.
-   */
-  if (namespace == VAR_NAMESPACE && block != NULL)
-    {
-      struct block *b;
-      /* Find the right symtab.  */
-      ALL_SYMTABS (objfile, s)
-      {
-       bv = BLOCKVECTOR (s);
-       b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-       if (BLOCK_START (b) <= BLOCK_START (block)
-           && BLOCK_END (b) > BLOCK_START (block))
-         {
-           sym = lookup_block_symbol (b, name, mangled_name, VAR_NAMESPACE);
-           if (sym)
-             {
-               block_found = b;
-               if (symtab != NULL)
-                 *symtab = s;
-               return fixup_symbol_section (sym, objfile);
-             }
-         }
-      }
-    }
+  /* Now do whatever is appropriate for LANGUAGE to look
+     up static and global variables.  */
 
+  sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, domain);
+  if (sym != NULL)
+    return sym;
 
-  /* C++: If requested to do so by the caller, 
-     check to see if NAME is a field of `this'. */
-  if (is_a_field_of_this)
+  /* Now search all static file-level symbols.  Not strictly correct,
+     but more useful than an error.  Do the symtabs first, then check
+     the psymtabs.  If a psymtab indicates the existence of the
+     desired name as a file-level static, then do psymtab-to-symtab
+     conversion on the fly and return the found symbol. */
+
+  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, linkage_name, domain);
+  if (sym != NULL)
+    return sym;
+
+  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name, domain);
+  if (sym != NULL)
+    return sym;
+
+  return NULL;
+}
+
+/* Check to see if the symbol is defined in BLOCK or its superiors.
+   Don't search STATIC_BLOCK or GLOBAL_BLOCK.  */
+
+static struct symbol *
+lookup_symbol_aux_local (const char *name, const char *linkage_name,
+                        const struct block *block,
+                        const domain_enum domain)
+{
+  struct symbol *sym;
+  const struct block *static_block = block_static_block (block);
+
+  /* Check if either no block is specified or it's a global block.  */
+
+  if (static_block == NULL)
+    return NULL;
+
+  while (block != static_block)
     {
-      struct value *v = value_of_this (0);
+      sym = lookup_symbol_aux_block (name, linkage_name, block, domain);
+      if (sym != NULL)
+       return sym;
 
-      *is_a_field_of_this = 0;
-      if (v && check_field (v, name))
-       {
-         *is_a_field_of_this = 1;
-         if (symtab != NULL)
-           *symtab = NULL;
-         return NULL;
-       }
+      if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block))
+       break;
+      block = BLOCK_SUPERBLOCK (block);
     }
 
-  /* Now search all global blocks.  Do the symtab's first, then
-     check the psymtab's. If a psymtab indicates the existence
-     of the desired name as a global, then do psymtab-to-symtab
-     conversion on the fly and return the found symbol. */
+  /* We've reached the edge of the function without finding a result.  */
 
-  ALL_SYMTABS (objfile, s)
-  {
-    bv = BLOCKVECTOR (s);
-    block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    sym = lookup_block_symbol (block, name, mangled_name, namespace);
-    if (sym)
+  return NULL;
+}
+
+/* Look up OBJFILE to BLOCK.  */
+
+static struct objfile *
+lookup_objfile_from_block (const struct block *block)
+{
+  struct objfile *obj;
+  struct symtab *s;
+
+  if (block == NULL)
+    return NULL;
+
+  block = block_global_block (block);
+  /* Go through SYMTABS.  */
+  ALL_SYMTABS (obj, s)
+    if (block == BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK))
       {
-       block_found = block;
-       if (symtab != NULL)
-         *symtab = s;
-       return fixup_symbol_section (sym, objfile);
+       if (obj->separate_debug_objfile_backlink)
+         obj = obj->separate_debug_objfile_backlink;
+
+       return obj;
       }
-  }
 
-#ifndef HPUXHPPA
+  return NULL;
+}
+
+/* Look up a symbol in a block; if found, fixup the symbol, and set
+   block_found appropriately.  */
 
-  /* Check for the possibility of the symbol being a function or
-     a mangled variable that is stored in one of the minimal symbol tables.
-     Eventually, all global symbols might be resolved in this way.  */
+struct symbol *
+lookup_symbol_aux_block (const char *name, const char *linkage_name,
+                        const struct block *block,
+                        const domain_enum domain)
+{
+  struct symbol *sym;
 
-  if (namespace == VAR_NAMESPACE)
+  sym = lookup_block_symbol (block, name, linkage_name, domain);
+  if (sym)
     {
-      msymbol = lookup_minimal_symbol (name, NULL, NULL);
-      if (msymbol != NULL)
-       {
-         s = find_pc_sect_symtab (SYMBOL_VALUE_ADDRESS (msymbol),
-                                  SYMBOL_BFD_SECTION (msymbol));
-         if (s != NULL)
-           {
-             /* This is a function which has a symtab for its address.  */
-             bv = BLOCKVECTOR (s);
-             block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-             sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
-                                        mangled_name, namespace);
-             /* We kept static functions in minimal symbol table as well as
-                in static scope. We want to find them in the symbol table. */
-             if (!sym)
-               {
-                 block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-                 sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
-                                            mangled_name, namespace);
-               }
+      block_found = block;
+      return fixup_symbol_section (sym, NULL);
+    }
 
-             /* sym == 0 if symbol was found in the minimal symbol table
-                but not in the symtab.
-                Return 0 to use the msymbol definition of "foo_".
+  return NULL;
+}
 
-                This happens for Fortran  "foo_" symbols,
-                which are "foo" in the symtab.
+/* Check all global symbols in OBJFILE in symtabs and
+   psymtabs.  */
 
-                This can also happen if "asm" is used to make a
-                regular symbol but not a debugging symbol, e.g.
-                asm(".globl _main");
-                asm("_main:");
-              */
+struct symbol *
+lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
+                                  const char *name,
+                                  const char *linkage_name,
+                                  const domain_enum domain)
+{
+  const struct objfile *objfile;
+  struct symbol *sym;
+  struct blockvector *bv;
+  const struct block *block;
+  struct symtab *s;
+  struct partial_symtab *ps;
 
-             if (symtab != NULL)
-               *symtab = s;
-             return fixup_symbol_section (sym, objfile);
-           }
-         else if (MSYMBOL_TYPE (msymbol) != mst_text
-                  && MSYMBOL_TYPE (msymbol) != mst_file_text
-                  && !STREQ (name, SYMBOL_NAME (msymbol)))
-           {
-             /* This is a mangled variable, look it up by its
-                mangled name.  */
-             return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name, block,
-                                       namespace, is_a_field_of_this, symtab);
-           }
-         /* There are no debug symbols for this file, or we are looking
-            for an unmangled variable.
-            Try to find a matching static symbol below. */
-       }
+  for (objfile = main_objfile;
+       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, linkage_name, domain);
+          if (sym)
+            {
+              block_found = block;
+              return fixup_symbol_section (sym, (struct objfile *)objfile);
+            }
+        }
+
+      /* Now go through psymtabs.  */
+      ALL_OBJFILE_PSYMTABS (objfile, ps)
+        {
+          if (!ps->readin
+              && lookup_partial_symbol (ps, name, linkage_name,
+                                        1, domain))
+            {
+              s = PSYMTAB_TO_SYMTAB (ps);
+              bv = BLOCKVECTOR (s);
+              block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+              sym = lookup_block_symbol (block, name, linkage_name, domain);
+              return fixup_symbol_section (sym, (struct objfile *)objfile);
+            }
+        }
     }
 
-#endif
+  return NULL;
+}
 
-  ALL_PSYMTABS (objfile, ps)
-  {
-    if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
-      {
-       s = PSYMTAB_TO_SYMTAB (ps);
-       bv = BLOCKVECTOR (s);
-       block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-       sym = lookup_block_symbol (block, name, mangled_name, namespace);
-       if (!sym)
-         {
-           /* This shouldn't be necessary, but as a last resort
-            * try looking in the statics even though the psymtab
-            * claimed the symbol was global. It's possible that
-            * the psymtab gets it wrong in some cases.
-            */
-           block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-           sym = lookup_block_symbol (block, name, mangled_name, namespace);
-           if (!sym)
-             error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
-                    name, ps->filename, name, name);
-         }
-       if (symtab != NULL)
-         *symtab = s;
-       return fixup_symbol_section (sym, objfile);
-      }
-  }
+/* Check to see if the symbol is defined in one of the symtabs.
+   BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
+   depending on whether or not we want to search global symbols or
+   static symbols.  */
 
-  /* Now search all static file-level symbols.
-     Not strictly correct, but more useful than an error.
-     Do the symtabs first, then check the psymtabs.
-     If a psymtab indicates the existence
-     of the desired name as a file-level static, then do psymtab-to-symtab
-     conversion on the fly and return the found symbol. */
+static struct symbol *
+lookup_symbol_aux_symtabs (int block_index,
+                          const char *name, const char *linkage_name,
+                          const domain_enum domain)
+{
+  struct symbol *sym;
+  struct objfile *objfile;
+  struct blockvector *bv;
+  const struct block *block;
+  struct symtab *s;
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     bv = BLOCKVECTOR (s);
-    block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    sym = lookup_block_symbol (block, name, mangled_name, namespace);
+    block = BLOCKVECTOR_BLOCK (bv, block_index);
+    sym = lookup_block_symbol (block, name, linkage_name, domain);
     if (sym)
       {
        block_found = block;
-       if (symtab != NULL)
-         *symtab = s;
        return fixup_symbol_section (sym, objfile);
       }
   }
 
+  return NULL;
+}
+
+/* Check to see if the symbol is defined in one of the partial
+   symtabs.  BLOCK_INDEX should be either GLOBAL_BLOCK or
+   STATIC_BLOCK, depending on whether or not we want to search global
+   symbols or static symbols.  */
+
+static struct symbol *
+lookup_symbol_aux_psymtabs (int block_index, const char *name,
+                           const char *linkage_name,
+                           const domain_enum domain)
+{
+  struct symbol *sym;
+  struct objfile *objfile;
+  struct blockvector *bv;
+  const struct block *block;
+  struct partial_symtab *ps;
+  struct symtab *s;
+  const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
+
   ALL_PSYMTABS (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
+    if (!ps->readin
+       && lookup_partial_symbol (ps, name, linkage_name,
+                                 psymtab_index, domain))
       {
        s = PSYMTAB_TO_SYMTAB (ps);
        bv = BLOCKVECTOR (s);
-       block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-       sym = lookup_block_symbol (block, name, mangled_name, namespace);
+       block = BLOCKVECTOR_BLOCK (bv, block_index);
+       sym = lookup_block_symbol (block, name, linkage_name, domain);
        if (!sym)
          {
-           /* This shouldn't be necessary, but as a last resort
-            * try looking in the globals even though the psymtab
-            * claimed the symbol was static. It's possible that
-            * the psymtab gets it wrong in some cases.
-            */
-           block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-           sym = lookup_block_symbol (block, name, mangled_name, namespace);
+           /* This shouldn't be necessary, but as a last resort try
+              looking in the statics even though the psymtab claimed
+              the symbol was global, or vice-versa. It's possible
+              that the psymtab gets it wrong in some cases.  */
+
+           /* FIXME: carlton/2002-09-30: Should we really do that?
+              If that happens, isn't it likely to be a GDB error, in
+              which case we should fix the GDB error rather than
+              silently dealing with it here?  So I'd vote for
+              removing the check for the symbol in the other
+              block.  */
+           block = BLOCKVECTOR_BLOCK (bv,
+                                      block_index == GLOBAL_BLOCK ?
+                                      STATIC_BLOCK : GLOBAL_BLOCK);
+           sym = lookup_block_symbol (block, name, linkage_name, domain);
            if (!sym)
-             error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
+             error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>)."),
+                    block_index == GLOBAL_BLOCK ? "global" : "static",
                     name, ps->filename, name, name);
          }
-       if (symtab != NULL)
-         *symtab = s;
        return fixup_symbol_section (sym, objfile);
       }
   }
 
-#ifdef HPUXHPPA
-
-  /* Check for the possibility of the symbol being a function or
-     a global variable that is stored in one of the minimal symbol tables.
-     The "minimal symbol table" is built from linker-supplied info.
-
-     RT: I moved this check to last, after the complete search of
-     the global (p)symtab's and static (p)symtab's. For HP-generated
-     symbol tables, this check was causing a premature exit from
-     lookup_symbol with NULL return, and thus messing up symbol lookups
-     of things like "c::f". It seems to me a check of the minimal
-     symbol table ought to be a last resort in any case. I'm vaguely
-     worried about the comment below which talks about FORTRAN routines "foo_"
-     though... is it saying we need to do the "minsym" check before
-     the static check in this case? 
-   */
+  return NULL;
+}
 
-  if (namespace == VAR_NAMESPACE)
-    {
-      msymbol = lookup_minimal_symbol (name, NULL, NULL);
-      if (msymbol != NULL)
-       {
-         /* OK, we found a minimal symbol in spite of not
-          * finding any symbol. There are various possible
-          * explanations for this. One possibility is the symbol
-          * exists in code not compiled -g. Another possibility
-          * is that the 'psymtab' isn't doing its job.
-          * A third possibility, related to #2, is that we were confused 
-          * by name-mangling. For instance, maybe the psymtab isn't
-          * doing its job because it only know about demangled
-          * names, but we were given a mangled name...
-          */
-
-         /* We first use the address in the msymbol to try to
-          * locate the appropriate symtab. Note that find_pc_symtab()
-          * has a side-effect of doing psymtab-to-symtab expansion,
-          * for the found symtab.
-          */
-         s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
-         if (s != NULL)
-           {
-             bv = BLOCKVECTOR (s);
-             block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-             sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
-                                        mangled_name, namespace);
-             /* We kept static functions in minimal symbol table as well as
-                in static scope. We want to find them in the symbol table. */
-             if (!sym)
-               {
-                 block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-                 sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
-                                            mangled_name, namespace);
-               }
-             /* If we found one, return it */
-             if (sym)
-               {
-                 if (symtab != NULL)
-                   *symtab = s;
-                 return sym;
-               }
+/* A default version of lookup_symbol_nonlocal for use by languages
+   that can't think of anything better to do.  This implements the C
+   lookup rules.  */
 
-             /* If we get here with sym == 0, the symbol was 
-                found in the minimal symbol table
-                but not in the symtab.
-                Fall through and return 0 to use the msymbol 
-                definition of "foo_".
-                (Note that outer code generally follows up a call
-                to this routine with a call to lookup_minimal_symbol(),
-                so a 0 return means we'll just flow into that other routine).
-
-                This happens for Fortran  "foo_" symbols,
-                which are "foo" in the symtab.
-
-                This can also happen if "asm" is used to make a
-                regular symbol but not a debugging symbol, e.g.
-                asm(".globl _main");
-                asm("_main:");
-              */
-           }
+struct symbol *
+basic_lookup_symbol_nonlocal (const char *name,
+                             const char *linkage_name,
+                             const struct block *block,
+                             const domain_enum domain)
+{
+  struct symbol *sym;
+
+  /* NOTE: carlton/2003-05-19: The comments below were written when
+     this (or what turned into this) was part of lookup_symbol_aux;
+     I'm much less worried about these questions now, since these
+     decisions have turned out well, but I leave these comments here
+     for posterity.  */
+
+  /* NOTE: carlton/2002-12-05: There is a question as to whether or
+     not it would be appropriate to search the current global block
+     here as well.  (That's what this code used to do before the
+     is_a_field_of_this check was moved up.)  On the one hand, it's
+     redundant with the lookup_symbol_aux_symtabs search that happens
+     next.  On the other hand, if decode_line_1 is passed an argument
+     like filename:var, then the user presumably wants 'var' to be
+     searched for in filename.  On the third hand, there shouldn't be
+     multiple global variables all of which are named 'var', and it's
+     not like decode_line_1 has ever restricted its search to only
+     global variables in a single filename.  All in all, only
+     searching the static block here seems best: it's correct and it's
+     cleanest.  */
+
+  /* NOTE: carlton/2002-12-05: There's also a possible performance
+     issue here: if you usually search for global symbols in the
+     current file, then it would be slightly better to search the
+     current global block before searching all the symtabs.  But there
+     are other factors that have a much greater effect on performance
+     than that one, so I don't think we should worry about that for
+     now.  */
+
+  sym = lookup_symbol_static (name, linkage_name, block, domain);
+  if (sym != NULL)
+    return sym;
 
-         /* If the lookup-by-address fails, try repeating the
-          * entire lookup process with the symbol name from
-          * the msymbol (if different from the original symbol name).
-          */
-         else if (MSYMBOL_TYPE (msymbol) != mst_text
-                  && MSYMBOL_TYPE (msymbol) != mst_file_text
-                  && !STREQ (name, SYMBOL_NAME (msymbol)))
-           {
-             return lookup_symbol_aux (SYMBOL_NAME (msymbol), mangled_name,
-                                       block, namespace, is_a_field_of_this,
-                                       symtab);
-           }
-       }
-    }
+  return lookup_symbol_global (name, linkage_name, block, domain);
+}
+
+/* Lookup a symbol in the static block associated to BLOCK, if there
+   is one; do nothing if BLOCK is NULL or a global block.  */
+
+struct symbol *
+lookup_symbol_static (const char *name,
+                     const char *linkage_name,
+                     const struct block *block,
+                     const domain_enum domain)
+{
+  const struct block *static_block = block_static_block (block);
+
+  if (static_block != NULL)
+    return lookup_symbol_aux_block (name, linkage_name, static_block, domain);
+  else
+    return NULL;
+}
+
+/* Lookup a symbol in all files' global blocks (searching psymtabs if
+   necessary).  */
+
+struct symbol *
+lookup_symbol_global (const char *name,
+                     const char *linkage_name,
+                     const struct block *block,
+                     const domain_enum domain)
+{
+  struct symbol *sym = NULL;
+  struct objfile *objfile = NULL;
+
+  /* Call library-specific lookup procedure.  */
+  objfile = lookup_objfile_from_block (block);
+  if (objfile != NULL)
+    sym = solib_global_lookup (objfile, name, linkage_name, domain);
+  if (sym != NULL)
+    return sym;
 
-#endif
+  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  if (sym != NULL)
+    return sym;
 
-  if (symtab != NULL)
-    *symtab = NULL;
-  return 0;
+  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+}
+
+int
+symbol_matches_domain (enum language symbol_language,
+                      domain_enum symbol_domain,
+                      domain_enum domain)
+{
+  /* For C++ "struct foo { ... }" also defines a typedef for "foo".
+     A Java class declaration also defines a typedef for the class.
+     Similarly, any Ada type declaration implicitly defines a typedef.  */
+  if (symbol_language == language_cplus
+      || symbol_language == language_java
+      || symbol_language == language_ada)
+    {
+      if ((domain == VAR_DOMAIN || domain == STRUCT_DOMAIN)
+         && symbol_domain == STRUCT_DOMAIN)
+       return 1;
+    }
+  /* For all other languages, strict match is required.  */
+  return (symbol_domain == domain);
 }
-                                                               
-/* Look, in partial_symtab PST, for symbol NAME.  Check the global
-   symbols if GLOBAL, the static symbols if not */
 
-static struct partial_symbol *
-lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
-                      namespace_enum namespace)
+/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
+   If LINKAGE_NAME is non-NULL, check in addition that the symbol's
+   linkage name matches it.  Check the global symbols if GLOBAL, the
+   static symbols if not */
+
+struct partial_symbol *
+lookup_partial_symbol (struct partial_symtab *pst, const char *name,
+                      const char *linkage_name, int global,
+                      domain_enum domain)
 {
   struct partial_symbol *temp;
   struct partial_symbol **start, **psym;
-  struct partial_symbol **top, **bottom, **center;
+  struct partial_symbol **top, **real_top, **bottom, **center;
   int length = (global ? pst->n_global_syms : pst->n_static_syms);
   int do_linear_search = 1;
-  
+
   if (length == 0)
     {
       return (NULL);
@@ -1106,29 +1773,31 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
   start = (global ?
           pst->objfile->global_psymbols.list + pst->globals_offset :
           pst->objfile->static_psymbols.list + pst->statics_offset);
-  
+
   if (global)                  /* This means we can use a binary search. */
     {
       do_linear_search = 0;
 
       /* Binary search.  This search is guaranteed to end with center
-         pointing at the earliest partial symbol with the correct
-         name.  At that point *all* partial symbols with that name
-         will be checked against the correct namespace. */
+         pointing at the earliest partial symbol whose name might be
+         correct.  At that point *all* partial symbols with an
+         appropriate name will be checked against the correct
+         domain.  */
 
       bottom = start;
       top = start + length - 1;
+      real_top = top;
       while (top > bottom)
        {
          center = bottom + (top - bottom) / 2;
          if (!(center < top))
-           internal_error (__FILE__, __LINE__, "failed internal consistency check");
+           internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
          if (!do_linear_search
              && (SYMBOL_LANGUAGE (*center) == language_java))
            {
              do_linear_search = 1;
            }
-         if (strcmp (SYMBOL_SOURCE_NAME (*center), name) >= 0)
+         if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0)
            {
              top = center;
            }
@@ -1138,17 +1807,16 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
            }
        }
       if (!(top == bottom))
-       internal_error (__FILE__, __LINE__, "failed internal consistency check");
+       internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
-      /* djb - 2000-06-03 - Use SYMBOL_MATCHES_NAME, not a strcmp, so
-        we don't have to force a linear search on C++. Probably holds true
-        for JAVA as well, no way to check.*/
-      while (SYMBOL_MATCHES_NAME (*top,name))
+      while (top <= real_top
+            && (linkage_name != NULL
+                ? strcmp (SYMBOL_LINKAGE_NAME (*top), linkage_name) == 0
+                : SYMBOL_MATCHES_SEARCH_NAME (*top,name)))
        {
-         if (SYMBOL_NAMESPACE (*top) == namespace)
-           {
-                 return (*top);
-           }
+         if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
+                                    SYMBOL_DOMAIN (*top), domain))
+           return (*top);
          top++;
        }
     }
@@ -1157,12 +1825,15 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
      we should also do a linear search. */
 
   if (do_linear_search)
-    {                  
+    {
       for (psym = start; psym < start + length; psym++)
        {
-         if (namespace == SYMBOL_NAMESPACE (*psym))
+         if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
+                                    SYMBOL_DOMAIN (*psym), domain))
            {
-             if (SYMBOL_MATCHES_NAME (*psym, name))
+             if (linkage_name != NULL
+                 ? strcmp (SYMBOL_LINKAGE_NAME (*psym), linkage_name) == 0
+                 : SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
                {
                  return (*psym);
                }
@@ -1173,34 +1844,42 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, int global,
   return (NULL);
 }
 
-/* Look up a type named NAME in the struct_namespace.  The type returned
-   must not be opaque -- i.e., must have at least one field defined
+/* Look up a type named NAME in the struct_domain.  The type returned
+   must not be opaque -- i.e., must have at least one field
+   defined.  */
 
-   This code was modelled on lookup_symbol -- the parts not relevant to looking
-   up types were just left out.  In particular it's assumed here that types
-   are available in struct_namespace and only at file-static or global blocks. */
+struct type *
+lookup_transparent_type (const char *name)
+{
+  return current_language->la_lookup_transparent_type (name);
+}
 
+/* The standard implementation of lookup_transparent_type.  This code
+   was modeled on lookup_symbol -- the parts not relevant to looking
+   up types were just left out.  In particular it's assumed here that
+   types are available in struct_domain and only at file-static or
+   global blocks.  */
 
 struct type *
-lookup_transparent_type (const char *name)
+basic_lookup_transparent_type (const char *name)
 {
-  register struct symbol *sym;
-  register struct symtab *s = NULL;
-  register struct partial_symtab *ps;
+  struct symbol *sym;
+  struct symtab *s = NULL;
+  struct partial_symtab *ps;
   struct blockvector *bv;
-  register struct objfile *objfile;
-  register struct block *block;
+  struct objfile *objfile;
+  struct block *block;
 
   /* Now search all the global symbols.  Do the symtab's first, then
      check the psymtab's. If a psymtab indicates the existence
      of the desired name as a global, then do psymtab-to-symtab
      conversion on the fly and return the found symbol.  */
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
     if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
       {
        return SYMBOL_TYPE (sym);
@@ -1209,12 +1888,13 @@ lookup_transparent_type (const char *name)
 
   ALL_PSYMTABS (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_NAMESPACE))
+    if (!ps->readin && lookup_partial_symbol (ps, name, NULL,
+                                             1, STRUCT_DOMAIN))
       {
        s = PSYMTAB_TO_SYMTAB (ps);
        bv = BLOCKVECTOR (s);
        block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-       sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+       sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
        if (!sym)
          {
            /* This shouldn't be necessary, but as a last resort
@@ -1223,11 +1903,11 @@ lookup_transparent_type (const char *name)
             * the psymtab gets it wrong in some cases.
             */
            block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-           sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+           sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
            if (!sym)
-             error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
+             error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
+(if a template, try specifying an instantiation: %s<type>)."),
                     name, ps->filename, name, name);
          }
        if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
@@ -1243,11 +1923,11 @@ lookup_transparent_type (const char *name)
      conversion on the fly and return the found symbol.
    */
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
     if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
       {
        return SYMBOL_TYPE (sym);
@@ -1256,12 +1936,12 @@ lookup_transparent_type (const char *name)
 
   ALL_PSYMTABS (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_NAMESPACE))
+    if (!ps->readin && lookup_partial_symbol (ps, name, NULL, 0, STRUCT_DOMAIN))
       {
        s = PSYMTAB_TO_SYMTAB (ps);
        bv = BLOCKVECTOR (s);
        block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-       sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+       sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
        if (!sym)
          {
            /* This shouldn't be necessary, but as a last resort
@@ -1270,11 +1950,11 @@ lookup_transparent_type (const char *name)
             * the psymtab gets it wrong in some cases.
             */
            block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-           sym = lookup_block_symbol (block, name, NULL, STRUCT_NAMESPACE);
+           sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
            if (!sym)
-             error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
+             error (_("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>).",
+(if a template, try specifying an instantiation: %s<type>)."),
                     name, ps->filename, name, name);
          }
        if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
@@ -1292,12 +1972,12 @@ lookup_transparent_type (const char *name)
 struct partial_symtab *
 find_main_psymtab (void)
 {
-  register struct partial_symtab *pst;
-  register struct objfile *objfile;
+  struct partial_symtab *pst;
+  struct objfile *objfile;
 
   ALL_PSYMTABS (objfile, pst)
   {
-    if (lookup_partial_symbol (pst, main_name (), 1, VAR_NAMESPACE))
+    if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN))
       {
        return (pst);
       }
@@ -1305,247 +1985,91 @@ find_main_psymtab (void)
   return (NULL);
 }
 
-/* Search BLOCK for symbol NAME in NAMESPACE.
+/* Search BLOCK for symbol NAME in DOMAIN.
 
    Note that if NAME is the demangled form of a C++ symbol, we will fail
    to find a match during the binary search of the non-encoded names, but
    for now we don't worry about the slight inefficiency of looking for
    a match we'll never find, since it will go pretty quick.  Once the
    binary search terminates, we drop through and do a straight linear
-   search on the symbols.  Each symbol which is marked as being a C++
-   symbol (language_cplus set) has both the encoded and non-encoded names
-   tested for a match.
+   search on the symbols.  Each symbol which is marked as being a ObjC/C++
+   symbol (language_cplus or language_objc set) has both the encoded and
+   non-encoded names tested for a match.
 
-   If MANGLED_NAME is non-NULL, verify that any symbol we find has this
+   If LINKAGE_NAME is non-NULL, verify that any symbol we find has this
    particular mangled name.
 */
 
 struct symbol *
-lookup_block_symbol (register const struct block *block, const char *name,
-                    const char *mangled_name,
-                    const namespace_enum namespace)
+lookup_block_symbol (const struct block *block, const char *name,
+                    const char *linkage_name,
+                    const domain_enum domain)
 {
-  register int bot, top, inc;
-  register struct symbol *sym;
-  register struct symbol *sym_found = NULL;
-  register int do_linear_search = 1;
+  struct dict_iterator iter;
+  struct symbol *sym;
 
-  if (BLOCK_HASHTABLE (block))
+  if (!BLOCK_FUNCTION (block))
     {
-      unsigned int hash_index;
-      hash_index = msymbol_hash_iw (name);
-      hash_index = hash_index % BLOCK_BUCKETS (block);
-      for (sym = BLOCK_BUCKET (block, hash_index); sym; sym = sym->hash_next)
+      for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+          sym != NULL;
+          sym = dict_iter_name_next (name, &iter))
        {
-         if (SYMBOL_NAMESPACE (sym) == namespace 
-             && (mangled_name
-                 ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
-                 : SYMBOL_MATCHES_NAME (sym, name)))
+         if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+                                    SYMBOL_DOMAIN (sym), domain)
+             && (linkage_name != NULL
+                 ? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
            return sym;
        }
       return NULL;
     }
-
-  /* If the blocks's symbols were sorted, start with a binary search.  */
-
-  if (BLOCK_SHOULD_SORT (block))
+  else
     {
-      /* Reset the linear search flag so if the binary search fails, we
-         won't do the linear search once unless we find some reason to
-         do so */
-
-      do_linear_search = 0;
-      top = BLOCK_NSYMS (block);
-      bot = 0;
-
-      /* Advance BOT to not far before the first symbol whose name is NAME. */
-
-      while (1)
-       {
-         inc = (top - bot + 1);
-         /* No need to keep binary searching for the last few bits worth.  */
-         if (inc < 4)
-           {
-             break;
-           }
-         inc = (inc >> 1) + bot;
-         sym = BLOCK_SYM (block, inc);
-         if (!do_linear_search && (SYMBOL_LANGUAGE (sym) == language_java))
-           {
-             do_linear_search = 1;
-           }
-         if (SYMBOL_SOURCE_NAME (sym)[0] < name[0])
-           {
-             bot = inc;
-           }
-         else if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
-           {
-             top = inc;
-           }
-         else if (strcmp (SYMBOL_SOURCE_NAME (sym), name) < 0)
-           {
-             bot = inc;
-           }
-         else
-           {
-             top = inc;
-           }
-       }
-
-      /* Now scan forward until we run out of symbols, find one whose
-         name is greater than NAME, or find one we want.  If there is
-         more than one symbol with the right name and namespace, we
-         return the first one; I believe it is now impossible for us
-         to encounter two symbols with the same name and namespace
-         here, because blocks containing argument symbols are no
-         longer sorted.  The exception is for C++, where multiple functions
-        (cloned constructors / destructors, in particular) can have
-        the same demangled name.  So if we have a particular
-        mangled name to match, try to do so.  */
-
-      top = BLOCK_NSYMS (block);
-      while (bot < top)
-       {
-         sym = BLOCK_SYM (block, bot);
-         if (SYMBOL_NAMESPACE (sym) == namespace
-             && (mangled_name
-                 ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
-                 : SYMBOL_MATCHES_NAME (sym, name)))
-           {
-             return sym;
-           }
-          if (SYMBOL_SOURCE_NAME (sym)[0] > name[0])
-            {
-              break;
-            }
-         bot++;
-       }
-    }
-
-  /* Here if block isn't sorted, or we fail to find a match during the
-     binary search above.  If during the binary search above, we find a
-     symbol which is a Java symbol, then we have re-enabled the linear
-     search flag which was reset when starting the binary search.
-
-     This loop is equivalent to the loop above, but hacked greatly for speed.
+      /* Note that parameter symbols do not always show up last in the
+        list; this loop makes sure to take anything else other than
+        parameter symbols first; it only uses parameter symbols as a
+        last resort.  Note that this only takes up extra computation
+        time on a match.  */
 
-     Note that parameter symbols do not always show up last in the
-     list; this loop makes sure to take anything else other than
-     parameter symbols first; it only uses parameter symbols as a
-     last resort.  Note that this only takes up extra computation
-     time on a match.  */
+      struct symbol *sym_found = NULL;
 
-  if (do_linear_search)
-    {
-      top = BLOCK_NSYMS (block);
-      bot = 0;
-      while (bot < top)
+      for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+          sym != NULL;
+          sym = dict_iter_name_next (name, &iter))
        {
-         sym = BLOCK_SYM (block, bot);
-         if (SYMBOL_NAMESPACE (sym) == namespace
-             && (mangled_name
-                 ? strcmp (SYMBOL_NAME (sym), mangled_name) == 0
-                 : SYMBOL_MATCHES_NAME (sym, name)))
+         if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+                                    SYMBOL_DOMAIN (sym), domain)
+             && (linkage_name != NULL
+                 ? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
            {
-             /* If SYM has aliases, then use any alias that is active
-                at the current PC.  If no alias is active at the current
-                PC, then use the main symbol.
-
-                ?!? Is checking the current pc correct?  Is this routine
-                ever called to look up a symbol from another context?
-
-                FIXME: No, it's not correct.  If someone sets a
-                conditional breakpoint at an address, then the
-                breakpoint's `struct expression' should refer to the
-                `struct symbol' appropriate for the breakpoint's
-                address, which may not be the PC.
-
-                Even if it were never called from another context,
-                it's totally bizarre for lookup_symbol's behavior to
-                depend on the value of the inferior's current PC.  We
-                should pass in the appropriate PC as well as the
-                block.  The interface to lookup_symbol should change
-                to require the caller to provide a PC.  */
-
-             if (SYMBOL_ALIASES (sym))
-               sym = find_active_alias (sym, read_pc ());
-
              sym_found = sym;
-             if (SYMBOL_CLASS (sym) != LOC_ARG &&
-                 SYMBOL_CLASS (sym) != LOC_LOCAL_ARG &&
-                 SYMBOL_CLASS (sym) != LOC_REF_ARG &&
-                 SYMBOL_CLASS (sym) != LOC_REGPARM &&
-                 SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR &&
-                 SYMBOL_CLASS (sym) != LOC_BASEREG_ARG)
+             if (!SYMBOL_IS_ARGUMENT (sym))
                {
                  break;
                }
            }
-         bot++;
-       }
-    }
-  return (sym_found);          /* Will be NULL if not found. */
-}
-
-/* Given a main symbol SYM and ADDR, search through the alias
-   list to determine if an alias is active at ADDR and return
-   the active alias.
-
-   If no alias is active, then return SYM.  */
-
-static struct symbol *
-find_active_alias (struct symbol *sym, CORE_ADDR addr)
-{
-  struct range_list *r;
-  struct alias_list *aliases;
-
-  /* If we have aliases, check them first.  */
-  aliases = SYMBOL_ALIASES (sym);
-
-  while (aliases)
-    {
-      if (!SYMBOL_RANGES (aliases->sym))
-       return aliases->sym;
-      for (r = SYMBOL_RANGES (aliases->sym); r; r = r->next)
-       {
-         if (r->start <= addr && r->end > addr)
-           return aliases->sym;
        }
-      aliases = aliases->next;
+      return (sym_found);      /* Will be NULL if not found. */
     }
-
-  /* Nothing found, return the main symbol.  */
-  return sym;
-}
-\f
-
-/* Return the symbol for the function which contains a specified
-   lexical block, described by a struct block BL.  */
-
-struct symbol *
-block_function (struct block *bl)
-{
-  while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
-    bl = BLOCK_SUPERBLOCK (bl);
-
-  return BLOCK_FUNCTION (bl);
 }
 
 /* Find the symtab associated with PC and SECTION.  Look through the
    psymtabs and read in another symtab if necessary. */
 
 struct symtab *
-find_pc_sect_symtab (CORE_ADDR pc, asection *section)
+find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
 {
-  register struct block *b;
+  struct block *b;
   struct blockvector *bv;
-  register struct symtab *s = NULL;
-  register struct symtab *best_s = NULL;
-  register struct partial_symtab *ps;
-  register struct objfile *objfile;
+  struct symtab *s = NULL;
+  struct symtab *best_s = NULL;
+  struct partial_symtab *ps;
+  struct objfile *objfile;
+  struct program_space *pspace;
   CORE_ADDR distance = 0;
   struct minimal_symbol *msymbol;
 
+  pspace = current_program_space;
+
   /* If we know that this is not a text address, return failure.  This is
      necessary because we loop based on the block's high and low code
      addresses, which do not include the data ranges, and because
@@ -1553,11 +2077,11 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
      on the partial_symtab's texthigh and textlow.  */
   msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
   if (msymbol
-      && (msymbol->type == mst_data
-         || msymbol->type == mst_bss
-         || msymbol->type == mst_abs
-         || msymbol->type == mst_file_data
-         || msymbol->type == mst_file_bss))
+      && (MSYMBOL_TYPE (msymbol) == mst_data
+         || MSYMBOL_TYPE (msymbol) == mst_bss
+         || MSYMBOL_TYPE (msymbol) == mst_abs
+         || MSYMBOL_TYPE (msymbol) == mst_file_data
+         || MSYMBOL_TYPE (msymbol) == mst_file_bss))
     return NULL;
 
   /* Search all symtabs for the one whose file contains our address, and which
@@ -1575,7 +2099,7 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
      It also happens for objfiles that have their functions reordered.
      For these, the symtab we are looking for is not necessarily read in.  */
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     bv = BLOCKVECTOR (s);
     b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
@@ -1599,16 +2123,16 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
          }
        if (section != 0)
          {
-           int i;
+           struct dict_iterator iter;
            struct symbol *sym = NULL;
 
-           ALL_BLOCK_SYMBOLS (b, i, sym)
+           ALL_BLOCK_SYMBOLS (b, iter, sym)
              {
                fixup_symbol_section (sym, objfile);
-               if (section == SYMBOL_BFD_SECTION (sym))
+               if (matching_obj_sections (SYMBOL_OBJ_SECTION (sym), section))
                  break;
              }
-           if ((i >= BLOCK_BUCKETS (b)) && (sym == NULL))
+           if (sym == NULL)
              continue;         /* no symbol in this symtab matches section */
          }
        distance = BLOCK_END (b) - BLOCK_START (b);
@@ -1627,9 +2151,9 @@ find_pc_sect_symtab (CORE_ADDR pc, asection *section)
        /* Might want to error() here (in case symtab is corrupt and
           will cause a core dump), but maybe we can successfully
           continue, so let's not.  */
-       warning ("\
-(Internal error: pc 0x%s in read in psymtab, but not in symtab.)\n",
-                paddr_nz (pc));
+       warning (_("\
+(Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
+                paddress (get_objfile_arch (ps->objfile), pc));
       s = PSYMTAB_TO_SYMTAB (ps);
     }
   return (s);
@@ -1645,94 +2169,6 @@ find_pc_symtab (CORE_ADDR pc)
 }
 \f
 
-#if 0
-
-/* Find the closest symbol value (of any sort -- function or variable)
-   for a given address value.  Slow but complete.  (currently unused,
-   mainly because it is too slow.  We could fix it if each symtab and
-   psymtab had contained in it the addresses ranges of each of its
-   sections, which also would be required to make things like "info
-   line *0x2345" cause psymtabs to be converted to symtabs).  */
-
-struct symbol *
-find_addr_symbol (CORE_ADDR addr, struct symtab **symtabp, CORE_ADDR *symaddrp)
-{
-  struct symtab *symtab, *best_symtab;
-  struct objfile *objfile;
-  register int bot, top;
-  register struct symbol *sym;
-  register CORE_ADDR sym_addr;
-  struct block *block;
-  int blocknum;
-
-  /* Info on best symbol seen so far */
-
-  register CORE_ADDR best_sym_addr = 0;
-  struct symbol *best_sym = 0;
-
-  /* FIXME -- we should pull in all the psymtabs, too!  */
-  ALL_SYMTABS (objfile, symtab)
-  {
-    /* Search the global and static blocks in this symtab for
-       the closest symbol-address to the desired address.  */
-
-    for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++)
-      {
-       QUIT;
-       block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum);
-       ALL_BLOCK_SYMBOLS (block, bot, sym)
-         {
-           switch (SYMBOL_CLASS (sym))
-             {
-             case LOC_STATIC:
-             case LOC_LABEL:
-               sym_addr = SYMBOL_VALUE_ADDRESS (sym);
-               break;
-
-             case LOC_INDIRECT:
-               sym_addr = SYMBOL_VALUE_ADDRESS (sym);
-               /* An indirect symbol really lives at *sym_addr,
-                * so an indirection needs to be done.
-                * However, I am leaving this commented out because it's
-                * expensive, and it's possible that symbolization
-                * could be done without an active process (in
-                * case this read_memory will fail). RT
-                sym_addr = read_memory_unsigned_integer
-                (sym_addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
-                */
-               break;
-
-             case LOC_BLOCK:
-               sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-               break;
-
-             default:
-               continue;
-             }
-
-           if (sym_addr <= addr)
-             if (sym_addr > best_sym_addr)
-               {
-                 /* Quit if we found an exact match.  */
-                 best_sym = sym;
-                 best_sym_addr = sym_addr;
-                 best_symtab = symtab;
-                 if (sym_addr == addr)
-                   goto done;
-               }
-         }
-      }
-  }
-
-done:
-  if (symtabp)
-    *symtabp = best_symtab;
-  if (symaddrp)
-    *symaddrp = best_sym_addr;
-  return best_sym;
-}
-#endif /* 0 */
-
 /* Find the source file and line number for a given PC value and SECTION.
    Return a structure containing a symtab pointer, a line number,
    and a pc range for the entire source line.
@@ -1751,13 +2187,13 @@ done:
 /* If it's worth the effort, we could be using a binary search.  */
 
 struct symtab_and_line
-find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
+find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
 {
   struct symtab *s;
-  register struct linetable *l;
-  register int len;
-  register int i;
-  register struct linetable_entry *item;
+  struct linetable *l;
+  int len;
+  int i;
+  struct linetable_entry *item;
   struct symtab_and_line val;
   struct blockvector *bv;
   struct minimal_symbol *msymbol;
@@ -1787,7 +2223,9 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
      But what we want is the statement containing the instruction.
      Fudge the pc to make sure we get that.  */
 
-  INIT_SAL (&val);             /* initialize to zeroes */
+  init_sal (&val);             /* initialize to zeroes */
+
+  val.pspace = current_program_space;
 
   /* It's tempting to assume that, if we can't find debugging info for
      any function enclosing PC, that we shouldn't search for line
@@ -1802,8 +2240,8 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
   /* elz: added this because this function returned the wrong
      information if the pc belongs to a stub (import/export)
      to call a shlib function. This stub would be anywhere between
-     two functions in the target, and the line info was erroneously 
-     taken to be the one of the line before the pc. 
+     two functions in the target, and the line info was erroneously
+     taken to be the one of the line before the pc.
    */
   /* RT: Further explanation:
 
@@ -1816,7 +2254,7 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
    * sorted by start address. The stubs are marked as "trampoline",
    * the others appear as text. E.g.:
    *
-   *  Minimal symbol table for main image 
+   *  Minimal symbol table for main image
    *     main:  code for main (text symbol)
    *     shr1: stub  (trampoline symbol)
    *     foo:   code for foo (text symbol)
@@ -1834,7 +2272,7 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
    * Assumptions being made about the minimal symbol table:
    *   1. lookup_minimal_symbol_by_pc() will return a trampoline only
    *      if we're really in the trampoline. If we're beyond it (say
-   *      we're in "foo" in the above example), it'll have a closer 
+   *      we're in "foo" in the above example), it'll have a closer
    *      symbol (the "foo" text symbol for example) and will not
    *      return the trampoline.
    *   2. lookup_minimal_symbol_text() will find a real text symbol
@@ -1847,26 +2285,27 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
   if (msymbol != NULL)
     if (MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
       {
-       mfunsym = lookup_minimal_symbol_text (SYMBOL_NAME (msymbol), NULL, NULL);
+       mfunsym = lookup_minimal_symbol_text (SYMBOL_LINKAGE_NAME (msymbol),
+                                             NULL);
        if (mfunsym == NULL)
          /* I eliminated this warning since it is coming out
           * in the following situation:
           * gdb shmain // test program with shared libraries
           * (gdb) break shr1  // function in shared lib
           * Warning: In stub for ...
-          * In the above situation, the shared lib is not loaded yet, 
+          * In the above situation, the shared lib is not loaded yet,
           * so of course we can't find the real func/line info,
           * but the "break" still works, and the warning is annoying.
           * So I commented out the warning. RT */
-         /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */ ;
+         /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_LINKAGE_NAME (msymbol)) */ ;
        /* fall through */
-       else if (SYMBOL_VALUE (mfunsym) == SYMBOL_VALUE (msymbol))
+       else if (SYMBOL_VALUE_ADDRESS (mfunsym) == SYMBOL_VALUE_ADDRESS (msymbol))
          /* Avoid infinite recursion */
          /* See above comment about why warning is commented out */
-         /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */ ;
+         /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_LINKAGE_NAME (msymbol)) */ ;
        /* fall through */
        else
-         return find_pc_line (SYMBOL_VALUE (mfunsym), 0);
+         return find_pc_line (SYMBOL_VALUE_ADDRESS (mfunsym), 0);
       }
 
 
@@ -1929,9 +2368,11 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
          the first line, prev will not be set.  */
 
       /* Is this file's best line closer than the best in the other files?
-         If so, record this file, and its best line, as best so far.  */
+         If so, record this file, and its best line, as best so far.  Don't
+         save prev if it represents the end of a function (i.e. line number
+         0) instead of a real line.  */
 
-      if (prev && (!best || prev->pc > best->pc))
+      if (prev && prev->line && (!best || prev->pc > best->pc))
        {
          best = prev;
          best_symtab = s;
@@ -1951,23 +2392,11 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
 
   if (!best_symtab)
     {
-      if (!alt_symtab)
-       {                       /* If we didn't find any line # info, just
-                                  return zeros.  */
-         val.pc = pc;
-       }
-      else
-       {
-         val.symtab = alt_symtab;
-         val.line = alt->line - 1;
-
-         /* Don't return line 0, that means that we didn't find the line.  */
-         if (val.line == 0)
-           ++val.line;
-
-         val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
-         val.end = alt->pc;
-       }
+      /* If we didn't find any line number info, just return zeros.
+        We used to return alt->line - 1 here, but that could be
+        anywhere; if we don't have line number info for this PC,
+        don't make some up.  */
+      val.pc = pc;
     }
   else if (best->line == 0)
     {
@@ -1997,7 +2426,7 @@ find_pc_sect_line (CORE_ADDR pc, struct sec *section, int notcurrent)
 struct symtab_and_line
 find_pc_line (CORE_ADDR pc, int notcurrent)
 {
-  asection *section;
+  struct obj_section *section;
 
   section = find_pc_overlay (pc);
   if (pc_in_unmapped_range (pc, section))
@@ -2018,7 +2447,7 @@ find_pc_line (CORE_ADDR pc, int notcurrent)
 struct symtab *
 find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
 {
-  int exact;
+  int exact = 0;  /* Initialized here to avoid a compiler warning.  */
 
   /* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE
      so far seen.  */
@@ -2047,19 +2476,34 @@ find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
 
       struct objfile *objfile;
       struct symtab *s;
+      struct partial_symtab *p;
 
       if (best_index >= 0)
        best = best_linetable->item[best_index].line;
       else
        best = 0;
 
+      ALL_PSYMTABS (objfile, p)
+      {
+        if (FILENAME_CMP (symtab->filename, p->filename) != 0)
+          continue;
+        PSYMTAB_TO_SYMTAB (p);
+      }
+
+      /* Get symbol full file name if possible.  */
+      symtab_to_fullname (symtab);
+
       ALL_SYMTABS (objfile, s)
       {
        struct linetable *l;
        int ind;
 
-       if (!STREQ (symtab->filename, s->filename))
+       if (FILENAME_CMP (symtab->filename, s->filename) != 0)
          continue;
+       if (symtab->fullname != NULL
+           && symtab_to_fullname (s) != NULL
+           && FILENAME_CMP (symtab->fullname, s->fullname) != 0)
+         continue;     
        l = LINETABLE (s);
        ind = find_line_common (l, line, &exact);
        if (ind >= 0)
@@ -2164,11 +2608,11 @@ find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr,
    Set *EXACT_MATCH nonzero if the value returned is an exact match.  */
 
 static int
-find_line_common (register struct linetable *l, register int lineno,
+find_line_common (struct linetable *l, int lineno,
                  int *exact_match)
 {
-  register int i;
-  register int len;
+  int i;
+  int len;
 
   /* BEST is the smallest linenumber > LINENO so far seen,
      or 0 if none has been seen so far.
@@ -2177,6 +2621,8 @@ find_line_common (register struct linetable *l, register int lineno,
   int best_index = -1;
   int best = 0;
 
+  *exact_match = 0;
+
   if (lineno <= 0)
     return -1;
   if (l == 0)
@@ -2185,7 +2631,7 @@ find_line_common (register struct linetable *l, register int lineno,
   len = l->nitems;
   for (i = 0; i < len; i++)
     {
-      register struct linetable_entry *item = &(l->item[i]);
+      struct linetable_entry *item = &(l->item[i]);
 
       if (item->line == lineno)
        {
@@ -2202,8 +2648,6 @@ find_line_common (register struct linetable *l, register int lineno,
     }
 
   /* If we got here, we didn't get an exact match.  */
-
-  *exact_match = 0;
   return best_index;
 }
 
@@ -2217,6 +2661,67 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr)
   return sal.symtab != 0;
 }
 
+/* Given a function start address PC and SECTION, find the first
+   address after the function prologue.  */
+CORE_ADDR
+find_function_start_pc (struct gdbarch *gdbarch,
+                       CORE_ADDR pc, struct obj_section *section)
+{
+  /* If the function is in an unmapped overlay, use its unmapped LMA address,
+     so that gdbarch_skip_prologue has something unique to work on.  */
+  if (section_is_overlay (section) && !section_is_mapped (section))
+    pc = overlay_unmapped_address (pc, section);
+
+  pc += gdbarch_deprecated_function_start_offset (gdbarch);
+  pc = gdbarch_skip_prologue (gdbarch, pc);
+
+  /* For overlays, map pc back into its mapped VMA range.  */
+  pc = overlay_mapped_address (pc, section);
+
+  return pc;
+}
+
+/* Given a function start address FUNC_ADDR and SYMTAB, find the first
+   address for that function that has an entry in SYMTAB's line info
+   table.  If such an entry cannot be found, return FUNC_ADDR
+   unaltered.  */
+CORE_ADDR
+skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab)
+{
+  CORE_ADDR func_start, func_end;
+  struct linetable *l;
+  int ind, i, len;
+  int best_lineno = 0;
+  CORE_ADDR best_pc = func_addr;
+
+  /* Give up if this symbol has no lineinfo table.  */
+  l = LINETABLE (symtab);
+  if (l == NULL)
+    return func_addr;
+
+  /* Get the range for the function's PC values, or give up if we
+     cannot, for some reason.  */
+  if (!find_pc_partial_function (func_addr, NULL, &func_start, &func_end))
+    return func_addr;
+
+  /* Linetable entries are ordered by PC values, see the commentary in
+     symtab.h where `struct linetable' is defined.  Thus, the first
+     entry whose PC is in the range [FUNC_START..FUNC_END[ is the
+     address we are looking for.  */
+  for (i = 0; i < l->nitems; i++)
+    {
+      struct linetable_entry *item = &(l->item[i]);
+
+      /* Don't use line numbers of zero, they mark special entries in
+        the table.  See the commentary on symtab.h before the
+        definition of struct linetable.  */
+      if (item->line > 0 && func_start <= item->pc && item->pc < func_end)
+       return item->pc;
+    }
+
+  return func_addr;
+}
+
 /* Given a function symbol SYM, find the symtab and line for the start
    of the function.
    If the argument FUNFIRSTLINE is nonzero, we want the first line
@@ -2225,46 +2730,92 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr)
 struct symtab_and_line
 find_function_start_sal (struct symbol *sym, int funfirstline)
 {
+  struct block *block = SYMBOL_BLOCK_VALUE (sym);
+  struct objfile *objfile = lookup_objfile_from_block (block);
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
   CORE_ADDR pc;
   struct symtab_and_line sal;
+  struct block *b, *function_block;
 
-  pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-  fixup_symbol_section (sym, NULL);
-  if (funfirstline)
-    {                          /* skip "first line" of function (which is actually its prologue) */
-      asection *section = SYMBOL_BFD_SECTION (sym);
-      /* If function is in an unmapped overlay, use its unmapped LMA
-         address, so that SKIP_PROLOGUE has something unique to work on */
-      if (section_is_overlay (section) &&
-         !section_is_mapped (section))
-       pc = overlay_unmapped_address (pc, section);
+  struct cleanup *old_chain;
 
-      pc += FUNCTION_START_OFFSET;
-      pc = SKIP_PROLOGUE (pc);
+  old_chain = save_current_space_and_thread ();
+  switch_to_program_space_and_thread (objfile->pspace);
 
-      /* For overlays, map pc back into its mapped VMA range */
-      pc = overlay_mapped_address (pc, section);
+  pc = BLOCK_START (block);
+  fixup_symbol_section (sym, objfile);
+  if (funfirstline)
+    {
+      /* Skip "first line" of function (which is actually its prologue).  */
+      pc = find_function_start_pc (gdbarch, pc, SYMBOL_OBJ_SECTION (sym));
     }
-  sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
+  sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
 
-#ifdef PROLOGUE_FIRSTLINE_OVERLAP
-  /* Convex: no need to suppress code on first line, if any */
-  sal.pc = pc;
-#else
-  /* Check if SKIP_PROLOGUE left us in mid-line, and the next
+  /* Check if gdbarch_skip_prologue left us in mid-line, and the next
      line is still part of the same function.  */
   if (sal.pc != pc
-      && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end
-      && sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+      && BLOCK_START (block) <= sal.end
+      && sal.end < BLOCK_END (block))
     {
       /* First pc of next line */
       pc = sal.end;
       /* Recalculate the line number (might not be N+1).  */
-      sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
+      sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
     }
+
+  /* On targets with executable formats that don't have a concept of
+     constructors (ELF with .init has, PE doesn't), gcc emits a call
+     to `__main' in `main' between the prologue and before user
+     code.  */
+  if (funfirstline
+      && gdbarch_skip_main_prologue_p (gdbarch)
+      && SYMBOL_LINKAGE_NAME (sym)
+      && strcmp (SYMBOL_LINKAGE_NAME (sym), "main") == 0)
+    {
+      pc = gdbarch_skip_main_prologue (gdbarch, pc);
+      /* Recalculate the line number (might not be N+1).  */
+      sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
+    }
+
+  /* If we still don't have a valid source line, try to find the first
+     PC in the lineinfo table that belongs to the same function.  This
+     happens with COFF debug info, which does not seem to have an
+     entry in lineinfo table for the code after the prologue which has
+     no direct relation to source.  For example, this was found to be
+     the case with the DJGPP target using "gcc -gcoff" when the
+     compiler inserted code after the prologue to make sure the stack
+     is aligned.  */
+  if (funfirstline && sal.symtab == NULL)
+    {
+      pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym));
+      /* Recalculate the line number.  */
+      sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
+    }
+
   sal.pc = pc;
-#endif
+  sal.pspace = objfile->pspace;
+
+  /* Check if we are now inside an inlined function.  If we can,
+     use the call site of the function instead.  */
+  b = block_for_pc_sect (sal.pc, SYMBOL_OBJ_SECTION (sym));
+  function_block = NULL;
+  while (b != NULL)
+    {
+      if (BLOCK_FUNCTION (b) != NULL && block_inlined_p (b))
+       function_block = b;
+      else if (BLOCK_FUNCTION (b) != NULL)
+       break;
+      b = BLOCK_SUPERBLOCK (b);
+    }
+  if (function_block != NULL
+      && SYMBOL_LINE (BLOCK_FUNCTION (function_block)) != 0)
+    {
+      sal.line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
+      sal.symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block));
+    }
 
+  do_cleanups (old_chain);
   return sal;
 }
 
@@ -2293,7 +2844,7 @@ operator_chars (char *p, char **end)
 
   if (isalpha (*p) || *p == '_' || *p == '$')
     {
-      register char *q = p + 1;
+      char *q = p + 1;
       while (isalnum (*q) || *q == '_' || *q == '$')
        q++;
       *end = q;
@@ -2315,16 +2866,16 @@ operator_chars (char *p, char **end)
        else if (p[1] == '[')
          {
            if (p[2] == ']')
-             error ("mismatched quoting on brackets, try 'operator\\[\\]'");
+             error (_("mismatched quoting on brackets, try 'operator\\[\\]'"));
            else if (p[2] == '\\' && p[3] == ']')
              {
                *end = p + 4;   /* 'operator\[\]' */
                return p;
              }
            else
-             error ("nothing is allowed between '[' and ']'");
+             error (_("nothing is allowed between '[' and ']'"));
          }
-       else 
+       else
          {
            /* Gratuitous qoute: skip it and move on. */
            p++;
@@ -2378,21 +2929,21 @@ operator_chars (char *p, char **end)
        return p;
       case '(':
        if (p[1] != ')')
-         error ("`operator ()' must be specified without whitespace in `()'");
+         error (_("`operator ()' must be specified without whitespace in `()'"));
        *end = p + 2;
        return p;
       case '?':
        if (p[1] != ':')
-         error ("`operator ?:' must be specified without whitespace in `?:'");
+         error (_("`operator ?:' must be specified without whitespace in `?:'"));
        *end = p + 2;
        return p;
       case '[':
        if (p[1] != ']')
-         error ("`operator []' must be specified without whitespace in `[]'");
+         error (_("`operator []' must be specified without whitespace in `[]'"));
        *end = p + 2;
        return p;
       default:
-       error ("`operator %s' not supported", p);
+       error (_("`operator %s' not supported"), p);
        break;
       }
 
@@ -2449,7 +3000,7 @@ filename_seen (const char *file, int add, int *first)
    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)
+output_source_filename (const 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
@@ -2483,14 +3034,14 @@ output_source_filename (char *name, int *first)
 static void
 sources_info (char *ignore, int from_tty)
 {
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct objfile *objfile;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct objfile *objfile;
   int first;
 
   if (!have_full_symbols () && !have_partial_symbols ())
     {
-      error ("No symbol table is loaded.  Use the \"file\" command.");
+      error (_("No symbol table is loaded.  Use the \"file\" command."));
     }
 
   printf_filtered ("Source files for which symbols have been read in:\n\n");
@@ -2498,7 +3049,8 @@ sources_info (char *ignore, int from_tty)
   first = 1;
   ALL_SYMTABS (objfile, s)
   {
-    output_source_filename (s->filename, &first);
+    const char *fullname = symtab_to_fullname (s);
+    output_source_filename (fullname ? fullname : s->filename, &first);
   }
   printf_filtered ("\n\n");
 
@@ -2509,7 +3061,8 @@ sources_info (char *ignore, int from_tty)
   {
     if (!ps->readin)
       {
-       output_source_filename (ps->filename, &first);
+       const char *fullname = psymtab_to_fullname (ps);
+       output_source_filename (fullname ? fullname : ps->filename, &first);
       }
   }
   printf_filtered ("\n");
@@ -2567,8 +3120,8 @@ compare_search_syms (const void *sa, const void *sb)
   struct symbol_search **sym_a = (struct symbol_search **) sa;
   struct symbol_search **sym_b = (struct symbol_search **) sb;
 
-  return strcmp (SYMBOL_SOURCE_NAME ((*sym_a)->symbol),
-                SYMBOL_SOURCE_NAME ((*sym_b)->symbol));
+  return strcmp (SYMBOL_PRINT_NAME ((*sym_a)->symbol),
+                SYMBOL_PRINT_NAME ((*sym_b)->symbol));
 }
 
 /* Sort the ``nfound'' symbols in the list after prevtail.  Leave
@@ -2610,10 +3163,9 @@ sort_search_symbols (struct symbol_search *prevtail, int nfound)
    returning the results in *MATCHES.
 
    Only symbols of KIND are searched:
-   FUNCTIONS_NAMESPACE - search all functions
-   TYPES_NAMESPACE     - search all type names
-   METHODS_NAMESPACE   - search all methods NOT IMPLEMENTED
-   VARIABLES_NAMESPACE - search all symbols, excluding functions, type names,
+   FUNCTIONS_DOMAIN - search all functions
+   TYPES_DOMAIN     - search all type names
+   VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
    and constants (enums)
 
    free_search_symbols should be called when *MATCHES is no longer needed.
@@ -2622,17 +3174,16 @@ sort_search_symbols (struct symbol_search *prevtail, int nfound)
    separately alphabetized.
  */
 void
-search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
+search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
                struct symbol_search **matches)
 {
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct blockvector *bv;
-  struct blockvector *prev_bv = 0;
-  register struct block *b;
-  register int i = 0;
-  register int j;
-  register struct symbol *sym;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct blockvector *bv;
+  struct block *b;
+  int i = 0;
+  struct dict_iterator iter;
+  struct symbol *sym;
   struct partial_symbol **psym;
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
@@ -2659,13 +3210,13 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
   struct symbol_search *tail;
   struct cleanup *old_chain = NULL;
 
-  if (kind < VARIABLES_NAMESPACE)
-    error ("must search on specific namespace");
+  if (kind < VARIABLES_DOMAIN)
+    error (_("must search on specific domain"));
 
-  ourtype = types[(int) (kind - VARIABLES_NAMESPACE)];
-  ourtype2 = types2[(int) (kind - VARIABLES_NAMESPACE)];
-  ourtype3 = types3[(int) (kind - VARIABLES_NAMESPACE)];
-  ourtype4 = types4[(int) (kind - VARIABLES_NAMESPACE)];
+  ourtype = types[(int) (kind - VARIABLES_DOMAIN)];
+  ourtype2 = types2[(int) (kind - VARIABLES_DOMAIN)];
+  ourtype3 = types3[(int) (kind - VARIABLES_DOMAIN)];
+  ourtype4 = types4[(int) (kind - VARIABLES_DOMAIN)];
 
   sr = *matches = NULL;
   tail = NULL;
@@ -2703,7 +3254,7 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
        }
 
       if (0 != (val = re_comp (regexp)))
-       error ("Invalid regexp (%s): %s", val, regexp);
+       error (_("Invalid regexp (%s): %s"), val, regexp);
     }
 
   /* Search through the partial symtabs *first* for all symbols
@@ -2743,14 +3294,20 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
            QUIT;
 
            /* If it would match (logic taken from loop below)
-              load the file and go on to the next one */
+              load the file and go on to the next one.  We check the
+              filename here, but that's a bit bogus: we don't know
+              what file it really comes from until we have full
+              symtabs.  The symbol might be in a header file included by
+              this psymtab.  This only affects Insight.  */
            if (file_matches (ps->filename, files, nfiles)
-               && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (*psym))
-                   && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
-                        && SYMBOL_CLASS (*psym) != LOC_BLOCK)
-                       || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK)
-                       || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)
-                       || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK))))
+               && ((regexp == NULL
+                    || re_exec (SYMBOL_NATURAL_NAME (*psym)) != 0)
+                   && ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+                        && SYMBOL_CLASS (*psym) != LOC_UNRESOLVED
+                        && SYMBOL_CLASS (*psym) != LOC_BLOCK
+                        && SYMBOL_CLASS (*psym) != LOC_CONST)
+                       || (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+                       || (kind == TYPES_DOMAIN && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))))
              {
                PSYMTAB_TO_SYMTAB (ps);
                keep_going = 0;
@@ -2773,24 +3330,33 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
      any matching symbols without debug info.
    */
 
-  if (nfiles == 0 && (kind == VARIABLES_NAMESPACE || kind == FUNCTIONS_NAMESPACE))
+  if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
     {
       ALL_MSYMBOLS (objfile, msymbol)
       {
+        QUIT;
+
        if (MSYMBOL_TYPE (msymbol) == ourtype ||
            MSYMBOL_TYPE (msymbol) == ourtype2 ||
            MSYMBOL_TYPE (msymbol) == ourtype3 ||
            MSYMBOL_TYPE (msymbol) == ourtype4)
          {
-           if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+           if (regexp == NULL
+               || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
              {
                if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
                  {
-                   if (kind == FUNCTIONS_NAMESPACE
-                       || lookup_symbol (SYMBOL_NAME (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_NAMESPACE,
-                                       0, (struct symtab **) NULL) == NULL)
+                                         VAR_DOMAIN, 0)
+                       == NULL)
                      found_misc = 1;
                  }
              }
@@ -2798,36 +3364,33 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
       }
     }
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     bv = BLOCKVECTOR (s);
-    /* Often many files share a blockvector.
-       Scan each blockvector only once so that
-       we don't get every symbol many times.
-       It happens that the first symtab in the list
-       for any given blockvector is the main file.  */
-    if (bv != prev_bv)
       for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
        {
          struct symbol_search *prevtail = tail;
          int nfound = 0;
          b = BLOCKVECTOR_BLOCK (bv, i);
-         ALL_BLOCK_SYMBOLS (b, j, sym)
+         ALL_BLOCK_SYMBOLS (b, iter, sym)
            {
+             struct symtab *real_symtab = SYMBOL_SYMTAB (sym);
              QUIT;
-             if (file_matches (s->filename, files, nfiles)
-                 && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym))
-                     && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+
+             if (file_matches (real_symtab->filename, files, nfiles)
+                 && ((regexp == NULL
+                      || re_exec (SYMBOL_NATURAL_NAME (sym)) != 0)
+                     && ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                          && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
                           && SYMBOL_CLASS (sym) != LOC_BLOCK
                           && SYMBOL_CLASS (sym) != LOC_CONST)
-                         || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK)
-                         || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
-                         || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK))))
+                         || (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                         || (kind == TYPES_DOMAIN && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
                {
                  /* match */
                  psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
                  psr->block = i;
-                 psr->symtab = s;
+                 psr->symtab = real_symtab;
                  psr->symbol = sym;
                  psr->msymbol = NULL;
                  psr->next = NULL;
@@ -2855,31 +3418,33 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
                tail = sort_search_symbols (prevtail, nfound);
            }
        }
-    prev_bv = bv;
   }
 
   /* 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_NAMESPACE)
+  if (found_misc || kind != FUNCTIONS_DOMAIN)
     {
       ALL_MSYMBOLS (objfile, msymbol)
       {
+        QUIT;
+
        if (MSYMBOL_TYPE (msymbol) == ourtype ||
            MSYMBOL_TYPE (msymbol) == ourtype2 ||
            MSYMBOL_TYPE (msymbol) == ourtype3 ||
            MSYMBOL_TYPE (msymbol) == ourtype4)
          {
-           if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+           if (regexp == NULL
+               || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
              {
                /* Functions:  Look up by address. */
-               if (kind != FUNCTIONS_NAMESPACE ||
+               if (kind != FUNCTIONS_DOMAIN ||
                    (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
                  {
                    /* Variables/Absolutes:  Look up by name */
-                   if (lookup_symbol (SYMBOL_NAME (msymbol),
-                                      (struct block *) NULL, VAR_NAMESPACE,
-                                      0, (struct symtab **) NULL) == NULL)
+                   if (lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
+                                      (struct block *) NULL, VAR_DOMAIN, 0)
+                        == NULL)
                      {
                        /* match */
                        psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
@@ -2913,7 +3478,7 @@ search_symbols (char *regexp, namespace_enum kind, int nfiles, char *files[],
    regarding the match to gdb_stdout.
  */
 static void
-print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym,
+print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym,
                   int block, char *last)
 {
   if (last == NULL || strcmp (last, s->filename) != 0)
@@ -2923,49 +3488,25 @@ print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym,
       fputs_filtered (":\n", gdb_stdout);
     }
 
-  if (kind != TYPES_NAMESPACE && block == STATIC_BLOCK)
+  if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
     printf_filtered ("static ");
 
   /* Typedef that is not a C++ class */
-  if (kind == TYPES_NAMESPACE
-      && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+  if (kind == TYPES_DOMAIN
+      && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
     typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
   /* variable, func, or typedef-that-is-c++-class */
-  else if (kind < TYPES_NAMESPACE ||
-          (kind == TYPES_NAMESPACE &&
-           SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE))
+  else if (kind < TYPES_DOMAIN ||
+          (kind == TYPES_DOMAIN &&
+           SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
     {
       type_print (SYMBOL_TYPE (sym),
                  (SYMBOL_CLASS (sym) == LOC_TYPEDEF
-                  ? "" : SYMBOL_SOURCE_NAME (sym)),
+                  ? "" : SYMBOL_PRINT_NAME (sym)),
                  gdb_stdout, 0);
 
       printf_filtered (";\n");
     }
-  else
-    {
-#if 0
-      /* Tiemann says: "info methods was never implemented."  */
-      char *demangled_name;
-      c_type_print_base (TYPE_FN_FIELD_TYPE (t, block),
-                        gdb_stdout, 0, 0);
-      c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (t, block),
-                                  gdb_stdout, 0);
-      if (TYPE_FN_FIELD_STUB (t, block))
-       check_stub_method (TYPE_DOMAIN_TYPE (type), j, block);
-      demangled_name =
-       cplus_demangle (TYPE_FN_FIELD_PHYSNAME (t, block),
-                       DMGL_ANSI | DMGL_PARAMS);
-      if (demangled_name == NULL)
-       fprintf_filtered (stream, "<badly mangled name %s>",
-                         TYPE_FN_FIELD_PHYSNAME (t, block));
-      else
-       {
-         fputs_filtered (demangled_name, stream);
-         xfree (demangled_name);
-       }
-#endif
-    }
 }
 
 /* This help function for symtab_symbol_info() prints information
@@ -2974,17 +3515,18 @@ print_symbol_info (namespace_enum kind, struct symtab *s, struct symbol *sym,
 static void
 print_msymbol_info (struct minimal_symbol *msymbol)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (msymbol_objfile (msymbol));
   char *tmp;
 
-  if (TARGET_ADDR_BIT <= 32)
-    tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
-                                  & (CORE_ADDR) 0xffffffff,
-                                  "08l");
+  if (gdbarch_addr_bit (gdbarch) <= 32)
+    tmp = hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol)
+                            & (CORE_ADDR) 0xffffffff,
+                            8);
   else
-    tmp = local_hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
-                                  "016l");
+    tmp = hex_string_custom (SYMBOL_VALUE_ADDRESS (msymbol),
+                            16);
   printf_filtered ("%s  %s\n",
-                  tmp, SYMBOL_SOURCE_NAME (msymbol));
+                  tmp, SYMBOL_PRINT_NAME (msymbol));
 }
 
 /* This is the guts of the commands "info functions", "info types", and
@@ -2993,7 +3535,7 @@ print_msymbol_info (struct minimal_symbol *msymbol)
    matches.
  */
 static void
-symtab_symbol_info (char *regexp, namespace_enum kind, int from_tty)
+symtab_symbol_info (char *regexp, domain_enum kind, int from_tty)
 {
   static char *classnames[]
   =
@@ -3011,7 +3553,7 @@ symtab_symbol_info (char *regexp, namespace_enum kind, int from_tty)
   printf_filtered (regexp
                   ? "All %ss matching regular expression \"%s\":\n"
                   : "All defined %ss:\n",
-                  classnames[(int) (kind - VARIABLES_NAMESPACE)], regexp);
+                  classnames[(int) (kind - VARIABLES_DOMAIN)], regexp);
 
   for (p = symbols; p != NULL; p = p->next)
     {
@@ -3043,30 +3585,21 @@ symtab_symbol_info (char *regexp, namespace_enum kind, int from_tty)
 static void
 variables_info (char *regexp, int from_tty)
 {
-  symtab_symbol_info (regexp, VARIABLES_NAMESPACE, from_tty);
+  symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty);
 }
 
 static void
 functions_info (char *regexp, int from_tty)
 {
-  symtab_symbol_info (regexp, FUNCTIONS_NAMESPACE, from_tty);
+  symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
 }
 
 
 static void
 types_info (char *regexp, int from_tty)
 {
-  symtab_symbol_info (regexp, TYPES_NAMESPACE, from_tty);
-}
-
-#if 0
-/* Tiemann says: "info methods was never implemented."  */
-static void
-methods_info (char *regexp)
-{
-  symtab_symbol_info (regexp, METHODS_NAMESPACE, 0, from_tty);
+  symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
 }
-#endif /* 0 */
 
 /* Breakpoint all functions matching regular expression. */
 
@@ -3083,22 +3616,22 @@ rbreak_command (char *regexp, int from_tty)
   struct symbol_search *p;
   struct cleanup *old_chain;
 
-  search_symbols (regexp, FUNCTIONS_NAMESPACE, 0, (char **) NULL, &ss);
+  search_symbols (regexp, FUNCTIONS_DOMAIN, 0, (char **) NULL, &ss);
   old_chain = make_cleanup_free_search_symbols (ss);
 
   for (p = ss; p != NULL; p = p->next)
     {
       if (p->msymbol == NULL)
        {
-         char *string = (char *) alloca (strlen (p->symtab->filename)
-                                         + strlen (SYMBOL_NAME (p->symbol))
-                                         + 4);
+         char *string = alloca (strlen (p->symtab->filename)
+                                + strlen (SYMBOL_LINKAGE_NAME (p->symbol))
+                                + 4);
          strcpy (string, p->symtab->filename);
          strcat (string, ":'");
-         strcat (string, SYMBOL_NAME (p->symbol));
+         strcat (string, SYMBOL_LINKAGE_NAME (p->symbol));
          strcat (string, "'");
          break_command (string, from_tty);
-         print_symbol_info (FUNCTIONS_NAMESPACE,
+         print_symbol_info (FUNCTIONS_DOMAIN,
                             p->symtab,
                             p->symbol,
                             p->block,
@@ -3106,9 +3639,15 @@ rbreak_command (char *regexp, int from_tty)
        }
       else
        {
-         break_command (SYMBOL_NAME (p->msymbol), from_tty);
+         char *string = alloca (strlen (SYMBOL_LINKAGE_NAME (p->msymbol))
+                                + 3);
+         strcpy (string, "'");
+         strcat (string, SYMBOL_LINKAGE_NAME (p->msymbol));
+         strcat (string, "'");
+
+         break_command (string, from_tty);
          printf_filtered ("<function, no debug info> %s;\n",
-                          SYMBOL_SOURCE_NAME (p->msymbol));
+                          SYMBOL_PRINT_NAME (p->msymbol));
        }
     }
 
@@ -3116,19 +3655,6 @@ rbreak_command (char *regexp, int from_tty)
 }
 \f
 
-/* Return Nonzero if block a is lexically nested within block b,
-   or if a and b have the same pc range.
-   Return zero otherwise. */
-int
-contained_in (struct block *a, struct block *b)
-{
-  if (!a || !b)
-    return 0;
-  return BLOCK_START (a) >= BLOCK_START (b)
-    && BLOCK_END (a) <= BLOCK_END (b);
-}
-\f
-
 /* Helper routine for make_symbol_completion_list.  */
 
 static int return_val_size;
@@ -3136,17 +3662,8 @@ static int return_val_index;
 static char **return_val;
 
 #define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
-  do { \
-    if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
-      /* Put only the mangled name on the list.  */ \
-      /* Advantage:  "b foo<TAB>" completes to "b foo(int, int)" */ \
-      /* Disadvantage:  "b foo__i<TAB>" doesn't complete.  */ \
       completion_list_add_name \
-       (SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \
-    else \
-      completion_list_add_name \
-       (SYMBOL_NAME (symbol), (sym_text), (len), (text), (word)); \
-  } while (0)
+       (SYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
 
 /*  Test to see if the symbol specified by SYMNAME (which is already
    demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
@@ -3201,31 +3718,174 @@ 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.
+/* ObjC: In case we are completing on a selector, look as the msymbol
+   again and feed all the selectors into the mill.  */
+
+static void
+completion_list_objc_symbol (struct minimal_symbol *msymbol, char *sym_text,
+                            int sym_text_len, char *text, char *word)
+{
+  static char *tmp = NULL;
+  static unsigned int tmplen = 0;
+
+  char *method, *category, *selector;
+  char *tmp2 = NULL;
+
+  method = SYMBOL_NATURAL_NAME (msymbol);
+
+  /* Is it a method?  */
+  if ((method[0] != '-') && (method[0] != '+'))
+    return;
+
+  if (sym_text[0] == '[')
+    /* Complete on shortened method method.  */
+    completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
+
+  while ((strlen (method) + 1) >= tmplen)
+    {
+      if (tmplen == 0)
+       tmplen = 1024;
+      else
+       tmplen *= 2;
+      tmp = xrealloc (tmp, tmplen);
+    }
+  selector = strchr (method, ' ');
+  if (selector != NULL)
+    selector++;
+
+  category = strchr (method, '(');
+
+  if ((category != NULL) && (selector != NULL))
+    {
+      memcpy (tmp, method, (category - method));
+      tmp[category - method] = ' ';
+      memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
+      completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+      if (sym_text[0] == '[')
+       completion_list_add_name (tmp + 1, sym_text, sym_text_len, text, word);
+    }
+
+  if (selector != NULL)
+    {
+      /* Complete on selector only.  */
+      strcpy (tmp, selector);
+      tmp2 = strchr (tmp, ']');
+      if (tmp2 != NULL)
+       *tmp2 = '\0';
+
+      completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+    }
+}
+
+/* Break the non-quoted text based on the characters which are in
+   symbols. FIXME: This should probably be language-specific. */
+
+static char *
+language_search_unquoted_string (char *text, char *p)
+{
+  for (; p > text; --p)
+    {
+      if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+       continue;
+      else
+       {
+         if ((current_language->la_language == language_objc))
+           {
+             if (p[-1] == ':')     /* might be part of a method name */
+               continue;
+             else if (p[-1] == '[' && (p[-2] == '-' || p[-2] == '+'))
+               p -= 2;             /* beginning of a method name */
+             else if (p[-1] == ' ' || p[-1] == '(' || p[-1] == ')')
+               {                   /* might be part of a method name */
+                 char *t = p;
+
+                 /* Seeing a ' ' or a '(' is not conclusive evidence
+                    that we are in the middle of a method name.  However,
+                    finding "-[" or "+[" should be pretty un-ambiguous.
+                    Unfortunately we have to find it now to decide.  */
+
+                 while (t > text)
+                   if (isalnum (t[-1]) || t[-1] == '_' ||
+                       t[-1] == ' '    || t[-1] == ':' ||
+                       t[-1] == '('    || t[-1] == ')')
+                     --t;
+                   else
+                     break;
+
+                 if (t[-1] == '[' && (t[-2] == '-' || t[-2] == '+'))
+                   p = t - 2;      /* method name detected */
+                 /* else we leave with p unchanged */
+               }
+           }
+         break;
+       }
+    }
+  return p;
+}
+
+static void
+completion_list_add_fields (struct symbol *sym, char *sym_text,
+                           int sym_text_len, char *text, char *word)
+{
+  if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+    {
+      struct type *t = SYMBOL_TYPE (sym);
+      enum type_code c = TYPE_CODE (t);
+      int j;
+
+      if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
+       for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
+         if (TYPE_FIELD_NAME (t, j))
+           completion_list_add_name (TYPE_FIELD_NAME (t, j),
+                                     sym_text, sym_text_len, text, word);
+    }
+}
+
+/* Type of the user_data argument passed to add_macro_name.  The
+   contents are simply whatever is needed by
+   completion_list_add_name.  */
+struct add_macro_name_data
+{
+  char *sym_text;
+  int sym_text_len;
+  char *text;
+  char *word;
+};
 
-   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.  */
+/* A callback used with macro_for_each and macro_for_each_in_scope.
+   This adds a macro's name to the current completion list.  */
+static void
+add_macro_name (const char *name, const struct macro_definition *ignore,
+               void *user_data)
+{
+  struct add_macro_name_data *datum = (struct add_macro_name_data *) user_data;
+  completion_list_add_name ((char *) name,
+                           datum->sym_text, datum->sym_text_len,
+                           datum->text, datum->word);
+}
 
 char **
-make_symbol_completion_list (char *text, char *word)
+default_make_symbol_completion_list (char *text, char *word)
 {
-  register struct symbol *sym;
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct minimal_symbol *msymbol;
-  register struct objfile *objfile;
-  register struct block *b, *surrounding_static_block = 0;
-  register int i, j;
+  /* 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.  */
+
+  struct symbol *sym;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct minimal_symbol *msymbol;
+  struct objfile *objfile;
+  struct block *b;
+  const struct block *surrounding_static_block, *surrounding_global_block;
+  struct dict_iterator iter;
   struct partial_symbol **psym;
   /* 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.  */
+  /* Now look for the symbol we are supposed to complete on.  */
   {
     char *p;
     char quote_found;
@@ -3268,7 +3928,8 @@ make_symbol_completion_list (char *text, char *word)
           which are in symbols.  */
        while (p > text)
          {
-           if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+           if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
+               || p[-1] == ':')
              --p;
            else
              break;
@@ -3323,83 +3984,134 @@ make_symbol_completion_list (char *text, char *word)
   {
     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);
   }
 
   /* Search upwards from currently selected frame (so that we can
-     complete on local vars.  */
+     complete on local vars).  Also catch fields of types defined in
+     this places which match our text string.  Only complete on types
+     visible from current context. */
+
+  b = get_selected_block (0);
+  surrounding_static_block = block_static_block (b);
+  surrounding_global_block = block_global_block (b);
+  if (surrounding_static_block != NULL)
+    while (b != surrounding_static_block)
+      {
+       QUIT;
 
-  for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
-    {
-      if (!BLOCK_SUPERBLOCK (b))
-       {
-         surrounding_static_block = b;         /* For elmin of dups */
-       }
+       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);
+         }
 
-      /* Also catch fields of types defined in this places which match our
-         text string.  Only complete on types visible from current context. */
+       /* Stop when we encounter an enclosing function.  Do not stop for
+          non-inlined functions - the locals of the enclosing function
+          are in scope for a nested function.  */
+       if (BLOCK_FUNCTION (b) != NULL && block_inlined_p (b))
+         break;
+       b = BLOCK_SUPERBLOCK (b);
+      }
 
-      ALL_BLOCK_SYMBOLS (b, i, sym)
-       {
-         COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
-         if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
-           {
-             struct type *t = SYMBOL_TYPE (sym);
-             enum type_code c = TYPE_CODE (t);
+  /* Add fields from the file's types; symbols will be added below.  */
 
-             if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
-               {
-                 for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
-                   {
-                     if (TYPE_FIELD_NAME (t, j))
-                       {
-                         completion_list_add_name (TYPE_FIELD_NAME (t, j),
-                                       sym_text, sym_text_len, text, word);
-                       }
-                   }
-               }
-           }
-       }
-    }
+  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);
 
   /* Go through the symtabs and check the externs and statics for
      symbols which match.  */
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     QUIT;
     b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
-    ALL_BLOCK_SYMBOLS (b, i, sym)
+    ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
        COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
       }
   }
 
-  ALL_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS (objfile, s)
   {
     QUIT;
     b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
-    /* Don't do this block twice.  */
-    if (b == surrounding_static_block)
-      continue;
-    ALL_BLOCK_SYMBOLS (b, i, sym)
+    ALL_BLOCK_SYMBOLS (b, iter, sym)
       {
        COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
       }
   }
 
+  if (current_language->la_macro_expansion == macro_expansion_c)
+    {
+      struct macro_scope *scope;
+      struct add_macro_name_data datum;
+
+      datum.sym_text = sym_text;
+      datum.sym_text_len = sym_text_len;
+      datum.text = text;
+      datum.word = word;
+
+      /* Add any macros visible in the default scope.  Note that this
+        may yield the occasional wrong result, because an expression
+        might be evaluated in a scope other than the default.  For
+        example, if the user types "break file:line if <TAB>", the
+        resulting expression will be evaluated at "file:line" -- but
+        at there does not seem to be a way to detect this at
+        completion time.  */
+      scope = default_macro_scope ();
+      if (scope)
+       {
+         macro_for_each_in_scope (scope->file, scope->line,
+                                  add_macro_name, &datum);
+         xfree (scope);
+       }
+
+      /* User-defined macros are always visible.  */
+      macro_for_each (macro_user_macros, add_macro_name, &datum);
+    }
+
   return (return_val);
 }
 
+/* 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.  */
+
+char **
+make_symbol_completion_list (char *text, char *word)
+{
+  return current_language->la_make_symbol_completion_list (text, word);
+}
+
+/* Like make_symbol_completion_list, but suitable for use as a
+   completion function.  */
+
+char **
+make_symbol_completion_list_fn (struct cmd_list_element *ignore,
+                               char *text, char *word)
+{
+  return make_symbol_completion_list (text, word);
+}
+
 /* 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;
+  struct symbol *sym;
+  struct symtab *s;
+  struct block *b;
+  struct dict_iterator iter;
   /* The symbol we are completing on.  Points in same buffer as text.  */
   char *sym_text;
   /* Length of sym_text.  */
@@ -3445,16 +4157,8 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
       }
     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;
+       /* Not a quoted string.  */
+       sym_text = language_search_unquoted_string (text, p);
       }
   }
 
@@ -3486,13 +4190,13 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile)
      symbols which match.  */
 
   b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
-  ALL_BLOCK_SYMBOLS (b, i, sym)
+  ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
       COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
     }
 
   b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
-  ALL_BLOCK_SYMBOLS (b, i, sym)
+  ALL_BLOCK_SYMBOLS (b, iter, sym)
     {
       COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
     }
@@ -3567,9 +4271,9 @@ not_interesting_fname (const char *fname)
 char **
 make_source_files_completion_list (char *text, char *word)
 {
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct objfile *objfile;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct objfile *objfile;
   int first = 1;
   int list_alloced = 1;
   int list_used = 0;
@@ -3668,7 +4372,7 @@ make_source_files_completion_list (char *text, char *word)
  */
 
 int
-in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
+in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start)
 {
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
@@ -3682,7 +4386,7 @@ in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
      - The minimal symbols and partial symbols, which can usually tell
        us the starting and ending addresses of a function.
      - If we know the function's start address, we can call the
-       architecture-defined SKIP_PROLOGUE function to analyze the
+       architecture-defined gdbarch_skip_prologue function to analyze the
        instruction stream and guess where the prologue ends.
      - Our `func_start' argument; if non-zero, this is the caller's
        best guess as to the function's entry point.  At the time of
@@ -3700,7 +4404,7 @@ in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
       if (! func_start)
        return 1;               /* We *might* be in a prologue.  */
 
-      prologue_end = SKIP_PROLOGUE (func_start);
+      prologue_end = gdbarch_skip_prologue (gdbarch, func_start);
 
       return func_start <= pc && pc < prologue_end;
     }
@@ -3724,7 +4428,7 @@ in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
       /* We don't have any good line number info, so use the minsym
         information, together with the architecture-specific prologue
         scanning code.  */
-      CORE_ADDR prologue_end = SKIP_PROLOGUE (func_addr);
+      CORE_ADDR prologue_end = gdbarch_skip_prologue (gdbarch, func_addr);
 
       return func_addr <= pc && pc < prologue_end;
     }
@@ -3733,281 +4437,440 @@ in_prologue (CORE_ADDR pc, CORE_ADDR func_start)
   return func_addr <= pc && pc < sal.end;
 }
 
+/* Given PC at the function's start address, attempt to find the
+   prologue end using SAL information.  Return zero if the skip fails.
 
-/* Begin overload resolution functions */
+   A non-optimized prologue traditionally has one SAL for the function
+   and a second for the function body.  A single line function has
+   them both pointing at the same line.
 
-static char *
-remove_params (const char *demangled_name)
-{
-  const char *argp;
-  char *new_name;
-  int depth;
+   An optimized prologue is similar but the prologue may contain
+   instructions (SALs) from the instruction body.  Need to skip those
+   while not getting into the function body.
 
-  if (demangled_name == NULL)
-    return NULL;
+   The functions end point and an increasing SAL line are used as
+   indicators of the prologue's endpoint.
 
-  /* First find the end of the arg list.  */
-  argp = strrchr (demangled_name, ')');
-  if (argp == NULL)
-    return NULL;
+   This code is based on the function refine_prologue_limit (versions
+   found in both ia64 and ppc).  */
+
+CORE_ADDR
+skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
+{
+  struct symtab_and_line prologue_sal;
+  CORE_ADDR start_pc;
+  CORE_ADDR end_pc;
+  struct block *bl;
 
-  /* Back up to the beginning.  */
-  depth = 1;
+  /* Get an initial range for the function.  */
+  find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
+  start_pc += gdbarch_deprecated_function_start_offset (gdbarch);
 
-  while (argp-- > demangled_name)
+  prologue_sal = find_pc_line (start_pc, 0);
+  if (prologue_sal.line != 0)
     {
-      if (*argp == ')')
-       depth ++;
-      else if (*argp == '(')
+      /* For langauges other than assembly, treat two consecutive line
+        entries at the same address as a zero-instruction prologue.
+        The GNU assembler emits separate line notes for each instruction
+        in a multi-instruction macro, but compilers generally will not
+        do this.  */
+      if (prologue_sal.symtab->language != language_asm)
+       {
+         struct linetable *linetable = LINETABLE (prologue_sal.symtab);
+         int exact;
+         int idx = 0;
+
+         /* Skip any earlier lines, and any end-of-sequence marker
+            from a previous function.  */
+         while (linetable->item[idx].pc != prologue_sal.pc
+                || linetable->item[idx].line == 0)
+           idx++;
+
+         if (idx+1 < linetable->nitems
+             && linetable->item[idx+1].line != 0
+             && linetable->item[idx+1].pc == start_pc)
+           return start_pc;
+       }
+
+      /* If there is only one sal that covers the entire function,
+        then it is probably a single line function, like
+        "foo(){}". */
+      if (prologue_sal.end >= end_pc)
+       return 0;
+
+      while (prologue_sal.end < end_pc)
        {
-         depth --;
+         struct symtab_and_line sal;
+
+         sal = find_pc_line (prologue_sal.end, 0);
+         if (sal.line == 0)
+           break;
+         /* Assume that a consecutive SAL for the same (or larger)
+            line mark the prologue -> body transition.  */
+         if (sal.line >= prologue_sal.line)
+           break;
 
-         if (depth == 0)
+         /* The line number is smaller.  Check that it's from the
+            same function, not something inlined.  If it's inlined,
+            then there is no point comparing the line numbers.  */
+         bl = block_for_pc (prologue_sal.end);
+         while (bl)
+           {
+             if (block_inlined_p (bl))
+               break;
+             if (BLOCK_FUNCTION (bl))
+               {
+                 bl = NULL;
+                 break;
+               }
+             bl = BLOCK_SUPERBLOCK (bl);
+           }
+         if (bl != NULL)
            break;
+
+         /* The case in which compiler's optimizer/scheduler has
+            moved instructions into the prologue.  We look ahead in
+            the function looking for address ranges whose
+            corresponding line number is less the first one that we
+            found for the function.  This is more conservative then
+            refine_prologue_limit which scans a large number of SALs
+            looking for any in the prologue */
+         prologue_sal = sal;
        }
     }
-  if (depth != 0)
-    internal_error (__FILE__, __LINE__,
-                   "bad demangled name %s\n", demangled_name);
-  while (argp[-1] == ' ' && argp > demangled_name)
-    argp --;
 
-  new_name = xmalloc (argp - demangled_name + 1);
-  memcpy (new_name, demangled_name, argp - demangled_name);
-  new_name[argp - demangled_name] = '\0';
-  return new_name;
+  if (prologue_sal.end < end_pc)
+    /* Return the end of this line, or zero if we could not find a
+       line.  */
+    return prologue_sal.end;
+  else
+    /* Don't return END_PC, which is past the end of the function.  */
+    return prologue_sal.pc;
 }
+\f
+struct symtabs_and_lines
+decode_line_spec (char *string, int funfirstline)
+{
+  struct symtabs_and_lines sals;
+  struct symtab_and_line cursal;
 
-/* Helper routine for make_symbol_completion_list.  */
-
-static int sym_return_val_size;
-static int sym_return_val_index;
-static struct symbol **sym_return_val;
-
-/*  Test to see if the symbol specified by SYMNAME (which is already
-   demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
-   characters.  If so, add it to the current completion list. */
+  if (string == 0)
+    error (_("Empty line specification."));
 
-static void
-overload_list_add_symbol (struct symbol *sym, char *oload_name)
-{
-  int newsize;
-  int i;
-  char *sym_name;
+  /* 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 ();
 
-  /* If there is no type information, we can't do anything, so skip */
-  if (SYMBOL_TYPE (sym) == NULL)
-    return;
+  sals = decode_line_1 (&string, funfirstline,
+                       cursal.symtab, cursal.line,
+                       (char ***) NULL, NULL);
 
-  /* skip any symbols that we've already considered. */
-  for (i = 0; i < sym_return_val_index; ++i)
-    if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i])))
-      return;
+  if (*string)
+    error (_("Junk at end of line specification: %s"), string);
+  return sals;
+}
 
-  /* Get the demangled name without parameters */
-  sym_name = remove_params (SYMBOL_DEMANGLED_NAME (sym));
-  if (!sym_name)
-    return;
+/* Track MAIN */
+static char *name_of_main;
 
-  /* skip symbols that cannot match */
-  if (strcmp (sym_name, oload_name) != 0)
+void
+set_main_name (const char *name)
+{
+  if (name_of_main != NULL)
     {
-      xfree (sym_name);
-      return;
+      xfree (name_of_main);
+      name_of_main = NULL;
     }
-
-  xfree (sym_name);
-
-  /* We have a match for an overload instance, so add SYM to the current list
-   * of overload instances */
-  if (sym_return_val_index + 3 > sym_return_val_size)
+  if (name != NULL)
     {
-      newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *);
-      sym_return_val = (struct symbol **) xrealloc ((char *) sym_return_val, newsize);
+      name_of_main = xstrdup (name);
     }
-  sym_return_val[sym_return_val_index++] = sym;
-  sym_return_val[sym_return_val_index] = NULL;
 }
 
-/* Return a null-terminated list of pointers to function symbols that
- * match name of the supplied symbol FSYM.
- * This is used in finding all overloaded instances of a function name.
- * This has been modified from make_symbol_completion_list.  */
+/* Deduce the name of the main procedure, and set NAME_OF_MAIN
+   accordingly.  */
 
-
-struct symbol **
-make_symbol_overload_list (struct symbol *fsym)
+static void
+find_main_name (void)
 {
-  register struct symbol *sym;
-  register struct symtab *s;
-  register struct partial_symtab *ps;
-  register struct objfile *objfile;
-  register struct block *b, *surrounding_static_block = 0;
-  register int i;
-  /* The name we are completing on. */
-  char *oload_name = NULL;
-  /* Length of name.  */
-  int oload_name_len = 0;
-
-  /* Look for the symbol we are supposed to complete on.  */
-
-  oload_name = remove_params (SYMBOL_DEMANGLED_NAME (fsym));
-  if (!oload_name)
+  const char *new_main_name;
+
+  /* Try to see if the main procedure is in Ada.  */
+  /* FIXME: brobecker/2005-03-07: Another way of doing this would
+     be to add a new method in the language vector, and call this
+     method for each language until one of them returns a non-empty
+     name.  This would allow us to remove this hard-coded call to
+     an Ada function.  It is not clear that this is a better approach
+     at this point, because all methods need to be written in a way
+     such that false positives never be returned. For instance, it is
+     important that a method does not return a wrong name for the main
+     procedure if the main procedure is actually written in a different
+     language.  It is easy to guaranty this with Ada, since we use a
+     special symbol generated only when the main in Ada to find the name
+     of the main procedure. It is difficult however to see how this can
+     be guarantied for languages such as C, for instance.  This suggests
+     that order of call for these methods becomes important, which means
+     a more complicated approach.  */
+  new_main_name = ada_main_name ();
+  if (new_main_name != NULL)
     {
-      sym_return_val_size = 1;
-      sym_return_val = (struct symbol **) xmalloc (2 * sizeof (struct symbol *));
-      sym_return_val[0] = fsym;
-      sym_return_val[1] = NULL;
+      set_main_name (new_main_name);
+      return;
+    }
 
-      return sym_return_val;
+  new_main_name = pascal_main_name ();
+  if (new_main_name != NULL)
+    {
+      set_main_name (new_main_name);
+      return;
     }
-  oload_name_len = strlen (oload_name);
 
-  sym_return_val_size = 100;
-  sym_return_val_index = 0;
-  sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *));
-  sym_return_val[0] = NULL;
+  /* The languages above didn't identify the name of the main procedure.
+     Fallback to "main".  */
+  set_main_name ("main");
+}
 
-  /* Look through the partial symtabs for all symbols which begin
-     by matching OLOAD_NAME.  Make sure we read that symbol table in. */
+char *
+main_name (void)
+{
+  if (name_of_main == NULL)
+    find_main_name ();
 
-  ALL_PSYMTABS (objfile, ps)
-  {
-    struct partial_symbol **psym;
+  return name_of_main;
+}
 
-    /* If the psymtab's been read in we'll get it when we search
-       through the blockvector.  */
-    if (ps->readin)
-      continue;
+/* Handle ``executable_changed'' events for the symtab module.  */
 
-    for (psym = objfile->global_psymbols.list + ps->globals_offset;
-        psym < (objfile->global_psymbols.list + ps->globals_offset
-                + ps->n_global_syms);
-        psym++)
-      {
-       /* If interrupted, then quit. */
-       QUIT;
-        /* This will cause the symbol table to be read if it has not yet been */
-        s = PSYMTAB_TO_SYMTAB (ps);
-      }
+static void
+symtab_observer_executable_changed (void)
+{
+  /* NAME_OF_MAIN may no longer be the same, so reset it for now.  */
+  set_main_name (NULL);
+}
 
-    for (psym = objfile->static_psymbols.list + ps->statics_offset;
-        psym < (objfile->static_psymbols.list + ps->statics_offset
-                + ps->n_static_syms);
-        psym++)
-      {
-       QUIT;
-        /* This will cause the symbol table to be read if it has not yet been */
-        s = PSYMTAB_TO_SYMTAB (ps);
-      }
-  }
+/* Helper to expand_line_sal below.  Appends new sal to SAL,
+   initializing it from SYMTAB, LINENO and PC.  */
+static void
+append_expanded_sal (struct symtabs_and_lines *sal,
+                    struct program_space *pspace,
+                    struct symtab *symtab,
+                    int lineno, CORE_ADDR pc)
+{
+  sal->sals = xrealloc (sal->sals,
+                       sizeof (sal->sals[0])
+                       * (sal->nelts + 1));
+  init_sal (sal->sals + sal->nelts);
+  sal->sals[sal->nelts].pspace = pspace;
+  sal->sals[sal->nelts].symtab = symtab;
+  sal->sals[sal->nelts].section = NULL;
+  sal->sals[sal->nelts].end = 0;
+  sal->sals[sal->nelts].line = lineno;
+  sal->sals[sal->nelts].pc = pc;
+  ++sal->nelts;
+}
 
-  /* Search upwards from currently selected frame (so that we can
-     complete on local vars.  */
+/* Helper to expand_line_sal below.  Search in the symtabs for any
+   linetable entry that exactly matches FULLNAME and LINENO and append
+   them to RET.  If FULLNAME is NULL or if a symtab has no full name,
+   use FILENAME and LINENO instead.  If there is at least one match,
+   return 1; otherwise, return 0, and return the best choice in BEST_ITEM
+   and BEST_SYMTAB.  */
 
-  for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
+static int
+append_exact_match_to_sals (char *filename, char *fullname, int lineno,
+                           struct symtabs_and_lines *ret,
+                           struct linetable_entry **best_item,
+                           struct symtab **best_symtab)
+{
+  struct program_space *pspace;
+  struct objfile *objfile;
+  struct symtab *symtab;
+  int exact = 0;
+  int j;
+  *best_item = 0;
+  *best_symtab = 0;
+
+  ALL_PSPACES (pspace)
+    ALL_PSPACE_SYMTABS (pspace, objfile, symtab)
     {
-      if (!BLOCK_SUPERBLOCK (b))
+      if (FILENAME_CMP (filename, symtab->filename) == 0)
        {
-         surrounding_static_block = b;         /* For elimination of dups */
-       }
+         struct linetable *l;
+         int len;
+         if (fullname != NULL
+             && symtab_to_fullname (symtab) != NULL
+             && FILENAME_CMP (fullname, symtab->fullname) != 0)
+           continue;             
+         l = LINETABLE (symtab);
+         if (!l)
+           continue;
+         len = l->nitems;
 
-      /* Also catch fields of types defined in this places which match our
-         text string.  Only complete on types visible from current context. */
+         for (j = 0; j < len; j++)
+           {
+             struct linetable_entry *item = &(l->item[j]);
 
-      ALL_BLOCK_SYMBOLS (b, i, sym)
-       {
-         overload_list_add_symbol (sym, oload_name);
+             if (item->line == lineno)
+               {
+                 exact = 1;
+                 append_expanded_sal (ret, objfile->pspace,
+                                      symtab, lineno, item->pc);
+               }
+             else if (!exact && item->line > lineno
+                      && (*best_item == NULL
+                          || item->line < (*best_item)->line))
+               {
+                 *best_item = item;
+                 *best_symtab = symtab;
+               }
+           }
        }
     }
-
-  /* Go through the symtabs and check the externs and statics for
-     symbols which match.  */
-
-  ALL_SYMTABS (objfile, s)
-  {
-    QUIT;
-    b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
-    ALL_BLOCK_SYMBOLS (b, i, sym)
-      {
-       overload_list_add_symbol (sym, oload_name);
-      }
-  }
-
-  ALL_SYMTABS (objfile, s)
-  {
-    QUIT;
-    b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
-    /* Don't do this block twice.  */
-    if (b == surrounding_static_block)
-      continue;
-    ALL_BLOCK_SYMBOLS (b, i, sym)
-      {
-       overload_list_add_symbol (sym, oload_name);
-      }
-  }
-
-  xfree (oload_name);
-
-  return (sym_return_val);
+  return exact;
 }
 
-/* End of overload resolution functions */
-\f
+/* Compute a set of all sals in all program spaces that correspond to
+   same file and line as SAL and return those.  If there are several
+   sals that belong to the same block, only one sal for the block is
+   included in results.  */
+
 struct symtabs_and_lines
-decode_line_spec (char *string, int funfirstline)
+expand_line_sal (struct symtab_and_line sal)
 {
-  struct symtabs_and_lines sals;
-  if (string == 0)
-    error ("Empty line specification.");
-  sals = decode_line_1 (&string, funfirstline,
-                       current_source_symtab, current_source_line,
-                       (char ***) NULL);
-  if (*string)
-    error ("Junk at end of line specification: %s", string);
-  return sals;
-}
+  struct symtabs_and_lines ret, this_line;
+  int i, j;
+  struct objfile *objfile;
+  struct partial_symtab *psymtab;
+  struct symtab *symtab;
+  int lineno;
+  int deleted = 0;
+  struct block **blocks = NULL;
+  int *filter;
+  struct cleanup *old_chain;
 
-/* Track MAIN */
-static char *name_of_main;
+  ret.nelts = 0;
+  ret.sals = NULL;
 
-void
-set_main_name (const char *name)
-{
-  if (name_of_main != NULL)
+  /* Only expand sals that represent file.c:line.  */
+  if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
     {
-      xfree (name_of_main);
-      name_of_main = NULL;
+      ret.sals = xmalloc (sizeof (struct symtab_and_line));
+      ret.sals[0] = sal;
+      ret.nelts = 1;
+      return ret;
     }
-  if (name != NULL)
+  else
     {
-      name_of_main = xstrdup (name);
+      struct program_space *pspace;
+      struct linetable_entry *best_item = 0;
+      struct symtab *best_symtab = 0;
+      int exact = 0;
+      char *match_filename;
+
+      lineno = sal.line;
+      match_filename = sal.symtab->filename;
+
+      /* We need to find all symtabs for a file which name
+        is described by sal.  We cannot just directly
+        iterate over symtabs, since a symtab might not be
+        yet created.  We also cannot iterate over psymtabs,
+        calling PSYMTAB_TO_SYMTAB and working on that symtab,
+        since PSYMTAB_TO_SYMTAB will return NULL for psymtab
+        corresponding to an included file.  Therefore, we do
+        first pass over psymtabs, reading in those with
+        the right name.  Then, we iterate over symtabs, knowing
+        that all symtabs we're interested in are loaded.  */
+
+      old_chain = save_current_program_space ();
+      ALL_PSPACES (pspace)
+       ALL_PSPACE_PSYMTABS (pspace, objfile, psymtab)
+       {
+         if (FILENAME_CMP (match_filename, psymtab->filename) == 0)
+           {
+             set_current_program_space (pspace);
+
+             PSYMTAB_TO_SYMTAB (psymtab);
+           }
+       }
+      do_cleanups (old_chain);
+
+      /* Now search the symtab for exact matches and append them.  If
+        none is found, append the best_item and all its exact
+        matches.  */
+      symtab_to_fullname (sal.symtab);
+      exact = append_exact_match_to_sals (sal.symtab->filename,
+                                         sal.symtab->fullname, lineno,
+                                         &ret, &best_item, &best_symtab);
+      if (!exact && best_item)
+       append_exact_match_to_sals (best_symtab->filename,
+                                   best_symtab->fullname, best_item->line,
+                                   &ret, &best_item, &best_symtab);
     }
-}
 
-char *
-main_name (void)
-{
-  if (name_of_main != NULL)
-    return name_of_main;
-  else
-    return "main";
+  /* For optimized code, compiler can scatter one source line accross
+     disjoint ranges of PC values, even when no duplicate functions
+     or inline functions are involved.  For example, 'for (;;)' inside
+     non-template non-inline non-ctor-or-dtor function can result
+     in two PC ranges.  In this case, we don't want to set breakpoint
+     on first PC of each range.  To filter such cases, we use containing
+     blocks -- for each PC found above we see if there are other PCs
+     that are in the same block.  If yes, the other PCs are filtered out.  */
+
+  old_chain = save_current_program_space ();
+  filter = alloca (ret.nelts * sizeof (int));
+  blocks = alloca (ret.nelts * sizeof (struct block *));
+  for (i = 0; i < ret.nelts; ++i)
+    {
+      struct blockvector *bl;
+      struct block *b;
+
+      set_current_program_space (ret.sals[i].pspace);
+
+      filter[i] = 1;
+      blocks[i] = block_for_pc_sect (ret.sals[i].pc, ret.sals[i].section);
+
+    }
+  do_cleanups (old_chain);
+
+  for (i = 0; i < ret.nelts; ++i)
+    if (blocks[i] != NULL)
+      for (j = i+1; j < ret.nelts; ++j)
+       if (blocks[j] == blocks[i])
+         {
+           filter[j] = 0;
+           ++deleted;
+           break;
+         }
+
+  {
+    struct symtab_and_line *final =
+      xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
+
+    for (i = 0, j = 0; i < ret.nelts; ++i)
+      if (filter[i])
+       final[j++] = ret.sals[i];
+
+    ret.nelts -= deleted;
+    xfree (ret.sals);
+    ret.sals = final;
+  }
+
+  return ret;
 }
 
 
 void
 _initialize_symtab (void)
 {
-  add_info ("variables", variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+  add_info ("variables", variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
   if (dbx_commands)
-    add_com ("whereis", class_info, variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+    add_com ("whereis", class_info, variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
 
   add_info ("functions", functions_info,
-           "All function names, or those matching REGEXP.");
+           _("All function names, or those matching REGEXP."));
 
-  
   /* FIXME:  This command has at least the following problems:
      1.  It prints builtin types (in a very strange and confusing fashion).
      2.  It doesn't print right, e.g. with
@@ -4017,29 +4880,30 @@ _initialize_symtab (void)
      I also think "ptype" or "whatis" is more likely to be useful (but if
      there is much disagreement "info types" can be fixed).  */
   add_info ("types", types_info,
-           "All type names, or those matching REGEXP.");
-
-#if 0
-  add_info ("methods", methods_info,
-           "All method names, or those matching REGEXP::REGEXP.\n\
-If the class qualifier is omitted, it is assumed to be the current scope.\n\
-If the first REGEXP is omitted, then all methods matching the second REGEXP\n\
-are listed.");
-#endif
+           _("All type names, or those matching REGEXP."));
+
   add_info ("sources", sources_info,
-           "Source files in the program.");
+           _("Source files in the program."));
 
   add_com ("rbreak", class_breakpoint, rbreak_command,
-          "Set a breakpoint for all functions matching REGEXP.");
+          _("Set a breakpoint for all functions matching REGEXP."));
 
   if (xdb_commands)
     {
-      add_com ("lf", class_info, sources_info, "Source files in the program");
-      add_com ("lg", class_info, variables_info,
-        "All global and static variable names, or those matching REGEXP.");
+      add_com ("lf", class_info, sources_info,
+              _("Source files in the program"));
+      add_com ("lg", class_info, variables_info, _("\
+All global and static variable names, or those matching REGEXP."));
     }
 
-  /* Initialize the one built-in type that isn't language dependent... */
-  builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0,
-                                 "<unknown type>", (struct objfile *) NULL);
+  add_setshow_enum_cmd ("multiple-symbols", no_class,
+                        multiple_symbols_modes, &multiple_symbols_mode,
+                        _("\
+Set the debugger behavior when more than one symbol are possible matches\n\
+in an expression."), _("\
+Show how the debugger handles ambiguities in expressions."), _("\
+Valid values are \"ask\", \"all\", \"cancel\", and the default is \"all\"."),
+                        NULL, NULL, &setlist, &showlist);
+
+  observer_attach_executable_changed (symtab_observer_executable_changed);
 }
This page took 0.081368 seconds and 4 git commands to generate.