*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / linespec.c
index 8b096d350718dd7e6efa0e704388f2b52dba70b7..0386a7511a96acb3d62cf0ba789c0d090ffd0277 100644 (file)
@@ -48,7 +48,15 @@ static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
 
-static void cplusplus_error (const char *name, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
+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);
 
@@ -62,6 +70,9 @@ 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,
@@ -80,7 +91,7 @@ symtabs_and_lines minsym_found (int funfirstline,
    single quoted demangled C++ symbols as part of the completion
    error.  */
 
-static void
+static NORETURN void
 cplusplus_error (const char *name, const char *fmt, ...)
 {
   struct ui_file *tmp_stream;
@@ -531,21 +542,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 {
   struct symtabs_and_lines values;
   struct symtab_and_line val;
-  register char *p, *p1;
-  char *q, *p2;
-#if 0
-  char *q1;
-#endif
-  register struct symtab *s = NULL;
+  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 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;
@@ -554,10 +560,7 @@ 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;
-  struct symbol **sym_arr;
-  struct type *t;
   char *saved_arg = *argptr;
-  extern char *gdb_completer_quote_characters;
 
   init_sal (&val);             /* initialize to zeroes */
 
@@ -589,266 +592,19 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
     {
-      /*  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)
-   {
-   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)
-                   {
-                     /* There is exactly one field with that name.  */
-                     sym = sym_arr[0];
-
-                     if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
-                       {
-                         values.sals = (struct symtab_and_line *)
-                           xmalloc (sizeof (struct symtab_and_line));
-                         values.nelts = 1;
-                         values.sals[0] = find_function_start_sal (sym,
-                                                             funfirstline);
-                       }
-                     else
-                       {
-                         values.nelts = 0;
-                       }
-                     return values;
-                   }
-                 if (i1 > 0)
-                   {
-                     /* There is more than one field with that name
-                        (overloaded).  Ask the user which one to use.  */
-                     return decode_line_2 (sym_arr, i1, funfirstline, canonical);
-                   }
-                 else
-                   {
-                     char *tmp;
-
-                     if (is_operator_name (copy))
-                       {
-                         tmp = (char *) alloca (strlen (copy + 3) + 9);
-                         strcpy (tmp, "operator ");
-                         strcat (tmp, copy + 3);
-                       }
-                     else
-                       tmp = copy;
-                     if (tmp[0] == '~')
-                       cplusplus_error (saved_arg,
-                                        "the class `%s' does not have destructor defined\n",
-                                        SYMBOL_SOURCE_NAME (sym_class));
-                     else
-                       cplusplus_error (saved_arg,
-                                        "the class %s does not have any method named %s\n",
-                                        SYMBOL_SOURCE_NAME (sym_class), tmp);
-                   }
-               }
-
-             /* Move pointer up to next possible class/namespace token */
-             p = p2 + 1;       /* restart with old value +1 */
-             /* Move pointer ahead to next double-colon */
-             while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
-               {
-                 if (p[0] == '<')
-                   {
-                     temp_end = find_template_name_end (p);
-                     if (!temp_end)
-                       error ("malformed template specification in command");
-                     p = temp_end;
-                   }
-                 else if ((p[0] == ':') && (p[1] == ':'))
-                   break;      /* found double-colon */
-                 else
-                   p++;
-               }
-
-             if (*p != ':')
-               break;          /* out of the while (1) */
-
-             p2 = p;           /* save restart for next time around */
-             *argptr = saved_arg2;     /* restore argptr */
-           }                   /* while (1) */
-
-         /* Last chance attempt -- check entire name as a symbol */
-         /* Use "copy" in preparation for jumping out of this block,
-            to be consistent with usage following the jump target */
-         copy = (char *) alloca (p - saved_arg2 + 1);
-         memcpy (copy, saved_arg2, p - saved_arg2);
-         /* Note: if is_quoted should be true, we snuff out quote here anyway */
-         copy[p - saved_arg2] = '\000';
-         /* Set argptr to skip over the name */
-         *argptr = (*p == '\'') ? p + 1 : p;
-         /* Look up entire name */
-         sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
-         s = (struct symtab *) 0;
-         if (sym)
-           return symbol_found (funfirstline, canonical, copy, sym,
-                                NULL, sym_symtab);
-
-         /* Couldn't find any interpretation as classes/namespaces, so give up */
-         /* The quotes are important if copy is empty.  */
-         cplusplus_error (saved_arg,
-                          "Can't find member of namespace, class, struct, or union named \"%s\"\n",
-                          copy);
-       }
-      /*  end of C++  */
-
+      
+      /* Is it a C++ or Java compound data structure?  */
 
-      /* 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;
+      if (p[0] == '.' || p[1] == ':')
+       return decode_compound (argptr, funfirstline, canonical,
+                               saved_arg, p);
 
-      /* 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
@@ -1094,13 +850,29 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
 \f
 
-/* Now, still more helper functions.  */
-
-/* NOTE: carlton/2002-11-07: Some of these have non-obvious side
-   effects.  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.)  */
+/* 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.  */
@@ -1280,6 +1052,296 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
   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)))
+       {
+         /* 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)
+           {
+             /* There is exactly one field with that name.  */
+             sym = sym_arr[0];
+
+             if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+               {
+                 values.sals = (struct symtab_and_line *)
+                   xmalloc (sizeof (struct symtab_and_line));
+                 values.nelts = 1;
+                 values.sals[0] = find_function_start_sal (sym,
+                                                           funfirstline);
+               }
+             else
+               {
+                 values.nelts = 0;
+               }
+             return values;
+           }
+         if (i1 > 0)
+           {
+             /* There is more than one field with that name
+                (overloaded).  Ask the user which one to use.  */
+             return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+           }
+         else
+           {
+             char *tmp;
+
+             if (is_operator_name (copy))
+               {
+                 tmp = (char *) alloca (strlen (copy + 3) + 9);
+                 strcpy (tmp, "operator ");
+                 strcat (tmp, copy + 3);
+               }
+             else
+               tmp = copy;
+             if (tmp[0] == '~')
+               cplusplus_error (saved_arg,
+                                "the class `%s' does not have destructor defined\n",
+                                SYMBOL_SOURCE_NAME (sym_class));
+             else
+               cplusplus_error (saved_arg,
+                                "the class %s does not have any method named %s\n",
+                                SYMBOL_SOURCE_NAME (sym_class), tmp);
+           }
+       }
+
+      /* Move pointer up to next possible class/namespace token */
+      p = p2 + 1;      /* restart with old value +1 */
+      /* Move pointer ahead to next double-colon */
+      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
+       {
+         if (p[0] == '<')
+           {
+             temp_end = find_template_name_end (p);
+             if (!temp_end)
+               error ("malformed template specification in command");
+             p = temp_end;
+           }
+         else if ((p[0] == ':') && (p[1] == ':'))
+           break;      /* found double-colon */
+         else
+           p++;
+       }
+
+      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);
+    }
+
+  /* Discard the file name from the arg.  */
+  p = p1 + 1;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  return s;
+}
+
+
 \f
 
 /* Now come some functions that are called from multiple places within
This page took 0.030358 seconds and 4 git commands to generate.