From Bernardo Innocenti <bernie@develer.com>:
[deliverable/binutils-gdb.git] / gdb / linespec.c
index 5f90985cb8e919363ba90b0bb996e015e9125122..741ac8835040b380ec274d83e6f9e739123fd148 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,
 /* 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.
    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 "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. */
 
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -48,12 +51,30 @@ static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
 
 
 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 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 NORETURN void cplusplus_error (const char *name,
                                      const char *fmt, ...)
      ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
@@ -62,20 +83,52 @@ 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 *, 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 ***);
 
 static char *find_toplevel_char (char *s, char c);
 
 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 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,
+                                           int *not_found_ptr);
+
+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,
+                                                int *not_found_ptr);
+
 static struct
 symtabs_and_lines symbol_found (int funfirstline,
                                char ***canonical,
                                char *copy,
                                struct symbol *sym,
 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
                                struct symtab *sym_symtab);
 
 static struct
@@ -152,7 +205,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,
      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;
                         (struct symtab **) NULL)))
     {
       int method_counter;
@@ -168,7 +221,6 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
           method_counter >= 0;
           --method_counter)
        {
           method_counter >= 0;
           --method_counter)
        {
-         int field_counter;
          char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
          char dem_opname[64];
 
          char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
          char dem_opname[64];
 
@@ -184,86 +236,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.  */
 
          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] == '<'))
          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);
        }
     }
 
        }
     }
 
@@ -285,6 +264,113 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
   return 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,
+                     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.
 /* 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.
@@ -336,7 +422,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 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++)
   char *scan;
 
   for (scan = s; *scan; scan++)
@@ -361,6 +447,25 @@ find_toplevel_char (char *s, char c)
   return 0;
 }
 
   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
 /* 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
@@ -396,23 +501,31 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
   printf_unfiltered ("[0] cancel\n[1] all\n");
   while (i < nelts)
     {
   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);
       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);
+         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++;
     }
 
        }
       else
        printf_unfiltered ("?HERE\n");
       i++;
     }
 
-  if ((prompt = getenv ("PS2")) == NULL)
+  prompt = getenv ("PS2");
+  if (prompt == NULL)
     {
       prompt = "> ";
     }
     {
       prompt = "> ";
     }
@@ -444,7 +557,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
                {
                  if (canonical_arr[i] == NULL)
                    {
                {
                  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));
                    }
                }
                      canonical_arr[i] = savestring (symname, strlen (symname));
                    }
                }
@@ -467,7 +580,7 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
            {
              if (canonical_arr)
                {
            {
              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));
                }
                  make_cleanup (xfree, symname);
                  canonical_arr[i] = savestring (symname, strlen (symname));
                }
@@ -526,7 +639,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.
 
    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
 
 /* We allow single quotes in various places.  This is a hideous
    kludge, which exists because the completer can't yet deal with the
@@ -535,19 +653,13 @@ 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,
 
 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)
 {
 {
-  struct symtabs_and_lines values;
-  struct symtab_and_line val;
-  register char *p, *p1;
+  char *p;
   char *q;
   char *q;
-  register struct symtab *s = NULL;
-
-  register struct symbol *sym;
-  /* The symtab that SYM was found in.  */
-  struct symtab *sym_symtab;
+  /* If a file name is specified, this is its symtab.  */
+  struct symtab *file_symtab = NULL;
 
 
-  register struct minimal_symbol *msymbol;
   char *copy;
   /* This is NULL if there are no parens in *ARGPTR, or a pointer to
      the closing parenthesis if there are parens.  */
   char *copy;
   /* This is NULL if there are no parens in *ARGPTR, or a pointer to
      the closing parenthesis if there are parens.  */
