This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA 3/5] Make cp-name-parser.y a pure parser


This changes cp-name-parser.y to be a pure parser.

Originally I had thought that doing this would mean that gdb would
always require Bison.  However, I've learned that Byacc supports some
of the Bison extensions in this area.  So, the new code ought to work
reasonably well with both.

Note that the Byacc documentations says:

    %pure-parser
        Most variables (other than yydebug and yynerrs) are allocated
        on the stack within yyparse, making the parser reasonably
        reentrant.

In our case this is ok, first because gdb does not yet actualy require
reentrancy, and second because gdb does not use yynerrs.

2018-05-30  Tom Tromey  <tom@tromey.com>

	* cp-name-parser.y: Use %pure-parser, %lex-param, and
	%parse-param.
	(lexptr, prev_lexptr, error_lexptr, global_errmsg, demangle_info)
	(global_result): Remove globals.
	(struct cpname_state): New.
	(yyparse): Don't declare.
	(yylex, yyerror): Move declarations after %union.
	(d_grab, fill_comp, make_operator, make_dtor, make_builtin_type)
	(make_name): Add state parameter.
	Update all callers.
	(d_qualify, d_int_type, d_unary, d_binary, parse_number) Add state
	parameter.
	(HANDLE_QUAL, HANDLE_SPECIAL, HANDLE_TOKEN2, HANDLE_TOKEN3):
	Update.
	(yylex): Add lvalp, state parameters.
	(yyerror): Add state parameter.
	(cp_demangled_name_to_comp): Update.
---
 gdb/ChangeLog        |  20 ++
 gdb/cp-name-parser.y | 588 ++++++++++++++++++++++++++-------------------------
 2 files changed, 324 insertions(+), 284 deletions(-)

diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index 043f311cc0e..b66257513d6 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -27,6 +27,14 @@
    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"
@@ -45,17 +53,6 @@ extern void parser_fprintf (FILE *, const char *, ...) ATTRIBUTE_PRINTF (2, 3);
 #define GDB_YY_REMAP_PREFIX cpname
 #include "yy-remap.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;
-
 /* The components built by the parser are allocated ahead of time,
    and cached in this structure.  */
 
@@ -67,46 +64,57 @@ struct demangle_info {
   struct demangle_component comps[ALLOC_CHUNK];
 };
 
-static struct demangle_info *demangle_info;
+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;
+};
 
 static struct demangle_component *
