/* YACC parser for C++ names, for GDB.
- Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2003-2019 Free Software Foundation, Inc.
Parts of the lexer are based on c-exp.y from GDB.
too messy, particularly when such includes can be inserted at random
times by the parser generator. */
+/* The Bison manual says that %pure-parser is deprecated, but we use
+ it anyway because it also works with Byacc. That is also why
+ this uses %lex-param and %parse-param rather than the simpler
+ %param -- Byacc does not support the latter. */
+%pure-parser
+%lex-param {struct cpname_state *state}
+%parse-param {struct cpname_state *state}
+
%{
#include "defs.h"
-#include <stdio.h>
-#include <stdlib.h>
#include <unistd.h>
-#include <string.h>
-
#include "safe-ctype.h"
-#include "libiberty.h"
#include "demangle.h"
#include "cp-support.h"
+#include "c-support.h"
+#include "parser-defs.h"
-/* Bison does not make it easy to create a parser without global
- state, unfortunately. Here are all the global variables used
- in this parser. */
-
-/* LEXPTR is the current pointer into our lex buffer. PREV_LEXPTR
- is the start of the last token lexed, only used for diagnostics.
- ERROR_LEXPTR is the first place an error occurred. GLOBAL_ERRMSG
- is the first error message encountered. */
-
-static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
+#define GDB_YY_REMAP_PREFIX cpname
+#include "yy-remap.h"
/* The components built by the parser are allocated ahead of time,
and cached in this structure. */
struct demangle_info {
int used;
- struct demangle_info *prev, *next;
+ struct demangle_info *next;
struct demangle_component comps[ALLOC_CHUNK];
};
-static struct demangle_info *demangle_info;
+%}
-static struct demangle_component *
-d_grab (void)
+%union
+ {
+ struct demangle_component *comp;
+ struct nested {
+ struct demangle_component *comp;
+ struct demangle_component **last;
+ } nested;
+ struct {
+ struct demangle_component *comp, *last;
+ } nested1;
+ struct {
+ struct demangle_component *comp, **last;
+ struct nested fn;
+ struct demangle_component *start;
+ int fold_flag;
+ } abstract;
+ int lval;
+ const char *opname;
+ }
+
+%{
+
+struct cpname_state
+{
+ /* LEXPTR is the current pointer into our lex buffer. PREV_LEXPTR
+ is the start of the last token lexed, only used for diagnostics.
+ ERROR_LEXPTR is the first place an error occurred. GLOBAL_ERRMSG
+ is the first error message encountered. */
+
+ const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
+
+ struct demangle_info *demangle_info;
+
+ /* The parse tree created by the parser is stored here after a
+ successful parse. */
+
+ struct demangle_component *global_result;
+
+ struct demangle_component *d_grab ();
+
+ /* Helper functions. These wrap the demangler tree interface,
+ handle allocation from our global store, and return the allocated
+ component. */
+
+ struct demangle_component *fill_comp (enum demangle_component_type d_type,
+ struct demangle_component *lhs,
+ struct demangle_component *rhs);
+
+ struct demangle_component *make_operator (const char *name, int args);
+
+ struct demangle_component *make_dtor (enum gnu_v3_dtor_kinds kind,
+ struct demangle_component *name);
+
+ struct demangle_component *make_builtin_type (const char *name);
+
+ struct demangle_component *make_name (const char *name, int len);
+
+ struct demangle_component *d_qualify (struct demangle_component *lhs,
+ int qualifiers, int is_method);
+
+ struct demangle_component *d_int_type (int flags);
+
+ struct demangle_component *d_unary (const char *name,
+ struct demangle_component *lhs);
+
+ struct demangle_component *d_binary (const char *name,
+ struct demangle_component *lhs,
+ struct demangle_component *rhs);
+
+ int parse_number (const char *p, int len, int parsed_float, YYSTYPE *lvalp);
+};
+
+struct demangle_component *
+cpname_state::d_grab ()
{
struct demangle_info *more;
{
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;
}
return &demangle_info->comps[demangle_info->used++];
}
-/* The parse tree created by the parser is stored here after a successful
- parse. */
-
-static struct demangle_component *global_result;
-
-/* Prototypes for helper functions used when constructing the parse
- tree. */
-
-static struct demangle_component *d_qualify (struct demangle_component *, int,
- int);
-
-static struct demangle_component *d_int_type (int);
-
-static struct demangle_component *d_unary (const char *,
- struct demangle_component *);
-static struct demangle_component *d_binary (const char *,
- struct demangle_component *,
- struct demangle_component *);
-
/* Flags passed to d_qualify. */
#define QUAL_CONST 1
#define INT_SIGNED (1 << 4)
#define INT_UNSIGNED (1 << 5)
-/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
- as well as gratuitiously global symbol names, so we can have multiple
- yacc generated parsers in gdb. Note that these are only the variables
- produced by yacc. If other parser generators (bison, byacc, etc) produce
- additional global names that conflict at link time, then those parser
- generators need to be fixed instead of adding those names to this list. */
-
-#define yymaxdepth cpname_maxdepth
-#define yyparse cpname_parse
-#define yylex cpname_lex
-#define yyerror cpname_error
-#define yylval cpname_lval
-#define yychar cpname_char
-#define yydebug cpname_debug
-#define yypact cpname_pact
-#define yyr1 cpname_r1
-#define yyr2 cpname_r2
-#define yydef cpname_def
-#define yychk cpname_chk
-#define yypgo cpname_pgo
-#define yyact cpname_act
-#define yyexca cpname_exca
-#define yyerrflag cpname_errflag
-#define yynerrs cpname_nerrs
-#define yyps cpname_ps
-#define yypv cpname_pv
-#define yys cpname_s
-#define yy_yys cpname_yys
-#define yystate cpname_state
-#define yytmp cpname_tmp
-#define yyv cpname_v
-#define yy_yyv cpname_yyv
-#define yyval cpname_val
-#define yylloc cpname_lloc
-#define yyreds cpname_reds /* With YYDEBUG defined */
-#define yytoks cpname_toks /* With YYDEBUG defined */
-#define yyname cpname_name /* With YYDEBUG defined */
-#define yyrule cpname_rule /* With YYDEBUG defined */
-#define yylhs cpname_yylhs
-#define yylen cpname_yylen
-#define yydefred cpname_yydefred
-#define yydgoto cpname_yydgoto
-#define yysindex cpname_yysindex
-#define yyrindex cpname_yyrindex
-#define yygindex cpname_yygindex
-#define yytable cpname_yytable
-#define yycheck cpname_yycheck
-
-int yyparse (void);
-static int yylex (void);
-static void yyerror (char *);
-
/* Enable yydebug for the stand-alone parser. */
#ifdef TEST_CPNAMES
# define YYDEBUG 1
/* Helper functions. These wrap the demangler tree interface, handle
allocation from our global store, and return the allocated component. */
-static struct demangle_component *
-fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
- struct demangle_component *rhs)
+struct demangle_component *
+cpname_state::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);
- return ret;
-}
+ int i;
+
+ i = cplus_demangle_fill_component (ret, d_type, lhs, rhs);
+ gdb_assert (i);
-static struct demangle_component *
-make_empty (enum demangle_component_type d_type)
-{
- struct demangle_component *ret = d_grab ();
- ret->type = d_type;
return ret;
}
-static struct demangle_component *
-make_operator (const char *name, int args)
+struct demangle_component *
+cpname_state::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;
}
-static struct demangle_component *
-make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
+struct demangle_component *
+cpname_state::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;
}
-static struct demangle_component *
-make_builtin_type (const char *name)
+struct demangle_component *
+cpname_state::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;
}
-static struct demangle_component *
-make_name (const char *name, int len)
+struct demangle_component *
+cpname_state::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;
}
#define d_left(dc) (dc)->u.s_binary.left
#define d_right(dc) (dc)->u.s_binary.right
+static int yylex (YYSTYPE *, cpname_state *);
+static void yyerror (cpname_state *, const char *);
%}
-%union
- {
- struct demangle_component *comp;
- struct nested {
- struct demangle_component *comp;
- struct demangle_component **last;
- } nested;
- struct {
- struct demangle_component *comp, *last;
- } nested1;
- struct {
- struct demangle_component *comp, **last;
- struct nested fn;
- struct demangle_component *start;
- int fold_flag;
- } abstract;
- int lval;
- struct {
- int val;
- struct demangle_component *type;
- } typed_val_int;
- const char *opname;
- }
-
-%type <comp> exp exp1 type start start_opt operator colon_name
+%type <comp> exp exp1 type start start_opt oper colon_name
%type <comp> unqualified_name colon_ext_name
-%type <comp> template template_arg
+%type <comp> templ template_arg
%type <comp> builtin_type
%type <comp> typespec_2 array_indicator
%type <comp> colon_ext_only ext_only_name
/* Non-C++ things we get from the demangler. */
%token <lval> DEMANGLER_SPECIAL
%token CONSTRUCTION_VTABLE CONSTRUCTION_IN
-%token <typed_val_int> GLOBAL
-
-%{
-enum {
- GLOBAL_CONSTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 20,
- GLOBAL_DESTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 21
-};
-%}
/* Precedence declarations. */
%%
result : start
- { global_result = $1; }
+ { state->global_result = $1; }
;
start : type
start_opt is used to handle "function-local" variables and
types. */
| typespec_2 function_arglist start_opt
- { $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
- if ($3) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME,
+ $1, $2.comp);
+ if ($3)
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME,
+ $$, $3);
+ }
| colon_ext_only function_arglist start_opt
- { $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
- if ($3) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+ if ($3) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
| conversion_op_name start_opt
{ $$ = $1.comp;
- if ($2) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
+ if ($2) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
| conversion_op_name abstract_declarator_fn
{ if ($2.last)
{
}
/* If we have an arglist, build a function type. */
if ($2.fn.comp)
- $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1.comp, $2.fn.comp);
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1.comp, $2.fn.comp);
else
$$ = $1.comp;
- if ($2.start) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2.start);
+ if ($2.start) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2.start);
}
;
demangler_special
: DEMANGLER_SPECIAL start
- { $$ = make_empty ($1);
- d_left ($$) = $2;
- d_right ($$) = NULL; }
+ { $$ = state->fill_comp ((enum demangle_component_type) $1, $2, 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; }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
;
-operator : OPERATOR NEW
- { $$ = make_operator ("new", 1); }
+oper : OPERATOR NEW
+ {
+ /* Match the whitespacing of cplus_demangle_operators.
+ It would abort on unrecognized string otherwise. */
+ $$ = state->make_operator ("new", 3);
+ }
| OPERATOR DELETE
- { $$ = make_operator ("delete", 1); }
+ {
+ /* Match the whitespacing of cplus_demangle_operators.
+ It would abort on unrecognized string otherwise. */
+ $$ = state->make_operator ("delete ", 1);
+ }
| OPERATOR NEW '[' ']'
- { $$ = make_operator ("new[]", 1); }
+ {
+ /* Match the whitespacing of cplus_demangle_operators.
+ It would abort on unrecognized string otherwise. */
+ $$ = state->make_operator ("new[]", 3);
+ }
| OPERATOR DELETE '[' ']'
- { $$ = make_operator ("delete[]", 1); }
+ {
+ /* Match the whitespacing of cplus_demangle_operators.
+ It would abort on unrecognized string otherwise. */
+ $$ = state->make_operator ("delete[] ", 1);
+ }
| OPERATOR '+'
- { $$ = make_operator ("+", 2); }
+ { $$ = state->make_operator ("+", 2); }
| OPERATOR '-'
- { $$ = make_operator ("-", 2); }
+ { $$ = state->make_operator ("-", 2); }
| OPERATOR '*'
- { $$ = make_operator ("*", 2); }
+ { $$ = state->make_operator ("*", 2); }
| OPERATOR '/'
- { $$ = make_operator ("/", 2); }
+ { $$ = state->make_operator ("/", 2); }
| OPERATOR '%'
- { $$ = make_operator ("%", 2); }
+ { $$ = state->make_operator ("%", 2); }
| OPERATOR '^'
- { $$ = make_operator ("^", 2); }
+ { $$ = state->make_operator ("^", 2); }
| OPERATOR '&'
- { $$ = make_operator ("&", 2); }
+ { $$ = state->make_operator ("&", 2); }
| OPERATOR '|'
- { $$ = make_operator ("|", 2); }
+ { $$ = state->make_operator ("|", 2); }
| OPERATOR '~'
- { $$ = make_operator ("~", 1); }
+ { $$ = state->make_operator ("~", 1); }
| OPERATOR '!'
- { $$ = make_operator ("!", 1); }
+ { $$ = state->make_operator ("!", 1); }
| OPERATOR '='
- { $$ = make_operator ("=", 2); }
+ { $$ = state->make_operator ("=", 2); }
| OPERATOR '<'
- { $$ = make_operator ("<", 2); }
+ { $$ = state->make_operator ("<", 2); }
| OPERATOR '>'
- { $$ = make_operator (">", 2); }
+ { $$ = state->make_operator (">", 2); }
| OPERATOR ASSIGN_MODIFY
- { $$ = make_operator ($2, 2); }
+ { $$ = state->make_operator ($2, 2); }
| OPERATOR LSH
- { $$ = make_operator ("<<", 2); }
+ { $$ = state->make_operator ("<<", 2); }
| OPERATOR RSH
- { $$ = make_operator (">>", 2); }
+ { $$ = state->make_operator (">>", 2); }
| OPERATOR EQUAL
- { $$ = make_operator ("==", 2); }
+ { $$ = state->make_operator ("==", 2); }
| OPERATOR NOTEQUAL
- { $$ = make_operator ("!=", 2); }
+ { $$ = state->make_operator ("!=", 2); }
| OPERATOR LEQ
- { $$ = make_operator ("<=", 2); }
+ { $$ = state->make_operator ("<=", 2); }
| OPERATOR GEQ
- { $$ = make_operator (">=", 2); }
+ { $$ = state->make_operator (">=", 2); }
| OPERATOR ANDAND
- { $$ = make_operator ("&&", 2); }
+ { $$ = state->make_operator ("&&", 2); }
| OPERATOR OROR
- { $$ = make_operator ("||", 2); }
+ { $$ = state->make_operator ("||", 2); }
| OPERATOR INCREMENT
- { $$ = make_operator ("++", 1); }
+ { $$ = state->make_operator ("++", 1); }
| OPERATOR DECREMENT
- { $$ = make_operator ("--", 1); }
+ { $$ = state->make_operator ("--", 1); }
| OPERATOR ','
- { $$ = make_operator (",", 2); }
+ { $$ = state->make_operator (",", 2); }
| OPERATOR ARROW '*'
- { $$ = make_operator ("->*", 2); }
+ { $$ = state->make_operator ("->*", 2); }
| OPERATOR ARROW
- { $$ = make_operator ("->", 2); }
+ { $$ = state->make_operator ("->", 2); }
| OPERATOR '(' ')'
- { $$ = make_operator ("()", 0); }
+ { $$ = state->make_operator ("()", 2); }
| OPERATOR '[' ']'
- { $$ = make_operator ("[]", 2); }
+ { $$ = state->make_operator ("[]", 2); }
;
/* Conversion operators. We don't try to handle some of
since it's not clear that it's parseable. */
conversion_op
: OPERATOR typespec_2
- { $$ = fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
;
conversion_op_name
/* DEMANGLE_COMPONENT_NAME */
/* This accepts certain invalid placements of '~'. */
-unqualified_name: operator
- | operator '<' template_params '>'
- { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+unqualified_name: oper
+ | oper '<' template_params '>'
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
| '~' NAME
- { $$ = make_dtor (gnu_v3_complete_object_dtor, $2); }
+ { $$ = state->make_dtor (gnu_v3_complete_object_dtor, $2); }
;
/* This rule is used in name and nested_name, and expanded inline there
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
;
nested_name : NAME COLONCOLON
- { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
- d_left ($$.comp) = $1;
- d_right ($$.comp) = NULL;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
$$.last = $$.comp;
}
| nested_name NAME COLONCOLON
{ $$.comp = $1.comp;
- d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
+ d_right ($1.last) = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
$$.last = d_right ($1.last);
- d_left ($$.last) = $2;
- d_right ($$.last) = NULL;
}
- | template COLONCOLON
- { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
- d_left ($$.comp) = $1;
- d_right ($$.comp) = NULL;
+ | templ COLONCOLON
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
$$.last = $$.comp;
}
- | nested_name template COLONCOLON
+ | nested_name templ COLONCOLON
{ $$.comp = $1.comp;
- d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
+ d_right ($1.last) = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
$$.last = d_right ($1.last);
- d_left ($$.last) = $2;
- d_right ($$.last) = NULL;
}
;
/* DEMANGLE_COMPONENT_TEMPLATE */
/* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */
-template : NAME '<' template_params '>'
- { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+templ : NAME '<' template_params '>'
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
;
template_params : template_arg
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $1, NULL);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $1, NULL);
$$.last = &d_right ($$.comp); }
| template_params ',' template_arg
{ $$.comp = $1.comp;
- *$1.last = fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $3, NULL);
+ *$1.last = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $3, NULL);
$$.last = &d_right (*$1.last);
}
;
*$2.last = $1;
}
| '&' start
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $2); }
| '&' '(' start ')'
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $3); }
| exp
;
function_args : typespec_2
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $1, NULL);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $1, NULL);
$$.last = &d_right ($$.comp);
}
| typespec_2 abstract_declarator
{ *$2.last = $1;
- $$.comp = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $2.comp, NULL);
+ $$.comp = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $2.comp, NULL);
$$.last = &d_right ($$.comp);
}
| function_args ',' typespec_2
- { *$1.last = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $3, NULL);
+ { *$1.last = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $3, NULL);
$$.comp = $1.comp;
$$.last = &d_right (*$1.last);
}
| function_args ',' typespec_2 abstract_declarator
{ *$4.last = $3;
- *$1.last = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $4.comp, NULL);
+ *$1.last = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $4.comp, NULL);
$$.comp = $1.comp;
$$.last = &d_right (*$1.last);
}
| function_args ',' ELLIPSIS
{ *$1.last
- = fill_comp (DEMANGLE_COMPONENT_ARGLIST,
- make_builtin_type ("..."),
+ = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST,
+ state->make_builtin_type ("..."),
NULL);
$$.comp = $1.comp;
$$.last = &d_right (*$1.last);
;
function_arglist: '(' function_args ')' qualifiers_opt %prec NAME
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
$$.last = &d_left ($$.comp);
- $$.comp = d_qualify ($$.comp, $4, 1); }
+ $$.comp = state->d_qualify ($$.comp, $4, 1); }
| '(' VOID ')' qualifiers_opt
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
$$.last = &d_left ($$.comp);
- $$.comp = d_qualify ($$.comp, $4, 1); }
+ $$.comp = state->d_qualify ($$.comp, $4, 1); }
| '(' ')' qualifiers_opt
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
$$.last = &d_left ($$.comp);
- $$.comp = d_qualify ($$.comp, $3, 1); }
+ $$.comp = state->d_qualify ($$.comp, $3, 1); }
;
/* Should do something about DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL */
;
builtin_type : int_seq
- { $$ = d_int_type ($1); }
+ { $$ = state->d_int_type ($1); }
| FLOAT_KEYWORD
- { $$ = make_builtin_type ("float"); }
+ { $$ = state->make_builtin_type ("float"); }
| DOUBLE_KEYWORD
- { $$ = make_builtin_type ("double"); }
+ { $$ = state->make_builtin_type ("double"); }
| LONG DOUBLE_KEYWORD
- { $$ = make_builtin_type ("long double"); }
+ { $$ = state->make_builtin_type ("long double"); }
| BOOL
- { $$ = make_builtin_type ("bool"); }
+ { $$ = state->make_builtin_type ("bool"); }
| WCHAR_T
- { $$ = make_builtin_type ("wchar_t"); }
+ { $$ = state->make_builtin_type ("wchar_t"); }
| VOID
- { $$ = make_builtin_type ("void"); }
+ { $$ = state->make_builtin_type ("void"); }
;
ptr_operator : '*' qualifiers_opt
- { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER);
- $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL);
$$.last = &d_left ($$.comp);
- $$.comp = d_qualify ($$.comp, $2, 0); }
+ $$.comp = state->d_qualify ($$.comp, $2, 0); }
/* g++ seems to allow qualifiers after the reference? */
| '&'
- { $$.comp = make_empty (DEMANGLE_COMPONENT_REFERENCE);
- $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL);
+ $$.last = &d_left ($$.comp); }
+ | ANDAND
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_RVALUE_REFERENCE, NULL, NULL);
$$.last = &d_left ($$.comp); }
| nested_name '*' qualifiers_opt
- { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE);
- $$.comp->u.s_binary.left = $1.comp;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $1.comp, NULL);
/* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */
*$1.last = *d_left ($1.last);
- $$.comp->u.s_binary.right = NULL;
$$.last = &d_right ($$.comp);
- $$.comp = d_qualify ($$.comp, $3, 0); }
+ $$.comp = state->d_qualify ($$.comp, $3, 0); }
| COLONCOLON nested_name '*' qualifiers_opt
- { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE);
- $$.comp->u.s_binary.left = $2.comp;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $2.comp, NULL);
/* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */
*$2.last = *d_left ($2.last);
- $$.comp->u.s_binary.right = NULL;
$$.last = &d_right ($$.comp);
- $$.comp = d_qualify ($$.comp, $4, 0); }
+ $$.comp = state->d_qualify ($$.comp, $4, 0); }
;
array_indicator : '[' ']'
- { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
- d_left ($$) = NULL;
- }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); }
| '[' INT ']'
- { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
- d_left ($$) = $2;
- }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); }
;
/* Details of this approach inspired by the G++ < 3.4 parser. */
*/
typespec_2 : builtin_type qualifiers
- { $$ = d_qualify ($1, $2, 0); }
+ { $$ = state->d_qualify ($1, $2, 0); }
| builtin_type
| qualifiers builtin_type qualifiers
- { $$ = d_qualify ($2, $1 | $3, 0); }
+ { $$ = state->d_qualify ($2, $1 | $3, 0); }
| qualifiers builtin_type
- { $$ = d_qualify ($2, $1, 0); }
+ { $$ = state->d_qualify ($2, $1, 0); }
| name qualifiers
- { $$ = d_qualify ($1, $2, 0); }
+ { $$ = state->d_qualify ($1, $2, 0); }
| name
| qualifiers name qualifiers
- { $$ = d_qualify ($2, $1 | $3, 0); }
+ { $$ = state->d_qualify ($2, $1 | $3, 0); }
| qualifiers name
- { $$ = d_qualify ($2, $1, 0); }
+ { $$ = state->d_qualify ($2, $1, 0); }
| COLONCOLON name qualifiers
- { $$ = d_qualify ($2, $3, 0); }
+ { $$ = state->d_qualify ($2, $3, 0); }
| COLONCOLON name
{ $$ = $2; }
| qualifiers COLONCOLON name qualifiers
- { $$ = d_qualify ($3, $1 | $4, 0); }
+ { $$ = state->d_qualify ($3, $1 | $4, 0); }
| qualifiers COLONCOLON name
- { $$ = d_qualify ($3, $1, 0); }
+ { $$ = state->d_qualify ($3, $1, 0); }
;
abstract_declarator
$$.last = &d_right ($2);
}
| colon_ext_name
- { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME);
- d_left ($$.comp) = $1;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
$$.last = &d_right ($$.comp);
}
;
$$.last = $1.last;
*$2.last = $1.comp; }
| colon_ext_name
- { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME);
- d_left ($$.comp) = $1;
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
$$.last = &d_right ($$.comp);
}
| direct_declarator_1
members will not be mangled. If they are hopefully
they'll end up to the right of the ::. */
| colon_ext_name function_arglist COLONCOLON start
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
$$.last = $2.last;
- $$.comp = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
+ $$.comp = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
}
| direct_declarator_1 function_arglist COLONCOLON start
{ $$.comp = $1.comp;
*$1.last = $2.comp;
$$.last = $2.last;
- $$.comp = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
+ $$.comp = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
}
;
$$.last = &d_right ($2);
}
| colon_ext_name function_arglist
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
$$.last = $2.last;
}
| colon_ext_name array_indicator
- { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2);
+ { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2);
$$.last = &d_right ($2);
}
;
;
exp1 : exp '>' exp
- { $$ = d_binary (">", $1, $3); }
+ { $$ = state->d_binary (">", $1, $3); }
;
/* References. Not allowed everywhere in template parameters, only
at the top level, but treat them as expressions in case they are wrapped
in parentheses. */
exp1 : '&' start
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $2); }
| '&' '(' start ')'
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $3); }
;
/* Expressions, not including the comma operator. */
exp : '-' exp %prec UNARY
- { $$ = d_unary ("-", $2); }
+ { $$ = state->d_unary ("-", $2); }
;
exp : '!' exp %prec UNARY
- { $$ = d_unary ("!", $2); }
+ { $$ = state->d_unary ("!", $2); }
;
exp : '~' exp %prec UNARY
- { $$ = d_unary ("~", $2); }
+ { $$ = state->d_unary ("~", $2); }
;
/* Casts. First your normal C-style cast. If exp is a LITERAL, just change
d_left ($4) = $2;
}
else
- $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
- fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL),
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+ state->fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL),
$4);
}
;
/* Mangling does not differentiate between these, so we don't need to
either. */
exp : STATIC_CAST '<' type '>' '(' exp1 ')' %prec UNARY
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
- fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+ state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
$6);
}
;
exp : DYNAMIC_CAST '<' type '>' '(' exp1 ')' %prec UNARY
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
- fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+ state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
$6);
}
;
exp : REINTERPRET_CAST '<' type '>' '(' exp1 ')' %prec UNARY
- { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
- fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+ state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
$6);
}
;
/* Binary operators in order of decreasing precedence. */
exp : exp '*' exp
- { $$ = d_binary ("*", $1, $3); }
+ { $$ = state->d_binary ("*", $1, $3); }
;
exp : exp '/' exp
- { $$ = d_binary ("/", $1, $3); }
+ { $$ = state->d_binary ("/", $1, $3); }
;
exp : exp '%' exp
- { $$ = d_binary ("%", $1, $3); }
+ { $$ = state->d_binary ("%", $1, $3); }
;
exp : exp '+' exp
- { $$ = d_binary ("+", $1, $3); }
+ { $$ = state->d_binary ("+", $1, $3); }
;
exp : exp '-' exp
- { $$ = d_binary ("-", $1, $3); }
+ { $$ = state->d_binary ("-", $1, $3); }
;
exp : exp LSH exp
- { $$ = d_binary ("<<", $1, $3); }
+ { $$ = state->d_binary ("<<", $1, $3); }
;
exp : exp RSH exp
- { $$ = d_binary (">>", $1, $3); }
+ { $$ = state->d_binary (">>", $1, $3); }
;
exp : exp EQUAL exp
- { $$ = d_binary ("==", $1, $3); }
+ { $$ = state->d_binary ("==", $1, $3); }
;
exp : exp NOTEQUAL exp
- { $$ = d_binary ("!=", $1, $3); }
+ { $$ = state->d_binary ("!=", $1, $3); }
;
exp : exp LEQ exp
- { $$ = d_binary ("<=", $1, $3); }
+ { $$ = state->d_binary ("<=", $1, $3); }
;
exp : exp GEQ exp
- { $$ = d_binary (">=", $1, $3); }
+ { $$ = state->d_binary (">=", $1, $3); }
;
exp : exp '<' exp
- { $$ = d_binary ("<", $1, $3); }
+ { $$ = state->d_binary ("<", $1, $3); }
;
exp : exp '&' exp
- { $$ = d_binary ("&", $1, $3); }
+ { $$ = state->d_binary ("&", $1, $3); }
;
exp : exp '^' exp
- { $$ = d_binary ("^", $1, $3); }
+ { $$ = state->d_binary ("^", $1, $3); }
;
exp : exp '|' exp
- { $$ = d_binary ("|", $1, $3); }
+ { $$ = state->d_binary ("|", $1, $3); }
;
exp : exp ANDAND exp
- { $$ = d_binary ("&&", $1, $3); }
+ { $$ = state->d_binary ("&&", $1, $3); }
;
exp : exp OROR exp
- { $$ = d_binary ("||", $1, $3); }
+ { $$ = state->d_binary ("||", $1, $3); }
;
/* Not 100% sure these are necessary, but they're harmless. */
exp : exp ARROW NAME
- { $$ = d_binary ("->", $1, $3); }
+ { $$ = state->d_binary ("->", $1, $3); }
;
exp : exp '.' NAME
- { $$ = d_binary (".", $1, $3); }
+ { $$ = state->d_binary (".", $1, $3); }
;
exp : exp '?' exp ':' exp %prec '?'
- { $$ = fill_comp (DEMANGLE_COMPONENT_TRINARY, make_operator ("?", 3),
- fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG1, $1,
- fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG2, $3, $5)));
+ { $$ = state->fill_comp (DEMANGLE_COMPONENT_TRINARY, state->make_operator ("?", 3),
+ state->fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG1, $1,
+ state->fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG2, $3, $5)));
}
;
;
exp : SIZEOF '(' type ')' %prec UNARY
- { $$ = d_unary ("sizeof", $3); }
+ {
+ /* Match the whitespacing of cplus_demangle_operators.
+ It would abort on unrecognized string otherwise. */
+ $$ = state->d_unary ("sizeof ", $3);
+ }
;
/* C++. */
exp : TRUEKEYWORD
{ struct demangle_component *i;
- i = make_name ("1", 1);
- $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
- make_builtin_type ("bool"),
+ i = state->make_name ("1", 1);
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+ state->make_builtin_type ( "bool"),
i);
}
;
exp : FALSEKEYWORD
{ struct demangle_component *i;
- i = make_name ("0", 1);
- $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
- make_builtin_type ("bool"),
+ i = state->make_name ("0", 1);
+ $$ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+ state->make_builtin_type ("bool"),
i);
}
;
may already be qualified; duplicate qualifiers are not created. */
struct demangle_component *
-d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
+cpname_state::d_qualify (struct demangle_component *lhs, int qualifiers,
+ int is_method)
{
struct demangle_component **inner_p;
enum demangle_component_type type;
#define HANDLE_QUAL(TYPE, MTYPE, QUAL) \
if ((qualifiers & QUAL) && (type != TYPE) && (type != MTYPE)) \
{ \
- *inner_p = fill_comp (is_method ? MTYPE : TYPE, \
- *inner_p, NULL); \
+ *inner_p = fill_comp (is_method ? MTYPE : TYPE, \
+ *inner_p, NULL); \
inner_p = &d_left (*inner_p); \
type = (*inner_p)->type; \
} \
/* Return a builtin type corresponding to FLAGS. */
-static struct demangle_component *
-d_int_type (int flags)
+struct demangle_component *
+cpname_state::d_int_type (int flags)
{
const char *name;
/* Wrapper to create a unary operation. */
-static struct demangle_component *
-d_unary (const char *name, struct demangle_component *lhs)
+struct demangle_component *
+cpname_state::d_unary (const char *name, struct demangle_component *lhs)
{
return fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator (name, 1), lhs);
}
/* Wrapper to create a binary operation. */
-static struct demangle_component *
-d_binary (const char *name, struct demangle_component *lhs, struct demangle_component *rhs)
+struct demangle_component *
+cpname_state::d_binary (const char *name, struct demangle_component *lhs,
+ struct demangle_component *rhs)
{
return fill_comp (DEMANGLE_COMPONENT_BINARY, make_operator (name, 2),
- fill_comp (DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
+ fill_comp (DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
}
/* Find the end of a symbol name starting at LEXPTR. */
{
const char *p = lexptr;
- while (*p && (ISALNUM (*p) || *p == '_' || *p == '$' || *p == '.'))
+ while (*p && (c_ident_is_alnum (*p) || *p == '_' || *p == '$' || *p == '.'))
p++;
return p;
The number starts at P and contains LEN characters. Store the result in
YYLVAL. */
-static int
-parse_number (const char *p, int len, int parsed_float)
+int
+cpname_state::parse_number (const char *p, int len, int parsed_float,
+ YYSTYPE *lvalp)
{
int unsigned_p = 0;
return ERROR;
name = make_name (p, len);
- yylval.comp = fill_comp (literal_type, type, name);
+ lvalp->comp = fill_comp (literal_type, type, name);
return FLOAT;
}
type = signed_type;
name = make_name (p, len);
- yylval.comp = fill_comp (literal_type, type, name);
+ lvalp->comp = fill_comp (literal_type, type, name);
return INT;
}
-static char backslashable[] = "abefnrtv";
-static char represented[] = "\a\b\e\f\n\r\t\v";
+static const char backslashable[] = "abefnrtv";
+static const char represented[] = "\a\b\e\f\n\r\t\v";
/* Translate the backslash the way we would in the host character set. */
static int
#define HANDLE_SPECIAL(string, comp) \
if (strncmp (tokstart, string, sizeof (string) - 1) == 0) \
{ \
- lexptr = tokstart + sizeof (string) - 1; \
- yylval.lval = comp; \
+ state->lexptr = tokstart + sizeof (string) - 1; \
+ lvalp->lval = comp; \
return DEMANGLER_SPECIAL; \
}
#define HANDLE_TOKEN2(string, token) \
- if (lexptr[1] == string[1]) \
+ if (state->lexptr[1] == string[1]) \
{ \
- lexptr += 2; \
- yylval.opname = string; \
+ state->lexptr += 2; \
+ lvalp->opname = string; \
return token; \
}
#define HANDLE_TOKEN3(string, token) \
- if (lexptr[1] == string[1] && lexptr[2] == string[2]) \
+ if (state->lexptr[1] == string[1] && state->lexptr[2] == string[2]) \
{ \
- lexptr += 3; \
- yylval.opname = string; \
+ state->lexptr += 3; \
+ lvalp->opname = string; \
return token; \
}
/* Read one token, getting characters through LEXPTR. */
static int
-yylex (void)
+yylex (YYSTYPE *lvalp, cpname_state *state)
{
int c;
int namelen;
- const char *tokstart, *tokptr;
+ const char *tokstart;
retry:
- prev_lexptr = lexptr;
- tokstart = lexptr;
+ state->prev_lexptr = state->lexptr;
+ tokstart = state->lexptr;
switch (c = *tokstart)
{
case ' ':
case '\t':
case '\n':
- lexptr++;
+ state->lexptr++;
goto retry;
case '\'':
/* We either have a character constant ('0' or '\177' for example)
or we have a quoted symbol reference ('foo(int,int)' in C++
for example). */
- lexptr++;
- c = *lexptr++;
+ state->lexptr++;
+ c = *state->lexptr++;
if (c == '\\')
- c = cp_parse_escape (&lexptr);
+ c = cp_parse_escape (&state->lexptr);
else if (c == '\'')
{
- yyerror ("empty character constant");
+ yyerror (state, _("empty character constant"));
return ERROR;
}
- c = *lexptr++;
+ c = *state->lexptr++;
if (c != '\'')
{
- yyerror ("invalid character constant");
+ yyerror (state, _("invalid character constant"));
return ERROR;
}
presumably the same one that appears in manglings - the decimal
representation. But if that isn't in our input then we have to
allocate memory for it somewhere. */
- yylval.comp = fill_comp (DEMANGLE_COMPONENT_LITERAL,
- make_builtin_type ("char"),
- make_name (tokstart, lexptr - tokstart));
+ lvalp->comp
+ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+ state->make_builtin_type ("char"),
+ state->make_name (tokstart,
+ state->lexptr - tokstart));
return INT;
case '(':
if (strncmp (tokstart, "(anonymous namespace)", 21) == 0)
{
- lexptr += 21;
- yylval.comp = make_name ("(anonymous namespace)",
- sizeof "(anonymous namespace)" - 1);
+ state->lexptr += 21;
+ lvalp->comp = state->make_name ("(anonymous namespace)",
+ sizeof "(anonymous namespace)" - 1);
return NAME;
}
/* FALL THROUGH */
case ')':
case ',':
- lexptr++;
+ state->lexptr++;
return c;
case '.':
- if (lexptr[1] == '.' && lexptr[2] == '.')
+ if (state->lexptr[1] == '.' && state->lexptr[2] == '.')
{
- lexptr += 3;
+ state->lexptr += 3;
return ELLIPSIS;
}
/* Might be a floating point number. */
- if (lexptr[1] < '0' || lexptr[1] > '9')
+ if (state->lexptr[1] < '0' || state->lexptr[1] > '9')
goto symbol; /* Nope, must be a symbol. */
goto try_number;
/* For construction vtables. This is kind of hokey. */
if (strncmp (tokstart, "-in-", 4) == 0)
{
- lexptr += 4;
+ state->lexptr += 4;
return CONSTRUCTION_IN;
}
- if (lexptr[1] < '0' || lexptr[1] > '9')
+ if (state->lexptr[1] < '0' || state->lexptr[1] > '9')
{
- lexptr++;
+ state->lexptr++;
return '-';
}
- /* FALL THRU into number case. */
+ /* FALL THRU. */
try_number:
case '0':
else if (! ISALNUM (*p))
break;
}
- toktype = parse_number (tokstart, p - tokstart, got_dot|got_e);
+ toktype = state->parse_number (tokstart, p - tokstart, got_dot|got_e,
+ lvalp);
if (toktype == ERROR)
{
char *err_copy = (char *) alloca (p - tokstart + 1);
memcpy (err_copy, tokstart, p - tokstart);
err_copy[p - tokstart] = 0;
- yyerror ("invalid number");
+ yyerror (state, _("invalid number"));
return ERROR;
}
- lexptr = p;
+ state->lexptr = p;
return toktype;
}
case '+':
HANDLE_TOKEN2 ("+=", ASSIGN_MODIFY);
HANDLE_TOKEN2 ("++", INCREMENT);
- lexptr++;
+ state->lexptr++;
return c;
case '*':
HANDLE_TOKEN2 ("*=", ASSIGN_MODIFY);
- lexptr++;
+ state->lexptr++;
return c;
case '/':
HANDLE_TOKEN2 ("/=", ASSIGN_MODIFY);
- lexptr++;
+ state->lexptr++;
return c;
case '%':
HANDLE_TOKEN2 ("%=", ASSIGN_MODIFY);
- lexptr++;
+ state->lexptr++;
return c;
case '|':
HANDLE_TOKEN2 ("|=", ASSIGN_MODIFY);
HANDLE_TOKEN2 ("||", OROR);
- lexptr++;
+ state->lexptr++;
return c;
case '&':
HANDLE_TOKEN2 ("&=", ASSIGN_MODIFY);
HANDLE_TOKEN2 ("&&", ANDAND);
- lexptr++;
+ state->lexptr++;
return c;
case '^':
HANDLE_TOKEN2 ("^=", ASSIGN_MODIFY);
- lexptr++;
+ state->lexptr++;
return c;
case '!':
HANDLE_TOKEN2 ("!=", NOTEQUAL);
- lexptr++;
+ state->lexptr++;
return c;
case '<':
HANDLE_TOKEN3 ("<<=", ASSIGN_MODIFY);
HANDLE_TOKEN2 ("<=", LEQ);
HANDLE_TOKEN2 ("<<", LSH);
- lexptr++;
+ state->lexptr++;
return c;
case '>':
HANDLE_TOKEN3 (">>=", ASSIGN_MODIFY);
HANDLE_TOKEN2 (">=", GEQ);
HANDLE_TOKEN2 (">>", RSH);
- lexptr++;
+ state->lexptr++;
return c;
case '=':
HANDLE_TOKEN2 ("==", EQUAL);
- lexptr++;
+ state->lexptr++;
return c;
case ':':
HANDLE_TOKEN2 ("::", COLONCOLON);
- lexptr++;
+ state->lexptr++;
return c;
case '[':
case '{':
case '}':
symbol:
- lexptr++;
+ state->lexptr++;
return c;
case '"':
/* These can't occur in C++ names. */
- yyerror ("unexpected string literal");
+ yyerror (state, _("unexpected string literal"));
return ERROR;
}
- if (!(c == '_' || c == '$' || ISALPHA (c)))
+ if (!(c == '_' || c == '$' || c_ident_is_alpha (c)))
{
/* We must have come across a bad character (e.g. ';'). */
- yyerror ("invalid character");
+ yyerror (state, _("invalid character"));
return ERROR;
}
namelen = 0;
do
c = tokstart[++namelen];
- while (ISALNUM (c) || c == '_' || c == '$');
+ while (c_ident_is_alnum (c) || c == '_' || c == '$');
- lexptr += namelen;
+ state->lexptr += namelen;
/* Catch specific keywords. Notice that some of the keywords contain
spaces, and are sorted by the length of the first word. They must
case 12:
if (strncmp (tokstart, "construction vtable for ", 24) == 0)
{
- lexptr = tokstart + 24;
+ state->lexptr = tokstart + 24;
return CONSTRUCTION_VTABLE;
}
if (strncmp (tokstart, "dynamic_cast", 12) == 0)
if (strncmp (tokstart, "global constructors keyed to ", 29) == 0)
{
const char *p;
- lexptr = tokstart + 29;
- yylval.typed_val_int.val = GLOBAL_CONSTRUCTORS;
+ state->lexptr = tokstart + 29;
+ lvalp->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);
- lexptr = p;
- return GLOBAL;
+ p = symbol_end (state->lexptr);
+ lvalp->comp = state->make_name (state->lexptr, p - state->lexptr);
+ state->lexptr = p;
+ 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;
+ state->lexptr = tokstart + 28;
+ lvalp->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);
- lexptr = p;
- return GLOBAL;
+ p = symbol_end (state->lexptr);
+ lvalp->comp = state->make_name (state->lexptr, p - state->lexptr);
+ state->lexptr = p;
+ return DEMANGLER_SPECIAL;
}
HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE);
break;
}
- yylval.comp = make_name (tokstart, namelen);
+ lvalp->comp = state->make_name (tokstart, namelen);
return NAME;
}
static void
-yyerror (char *msg)
+yyerror (cpname_state *state, const char *msg)
{
- if (global_errmsg)
+ if (state->global_errmsg)
return;
- error_lexptr = prev_lexptr;
- global_errmsg = msg ? msg : "parse error";
+ state->error_lexptr = state->prev_lexptr;
+ state->global_errmsg = msg ? msg : "parse error";
}
/* 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
+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
cplus_demangle_print does not, specifically the global destructor
and constructor labels. */
-char *
+gdb::unique_xmalloc_ptr<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)
+ char *res = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI,
+ result, estimated_len, &err);
+ return gdb::unique_xmalloc_ptr<char> (res);
+}
+
+/* Constructor for demangle_parse_info. */
+
+demangle_parse_info::demangle_parse_info ()
+: info (NULL),
+ tree (NULL)
+{
+ obstack_init (&obstack);
+}
+
+/* Destructor for demangle_parse_info. */
+
+demangle_parse_info::~demangle_parse_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 (&obstack, NULL);
+}
- if (prefix == NULL)
- return str;
+/* 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.
- buf = malloc (strlen (str) + strlen (prefix) + 1);
- strcpy (buf, prefix);
- strcat (buf, str);
- free (str);
- return (buf);
+ 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;
}
/* 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). */
+ a structure containing the root of the new tree is returned. On
+ error, NULL is returned, and an error message will be set in
+ *ERRMSG. */
-struct demangle_component *
-cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
+struct std::unique_ptr<demangle_parse_info>
+cp_demangled_name_to_comp (const char *demangled_name,
+ std::string *errmsg)
{
- static char errbuf[60];
- struct demangle_component *result;
+ cpname_state state;
+
+ state.prev_lexptr = state.lexptr = demangled_name;
+ state.error_lexptr = NULL;
+ state.global_errmsg = NULL;
- prev_lexptr = lexptr = demangled_name;
- error_lexptr = NULL;
- global_errmsg = NULL;
+ state.demangle_info = allocate_info ();
- allocate_info ();
+ std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
+ result->info = state.demangle_info;
- if (yyparse ())
+ if (yyparse (&state))
{
- if (global_errmsg && errmsg)
- {
- snprintf (errbuf, sizeof (errbuf) - 2, "%s, near `%s",
- global_errmsg, error_lexptr);
- strcat (errbuf, "'");
- *errmsg = errbuf;
- }
+ if (state.global_errmsg && errmsg)
+ *errmsg = state.global_errmsg;
return NULL;
}
- result = global_result;
- global_result = NULL;
+ result->tree = state.global_result;
return 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;
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
main (int argc, char **argv)
{
- char *str2, *extra_chars = "", c;
+ char *str2, *extra_chars, c;
char buf[65536];
int arg;
- const char *errmsg;
- struct demangle_component *result;
arg = 1;
if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
if (argv[arg] == NULL)
while (fgets (buf, 65536, stdin) != NULL)
{
- int len;
buf[strlen (buf) - 1] = 0;
/* Use DMGL_VERBOSE to get expanded standard substitutions. */
c = trim_chars (buf, &extra_chars);
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
printf ("%s\n", buf);
continue;
}
- result = cp_demangled_name_to_comp (str2, &errmsg);
+
+ std::string errmsg;
+ std::unique_ptr<demangle_parse_info> result
+ = cp_demangled_name_to_comp (str2, &errmsg);
if (result == NULL)
{
- fputs (errmsg, stderr);
+ fputs (errmsg.c_str (), stderr);
fputc ('\n', stderr);
continue;
}
- cp_print (result);
+ cp_print (result->tree);
free (str2);
if (c)
}
else
{
- result = cp_demangled_name_to_comp (argv[arg], &errmsg);
+ std::string errmsg;
+ std::unique_ptr<demangle_parse_info> result
+ = cp_demangled_name_to_comp (argv[arg], &errmsg);
if (result == NULL)
{
- fputs (errmsg, stderr);
+ fputs (errmsg.c_str (), stderr);
fputc ('\n', stderr);
return 0;
}
- cp_print (result);
+ cp_print (result->tree);
putchar ('\n');
}
return 0;