X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-name-parser.y;h=c6a5c341bfc521065284735b9910b9a0ebd34bfd;hb=484b3c325d8182cd7b7da4ceeaedc238c7f80b5c;hp=e1641f4ce90b9f5afda85762aab93a80838d1301;hpb=5256a53bb3fbf514d1e9a1fed84ce57d7a94ecc8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index e1641f4ce9..c6a5c341bf 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -1,25 +1,23 @@ /* YACC parser for C++ names, for GDB. - Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2003-2016 Free Software Foundation, Inc. Parts of the lexer are based on c-exp.y from GDB. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ /* Note that malloc's and realloc's in this file are transformed to xmalloc and xrealloc respectively by the same sed command in the @@ -33,14 +31,10 @@ Boston, MA 02110-1301, USA. */ #include "defs.h" -#include -#include #include -#include - #include "safe-ctype.h" -#include "libiberty.h" #include "demangle.h" +#include "cp-support.h" /* Bison does not make it easy to create a parser without global state, unfortunately. Here are all the global variables used @@ -60,7 +54,7 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg; struct demangle_info { int used; - struct demangle_info *prev, *next; + struct demangle_info *next; struct demangle_component comps[ALLOC_CHUNK]; }; @@ -75,8 +69,7 @@ d_grab (void) { if (demangle_info->next == NULL) { - more = malloc (sizeof (struct demangle_info)); - more->prev = demangle_info; + more = XNEW (struct demangle_info); more->next = NULL; demangle_info->next = more; } @@ -171,6 +164,12 @@ static struct demangle_component *d_binary (const char *, #define yygindex cpname_yygindex #define yytable cpname_yytable #define yycheck cpname_yycheck +#define yyss cpname_yyss +#define yysslim cpname_yysslim +#define yyssp cpname_yyssp +#define yystacksize cpname_yystacksize +#define yyvs cpname_yyvs +#define yyvsp cpname_yyvsp int yyparse (void); static int yylex (void); @@ -189,7 +188,11 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs, struct demangle_component *rhs) { struct demangle_component *ret = d_grab (); - cplus_demangle_fill_component (ret, d_type, lhs, rhs); + int i; + + i = cplus_demangle_fill_component (ret, d_type, lhs, rhs); + gdb_assert (i); + return ret; } @@ -205,7 +208,11 @@ static struct demangle_component * make_operator (const char *name, int args) { struct demangle_component *ret = d_grab (); - cplus_demangle_fill_operator (ret, name, args); + int i; + + i = cplus_demangle_fill_operator (ret, name, args); + gdb_assert (i); + return ret; } @@ -213,7 +220,11 @@ static struct demangle_component * make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name) { struct demangle_component *ret = d_grab (); - cplus_demangle_fill_dtor (ret, kind, name); + int i; + + i = cplus_demangle_fill_dtor (ret, kind, name); + gdb_assert (i); + return ret; } @@ -221,7 +232,11 @@ static struct demangle_component * make_builtin_type (const char *name) { struct demangle_component *ret = d_grab (); - cplus_demangle_fill_builtin_type (ret, name); + int i; + + i = cplus_demangle_fill_builtin_type (ret, name); + gdb_assert (i); + return ret; } @@ -229,7 +244,11 @@ static struct demangle_component * make_name (const char *name, int len) { struct demangle_component *ret = d_grab (); - cplus_demangle_fill_name (ret, name, len); + int i; + + i = cplus_demangle_fill_name (ret, name, len); + gdb_assert (i); + return ret; } @@ -255,16 +274,12 @@ make_name (const char *name, int len) int fold_flag; } abstract; int lval; - struct { - int val; - struct demangle_component *type; - } typed_val_int; const char *opname; } -%type exp exp1 type start start_opt operator colon_name +%type exp exp1 type start start_opt oper colon_name %type unqualified_name colon_ext_name -%type template template_arg +%type templ template_arg %type builtin_type %type typespec_2 array_indicator %type colon_ext_only ext_only_name @@ -313,14 +328,6 @@ make_name (const char *name, int len) /* Non-C++ things we get from the demangler. */ %token DEMANGLER_SPECIAL %token CONSTRUCTION_VTABLE CONSTRUCTION_IN -%token GLOBAL - -%{ -enum { - GLOBAL_CONSTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 20, - GLOBAL_DESTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 21 -}; -%} /* Precedence declarations. */ @@ -425,25 +432,37 @@ function demangler_special : DEMANGLER_SPECIAL start - { $$ = make_empty ($1); + { $$ = make_empty ((enum demangle_component_type) $1); d_left ($$) = $2; d_right ($$) = NULL; } | CONSTRUCTION_VTABLE start CONSTRUCTION_IN start { $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); } - | GLOBAL - { $$ = make_empty ($1.val); - d_left ($$) = $1.type; - d_right ($$) = NULL; } ; -operator : OPERATOR NEW - { $$ = make_operator ("new", 1); } +oper : OPERATOR NEW + { + /* Match the whitespacing of cplus_demangle_operators. + It would abort on unrecognized string otherwise. */ + $$ = make_operator ("new", 3); + } | OPERATOR DELETE - { $$ = make_operator ("delete", 1); } + { + /* Match the whitespacing of cplus_demangle_operators. + It would abort on unrecognized string otherwise. */ + $$ = make_operator ("delete ", 1); + } | OPERATOR NEW '[' ']' - { $$ = make_operator ("new[]", 1); } + { + /* Match the whitespacing of cplus_demangle_operators. + It would abort on unrecognized string otherwise. */ + $$ = make_operator ("new[]", 3); + } | OPERATOR DELETE '[' ']' - { $$ = make_operator ("delete[]", 1); } + { + /* Match the whitespacing of cplus_demangle_operators. + It would abort on unrecognized string otherwise. */ + $$ = make_operator ("delete[] ", 1); + } | OPERATOR '+' { $$ = make_operator ("+", 2); } | OPERATOR '-' @@ -499,7 +518,7 @@ operator : OPERATOR NEW | OPERATOR ARROW { $$ = make_operator ("->", 2); } | OPERATOR '(' ')' - { $$ = make_operator ("()", 0); } + { $$ = make_operator ("()", 2); } | OPERATOR '[' ']' { $$ = make_operator ("[]", 2); } ; @@ -509,7 +528,7 @@ operator : OPERATOR NEW since it's not clear that it's parseable. */ conversion_op : OPERATOR typespec_2 - { $$ = fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL); } + { $$ = fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); } ; conversion_op_name @@ -535,8 +554,8 @@ conversion_op_name /* DEMANGLE_COMPONENT_NAME */ /* This accepts certain invalid placements of '~'. */ -unqualified_name: operator - | operator '<' template_params '>' +unqualified_name: oper + | oper '<' template_params '>' { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); } | '~' NAME { $$ = make_dtor (gnu_v3_complete_object_dtor, $2); } @@ -560,9 +579,9 @@ colon_name : name name : nested_name NAME %prec NAME { $$ = $1.comp; d_right ($1.last) = $2; } | NAME %prec NAME - | nested_name template %prec NAME + | nested_name templ %prec NAME { $$ = $1.comp; d_right ($1.last) = $2; } - | template %prec NAME + | templ %prec NAME ; colon_ext_name : colon_name @@ -592,13 +611,13 @@ nested_name : NAME COLONCOLON d_left ($$.last) = $2; d_right ($$.last) = NULL; } - | template COLONCOLON + | templ COLONCOLON { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); d_left ($$.comp) = $1; d_right ($$.comp) = NULL; $$.last = $$.comp; } - | nested_name template COLONCOLON + | nested_name templ COLONCOLON { $$.comp = $1.comp; d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); $$.last = d_right ($1.last); @@ -609,7 +628,7 @@ nested_name : NAME COLONCOLON /* DEMANGLE_COMPONENT_TEMPLATE */ /* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */ -template : NAME '<' template_params '>' +templ : NAME '<' template_params '>' { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); } ; @@ -1174,7 +1193,11 @@ exp : FLOAT ; exp : SIZEOF '(' type ')' %prec UNARY - { $$ = d_unary ("sizeof", $3); } + { + /* Match the whitespacing of cplus_demangle_operators. + It would abort on unrecognized string otherwise. */ + $$ = d_unary ("sizeof ", $3); + } ; /* C++. */ @@ -1557,7 +1580,7 @@ yylex (void) { int c; int namelen; - const char *tokstart, *tokptr; + const char *tokstart; retry: prev_lexptr = lexptr; @@ -1584,14 +1607,14 @@ yylex (void) c = cp_parse_escape (&lexptr); else if (c == '\'') { - yyerror ("empty character constant"); + yyerror (_("empty character constant")); return ERROR; } c = *lexptr++; if (c != '\'') { - yyerror ("invalid character constant"); + yyerror (_("invalid character constant")); return ERROR; } @@ -1715,7 +1738,7 @@ yylex (void) memcpy (err_copy, tokstart, p - tokstart); err_copy[p - tokstart] = 0; - yyerror ("invalid number"); + yyerror (_("invalid number")); return ERROR; } lexptr = p; @@ -1791,14 +1814,14 @@ yylex (void) case '"': /* These can't occur in C++ names. */ - yyerror ("unexpected string literal"); + yyerror (_("unexpected string literal")); return ERROR; } if (!(c == '_' || c == '$' || ISALPHA (c))) { /* We must have come across a bad character (e.g. ';'). */ - yyerror ("invalid character"); + yyerror (_("invalid character")); return ERROR; } @@ -1861,23 +1884,23 @@ yylex (void) { const char *p; lexptr = tokstart + 29; - yylval.typed_val_int.val = GLOBAL_CONSTRUCTORS; + yylval.lval = DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS; /* Find the end of the symbol. */ p = symbol_end (lexptr); - yylval.typed_val_int.type = make_name (lexptr, p - lexptr); + yylval.comp = make_name (lexptr, p - lexptr); lexptr = p; - return GLOBAL; + return DEMANGLER_SPECIAL; } if (strncmp (tokstart, "global destructors keyed to ", 28) == 0) { const char *p; lexptr = tokstart + 28; - yylval.typed_val_int.val = GLOBAL_DESTRUCTORS; + yylval.lval = DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS; /* Find the end of the symbol. */ p = symbol_end (lexptr); - yylval.typed_val_int.type = make_name (lexptr, p - lexptr); + yylval.comp = make_name (lexptr, p - lexptr); lexptr = p; - return GLOBAL; + return DEMANGLER_SPECIAL; } HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE); @@ -1951,20 +1974,14 @@ yyerror (char *msg) 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 +static struct demangle_info * allocate_info (void) { - 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; + struct demangle_info *info = XNEW (struct demangle_info); - demangle_info->used = 0; + info->next = NULL; + info->used = 0; + return info; } /* Convert RESULT to a string. The return value is allocated @@ -1976,51 +1993,105 @@ allocate_info (void) char * cp_comp_to_string (struct demangle_component *result, int estimated_len) { - char *str, *prefix = NULL, *buf; - size_t err = 0; + size_t err; - if (result->type == GLOBAL_DESTRUCTORS) - { - result = d_left (result); - prefix = "global destructors keyed to "; - } - else if (result->type == GLOBAL_CONSTRUCTORS) + return cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, estimated_len, + &err); +} + +/* A convenience function to allocate and initialize a new struct + demangled_parse_info. */ + +struct demangle_parse_info * +cp_new_demangle_parse_info (void) +{ + struct demangle_parse_info *info; + + info = XNEW (struct demangle_parse_info); + info->info = NULL; + info->tree = NULL; + obstack_init (&info->obstack); + + return info; +} + +/* Free any memory associated with the given PARSE_INFO. */ + +void +cp_demangled_name_parse_free (struct demangle_parse_info *parse_info) +{ + struct demangle_info *info = parse_info->info; + + /* Free any allocated chunks of memory for the parse. */ + while (info != NULL) { - result = d_left (result); - prefix = "global constructors keyed to "; + struct demangle_info *next = info->next; + + free (info); + info = next; } - str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, estimated_len, &err); - if (str == NULL) - return NULL; + /* Free any memory allocated during typedef replacement. */ + obstack_free (&parse_info->obstack, NULL); - if (prefix == NULL) - return str; + /* Free the parser info. */ + free (parse_info); +} - buf = malloc (strlen (str) + strlen (prefix) + 1); - strcpy (buf, prefix); - strcat (buf, str); - free (str); - return (buf); +/* Merge the two parse trees given by DEST and SRC. The parse tree + in SRC is attached to DEST at the node represented by TARGET. + SRC is then freed. + + NOTE 1: Since there is no API to merge obstacks, this function does + even attempt to try it. Fortunately, we do not (yet?) need this ability. + The code will assert if SRC->obstack is not empty. + + NOTE 2: The string from which SRC was parsed must not be freed, since + this function will place pointers to that string into DEST. */ + +void +cp_merge_demangle_parse_infos (struct demangle_parse_info *dest, + struct demangle_component *target, + struct demangle_parse_info *src) + +{ + struct demangle_info *di; + + /* Copy the SRC's parse data into DEST. */ + *target = *src->tree; + di = dest->info; + while (di->next != NULL) + di = di->next; + di->next = src->info; + + /* Clear the (pointer to) SRC's parse data so that it is not freed when + cp_demangled_parse_info_free is called. */ + src->info = NULL; + + /* Free SRC. */ + cp_demangled_name_parse_free (src); } /* 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 + a structure containing the root of the new tree is returned; it must + be freed by calling cp_demangled_name_parse_free. On error, NULL is returned, and an error message will be set in *ERRMSG (which does not need to be freed). */ -struct demangle_component * +struct demangle_parse_info * cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg) { static char errbuf[60]; - struct demangle_component *result; + struct demangle_parse_info *result; prev_lexptr = lexptr = demangled_name; error_lexptr = NULL; global_errmsg = NULL; - allocate_info (); + demangle_info = allocate_info (); + + result = cp_new_demangle_parse_info (); + result->info = demangle_info; if (yyparse ()) { @@ -2031,10 +2102,11 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg) strcat (errbuf, "'"); *errmsg = errbuf; } + cp_demangled_name_parse_free (result); return NULL; } - result = global_result; + result->tree = global_result; global_result = NULL; return result; @@ -2048,17 +2120,6 @@ cp_print (struct demangle_component *result) char *str; size_t err = 0; - if (result->type == GLOBAL_DESTRUCTORS) - { - result = d_left (result); - fputs ("global destructors keyed to ", stdout); - } - else if (result->type == GLOBAL_CONSTRUCTORS) - { - result = d_left (result); - fputs ("global constructors keyed to ", stdout); - } - str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, 64, &err); if (str == NULL) return; @@ -2091,7 +2152,24 @@ void xfree (void *ptr) { if (ptr != NULL) - free (ptr); + { + /* Literal `free' would get translated back to xfree again. */ + CONCAT2 (fr,ee) (ptr); + } +} + +/* GDB normally defines internal_error itself, but when this file is built + as a standalone program, we must also provide an implementation. */ + +void +internal_error (const char *file, int line, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + fprintf (stderr, "%s:%d: internal error: ", file, line); + vfprintf (stderr, fmt, ap); + exit (1); } int @@ -2101,7 +2179,7 @@ main (int argc, char **argv) char buf[65536]; int arg; const char *errmsg; - struct demangle_component *result; + struct demangle_parse_info *result; arg = 1; if (argv[arg] && strcmp (argv[arg], "--debug") == 0) @@ -2120,7 +2198,7 @@ main (int argc, char **argv) str2 = cplus_demangle (buf, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); if (str2 == NULL) { - /* printf ("Demangling error\n"); */ + printf ("Demangling error\n"); if (c) printf ("%s%c%s\n", buf, c, extra_chars); else @@ -2135,7 +2213,8 @@ main (int argc, char **argv) continue; } - cp_print (result); + cp_print (result->tree); + cp_demangled_name_parse_free (result); free (str2); if (c) @@ -2154,7 +2233,8 @@ main (int argc, char **argv) fputc ('\n', stderr); return 0; } - cp_print (result); + cp_print (result->tree); + cp_demangled_name_parse_free (result); putchar ('\n'); } return 0;