-d_grab (void)
+d_grab (cpname_state *state)
 {
   struct demangle_info *more;
 
-  if (demangle_info->used >= ALLOC_CHUNK)
+  if (state->demangle_info->used >= ALLOC_CHUNK)
     {
-      if (demangle_info->next == NULL)
+      if (state->demangle_info->next == NULL)
 	{
 	  more = XNEW (struct demangle_info);
 	  more->next = NULL;
-	  demangle_info->next = more;
+	  state->demangle_info->next = more;
 	}
       else
-	more = demangle_info->next;
+	more = state->demangle_info->next;
 
       more->used = 0;
-      demangle_info = more;
+      state->demangle_info = more;
     }
-  return &demangle_info->comps[demangle_info->used++];
+  return &state->demangle_info->comps[state->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,
+static struct demangle_component *d_qualify (cpname_state *state,
+					     struct demangle_component *, int,
 					     int);
 
-static struct demangle_component *d_int_type (int);
+static struct demangle_component *d_int_type (cpname_state *state, int);
 
-static struct demangle_component *d_unary (const char *,
+static struct demangle_component *d_unary (cpname_state *state, const char *,
 					   struct demangle_component *);
-static struct demangle_component *d_binary (const char *,
+static struct demangle_component *d_binary (cpname_state *state, const char *,
 					    struct demangle_component *,
 					    struct demangle_component *);
 
@@ -126,10 +134,6 @@ static struct demangle_component *d_binary (const char *,
 #define INT_SIGNED	(1 << 4)
 #define INT_UNSIGNED	(1 << 5)
 
-int yyparse (void);
-static int yylex (void);
-static void yyerror (const char *);
-
 /* Enable yydebug for the stand-alone parser.  */
 #ifdef TEST_CPNAMES
 # define YYDEBUG	1
@@ -139,10 +143,11 @@ static void yyerror (const char *);
    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,
+fill_comp (cpname_state *state,
+	   enum demangle_component_type d_type, struct demangle_component *lhs,
 	   struct demangle_component *rhs)
 {
-  struct demangle_component *ret = d_grab ();
+  struct demangle_component *ret = d_grab (state);
   int i;
 
   i = cplus_demangle_fill_component (ret, d_type, lhs, rhs);
@@ -152,9 +157,9 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
 }
 
 static struct demangle_component *
-make_operator (const char *name, int args)
+make_operator (cpname_state *state, const char *name, int args)
 {
-  struct demangle_component *ret = d_grab ();
+  struct demangle_component *ret = d_grab (state);
   int i;
 
   i = cplus_demangle_fill_operator (ret, name, args);
@@ -164,9 +169,10 @@ make_operator (const char *name, int args)
 }
 
 static struct demangle_component *
-make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
+make_dtor (cpname_state *state, enum gnu_v3_dtor_kinds kind,
+	   struct demangle_component *name)
 {
-  struct demangle_component *ret = d_grab ();
+  struct demangle_component *ret = d_grab (state);
   int i;
 
   i = cplus_demangle_fill_dtor (ret, kind, name);
@@ -176,9 +182,9 @@ make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
 }
 
 static struct demangle_component *
-make_builtin_type (const char *name)
+make_builtin_type (cpname_state *state, const char *name)
 {
-  struct demangle_component *ret = d_grab ();
+  struct demangle_component *ret = d_grab (state);
   int i;
 
   i = cplus_demangle_fill_builtin_type (ret, name);
@@ -188,9 +194,9 @@ make_builtin_type (const char *name)
 }
 
 static struct demangle_component *
-make_name (const char *name, int len)
+make_name (cpname_state *state, const char *name, int len)
 {
-  struct demangle_component *ret = d_grab ();
+  struct demangle_component *ret = d_grab (state);
   int i;
 
   i = cplus_demangle_fill_name (ret, name, len);
@@ -224,6 +230,11 @@ make_name (const char *name, int len)
     const char *opname;
   }
 
+%{
+static int yylex (YYSTYPE *, cpname_state *);
+static void yyerror (cpname_state *, const char *);
+%}
+
 %type <comp> exp exp1 type start start_opt oper colon_name
 %type <comp> unqualified_name colon_ext_name
 %type <comp> templ template_arg
@@ -320,7 +331,7 @@ make_name (const char *name, int len)
 %%
 
 result		:	start
-			{ global_result = $1; }
+			{ state->global_result = $1; }
 		;
 
 start		:	type
@@ -350,15 +361,20 @@ function
 		   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); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME,
+					  $1, $2.comp);
+			  if ($3)
+			    $$ = fill_comp (state,
+					    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); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+			  if ($3) $$ = fill_comp (state, DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
 
 		|	conversion_op_name start_opt
 			{ $$ = $1.comp;
-			  if ($2) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
+			  if ($2) $$ = fill_comp (state, DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
 		|	conversion_op_name abstract_declarator_fn
 			{ if ($2.last)
 			    {
@@ -370,102 +386,102 @@ function
 			    }
 			  /* If we have an arglist, build a function type.  */
 			  if ($2.fn.comp)
-			    $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1.comp, $2.fn.comp);
+			    $$ = fill_comp (state, 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) $$ = fill_comp (state, DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2.start);
 			}
 		;
 
 demangler_special
 		:	DEMANGLER_SPECIAL start
-			{ $$ = fill_comp ((enum demangle_component_type) $1, $2, NULL); }
+			{ $$ = fill_comp (state, (enum demangle_component_type) $1, $2, NULL); }
 		|	CONSTRUCTION_VTABLE start CONSTRUCTION_IN start
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
 		;
 
 oper	:	OPERATOR NEW
 			{
 			  /* Match the whitespacing of cplus_demangle_operators.
 			     It would abort on unrecognized string otherwise.  */
-			  $$ = make_operator ("new", 3);
+			  $$ = make_operator (state, "new", 3);
 			}
 		|	OPERATOR DELETE
 			{
 			  /* Match the whitespacing of cplus_demangle_operators.
 			     It would abort on unrecognized string otherwise.  */
-			  $$ = make_operator ("delete ", 1);
+			  $$ = make_operator (state, "delete ", 1);
 			}
 		|	OPERATOR NEW '[' ']'
 			{
 			  /* Match the whitespacing of cplus_demangle_operators.
 			     It would abort on unrecognized string otherwise.  */
-			  $$ = make_operator ("new[]", 3);
+			  $$ = make_operator (state, "new[]", 3);
 			}
 		|	OPERATOR DELETE '[' ']'
 			{
 			  /* Match the whitespacing of cplus_demangle_operators.
 			     It would abort on unrecognized string otherwise.  */
-			  $$ = make_operator ("delete[] ", 1);
+			  $$ = make_operator (state, "delete[] ", 1);
 			}
 		|	OPERATOR '+'
-			{ $$ = make_operator ("+", 2); }
+			{ $$ = make_operator (state, "+", 2); }
 		|	OPERATOR '-'
-			{ $$ = make_operator ("-", 2); }
+			{ $$ = make_operator (state, "-", 2); }
 		|	OPERATOR '*'
-			{ $$ = make_operator ("*", 2); }
+			{ $$ = make_operator (state, "*", 2); }
 		|	OPERATOR '/'
-			{ $$ = make_operator ("/", 2); }
+			{ $$ = make_operator (state, "/", 2); }
 		|	OPERATOR '%'
-			{ $$ = make_operator ("%", 2); }
+			{ $$ = make_operator (state, "%", 2); }
 		|	OPERATOR '^'
-			{ $$ = make_operator ("^", 2); }
+			{ $$ = make_operator (state, "^", 2); }
 		|	OPERATOR '&'
-			{ $$ = make_operator ("&", 2); }
+			{ $$ = make_operator (state, "&", 2); }
 		|	OPERATOR '|'
-			{ $$ = make_operator ("|", 2); }
+			{ $$ = make_operator (state, "|", 2); }
 		|	OPERATOR '~'
-			{ $$ = make_operator ("~", 1); }
+			{ $$ = make_operator (state, "~", 1); }
 		|	OPERATOR '!'
-			{ $$ = make_operator ("!", 1); }
+			{ $$ = make_operator (state, "!", 1); }
 		|	OPERATOR '='
-			{ $$ = make_operator ("=", 2); }
+			{ $$ = make_operator (state, "=", 2); }
 		|	OPERATOR '<'
-			{ $$ = make_operator ("<", 2); }
+			{ $$ = make_operator (state, "<", 2); }
 		|	OPERATOR '>'
-			{ $$ = make_operator (">", 2); }
+			{ $$ = make_operator (state, ">", 2); }
 		|	OPERATOR ASSIGN_MODIFY
-			{ $$ = make_operator ($2, 2); }
+			{ $$ = make_operator (state, $2, 2); }
 		|	OPERATOR LSH
-			{ $$ = make_operator ("<<", 2); }
+			{ $$ = make_operator (state, "<<", 2); }
 		|	OPERATOR RSH
-			{ $$ = make_operator (">>", 2); }
+			{ $$ = make_operator (state, ">>", 2); }
 		|	OPERATOR EQUAL
-			{ $$ = make_operator ("==", 2); }
+			{ $$ = make_operator (state, "==", 2); }
 		|	OPERATOR NOTEQUAL
-			{ $$ = make_operator ("!=", 2); }
+			{ $$ = make_operator (state, "!=", 2); }
 		|	OPERATOR LEQ
-			{ $$ = make_operator ("<=", 2); }
+			{ $$ = make_operator (state, "<=", 2); }
 		|	OPERATOR GEQ
-			{ $$ = make_operator (">=", 2); }
+			{ $$ = make_operator (state, ">=", 2); }
 		|	OPERATOR ANDAND
-			{ $$ = make_operator ("&&", 2); }
+			{ $$ = make_operator (state, "&&", 2); }
 		|	OPERATOR OROR
-			{ $$ = make_operator ("||", 2); }
+			{ $$ = make_operator (state, "||", 2); }
 		|	OPERATOR INCREMENT
-			{ $$ = make_operator ("++", 1); }
+			{ $$ = make_operator (state, "++", 1); }
 		|	OPERATOR DECREMENT
-			{ $$ = make_operator ("--", 1); }
+			{ $$ = make_operator (state, "--", 1); }
 		|	OPERATOR ','
-			{ $$ = make_operator (",", 2); }
+			{ $$ = make_operator (state, ",", 2); }
 		|	OPERATOR ARROW '*'
-			{ $$ = make_operator ("->*", 2); }
+			{ $$ = make_operator (state, "->*", 2); }
 		|	OPERATOR ARROW
-			{ $$ = make_operator ("->", 2); }
+			{ $$ = make_operator (state, "->", 2); }
 		|	OPERATOR '(' ')'
-			{ $$ = make_operator ("()", 2); }
+			{ $$ = make_operator (state, "()", 2); }
 		|	OPERATOR '[' ']'
-			{ $$ = make_operator ("[]", 2); }
+			{ $$ = make_operator (state, "[]", 2); }
 		;
 
 		/* Conversion operators.  We don't try to handle some of
@@ -473,7 +489,7 @@ oper	:	OPERATOR NEW
 		   since it's not clear that it's parseable.  */
 conversion_op
 		:	OPERATOR typespec_2
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
 		;
 
 conversion_op_name
@@ -501,9 +517,9 @@ conversion_op_name
 /* This accepts certain invalid placements of '~'.  */
 unqualified_name:	oper
 		|	oper '<' template_params '>'
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
 		|	'~' NAME
-			{ $$ = make_dtor (gnu_v3_complete_object_dtor, $2); }
+			{ $$ = make_dtor (state, gnu_v3_complete_object_dtor, $2); }
 		;
 
 /* This rule is used in name and nested_name, and expanded inline there
@@ -544,21 +560,21 @@ ext_only_name	:	nested_name unqualified_name
 		;
 
 nested_name	:	NAME COLONCOLON
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
 			  $$.last = $$.comp;
 			}
 		|	nested_name NAME COLONCOLON
 			{ $$.comp = $1.comp;
-			  d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
+			  d_right ($1.last) = fill_comp (state, DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
 			  $$.last = d_right ($1.last);
 			}
 		|	templ COLONCOLON
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
 			  $$.last = $$.comp;
 			}
 		|	nested_name templ COLONCOLON
 			{ $$.comp = $1.comp;
-			  d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
+			  d_right ($1.last) = fill_comp (state, DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
 			  $$.last = d_right ($1.last);
 			}
 		;
@@ -566,15 +582,15 @@ nested_name	:	NAME COLONCOLON
 /* DEMANGLE_COMPONENT_TEMPLATE */
 /* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */
 templ	:	NAME '<' template_params '>'
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
 		;
 
 template_params	:	template_arg
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $1, NULL);
+			{ $$.comp = fill_comp (state, 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 = fill_comp (state, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $3, NULL);
 			  $$.last = &d_right (*$1.last);
 			}
 		;
@@ -589,36 +605,36 @@ template_arg	:	typespec_2
 			  *$2.last = $1;
 			}
 		|	'&' start
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY, make_operator (state, "&", 1), $2); }
 		|	'&' '(' start ')'
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY, make_operator (state, "&", 1), $3); }
 		|	exp
 		;
 
 function_args	:	typespec_2
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $1, NULL);
+			{ $$.comp = fill_comp (state, 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 = fill_comp (state, 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 = fill_comp (state, 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 = fill_comp (state, 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 ("..."),
+			    = fill_comp (state, DEMANGLE_COMPONENT_ARGLIST,
+					   make_builtin_type (state, "..."),
 					   NULL);
 			  $$.comp = $1.comp;
 			  $$.last = &d_right (*$1.last);
@@ -626,17 +642,17 @@ function_args	:	typespec_2
 		;
 
 function_arglist:	'(' function_args ')' qualifiers_opt %prec NAME
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
 			  $$.last = &d_left ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $4, 1); }
+			  $$.comp = d_qualify (state, $$.comp, $4, 1); }
 		|	'(' VOID ')' qualifiers_opt
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
 			  $$.last = &d_left ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $4, 1); }
