2010-05-14 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / linespec.c
index fc64ebe0f715a07ada7dc5652741c17b656e1174..378c6c940cf61af7942e92cce8a7c8d54adb8dec 100644 (file)
@@ -1,13 +1,14 @@
 /* Parser for linespec for the GNU debugger, GDB.
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   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, 2005, 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,
@@ -16,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 "value.h"
 #include "completer.h"
 #include "cp-abi.h"
+#include "cp-support.h"
 #include "parser-defs.h"
+#include "block.h"
+#include "objc-lang.h"
+#include "linespec.h"
+#include "exceptions.h"
+#include "language.h"
+#include "interps.h"
+#include "mi/mi-cmds.h"
+#include "target.h"
+#include "arch-utils.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -42,36 +51,62 @@ extern char *operator_chars (char *, char **);
 static void initialize_defaults (struct symtab **default_symtab,
                                 int *default_line);
 
-static void set_flags (char *arg, int *is_quoted, char **paren_pointer);
-
 static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
 
+static struct symtabs_and_lines decode_objc (char **argptr,
+                                            int funfirstline,
+                                            struct symtab *file_symtab,
+                                            char ***canonical,
+                                            char *saved_arg);
+
 static struct symtabs_and_lines decode_compound (char **argptr,
                                                 int funfirstline,
                                                 char ***canonical,
                                                 char *saved_arg,
-                                                char *p);
+                                                char *p,
+                                                int *not_found_ptr);
+
+static struct symbol *lookup_prefix_sym (char **argptr, char *p);
+
+static struct symtabs_and_lines find_method (int funfirstline,
+                                            char ***canonical,
+                                            char *saved_arg,
+                                            char *copy,
+                                            struct type *t,
+                                            struct symbol *sym_class,
+                                            int *not_found_ptr);
 
-static NORETURN void cplusplus_error (const char *name,
-                                     const char *fmt, ...)
-     ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
+static void cplusplus_error (const char *name, const char *fmt, ...)
+     ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
 
 static int total_number_of_methods (struct type *type);
 
-static int find_methods (struct type *, char *, struct symbol **);
+static int find_methods (struct type *, char *,
+                        enum language, struct symbol **);
+
+static int add_matching_methods (int method_counter, struct type *t,
+                                enum language language,
+                                struct symbol **sym_arr);
+
+static int add_constructors (int method_counter, struct type *t,
+                            enum language language,
+                            struct symbol **sym_arr);
 
 static void build_canonical_line_spec (struct symtab_and_line *,
                                       char *, char ***);
 
 static char *find_toplevel_char (char *s, char c);
 
+static int is_objc_method_format (const char *s);
+
 static struct symtabs_and_lines decode_line_2 (struct symbol *[],
                                               int, int, char ***);
 
 static struct symtab *symtab_from_filename (char **argptr,
-                                           char *p, int is_quote_enclosed);
+                                           char *p, int is_quote_enclosed,
+                                           int *not_found_ptr);
 
 static struct
 symtabs_and_lines decode_all_digits (char **argptr,
@@ -90,15 +125,15 @@ static struct symtabs_and_lines decode_dollar (char *copy,
 static struct symtabs_and_lines decode_variable (char *copy,
                                                 int funfirstline,
                                                 char ***canonical,
-                                                struct symtab *file_symtab);
+                                                struct symtab *file_symtab,
+                                                int *not_found_ptr);
 
 static struct
 symtabs_and_lines symbol_found (int funfirstline,
                                char ***canonical,
                                char *copy,
                                struct symbol *sym,
-                               struct symtab *file_symtab,
-                               struct symtab *sym_symtab);
+                               struct symtab *file_symtab);
 
 static struct
 symtabs_and_lines minsym_found (int funfirstline,
@@ -110,15 +145,18 @@ symtabs_and_lines minsym_found (int funfirstline,
    single quoted demangled C++ symbols as part of the completion
    error.  */
 
-static NORETURN void
+static void
 cplusplus_error (const char *name, const char *fmt, ...)
 {
   struct ui_file *tmp_stream;
+  char *message;
+
   tmp_stream = mem_fileopen ();
   make_cleanup_ui_file_delete (tmp_stream);
 
   {
     va_list args;
+
     va_start (args, fmt);
     vfprintf_unfiltered (tmp_stream, fmt, args);
     va_end (args);
@@ -130,7 +168,10 @@ cplusplus_error (const char *name, const char *fmt, ...)
                      ("Hint: try '%s<TAB> or '%s<ESC-?>\n"
                       "(Note leading single quote.)"),
                      name, name);
-  error_stream (tmp_stream);
+
+  message = ui_file_xstrdup (tmp_stream, NULL);
+  make_cleanup (xfree, message);
+  throw_error (NOT_FOUND_ERROR, "%s", message);
 }
 
 /* Return the number of methods described for TYPE, including the
@@ -145,7 +186,7 @@ total_number_of_methods (struct type *type)
   int count;
 
   CHECK_TYPEDEF (type);
-  if (TYPE_CPLUS_SPECIFIC (type) == NULL)
+  if (! HAVE_CPLUS_STRUCT (type))
     return 0;
   count = TYPE_NFN_FIELDS_TOTAL (type);
 
@@ -163,7 +204,8 @@ total_number_of_methods (struct type *type)
    Note that this function is g++ specific.  */
 
 static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
+find_methods (struct type *t, char *name, enum language language,
+             struct symbol **sym_arr)
 {
   int i1 = 0;
   int ibase;
@@ -173,9 +215,8 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
      unless we figure out how to get the physname without the name of
      the class, then the loop can't do any good.  */
   if (class_name
-      && (lookup_symbol (class_name, (struct block *) NULL,
-                        STRUCT_NAMESPACE, (int *) NULL,
-                        (struct symtab **) NULL)))
+      && (lookup_symbol_in_language (class_name, (struct block *) NULL,
+                        STRUCT_DOMAIN, language, (int *) NULL)))
     {
       int method_counter;
       int name_len = strlen (name);
@@ -190,7 +231,6 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
           method_counter >= 0;
           --method_counter)
        {
-         int field_counter;
          char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
          char dem_opname[64];
 
@@ -206,86 +246,13 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
 
          if (strcmp_iw (name, method_name) == 0)
            /* Find all the overloaded methods with that name.  */
-           for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
-                field_counter >= 0;
-                --field_counter)
-             {
-               struct fn_field *f;
-               char *phys_name;
-
-               f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
-               if (TYPE_FN_FIELD_STUB (f, field_counter))
-                 {
-                   char *tmp_name;
-
-                   tmp_name = gdb_mangle_name (t,
-                                               method_counter,
-                                               field_counter);
-                   phys_name = alloca (strlen (tmp_name) + 1);
-                   strcpy (phys_name, tmp_name);
-                   xfree (tmp_name);
-                 }
-               else
-                 phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-               
-               /* Destructor is handled by caller, dont add it to the list */
-               if (is_destructor_name (phys_name) != 0)
-                 continue;
-
-               sym_arr[i1] = lookup_symbol (phys_name,
-                                            NULL, VAR_NAMESPACE,
-                                            (int *) NULL,
-                                            (struct symtab **) NULL);
-               if (sym_arr[i1])
-                 i1++;
-               else
-                 {
-                   /* This error message gets printed, but the method
-                      still seems to be found
-                      fputs_filtered("(Cannot find method ", gdb_stdout);
-                      fprintf_symbol_filtered (gdb_stdout, phys_name,
-                      language_cplus,
-                      DMGL_PARAMS | DMGL_ANSI);
-                      fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
-                    */
-                 }
-             }
+           i1 += add_matching_methods (method_counter, t, language,
+                                       sym_arr + i1);
          else if (strncmp (class_name, name, name_len) == 0
                   && (class_name[name_len] == '\0'
                       || class_name[name_len] == '<'))
-           {
-             /* For GCC 3.x and stabs, constructors and destructors have names
-                like __base_ctor and __complete_dtor.  Check the physname for now
-                if we're looking for a constructor.  */
-             for (field_counter
-                    = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
-                  field_counter >= 0;
-                  --field_counter)
-               {
-                 struct fn_field *f;
-                 char *phys_name;
-                 
-                 f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
-                 /* GCC 3.x will never produce stabs stub methods, so we don't need
-                    to handle this case.  */
-                 if (TYPE_FN_FIELD_STUB (f, field_counter))
-                   continue;
-                 phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-                 if (! is_constructor_name (phys_name))
-                   continue;
-
-                 /* If this method is actually defined, include it in the
-                    list.  */
-                 sym_arr[i1] = lookup_symbol (phys_name,
-                                              NULL, VAR_NAMESPACE,
-                                              (int *) NULL,
-                                              (struct symtab **) NULL);
-                 if (sym_arr[i1])
-                   i1++;
-               }
-           }
+           i1 += add_constructors (method_counter, t, language,
+                                   sym_arr + i1);
        }
     }
 
