2002-12-06 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / linespec.c
index 266ac6dba77fe59cfc8a79796ad6eb95fc67e7af..0386a7511a96acb3d62cf0ba789c0d090ffd0277 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
+   1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "command.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "source.h"
 #include "demangle.h"
 #include "value.h"
 #include "completer.h"
-
-/* Prototype for one function in parser-defs.h,
-   instead of including that entire file. */
-
-extern char *find_template_name_end (char *);
+#include "cp-abi.h"
+#include "parser-defs.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -41,7 +39,24 @@ extern char *operator_chars (char *, char **);
 
 /* Prototypes for local functions */
 
-static void cplusplus_hint (char *name);
+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_compound (char **argptr,
+                                                int funfirstline,
+                                                char ***canonical,
+                                                char *saved_arg,
+                                                char *p);
+
+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);
 
@@ -55,19 +70,48 @@ 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 symbol_found (int funfirstline,
+                               char ***canonical,
+                               char *copy,
+                               struct symbol *sym,
+                               struct symtab *s,
+                               struct symtab *sym_symtab);
+
+static struct
+symtabs_and_lines minsym_found (int funfirstline,
+                               struct minimal_symbol *msymbol);
+
 /* Helper functions. */
 
-/* While the C++ support is still in flux, issue a possibly helpful hint on
-   using the new command completion feature on single quoted demangled C++
-   symbols.  Remove when loose ends are cleaned up.   FIXME -fnf */
+/* Issue a helpful hint on using the command completion feature on
+   single quoted demangled C++ symbols as part of the completion
+   error.  */
 
-static void
-cplusplus_hint (char *name)
+static NORETURN void
+cplusplus_error (const char *name, const char *fmt, ...)
 {
+  struct ui_file *tmp_stream;
+  tmp_stream = mem_fileopen ();
+  make_cleanup_ui_file_delete (tmp_stream);
+
+  {
+    va_list args;
+    va_start (args, fmt);
+    vfprintf_unfiltered (tmp_stream, fmt, args);
+    va_end (args);
+  }
+
   while (*name == '\'')
     name++;
-  printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
-  printf_filtered ("(Note leading single quote.)\n");
+  fprintf_unfiltered (tmp_stream,
+                     ("Hint: try '%s<TAB> or '%s<ESC-?>\n"
+                      "(Note leading single quote.)"),
+                     name, name);
+  error_stream (tmp_stream);
 }
 
 /* Return the number of methods described for TYPE, including the
@@ -104,23 +148,20 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
 {
   int i1 = 0;
   int ibase;
-  struct symbol *sym_class;
   char *class_name = type_name_no_tag (t);
 
   /* Ignore this class if it doesn't have a name.  This is ugly, but
      unless we figure out how to get the physname without the name of
      the class, then the loop can't do any good.  */
   if (class_name
-      && (sym_class = lookup_symbol (class_name,
-                                    (struct block *) NULL,
-                                    STRUCT_NAMESPACE,
-                                    (int *) NULL,
-                                    (struct symtab **) NULL)))
+      && (lookup_symbol (class_name, (struct block *) NULL,
+                        STRUCT_NAMESPACE, (int *) NULL,
+                        (struct symtab **) NULL)))
     {
       int method_counter;
+      int name_len = strlen (name);
 
-      /* FIXME: Shouldn't this just be CHECK_TYPEDEF (t)?  */
-      t = SYMBOL_TYPE (sym_class);
+      CHECK_TYPEDEF (t);
 
       /* Loop over each method name.  At this level, all overloads of a name
          are counted as a single name.  There is an inner loop which loops over
@@ -144,7 +185,7 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
                method_name = dem_opname;
            }
 
-         if (STREQ (name, method_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;
@@ -168,9 +209,9 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
                  }
                else
                  phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-
+               
                /* Destructor is handled by caller, dont add it to the list */
-               if (DESTRUCTOR_PREFIX_P (phys_name))
+               if (is_destructor_name (phys_name) != 0)
                  continue;
 
                sym_arr[i1] = lookup_symbol (phys_name,
@@ -191,6 +232,41 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
                     */
                  }
              }
+         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++;
+               }
+           }
        }
     }
 