+			  $$.comp = d_qualify (state, $$.comp, $4, 1); }
 		|	'(' ')' qualifiers_opt
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
 			  $$.last = &d_left ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $3, 1); }
+			  $$.comp = d_qualify (state, $$.comp, $3, 1); }
 		;
 
 /* Should do something about DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL */
@@ -681,50 +697,50 @@ int_seq		:	int_part
 		;
 
 builtin_type	:	int_seq
-			{ $$ = d_int_type ($1); }
+			{ $$ = d_int_type (state, $1); }
 		|	FLOAT_KEYWORD
-			{ $$ = make_builtin_type ("float"); }
+			{ $$ = make_builtin_type (state, "float"); }
 		|	DOUBLE_KEYWORD
-			{ $$ = make_builtin_type ("double"); }
+			{ $$ = make_builtin_type (state, "double"); }
 		|	LONG DOUBLE_KEYWORD
-			{ $$ = make_builtin_type ("long double"); }
+			{ $$ = make_builtin_type (state, "long double"); }
 		|	BOOL
-			{ $$ = make_builtin_type ("bool"); }
+			{ $$ = make_builtin_type (state, "bool"); }
 		|	WCHAR_T
-			{ $$ = make_builtin_type ("wchar_t"); }
+			{ $$ = make_builtin_type (state, "wchar_t"); }
 		|	VOID