@@ -302,7 +269,110 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
 
   if (i1 == 0)
     for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
-      i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
+      i1 += find_methods (TYPE_BASECLASS (t, ibase), name,
+                         language, sym_arr + i1);
+
+  return i1;
+}
+
+/* Add the symbols associated to methods of the class whose type is T
+   and whose name matches the method indexed by METHOD_COUNTER in the
+   array SYM_ARR.  Return the number of methods added.  */
+
+static int
+add_matching_methods (int method_counter, struct type *t,
+                     enum language language, struct symbol **sym_arr)
+{
+  int field_counter;
+  int i1 = 0;
+
+  for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+       field_counter >= 0;
+       --field_counter)
+    {
+      struct fn_field *f;
+      char *phys_name;
+
+      f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+      if (TYPE_FN_FIELD_STUB (f, field_counter))
+       {
+         char *tmp_name;
+
+         tmp_name = gdb_mangle_name (t,
+                                     method_counter,
+                                     field_counter);
+         phys_name = alloca (strlen (tmp_name) + 1);
+         strcpy (phys_name, tmp_name);
+         xfree (tmp_name);
+       }
+      else
+       phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+
+      sym_arr[i1] = lookup_symbol_in_language (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  language,
+                                  (int *) NULL);
+      if (sym_arr[i1])
+       i1++;
+      else
+       {
+         /* This error message gets printed, but the method
+            still seems to be found
+            fputs_filtered("(Cannot find method ", gdb_stdout);
+            fprintf_symbol_filtered (gdb_stdout, phys_name,
+            language_cplus,
+            DMGL_PARAMS | DMGL_ANSI);
+            fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
+         */
+       }
+    }
+
+  return i1;
+}
+
+/* Add the symbols associated to constructors of the class whose type
+   is CLASS_TYPE and which are indexed by by METHOD_COUNTER to the
+   array SYM_ARR.  Return the number of methods added.  */
+
+static int
+add_constructors (int method_counter, struct type *t,
+                 enum language language, struct symbol **sym_arr)
+{
+  int field_counter;
+  int i1 = 0;
+
+  /* For GCC 3.x and stabs, constructors and destructors
+     have names like __base_ctor and __complete_dtor.
+     Check the physname for now if we're looking for a
+     constructor.  */
+  for (field_counter
+        = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+       field_counter >= 0;
+       --field_counter)
+    {
+      struct fn_field *f;
+      char *phys_name;
+
+      f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+      /* GCC 3.x will never produce stabs stub methods, so
+        we don't need to handle this case.  */
+      if (TYPE_FN_FIELD_STUB (f, field_counter))
+       continue;
+      phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+      if (! is_constructor_name (phys_name))
+       continue;
+
+      /* If this method is actually defined, include it in the
+        list.  */
+      sym_arr[i1] = lookup_symbol_in_language (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  language,
+                                  (int *) NULL);
+      if (sym_arr[i1])
+       i1++;
+    }
 
   return i1;
 }
@@ -358,7 +428,7 @@ find_toplevel_char (char *s, char c)
   int quoted = 0;              /* zero if we're not in quotes;
                                   '"' if we're in a double-quoted string;
                                   '\'' if we're in a single-quoted string.  */
-  int depth = 0;               /* number of unclosed parens we've seen */
+  int depth = 0;               /* Number of unclosed parens we've seen.  */
   char *scan;
 
   for (scan = s; *scan; scan++)
@@ -383,6 +453,25 @@ find_toplevel_char (char *s, char c)
   return 0;
 }
 
+/* Determines if the gives string corresponds to an Objective-C method
+   representation, such as -[Foo bar:] or +[Foo bar]. Objective-C symbols
+   are allowed to have spaces and parentheses in them.  */
+
+static int 
+is_objc_method_format (const char *s)
+{
+  if (s == NULL || *s == '\0')
+    return 0;
+  /* Handle arguments with the format FILENAME:SYMBOL.  */
+  if ((s[0] == ':') && (strchr ("+-", s[1]) != NULL) 
+      && (s[2] == '[') && strchr(s, ']'))
+    return 1;
+  /* Handle arguments that are just SYMBOL.  */
+  else if ((strchr ("+-", s[0]) != NULL) && (s[1] == '[') && strchr(s, ']'))
+    return 1;
+  return 0;
+}
+
 /* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
    operate on (ask user if necessary).
    If CANONICAL is non-NULL return a corresponding array of mangled names
@@ -399,7 +488,13 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
   char *symname;
   struct cleanup *old_chain;
   char **canonical_arr = (char **) NULL;
+  const char *select_mode = multiple_symbols_select_mode ();
 
+  if (select_mode == multiple_symbols_cancel)
+    error (_("\
+canceled because the command is ambiguous\n\
+See set/show multiple-symbol."));
+  
   values.sals = (struct symtab_and_line *)
     alloca (nelts * sizeof (struct symtab_and_line));
   return_values.sals = (struct symtab_and_line *)
@@ -415,33 +510,56 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
     }
 
   i = 0;
-  printf_unfiltered ("[0] cancel\n[1] all\n");
   while (i < nelts)
     {
-      init_sal (&return_values.sals[i]);       /* initialize to zeroes */
+      init_sal (&return_values.sals[i]);       /* Initialize to zeroes.  */
       init_sal (&values.sals[i]);
       if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
-       {
-         values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
-         printf_unfiltered ("[%d] %s at %s:%d\n",
-                            (i + 2),
-                            SYMBOL_SOURCE_NAME (sym_arr[i]),
-                            values.sals[i].symtab->filename,
-                            values.sals[i].line);
-       }
-      else
-       printf_unfiltered ("?HERE\n");
+       values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
       i++;
     }
 
-  if ((prompt = getenv ("PS2")) == NULL)
+  /* If select_mode is "all", then do not print the multiple-choice
+     menu and act as if the user had chosen choice "1" (all).  */
+  if (select_mode == multiple_symbols_all
+      || ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+    args = "1";
+  else
     {
-      prompt = "> ";
+      i = 0;
+      printf_unfiltered (_("[0] cancel\n[1] all\n"));
+      while (i < nelts)
+        {
+          if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+            {
+              if (values.sals[i].symtab)
+                printf_unfiltered ("[%d] %s at %s:%d\n",
+                                   (i + 2),
+                                   SYMBOL_PRINT_NAME (sym_arr[i]),
+                                   values.sals[i].symtab->filename,
+                                   values.sals[i].line);
+              else
+                printf_unfiltered (_("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n"),
+                                   (i + 2),
+                                   SYMBOL_PRINT_NAME (sym_arr[i]),
+                                   values.sals[i].line);
+
+            }
+          else
+            printf_unfiltered (_("?HERE\n"));
+          i++;
+        }
+
+      prompt = getenv ("PS2");
+      if (prompt == NULL)
+        {
+          prompt = "> ";
+        }
+      args = command_line_input (prompt, 0, "overload-choice");
     }
-  args = command_line_input (prompt, 0, "overload-choice");
 
   if (args == 0 || *args == 0)
-    error_no_arg ("one or more choice numbers");
+    error_no_arg (_("one or more choice numbers"));
 
   i = 0;
   while (*args)
@@ -452,12 +570,12 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
       while (*arg1 >= '0' && *arg1 <= '9')
        arg1++;
       if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
-       error ("Arguments must be choice numbers.");
+       error (_("Arguments must be choice numbers."));
 
       num = atoi (args);
 
       if (num == 0)
-       error ("canceled");
+       error (_("canceled"));
       else if (num == 1)
        {
          if (canonical_arr)
@@ -466,8 +584,8 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
                {
                  if (canonical_arr[i] == NULL)
                    {
-                     symname = SYMBOL_NAME (sym_arr[i]);
-                     canonical_arr[i] = savestring (symname, strlen (symname));
+                     symname = SYMBOL_LINKAGE_NAME (sym_arr[i]);
+                     canonical_arr[i] = xstrdup (symname);
                    }
                }
            }
@@ -480,7 +598,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
 
       if (num >= nelts + 2)
        {
-         printf_unfiltered ("No choice number %d.\n", num);
+         printf_unfiltered (_("No choice number %d.\n"), num);
        }
       else
        {
@@ -489,16 +607,16 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
            {
              if (canonical_arr)
                {
-                 symname = SYMBOL_NAME (sym_arr[num]);
+                 symname = SYMBOL_LINKAGE_NAME (sym_arr[num]);
                  make_cleanup (xfree, symname);
-                 canonical_arr[i] = savestring (symname, strlen (symname));
+                 canonical_arr[i] = xstrdup (symname);
                }
              return_values.sals[i++] = values.sals[num];
              values.sals[num].pc = 0;
            }
          else
            {
-             printf_unfiltered ("duplicate request for %d ignored.\n", num);
+             printf_unfiltered (_("duplicate request for %d ignored.\n"), num);
            }
        }
 
@@ -510,6 +628,37 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
   discard_cleanups (old_chain);
   return return_values;
 }