@@ -254,7 +330,9 @@ build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
 
 /* Find an instance of the character C in the string S that is outside
    of all parenthesis pairs, single-quoted strings, and double-quoted
-   strings.  */
+   strings.  Also, ignore the char within a template name, like a ','
+   within foo<int, int>.  */
+
 static char *
 find_toplevel_char (char *s, char c)
 {
@@ -277,9 +355,9 @@ find_toplevel_char (char *s, char c)
        return scan;
       else if (*scan == '"' || *scan == '\'')
        quoted = *scan;
-      else if (*scan == '(')
+      else if (*scan == '(' || *scan == '<')
        depth++;
-      else if (*scan == ')' && depth > 0)
+      else if ((*scan == ')' || *scan == '>') && depth > 0)
        depth--;
     }
 
@@ -321,8 +399,8 @@ 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 (&values.sals[i]);
+      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);
@@ -463,493 +541,70 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
               int default_line, char ***canonical)
 {
   struct symtabs_and_lines values;
-#ifdef HPPA_COMPILER_BUG
-  /* FIXME: The native HP 9000/700 compiler has a bug which appears
-     when optimizing this file with target i960-vxworks.  I haven't
-     been able to construct a simple test case.  The problem is that
-     in the second call to SKIP_PROLOGUE below, the compiler somehow
-     does not realize that the statement val = find_pc_line (...) will
-     change the values of the fields of val.  It extracts the elements
-     into registers at the top of the block, and does not update the
-     registers after the call to find_pc_line.  You can check this by
-     inserting a printf at the end of find_pc_line to show what values
-     it is returning for val.pc and val.end and another printf after
-     the call to see what values the function actually got (remember,
-     this is compiling with cc -O, with this patch removed).  You can
-     also examine the assembly listing: search for the second call to
-     skip_prologue; the LDO statement before the next call to
-     find_pc_line loads the address of the structure which
-     find_pc_line will return; if there is a LDW just before the LDO,
-     which fetches an element of the structure, then the compiler
-     still has the bug.
-
-     Setting val to volatile avoids the problem.  We must undef
-     volatile, because the HPPA native compiler does not define
-     __STDC__, although it does understand volatile, and so volatile
-     will have been defined away in defs.h.  */
-#undef volatile
-  volatile struct symtab_and_line val;
-#define volatile               /*nothing */
-#else
   struct symtab_and_line val;
-#endif
-  register char *p, *p1;
-  char *q, *pp, *ii, *p2;
-#if 0
-  char *q1;
-#endif
-  register struct symtab *s;
+  char *p;
+  char *q;
+  struct symtab *s = NULL;
 
-  register struct symbol *sym;
+  struct symbol *sym;
   /* The symtab that SYM was found in.  */
   struct symtab *sym_symtab;
 
-  register CORE_ADDR pc;
-  register struct minimal_symbol *msymbol;
+  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;
   char *saved_arg = *argptr;
-  extern char *gdb_completer_quote_characters;
 
-  INIT_SAL (&val);             /* initialize to zeroes */
+  init_sal (&val);             /* initialize to zeroes */
 
   /* Defaults have defaults.  */
 
-  if (default_symtab == 0)
-    {
-      default_symtab = current_source_symtab;
-      default_line = current_source_line;
-    }
-
+  initialize_defaults (&default_symtab, &default_line);
+  
   /* See if arg is *PC */
 
   if (**argptr == '*')
-    {
-      (*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;
-    }
-
-  /* '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)
-    has_if = 1;
-  /* Temporarily zap out "if (condition)" to not
-   * confuse the parenthesis-checking code below.
-   * This is undone below. Do not change ii!!
-   */
-  if (has_if)
-    {
-      *ii = '\0';
-    }
+    return decode_indirect (argptr);
 
   /* Set various flags.
-   * 'has_parens' is important for overload checking, where
+   * 'paren_pointer' is important for overload checking, where
    * we allow things like: 
    *     (gdb) break c::f(int)
    */
 
-  /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+  set_flags (*argptr, &is_quoted, &paren_pointer);
 
-  is_quoted = (**argptr
-              && strchr (get_gdb_completer_quote_characters (),
-                         **argptr) != NULL);
+  /* Check to see if it's a multipart linespec (with colons or
+     periods).  */
 
-  has_parens = ((pp = strchr (*argptr, '(')) != NULL
-               && (pp = strrchr (pp, ')')) != NULL);
+  /* Locate the end of the first half of the linespec.  */
 
-  /* Now that we're safely past the has_parens check,
-   * put back " if (condition)" so outer layers can see it 
-   */
-  if (has_if)
-    *ii = ' ';
+  p = locate_first_half (argptr, &is_quote_enclosed);
 
-  /* 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
-     for the second half.
-
-     Don't count commas that appear in argument lists of overloaded
-     functions, or in quoted strings.  It's stupid to go to this much
-     trouble when the rest of the function is such an obvious roach hotel.  */
-  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!!
-   */
-  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 <> */
-
-  s = NULL;
-  p = *argptr;
-  if (p[0] == '"')
-    {
-      is_quote_enclosed = 1;
-      p++;
-    }
-  else
-    is_quote_enclosed = 0;
-  for (; *p; p++)
-    {
-      if (p[0] == '<')
-       {
-         char *temp_end = find_template_name_end (p);
-         if (!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 */
-      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. */
-       {
-         /* Find the *last* '.', since the others are package qualifiers. */
-         for (p1 = p; *p1; p1++)
-           {
-             if (*p1 == '.')
-               p = p1;
-           }
-         break;
-       }
-    }
-  while (p[0] == ' ' || p[0] == '\t')
-    p++;
+  /* Does it look like there actually were two parts?  */
 
-  /* if the closing double quote was left at the end, remove it */
-  if (is_quote_enclosed)
+  if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
     {
-      char *closing_quote = strchr (p, '"');
-      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 
-   */
-  if (has_comma)
-    *ii = ',';
-
-  if ((p[0] == ':' || p[0] == '.') && !has_parens)
-    {
-      /*  C++ */
-      /*  ... or Java */
       if (is_quoted)
        *argptr = *argptr + 1;
-      if (p[0] == '.' || p[1] == ':')
-       {
-         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)
-           {
-             /* 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);
-
-             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)
-   {
-   char *opname;
-   char *tmp = alloca (q1 - q + 1);
-   memcpy (tmp, q, q1 - q);
-   tmp[q1 - q] = '\0';
-   opname = cplus_mangle_opname (tmp, DMGL_ANSI);
-   if (opname == NULL)
-   {
-   error_begin ();
-   printf_filtered ("no mangling for \"%s\"\n", tmp);
-   cplusplus_hint (saved_arg);
-   return_to_top_level (RETURN_ERROR);
-   }
-   copy = (char*) alloca (3 + strlen(opname));
-   sprintf (copy, "__%s", opname);
-   p = q1;
-   }
-   else
- */
-                 {
-                   copy = (char *) alloca (p - *argptr + 1);
-                   memcpy (copy, *argptr, p - *argptr);
-                   copy[p - *argptr] = '\0';
-                   if (p != *argptr
-                       && copy[p - *argptr - 1]
-                       && strchr (get_gdb_completer_quote_characters (),
-                                  copy[p - *argptr - 1]) != NULL)
-                     copy[p - *argptr - 1] = '\0';
-                 }
-
-                 /* no line number may be specified */
-                 while (*p == ' ' || *p == '\t')
-                   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 (OPNAME_PREFIX_P (copy))
-                       {
-                         tmp = (char *) alloca (strlen (copy + 3) + 9);
-                         strcpy (tmp, "operator ");
-                         strcat (tmp, copy + 3);
-                       }
-                     else
-                       tmp = copy;
-                     error_begin ();
-                     if (tmp[0] == '~')
-                       printf_filtered
-                         ("the class `%s' does not have destructor defined\n",
-                          SYMBOL_SOURCE_NAME (sym_class));
-                     else
-                       printf_filtered
-                         ("the class %s does not have any method named %s\n",
-                          SYMBOL_SOURCE_NAME (sym_class), tmp);
-                     cplusplus_hint (saved_arg);
-                     return_to_top_level (RETURN_ERROR);
-                   }
-               }
-
-             /* 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++;
-               }
-
-             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;
-         /* Prepare to jump: restore the " if (condition)" so outer layers see it */
-         /* Symbol was found --> jump to normal symbol processing.
-            Code following "symbol_found" expects "copy" to have the
-            symbol name, "sym" to have the symbol pointer, "s" to be
-            a specified file's symtab, and sym_symtab to be the symbol's
-            symtab. */
-         /* By jumping there we avoid falling through the FILE:LINE and
-            FILE:FUNC processing stuff below */
-         if (sym)
-           goto symbol_found;
-
-         /* Couldn't find any interpretation as classes/namespaces, so give up */
-         error_begin ();
-         /* The quotes are important if copy is empty.  */
-         printf_filtered
-           ("Can't find member of namespace, class, struct, or union named \"%s\"\n", copy);
-         cplusplus_hint (saved_arg);
-         return_to_top_level (RETURN_ERROR);
-       }
-      /*  end of C++  */
+      
+      /* Is it a C++ or Java compound data structure?  */
 
+      if (p[0] == '.' || p[1] == ':')
+       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);
-      if ((**argptr == '"') && is_quote_enclosed)
-       {
-         memcpy (copy, *argptr + 1, p - *argptr - 1);
-         /* It may have the ending quote right after the file name */
-         if (copy[p - *argptr - 2] == '"')
-           copy[p - *argptr - 2] = 0;
-         else
-           copy[p - *argptr - 1] = 0;
-       }
-      else
-       {
-         memcpy (copy, *argptr, p - *argptr);
-         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;
+      s = symtab_from_filename (argptr, p, is_quote_enclosed);
     }
 #if 0
   /* No one really seems to know why this was added. It certainly
@@ -977,12 +632,9 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
       if (sym)
        {
-         /* Yes, we have a symbol; jump to symbol processing */
-         /* Code after symbol_found expects S, SYM_SYMTAB, SYM, 
-            and COPY to be set correctly */
          *argptr = (*p == '\'') ? p + 1 : p;
-         s = (struct symtab *) 0;
-         goto symbol_found;
+         return symbol_found (funfirstline, canonical, copy, sym,
+                              NULL, sym_symtab);
        }
       /* Otherwise fall out from here and go to file/line spec
          processing, etc. */
@@ -1015,13 +667,14 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       /* 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
-         select_source_symtab calls us with such an argument  */
+        set_default_source_symtab_and_line uses
+         select_source_symtab that calls us with such an argument  */
 
       if (s == 0 && default_symtab == 0)
        {
-         select_source_symtab (0);
-         default_symtab = current_source_symtab;
-         default_line = current_source_line;
+         /* Make sure we have at least a default source file. */
+         set_default_source_symtab_and_line ();
+         initialize_defaults (&default_symtab, &default_line);
        }
 
       if (**argptr == '+')
@@ -1083,18 +736,15 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       if (p[-1] != '\'')
        error ("Unmatched single quote.");
     }
-  else if (has_parens)
+  else if (paren_pointer != NULL)
     {
-      p = pp + 1;
+      p = paren_pointer + 1;
     }
   else
     {
       p = skip_quoted (*argptr);
     }
 
-  if (is_quote_enclosed && **argptr == '"')
-    (*argptr)++;
-
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
   copy[p - *argptr] = '\0';
@@ -1116,7 +766,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   if (*copy == '$')
     {
-      value_ptr valx;
+      struct value *valx;
       int index = 0;
       int need_canonical = 0;
 
@@ -1140,19 +790,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
          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.
-            Code following "symbol_found" expects "copy" to have the
-            symbol name, "sym" to have the symbol pointer, "s" to be
-            a specified file's symtab, and sym_symtab to be the symbol's
-            symtab. */
+         /* Symbol was found --> jump to normal symbol processing.  */
          if (sym)
-           goto symbol_found;
+           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, 0, 0);
+         msymbol = lookup_minimal_symbol (copy, NULL, NULL);
          /* Min symbol was found --> jump to minsym processing. */
          if (msymbol)
-           goto minimal_symbol_found;
+           return minsym_found (funfirstline, msymbol);
 
          /* Not a user variable or function -- must be convenience variable */
          need_canonical = (s == 0) ? 1 : 0;
@@ -1182,87 +829,600 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   sym = lookup_symbol (copy,
                       (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
-                       : get_selected_block ()),
+                       : get_selected_block (0)),
                       VAR_NAMESPACE, 0, &sym_symtab);
 