-			{ $$ = make_builtin_type ("void"); }
+			{ $$ = make_builtin_type (state, "void"); }
 		;
 
 ptr_operator	:	'*' qualifiers_opt
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_POINTER, NULL, NULL);
 			  $$.last = &d_left ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $2, 0); }
+			  $$.comp = d_qualify (state, $$.comp, $2, 0); }
 		/* g++ seems to allow qualifiers after the reference?  */
 		|	'&'
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_REFERENCE, NULL, NULL);
 			  $$.last = &d_left ($$.comp); }
 		|	ANDAND
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_RVALUE_REFERENCE, NULL, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_RVALUE_REFERENCE, NULL, NULL);
 			  $$.last = &d_left ($$.comp); }
 		|	nested_name '*' qualifiers_opt
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $1.comp, NULL);
+			{ $$.comp = fill_comp (state, 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);
 			  $$.last = &d_right ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $3, 0); }
+			  $$.comp = d_qualify (state, $$.comp, $3, 0); }
 		|	COLONCOLON nested_name '*' qualifiers_opt
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $2.comp, NULL);
+			{ $$.comp = fill_comp (state, 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);
 			  $$.last = &d_right ($$.comp);
-			  $$.comp = d_qualify ($$.comp, $4, 0); }
+			  $$.comp = d_qualify (state, $$.comp, $4, 0); }
 		;
 
 array_indicator	:	'[' ']'
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); }
 		|	'[' INT ']'