+
+/* A helper function for decode_line_1 and friends which skips P
+   past any method overload information at the beginning of P, e.g.,
+   "(const struct foo *)".
+
+   This function assumes that P has already been validated to contain
+   overload information, and it will assert if *P != '('.  */
+static char *
+find_method_overload_end (char *p)
+{
+  int depth = 0;
+
+  gdb_assert (*p == '(');
+
+  while (*p)
+    {
+      if (*p == '(')
+       ++depth;
+      else if (*p == ')')
+       {
+         if (--depth == 0)
+           {
+             ++p;
+             break;
+           }
+       }
+      ++p;
+    }
+
+  return p;
+}
 \f
 /* The parser of linespec itself. */
 
@@ -548,7 +697,12 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
 
    Note that it is possible to return zero for the symtab
    if no file is validly specified.  Callers must check that.
-   Also, the line number returned may be invalid.  */
+   Also, the line number returned may be invalid.  
+   If NOT_FOUND_PTR is not null, store a boolean true/false value at the location, based
+   on whether or not failure occurs due to an unknown function or file.  In the case
+   where failure does occur due to an unknown function or file, do not issue an error
+   message.  */
 
 /* We allow single quotes in various places.  This is a hideous
    kludge, which exists because the completer can't yet deal with the
@@ -557,7 +711,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
 
 struct symtabs_and_lines
 decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
-              int default_line, char ***canonical)
+              int default_line, char ***canonical, int *not_found_ptr)
 {
   char *p;
   char *q;
@@ -565,97 +719,119 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   struct symtab *file_symtab = NULL;
 
   char *copy;
-  /* This is NULL if there are no parens in *ARGPTR, or a pointer to
-     the closing parenthesis if there are parens.  */
-  char *paren_pointer;
   /* This says whether or not something in *ARGPTR is quoted with
      completer_quotes (i.e. with single quotes).  */
   int is_quoted;
-  /* Is part of *ARGPTR is enclosed in double quotes?  */
+  /* Is *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
+  int is_objc_method = 0;
   char *saved_arg = *argptr;
+  /* If IS_QUOTED, the end of the quoted bit.  */
+  char *end_quote = NULL;
+  /* The "first half" of the linespec.  */
+  char *first_half;
+
+  if (not_found_ptr)
+    *not_found_ptr = 0;
 
   /* Defaults have defaults.  */
 
   initialize_defaults (&default_symtab, &default_line);
   
-  /* See if arg is *PC */
+  /* See if arg is *PC */
 
   if (**argptr == '*')
     return decode_indirect (argptr);
 
-  /* Set various flags.
-   * 'paren_pointer' is important for overload checking, where
-   * we allow things like: 
-   *     (gdb) break c::f(int)
-   */
-
-  set_flags (*argptr, &is_quoted, &paren_pointer);
+  is_quoted = (*argptr
+              && strchr (get_gdb_completer_quote_characters (),
+                         **argptr) != NULL);
+  if (is_quoted)
+    end_quote = skip_quoted (*argptr);
 
   /* Check to see if it's a multipart linespec (with colons or
      periods).  */
 
-  /* Locate the end of the first half of the linespec.  */
+  /* Locate the end of the first half of the linespec.
+     After the call, for instance, if the argptr string is "foo.c:123"
+     p will point at "123".  If there is only one part, like "foo", p
+     will point to "". If this is a C++ name, like "A::B::foo", p will
+     point to "::B::foo". Argptr is not changed by this call.  */
+
+  first_half = p = locate_first_half (argptr, &is_quote_enclosed);
+
+  /* Check if this is an Objective-C method (anything that starts with
+     a '+' or '-' and a '[').  */
+  if (is_objc_method_format (p))
+    is_objc_method = 1;
+
+  /* Check if the symbol could be an Objective-C selector.  */
+
+  {
+    struct symtabs_and_lines values;
 
-  p = locate_first_half (argptr, &is_quote_enclosed);
+    values = decode_objc (argptr, funfirstline, NULL,
+                         canonical, saved_arg);
+    if (values.sals != NULL)
+      return values;
+  }
 
   /* Does it look like there actually were two parts?  */
 
-  if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
+  if (p[0] == ':' || p[0] == '.')
     {
-      if (is_quoted)
-       *argptr = *argptr + 1;
-      
-      /* Is it a C++ or Java compound data structure?  */
-
+      /* Is it a C++ or Java compound data structure?
+        The check on p[1] == ':' is capturing the case of "::",
+        since p[0]==':' was checked above.  
+        Note that the call to decode_compound does everything
+        for us, including the lookup on the symbol table, so we
+        can return now. */
+       
       if (p[0] == '.' || p[1] == ':')
-       return decode_compound (argptr, funfirstline, canonical,
-                               saved_arg, p);
+       {
+         struct symtabs_and_lines values;
+
+         if (is_quote_enclosed)
+           ++saved_arg;
+         values = decode_compound (argptr, funfirstline, canonical,
+                                   saved_arg, p, not_found_ptr);
+         if (is_quoted && **argptr == '\'')
+           *argptr = *argptr + 1;
+         return values;
+       }
 
-      /* No, the first part is a filename; set s to be that file's
+      /* No, the first part is a filename; set file_symtab to be that file's
         symtab.  Also, move argptr past the filename.  */
 
-      file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed);
-    }
-#if 0
-  /* No one really seems to know why this was added. It certainly
-     breaks the command line, though, whenever the passed
-     name is of the form ClassName::Method. This bit of code
-     singles out the class name, and if funfirstline is set (for
-     example, you are setting a breakpoint at this function),
-     you get an error. This did not occur with earlier
-     verions, so I am ifdef'ing this out. 3/29/99 */
-  else
-    {
-      /* Check if what we have till now is a symbol name */
-
-      /* We may be looking at a template instantiation such
-         as "foo<int>".  Check here whether we know about it,
-         instead of falling through to the code below which
-         handles ordinary function names, because that code
-         doesn't like seeing '<' and '>' in a name -- the
-         skip_quoted call doesn't go past them.  So see if we
-         can figure it out right now. */
+      file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
+                                         not_found_ptr);
 
-      copy = (char *) alloca (p - *argptr + 1);
-      memcpy (copy, *argptr, p - *argptr);
-      copy[p - *argptr] = '\000';
-      sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
-      if (sym)
+      /* Check for single quotes on the non-filename part.  */
+      if (!is_quoted)
        {
-         *argptr = (*p == '\'') ? p + 1 : p;
-         return symbol_found (funfirstline, canonical, copy, sym,
-                              NULL, sym_symtab);
+         is_quoted = (**argptr
+                      && strchr (get_gdb_completer_quote_characters (),
+                                 **argptr) != NULL);
+         if (is_quoted)
+           end_quote = skip_quoted (*argptr);
        }
-      /* Otherwise fall out from here and go to file/line spec
-         processing, etc. */
     }
-#endif
 
-  /* S is specified file's symtab, or 0 if no file specified.
+  /* file_symtab is specified file's symtab, or 0 if no file specified.
      arg no longer contains the file name.  */
 
-  /* Check whether arg is all digits (and sign) */
+  /* If the filename was quoted, we must re-check the quotation.  */
+
+  if (end_quote == first_half && *end_quote!= '\0')
+    {
+      is_quoted = (**argptr
+                  && strchr (get_gdb_completer_quote_characters (),
+                             **argptr) != NULL);
+      if (is_quoted)
+       end_quote = skip_quoted (*argptr);
+    }
+
+  /* Check whether arg is all digits (and sign).  */
 
   q = *argptr;
   if (*q == '-' || *q == '+')
@@ -671,23 +847,37 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   /* Arg token is not digits => try it as a variable name
      Find the next token (everything up to end or next whitespace).  */
 
-  if (**argptr == '$')         /* May be a convenience variable */
-    p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));       /* One or two $ chars possible */
+  if (**argptr == '$')         /* May be a convenience variable.  */
+    /* One or two $ chars possible.  */
+    p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));
   else if (is_quoted)
     {
-      p = skip_quoted (*argptr);
+      p = end_quote;
       if (p[-1] != '\'')
-       error ("Unmatched single quote.");
+       error (_("Unmatched single quote."));
     }
-  else if (paren_pointer != NULL)
+  else if (is_objc_method)
     {
-      p = paren_pointer + 1;
+      /* allow word separators in method names for Obj-C */
+      p = skip_quoted_chars (*argptr, NULL, "");
     }
   else
     {
       p = skip_quoted (*argptr);
     }
 
