2003-06-08 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / linespec.c
index e496c71132b56f565cf30b9a57d95e9b53c17a63..b8f727453ea04a30b46a7ab394e6c69f840ad5c5 100644 (file)
@@ -1,6 +1,6 @@
 /* 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
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -32,6 +32,9 @@
 #include "completer.h"
 #include "cp-abi.h"
 #include "parser-defs.h"
+#include "block.h"
+#include "objc-lang.h"
+#include "linespec.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -39,12 +42,53 @@ extern char *operator_chars (char *, char **);
 
 /* Prototypes for local functions */
 
-static void cplusplus_error (const char *name, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
+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);
+
+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);
+
+static int collect_methods (char *copy, struct type *t,
+                           struct symbol **sym_arr);
+
+static NORETURN void cplusplus_error (const char *name,
+                                     const char *fmt, ...)
+     ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
 
 static int total_number_of_methods (struct type *type);
 
 static int find_methods (struct type *, char *, struct symbol **);
 
+static int add_matching_methods (int method_counter, struct type *t,
+                                struct symbol **sym_arr);
+
+static int add_constructors (int method_counter, struct type *t,
+                            struct symbol **sym_arr);
+
 static void build_canonical_line_spec (struct symtab_and_line *,
                                       char *, char ***);
 
@@ -53,12 +97,34 @@ static char *find_toplevel_char (char *s, char c);
 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);
+
+static struct
+symtabs_and_lines decode_all_digits (char **argptr,
+                                    struct symtab *default_symtab,
+                                    int default_line,
+                                    char ***canonical,
+                                    struct symtab *file_symtab,
+                                    char *q);
+
+static struct symtabs_and_lines decode_dollar (char *copy,
+                                              int funfirstline,
+                                              struct symtab *default_symtab,
+                                              char ***canonical,
+                                              struct symtab *file_symtab);
+
+static struct symtabs_and_lines decode_variable (char *copy,
+                                                int funfirstline,
+                                                char ***canonical,
+                                                struct symtab *file_symtab);
+
 static struct
 symtabs_and_lines symbol_found (int funfirstline,
                                char ***canonical,
                                char *copy,
                                struct symbol *sym,
-                               struct symtab *s,
+                               struct symtab *file_symtab,
                                struct symtab *sym_symtab);
 
 static struct
@@ -71,7 +137,7 @@ symtabs_and_lines minsym_found (int funfirstline,
    single quoted demangled C++ symbols as part of the completion
    error.  */
 
-static void
+static NORETURN void
 cplusplus_error (const char *name, const char *fmt, ...)
 {
   struct ui_file *tmp_stream;
@@ -135,7 +201,7 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
      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_DOMAIN, (int *) NULL,
                         (struct symtab **) NULL)))
     {
       int method_counter;
@@ -151,7 +217,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];
 
@@ -167,86 +232,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,
+                                       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,
+                                   sym_arr + i1);
        }
     }
 
@@ -268,6 +260,113 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
   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,
+                     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);
+               
+      /* Destructor is handled by caller, don't add it to
+        the list.  */
+      if (is_destructor_name (phys_name) != 0)
+       continue;
+
+      sym_arr[i1] = lookup_symbol (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  (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);
+         */
+       }
+    }
+
+  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,
+                 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 (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  (int *) NULL,
+                                  (struct symtab **) NULL);
+      if (sym_arr[i1])
+       i1++;
+    }
+
+  return i1;
+}
+
 /* Helper function for decode_line_1.
    Build a canonical line spec in CANONICAL if it is non-NULL and if
    the SAL has a symtab.
@@ -319,7 +418,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++)
@@ -379,14 +478,14 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
   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]),
+                            SYMBOL_PRINT_NAME (sym_arr[i]),
                             values.sals[i].symtab->filename,
                             values.sals[i].line);
        }
@@ -395,7 +494,8 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
       i++;
     }
 
-  if ((prompt = getenv ("PS2")) == NULL)
+  prompt = getenv ("PS2");
+  if (prompt == NULL)
     {
       prompt = "> ";
     }
@@ -427,7 +527,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
                {
                  if (canonical_arr[i] == NULL)
                    {
-                     symname = SYMBOL_NAME (sym_arr[i]);
+                     symname = DEPRECATED_SYMBOL_NAME (sym_arr[i]);
                      canonical_arr[i] = savestring (symname, strlen (symname));
                    }
                }
@@ -450,7 +550,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
            {
              if (canonical_arr)
                {
-                 symname = SYMBOL_NAME (sym_arr[num]);
+                 symname = DEPRECATED_SYMBOL_NAME (sym_arr[num]);
                  make_cleanup (xfree, symname);
                  canonical_arr[i] = savestring (symname, strlen (symname));
                }
@@ -520,107 +620,309 @@ struct symtabs_and_lines
 decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
               int default_line, char ***canonical)
 {
-  struct symtabs_and_lines values;
-  struct symtab_and_line val;
-  register char *p, *p1;
-  char *q, *pp, *ii, *p2;
-#if 0
-  char *q1;
-#endif
-  register struct symtab *s;
-
-  register struct symbol *sym;
-  /* The symtab that SYM was found in.  */
-  struct symtab *sym_symtab;
+  char *p;
+  char *q;
+  /* If a file name is specified, this is its symtab.  */
+  struct symtab *file_symtab = NULL;
 