-			{ $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); }
+			{ $$ = fill_comp (state, DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); }
 		;
 
 /* Details of this approach inspired by the G++ < 3.4 parser.  */
@@ -738,29 +754,29 @@ typespec	:	builtin_type
 */
 
 typespec_2	:	builtin_type qualifiers
-			{ $$ = d_qualify ($1, $2, 0); }
+			{ $$ = d_qualify (state, $1, $2, 0); }
 		|	builtin_type
 		|	qualifiers builtin_type qualifiers
-			{ $$ = d_qualify ($2, $1 | $3, 0); }
+			{ $$ = d_qualify (state, $2, $1 | $3, 0); }
 		|	qualifiers builtin_type
-			{ $$ = d_qualify ($2, $1, 0); }
+			{ $$ = d_qualify (state, $2, $1, 0); }
 
 		|	name qualifiers
-			{ $$ = d_qualify ($1, $2, 0); }
+			{ $$ = d_qualify (state, $1, $2, 0); }
 		|	name
 		|	qualifiers name qualifiers
-			{ $$ = d_qualify ($2, $1 | $3, 0); }
+			{ $$ = d_qualify (state, $2, $1 | $3, 0); }
 		|	qualifiers name
-			{ $$ = d_qualify ($2, $1, 0); }
+			{ $$ = d_qualify (state, $2, $1, 0); }
 
 		|	COLONCOLON name qualifiers
-			{ $$ = d_qualify ($2, $3, 0); }
+			{ $$ = d_qualify (state, $2, $3, 0); }
 		|	COLONCOLON name
 			{ $$ = $2; }
 		|	qualifiers COLONCOLON name qualifiers
-			{ $$ = d_qualify ($3, $1 | $4, 0); }
+			{ $$ = d_qualify (state, $3, $1 | $4, 0); }
 		|	qualifiers COLONCOLON name
-			{ $$ = d_qualify ($3, $1, 0); }
+			{ $$ = d_qualify (state, $3, $1, 0); }
 		;
 
 abstract_declarator
@@ -877,7 +893,7 @@ direct_declarator
 			  $$.last = &d_right ($2);
 			}
 		|	colon_ext_name
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
 			  $$.last = &d_right ($$.comp);
 			}
 		;
@@ -893,7 +909,7 @@ declarator_1	:	ptr_operator declarator_1
 			  $$.last = $1.last;
 			  *$2.last = $1.comp; }
 		|	colon_ext_name
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
+			{ $$.comp = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
 			  $$.last = &d_right ($$.comp);
 			}
 		|	direct_declarator_1
@@ -905,15 +921,15 @@ declarator_1	:	ptr_operator 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 = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
 			  $$.last = $2.last;
-			  $$.comp = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
+			  $$.comp = fill_comp (state, 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 = fill_comp (state, DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
 			}
 		;
 
@@ -933,11 +949,11 @@ direct_declarator_1
 			  $$.last = &d_right ($2);
 			}
 		|	colon_ext_name function_arglist
-			{ $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+			{ $$.comp = fill_comp (state, 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 = fill_comp (state, DEMANGLE_COMPONENT_TYPED_NAME, $1, $2);
 			  $$.last = &d_right ($2);
 			}
 		;
@@ -952,29 +968,29 @@ exp1	:	exp
 	;
 
 exp1	:	exp '>' exp
-		{ $$ = d_binary (">", $1, $3); }
+		{ $$ = d_binary (state, ">", $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); }
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY, make_operator (state, "&", 1), $2); }
 	|	'&' '(' start ')'
-		{ $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY, make_operator (state, "&", 1), $3); }
 	;
 
 /* Expressions, not including the comma operator.  */
 exp	:	'-' exp    %prec UNARY
-		{ $$ = d_unary ("-", $2); }
+		{ $$ = d_unary (state, "-", $2); }
 	;
 
 exp	:	'!' exp    %prec UNARY
-		{ $$ = d_unary ("!", $2); }
+		{ $$ = d_unary (state, "!", $2); }
 	;
 
 exp	:	'~' exp    %prec UNARY
-		{ $$ = d_unary ("~", $2); }
+		{ $$ = d_unary (state, "~", $2); }
 	;
 
 /* Casts.  First your normal C-style cast.  If exp is a LITERAL, just change
@@ -988,8 +1004,8 @@ exp	:	'(' type ')' exp  %prec UNARY
 		      d_left ($4) = $2;
 		    }
 		  else
-		    $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-				      fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL),
+		    $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY,
+				      fill_comp (state, DEMANGLE_COMPONENT_CAST, $2, NULL),
 				      $4);
 		}
 	;
@@ -997,22 +1013,22 @@ exp	:	'(' type ')' exp  %prec UNARY
 /* 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),
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY,
+				    fill_comp (state, 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),
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY,
+				    fill_comp (state, 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),
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_UNARY,
+				    fill_comp (state, DEMANGLE_COMPONENT_CAST, $3, NULL),
 				    $6);
 		}
 	;
@@ -1030,86 +1046,86 @@ exp	:	REINTERPRET_CAST '<' type '>' '(' exp1 ')' %prec UNARY
 /* Binary operators in order of decreasing precedence.  */
 
 exp	:	exp '*' exp