+  /* Keep any template parameters */
+  if (*p == '<')
+    p = find_template_name_end (p);
+
+  /* Keep method overload information.  */
+  if (*p == '(')
+    p = find_method_overload_end (p);
+
+  /* Make sure we keep important kewords like "const" */
+  if (strncmp (p, " const", 6) == 0)
+    p += 6;
+
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
   copy[p - *argptr] = '\0';
@@ -699,13 +889,15 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       copy[p - *argptr - 1] = '\0';
       copy++;
     }
+  else if (is_quoted)
+    copy[p - *argptr - 1] = '\0';
   while (*p == ' ' || *p == '\t')
     p++;
   *argptr = p;
 
   /* If it starts with $: may be a legitimate variable or routine name
      (e.g. HP-UX millicode routines such as $$dyncall), or it may
-     be history value, or it may be a convenience variable */
+     be history value, or it may be a convenience variable */
 
   if (*copy == '$')
     return decode_dollar (copy, funfirstline, default_symtab,
@@ -714,7 +906,8 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   /* Look up that token as a variable.
      If file specified, use that file's per-file block to start with.  */
 
-  return decode_variable (copy, funfirstline, canonical, file_symtab);
+  return decode_variable (copy, funfirstline, canonical,
+                         file_symtab, not_found_ptr);
 }
 
 \f
@@ -732,10 +925,9 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
    function is passed ARGPTR as an argument, it modifies what ARGPTR
    points to; typically, it advances *ARGPTR past whatever substring
    it has just looked at.  (If it doesn't modify *ARGPTR, then the
-   function gets passed *ARGPTR instead, which is then called ARG: see
-   set_flags, for example.)  Also, functions that return a struct
-   symtabs_and_lines may modify CANONICAL, as in the description of
-   decode_line_1.
+   function gets passed *ARGPTR instead, which is then called ARG.)
+   Also, functions that return a struct symtabs_and_lines may modify
+   CANONICAL, as in the description of decode_line_1.
 
    If a function returns a struct symtabs_and_lines, then that struct
    will immediately make its way up the call chain to be returned by
@@ -762,46 +954,6 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
     }
 }
 
-static void
-set_flags (char *arg, int *is_quoted, char **paren_pointer)
-{
-  char *ii;
-  int has_if = 0;
-
-  /* 'has_if' is for the syntax:
-   *     (gdb) break foo if (a==b)
-   */
-  if ((ii = strstr (arg, " if ")) != NULL ||
-      (ii = strstr (arg, "\tif ")) != NULL ||
-      (ii = strstr (arg, " if\t")) != NULL ||
-      (ii = strstr (arg, "\tif\t")) != NULL ||
-      (ii = strstr (arg, " if(")) != NULL ||
-      (ii = strstr (arg, "\tif( ")) != NULL)
-    has_if = 1;
-  /* Temporarily zap out "if (condition)" to not
-   * confuse the parenthesis-checking code below.
-   * This is undone below. Do not change ii!!
-   */
-  if (has_if)
-    {
-      *ii = '\0';
-    }
-
-  *is_quoted = (*arg
-               && strchr (get_gdb_completer_quote_characters (),
-                          *arg) != NULL);
-
-  *paren_pointer = strchr (arg, '(');
-  if (*paren_pointer != NULL)
-    *paren_pointer = strrchr (*paren_pointer, ')');
-
-  /* Now that we're safely past the paren_pointer check,
-   * put back " if (condition)" so outer layers can see it 
-   */
-  if (has_if)
-    *ii = ' ';
-}
-
 \f
 
 /* Decode arg of the form *PC.  */
@@ -822,6 +974,7 @@ decode_indirect (char **argptr)
   values.sals[0] = find_pc_line (pc, 0);
   values.sals[0].pc = pc;
   values.sals[0].section = find_pc_overlay (pc);
+  values.sals[0].explicit_pc = 1;
 
   return values;
 }
@@ -831,7 +984,9 @@ decode_indirect (char **argptr)
 /* Locate the first half of the linespec, ending in a colon, period,
    or whitespace.  (More or less.)  Also, check to see if *ARGPTR is
    enclosed in double quotes; if so, set is_quote_enclosed, advance
-   ARGPTR past that and zero out the trailing double quote.  */
+   ARGPTR past that and zero out the trailing double quote.
+   If ARGPTR is just a simple name like "main", p will point to ""
+   at the end.  */
 
 static char *
 locate_first_half (char **argptr, int *is_quote_enclosed)
@@ -850,18 +1005,16 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   ii = find_toplevel_char (*argptr, ',');
   has_comma = (ii != 0);
 
-  /* Temporarily zap out second half to not
-   * confuse the code below.
-   * This is undone below. Do not change ii!!
-   */
+  /* Temporarily zap out second half to not confuse the code below.
+     This is undone below. Do not change ii!!  */
   if (has_comma)
     {
       *ii = '\0';
     }
 
-  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
-  /* May also be CLASS::MEMBER, or NAMESPACE::NAME */
-  /* Look for ':', but ignore inside of <> */
+  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION.  May also be
+     CLASS::MEMBER, or NAMESPACE::NAME.  Look for ':', but ignore
+     inside of <>.  */
 
   p = *argptr;
   if (p[0] == '"')
@@ -871,29 +1024,46 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
       p++;
     }
   else