-  register CORE_ADDR pc;
-  register struct minimal_symbol *msymbol;
   char *copy;
-  struct symbol *sym_class;
-  int i1;
+  /* 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?  */
   int is_quote_enclosed;
-  int has_parens;
-  int has_if = 0;
-  int has_comma = 0;
-  struct symbol **sym_arr;
-  struct type *t;
+  int is_objc_method = 0;
   char *saved_arg = *argptr;
-  extern char *gdb_completer_quote_characters;
-
-  init_sal (&val);             /* initialize to zeroes */
 
   /* Defaults have defaults.  */
 
-  if (default_symtab == 0)
+  initialize_defaults (&default_symtab, &default_line);
+  
+  /* 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);
+
+  /* Check to see if it's a multipart linespec (with colons or
+     periods).  */
+
+  /* Locate the end of the first half of the linespec.  */
+
+  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 (*p && (p[0] == ':') && (strchr ("+-", p[1]) != NULL) 
+      && (p[2] == '['))
     {
-      /* Use whatever we have for the default source line.  We don't use
-         get_current_or_default_symtab_and_line as it can recurse and call
-        us back! */
-      struct symtab_and_line cursal = 
-                       get_current_source_symtab_and_line ();
+      is_objc_method = 1;
+      paren_pointer  = NULL; /* Just a category name.  Ignore it.  */
+    }
+
+  /* Check if the symbol could be an Objective-C selector.  */
+
+  {
+    struct symtabs_and_lines values;
+    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 (is_quoted)
+       *argptr = *argptr + 1;
       
-      default_symtab = cursal.symtab;
-      default_line = cursal.line;
+      /* Is it a C++ or Java compound data structure?  */
+
+      if (p[0] == '.' || p[1] == ':')
+       return decode_compound (argptr, funfirstline, canonical,
+                               saved_arg, p);
+
+      /* No, the first part is a filename; set s 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 */
 
-  /* See if arg is *PC */
+      /* 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. */
 
-  if (**argptr == '*')
+      copy = (char *) alloca (p - *argptr + 1);
+      memcpy (copy, *argptr, p - *argptr);
+      copy[p - *argptr] = '\000';
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+      if (sym)
+       {
+         *argptr = (*p == '\'') ? p + 1 : p;
+         return symbol_found (funfirstline, canonical, copy, sym,
+                              NULL, sym_symtab);
+       }
+      /* 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.
+     arg no longer contains the file name.  */
+
+  /* Check whether arg is all digits (and sign).  */
+
+  q = *argptr;
+  if (*q == '-' || *q == '+')
+    q++;
+  while (*q >= '0' && *q <= '9')
+    q++;
+
+  if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
+    /* We found a token consisting of all digits -- at least one digit.  */
+    return decode_all_digits (argptr, default_symtab, default_line,
+                             canonical, file_symtab, q);
+
+  /* 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.  */
+    /* One or two $ chars possible.  */
+    p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));
+  else if (is_quoted)
     {
-      (*argptr)++;
-      pc = parse_and_eval_address_1 (argptr);
+      p = skip_quoted (*argptr);
+      if (p[-1] != '\'')
+       error ("Unmatched single quote.");
+    }
+  else if (is_objc_method)
+    {
+      /* allow word separators in method names for Obj-C */
+      p = skip_quoted_chars (*argptr, NULL, "");
+    }
+  else if (paren_pointer != NULL)
+    {
+      p = paren_pointer + 1;
+    }
+  else
+    {
+      p = skip_quoted (*argptr);
+    }
 
