From 614b3b14dc988679a7e9fa8eb8e5b4a37b71b393 Mon Sep 17 00:00:00 2001 From: David Carlton Date: Thu, 5 Dec 2002 22:25:49 +0000 Subject: [PATCH] 2002-12-05 David Carlton * linespec.c (decode_compound): New function. (decode_line_1): Move code into decode_compound. --- gdb/ChangeLog | 5 + gdb/linespec.c | 530 ++++++++++++++++++++++++++----------------------- 2 files changed, 289 insertions(+), 246 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bea0c1fd021..c6a4850ff00 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2002-12-05 David Carlton + + * linespec.c (decode_compound): New function. + (decode_line_1): Move code into decode_compound. + 2002-12-05 David Carlton * symtab.c (lookup_symbol_aux_local): Add 'static_block' 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. */ -- 2.30.2