-    *is_quote_enclosed = 0;
+    {
+      *is_quote_enclosed = 0;
+      if (strchr (get_gdb_completer_quote_characters (), *p))
+       {
+         ++(*argptr);
+         ++p;
+       }
+    }
   for (; *p; p++)
     {
       if (p[0] == '<')
        {
          char *temp_end = find_template_name_end (p);
+
          if (!temp_end)
-           error ("malformed template specification in command");
+           error (_("malformed template specification in command"));
          p = temp_end;
        }
-      /* Check for the end of the first half of the linespec.  End of line,
-         a tab, a double colon or the last single colon, or a space.  But
-         if enclosed in double quotes we do not break on enclosed spaces */
+      /* Check for a colon and a plus or minus and a [ (which
+         indicates an Objective-C method) */
+      if (is_objc_method_format (p))
+       {
+         break;
+       }
+      /* Check for the end of the first half of the linespec.  End of
+         line, a tab, a double colon or the last single colon, or a
+         space.  But if enclosed in double quotes we do not break on
+         enclosed spaces.  */
       if (!*p
          || p[0] == '\t'
          || ((p[0] == ':')
              && ((p[1] == ':') || (strchr (p + 1, ':') == NULL)))
          || ((p[0] == ' ') && !*is_quote_enclosed))
        break;
-      if (p[0] == '.' && strchr (p, ':') == NULL)      /* Java qualified method. */
+      if (p[0] == '.' && strchr (p, ':') == NULL)
        {
-         /* Find the *last* '.', since the others are package qualifiers. */
-         for (p1 = p; *p1; p1++)
+         /* Java qualified method.  Find the *last* '.', since the
+            others are package qualifiers.  Stop at any open parenthesis
+            which might provide overload information.  */
+         for (p1 = p; *p1 && *p1 != '('; p1++)
            {
              if (*p1 == '.')
                p = p1;
@@ -904,17 +1074,17 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   while (p[0] == ' ' || p[0] == '\t')
     p++;
 
-  /* if the closing double quote was left at the end, remove it */
+  /* If the closing double quote was left at the end, remove it.  */
   if (*is_quote_enclosed)
     {
       char *closing_quote = strchr (p - 1, '"');
+
       if (closing_quote && closing_quote[1] == '\0')
        *closing_quote = '\0';
     }
 
-  /* Now that we've safely parsed the first half,
-   * put back ',' so outer layers can see it 
-   */
+  /* Now that we've safely parsed the first half, put back ',' so
+     outer layers can see it.  */
   if (has_comma)
     *ii = ',';
 
@@ -923,261 +1093,549 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
 
 \f
 
+/* Here's where we recognise an Objective-C Selector.  An Objective C
+   selector may be implemented by more than one class, therefore it
+   may represent more than one method/function.  This gives us a
+   situation somewhat analogous to C++ overloading.  If there's more
+   than one method that could represent the selector, then use some of
+   the existing C++ code to let the user choose one.  */
+
+struct symtabs_and_lines
+decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
+            char ***canonical, char *saved_arg)
+{
+  struct symtabs_and_lines values;
+  struct symbol **sym_arr = NULL;
+  struct symbol *sym = NULL;
+  char *copy = NULL;
+  struct block *block = NULL;
+  unsigned i1 = 0;
+  unsigned i2 = 0;
+
+  values.sals = NULL;
+  values.nelts = 0;
+
+  if (file_symtab != NULL)
+    block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
+  else
+    {
+      enum language save_language;
+
+      /* get_selected_block can change the current language when there is
+        no selected frame yet.  */
+      save_language = current_language->la_language;
+      block = get_selected_block (0);
+      set_language (save_language);
+    }
+
+  copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2); 
+    
+  if (i1 > 0)
+    {
+      sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
+      sym_arr[i1] = NULL;
+
+      copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2); 
+      *argptr = copy;
+    }
+
+  /* i1 now represents the TOTAL number of matches found.
+     i2 represents how many HIGH-LEVEL (struct symbol) matches,
+     which will come first in the sym_arr array.  Any low-level
+     (minimal_symbol) matches will follow those.  */
+      
+  if (i1 == 1)
+    {
+      if (i2 > 0)
+       {
+         /* Already a struct symbol.  */
+         sym = sym_arr[0];
+       }
+      else
+       {
+         sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
+         if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]), SYMBOL_LINKAGE_NAME (sym)) != 0)
+           {
+             warning (_("debugging symbol \"%s\" does not match selector; ignoring"), SYMBOL_LINKAGE_NAME (sym));
+             sym = NULL;
+           }
+       }
+             
+      values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+      values.nelts = 1;
+             
+      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+       {
+         /* Canonicalize this, so it remains resolved for dylib loads.  */
+         values.sals[0] = find_function_start_sal (sym, funfirstline);
+         build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical);
+       }
+      else
+       {
+         /* The only match was a non-debuggable symbol, which might point
+            to a function descriptor; resolve it to the actual code address
+            instead.  */
+         struct minimal_symbol *msymbol = (struct minimal_symbol *)sym_arr[0];
+         struct objfile *objfile = msymbol_objfile (msymbol);
+         struct gdbarch *gdbarch = get_objfile_arch (objfile);
+         CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
+
+         pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
+                                                  &current_target);
+
+         init_sal (&values.sals[0]);
+         values.sals[0].pc = pc;
+       }
+      return values;
+    }
+
+  if (i1 > 1)
+    {
+      /* More than one match. The user must choose one or more.  */
+      return decode_line_2 (sym_arr, i2, funfirstline, canonical);
+    }
+
+  return values;
+}
+
 /* This handles C++ and Java compound data structures.  P should point
-   at the first component separator, i.e. double-colon or period.  */
+   at the first component separator, i.e. double-colon or period.  As
+   an example, on entrance to this function we could have ARGPTR
+   pointing to "AAA::inA::fun" and P pointing to "::inA::fun".  */
 
 static struct symtabs_and_lines
 decode_compound (char **argptr, int funfirstline, char ***canonical,
-                char *saved_arg, char *p)
+                char *saved_arg, char *p, int *not_found_ptr)
 {
   struct symtabs_and_lines values;
-  char *p1, *p2;
-#if 0
-  char *q, *q1;
-#endif
+  char *p2;
   char *saved_arg2 = *argptr;
   char *temp_end;
   struct symbol *sym;
-  /* The symtab that SYM was found in.  */
-  struct symtab *sym_symtab;
   char *copy;
   struct symbol *sym_class;
-  int i1;
-  struct symbol **sym_arr;
   struct type *t;
+  char *saved_java_argptr = NULL;
 
-  /* First check for "global" namespace specification,
-     of the form "::foo". If found, skip over the colons
-     and jump to normal symbol processing */
+  /* First check for "global" namespace specification, of the form
+     "::foo".  If found, skip over the colons and jump to normal
+     symbol processing.  I.e. the whole line specification starts with
+     "::" (note the condition that *argptr == p). */
   if (p[0] == ':' 
       && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
     saved_arg2 += 2;
 
-  /* We have what looks like a class or namespace
-     scope specification (A::B), possibly with many
-     levels of namespaces or classes (A::B::C::D).
-
-     Some versions of the HP ANSI C++ compiler (as also possibly
-     other compilers) generate class/function/member names with
-     embedded double-colons if they are inside namespaces. To
-     handle this, we loop a few times, considering larger and
-     larger prefixes of the string as though they were single
-     symbols.  So, if the initially supplied string is
-     A::B::C::D::foo, we have to look up "A", then "A::B",
-     then "A::B::C", then "A::B::C::D", and finally
-     "A::B::C::D::foo" as single, monolithic symbols, because
-     A, B, C or D may be namespaces.
-
-     Note that namespaces can nest only inside other
-     namespaces, and not inside classes.  So we need only
-     consider *prefixes* of the string; there is no need to look up
-     "B::C" separately as a symbol in the previous example. */
-
-  p2 = p;              /* save for restart */
+  /* Given our example "AAA::inA::fun", we have two cases to consider:
+
+     1) AAA::inA is the name of a class.  In that case, presumably it
+        has a method called "fun"; we then look up that method using
+        find_method.
+
+     2) AAA::inA isn't the name of a class.  In that case, either the
+        user made a typo or AAA::inA is the name of a namespace.
+        Either way, we just look up AAA::inA::fun with lookup_symbol.
+
+     Thus, our first task is to find everything before the last set of
+     double-colons and figure out if it's the name of a class.  So we
+     first loop through all of the double-colons.  */
+
+  p2 = p;              /* Save for restart.  */
+
+  /* This is very messy. Following the example above we have now the
+     following pointers:
+     p -> "::inA::fun"
+     argptr -> "AAA::inA::fun
+     saved_arg -> "AAA::inA::fun
+     saved_arg2 -> "AAA::inA::fun
+     p2 -> "::inA::fun". */
+
+  /* In the loop below, with these strings, we'll make 2 passes, each
+     is marked in comments.*/
+
   while (1)
     {
-      /* Extract the class name.  */
-      p1 = p;
-      while (p != *argptr && p[-1] == ' ')
-       --p;
-      copy = (char *) alloca (p - *argptr + 1);
-      memcpy (copy, *argptr, p - *argptr);
-      copy[p - *argptr] = 0;
+      /* Move pointer up to next possible class/namespace token.  */
 
-      /* Discard the class name from the arg.  */
-      p = p1 + (p1[0] == ':' ? 2 : 1);
-      while (*p == ' ' || *p == '\t')
-       p++;
-      *argptr = p;
+      p = p2 + 1;      /* Restart with old value +1.  */
 
-      sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
-                                (struct symtab **) NULL);
+      /* PASS1: at this point p2->"::inA::fun", so p->":inA::fun",
+        i.e. if there is a double-colon, p will now point to the
+        second colon. */
+      /* PASS2: p2->"::fun", p->":fun" */
 
-      if (sym_class &&
-         (t = check_typedef (SYMBOL_TYPE (sym_class)),
-          (TYPE_CODE (t) == TYPE_CODE_STRUCT
-           || TYPE_CODE (t) == TYPE_CODE_UNION)))
+      /* Move pointer ahead to next double-colon.  */
+      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\'')
+            && (*p != '('))
        {
-         /* Arg token is not digits => try it as a function name
-            Find the next token(everything up to end or next blank). */
-         if (**argptr
-             && strchr (get_gdb_completer_quote_characters (),
-                        **argptr) != NULL)
+         if (current_language->la_language == language_cplus)
+           p += cp_validate_operator (p);
+
+         if (p[0] == '<')
            {
-             p = skip_quoted (*argptr);
-             *argptr = *argptr + 1;
+             temp_end = find_template_name_end (p);
+             if (!temp_end)
+               error (_("malformed template specification in command"));
+             p = temp_end;
            }
+         /* Note that, since, at the start of this loop, p would be
+            pointing to the second colon in a double-colon, we only
+            satisfy the condition below if there is another
+            double-colon to the right (after). I.e. there is another
+            component that can be a class or a namespace. I.e, if at
+            the beginning of this loop (PASS1), we had
+            p->":inA::fun", we'll trigger this when p has been
+            advanced to point to "::fun".  */
+         /* PASS2: we will not trigger this. */
+         else if ((p[0] == ':') && (p[1] == ':'))
+           break;      /* Found double-colon.  */
          else
-           {
-             p = *argptr;
-             while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
-               p++;
-           }
-/*
-   q = operator_chars (*argptr, &q1);
-   if (q1 - q)
-   {
-   char *opname;
-   char *tmp = alloca (q1 - q + 1);
-   memcpy (tmp, q, q1 - q);
-   tmp[q1 - q] = '\0';
-   opname = cplus_mangle_opname (tmp, DMGL_ANSI);
-   if (opname == NULL)
-   {
-   cplusplus_error (saved_arg, "no mangling for \"%s\"\n", tmp);
-   }
-   copy = (char*) alloca (3 + strlen(opname));
-   sprintf (copy, "__%s", opname);
-   p = q1;
-   }
-   else
- */
-         {
-           copy = (char *) alloca (p - *argptr + 1);
-           memcpy (copy, *argptr, p - *argptr);
-           copy[p - *argptr] = '\0';
-           if (p != *argptr
-               && copy[p - *argptr - 1]
-               && strchr (get_gdb_completer_quote_characters (),
-                          copy[p - *argptr - 1]) != NULL)
-             copy[p - *argptr - 1] = '\0';
-         }
-
-         /* no line number may be specified */
-         while (*p == ' ' || *p == '\t')
+           /* PASS2: We'll keep getting here, until p->"", at which point
+              we exit this loop.  */
            p++;
-         *argptr = p;
+       }
 