-      values.sals = (struct symtab_and_line *)
-       xmalloc (sizeof (struct symtab_and_line));
+  copy = (char *) alloca (p - *argptr + 1);
+  memcpy (copy, *argptr, p - *argptr);
+  copy[p - *argptr] = '\0';
+  if (p != *argptr
+      && copy[0]
+      && copy[0] == copy[p - *argptr - 1]
+      && strchr (get_gdb_completer_quote_characters (), copy[0]) != NULL)
+    {
+      copy[p - *argptr - 1] = '\0';
+      copy++;
+    }
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
 
-      values.nelts = 1;
-      values.sals[0] = find_pc_line (pc, 0);
-      values.sals[0].pc = pc;
-      values.sals[0].section = find_pc_overlay (pc);
+  /* 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.  */
 
-      return values;
+  if (*copy == '$')
+    return decode_dollar (copy, funfirstline, default_symtab,
+                         canonical, file_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);
+}
+
+\f
+
+/* Now, more helper functions for decode_line_1.  Some conventions
+   that these functions follow:
+
+   Decode_line_1 typically passes along some of its arguments or local
+   variables to the subfunctions.  It passes the variables by
+   reference if they are modified by the subfunction, and by value
+   otherwise.
+
+   Some of the functions have side effects that don't arise from
+   variables that are passed by reference.  In particular, if a
+   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.
+
+   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
+   decode_line_1.  In particular, all of the functions decode_XXX
+   calculate the appropriate struct symtabs_and_lines, under the
+   assumption that their argument is of the form XXX.  */
+
+/* First, some functions to initialize stuff at the beggining of the
+   function.  */
+
+static void
+initialize_defaults (struct symtab **default_symtab, int *default_line)
+{
+  if (*default_symtab == 0)
+    {
+      /* Use whatever we have for the default source line.  We don't use
+         get_current_or_default_symtab_and_line as it can recurse and call
+        us back! */
+      struct symtab_and_line cursal = 
+       get_current_source_symtab_and_line ();
+      
+      *default_symtab = cursal.symtab;
+      *default_line = cursal.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 (*argptr, " if ")) != NULL ||
-      (ii = strstr (*argptr, "\tif ")) != NULL ||
-      (ii = strstr (*argptr, " if\t")) != NULL ||
-      (ii = strstr (*argptr, "\tif\t")) != NULL ||
-      (ii = strstr (*argptr, " if(")) != NULL ||
-      (ii = strstr (*argptr, "\tif( ")) != NULL)
+        (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!!
-   */
+  /* 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';
     }
 
-  /* Set various flags.
-   * 'has_parens' is important for overload checking, where
-   * we allow things like: 
-   *     (gdb) break c::f(int)
-   */
-
-  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+  *is_quoted = (*arg
+               && strchr (get_gdb_completer_quote_characters (),
+                          *arg) != NULL);
 
-  is_quoted = (**argptr
-              && strchr (get_gdb_completer_quote_characters (),
-                         **argptr) != NULL);
+  *paren_pointer = strchr (arg, '(');
+  if (*paren_pointer != NULL)
+    *paren_pointer = strrchr (*paren_pointer, ')');
 
-  has_parens = ((pp = strchr (*argptr, '(')) != NULL
-               && (pp = strrchr (pp, ')')) != NULL);
-
-  /* Now that we're safely past the has_parens check,
-   * put back " if (condition)" so outer layers can see it 
-   */
+  /* 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.  */
+
+static struct symtabs_and_lines
+decode_indirect (char **argptr)
+{
+  struct symtabs_and_lines values;
+  CORE_ADDR pc;
+  
+  (*argptr)++;
+  pc = parse_and_eval_address_1 (argptr);
+
+  values.sals = (struct symtab_and_line *)
+    xmalloc (sizeof (struct symtab_and_line));
+
+  values.nelts = 1;
+  values.sals[0] = find_pc_line (pc, 0);
+  values.sals[0].pc = pc;
+  values.sals[0].section = find_pc_overlay (pc);
+
+  return values;
+}
+
+\f
+
+/* 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.  */
+
+static char *
+locate_first_half (char **argptr, int *is_quote_enclosed)
+{
+  char *ii;
+  char *p, *p1;
+  int has_comma;
 
   /* Maybe we were called with a line range FILENAME:LINENUM,FILENAME:LINENUM
      and we must isolate the first half.  Outer layers will call again later
@@ -632,29 +934,26 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   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 <>.  */
 
-  s = NULL;
   p = *argptr;
   if (p[0] == '"')
     {
-      is_quote_enclosed = 1;
+      *is_quote_enclosed = 1;
       (*argptr)++;
       p++;
     }
   else
-    is_quote_enclosed = 0;
+    *is_quote_enclosed = 0;
   for (; *p; p++)
     {
       if (p[0] == '<')
@@ -664,18 +963,27 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
            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 (*p && (p[0] == ':') && (strchr ("+-", p[1]) != NULL) 
+         && (p[2] == '['))
+       {
+         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))
+         || ((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. */
+         /* Java qualified method.  Find the *last* '.', since the
+            others are package qualifiers.  */
          for (p1 = p; *p1; p1++)
            {
              if (*p1 == '.')
@@ -687,97 +995,188 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   while (p[0] == ' ' || p[0] == '\t')
     p++;
 
-  /* if the closing double quote was left at the end, remove it */
-  if (is_quote_enclosed)
+  /* 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 = ',';
 
-  if ((p[0] == ':' || p[0] == '.') && !has_parens)
+  return p;
+}
+
+\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;
+  int i1 = 0;
+  int i2 = 0;
+
+  values.sals = NULL;
+  values.nelts = 0;
+
+  if (file_symtab != NULL)
+    block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
+  else
+    block = get_selected_block (0);
+    
+  copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2); 
+    
+  if (i1 > 0)
     {
-      /*  C++ */
-      /*  ... or Java */
-      if (is_quoted)
-       *argptr = *argptr + 1;
-      if (p[0] == '.' || p[1] == ':')
+      sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
+      sym_arr[i1] = 0;
+
+      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
        {
-         char *saved_arg2 = *argptr;
-         char *temp_end;
-         /* First check for "global" namespace specification,
-            of the form "::foo". If found, skip over the colons
-            and jump to normal symbol processing */
-         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 */
-         while (1)
+         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)
            {
-             /* 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 arg.  */
-             p = p1 + (p1[0] == ':' ? 2 : 1);
-             while (*p == ' ' || *p == '\t')
-               p++;
-             *argptr = p;
+             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.  */
+         values.sals[0].symtab = 0;
+         values.sals[0].line = 0;
+         values.sals[0].end = 0;
+         values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
+       }
+      return values;
+    }
 
-             sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
-                                        (struct symtab **) NULL);
+  if (i1 > 1)
+    {
+      /* More than one match. The user must choose one or more.  */
+      return decode_line_2 (sym_arr, i2, funfirstline, canonical);
+    }
 
-             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
-                   {
-                     p = *argptr;
-                     while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
-                       p++;
-                   }
+  return values;
+}
+
+/* This handles C++ and Java compound data structures.  P should point
+   at the first component separator, i.e. double-colon or period.  */
+
+static struct symtabs_and_lines
+decode_compound (char **argptr, int funfirstline, char ***canonical,
+                char *saved_arg, char *p)
+{
+  struct symtabs_and_lines values;
+  char *p2;
+#if 0
+  char *q, *q1;
+#endif
+  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;
+  struct symbol **sym_arr;
+  struct type *t;
+
+  /* First check for "global" namespace specification,
+     of the form "::foo".  If found, skip over the colons
+     and jump to normal symbol processing.  */
+  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.  */
+  while (1)
+    {
+      sym_class = lookup_prefix_sym (argptr, p);
+
+      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
+           {
+             p = *argptr;
+             while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
+               p++;
+           }
 /*
    q = operator_chars (*argptr, &q1);
    if (q1 - q)
@@ -797,406 +1196,432 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
    }
    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')
-                   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 (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];
-
-                     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)
-                   {
-                     /* 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);
-                   }
-                 else
-                   {
-                     char *tmp;
-
-                     if (is_operator_name (copy))
-                       {
-                         tmp = (char *) alloca (strlen (copy + 3) + 9);
-                         strcpy (tmp, "operator ");
-                         strcat (tmp, copy + 3);
-                       }
-                     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] != '\''))
-               {
-                 if (p[0] == '<')
-                   {
-                     temp_end = find_template_name_end (p);
-                     if (!temp_end)
-                       error ("malformed template specification in command");
-                     p = temp_end;
-                   }
-                 else if ((p[0] == ':') && (p[1] == ':'))
-                   break;      /* found double-colon */
-                 else
-                   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';
+         }
+
+         /* No line number may be specified.  */
+         while (*p == ' ' || *p == '\t')
+           p++;
+         *argptr = p;
+
+         return find_method (funfirstline, canonical, saved_arg,
+                             copy, t, sym_class);
+       }
 
-             if (*p != ':')
-               break;          /* out of the while (1) */
-
-             p2 = p;           /* save restart for next time around */
-             *argptr = saved_arg2;     /* restore argptr */
-           }                   /* while (1) */
-
-         /* 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 */
-         copy[p - saved_arg2] = '\000';
-         /* 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);
-         s = (struct symtab *) 0;
-         if (sym)
-           return symbol_found (funfirstline, canonical, copy, sym,
-                                NULL, sym_symtab);
-
-         /* Couldn't find any interpretation as classes/namespaces, so give up */
-         /* The quotes are important if copy is empty.  */
-         cplusplus_error (saved_arg,
-                          "Can't find member of namespace, class, struct, or union named \"%s\"\n",
-                          copy);
+      /* 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] != '\''))
+       {
+         if (p[0] == '<')
+           {
+             temp_end = find_template_name_end (p);
+             if (!temp_end)
+               error ("malformed template specification in command");
+             p = temp_end;
+           }
+         else if ((p[0] == ':') && (p[1] == ':'))
+           break;      /* Found double-colon.  */
+         else
+           p++;
        }