-		{ $$ = d_binary ("*", $1, $3); }
+		{ $$ = d_binary (state, "*", $1, $3); }
 	;
 
 exp	:	exp '/' exp
-		{ $$ = d_binary ("/", $1, $3); }
+		{ $$ = d_binary (state, "/", $1, $3); }
 	;
 
 exp	:	exp '%' exp
-		{ $$ = d_binary ("%", $1, $3); }
+		{ $$ = d_binary (state, "%", $1, $3); }
 	;
 
 exp	:	exp '+' exp
-		{ $$ = d_binary ("+", $1, $3); }
+		{ $$ = d_binary (state, "+", $1, $3); }
 	;
 
 exp	:	exp '-' exp
-		{ $$ = d_binary ("-", $1, $3); }
+		{ $$ = d_binary (state, "-", $1, $3); }
 	;
 
 exp	:	exp LSH exp
-		{ $$ = d_binary ("<<", $1, $3); }
+		{ $$ = d_binary (state, "<<", $1, $3); }
 	;
 
 exp	:	exp RSH exp
-		{ $$ = d_binary (">>", $1, $3); }
+		{ $$ = d_binary (state, ">>", $1, $3); }
 	;
 
 exp	:	exp EQUAL exp
-		{ $$ = d_binary ("==", $1, $3); }
+		{ $$ = d_binary (state, "==", $1, $3); }
 	;
 
 exp	:	exp NOTEQUAL exp
-		{ $$ = d_binary ("!=", $1, $3); }
+		{ $$ = d_binary (state, "!=", $1, $3); }
 	;
 
 exp	:	exp LEQ exp
-		{ $$ = d_binary ("<=", $1, $3); }
+		{ $$ = d_binary (state, "<=", $1, $3); }
 	;
 
 exp	:	exp GEQ exp
-		{ $$ = d_binary (">=", $1, $3); }
+		{ $$ = d_binary (state, ">=", $1, $3); }
 	;
 
 exp	:	exp '<' exp
-		{ $$ = d_binary ("<", $1, $3); }
+		{ $$ = d_binary (state, "<", $1, $3); }
 	;
 
 exp	:	exp '&' exp
-		{ $$ = d_binary ("&", $1, $3); }
+		{ $$ = d_binary (state, "&", $1, $3); }
 	;
 
 exp	:	exp '^' exp
-		{ $$ = d_binary ("^", $1, $3); }
+		{ $$ = d_binary (state, "^", $1, $3); }
 	;
 
 exp	:	exp '|' exp
-		{ $$ = d_binary ("|", $1, $3); }
+		{ $$ = d_binary (state, "|", $1, $3); }
 	;
 
 exp	:	exp ANDAND exp
-		{ $$ = d_binary ("&&", $1, $3); }
+		{ $$ = d_binary (state, "&&", $1, $3); }
 	;
 
 exp	:	exp OROR exp
-		{ $$ = d_binary ("||", $1, $3); }
+		{ $$ = d_binary (state, "||", $1, $3); }
 	;
 
 /* Not 100% sure these are necessary, but they're harmless.  */
 exp	:	exp ARROW NAME
-		{ $$ = d_binary ("->", $1, $3); }
+		{ $$ = d_binary (state, "->", $1, $3); }
 	;
 
 exp	:	exp '.' NAME
-		{ $$ = d_binary (".", $1, $3); }
+		{ $$ = d_binary (state, ".", $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)));
+		{ $$ = fill_comp (state, DEMANGLE_COMPONENT_TRINARY, make_operator (state, "?", 3),
+				    fill_comp (state, DEMANGLE_COMPONENT_TRINARY_ARG1, $1,
+						 fill_comp (state, DEMANGLE_COMPONENT_TRINARY_ARG2, $3, $5)));
 		}
 	;
 			  
@@ -1124,25 +1140,25 @@ exp	:	SIZEOF '(' type ')'	%prec UNARY
 		{
 		  /* Match the whitespacing of cplus_demangle_operators.
 		     It would abort on unrecognized string otherwise.  */
-		  $$ = d_unary ("sizeof ", $3);
+		  $$ = d_unary (state, "sizeof ", $3);
 		}
 	;
 
 /* C++.  */
 exp     :       TRUEKEYWORD    
 		{ struct demangle_component *i;
-		  i = make_name ("1", 1);
-		  $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
-				    make_builtin_type ("bool"),
+		  i = make_name (state, "1", 1);
+		  $$ = fill_comp (state, DEMANGLE_COMPONENT_LITERAL,
+				    make_builtin_type (state, "bool"),
 				    i);
 		}
 	;
 
 exp     :       FALSEKEYWORD   
 		{ struct demangle_component *i;
-		  i = make_name ("0", 1);
-		  $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
-				    make_builtin_type ("bool"),
+		  i = make_name (state, "0", 1);
+		  $$ = fill_comp (state, DEMANGLE_COMPONENT_LITERAL,
+				    make_builtin_type (state, "bool"),
 				    i);
 		}
 	;