-         sym = 0;
-         i1 = 0;       /*  counter for the symbol array */
-         sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
-                                              * sizeof (struct symbol *));
+      if (*p != ':')
+       break;          /* Out of the while (1).  This would happen
+                          for instance if we have looked up
+                          unsuccessfully all the components of the
+                          string, and p->""(PASS2)  */
+
+      /* We get here if p points to ' ', '\t', '\'', "::" or ""(i.e
+        string ended). */
+      /* Save restart for next time around.  */
+      p2 = p;
+      /* Restore argptr as it was on entry to this function.  */
+      *argptr = saved_arg2;
+      /* PASS1: at this point p->"::fun" argptr->"AAA::inA::fun",
+        p2->"::fun".  */
+
+      /* All ready for next pass through the loop.  */
+    }                  /* while (1) */
 
-         if (destructor_name_p (copy, t))
-           {
-             /* Destructors are a special case.  */
-             int m_index, f_index;
 
-             if (get_destructor_fn_field (t, &m_index, &f_index))
-               {
-                 struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
-
-                 sym_arr[i1] =
-                   lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
-                                  NULL, VAR_NAMESPACE, (int *) NULL,
-                                  (struct symtab **) NULL);
-                 if (sym_arr[i1])
-                   i1++;
-               }
-           }
-         else
-           i1 = find_methods (t, copy, sym_arr);
-         if (i1 == 1)
-           {
-             /* There is exactly one field with that name.  */
-             sym = sym_arr[0];
+  /* Start of lookup in the symbol tables. */
 
-             if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
-               {
-                 values.sals = (struct symtab_and_line *)
-                   xmalloc (sizeof (struct symtab_and_line));
-                 values.nelts = 1;
-                 values.sals[0] = find_function_start_sal (sym,
-                                                           funfirstline);
-               }
-             else
-               {
-                 values.nelts = 0;
-               }
-             return values;
-           }
-         if (i1 > 0)
+  /* Lookup in the symbol table the substring between argptr and
+     p. Note, this call changes the value of argptr.  */
+  /* Before the call, argptr->"AAA::inA::fun",
+     p->"", p2->"::fun".  After the call: argptr->"fun", p, p2
+     unchanged.  */
+  sym_class = lookup_prefix_sym (argptr, p2);
+
+  /* If sym_class has been found, and if "AAA::inA" is a class, then
+     we're in case 1 above.  So we look up "fun" as a method of that
+     class.  */
+  if (sym_class &&
+      (t = check_typedef (SYMBOL_TYPE (sym_class)),
+       (TYPE_CODE (t) == TYPE_CODE_STRUCT
+       || TYPE_CODE (t) == TYPE_CODE_UNION)))
+    {
+      /* Arg token is not digits => try it as a function name.
+        Find the next token (everything up to end or next
+        blank).  */
+      if (**argptr
+         && strchr (get_gdb_completer_quote_characters (),
+                    **argptr) != NULL)
+       {
+         p = skip_quoted (*argptr);
+         *argptr = *argptr + 1;
+       }
+      else
+       {
+         /* At this point argptr->"fun".  */
+         char *a;
+
+         p = *argptr;
+         while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':'
+                && *p != '(')
+           p++;
+         /* At this point p->"".  String ended.  */
+         /* Nope, C++ operators could have spaces in them
+            ("foo::operator <" or "foo::operator delete []").
+            I apologize, this is a bit hacky...  */
+         if (current_language->la_language == language_cplus
+             && *p == ' ' && p - 8 - *argptr + 1 > 0)
            {
-             /* There is more than one field with that name
-                (overloaded).  Ask the user which one to use.  */
-             return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+             /* The above loop has already swallowed "operator".  */
+             p += cp_validate_operator (p - 8) - 8;
            }
-         else
-           {
-             char *tmp;
 
-             if (is_operator_name (copy))
+         /* Keep any template parameters */
+         if (*p == '<')
+           p = find_template_name_end (p);
+
+         /* Keep method overload information.  */
+         a = strchr (p, '(');
+         if (a != NULL)
+           p = find_method_overload_end (a);
+
+         /* Make sure we keep important kewords like "const" */
+         if (strncmp (p, " const", 6) == 0)
+           p += 6;
+
+         /* Java may append typenames,  so assume that if there is
+            anything else left in *argptr, it must be a typename.  */
+         if (*p && current_language->la_language == language_java)
+           {
+             struct type *type;
+
+             p2 = p;
+             while (*p2)
+               ++p2;
+             copy = (char *) alloca (p2 - p + 1);
+             memcpy (copy, p, p2 - p);
+             copy[p2 - p] = '\0';
+             type = lookup_typename (current_language, get_current_arch (),
+                                     copy, NULL, 1);
+             if (type != NULL)
                {
-                 tmp = (char *) alloca (strlen (copy + 3) + 9);
-                 strcpy (tmp, "operator ");
-                 strcat (tmp, copy + 3);
+                 /* Save the location of this just in case this
+                    method/type combination isn't actually defined.
+                    It will be checked later.  */
+                 saved_java_argptr = p;
+                 p = p2;
                }
-             else
-               tmp = copy;
-             if (tmp[0] == '~')
-               cplusplus_error (saved_arg,
-                                "the class `%s' does not have destructor defined\n",
-                                SYMBOL_SOURCE_NAME (sym_class));
-             else
-               cplusplus_error (saved_arg,
-                                "the class %s does not have any method named %s\n",
-                                SYMBOL_SOURCE_NAME (sym_class), tmp);
            }
        }
 
-      /* Move pointer up to next possible class/namespace token */
-      p = p2 + 1;      /* restart with old value +1 */
-      /* Move pointer ahead to next double-colon */
-      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
+      /* Allocate our own copy of the substring between argptr and
+        p. */
+      copy = (char *) alloca (p - *argptr + 1);
+      memcpy (copy, *argptr, p - *argptr);
+      copy[p - *argptr] = '\0';
+      if (p != *argptr
+         && copy[p - *argptr - 1]
+         && strchr (get_gdb_completer_quote_characters (),
+                    copy[p - *argptr - 1]) != NULL)
+       copy[p - *argptr - 1] = '\0';
+
+      /* At this point copy->"fun", p->"" */
+
+      /* No line number may be specified.  */
+      while (*p == ' ' || *p == '\t')
+       p++;
+      *argptr = p;
+      /* At this point arptr->"".  */
+
+      /* Look for copy as a method of sym_class. */
+      /* At this point copy->"fun", sym_class is "AAA:inA",
+        saved_arg->"AAA::inA::fun".  This concludes the scanning of
+        the string for possible components matches.  If we find it
+        here, we return. If not, and we are at the and of the string,
+        we'll lookup the whole string in the symbol tables.  */
+
+      values = find_method (funfirstline, canonical, saved_arg,
+                           copy, t, sym_class, not_found_ptr);
+      if (saved_java_argptr != NULL && values.nelts == 1)
        {
-         if (p[0] == '<')
+         /* The user specified a specific return type for a java method.
+            Double-check that it really is the one the user specified.
+            [This is a necessary evil because strcmp_iw_ordered stops
+            comparisons too prematurely.]  */
+         sym = find_pc_sect_function (values.sals[0].pc,
+                                      values.sals[0].section);
+         /* We just found a SAL, we had better be able to go backwards!  */
+         gdb_assert (sym != NULL);
+         if (strcmp_iw (SYMBOL_LINKAGE_NAME (sym), saved_arg) != 0)
            {
-             temp_end = find_template_name_end (p);
-             if (!temp_end)
-               error ("malformed template specification in command");
-             p = temp_end;
+             xfree (values.sals);
+             error (_("the class `%s' does not have any method instance named %s\n"),
+                    SYMBOL_PRINT_NAME (sym_class), copy);
            }
-         else if ((p[0] == ':') && (p[1] == ':'))
-           break;      /* found double-colon */
-         else
-           p++;
        }
+      return values;
+    } /* End if symbol found */
 
-      if (*p != ':')
-       break;          /* out of the while (1) */
 
-      p2 = p;          /* save restart for next time around */
-      *argptr = saved_arg2;    /* restore argptr */
-    }                  /* while (1) */
+  /* We couldn't find a class, so we're in case 2 above.  We check the
+     entire name as a symbol instead.  */
 