-      /*  end of C++  */
 
+      if (*p != ':')
+       break;          /* Out of the while (1).  */
+
+      p2 = p;          /* Save restart for next time around.  */
+      *argptr = saved_arg2;    /* Restore argptr.  */
+    }                  /* while (1) */
+
+  /* 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.  */
+  copy[p - saved_arg2] = '\000';
+  /* Set argptr to skip over the name.  */
+  *argptr = (*p == '\'') ? p + 1 : p;
+  /* Look up entire name */
+  sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+  if (sym)
+    return symbol_found (funfirstline, canonical, copy, sym,
+                        NULL, sym_symtab);
+
+  /* Couldn't find any interpretation as classes/namespaces, so give
+     up.  The quotes are important if copy is empty.  */
+  cplusplus_error (saved_arg,
+                  "Can't find member of namespace, class, struct, or union named \"%s\"\n",
+                  copy);
+}
 
-      /* Extract the file name.  */
-      p1 = p;
-      while (p != *argptr && p[-1] == ' ')
-       --p;
-      if ((*p == '"') && 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] == '"')
-       copy[p - *argptr - 1] = 0;
-      else
-       copy[p - *argptr] = 0;
+/* 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.  */
+
+static struct symbol *
+lookup_prefix_sym (char **argptr, char *p)
+{
+  char *p1;
+  char *copy;
 
-      /* Find that file's data.  */
-      s = lookup_symtab (copy);
-      if (s == 0)
+  /* 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 arg.  */
+  p = p1 + (p1[0] == ':' ? 2 : 1);
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  return lookup_symbol (copy, 0, STRUCT_DOMAIN, 0,
+                       (struct symtab **) NULL);
+}
+
+/* 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)
+{
+  struct symtabs_and_lines values;
+  struct symbol *sym = 0;
+  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 = collect_methods (copy, t, sym_arr);
+
+  if (i1 == 1)
+    {
+      /* There is exactly one field with that name.  */
+      sym = sym_arr[0];
+
+      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
        {
-         if (!have_full_symbols () && !have_partial_symbols ())
-           error ("No symbol table is loaded.  Use the \"file\" command.");
-         error ("No source file named %s.", copy);
+         values.sals = (struct symtab_and_line *)
+           xmalloc (sizeof (struct symtab_and_line));
+         values.nelts = 1;
+         values.sals[0] = find_function_start_sal (sym,
+                                                   funfirstline);
        }
