From f88e9fd3159d3b7786ccc1bf831d8e255c1df174 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Mon, 22 Oct 2007 14:37:36 +0000 Subject: [PATCH] * cp-support.c: Include "safe-ctype.h". (cp_already_canonical): New function. (cp_canonicalize_string): Use it. Return NULL for already canonical strings. (mangled_name_to_comp): Update call to cp_demangled_name_to_comp. (cp_func_name, remove_params): Likewise. (cp_find_first_component_aux): Use ISSPACE. * cp-support.h (cp_demangled_name_to_comp): Correct comment. Remove MEMORY_P argument. * cp-name-parser.y (ALLOC_CHUNK): Define. (struct demangle_info): Add PREV and NEXT. Increase the size of COMPS. (d_grab): Convert to a function. (allocate_info): Rewrite. (cp_demangled_name_to_comp): Remove MEMORY argument. Do not use strlen. Update call to allocate_info. Do not free it on failure. (main): Update calls to cp_demangled_name_to_comp. * Makefile.in (cp-support.o): Update. --- gdb/ChangeLog | 21 +++++++++++++ gdb/Makefile.in | 2 +- gdb/cp-name-parser.y | 84 +++++++++++++++++++++++++++++++++------------------- gdb/cp-support.c | 70 ++++++++++++++++++++++++++++++------------- gdb/cp-support.h | 4 +-- 5 files changed, 127 insertions(+), 54 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d728e9f..c66a8c7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2007-10-22 Daniel Jacobowitz + + * cp-support.c: Include "safe-ctype.h". + (cp_already_canonical): New function. + (cp_canonicalize_string): Use it. Return NULL for already canonical + strings. + (mangled_name_to_comp): Update call to cp_demangled_name_to_comp. + (cp_func_name, remove_params): Likewise. + (cp_find_first_component_aux): Use ISSPACE. + * cp-support.h (cp_demangled_name_to_comp): Correct comment. Remove + MEMORY_P argument. + * cp-name-parser.y (ALLOC_CHUNK): Define. + (struct demangle_info): Add PREV and NEXT. Increase the size of + COMPS. + (d_grab): Convert to a function. + (allocate_info): Rewrite. + (cp_demangled_name_to_comp): Remove MEMORY argument. Do not use + strlen. Update call to allocate_info. Do not free it on failure. + (main): Update calls to cp_demangled_name_to_comp. + * Makefile.in (cp-support.o): Update. + 2007-10-22 Markus Deuling * std-regs.c (value_of_builtin_frame_fp_reg) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 722d361..05b1deb 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1931,7 +1931,7 @@ cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \ cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \ $(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \ $(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h) \ - $(gdbtypes_h) + $(gdbtypes_h) $(safe_ctype_h) cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \ $(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \ $(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \ diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index 0916e86..0eab4f2 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -54,13 +54,38 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg; /* The components built by the parser are allocated ahead of time, and cached in this structure. */ +#define ALLOC_CHUNK 100 + struct demangle_info { int used; - struct demangle_component comps[1]; + struct demangle_info *prev, *next; + struct demangle_component comps[ALLOC_CHUNK]; }; static struct demangle_info *demangle_info; -#define d_grab() (&demangle_info->comps[demangle_info->used++]) + +static struct demangle_component * +d_grab (void) +{ + struct demangle_info *more; + + if (demangle_info->used >= ALLOC_CHUNK) + { + if (demangle_info->next == NULL) + { + more = malloc (sizeof (struct demangle_info)); + more->prev = demangle_info; + more->next = NULL; + demangle_info->next = more; + } + else + more = demangle_info->next; + + more->used = 0; + demangle_info = more; + } + return &demangle_info->comps[demangle_info->used++]; +} /* The parse tree created by the parser is stored here after a successful parse. */ @@ -1923,19 +1948,24 @@ yyerror (char *msg) global_errmsg = msg ? msg : "parse error"; } -/* Allocate all the components we'll need to build a tree. We generally - allocate too many components, but the extra memory usage doesn't hurt - because the trees are temporary. If we start keeping the trees for - a longer lifetime we'll need to be cleverer. */ -static struct demangle_info * -allocate_info (int comps) +/* Allocate a chunk of the components we'll need to build a tree. We + generally allocate too many components, but the extra memory usage + doesn't hurt because the trees are temporary and the storage is + reused. More may be allocated later, by d_grab. */ +static void +allocate_info (void) { - struct demangle_info *ret; + if (demangle_info == NULL) + { + demangle_info = malloc (sizeof (struct demangle_info)); + demangle_info->prev = NULL; + demangle_info->next = NULL; + } + else + while (demangle_info->prev) + demangle_info = demangle_info->prev; - ret = malloc (sizeof (struct demangle_info) - + sizeof (struct demangle_component) * (comps - 1)); - ret->used = 0; - return ret; + demangle_info->used = 0; } /* Convert RESULT to a string. The return value is allocated @@ -1975,26 +2005,23 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len) return (buf); } -/* Convert a demangled name to a demangle_component tree. *MEMORY is set to the - block of used memory that should be freed when finished with the - tree. On error, NULL is returned, and an error message will be - set in *ERRMSG (which does not need to be freed). */ +/* Convert a demangled name to a demangle_component tree. On success, + the root of the new tree is returned; it is valid until the next + call to this function and should not be freed. On error, NULL is + returned, and an error message will be set in *ERRMSG (which does + not need to be freed). */ struct demangle_component * -cp_demangled_name_to_comp (const char *demangled_name, void **memory, - const char **errmsg) +cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg) { static char errbuf[60]; struct demangle_component *result; - int len = strlen (demangled_name); - - len = len + len / 8; prev_lexptr = lexptr = demangled_name; error_lexptr = NULL; global_errmsg = NULL; - demangle_info = allocate_info (len); + allocate_info (); if (yyparse ()) { @@ -2005,11 +2032,9 @@ cp_demangled_name_to_comp (const char *demangled_name, void **memory, strcat (errbuf, "'"); *errmsg = errbuf; } - free (demangle_info); return NULL; } - *memory = demangle_info; result = global_result; global_result = NULL; @@ -2063,11 +2088,10 @@ trim_chars (char *lexptr, char **extra_chars) int main (int argc, char **argv) { - char *str2, *extra_chars, c; + char *str2, *extra_chars = "", c; char buf[65536]; int arg; const char *errmsg; - void *memory; struct demangle_component *result; arg = 1; @@ -2094,7 +2118,7 @@ main (int argc, char **argv) printf ("%s\n", buf); continue; } - result = cp_demangled_name_to_comp (str2, &memory, &errmsg); + result = cp_demangled_name_to_comp (str2, &errmsg); if (result == NULL) { fputs (errmsg, stderr); @@ -2103,7 +2127,6 @@ main (int argc, char **argv) } cp_print (result); - free (memory); free (str2); if (c) @@ -2115,7 +2138,7 @@ main (int argc, char **argv) } else { - result = cp_demangled_name_to_comp (argv[arg], &memory, &errmsg); + result = cp_demangled_name_to_comp (argv[arg], &errmsg); if (result == NULL) { fputs (errmsg, stderr); @@ -2124,7 +2147,6 @@ main (int argc, char **argv) } cp_print (result); putchar ('\n'); - free (memory); } return 0; } diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 2d8c3c7..34ddde3 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -19,7 +19,6 @@ along with this program. If not, see . */ #include "defs.h" -#include #include "cp-support.h" #include "gdb_string.h" #include "demangle.h" @@ -33,6 +32,8 @@ #include "complaints.h" #include "gdbtypes.h" +#include "safe-ctype.h" + #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right @@ -68,30 +69,63 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL; static void maint_cplus_command (char *arg, int from_tty); static void first_component_command (char *arg, int from_tty); -/* Return the canonicalized form of STRING, or NULL if STRING can not be - parsed. The return value is allocated via xmalloc. +/* Return 1 if STRING is clearly already in canonical form. This + function is conservative; things which it does not recognize are + assumed to be non-canonical, and the parser will sort them out + afterwards. This speeds up the critical path for alphanumeric + identifiers. */ + +static int +cp_already_canonical (const char *string) +{ + /* Identifier start character [a-zA-Z_]. */ + if (!ISIDST (string[0])) + return 0; + + /* These are the only two identifiers which canonicalize to other + than themselves or an error: unsigned -> unsigned int and + signed -> int. */ + if (string[0] == 'u' && strcmp (&string[1], "nsigned") == 0) + return 0; + else if (string[0] == 's' && strcmp (&string[1], "igned") == 0) + return 0; + + /* Identifier character [a-zA-Z0-9_]. */ + while (ISIDNUM (string[1])) + string++; + + if (string[1] == '\0') + return 1; + else + return 0; +} - drow/2005-03-07: Should we also return NULL for things that trivially do - not require any change? e.g. simple identifiers. This could be more - efficient. */ +/* Parse STRING and convert it to canonical form. If parsing fails, + or if STRING is already canonical, return NULL. Otherwise return + the canonical form. The return value is allocated via xmalloc. */ char * cp_canonicalize_string (const char *string) { - void *storage; struct demangle_component *ret_comp; + unsigned int estimated_len; char *ret; - int len = strlen (string); - len = len + len / 8; + if (cp_already_canonical (string)) + return NULL; - ret_comp = cp_demangled_name_to_comp (string, &storage, NULL); + ret_comp = cp_demangled_name_to_comp (string, NULL); if (ret_comp == NULL) return NULL; - ret = cp_comp_to_string (ret_comp, len); + estimated_len = strlen (string) * 2; + ret = cp_comp_to_string (ret_comp, estimated_len); - xfree (storage); + if (strcmp (string, ret) == 0) + { + xfree (ret); + return NULL; + } return ret; } @@ -128,7 +162,7 @@ mangled_name_to_comp (const char *mangled_name, int options, return NULL; /* If we could demangle the name, parse it to build the component tree. */ - ret = cp_demangled_name_to_comp (demangled_name, memory, NULL); + ret = cp_demangled_name_to_comp (demangled_name, NULL); if (ret == NULL) { @@ -321,12 +355,11 @@ method_name_from_physname (const char *physname) char * cp_func_name (const char *full_name) { - void *storage; char *ret; struct demangle_component *ret_comp; int done; - ret_comp = cp_demangled_name_to_comp (full_name, &storage, NULL); + ret_comp = cp_demangled_name_to_comp (full_name, NULL); if (!ret_comp) return NULL; @@ -336,7 +369,6 @@ cp_func_name (const char *full_name) if (ret_comp != NULL) ret = cp_comp_to_string (ret_comp, 10); - xfree (storage); return ret; } @@ -349,13 +381,12 @@ remove_params (const char *demangled_name) { int done = 0; struct demangle_component *ret_comp; - void *storage; char *ret = NULL; if (demangled_name == NULL) return NULL; - ret_comp = cp_demangled_name_to_comp (demangled_name, &storage, NULL); + ret_comp = cp_demangled_name_to_comp (demangled_name, NULL); if (ret_comp == NULL) return NULL; @@ -381,7 +412,6 @@ remove_params (const char *demangled_name) if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME) ret = cp_comp_to_string (d_left (ret_comp), 10); - xfree (storage); return ret; } @@ -511,7 +541,7 @@ cp_find_first_component_aux (const char *name, int permissive) && strncmp (name + index, "operator", LENGTH_OF_OPERATOR) == 0) { index += LENGTH_OF_OPERATOR; - while (isspace(name[index])) + while (ISSPACE(name[index])) ++index; switch (name[index]) { diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 960fc6b..e85fa46 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -114,10 +114,10 @@ extern void cp_check_possible_namespace_symbols (const char *name, struct type *cp_lookup_transparent_type (const char *name); -/* Functions from cp-names.y. */ +/* Functions from cp-name-parser.y. */ extern struct demangle_component *cp_demangled_name_to_comp - (const char *demangled_name, void **memory_p, const char **errmsg); + (const char *demangled_name, const char **errmsg); extern char *cp_comp_to_string (struct demangle_component *result, int estimated_len); -- 2.7.4