-  /* Last chance attempt -- check entire name as a symbol */
-  /* Use "copy" in preparation for jumping out of this block,
-     to be consistent with usage following the jump target */
   copy = (char *) alloca (p - saved_arg2 + 1);
   memcpy (copy, saved_arg2, p - saved_arg2);
-  /* Note: if is_quoted should be true, we snuff out quote here anyway */
+  /* Note: if is_quoted should be true, we snuff out quote here
+     anyway.  */
   copy[p - saved_arg2] = '\000';
-  /* Set argptr to skip over the name */
+  /* Set argptr to skip over the name */
   *argptr = (*p == '\'') ? p + 1 : p;
+
   /* Look up entire name */
-  sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+  sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
   if (sym)
-    return symbol_found (funfirstline, canonical, copy, sym,
-                        NULL, sym_symtab);
+    return symbol_found (funfirstline, canonical, copy, sym, NULL);
 
-  /* Couldn't find any interpretation as classes/namespaces, so give up */
-  /* The quotes are important if copy is empty.  */
+  /* Couldn't find any interpretation as classes/namespaces, so give
+     up.  The quotes are important if copy is empty.  */
+  if (not_found_ptr)
+    *not_found_ptr = 1;
   cplusplus_error (saved_arg,
                   "Can't find member of namespace, class, struct, or union named \"%s\"\n",
                   copy);
 }
 
+/* Next come some helper functions for decode_compound.  */
+
+/* Return the symbol corresponding to the substring of *ARGPTR ending
+   at P, allowing whitespace.  Also, advance *ARGPTR past the symbol
+   name in question, the compound object separator ("::" or "."), and
+   whitespace.  Note that *ARGPTR is changed whether or not the
+   lookup_symbol call finds anything (i.e we return NULL).  As an
+   example, say ARGPTR is "AAA::inA::fun" and P is "::inA::fun".  */
+
+static struct symbol *
+lookup_prefix_sym (char **argptr, char *p)
+{
+  char *p1;
+  char *copy;
+  struct symbol *sym;
+
+  /* Extract the class name.  */
+  p1 = p;
+  while (p != *argptr && p[-1] == ' ')
+    --p;
+  copy = (char *) alloca (p - *argptr + 1);
+  memcpy (copy, *argptr, p - *argptr);
+  copy[p - *argptr] = 0;
+
+  /* Discard the class name from the argptr.  */
+  p = p1 + (p1[0] == ':' ? 2 : 1);
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  /* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA",
+     argptr->"inA::fun" */
+
+  sym = lookup_symbol (copy, 0, STRUCT_DOMAIN, 0);
+  if (sym == NULL)
+    {
+      /* Typedefs are in VAR_DOMAIN so the above symbol lookup will
+        fail when the user attempts to lookup a method of a class
+        via a typedef'd name (NOT via the class's name, which is already
+        handled in symbol_matches_domain).  So try the lookup again
+        using VAR_DOMAIN (where typedefs live) and double-check that we
+        found a struct/class type.  */
+      struct symbol *s = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+
+      if (s != NULL)
+       {
+         struct type *t = SYMBOL_TYPE (s);
+
+         CHECK_TYPEDEF (t);
+         if (TYPE_CODE (t) == TYPE_CODE_STRUCT)
+           return s;
+       }
+    }
+
+  return sym;
+}
+
+/* This finds the method COPY in the class whose type is T and whose
+   symbol is SYM_CLASS.  */
+
+static struct symtabs_and_lines
+find_method (int funfirstline, char ***canonical, char *saved_arg,
+            char *copy, struct type *t, struct symbol *sym_class, int *not_found_ptr)
+{
+  struct symtabs_and_lines values;
+  struct symbol *sym = NULL;
+  int i1;      /*  Counter for the symbol array.  */
+  struct symbol **sym_arr =  alloca (total_number_of_methods (t)
+                                    * sizeof (struct symbol *));
+
+  /* Find all methods with a matching name, and put them in
+     sym_arr.  */
+
+  i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
+
+  if (i1 == 1)
+    {
+      /* There is exactly one field with that name.  */
+      sym = sym_arr[0];
+
+      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+       {
+         values.sals = (struct symtab_and_line *)
+           xmalloc (sizeof (struct symtab_and_line));
+         values.nelts = 1;
+         values.sals[0] = find_function_start_sal (sym,
+                                                   funfirstline);
+       }
+      else
+       {
+         values.sals = NULL;
+         values.nelts = 0;
+       }
+      return values;
+    }
+  if (i1 > 0)
+    {
+      /* If we were given a specific overload instance, use that
+        (or error if no matches were found).  Otherwise ask the user
+        which one to use.  */
+      if (strchr (saved_arg, '(') != NULL)
+       {
+         int i;
+
+         for (i = 0; i < i1; ++i)
+           {
+             char *name = saved_arg;
+             char *canon = cp_canonicalize_string (name);
+
+             if (canon != NULL)
+               name = canon;
+
+             if (strcmp_iw (name, SYMBOL_LINKAGE_NAME (sym_arr[i])) == 0)
+               {
+                 values.sals = (struct symtab_and_line *)
+                   xmalloc (sizeof (struct symtab_and_line));
+                 values.nelts = 1;
+                 values.sals[0] = find_function_start_sal (sym_arr[i],
+                                                           funfirstline);
+                 if (canon)
+                   xfree (canon);
+                 return values;
+               }
+
+             if (canon)
+               xfree (canon);
+           }
+
+         error (_("the class `%s' does not have any method instance named %s\n"),
+                SYMBOL_PRINT_NAME (sym_class), copy);
+       }
+
+      return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+    }
+  else
+    {
+      if (not_found_ptr)
+        *not_found_ptr = 1;
+      if (copy[0] == '~')
+       cplusplus_error (saved_arg,
+                        "the class `%s' does not have destructor defined\n",
+                        SYMBOL_PRINT_NAME (sym_class));
+      else
+       cplusplus_error (saved_arg,
+                        "the class %s does not have any method named %s\n",
+                        SYMBOL_PRINT_NAME (sym_class), copy);
+    }
+}
+
 \f
 
 /* Return the symtab associated to the filename given by the substring
-   of *ARGPTR ending at P, and advance ARGPTR past that filename.  */
+   of *ARGPTR ending at P, and advance ARGPTR past that filename.  If
+   NOT_FOUND_PTR is not null and the source file is not found, store
+   boolean true at the location pointed to and do not issue an
+   error message.  */
 
 static struct symtab *
-symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+symtab_from_filename (char **argptr, char *p, int is_quote_enclosed, 
+                     int *not_found_ptr)
 {
   char *p1;
   char *copy;
-  struct symtab *s;
+  struct symtab *file_symtab;
   
   p1 = p;
   while (p != *argptr && p[-1] == ' ')
@@ -1186,19 +1644,23 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
     --p;
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
-  /* It may have the ending quote right after the file name */
-  if (is_quote_enclosed && copy[p - *argptr - 1] == '"')
+  /* It may have the ending quote right after the file name.  */
+  if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
+      || copy[p - *argptr - 1] == '\'')
     copy[p - *argptr - 1] = 0;
   else
     copy[p - *argptr] = 0;
 
   /* Find that file's data.  */
-  s = lookup_symtab (copy);
-  if (s == 0)
+  file_symtab = lookup_symtab (copy);
+  if (file_symtab == 0)
     {
+      if (not_found_ptr)
+       *not_found_ptr = 1;
       if (!have_full_symbols () && !have_partial_symbols ())
-       error ("No symbol table is loaded.  Use the \"file\" command.");
-      error ("No source file named %s.", copy);
+       throw_error (NOT_FOUND_ERROR,
+                    _("No symbol table is loaded.  Use the \"file\" command."));
+      throw_error (NOT_FOUND_ERROR, _("No source file named %s."), copy);
     }
 
   /* Discard the file name from the arg.  */
@@ -1207,7 +1669,7 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
     p++;
   *argptr = p;
 
-  return s;
+  return file_symtab;
 }
 
 \f
@@ -1232,19 +1694,21 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
   sign = none;
 
   /* We might need a canonical line spec if no file was specified.  */
-  int need_canonical = (file_symtab == 0) ? 1 : 0;
+  int need_canonical = (file_symtab == NULL) ? 1 : 0;
 
   init_sal (&val);
 
+  val.pspace = current_program_space;
+
   /* This is where we need to make sure that we have good defaults.
      We must guarantee that this section of code is never executed
      when we are called with just a function name, since
      set_default_source_symtab_and_line uses
-     select_source_symtab that calls us with such an argument  */
+     select_source_symtab that calls us with such an argument.  */
 
   if (file_symtab == 0 && default_symtab == 0)
     {
-      /* Make sure we have at least a default source file. */
+      /* Make sure we have at least a default source file.  */
       set_default_source_symtab_and_line ();
       initialize_defaults (&default_symtab, &default_line);
     }
