summaryrefslogtreecommitdiff
path: root/gdb/linespec.c
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2002-12-05 22:25:49 +0000
committerDavid Carlton <carlton@bactrian.org>2002-12-05 22:25:49 +0000
commit0a63f66c100b9007f3f36a62e1e3ae2f921ff8f5 (patch)
tree29a545d0d27e99aa327ea73990f456dd719c602b /gdb/linespec.c
parent250e2b60807934009a2a29822c4c6f352e65a9e5 (diff)
downloadgdb-0a63f66c100b9007f3f36a62e1e3ae2f921ff8f5.tar.gz
2002-12-05 David Carlton <carlton@math.stanford.edu>
* linespec.c (decode_compound): New function. (decode_line_1): Move code into decode_compound.
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r--gdb/linespec.c530
1 files changed, 284 insertions, 246 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 8b096d35071..5f90985cb8e 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -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);
@@ -80,7 +88,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;
@@ -532,10 +540,7 @@ 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
+ char *q;
register struct symtab *s = NULL;
register struct symbol *sym;
@@ -544,8 +549,6 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
register struct minimal_symbol *msymbol;
char *copy;
- struct symbol *sym_class;
- int i1;
/* This is NULL if there are no parens in *ARGPTR, or a pointer to
the closing parenthesis if there are parens. */
char *paren_pointer;
@@ -554,10 +557,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,237 +589,13 @@ 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++ */
-
+ /* C++ */
+ /* ... or Java */
+ return decode_compound (argptr, funfirstline, canonical,
+ saved_arg, p);
/* Extract the file name. */
p1 = p;
@@ -1094,13 +870,29 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
-/* 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. */
@@ -1282,6 +1074,252 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
+/* 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);
+}
+
+
+
/* Now come some functions that are called from multiple places within
decode_line_1. */