@@ -557,24 +669,25 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   int is_quoted;
   /* Is part of *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
   int is_quoted;
   /* Is part of *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
+  int is_objc_method = 0;
   char *saved_arg = *argptr;
 
   char *saved_arg = *argptr;
 
-  init_sal (&val);             /* initialize to zeroes */
+  if (not_found_ptr)
+    *not_found_ptr = 0;
 
   /* Defaults have defaults.  */
 
   initialize_defaults (&default_symtab, &default_line);
   
 
   /* 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);
 
 
   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 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);
 
 
   set_flags (*argptr, &is_quoted, &paren_pointer);
 
@@ -585,46 +698,42 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   p = locate_first_half (argptr, &is_quote_enclosed);
 
 
   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;
+      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;
   /* Does it look like there actually were two parts?  */
 
   if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
     {
       if (is_quoted)
        *argptr = *argptr + 1;
+      
+      /* Is it a C++ or Java compound data structure?  */
+
       if (p[0] == '.' || p[1] == ':')
       if (p[0] == '.' || p[1] == ':')
-       /*  C++ */
-       /*  ... or Java */
        return decode_compound (argptr, funfirstline, canonical,
                                saved_arg, p);
 
        return decode_compound (argptr, funfirstline, canonical,
                                saved_arg, p);
 
-      /* 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;
-
-      /* Find that file's data.  */
-      s = lookup_symtab (copy);
-      if (s == 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);
-       }
+      /* No, the first part is a filename; set s to be that file's
+        symtab.  Also, move argptr past the filename.  */
 
 
-      /* Discard the file name from the arg.  */
-      p = p1 + 1;
-      while (*p == ' ' || *p == '\t')
-       p++;
-      *argptr = p;
+      file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed, 
+                                         not_found_ptr);
     }
 #if 0
   /* No one really seems to know why this was added. It certainly
     }
 #if 0
   /* No one really seems to know why this was added. It certainly
@@ -649,7 +758,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       copy = (char *) alloca (p - *argptr + 1);
       memcpy (copy, *argptr, p - *argptr);
       copy[p - *argptr] = '\000';
       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);
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
       if (sym)
        {
          *argptr = (*p == '\'') ? p + 1 : p;
       if (sym)
        {
          *argptr = (*p == '\'') ? p + 1 : p;
@@ -664,7 +773,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   /* S is specified file's symtab, or 0 if no file specified.
      arg no longer contains the file name.  */
 
   /* 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) */
+  /* Check whether arg is all digits (and sign) */
 
   q = *argptr;
   if (*q == '-' || *q == '+')
 
   q = *argptr;
   if (*q == '-' || *q == '+')
@@ -673,89 +782,27 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
     q++;
 
   if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
     q++;
 
   if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
-    {
-      /* We found a token consisting of all digits -- at least one digit.  */
-      enum sign
-       {
-         none, plus, minus
-       }
-      sign = none;
-
-      /* We might need a canonical line spec if no file was specified.  */
-      int need_canonical = (s == 0) ? 1 : 0;
-
-      /* 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 (s == 0 && default_symtab == 0)
-       {
-         /* Make sure we have at least a default source file. */
-         set_default_source_symtab_and_line ();
-         initialize_defaults (&default_symtab, &default_line);
-       }
-
-      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.  */
-       }
-
-      while (*q == ' ' || *q == '\t')
-       q++;
-      *argptr = q;
-      if (s == 0)
-       s = 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 s) to a new one.  */
-      val.symtab = find_line_symtab (s, val.line, NULL, NULL);
-      if (val.symtab == 0)
-       val.symtab = s;
-
-      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;
-    }
+    /* 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).  */
 
 
   /* 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);
       if (p[-1] != '\'')
        error ("Unmatched single quote.");
     }
   else if (is_quoted)
     {
       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 if (paren_pointer != NULL)
     {
       p = paren_pointer + 1;
@@ -782,90 +829,17 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   /* If it starts with $: may be a legitimate variable or routine name
      (e.g. HP-UX millicode routines such as $$dyncall), or it may
 
   /* 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 == '$')
 
   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 = 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;
-
-      if (need_canonical)
-       build_canonical_line_spec (values.sals, NULL, canonical);
-
-      return values;
-    }
-
+    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.  */
 
 
   /* Look up that token as a variable.
      If file specified, use that file's per-file block to start with.  */
 
-  sym = lookup_symbol (copy,
-                      (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
-                       : get_selected_block (0)),
-                      VAR_NAMESPACE, 0, &sym_symtab);
-
-  if (sym != NULL)
-    return symbol_found (funfirstline, canonical, copy, sym, s, sym_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.");
-
-  error ("Function \"%s\" not defined.", copy);
-  return values;               /* for lint */
+  return decode_variable (copy, funfirstline, canonical,
+                         file_symtab, not_found_ptr);
 }
 
 \f
 }
 
 \f