-
-      /* Discard the file name from the arg.  */
-      p = p1 + 1;
-      while (*p == ' ' || *p == '\t')
-       p++;
-      *argptr = p;
+      else
+       {
+         values.nelts = 0;
+       }
+      return values;
+    }
+  if (i1 > 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);
     }
-#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 */
+      char *tmp;
 
-      /* 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. */
-
-      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)
+      if (is_operator_name (copy))
        {
-         *argptr = (*p == '\'') ? p + 1 : p;
-         return symbol_found (funfirstline, canonical, copy, sym,
-                              NULL, sym_symtab);
+         tmp = (char *) alloca (strlen (copy + 3) + 9);
+         strcpy (tmp, "operator ");
+         strcat (tmp, copy + 3);
        }
-      /* Otherwise fall out from here and go to file/line spec
-         processing, etc. */
+      else
+       tmp = copy;
+      if (tmp[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), tmp);
     }
-#endif
-
-  /* S 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) */
+/* Find all methods named COPY in the class whose type is T, and put
+   them in SYM_ARR.  Return the number of methods found.  */
 
-  q = *argptr;
-  if (*q == '-' || *q == '+')
-    q++;
-  while (*q >= '0' && *q <= '9')
-    q++;
+static int
+collect_methods (char *copy, struct type *t,
+                struct symbol **sym_arr)
+{
+  int i1 = 0;  /*  Counter for the symbol array.  */
 
-  if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
+  if (destructor_name_p (copy, t))
     {
-      /* We found a token consisting of all digits -- at least one digit.  */
-      enum sign
+      /* Destructors are a special case.  */
+      int m_index, f_index;
+
+      if (get_destructor_fn_field (t, &m_index, &f_index))
        {
-         none, plus, minus
+         struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
+
+         sym_arr[i1] =
+           lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
+                          NULL, VAR_DOMAIN, (int *) NULL,
+                          (struct symtab **) NULL);
+         if (sym_arr[i1])
+           i1++;
        }
-      sign = none;
+    }
+  else
+    i1 = find_methods (t, copy, sym_arr);
 
