2002-12-05 David Carlton <carlton@math.stanford.edu>

* linespec.c (decode_compound): New function.
	(decode_line_1): Move code into decode_compound.
This commit is contained in:
David Carlton 2002-12-05 22:25:49 +00:00
parent e4051eebcd
commit 614b3b14dc
2 changed files with 288 additions and 245 deletions

View File

@ -1,3 +1,8 @@
2002-12-05 David Carlton <carlton@math.stanford.edu>
* linespec.c (decode_compound): New function.
(decode_line_1): Move code into decode_compound.
2002-12-05 David Carlton <carlton@math.stanford.edu>
* symtab.c (lookup_symbol_aux_local): Add 'static_block'

View 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);
@ -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. */
/* Now, more helper functions for decode_line_1. Some conventions
that these functions follow:
/* 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.) */
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. */