@@ -1157,7 +1173,8 @@ exp     :       FALSEKEYWORD
    may already be qualified; duplicate qualifiers are not created.  */
 
 struct demangle_component *
-d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
+d_qualify (cpname_state *state, struct demangle_component *lhs, int qualifiers,
+	   int is_method)
 {
   struct demangle_component **inner_p;
   enum demangle_component_type type;
@@ -1167,7 +1184,7 @@ d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
 #define HANDLE_QUAL(TYPE, MTYPE, QUAL)				\
   if ((qualifiers & QUAL) && (type != TYPE) && (type != MTYPE))	\
     {								\
-      *inner_p = fill_comp (is_method ? MTYPE : TYPE,	\
+      *inner_p = fill_comp (state, is_method ? MTYPE : TYPE,	\
 			      *inner_p, NULL);			\
       inner_p = &d_left (*inner_p);				\
       type = (*inner_p)->type;					\
@@ -1192,7 +1209,7 @@ d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
 /* Return a builtin type corresponding to FLAGS.  */
 
 static struct demangle_component *
-d_int_type (int flags)
+d_int_type (cpname_state *state, int flags)
 {
   const char *name;
 
@@ -1239,24 +1256,25 @@ d_int_type (int flags)
       return NULL;
     }
 
-  return make_builtin_type (name);
+  return make_builtin_type (state, name);
 }
 
 /* Wrapper to create a unary operation.  */
 
 static struct demangle_component *
-d_unary (const char *name, struct demangle_component *lhs)
+d_unary (cpname_state *state, const char *name, struct demangle_component *lhs)
 {
-  return fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator (name, 1), lhs);
+  return fill_comp (state, DEMANGLE_COMPONENT_UNARY, make_operator (state, 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)
+d_binary (cpname_state *state, 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));
+  return fill_comp (state, DEMANGLE_COMPONENT_BINARY, make_operator (state, name, 2),
+		      fill_comp (state, DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
 }
 
 /* Find the end of a symbol name starting at LEXPTR.  */
@@ -1277,7 +1295,8 @@ symbol_end (const char *lexptr)
    YYLVAL.  */
 
 static int
-parse_number (const char *p, int len, int parsed_float)
+parse_number (cpname_state *state, const char *p, int len, int parsed_float,
+	      YYSTYPE *lvalp)
 {
   int unsigned_p = 0;
 
@@ -1314,20 +1333,20 @@ parse_number (const char *p, int len, int parsed_float)
       if (c == 'f')
       	{
       	  len--;
-      	  type = make_builtin_type ("float");
+      	  type = make_builtin_type (state, "float");
       	}
       else if (c == 'l')
 	{
 	  len--;
-	  type = make_builtin_type ("long double");
+	  type = make_builtin_type (state, "long double");
 	}
       else if (ISDIGIT (c) || c == '.')
-	type = make_builtin_type ("double");
+	type = make_builtin_type (state, "double");
       else
 	return ERROR;
 
-      name = make_name (p, len);
-      yylval.comp = fill_comp (literal_type, type, name);
+      name = make_name (state, p, len);
+      lvalp->comp = fill_comp (state, literal_type, type, name);
 
       return FLOAT;
     }
@@ -1356,18 +1375,18 @@ parse_number (const char *p, int len, int parsed_float)
 
   if (long_p == 0)
     {
-      unsigned_type = make_builtin_type ("unsigned int");
-      signed_type = make_builtin_type ("int");
+      unsigned_type = make_builtin_type (state, "unsigned int");
+      signed_type = make_builtin_type (state, "int");
     }
   else if (long_p == 1)
     {
-      unsigned_type = make_builtin_type ("unsigned long");
-      signed_type = make_builtin_type ("long");
+      unsigned_type = make_builtin_type (state, "unsigned long");
+      signed_type = make_builtin_type (state, "long");
     }
   else
     {
-      unsigned_type = make_builtin_type ("unsigned long long");
-      signed_type = make_builtin_type ("long long");
+      unsigned_type = make_builtin_type (state, "unsigned long long");
+      signed_type = make_builtin_type (state, "long long");
     }
 
    if (unsigned_p)
@@ -1375,8 +1394,8 @@ parse_number (const char *p, int len, int parsed_float)
    else
      type = signed_type;
 
-   name = make_name (p, len);
-   yylval.comp = fill_comp (literal_type, type, name);
+   name = make_name (state, p, len);
+   lvalp->comp = fill_comp (state, literal_type, type, name);
 
    return INT;
 }
@@ -1480,39 +1499,39 @@ cp_parse_escape (const char **string_ptr)
 #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;
 
  retry:
-  prev_lexptr = lexptr;
-  tokstart = lexptr;
+  state->prev_lexptr = state->lexptr;
+  tokstart = state->lexptr;
 
   switch (c = *tokstart)
     {
@@ -1522,27 +1541,27 @@ yylex (void)
     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;
 	}
 
@@ -1550,17 +1569,17 @@ yylex (void)
 	 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 = fill_comp (state, DEMANGLE_COMPONENT_LITERAL,
+				 make_builtin_type (state, "char"),
+				 make_name (state, tokstart, state->lexptr - tokstart));
 
       return INT;
 
     case '(':
       if (strncmp (tokstart, "(anonymous namespace)", 21) == 0)
 	{
-	  lexptr += 21;
-	  yylval.comp = make_name ("(anonymous namespace)",
+	  state->lexptr += 21;
+	  lvalp->comp = make_name (state, "(anonymous namespace)",
 				     sizeof "(anonymous namespace)" - 1);
 	  return NAME;
 	}
@@ -1568,18 +1587,18 @@ yylex (void)
 
     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;
@@ -1592,13 +1611,13 @@ yylex (void)
       /* 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.  */
@@ -1659,74 +1678,75 @@ yylex (void)
 	    else if (! ISALNUM (*p))
 	      break;
 	  }
-	toktype = parse_number (tokstart, p - tokstart, got_dot|got_e);
+	toktype = parse_number (state, 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 '[':
@@ -1737,19 +1757,19 @@ yylex (void)
     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 == '$' || c_ident_is_alpha (c)))
     {
       /* We must have come across a bad character (e.g. ';').  */
-      yyerror (_("invalid character"));
+      yyerror (state, _("invalid character"));
       return ERROR;
     }
 
@@ -1759,7 +1779,7 @@ yylex (void)
     c = tokstart[++namelen];
   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
@@ -1773,7 +1793,7 @@ yylex (void)
     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)