-      /* We might need a canonical line spec if no file was specified.  */
-      int need_canonical = (s == 0) ? 1 : 0;
+  return i1;
+}
 
-      /* 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  */
+\f
 
-      if (s == 0 && default_symtab == 0)
-       {
-          struct symtab_and_line cursal;
+/* Return the symtab associated to the filename given by the substring
+   of *ARGPTR ending at P, and advance ARGPTR past that filename.  */
 
-         /* Make sure we have at least a default source file. */
-         set_default_source_symtab_and_line ();
-          cursal = get_current_source_symtab_and_line ();
-      
-          default_symtab = cursal.symtab;
-          default_line = cursal.line;
-       }
+static struct symtab *
+symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+{
+  char *p1;
+  char *copy;
+  struct symtab *file_symtab;
+  
+  p1 = p;
+  while (p != *argptr && p[-1] == ' ')
+    --p;
+  if ((*p == '"') && 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] == '"')
+    copy[p - *argptr - 1] = 0;
+  else
+    copy[p - *argptr] = 0;
 
-      if (**argptr == '+')
-       sign = plus, (*argptr)++;
-      else if (**argptr == '-')
-       sign = minus, (*argptr)++;
-      val.line = atoi (*argptr);
-      switch (sign)
-       {
-       case plus:
-         if (q == *argptr)
-           val.line = 5;
-         if (s == 0)
-           val.line = default_line + val.line;
-         break;
-       case minus:
-         if (q == *argptr)
-           val.line = 15;
-         if (s == 0)
-           val.line = default_line - val.line;
-         else
-           val.line = 1;
-         break;
-       case none:
-         break;                /* No need to adjust val.line.  */
-       }
+  /* Find that file's data.  */
+  file_symtab = lookup_symtab (copy);
+  if (file_symtab == 0)
+    {
+      if (!have_full_symbols () && !have_partial_symbols ())
+       error ("No symbol table is loaded.  Use the \"file\" command.");
+      error ("No source file named %s.", copy);
+    }
 
-      while (*q == ' ' || *q == '\t')
-       q++;
-      *argptr = q;
-      if (s == 0)
-       s = default_symtab;
+  /* Discard the file name from the arg.  */
+  p = p1 + 1;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
 