@@ -1287,6 +1751,7 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
   if (val.symtab == 0)
     val.symtab = file_symtab;
 
+  val.pspace = SYMTAB_PSPACE (val.symtab);
   val.pc = 0;
   values.sals = (struct symtab_and_line *)
     xmalloc (sizeof (struct symtab_and_line));
@@ -1294,6 +1759,7 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
   values.nelts = 1;
   if (need_canonical)
     build_canonical_line_spec (values.sals, NULL, canonical);
+  values.sals[0].explicit_line = 1;
   return values;
 }
 
@@ -1305,61 +1771,60 @@ static struct symtabs_and_lines
 decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
               char ***canonical, struct symtab *file_symtab)
 {
-  struct value *valx;
+  LONGEST valx;
   int index = 0;
   int need_canonical = 0;
   struct symtabs_and_lines values;
   struct symtab_and_line val;
   char *p;
   struct symbol *sym;
-  /* The symtab that SYM was found in.  */
-  struct symtab *sym_symtab;
   struct minimal_symbol *msymbol;
 
   p = (copy[1] == '$') ? copy + 2 : copy + 1;
   while (*p >= '0' && *p <= '9')
     p++;
-  if (!*p)                     /* reached end of token without hitting non-digit */
+  if (!*p)             /* Reached end of token without hitting non-digit.  */
     {
-      /* We have a value history reference */
+      /* We have a value history reference.  */
+      struct value *val_history;
+
       sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
-      valx = access_value_history ((copy[1] == '$') ? -index : index);
-      if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
-       error ("History values used in line specs must have integer values.");
+      val_history = access_value_history ((copy[1] == '$') ? -index : index);
+      if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
+       error (_("History values used in line specs must have integer values."));
+      valx = value_as_long (val_history);
     }
   else
     {
       /* Not all digits -- may be user variable/function or a
-        convenience variable */
+        convenience variable */
 
-      /* Look up entire name as a symbol first */
-      sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
-      file_symtab = (struct symtab *) 0;
+      /* Look up entire name as a symbol first */
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+      file_symtab = (struct symtab *) NULL;
       need_canonical = 1;
       /* Symbol was found --> jump to normal symbol processing.  */
       if (sym)
-       return symbol_found (funfirstline, canonical, copy, sym,
-                            NULL, sym_symtab);
+       return symbol_found (funfirstline, canonical, copy, sym, NULL);
 
-      /* If symbol was not found, look in minimal symbol tables */
+      /* If symbol was not found, look in minimal symbol tables */
       msymbol = lookup_minimal_symbol (copy, NULL, NULL);
-      /* Min symbol was found --> jump to minsym processing. */
+      /* Min symbol was found --> jump to minsym processing.  */
       if (msymbol)
        return minsym_found (funfirstline, msymbol);
 
-      /* Not a user variable or function -- must be convenience variable */
-      need_canonical = (file_symtab == 0) ? 1 : 0;
-      valx = value_of_internalvar (lookup_internalvar (copy + 1));
-      if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
-       error ("Convenience variables used in line specs must have integer values.");
+      /* Not a user variable or function -- must be convenience variable.  */
+      if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
+       error (_("Convenience variables used in line specs must have integer values."));
     }
 
   init_sal (&val);
 
-  /* Either history value or convenience value from above, in valx */
+  /* Either history value or convenience value from above, in valx */
   val.symtab = file_symtab ? file_symtab : default_symtab;
-  val.line = value_as_long (valx);
+  val.line = valx;
   val.pc = 0;
+  val.pspace = current_program_space;
 
   values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
   values.sals[0] = val;
@@ -1374,16 +1839,15 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
 \f
 
 /* Decode a linespec that's a variable.  If FILE_SYMTAB is non-NULL,
-   look in that symtab's static variables first.  */
+   look in that symtab's static variables first.  If NOT_FOUND_PTR is not NULL and
+   the function cannot be found, store boolean true in the location pointed to
+   and do not issue an error message.  */ 
 
 static struct symtabs_and_lines
 decode_variable (char *copy, int funfirstline, char ***canonical,
-                struct symtab *file_symtab)
+                struct symtab *file_symtab, int *not_found_ptr)
 {
   struct symbol *sym;
-  /* The symtab that SYM was found in.  */
-  struct symtab *sym_symtab;
-
   struct minimal_symbol *msymbol;
 
   sym = lookup_symbol (copy,
@@ -1391,22 +1855,25 @@ decode_variable (char *copy, int funfirstline, char ***canonical,
                        ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
                                             STATIC_BLOCK)
                        : get_selected_block (0)),
-                      VAR_NAMESPACE, 0, &sym_symtab);
+                      VAR_DOMAIN, 0);
 
   if (sym != NULL)
-    return symbol_found (funfirstline, canonical, copy, sym,
-                        file_symtab, sym_symtab);
+    return symbol_found (funfirstline, canonical, copy, sym, file_symtab);
 
   msymbol = lookup_minimal_symbol (copy, NULL, NULL);
 
   if (msymbol != NULL)
     return minsym_found (funfirstline, msymbol);
 
-  if (!have_full_symbols () &&
-      !have_partial_symbols () && !have_minimal_symbols ())
-    error ("No symbol table is loaded.  Use the \"file\" command.");
+  if (not_found_ptr)
+    *not_found_ptr = 1;
 
-  error ("Function \"%s\" not defined.", copy);
+  if (!have_full_symbols ()
+      && !have_partial_symbols ()
+      && !have_minimal_symbols ())
+    throw_error (NOT_FOUND_ERROR,
+                _("No symbol table is loaded.  Use the \"file\" command."));
+  throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
 }
 
 
@@ -1420,8 +1887,7 @@ decode_variable (char *copy, int funfirstline, char ***canonical,
 
 static struct symtabs_and_lines
 symbol_found (int funfirstline, char ***canonical, char *copy,
-             struct symbol *sym, struct symtab *file_symtab,
-             struct symtab *sym_symtab)
+             struct symbol *sym, struct symtab *file_symtab)
 {
   struct symtabs_and_lines values;
   
@@ -1441,9 +1907,10 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
         function.  */
       if (file_symtab == 0)
        {
-         struct blockvector *bv = BLOCKVECTOR (sym_symtab);
+         struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
          struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-         if (lookup_block_symbol (b, copy, NULL, VAR_NAMESPACE) != NULL)
+
+         if (lookup_block_symbol (b, copy, VAR_DOMAIN) != NULL)
            build_canonical_line_spec (values.sals, copy, canonical);
        }
       return values;
@@ -1451,7 +1918,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
   else
     {
       if (funfirstline)
-       error ("\"%s\" is not a function", copy);
+       error (_("\"%s\" is not a function"), copy);
       else if (SYMBOL_LINE (sym) != 0)
        {
          /* We know its line number.  */
@@ -1459,7 +1926,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
            xmalloc (sizeof (struct symtab_and_line));
          values.nelts = 1;
          memset (&values.sals[0], 0, sizeof (values.sals[0]));
-         values.sals[0].symtab = sym_symtab;
+         values.sals[0].symtab = SYMBOL_SYMTAB (sym);
          values.sals[0].line = SYMBOL_LINE (sym);
          return values;
        }
@@ -1469,7 +1936,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
        /* FIXME: Shouldn't we just set .line and .symtab to zero
           and return?  For example, "info line foo" could print
           the address.  */
-       error ("Line number not known for symbol \"%s\"", copy);
+       error (_("Line number not known for symbol \"%s\""), copy);
     }
 }
 
@@ -1479,18 +1946,28 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
 static struct symtabs_and_lines
 minsym_found (int funfirstline, struct minimal_symbol *msymbol)
 {
+  struct objfile *objfile = msymbol_objfile (msymbol);
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct symtabs_and_lines values;
+  CORE_ADDR pc;
 
   values.sals = (struct symtab_and_line *)
     xmalloc (sizeof (struct symtab_and_line));
   values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
-                                     (struct sec *) 0, 0);
-  values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
+                                     (struct obj_section *) 0, 0);
+  values.sals[0].section = SYMBOL_OBJ_SECTION (msymbol);
+
+  /* The minimal symbol might point to a function descriptor;
+     resolve it to the actual code address instead.  */
+  pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
+                                           values.sals[0].pc,
+                                           &current_target);
+  if (pc != values.sals[0].pc)
+    values.sals[0] = find_pc_sect_line (pc, NULL, 0);
+
   if (funfirstline)
-    {
-      values.sals[0].pc += FUNCTION_START_OFFSET;
-      values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
-    }
+    skip_prologue_sal (&values.sals[0]);
+
   values.nelts = 1;
   return values;
 }
This page took 0.047194 seconds and 4 git commands to generate.