-symbol_found:                  /* We also jump here from inside the C++ class/namespace 
-                                  code on finding a symbol of the form "A::B::C" */
-
   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 */
+}
+
+\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)
     {
-      if (SYMBOL_CLASS (sym) == LOC_BLOCK)
-       {
-         /* Arg is the name of a function */
-         values.sals = (struct symtab_and_line *)
-           xmalloc (sizeof (struct symtab_and_line));
-         values.sals[0] = find_function_start_sal (sym, funfirstline);
-         values.nelts = 1;
+      /* 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;
+    }
+}
 
-         /* Don't use the SYMBOL_LINE; if used at all it points to
-            the line containing the parameters or thereabouts, not
-            the first line of code.  */
+static void
+set_flags (char *arg, int *is_quoted, char **paren_pointer)
+{
+  char *ii;
+  int has_if = 0;
 
-         /* We might need a canonical line spec if it is a static
-            function.  */
-         if (s == 0)
+  /* 'has_if' is for the syntax:
+   *     (gdb) break foo if (a==b)
+   */
+  if ((ii = strstr (arg, " if ")) != NULL ||
+      (ii = strstr (arg, "\tif ")) != NULL ||
+      (ii = strstr (arg, " if\t")) != NULL ||
+      (ii = strstr (arg, "\tif\t")) != NULL ||
+      (ii = strstr (arg, " if(")) != NULL ||
+      (ii = strstr (arg, "\tif( ")) != NULL)
+    has_if = 1;
+  /* Temporarily zap out "if (condition)" to not
+   * confuse the parenthesis-checking code below.
+   * This is undone below. Do not change ii!!
+   */
+  if (has_if)
+    {
+      *ii = '\0';
+    }
+
+  *is_quoted = (*arg
+               && strchr (get_gdb_completer_quote_characters (),
+                          *arg) != NULL);
+
+  *paren_pointer = strchr (arg, '(');
+  if (*paren_pointer != NULL)
+    *paren_pointer = strrchr (*paren_pointer, ')');
+
+  /* Now that we're safely past the paren_pointer check,
+   * put back " if (condition)" so outer layers can see it 
+   */
+  if (has_if)
+    *ii = ' ';
+}
+
+\f
+
+/* Decode arg of the form *PC.  */
+
+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
+     for the second half.
+
+     Don't count commas that appear in argument lists of overloaded
+     functions, or in quoted strings.  It's stupid to go to this much
+     trouble when the rest of the function is such an obvious roach hotel.  */
+  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!!
+   */
+  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 <> */
+
+  p = *argptr;
+  if (p[0] == '"')
+    {
+      *is_quote_enclosed = 1;
+      (*argptr)++;
+      p++;
+    }
+  else
+    *is_quote_enclosed = 0;
+  for (; *p; p++)
+    {
+      if (p[0] == '<')
+       {
+         char *temp_end = find_template_name_end (p);
+         if (!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 */
+      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. */
+       {
+         /* Find the *last* '.', since the others are package qualifiers. */
+         for (p1 = p; *p1; p1++)
            {
-             struct blockvector *bv = BLOCKVECTOR (sym_symtab);
-             struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-             if (lookup_block_symbol (b, copy, VAR_NAMESPACE) != NULL)
-               build_canonical_line_spec (values.sals, copy, canonical);
+             if (*p1 == '.')
+               p = p1;
            }
-         return values;
+         break;
        }
-      else
+    }
+  while (p[0] == ' ' || p[0] == '\t')
+    p++;
+
+  /* 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 
+   */
+  if (has_comma)
+    *ii = ',';
+
+  return p;
+}
+
+\f
+
+/* 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 *p1, *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;
+  int i1;
+  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)
+    {
+      /* 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);
+
+      if (sym_class &&
+         (t = check_typedef (SYMBOL_TYPE (sym_class)),
+          (TYPE_CODE (t) == TYPE_CODE_STRUCT
+           || TYPE_CODE (t) == TYPE_CODE_UNION)))
        {
-         if (funfirstline)
-           error ("\"%s\" is not a function", copy);
-         else if (SYMBOL_LINE (sym) != 0)
+         /* 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)
+   {
+   char *opname;
+   char *tmp = alloca (q1 - q + 1);
+   memcpy (tmp, q, q1 - q);
+   tmp[q1 - q] = '\0';
+   opname = cplus_mangle_opname (tmp, DMGL_ANSI);
+   if (opname == NULL)
+   {
+   cplusplus_error (saved_arg, "no mangling for \"%s\"\n", tmp);
+   }
+   copy = (char*) alloca (3 + strlen(opname));
+   sprintf (copy, "__%s", opname);
+   p = q1;
+   }
+   else
+ */
+         {
+           copy = (char *) alloca (p - *argptr + 1);
+           memcpy (copy, *argptr, p - *argptr);
+           copy[p - *argptr] = '\0';
+           if (p != *argptr
+               && copy[p - *argptr - 1]
+               && strchr (get_gdb_completer_quote_characters (),
+                          copy[p - *argptr - 1]) != NULL)
+             copy[p - *argptr - 1] = '\0';
+         }
+
+         /* no line number may be specified */
+         while (*p == ' ' || *p == '\t')
+           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)
            {
-             /* We know its line number.  */
-             values.sals = (struct symtab_and_line *)
-               xmalloc (sizeof (struct symtab_and_line));
-             values.nelts = 1;
-             memset (&values.sals[0], 0, sizeof (values.sals[0]));
-             values.sals[0].symtab = sym_symtab;
-             values.sals[0].line = SYMBOL_LINE (sym);
+             /* 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
-           /* This can happen if it is compiled with a compiler which doesn't
-              put out line numbers for variables.  */
-           /* FIXME: Shouldn't we just set .line and .symtab to zero
-              and return?  For example, "info line foo" could print
-              the address.  */
-           error ("Line number not known for symbol \"%s\"", copy);
+           p++;
        }
+
+      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);
+  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);
+}
+
+\f
+
+/* Return the symtab associated to the filename given by the substring
+   of *ARGPTR ending at P, and advance ARGPTR past that filename.  */
+
+static struct symtab *
+symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+{
+  char *p1;
+  char *copy;
+  struct symtab *s;
+  
+  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);
     }
 