-      /* It is possible that this source file has more than one symtab, 
-         and that the new line number specification has moved us from the
-         default (in s) to a new one.  */
-      val.symtab = find_line_symtab (s, val.line, NULL, NULL);
-      if (val.symtab == 0)
-       val.symtab = s;
+  return file_symtab;
+}
 
-      val.pc = 0;
-      values.sals = (struct symtab_and_line *)
-       xmalloc (sizeof (struct symtab_and_line));
-      values.sals[0] = val;
-      values.nelts = 1;
-      if (need_canonical)
-       build_canonical_line_spec (values.sals, NULL, canonical);
-      return values;
-    }
+\f
 
-  /* Arg token is not digits => try it as a variable name
-     Find the next token (everything up to end or next whitespace).  */
+/* This decodes a line where the argument is all digits (possibly
+   preceded by a sign).  Q should point to the end of those digits;
+   the other arguments are as usual.  */
 
-  if (**argptr == '$')         /* May be a convenience variable */
-    p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));       /* One or two $ chars possible */
-  else if (is_quoted)
+static struct symtabs_and_lines
+decode_all_digits (char **argptr, struct symtab *default_symtab,
+                  int default_line, char ***canonical,
+                  struct symtab *file_symtab, char *q)
+
+{
+  struct symtabs_and_lines values;
+  struct symtab_and_line val;
+
+  enum sign
     {
-      p = skip_quoted (*argptr);
-      if (p[-1] != '\'')
-       error ("Unmatched single quote.");
+      none, plus, minus
     }
-  else if (has_parens)
+  sign = none;
+
+  /* We might need a canonical line spec if no file was specified.  */
+  int need_canonical = (file_symtab == 0) ? 1 : 0;
+
+  init_sal (&val);
+
+  /* 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.  */
+
+  if (file_symtab == 0 && default_symtab == 0)
     {
-      p = pp + 1;
+      /* Make sure we have at least a default source file.  */
+      set_default_source_symtab_and_line ();
+      initialize_defaults (&default_symtab, &default_line);
     }
-  else
+
+  if (**argptr == '+')
+    sign = plus, (*argptr)++;
+  else if (**argptr == '-')
+    sign = minus, (*argptr)++;
+  val.line = atoi (*argptr);
+  switch (sign)
     {
-      p = skip_quoted (*argptr);
+    case plus:
+      if (q == *argptr)
+       val.line = 5;
+      if (file_symtab == 0)
+       val.line = default_line + val.line;
+      break;
+    case minus:
+      if (q == *argptr)
+       val.line = 15;
+      if (file_symtab == 0)
+       val.line = default_line - val.line;
+      else
+       val.line = 1;
+      break;
+    case none:
+      break;           /* No need to adjust val.line.  */
     }
 
-  copy = (char *) alloca (p - *argptr + 1);
-  memcpy (copy, *argptr, p - *argptr);
-  copy[p - *argptr] = '\0';
-  if (p != *argptr
-      && copy[0]
-      && copy[0] == copy[p - *argptr - 1]
-      && strchr (get_gdb_completer_quote_characters (), copy[0]) != NULL)
+  while (*q == ' ' || *q == '\t')
+    q++;
+  *argptr = q;
+  if (file_symtab == 0)
+    file_symtab = default_symtab;
+
+  /* It is possible that this source file has more than one symtab, 
+     and that the new line number specification has moved us from the
+     default (in file_symtab) to a new one.  */
+  val.symtab = find_line_symtab (file_symtab, val.line, NULL, NULL);
+  if (val.symtab == 0)
+    val.symtab = file_symtab;
+
+  val.pc = 0;
+  values.sals = (struct symtab_and_line *)
+    xmalloc (sizeof (struct symtab_and_line));
+  values.sals[0] = val;
+  values.nelts = 1;
+  if (need_canonical)
+    build_canonical_line_spec (values.sals, NULL, canonical);
+  return values;
+}
+
+\f
+
+/* Decode a linespec starting with a dollar sign.  */
+
+static struct symtabs_and_lines
+decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
+              char ***canonical, struct symtab *file_symtab)
+{
+  struct value *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.  */
     {
-      copy[p - *argptr - 1] = '\0';
-      copy++;
+      /* We have a value history reference.  */
+      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.");
+    }
+  else
+    {
+      /* Not all digits -- may be user variable/function or a
+        convenience variable.  */
+
+      /* Look up entire name as a symbol first.  */
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
+      file_symtab = (struct symtab *) 0;
+      need_canonical = 1;
+      /* Symbol was found --> jump to normal symbol processing.  */
+      if (sym)
+       return symbol_found (funfirstline, canonical, copy, sym,
+                            NULL, sym_symtab);
+
+      /* 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.  */
+      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.");
     }
-  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 */
+  init_sal (&val);
 
-  if (*copy == '$')
-    {
-      struct value *valx;
-      int index = 0;
-      int need_canonical = 0;
-
-      p = (copy[1] == '$') ? copy + 2 : copy + 1;
-      while (*p >= '0' && *p <= '9')
-       p++;
-      if (!*p)                 /* reached end of token without hitting non-digit */
-       {
-         /* We have a value history reference */
-         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.");
-       }
-      else
-       {
-         /* Not all digits -- may be user variable/function or a
-            convenience variable */
-
-         /* Look up entire name as a symbol first */
-         sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
-         s = (struct symtab *) 0;
-         need_canonical = 1;
-         /* Symbol was found --> jump to normal symbol processing.  */
-         if (sym)
-           return symbol_found (funfirstline, canonical, copy, sym,
-                                NULL, sym_symtab);
-
-         /* 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. */
-         if (msymbol)
-           return minsym_found (funfirstline, msymbol);
-
-         /* Not a user variable or function -- must be convenience variable */
-         need_canonical = (s == 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.");
-       }
+  /* 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.pc = 0;
 
-      /* Either history value or convenience value from above, in valx */
-      val.symtab = s ? s : default_symtab;
-      val.line = value_as_long (valx);
-      val.pc = 0;
+  values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
+  values.sals[0] = val;
+  values.nelts = 1;
 
-      values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
-      values.sals[0] = val;
-      values.nelts = 1;
+  if (need_canonical)
+    build_canonical_line_spec (values.sals, NULL, canonical);
 
-      if (need_canonical)
-       build_canonical_line_spec (values.sals, NULL, canonical);
+  return values;
+}
 
-      return values;
-    }
+\f
 
+/* Decode a linespec that's a variable.  If FILE_SYMTAB is non-NULL,
+   look in that symtab's static variables first.  */
 
-  /* Look up that token as a variable.
-     If file specified, use that file's per-file block to start with.  */
+static struct symtabs_and_lines
+decode_variable (char *copy, int funfirstline, char ***canonical,
+                struct symtab *file_symtab)
+{
+  struct symbol *sym;
+  /* The symtab that SYM was found in.  */
+  struct symtab *sym_symtab;
+
+  struct minimal_symbol *msymbol;
 
   sym = lookup_symbol (copy,
-                      (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
+                      (file_symtab
+                       ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
+                                            STATIC_BLOCK)
                        : get_selected_block (0)),
-                      VAR_NAMESPACE, 0, &sym_symtab);
+                      VAR_DOMAIN, 0, &sym_symtab);
 
   if (sym != NULL)
-    return symbol_found (funfirstline, canonical, copy, sym, s, sym_symtab);
+    return symbol_found (funfirstline, canonical, copy, sym,
+                        file_symtab, sym_symtab);
 
   msymbol = lookup_minimal_symbol (copy, NULL, NULL);
 
@@ -1208,7 +1633,6 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
     error ("No symbol table is loaded.  Use the \"file\" command.");
 
   error ("Function \"%s\" not defined.", copy);
-  return values;               /* for lint */
 }
 
 
@@ -1222,7 +1646,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
 static struct symtabs_and_lines
 symbol_found (int funfirstline, char ***canonical, char *copy,
-             struct symbol *sym, struct symtab *s,
+             struct symbol *sym, struct symtab *file_symtab,
              struct symtab *sym_symtab)
 {
   struct symtabs_and_lines values;
@@ -1241,11 +1665,11 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
 
       /* We might need a canonical line spec if it is a static
         function.  */
-      if (s == 0)
+      if (file_symtab == 0)
        {
          struct blockvector *bv = BLOCKVECTOR (sym_symtab);
          struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-         if (lookup_block_symbol (b, copy, NULL, VAR_NAMESPACE) != NULL)
+         if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
            build_canonical_line_spec (values.sals, copy, canonical);
        }
       return values;
This page took 0.047627 seconds and 4 git commands to generate.