@@ -1811,23 +1831,23 @@ yylex (void)
       if (strncmp (tokstart, "global constructors keyed to ", 29) == 0)
 	{
 	  const char *p;
-	  lexptr = tokstart + 29;
-	  yylval.lval = DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS;
+	  state->lexptr = tokstart + 29;
+	  lvalp->lval = DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS;
 	  /* Find the end of the symbol.  */
-	  p = symbol_end (lexptr);
-	  yylval.comp = make_name (lexptr, p - lexptr);
-	  lexptr = p;
+	  p = symbol_end (state->lexptr);
+	  lvalp->comp = make_name (state, 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.lval = DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS;
+	  state->lexptr = tokstart + 28;
+	  lvalp->lval = DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS;
 	  /* Find the end of the symbol.  */
-	  p = symbol_end (lexptr);
-	  yylval.comp = make_name (lexptr, p - lexptr);
-	  lexptr = p;
+	  p = symbol_end (state->lexptr);
+	  lvalp->comp = make_name (state, state->lexptr, p - state->lexptr);
+	  state->lexptr = p;
 	  return DEMANGLER_SPECIAL;
 	}
 
@@ -1884,18 +1904,18 @@ yylex (void)
       break;
     }
 
-  yylval.comp = make_name (tokstart, namelen);
+  lvalp->comp = make_name (state, tokstart, namelen);
   return NAME;
 }
 
 static void
-yyerror (const 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
@@ -1993,25 +2013,25 @@ struct std::unique_ptr<demangle_parse_info>
 cp_demangled_name_to_comp (const char *demangled_name,
 			   std::string *errmsg)
 {
-  prev_lexptr = lexptr = demangled_name;
-  error_lexptr = NULL;
-  global_errmsg = NULL;
+  cpname_state state;
+
+  state.prev_lexptr = state.lexptr = demangled_name;
+  state.error_lexptr = NULL;
+  state.global_errmsg = NULL;
 
-  demangle_info = allocate_info ();
+  state.demangle_info = allocate_info ();
 
   std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
-  result->info = demangle_info;
+  result->info = state.demangle_info;
 
-  if (yyparse ())
+  if (yyparse (&state))
     {
-      if (global_errmsg && errmsg)
-	*errmsg = string_printf ("%s, near `%s'", global_errmsg,
-				 error_lexptr);
+      if (state.global_errmsg && errmsg)
+	*errmsg = state.global_errmsg;
       return NULL;
     }
 
-  result->tree = global_result;
-  global_result = NULL;
+  result->tree = state.global_result;
 
   return result;
 }
-- 
2.13.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]