-  msymbol = lookup_minimal_symbol (copy, NULL, NULL);
+  /* Discard the file name from the arg.  */
+  p = p1 + 1;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  return s;
+}
 
-minimal_symbol_found:          /* We also jump here from the case for variables
-                                  that begin with '$' */
 
-  if (msymbol != NULL)
+\f
+
+/* Now come some functions that are called from multiple places within
+   decode_line_1.  */
+
+/* We've found a symbol SYM to associate with our linespec; build a
+   corresponding struct symtabs_and_lines.  */
+
+static struct symtabs_and_lines
+symbol_found (int funfirstline, char ***canonical, char *copy,
+             struct symbol *sym, struct symtab *s,
+             struct symtab *sym_symtab)
+{
+  struct symtabs_and_lines values;
+  
+  if (SYMBOL_CLASS (sym) == LOC_BLOCK)
     {
+      /* Arg is the name of a function */
       values.sals = (struct symtab_and_line *)
        xmalloc (sizeof (struct symtab_and_line));
-      values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
-                                         (struct sec *) 0, 0);
-      values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
-      if (funfirstline)
+      values.sals[0] = find_function_start_sal (sym, funfirstline);
+      values.nelts = 1;
+
+      /* Don't use the SYMBOL_LINE; if used at all it points to
+        the line containing the parameters or thereabouts, not
+        the first line of code.  */
+
+      /* We might need a canonical line spec if it is a static
+        function.  */
+      if (s == 0)
        {
-         values.sals[0].pc += FUNCTION_START_OFFSET;
-         values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
+         struct blockvector *bv = BLOCKVECTOR (sym_symtab);
+         struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+         if (lookup_block_symbol (b, copy, NULL, VAR_NAMESPACE) != NULL)
+           build_canonical_line_spec (values.sals, copy, canonical);
        }
-      values.nelts = 1;
       return values;
     }