@@ -920,8 +894,8 @@ set_flags (char *arg, int *is_quoted, char **paren_pointer)
   int has_if = 0;
 
   /* 'has_if' is for the syntax:
   int has_if = 0;
 
   /* 'has_if' is for the syntax:
-   *     (gdb) break foo if (a==b)
-   */
+        (gdb) break foo if (a==b)
+  */
   if ((ii = strstr (arg, " if ")) != NULL ||
       (ii = strstr (arg, "\tif ")) != NULL ||
       (ii = strstr (arg, " if\t")) != NULL ||
   if ((ii = strstr (arg, " if ")) != NULL ||
       (ii = strstr (arg, "\tif ")) != NULL ||
       (ii = strstr (arg, " if\t")) != NULL ||
@@ -929,10 +903,9 @@ set_flags (char *arg, int *is_quoted, char **paren_pointer)
       (ii = strstr (arg, " if(")) != NULL ||
       (ii = strstr (arg, "\tif( ")) != NULL)
     has_if = 1;
       (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';
   if (has_if)
     {
       *ii = '\0';
@@ -946,9 +919,8 @@ set_flags (char *arg, int *is_quoted, char **paren_pointer)
   if (*paren_pointer != NULL)
     *paren_pointer = strrchr (*paren_pointer, ')');
 
   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 
-   */
+  /* Now that we're safely past the paren_pointer check, put back " if
+     (condition)" so outer layers can see it.  */
   if (has_if)
     *ii = ' ';
 }
   if (has_if)
     *ii = ' ';
 }
@@ -1001,18 +973,16 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   ii = find_toplevel_char (*argptr, ',');
   has_comma = (ii != 0);
 
   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';
     }
 
   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] == '"')
 
   p = *argptr;
   if (p[0] == '"')
@@ -1032,18 +1002,26 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
            error ("malformed template specification in command");
          p = temp_end;
        }
            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
          || 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. */
+         /* Java qualified method.  Find the *last* '.', since the
+            others are package qualifiers.  */
          for (p1 = p; *p1; p1++)
            {
              if (*p1 == '.')
          for (p1 = p; *p1; p1++)
            {
              if (*p1 == '.')
@@ -1055,7 +1033,7 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   while (p[0] == ' ' || p[0] == '\t')
     p++;
 
   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 (*is_quote_enclosed)
     {
       char *closing_quote = strchr (p - 1, '"');
@@ -1063,9 +1041,8 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
        *closing_quote = '\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 (has_comma)
     *ii = ',';
 
@@ -1074,6 +1051,95 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
 
 \f
 
 
 \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)
+    {
+      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
+       {
+         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.  */
+         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;
+    }
+
+  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.  */
 
 /* This handles C++ and Java compound data structures.  P should point
    at the first component separator, i.e. double-colon or period.  */
 
@@ -1082,7 +1148,7 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
                 char *saved_arg, char *p)
 {
   struct symtabs_and_lines values;
                 char *saved_arg, char *p)
 {
   struct symtabs_and_lines values;
-  char *p1, *p2;
+  char *p2;
 #if 0
   char *q, *q1;
 #endif
 #if 0
   char *q, *q1;
 #endif
@@ -1093,13 +1159,12 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
   struct symtab *sym_symtab;
   char *copy;
   struct symbol *sym_class;
   struct symtab *sym_symtab;
   char *copy;
   struct symbol *sym_class;
-  int i1;
   struct symbol **sym_arr;
   struct type *t;
 
   /* First check for "global" namespace specification,
   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 */
+     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;
   if (p[0] == ':' 
       && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
     saved_arg2 += 2;
@@ -1122,35 +1187,21 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
      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
      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. */
+     "B::C" separately as a symbol in the previous example.  */
 
 
-  p2 = p;              /* save for restart */
+  p2 = p;              /* Save for restart.  */
   while (1)
     {
   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;
-
-      /* Discard the class name from the arg.  */
-      p = p1 + (p1[0] == ':' ? 2 : 1);
-      while (*p == ' ' || *p == '\t')
-       p++;
-      *argptr = p;
-
-      sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
-                                (struct symtab **) NULL);
+      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)))
        {
 
       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). */
+         /* 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 (**argptr
              && strchr (get_gdb_completer_quote_characters (),
                         **argptr) != NULL)
@@ -1194,86 +1245,18 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
              copy[p - *argptr - 1] = '\0';
          }
 
              copy[p - *argptr - 1] = '\0';
          }
 
-         /* no line number may be specified */
+         /* No line number may be specified.  */
          while (*p == ' ' || *p == '\t')
            p++;
          *argptr = p;
 
          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);
-           }
+         return find_method (funfirstline, canonical, saved_arg,
+                             copy, t, sym_class);
        }
 
        }
 
