aboutsummaryrefslogtreecommitdiff
path: root/third_party/gcc_demangler.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/gcc_demangler.c')
-rw-r--r--third_party/gcc_demangler.c4218
1 files changed, 4218 insertions, 0 deletions
diff --git a/third_party/gcc_demangler.c b/third_party/gcc_demangler.c
new file mode 100644
index 00000000..6cfbb19e
--- /dev/null
+++ b/third_party/gcc_demangler.c
@@ -0,0 +1,4218 @@
+#include <string.h>
+#include <stdlib.h>
+
+/* Demangler for g++ V3 ABI.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@wasabisystems.com>.
+
+ This file is part of the libiberty library, which is part of GCC.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combined
+ executable.)
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* This code implements a demangler for the g++ V3 ABI. The ABI is
+ described on this web page:
+ http://www.codesourcery.com/cxx-abi/abi.html#mangling
+
+ This code was written while looking at the demangler written by
+ Alex Samuel <samuel@codesourcery.com>.
+
+ This code first pulls the mangled name apart into a list of
+ components, and then walks the list generating the demangled
+ name.
+
+ This file will normally define the following functions, q.v.:
+ char *cplus_demangle_v3(const char *mangled, int options)
+ char *java_demangle_v3(const char *mangled)
+ enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name)
+ enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name)
+
+ Also, the interface to the component list is public, and defined in
+ demangle.h. The interface consists of these types, which are
+ defined in demangle.h:
+ enum demangle_component_type
+ struct demangle_component
+ and these functions defined in this file:
+ cplus_demangle_fill_name
+ cplus_demangle_fill_extended_operator
+ cplus_demangle_fill_ctor
+ cplus_demangle_fill_dtor
+ cplus_demangle_print
+ and other functions defined in the file cp-demint.c.
+
+ This file also defines some other functions and variables which are
+ only to be used by the file cp-demint.c.
+
+ Preprocessor macros you can define while compiling this file:
+
+ IN_LIBGCC2
+ If defined, this file defines the following function, q.v.:
+ char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
+ int *status)
+ instead of cplus_demangle_v3() and java_demangle_v3().
+
+ IN_GLIBCPP_V3
+ If defined, this file defines only __cxa_demangle(), and no other
+ publically visible functions or variables.
+
+ STANDALONE_DEMANGLER
+ If defined, this file defines a main() function which demangles
+ any arguments, or, if none, demangles stdin.
+
+ CP_DEMANGLE_DEBUG
+ If defined, turns on debugging mode, which prints information on
+ stdout about the mangled string. This is not generally useful.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "ansidecl.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "cp-demangle.h"
+
+/* If IN_GLIBCPP_V3 is defined, some functions are made static. We
+ also rename them via #define to avoid compiler errors when the
+ static definition conflicts with the extern declaration in a header
+ file. */
+#ifdef IN_GLIBCPP_V3
+
+#define CP_STATIC_IF_GLIBCPP_V3 static
+
+#define cplus_demangle_fill_name d_fill_name
+static int d_fill_name (struct demangle_component *, const char *, int);
+
+#define cplus_demangle_fill_extended_operator d_fill_extended_operator
+static int
+d_fill_extended_operator (struct demangle_component *, int,
+ struct demangle_component *);
+
+#define cplus_demangle_fill_ctor d_fill_ctor
+static int
+d_fill_ctor (struct demangle_component *, enum gnu_v3_ctor_kinds,
+ struct demangle_component *);
+
+#define cplus_demangle_fill_dtor d_fill_dtor
+static int
+d_fill_dtor (struct demangle_component *, enum gnu_v3_dtor_kinds,
+ struct demangle_component *);
+
+#define cplus_demangle_mangled_name d_mangled_name
+static struct demangle_component *d_mangled_name (struct d_info *, int);
+
+#define cplus_demangle_type d_type
+static struct demangle_component *d_type (struct d_info *);
+
+#define cplus_demangle_print d_print
+static char *d_print (int, const struct demangle_component *, int, size_t *);
+
+#define cplus_demangle_init_info d_init_info
+static void d_init_info (const char *, int, size_t, struct d_info *);
+
+#else /* ! defined(IN_GLIBCPP_V3) */
+#define CP_STATIC_IF_GLIBCPP_V3
+#endif /* ! defined(IN_GLIBCPP_V3) */
+
+/* See if the compiler supports dynamic arrays. */
+
+#ifdef __GNUC__
+#define CP_DYNAMIC_ARRAYS
+#else
+#ifdef __STDC__
+#ifdef __STDC_VERSION__
+#if __STDC_VERSION__ >= 199901L
+#define CP_DYNAMIC_ARRAYS
+#endif /* __STDC__VERSION >= 199901L */
+#endif /* defined (__STDC_VERSION__) */
+#endif /* defined (__STDC__) */
+#endif /* ! defined (__GNUC__) */
+
+/* We avoid pulling in the ctype tables, to prevent pulling in
+ additional unresolved symbols when this code is used in a library.
+ FIXME: Is this really a valid reason? This comes from the original
+ V3 demangler code.
+
+ As of this writing this file has the following undefined references
+ when compiled with -DIN_GLIBCPP_V3: malloc, realloc, free, memcpy,
+ strcpy, strcat, strlen. */
+
+#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
+#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+/* The prefix prepended by GCC to an identifier represnting the
+ anonymous namespace. */
+#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
+#define ANONYMOUS_NAMESPACE_PREFIX_LEN \
+ (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1)
+
+/* Information we keep for the standard substitutions. */
+
+struct d_standard_sub_info
+{
+ /* The code for this substitution. */
+ char code;
+ /* The simple string it expands to. */
+ const char *simple_expansion;
+ /* The length of the simple expansion. */
+ int simple_len;
+ /* The results of a full, verbose, expansion. This is used when
+ qualifying a constructor/destructor, or when in verbose mode. */
+ const char *full_expansion;
+ /* The length of the full expansion. */
+ int full_len;
+ /* What to set the last_name field of d_info to; NULL if we should
+ not set it. This is only relevant when qualifying a
+ constructor/destructor. */
+ const char *set_last_name;
+ /* The length of set_last_name. */
+ int set_last_name_len;
+};
+
+/* Accessors for subtrees of struct demangle_component. */
+
+#define d_left(dc) ((dc)->u.s_binary.left)
+#define d_right(dc) ((dc)->u.s_binary.right)
+
+/* A list of templates. This is used while printing. */
+
+struct d_print_template
+{
+ /* Next template on the list. */
+ struct d_print_template *next;
+ /* This template. */
+ const struct demangle_component *template_decl;
+};
+
+/* A list of type modifiers. This is used while printing. */
+
+struct d_print_mod
+{
+ /* Next modifier on the list. These are in the reverse of the order
+ in which they appeared in the mangled string. */
+ struct d_print_mod *next;
+ /* The modifier. */
+ const struct demangle_component *mod;
+ /* Whether this modifier was printed. */
+ int printed;
+ /* The list of templates which applies to this modifier. */
+ struct d_print_template *templates;
+};
+
+/* We use this structure to hold information during printing. */
+
+struct d_print_info
+{
+ /* The options passed to the demangler. */
+ int options;
+ /* Buffer holding the result. */
+ char *buf;
+ /* Current length of data in buffer. */
+ size_t len;
+ /* Allocated size of buffer. */
+ size_t alc;
+ /* The current list of templates, if any. */
+ struct d_print_template *templates;
+ /* The current list of modifiers (e.g., pointer, reference, etc.),
+ if any. */
+ struct d_print_mod *modifiers;
+ /* Set to 1 if we had a memory allocation failure. */
+ int allocation_failure;
+};
+
+#define d_print_saw_error(dpi) ((dpi)->buf == NULL)
+
+#define d_append_char(dpi, c) \
+ do \
+ { \
+ if ((dpi)->buf != NULL && (dpi)->len < (dpi)->alc) \
+ (dpi)->buf[(dpi)->len++] = (c); \
+ else \
+ d_print_append_char ((dpi), (c)); \
+ } \
+ while (0)
+
+#define d_append_buffer(dpi, s, l) \
+ do \
+ { \
+ if ((dpi)->buf != NULL && (dpi)->len + (l) <= (dpi)->alc) \
+ { \
+ memcpy ((dpi)->buf + (dpi)->len, (s), (l)); \
+ (dpi)->len += l; \
+ } \
+ else \
+ d_print_append_buffer ((dpi), (s), (l)); \
+ } \
+ while (0)
+
+#define d_append_string_constant(dpi, s) \
+ d_append_buffer (dpi, (s), sizeof (s) - 1)
+
+#define d_last_char(dpi) \
+ ((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1])
+
+#ifdef CP_DEMANGLE_DEBUG
+static void d_dump (struct demangle_component *, int);
+#endif
+
+static struct demangle_component *
+d_make_empty (struct d_info *);
+
+static struct demangle_component *
+d_make_comp (struct d_info *, enum demangle_component_type,
+ struct demangle_component *,
+ struct demangle_component *);
+
+static struct demangle_component *
+d_make_name (struct d_info *, const char *, int);
+
+static struct demangle_component *
+d_make_builtin_type (struct d_info *,
+ const struct demangle_builtin_type_info *);
+
+static struct demangle_component *
+d_make_operator (struct d_info *,
+ const struct demangle_operator_info *);
+
+static struct demangle_component *
+d_make_extended_operator (struct d_info *, int,
+ struct demangle_component *);
+
+static struct demangle_component *
+d_make_ctor (struct d_info *, enum gnu_v3_ctor_kinds,
+ struct demangle_component *);
+
+static struct demangle_component *
+d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds,
+ struct demangle_component *);
+
+static struct demangle_component *
+d_make_template_param (struct d_info *, long);
+
+static struct demangle_component *
+d_make_sub (struct d_info *, const char *, int);
+
+static int
+has_return_type (struct demangle_component *);
+
+static int
+is_ctor_dtor_or_conversion (struct demangle_component *);
+
+static struct demangle_component *d_encoding (struct d_info *, int);
+
+static struct demangle_component *d_name (struct d_info *);
+
+static struct demangle_component *d_nested_name (struct d_info *);
+
+static struct demangle_component *d_prefix (struct d_info *);
+
+static struct demangle_component *d_unqualified_name (struct d_info *);
+
+static struct demangle_component *d_source_name (struct d_info *);
+
+static long d_number (struct d_info *);
+
+static struct demangle_component *d_identifier (struct d_info *, int);
+
+static struct demangle_component *d_operator_name (struct d_info *);
+
+static struct demangle_component *d_special_name (struct d_info *);
+
+static int d_call_offset (struct d_info *, int);
+
+static struct demangle_component *d_ctor_dtor_name (struct d_info *);
+
+static struct demangle_component **
+d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
+
+static struct demangle_component *
+d_function_type (struct d_info *);
+
+static struct demangle_component *
+d_bare_function_type (struct d_info *, int);
+
+static struct demangle_component *
+d_class_enum_type (struct d_info *);
+
+static struct demangle_component *d_array_type (struct d_info *);
+
+static struct demangle_component *
+d_pointer_to_member_type (struct d_info *);
+
+static struct demangle_component *
+d_template_param (struct d_info *);
+
+static struct demangle_component *d_template_args (struct d_info *);
+
+static struct demangle_component *
+d_template_arg (struct d_info *);
+
+static struct demangle_component *d_expression (struct d_info *);
+
+static struct demangle_component *d_expr_primary (struct d_info *);
+
+static struct demangle_component *d_local_name (struct d_info *);
+
+static int d_discriminator (struct d_info *);
+
+static int
+d_add_substitution (struct d_info *, struct demangle_component *);
+
+static struct demangle_component *d_substitution (struct d_info *, int);
+
+static void d_print_resize (struct d_print_info *, size_t);
+
+static void d_print_append_char (struct d_print_info *, int);
+
+static void
+d_print_append_buffer (struct d_print_info *, const char *, size_t);
+
+static void d_print_error (struct d_print_info *);
+
+static void
+d_print_comp (struct d_print_info *, const struct demangle_component *);
+
+static void
+d_print_java_identifier (struct d_print_info *, const char *, int);
+
+static void
+d_print_mod_list (struct d_print_info *, struct d_print_mod *, int);
+
+static void
+d_print_mod (struct d_print_info *, const struct demangle_component *);
+
+static void
+d_print_function_type (struct d_print_info *,
+ const struct demangle_component *,
+ struct d_print_mod *);
+
+static void
+d_print_array_type (struct d_print_info *,
+ const struct demangle_component *,
+ struct d_print_mod *);
+
+static void
+d_print_expr_op (struct d_print_info *, const struct demangle_component *);
+
+static void
+d_print_cast (struct d_print_info *, const struct demangle_component *);
+
+static char *d_demangle (const char *, int, size_t *);
+
+#ifdef CP_DEMANGLE_DEBUG
+
+static void
+d_dump (struct demangle_component *dc, int indent)
+{
+ int i;
+
+ if (dc == NULL)
+ return;
+
+ for (i = 0; i < indent; ++i)
+ putchar (' ');
+
+ switch (dc->type)
+ {
+ case DEMANGLE_COMPONENT_NAME:
+ printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
+ return;
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ printf ("template parameter %ld\n", dc->u.s_number.number);
+ return;
+ case DEMANGLE_COMPONENT_CTOR:
+ printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
+ d_dump (dc->u.s_ctor.name, indent + 2);
+ return;
+ case DEMANGLE_COMPONENT_DTOR:
+ printf ("destructor %d\n", (int) dc->u.s_dtor.kind);
+ d_dump (dc->u.s_dtor.name, indent + 2);
+ return;
+ case DEMANGLE_COMPONENT_SUB_STD:
+ printf ("standard substitution %s\n", dc->u.s_string.string);
+ return;
+ case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ printf ("builtin type %s\n", dc->u.s_builtin.type->name);
+ return;
+ case DEMANGLE_COMPONENT_OPERATOR:
+ printf ("operator %s\n", dc->u.s_operator.op->name);
+ return;
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ printf ("extended operator with %d args\n",
+ dc->u.s_extended_operator.args);
+ d_dump (dc->u.s_extended_operator.name, indent + 2);
+ return;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ printf ("qualified name\n");
+ break;
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ printf ("local name\n");
+ break;
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ printf ("typed name\n");
+ break;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ printf ("template\n");
+ break;
+ case DEMANGLE_COMPONENT_VTABLE:
+ printf ("vtable\n");
+ break;
+ case DEMANGLE_COMPONENT_VTT:
+ printf ("VTT\n");
+ break;
+ case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+ printf ("construction vtable\n");
+ break;
+ case DEMANGLE_COMPONENT_TYPEINFO:
+ printf ("typeinfo\n");
+ break;
+ case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+ printf ("typeinfo name\n");
+ break;
+ case DEMANGLE_COMPONENT_TYPEINFO_FN:
+ printf ("typeinfo function\n");
+ break;
+ case DEMANGLE_COMPONENT_THUNK:
+ printf ("thunk\n");
+ break;
+ case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+ printf ("virtual thunk\n");
+ break;
+ case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+ printf ("covariant thunk\n");
+ break;
+ case DEMANGLE_COMPONENT_JAVA_CLASS:
+ printf ("java class\n");
+ break;
+ case DEMANGLE_COMPONENT_GUARD:
+ printf ("guard\n");
+ break;
+ case DEMANGLE_COMPONENT_REFTEMP:
+ printf ("reference temporary\n");
+ break;
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+ printf ("hidden alias\n");
+ break;
+ case DEMANGLE_COMPONENT_RESTRICT:
+ printf ("restrict\n");
+ break;
+ case DEMANGLE_COMPONENT_VOLATILE:
+ printf ("volatile\n");
+ break;
+ case DEMANGLE_COMPONENT_CONST:
+ printf ("const\n");
+ break;
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ printf ("restrict this\n");
+ break;
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ printf ("volatile this\n");
+ break;
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ printf ("const this\n");
+ break;
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ printf ("vendor type qualifier\n");
+ break;
+ case DEMANGLE_COMPONENT_POINTER:
+ printf ("pointer\n");
+ break;
+ case DEMANGLE_COMPONENT_REFERENCE:
+ printf ("reference\n");
+ break;
+ case DEMANGLE_COMPONENT_COMPLEX:
+ printf ("complex\n");
+ break;
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ printf ("imaginary\n");
+ break;
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ printf ("vendor type\n");
+ break;
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ printf ("function type\n");
+ break;
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ printf ("array type\n");
+ break;
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ printf ("pointer to member type\n");
+ break;
+ case DEMANGLE_COMPONENT_ARGLIST:
+ printf ("argument list\n");
+ break;
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+ printf ("template argument list\n");
+ break;
+ case DEMANGLE_COMPONENT_CAST:
+ printf ("cast\n");
+ break;
+ case DEMANGLE_COMPONENT_UNARY:
+ printf ("unary operator\n");
+ break;
+ case DEMANGLE_COMPONENT_BINARY:
+ printf ("binary operator\n");
+ break;
+ case DEMANGLE_COMPONENT_BINARY_ARGS:
+ printf ("binary operator arguments\n");
+ break;
+ case DEMANGLE_COMPONENT_TRINARY:
+ printf ("trinary operator\n");
+ break;
+ case DEMANGLE_COMPONENT_TRINARY_ARG1:
+ printf ("trinary operator arguments 1\n");
+ break;
+ case DEMANGLE_COMPONENT_TRINARY_ARG2:
+ printf ("trinary operator arguments 1\n");
+ break;
+ case DEMANGLE_COMPONENT_LITERAL:
+ printf ("literal\n");
+ break;
+ case DEMANGLE_COMPONENT_LITERAL_NEG:
+ printf ("negative literal\n");
+ break;
+ }
+
+ d_dump (d_left (dc), indent + 2);
+ d_dump (d_right (dc), indent + 2);
+}
+
+#endif /* CP_DEMANGLE_DEBUG */
+
+/* Fill in a DEMANGLE_COMPONENT_NAME. */
+
+CP_STATIC_IF_GLIBCPP_V3
+int
+cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len)
+{
+ if (p == NULL || s == NULL || len == 0)
+ return 0;
+ p->type = DEMANGLE_COMPONENT_NAME;
+ p->u.s_name.s = s;
+ p->u.s_name.len = len;
+ return 1;
+}
+
+/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */
+
+CP_STATIC_IF_GLIBCPP_V3
+int
+cplus_demangle_fill_extended_operator (struct demangle_component *p, int args,
+ struct demangle_component *name)
+{
+ if (p == NULL || args < 0 || name == NULL)
+ return 0;
+ p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR;
+ p->u.s_extended_operator.args = args;
+ p->u.s_extended_operator.name = name;
+ return 1;
+}
+
+/* Fill in a DEMANGLE_COMPONENT_CTOR. */
+
+CP_STATIC_IF_GLIBCPP_V3
+int
+cplus_demangle_fill_ctor (struct demangle_component *p,
+ enum gnu_v3_ctor_kinds kind,
+ struct demangle_component *name)
+{
+ if (p == NULL
+ || name == NULL
+ || (kind < gnu_v3_complete_object_ctor
+ && kind > gnu_v3_complete_object_allocating_ctor))
+ return 0;
+ p->type = DEMANGLE_COMPONENT_CTOR;
+ p->u.s_ctor.kind = kind;
+ p->u.s_ctor.name = name;
+ return 1;
+}
+
+/* Fill in a DEMANGLE_COMPONENT_DTOR. */
+
+CP_STATIC_IF_GLIBCPP_V3
+int
+cplus_demangle_fill_dtor (struct demangle_component *p,
+ enum gnu_v3_dtor_kinds kind,
+ struct demangle_component *name)
+{
+ if (p == NULL
+ || name == NULL
+ || (kind < gnu_v3_deleting_dtor
+ && kind > gnu_v3_base_object_dtor))
+ return 0;
+ p->type = DEMANGLE_COMPONENT_DTOR;
+ p->u.s_dtor.kind = kind;
+ p->u.s_dtor.name = name;
+ return 1;
+}
+
+/* Add a new component. */
+
+static struct demangle_component *
+d_make_empty (struct d_info *di)
+{
+ struct demangle_component *p;
+
+ if (di->next_comp >= di->num_comps)
+ return NULL;
+ p = &di->comps[di->next_comp];
+ ++di->next_comp;
+ return p;
+}
+
+/* Add a new generic component. */
+
+static struct demangle_component *
+d_make_comp (struct d_info *di, enum demangle_component_type type,
+ struct demangle_component *left,
+ struct demangle_component *right)
+{
+ struct demangle_component *p;
+
+ /* We check for errors here. A typical error would be a NULL return
+ from a subroutine. We catch those here, and return NULL
+ upward. */
+ switch (type)
+ {
+ /* These types require two parameters. */
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ case DEMANGLE_COMPONENT_UNARY:
+ case DEMANGLE_COMPONENT_BINARY:
+ case DEMANGLE_COMPONENT_BINARY_ARGS:
+ case DEMANGLE_COMPONENT_TRINARY:
+ case DEMANGLE_COMPONENT_TRINARY_ARG1:
+ case DEMANGLE_COMPONENT_TRINARY_ARG2:
+ case DEMANGLE_COMPONENT_LITERAL:
+ case DEMANGLE_COMPONENT_LITERAL_NEG:
+ if (left == NULL || right == NULL)
+ return NULL;
+ break;
+
+ /* These types only require one parameter. */
+ case DEMANGLE_COMPONENT_VTABLE:
+ case DEMANGLE_COMPONENT_VTT:
+ case DEMANGLE_COMPONENT_TYPEINFO:
+ case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+ case DEMANGLE_COMPONENT_TYPEINFO_FN:
+ case DEMANGLE_COMPONENT_THUNK:
+ case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+ case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+ case DEMANGLE_COMPONENT_JAVA_CLASS:
+ case DEMANGLE_COMPONENT_GUARD:
+ case DEMANGLE_COMPONENT_REFTEMP:
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+ case DEMANGLE_COMPONENT_CAST:
+ if (left == NULL)
+ return NULL;
+ break;
+
+ /* This needs a right parameter, but the left parameter can be
+ empty. */
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ if (right == NULL)
+ return NULL;
+ break;
+
+ /* These are allowed to have no parameters--in some cases they
+ will be filled in later. */
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ break;
+
+ /* Other types should not be seen here. */
+ default:
+ return NULL;
+ }
+
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = type;
+ p->u.s_binary.left = left;
+ p->u.s_binary.right = right;
+ }
+ return p;
+}
+
+/* Add a new name component. */
+
+static struct demangle_component *
+d_make_name (struct d_info *di, const char *s, int len)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (! cplus_demangle_fill_name (p, s, len))
+ return NULL;
+ return p;
+}
+
+/* Add a new builtin type component. */
+
+static struct demangle_component *
+d_make_builtin_type (struct d_info *di,
+ const struct demangle_builtin_type_info *type)
+{
+ struct demangle_component *p;
+
+ if (type == NULL)
+ return NULL;
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE;
+ p->u.s_builtin.type = type;
+ }
+ return p;
+}
+
+/* Add a new operator component. */
+
+static struct demangle_component *
+d_make_operator (struct d_info *di, const struct demangle_operator_info *op)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_OPERATOR;
+ p->u.s_operator.op = op;
+ }
+ return p;
+}
+
+/* Add a new extended operator component. */
+
+static struct demangle_component *
+d_make_extended_operator (struct d_info *di, int args,
+ struct demangle_component *name)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (! cplus_demangle_fill_extended_operator (p, args, name))
+ return NULL;
+ return p;
+}
+
+/* Add a new constructor component. */
+
+static struct demangle_component *
+d_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind,
+ struct demangle_component *name)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (! cplus_demangle_fill_ctor (p, kind, name))
+ return NULL;
+ return p;
+}
+
+/* Add a new destructor component. */
+
+static struct demangle_component *
+d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind,
+ struct demangle_component *name)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (! cplus_demangle_fill_dtor (p, kind, name))
+ return NULL;
+ return p;
+}
+
+/* Add a new template parameter. */
+
+static struct demangle_component *
+d_make_template_param (struct d_info *di, long i)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM;
+ p->u.s_number.number = i;
+ }
+ return p;
+}
+
+/* Add a new standard substitution component. */
+
+static struct demangle_component *
+d_make_sub (struct d_info *di, const char *name, int len)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_SUB_STD;
+ p->u.s_string.string = name;
+ p->u.s_string.len = len;
+ }
+ return p;
+}
+
+/* <mangled-name> ::= _Z <encoding>
+
+ TOP_LEVEL is non-zero when called at the top level. */
+
+CP_STATIC_IF_GLIBCPP_V3
+struct demangle_component *
+cplus_demangle_mangled_name (struct d_info *di, int top_level)
+{
+ if (d_next_char (di) != '_')
+ return NULL;
+ if (d_next_char (di) != 'Z')
+ return NULL;
+ return d_encoding (di, top_level);
+}
+
+/* Return whether a function should have a return type. The argument
+ is the function name, which may be qualified in various ways. The
+ rules are that template functions have return types with some
+ exceptions, function types which are not part of a function name
+ mangling have return types with some exceptions, and non-template
+ function names do not have return types. The exceptions are that
+ constructors, destructors, and conversion operators do not have
+ return types. */
+
+static int
+has_return_type (struct demangle_component *dc)
+{
+ if (dc == NULL)
+ return 0;
+ switch (dc->type)
+ {
+ default:
+ return 0;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ return ! is_ctor_dtor_or_conversion (d_left (dc));
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ return has_return_type (d_left (dc));
+ }
+}
+
+/* Return whether a name is a constructor, a destructor, or a
+ conversion operator. */
+
+static int
+is_ctor_dtor_or_conversion (struct demangle_component *dc)
+{
+ if (dc == NULL)
+ return 0;
+ switch (dc->type)
+ {
+ default:
+ return 0;
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ return is_ctor_dtor_or_conversion (d_right (dc));
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_CAST:
+ return 1;
+ }
+}
+
+/* <encoding> ::= <(function) name> <bare-function-type>
+ ::= <(data) name>
+ ::= <special-name>
+
+ TOP_LEVEL is non-zero when called at the top level, in which case
+ if DMGL_PARAMS is not set we do not demangle the function
+ parameters. We only set this at the top level, because otherwise
+ we would not correctly demangle names in local scopes. */
+
+static struct demangle_component *
+d_encoding (struct d_info *di, int top_level)
+{
+ char peek = d_peek_char (di);
+
+ if (peek == 'G' || peek == 'T')
+ return d_special_name (di);
+ else
+ {
+ struct demangle_component *dc;
+
+ dc = d_name (di);
+
+ if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0)
+ {
+ /* Strip off any initial CV-qualifiers, as they really apply
+ to the `this' parameter, and they were not output by the
+ v2 demangler without DMGL_PARAMS. */
+ while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+ dc = d_left (dc);
+
+ /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
+ there may be CV-qualifiers on its right argument which
+ really apply here; this happens when parsing a class
+ which is local to a function. */
+ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME)
+ {
+ struct demangle_component *dcr;
+
+ dcr = d_right (dc);
+ while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
+ dcr = d_left (dcr);
+ dc->u.s_binary.right = dcr;
+ }
+
+ return dc;
+ }
+
+ peek = d_peek_char (di);
+ if (peek == '\0' || peek == 'E')
+ return dc;
+ return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc,
+ d_bare_function_type (di, has_return_type (dc)));
+ }
+}
+
+/* <name> ::= <nested-name>
+ ::= <unscoped-name>
+ ::= <unscoped-template-name> <template-args>
+ ::= <local-name>
+
+ <unscoped-name> ::= <unqualified-name>
+ ::= St <unqualified-name>
+
+ <unscoped-template-name> ::= <unscoped-name>
+ ::= <substitution>
+*/
+
+static struct demangle_component *
+d_name (struct d_info *di)
+{
+ char peek = d_peek_char (di);
+ struct demangle_component *dc;
+
+ switch (peek)
+ {
+ case 'N':
+ return d_nested_name (di);
+
+ case 'Z':
+ return d_local_name (di);
+
+/* APPLE LOCAL begin mainline 2007-05-09 5173149 */ \
+ case 'L':
+ return d_unqualified_name (di);
+
+/* APPLE LOCAL end mainline 2007-05-09 5173149 */ \
+ case 'S':
+ {
+ int subst;
+
+ if (d_peek_next_char (di) != 't')
+ {
+ dc = d_substitution (di, 0);
+ subst = 1;
+ }
+ else
+ {
+ d_advance (di, 2);
+ dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME,
+ d_make_name (di, "std", 3),
+ d_unqualified_name (di));
+ di->expansion += 3;
+ subst = 0;
+ }
+
+ if (d_peek_char (di) != 'I')
+ {
+ /* The grammar does not permit this case to occur if we
+ called d_substitution() above (i.e., subst == 1). We
+ don't bother to check. */
+ }
+ else
+ {
+ /* This is <template-args>, which means that we just saw
+ <unscoped-template-name>, which is a substitution
+ candidate if we didn't just get it from a
+ substitution. */
+ if (! subst)
+ {
+ if (! d_add_substitution (di, dc))
+ return NULL;
+ }
+ dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
+ d_template_args (di));
+ }
+
+ return dc;
+ }
+
+ default:
+ dc = d_unqualified_name (di);
+ if (d_peek_char (di) == 'I')
+ {
+ /* This is <template-args>, which means that we just saw
+ <unscoped-template-name>, which is a substitution
+ candidate. */
+ if (! d_add_substitution (di, dc))
+ return NULL;
+ dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
+ d_template_args (di));
+ }
+ return dc;
+ }
+}
+
+/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+ ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+*/
+
+static struct demangle_component *
+d_nested_name (struct d_info *di)
+{
+ struct demangle_component *ret;
+ struct demangle_component **pret;
+
+ if (d_next_char (di) != 'N')
+ return NULL;
+
+ pret = d_cv_qualifiers (di, &ret, 1);
+ if (pret == NULL)
+ return NULL;
+
+ *pret = d_prefix (di);
+ if (*pret == NULL)
+ return NULL;
+
+ if (d_next_char (di) != 'E')
+ return NULL;
+
+ return ret;
+}
+