+  else
+    {
+      if (funfirstline)
+       error ("\"%s\" is not a function", copy);
+      else if (SYMBOL_LINE (sym) != 0)
+       {
+         /* We know its line number.  */
+         values.sals = (struct symtab_and_line *)
+           xmalloc (sizeof (struct symtab_and_line));
+         values.nelts = 1;
+         memset (&values.sals[0], 0, sizeof (values.sals[0]));
+         values.sals[0].symtab = sym_symtab;
+         values.sals[0].line = SYMBOL_LINE (sym);
+         return values;
+       }
+      else
+       /* This can happen if it is compiled with a compiler which doesn't
+          put out line numbers for variables.  */
+       /* FIXME: Shouldn't we just set .line and .symtab to zero
+          and return?  For example, "info line foo" could print
+          the address.  */
+       error ("Line number not known for symbol \"%s\"", copy);
+    }
+}
 
-  if (!have_full_symbols () &&
-      !have_partial_symbols () && !have_minimal_symbols ())
-    error ("No symbol table is loaded.  Use the \"file\" command.");
+/* We've found a minimal symbol MSYMBOL to associate with our
+   linespec; build a corresponding struct symtabs_and_lines.  */
 
-  error ("Function \"%s\" not defined.", copy);
-  return values;               /* for lint */
+static struct symtabs_and_lines
+minsym_found (int funfirstline, struct minimal_symbol *msymbol)
+{
+  struct symtabs_and_lines values;
+
+  values.sals = (struct symtab_and_line *)
+    xmalloc (sizeof (struct symtab_and_line));
+  values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
+                                     (struct sec *) 0, 0);
+  values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
+  if (funfirstline)
+    {
+      values.sals[0].pc += FUNCTION_START_OFFSET;
+      values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
+    }
+  values.nelts = 1;
+  return values;
 }
This page took 0.040253 seconds and 4 git commands to generate.