-      /* Move pointer up to next possible class/namespace token */
-      p = p2 + 1;      /* restart with old value +1 */
-      /* Move pointer ahead to next double-colon */
+      /* 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] == '<')
       while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
        {
          if (p[0] == '<')
@@ -1284,40 +1267,430 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
              p = temp_end;
            }
          else if ((p[0] == ':') && (p[1] == ':'))
              p = temp_end;
            }
          else if ((p[0] == ':') && (p[1] == ':'))
-           break;      /* found double-colon */
+           break;      /* Found double-colon.  */
          else
            p++;
        }
 
       if (*p != ':')
          else
            p++;
        }
 
       if (*p != ':')
-       break;          /* out of the while (1) */
+       break;          /* Out of the while (1).  */
 
 
-      p2 = p;          /* save restart for next time around */
-      *argptr = saved_arg2;    /* restore argptr */
+      p2 = p;          /* Save restart for next time around.  */
+      *argptr = saved_arg2;    /* Restore argptr.  */
     }                  /* while (1) */
 
     }                  /* 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 */
+  /* 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);
   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';
   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 */
   *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, &sym_symtab);
   if (sym)
     return symbol_found (funfirstline, canonical, copy, sym,
                         NULL, 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.  */
+  /* 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);
 }
 
   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.  */
+
+static struct symbol *
+lookup_prefix_sym (char **argptr, char *p)
+{
+  char *p1;
+  char *copy;
+
+  /* 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)
+       {
+         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_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);
+    }
+}
+
+/* Find all methods named COPY in the class whose type is T, and put
+   them in SYM_ARR.  Return the number of methods found.  */
+
+static int
+collect_methods (char *copy, struct type *t,
+                struct symbol **sym_arr)
+{
+  int i1 = 0;  /*  Counter for the symbol array.  */
+
+  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_DOMAIN, (int *) NULL,
+                          (struct symtab **) NULL);
+         if (sym_arr[i1])
+           i1++;
+       }
+    }
+  else
+    i1 = find_methods (t, copy, sym_arr);
+
+  return i1;
+}
+
+\f
+
+/* Return the symtab associated to the filename given by the substring
+   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, 
+                     int *not_found_ptr)
+{
+  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;
+
+  /* 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.");
+      if (not_found_ptr)
+       {
+         *not_found_ptr = 1;
+         throw_exception (RETURN_ERROR);
+       }
+      error ("No source file named %s.", copy);
+    }
+
+  /* Discard the file name from the arg.  */
+  p = p1 + 1;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  return file_symtab;
+}
+
+\f
+
+/* 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.  */
+
+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
+    {
+      none, plus, minus
+    }
+  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)
+    {
+      /* Make sure we have at least a default source file.  */
+      set_default_source_symtab_and_line ();
+      initialize_defaults (&default_symtab, &default_line);
+    }
+
+  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 (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.  */
+    }
+
+  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.  */
+    {
+      /* 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.");
+    }
+
+  init_sal (&val);
+
+  /* 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;
+
+  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);
+
+  return values;
+}
+
+\f
+
+/* Decode a linespec that's a variable.  If FILE_SYMTAB is non-NULL,
+   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, 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,
+                      (file_symtab
+                       ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
+                                            STATIC_BLOCK)
+                       : get_selected_block (0)),
+                      VAR_DOMAIN, 0, &sym_symtab);
+
+  if (sym != NULL)
+    return symbol_found (funfirstline, canonical, copy, sym,
+                        file_symtab, sym_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;
+      throw_exception (RETURN_ERROR);
+    }
+  
+  error ("Function \"%s\" not defined.", copy);
+}
+
+
 \f
 
 /* Now come some functions that are called from multiple places within
 \f
 
 /* Now come some functions that are called from multiple places within
@@ -1328,7 +1701,7 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
 
 static struct symtabs_and_lines
 symbol_found (int funfirstline, char ***canonical, char *copy,
 
 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;
              struct symtab *sym_symtab)
 {
   struct symtabs_and_lines values;
@@ -1347,11 +1720,11 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
 
       /* We might need a canonical line spec if it is a static
         function.  */
 
       /* 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);
        {
          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;
            build_canonical_line_spec (values.sals, copy, canonical);
        }
       return values;
@@ -1392,7 +1765,7 @@ minsym_found (int funfirstline, struct minimal_symbol *msymbol)
   values.sals = (struct symtab_and_line *)
     xmalloc (sizeof (struct symtab_and_line));
   values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
   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);
+                                     (struct bfd_section *) 0, 0);
   values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
   if (funfirstline)
     {
   values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
   if (funfirstline)
     {
This page took 0.041486 seconds and 4 git commands to generate.