aboutsummaryrefslogtreecommitdiff
path: root/third_party
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-10-20 22:56:12 -0700
committeralon@honor <none@none>2010-10-20 22:56:12 -0700
commit5f4f3fe49a065a7e5ccbc9116e8d966f37e3516a (patch)
tree3f53e24bb9255eb56b1c44ed8d32af1f83166cf3 /third_party
parent0feb052bd9ea18f2d943368eba5e6f40342e7105 (diff)
non-working gcc demangler test
Diffstat (limited to 'third_party')
-rw-r--r--third_party/ansidecl.h371
-rw-r--r--third_party/cp-demangle.h161
-rw-r--r--third_party/demangle.h549
-rw-r--r--third_party/gcc_demangler.c4218
-rw-r--r--third_party/libiberty.h634
5 files changed, 5933 insertions, 0 deletions
diff --git a/third_party/ansidecl.h b/third_party/ansidecl.h
new file mode 100644
index 00000000..a1a765d6
--- /dev/null
+++ b/third_party/ansidecl.h
@@ -0,0 +1,371 @@
+/* ANSI and traditional C compatability macros
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is 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. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ ANSI_PROTOTYPES 1 not defined
+ PTR `void *' `char *'
+ PTRCONST `void *const' `char *'
+ LONG_DOUBLE `long double' `double'
+ const not defined `'
+ volatile not defined `'
+ signed not defined `'
+ VA_START(ap, var) va_start(ap, var) va_start(ap)
+
+ Note that it is safe to write "void foo();" indicating a function
+ with no return value, in all K+R compilers we have been able to test.
+
+ For declaring functions with prototypes, we also provide these:
+
+ PARAMS ((prototype))
+ -- for functions which take a fixed number of arguments. Use this
+ when declaring the function. When defining the function, write a
+ K+R style argument list. For example:
+
+ char *strcpy PARAMS ((char *dest, char *source));
+ ...
+ char *
+ strcpy (dest, source)
+ char *dest;
+ char *source;
+ { ... }
+
+
+ VPARAMS ((prototype, ...))
+ -- for functions which take a variable number of arguments. Use
+ PARAMS to declare the function, VPARAMS to define it. For example:
+
+ int printf PARAMS ((const char *format, ...));
+ ...
+ int
+ printf VPARAMS ((const char *format, ...))
+ {
+ ...
+ }
+
+ For writing functions which take variable numbers of arguments, we
+ also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros. These
+ hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
+ thoroughly than the simple VA_START() macro mentioned above.
+
+ VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
+ Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
+ corresponding to the list of fixed arguments. Then use va_arg
+ normally to get the variable arguments, or pass your va_list object
+ around. You do not declare the va_list yourself; VA_OPEN does it
+ for you.
+
+ Here is a complete example:
+
+ int
+ printf VPARAMS ((const char *format, ...))
+ {
+ int result;
+
+ VA_OPEN (ap, format);
+ VA_FIXEDARG (ap, const char *, format);
+
+ result = vfprintf (stdout, format, ap);
+ VA_CLOSE (ap);
+
+ return result;
+ }
+
+
+ You can declare variables either before or after the VA_OPEN,
+ VA_FIXEDARG sequence. Also, VA_OPEN and VA_CLOSE are the beginning
+ and end of a block. They must appear at the same nesting level,
+ and any variables declared after VA_OPEN go out of scope at
+ VA_CLOSE. Unfortunately, with a K+R compiler, that includes the
+ argument list. You can have multiple instances of VA_OPEN/VA_CLOSE
+ pairs in a single function in case you need to traverse the
+ argument list more than once.
+
+ For ease of writing code which uses GCC extensions but needs to be
+ portable to other compilers, we provide the GCC_VERSION macro that
+ simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
+ wrappers around __attribute__. Also, __extension__ will be #defined
+ to nothing if it doesn't work. See below.
+
+ This header also defines a lot of obsolete macros:
+ CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
+ AND, DOTS, NOARGS. Don't use them. */
+
+#ifndef _ANSIDECL_H
+#define _ANSIDECL_H 1
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+ older preprocessors. Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+ (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values. */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+ is of a particular minimum version. (Both major & minor numbers are
+ significant.) This macro will evaluate to 0 if we are not using
+ gcc at all. */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
+/* All known AIX compilers implement these things (but don't always
+ define __STDC__). The RISC/OS MIPS compiler defines these things
+ in SVR4 mode, but does not define __STDC__. */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+ C++ compilers, does not define __STDC__, though it acts as if this
+ was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
+
+#define ANSI_PROTOTYPES 1
+#define PTR void *
+#define PTRCONST void *const
+#define LONG_DOUBLE long double
+
+/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in
+ a #ifndef. */
+#ifndef PARAMS
+#define PARAMS(ARGS) ARGS
+#endif
+
+#define VPARAMS(ARGS) ARGS
+#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
+
+/* variadic function helper macros */
+/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
+ use without inhibiting further decls and without declaring an
+ actual variable. */
+#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP, VAR); { struct Qdmy
+#define VA_CLOSE(AP) } va_end(AP); }
+#define VA_FIXEDARG(AP, T, N) struct Qdmy
+
+#undef const
+#undef volatile
+#undef signed
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+ it too, but it's not in C89. */
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if GCC_VERSION >= 2007
+# define inline __inline__ /* __inline__ prevents -pedantic warnings */
+# else
+# define inline /* nothing */
+# endif
+#endif
+
+/* These are obsolete. Do not use. */
+#ifndef IN_GCC
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+
+#define PROTO(type, name, arglist) type name arglist
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(void)
+#define AND ,
+#define DOTS , ...
+#define NOARGS void
+#endif /* ! IN_GCC */
+
+#else /* Not ANSI C. */
+
+#undef ANSI_PROTOTYPES
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define PARAMS(args) ()
+#define VPARAMS(args) (va_alist) va_dcl
+#define VA_START(va_list, var) va_start(va_list)
+
+#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP); { struct Qdmy
+#define VA_CLOSE(AP) } va_end(AP); }
+#define VA_FIXEDARG(AP, TYPE, NAME) TYPE NAME = va_arg(AP, TYPE)
+
+/* some systems define these in header files for non-ansi mode */
+#undef const
+#undef volatile
+#undef signed
+#undef inline
+#define const
+#define volatile
+#define signed
+#define inline
+
+#ifndef IN_GCC
+#define CONST
+#define VOLATILE
+#define SIGNED
+
+#define PROTO(type, name, arglist) type name ()
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+#define AND ;
+#define DOTS
+#define NOARGS
+#endif /* ! IN_GCC */
+
+#endif /* ANSI C. */
+
+/* Define macros for some gcc attributes. This permits us to use the
+ macros freely, and know that they will come into play for the
+ version of gcc in which they are supported. */
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+# define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (!defined (__cplusplus) && GCC_VERSION >= 2093)
+# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+# define ATTRIBUTE_UNUSED_LABEL
+# endif /* !__cplusplus && GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
+ identifier name. */
+#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
+# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
+#else /* !__cplusplus || GNUC >= 3.4 */
+# define ARG_UNUSED(NAME) NAME
+#endif /* !__cplusplus || GNUC >= 3.4 */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* Attribute `nonnull' was valid as of gcc 3.3. */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+# define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+# define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Attribute `pure' was valid as of gcc 3.0. */
+#ifndef ATTRIBUTE_PURE
+# if (GCC_VERSION >= 3000)
+# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define ATTRIBUTE_PURE
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_PURE */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+ This was the case for the `printf' format attribute by itself
+ before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+ attribute to retain this behavior. */
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
+#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
+#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
+#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
+#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
+#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
+#endif /* ATTRIBUTE_PRINTF */
+
+/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
+ a function pointer. Format attributes were allowed on function
+ pointers as of gcc 3.1. */
+#ifndef ATTRIBUTE_FPTR_PRINTF
+# if (GCC_VERSION >= 3001)
+# define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
+# else
+# define ATTRIBUTE_FPTR_PRINTF(m, n)
+# endif /* GNUC >= 3.1 */
+# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
+# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
+# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
+# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
+# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
+#endif /* ATTRIBUTE_FPTR_PRINTF */
+
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL. A
+ NULL format specifier was allowed as of gcc 3.3. */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+# define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+# define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
+/* Attribute `sentinel' was valid as of gcc 3.5. */
+#ifndef ATTRIBUTE_SENTINEL
+# if (GCC_VERSION >= 3005)
+# define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
+# else
+# define ATTRIBUTE_SENTINEL
+# endif /* GNUC >= 3.5 */
+#endif /* ATTRIBUTE_SENTINEL */
+
+
+#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
+# if (GCC_VERSION >= 3000)
+# define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
+# else
+# define ATTRIBUTE_ALIGNED_ALIGNOF(m)
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+ about GCC extensions. This feature didn't work properly before
+ gcc 2.8. */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+#endif /* ansidecl.h */
diff --git a/third_party/cp-demangle.h b/third_party/cp-demangle.h
new file mode 100644
index 00000000..2517a57e
--- /dev/null
+++ b/third_party/cp-demangle.h
@@ -0,0 +1,161 @@
+/* Internal demangler interface for g++ V3 ABI.
+ Copyright (C) 2003, 2004 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 file provides some definitions shared by cp-demangle.c and
+ cp-demint.c. It should not be included by any other files. */
+
+/* Information we keep for operators. */
+
+struct demangle_operator_info
+{
+ /* Mangled name. */
+ const char *code;
+ /* Real name. */
+ const char *name;
+ /* Length of real name. */
+ int len;
+ /* Number of arguments. */
+ int args;
+};
+
+/* How to print the value of a builtin type. */
+
+enum d_builtin_type_print
+{
+ /* Print as (type)val. */
+ D_PRINT_DEFAULT,
+ /* Print as integer. */
+ D_PRINT_INT,
+ /* Print as unsigned integer, with trailing "u". */
+ D_PRINT_UNSIGNED,
+ /* Print as long, with trailing "l". */
+ D_PRINT_LONG,
+ /* Print as unsigned long, with trailing "ul". */
+ D_PRINT_UNSIGNED_LONG,
+ /* Print as long long, with trailing "ll". */
+ D_PRINT_LONG_LONG,
+ /* Print as unsigned long long, with trailing "ull". */
+ D_PRINT_UNSIGNED_LONG_LONG,
+ /* Print as bool. */
+ D_PRINT_BOOL,
+ /* Print as float--put value in square brackets. */
+ D_PRINT_FLOAT,
+ /* Print in usual way, but here to detect void. */
+ D_PRINT_VOID
+};
+
+/* Information we keep for a builtin type. */
+
+struct demangle_builtin_type_info
+{
+ /* Type name. */
+ const char *name;
+ /* Length of type name. */
+ int len;
+ /* Type name when using Java. */
+ const char *java_name;
+ /* Length of java name. */
+ int java_len;
+ /* How to print a value of this type. */
+ enum d_builtin_type_print print;
+};
+
+/* The information structure we pass around. */
+
+struct d_info
+{
+ /* The string we are demangling. */
+ const char *s;
+ /* The end of the string we are demangling. */
+ const char *send;
+ /* The options passed to the demangler. */
+ int options;
+ /* The next character in the string to consider. */
+ const char *n;
+ /* The array of components. */
+ struct demangle_component *comps;
+ /* The index of the next available component. */
+ int next_comp;
+ /* The number of available component structures. */
+ int num_comps;
+ /* The array of substitutions. */
+ struct demangle_component **subs;
+ /* The index of the next substitution. */
+ int next_sub;
+ /* The number of available entries in the subs array. */
+ int num_subs;
+ /* The number of substitutions which we actually made from the subs
+ array, plus the number of template parameter references we
+ saw. */
+ int did_subs;
+ /* The last name we saw, for constructors and destructors. */
+ struct demangle_component *last_name;
+ /* A running total of the length of large expansions from the
+ mangled name to the demangled name, such as standard
+ substitutions and builtin types. */
+ int expansion;
+};
+
+#define d_peek_char(di) (*((di)->n))
+#define d_peek_next_char(di) ((di)->n[1])
+#define d_advance(di, i) ((di)->n += (i))
+#define d_next_char(di) (*((di)->n++))
+#define d_str(di) ((di)->n)
+
+/* Functions and arrays in cp-demangle.c which are referenced by
+ functions in cp-demint.c. */
+#ifdef IN_GLIBCPP_V3
+#define CP_STATIC_IF_GLIBCPP_V3 static
+#else
+#define CP_STATIC_IF_GLIBCPP_V3 extern
+#endif
+
+CP_STATIC_IF_GLIBCPP_V3
+const struct demangle_operator_info cplus_demangle_operators[];
+
+#define D_BUILTIN_TYPE_COUNT (26)
+
+CP_STATIC_IF_GLIBCPP_V3
+const struct demangle_builtin_type_info
+cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT];
+
+CP_STATIC_IF_GLIBCPP_V3
+struct demangle_component *
+cplus_demangle_mangled_name (struct d_info *, int);
+
+CP_STATIC_IF_GLIBCPP_V3
+struct demangle_component *
+cplus_demangle_type (struct d_info *);
+
+extern void
+cplus_demangle_init_info (const char *, int, size_t, struct d_info *);
+
+/* cp-demangle.c needs to define this a little differently */
+#undef CP_STATIC_IF_GLIBCPP_V3
diff --git a/third_party/demangle.h b/third_party/demangle.h
new file mode 100644
index 00000000..7d6b6370
--- /dev/null
+++ b/third_party/demangle.h
@@ -0,0 +1,549 @@
+/* Defs for interface to demanglers.
+ Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ In addition to the permissions in the GNU Library 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 Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library 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. */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#include "libiberty.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */
+#define DMGL_VERBOSE (1 << 3) /* Include implementation details. */
+#define DMGL_TYPES (1 << 4) /* Also try to demangle type encodings. */
+#define DMGL_RET_POSTFIX (1 << 5) /* Print function return types (when
+ present) after function signature */
+
+#define DMGL_AUTO (1 << 8)
+#define DMGL_GNU (1 << 9)
+#define DMGL_LUCID (1 << 10)
+#define DMGL_ARM (1 << 11)
+#define DMGL_HP (1 << 12) /* For the HP aCC compiler;
+ same as ARM except for
+ template arguments, etc. */
+#define DMGL_EDG (1 << 13)
+#define DMGL_GNU_V3 (1 << 14)
+#define DMGL_GNAT (1 << 15)
+
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT)
+
+/* Enumeration of possible demangling styles.
+
+ Lucid and ARM styles are still kept logically distinct, even though
+ they now both behave identically. The resulting style is actual the
+ union of both. I.E. either style recognizes both "__pt__" and "__rf__"
+ for operator "->", even though the first is lucid style and the second
+ is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+ no_demangling = -1,
+ unknown_demangling = 0,
+ auto_demangling = DMGL_AUTO,
+ gnu_demangling = DMGL_GNU,
+ lucid_demangling = DMGL_LUCID,
+ arm_demangling = DMGL_ARM,
+ hp_demangling = DMGL_HP,
+ edg_demangling = DMGL_EDG,
+ gnu_v3_demangling = DMGL_GNU_V3,
+ java_demangling = DMGL_JAVA,
+ gnat_demangling = DMGL_GNAT
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define NO_DEMANGLING_STYLE_STRING "none"
+#define AUTO_DEMANGLING_STYLE_STRING "auto"
+#define GNU_DEMANGLING_STYLE_STRING "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING "lucid"
+#define ARM_DEMANGLING_STYLE_STRING "arm"
+#define HP_DEMANGLING_STYLE_STRING "hp"
+#define EDG_DEMANGLING_STYLE_STRING "edg"
+#define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3"
+#define JAVA_DEMANGLING_STYLE_STRING "java"
+#define GNAT_DEMANGLING_STYLE_STRING "gnat"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM)
+#define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP)
+#define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG)
+#define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3)
+#define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA)
+#define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
+
+/* Provide information about the available demangle styles. This code is
+ pulled from gdb into libiberty because it is useful to binutils also. */
+
+extern const struct demangler_engine
+{
+ const char *const demangling_style_name;
+ const enum demangling_styles demangling_style;
+ const char *const demangling_style_doc;
+} libiberty_demanglers[];
+
+extern char *
+cplus_demangle (const char *mangled, int options);
+
+extern int
+cplus_demangle_opname (const char *opname, char *result, int options);
+
+extern const char *
+cplus_mangle_opname (const char *opname, int options);
+
+/* Note: This sets global state. FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling (int ch);
+
+extern enum demangling_styles
+cplus_demangle_set_style (enum demangling_styles style);
+
+extern enum demangling_styles
+cplus_demangle_name_to_style (const char *name);
+
+/* V3 ABI demangling entry points, defined in cp-demangle.c. */
+extern char*
+cplus_demangle_v3 (const char* mangled, int options);
+
+extern char*
+java_demangle_v3 (const char* mangled);
+
+
+enum gnu_v3_ctor_kinds {
+ gnu_v3_complete_object_ctor = 1,
+ gnu_v3_base_object_ctor,
+ gnu_v3_complete_object_allocating_ctor
+ /* APPLE LOCAL decloning */
+ , gnu_v3_unified_ctor
+};
+
+/* Return non-zero iff NAME is the mangled form of a constructor name
+ in the G++ V3 ABI demangling style. Specifically, return an `enum
+ gnu_v3_ctor_kinds' value indicating what kind of constructor
+ it is. */
+extern enum gnu_v3_ctor_kinds
+ is_gnu_v3_mangled_ctor (const char *name);
+
+
+enum gnu_v3_dtor_kinds {
+ gnu_v3_deleting_dtor = 1,
+ gnu_v3_complete_object_dtor,
+ gnu_v3_base_object_dtor
+ /* APPLE LOCAL decloning */
+ , gnu_v3_unified_dtor
+};
+
+/* Return non-zero iff NAME is the mangled form of a destructor name
+ in the G++ V3 ABI demangling style. Specifically, return an `enum
+ gnu_v3_dtor_kinds' value, indicating what kind of destructor
+ it is. */
+extern enum gnu_v3_dtor_kinds
+ is_gnu_v3_mangled_dtor (const char *name);
+
+/* The V3 demangler works in two passes. The first pass builds a tree
+ representation of the mangled name, and the second pass turns the
+ tree representation into a demangled string. Here we define an
+ interface to permit a caller to build their own tree
+ representation, which they can pass to the demangler to get a
+ demangled string. This can be used to canonicalize user input into
+ something which the demangler might output. It could also be used
+ by other demanglers in the future. */
+
+/* These are the component types which may be found in the tree. Many
+ component types have one or two subtrees, referred to as left and
+ right (a component type with only one subtree puts it in the left
+ subtree). */
+
+enum demangle_component_type
+{
+ /* A name, with a length and a pointer to a string. */
+ DEMANGLE_COMPONENT_NAME,
+ /* A qualified name. The left subtree is a class or namespace or
+ some such thing, and the right subtree is a name qualified by
+ that class. */
+ DEMANGLE_COMPONENT_QUAL_NAME,
+ /* A local name. The left subtree describes a function, and the
+ right subtree is a name which is local to that function. */
+ DEMANGLE_COMPONENT_LOCAL_NAME,
+ /* A typed name. The left subtree is a name, and the right subtree
+ describes that name as a function. */
+ DEMANGLE_COMPONENT_TYPED_NAME,
+ /* A template. The left subtree is a template name, and the right
+ subtree is a template argument list. */
+ DEMANGLE_COMPONENT_TEMPLATE,
+ /* A template parameter. This holds a number, which is the template
+ parameter index. */
+ DEMANGLE_COMPONENT_TEMPLATE_PARAM,
+ /* A constructor. This holds a name and the kind of
+ constructor. */
+ DEMANGLE_COMPONENT_CTOR,
+ /* A destructor. This holds a name and the kind of destructor. */
+ DEMANGLE_COMPONENT_DTOR,
+ /* A vtable. This has one subtree, the type for which this is a
+ vtable. */
+ DEMANGLE_COMPONENT_VTABLE,
+ /* A VTT structure. This has one subtree, the type for which this
+ is a VTT. */
+ DEMANGLE_COMPONENT_VTT,
+ /* A construction vtable. The left subtree is the type for which
+ this is a vtable, and the right subtree is the derived type for
+ which this vtable is built. */
+ DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE,
+ /* A typeinfo structure. This has one subtree, the type for which
+ this is the tpeinfo structure. */
+ DEMANGLE_COMPONENT_TYPEINFO,
+ /* A typeinfo name. This has one subtree, the type for which this
+ is the typeinfo name. */
+ DEMANGLE_COMPONENT_TYPEINFO_NAME,
+ /* A typeinfo function. This has one subtree, the type for which
+ this is the tpyeinfo function. */
+ DEMANGLE_COMPONENT_TYPEINFO_FN,
+ /* A thunk. This has one subtree, the name for which this is a
+ thunk. */
+ DEMANGLE_COMPONENT_THUNK,
+ /* A virtual thunk. This has one subtree, the name for which this
+ is a virtual thunk. */
+ DEMANGLE_COMPONENT_VIRTUAL_THUNK,
+ /* A covariant thunk. This has one subtree, the name for which this
+ is a covariant thunk. */
+ DEMANGLE_COMPONENT_COVARIANT_THUNK,
+ /* A Java class. This has one subtree, the type. */
+ DEMANGLE_COMPONENT_JAVA_CLASS,
+ /* A guard variable. This has one subtree, the name for which this
+ is a guard variable. */
+ DEMANGLE_COMPONENT_GUARD,
+ /* A reference temporary. This has one subtree, the name for which
+ this is a temporary. */
+ DEMANGLE_COMPONENT_REFTEMP,
+ /* A hidden alias. This has one subtree, the encoding for which it
+ is providing alternative linkage. */
+ DEMANGLE_COMPONENT_HIDDEN_ALIAS,
+ /* A standard substitution. This holds the name of the
+ substitution. */
+ DEMANGLE_COMPONENT_SUB_STD,
+ /* The restrict qualifier. The one subtree is the type which is
+ being qualified. */
+ DEMANGLE_COMPONENT_RESTRICT,
+ /* The volatile qualifier. The one subtree is the type which is
+ being qualified. */
+ DEMANGLE_COMPONENT_VOLATILE,
+ /* The const qualifier. The one subtree is the type which is being
+ qualified. */
+ DEMANGLE_COMPONENT_CONST,
+ /* The restrict qualifier modifying a member function. The one
+ subtree is the type which is being qualified. */
+ DEMANGLE_COMPONENT_RESTRICT_THIS,
+ /* The volatile qualifier modifying a member function. The one
+ subtree is the type which is being qualified. */
+ DEMANGLE_COMPONENT_VOLATILE_THIS,
+ /* The const qualifier modifying a member function. The one subtree
+ is the type which is being qualified. */
+ DEMANGLE_COMPONENT_CONST_THIS,
+ /* A vendor qualifier. The left subtree is the type which is being
+ qualified, and the right subtree is the name of the
+ qualifier. */
+ DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
+ /* A pointer. The one subtree is the type which is being pointed
+ to. */
+ DEMANGLE_COMPONENT_POINTER,
+ /* A reference. The one subtree is the type which is being
+ referenced. */
+ DEMANGLE_COMPONENT_REFERENCE,
+ /* A complex type. The one subtree is the base type. */
+ DEMANGLE_COMPONENT_COMPLEX,
+ /* An imaginary type. The one subtree is the base type. */
+ DEMANGLE_COMPONENT_IMAGINARY,
+ /* A builtin type. This holds the builtin type information. */
+ DEMANGLE_COMPONENT_BUILTIN_TYPE,
+ /* A vendor's builtin type. This holds the name of the type. */
+ DEMANGLE_COMPONENT_VENDOR_TYPE,
+ /* A function type. The left subtree is the return type. The right
+ subtree is a list of ARGLIST nodes. Either or both may be
+ NULL. */
+ DEMANGLE_COMPONENT_FUNCTION_TYPE,
+ /* An array type. The left subtree is the dimension, which may be
+ NULL, or a string (represented as DEMANGLE_COMPONENT_NAME), or an
+ expression. The right subtree is the element type. */
+ DEMANGLE_COMPONENT_ARRAY_TYPE,
+ /* A pointer to member type. The left subtree is the class type,
+ and the right subtree is the member type. CV-qualifiers appear
+ on the latter. */
+ DEMANGLE_COMPONENT_PTRMEM_TYPE,
+ /* An argument list. The left subtree is the current argument, and
+ the right subtree is either NULL or another ARGLIST node. */
+ DEMANGLE_COMPONENT_ARGLIST,
+ /* A template argument list. The left subtree is the current
+ template argument, and the right subtree is either NULL or
+ another TEMPLATE_ARGLIST node. */
+ DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
+ /* An operator. This holds information about a standard
+ operator. */
+ DEMANGLE_COMPONENT_OPERATOR,
+ /* An extended operator. This holds the number of arguments, and
+ the name of the extended operator. */
+ DEMANGLE_COMPONENT_EXTENDED_OPERATOR,
+ /* A typecast, represented as a unary operator. The one subtree is
+ the type to which the argument should be cast. */
+ DEMANGLE_COMPONENT_CAST,
+ /* A unary expression. The left subtree is the operator, and the
+ right subtree is the single argument. */
+ DEMANGLE_COMPONENT_UNARY,
+ /* A binary expression. The left subtree is the operator, and the
+ right subtree is a BINARY_ARGS. */
+ DEMANGLE_COMPONENT_BINARY,
+ /* Arguments to a binary expression. The left subtree is the first
+ argument, and the right subtree is the second argument. */
+ DEMANGLE_COMPONENT_BINARY_ARGS,
+ /* A trinary expression. The left subtree is the operator, and the
+ right subtree is a TRINARY_ARG1. */
+ DEMANGLE_COMPONENT_TRINARY,
+ /* Arguments to a trinary expression. The left subtree is the first
+ argument, and the right subtree is a TRINARY_ARG2. */
+ DEMANGLE_COMPONENT_TRINARY_ARG1,
+ /* More arguments to a trinary expression. The left subtree is the
+ second argument, and the right subtree is the third argument. */
+ DEMANGLE_COMPONENT_TRINARY_ARG2,
+ /* A literal. The left subtree is the type, and the right subtree
+ is the value, represented as a DEMANGLE_COMPONENT_NAME. */
+ DEMANGLE_COMPONENT_LITERAL,
+ /* A negative literal. Like LITERAL, but the value is negated.
+ This is a minor hack: the NAME used for LITERAL points directly
+ to the mangled string, but since negative numbers are mangled
+ using 'n' instead of '-', we want a way to indicate a negative
+ number which involves neither modifying the mangled string nor
+ allocating a new copy of the literal in memory. */
+ DEMANGLE_COMPONENT_LITERAL_NEG
+};
+
+/* Types which are only used internally. */
+
+struct demangle_operator_info;
+struct demangle_builtin_type_info;
+
+/* A node in the tree representation is an instance of a struct
+ demangle_component. Note that the field names of the struct are
+ not well protected against macros defined by the file including
+ this one. We can fix this if it ever becomes a problem. */
+
+struct demangle_component
+{
+ /* The type of this component. */
+ enum demangle_component_type type;
+
+ union
+ {
+ /* For DEMANGLE_COMPONENT_NAME. */
+ struct
+ {
+ /* A pointer to the name (which need not NULL terminated) and
+ its length. */
+ const char *s;
+ int len;
+ } s_name;
+
+ /* For DEMANGLE_COMPONENT_OPERATOR. */
+ struct
+ {
+ /* Operator. */
+ const struct demangle_operator_info *op;
+ } s_operator;
+
+ /* For DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */
+ struct
+ {
+ /* Number of arguments. */
+ int args;
+ /* Name. */
+ struct demangle_component *name;
+ } s_extended_operator;
+
+ /* For DEMANGLE_COMPONENT_CTOR. */
+ struct
+ {
+ /* Kind of constructor. */
+ enum gnu_v3_ctor_kinds kind;
+ /* Name. */
+ struct demangle_component *name;
+ } s_ctor;
+
+ /* For DEMANGLE_COMPONENT_DTOR. */
+ struct
+ {
+ /* Kind of destructor. */
+ enum gnu_v3_dtor_kinds kind;
+ /* Name. */
+ struct demangle_component *name;
+ } s_dtor;
+
+ /* For DEMANGLE_COMPONENT_BUILTIN_TYPE. */
+ struct
+ {
+ /* Builtin type. */
+ const struct demangle_builtin_type_info *type;
+ } s_builtin;
+
+ /* For DEMANGLE_COMPONENT_SUB_STD. */
+ struct
+ {
+ /* Standard substitution string. */
+ const char* string;
+ /* Length of string. */
+ int len;
+ } s_string;
+
+ /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM. */
+ struct
+ {
+ /* Template parameter index. */
+ long number;
+ } s_number;
+
+ /* For other types. */
+ struct
+ {
+ /* Left (or only) subtree. */
+ struct demangle_component *left;
+ /* Right subtree. */
+ struct demangle_component *right;
+ } s_binary;
+
+ } u;
+};
+
+/* People building mangled trees are expected to allocate instances of
+ struct demangle_component themselves. They can then call one of
+ the following functions to fill them in. */
+
+/* Fill in most component types with a left subtree and a right
+ subtree. Returns non-zero on success, zero on failure, such as an
+ unrecognized or inappropriate component type. */
+
+extern int
+cplus_demangle_fill_component (struct demangle_component *fill,
+ enum demangle_component_type,
+ struct demangle_component *left,
+ struct demangle_component *right);
+
+/* Fill in a DEMANGLE_COMPONENT_NAME. Returns non-zero on success,
+ zero for bad arguments. */
+
+extern int
+cplus_demangle_fill_name (struct demangle_component *fill,
+ const char *, int);
+
+/* Fill in a DEMANGLE_COMPONENT_BUILTIN_TYPE, using the name of the
+ builtin type (e.g., "int", etc.). Returns non-zero on success,
+ zero if the type is not recognized. */
+
+extern int
+cplus_demangle_fill_builtin_type (struct demangle_component *fill,
+ const char *type_name);
+
+/* Fill in a DEMANGLE_COMPONENT_OPERATOR, using the name of the
+ operator and the number of arguments which it takes (the latter is
+ used to disambiguate operators which can be both binary and unary,
+ such as '-'). Returns non-zero on success, zero if the operator is
+ not recognized. */
+
+extern int
+cplus_demangle_fill_operator (struct demangle_component *fill,
+ const char *opname, int args);
+
+/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR, providing the
+ number of arguments and the name. Returns non-zero on success,
+ zero for bad arguments. */
+
+extern int
+cplus_demangle_fill_extended_operator (struct demangle_component *fill,
+ int numargs,
+ struct demangle_component *nm);
+
+/* Fill in a DEMANGLE_COMPONENT_CTOR. Returns non-zero on success,
+ zero for bad arguments. */
+
+extern int
+cplus_demangle_fill_ctor (struct demangle_component *fill,
+ enum gnu_v3_ctor_kinds kind,
+ struct demangle_component *name);
+
+/* Fill in a DEMANGLE_COMPONENT_DTOR. Returns non-zero on success,
+ zero for bad arguments. */
+
+extern int
+cplus_demangle_fill_dtor (struct demangle_component *fill,
+ enum gnu_v3_dtor_kinds kind,
+ struct demangle_component *name);
+
+/* This function translates a mangled name into a struct
+ demangle_component tree. The first argument is the mangled name.
+ The second argument is DMGL_* options. This returns a pointer to a
+ tree on success, or NULL on failure. On success, the third
+ argument is set to a block of memory allocated by malloc. This
+ block should be passed to free when the tree is no longer
+ needed. */
+
+extern struct demangle_component *
+cplus_demangle_v3_components (const char *mangled, int options, void **mem);
+
+/* This function takes a struct demangle_component tree and returns
+ the corresponding demangled string. The first argument is DMGL_*
+ options. The second is the tree to demangle. The third is a guess
+ at the length of the demangled string, used to initially allocate
+ the return buffer. The fourth is a pointer to a size_t. On
+ success, this function returns a buffer allocated by malloc(), and
+ sets the size_t pointed to by the fourth argument to the size of
+ the allocated buffer (not the length of the returned string). On
+ failure, this function returns NULL, and sets the size_t pointed to
+ by the fourth argument to 0 for an invalid tree, or to 1 for a
+ memory allocation error. */
+
+extern char *
+cplus_demangle_print (int options,
+ const struct demangle_component *tree,
+ int estimated_length,
+ size_t *p_allocated_size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* DEMANGLE_H */
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;
+}
+
+/* <prefix> ::= <prefix> <unqualified-name>
+ ::= <template-prefix> <template-args>
+ ::= <template-param>
+ ::=
+ ::= <substitution>
+
+ <template-prefix> ::= <prefix> <(template) unqualified-name>
+ ::= <template-param>
+ ::= <substitution>
+*/
+
+static struct demangle_component *
+d_prefix (struct d_info *di)
+{
+ struct demangle_component *ret = NULL;
+
+ while (1)
+ {
+ char peek;
+ enum demangle_component_type comb_type;
+ struct demangle_component *dc;
+
+ peek = d_peek_char (di);
+ if (peek == '\0')
+ return NULL;
+
+ /* The older code accepts a <local-name> here, but I don't see
+ that in the grammar. The older code does not accept a
+ <template-param> here. */
+
+ comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
+ if (IS_DIGIT (peek)
+ || IS_LOWER (peek)
+ || peek == 'C'
+/* APPLE LOCAL begin mainline 2007-05-09 5173149 */ \
+ || peek == 'D'
+ || peek == 'L')
+/* APPLE LOCAL end mainline 2007-05-09 5173149 */ \
+ dc = d_unqualified_name (di);
+ else if (peek == 'S')
+ dc = d_substitution (di, 1);
+ else if (peek == 'I')
+ {
+ if (ret == NULL)
+ return NULL;
+ comb_type = DEMANGLE_COMPONENT_TEMPLATE;
+ dc = d_template_args (di);
+ }
+ else if (peek == 'T')
+ dc = d_template_param (di);
+ else if (peek == 'E')
+ return ret;
+ else
+ return NULL;
+
+ if (ret == NULL)
+ ret = dc;
+ else
+ ret = d_make_comp (di, comb_type, ret, dc);
+
+ if (peek != 'S' && d_peek_char (di) != 'E')
+ {
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ }
+ }
+}
+
+/* <unqualified-name> ::= <operator-name>
+ ::= <ctor-dtor-name>
+ ::= <source-name>
+ APPLE LOCAL begin mainline 2007-05-09 5173149
+ ::= <local-source-name>
+
+ <local-source-name> ::= L <source-name> <discriminator>
+ APPLE LOCAL end mainline 2007-05-09 5173149
+*/
+
+static struct demangle_component *
+d_unqualified_name (struct d_info *di)
+{
+ char peek;
+
+ peek = d_peek_char (di);
+ if (IS_DIGIT (peek))
+ return d_source_name (di);
+ else if (IS_LOWER (peek))
+ {
+ struct demangle_component *ret;
+
+ ret = d_operator_name (di);
+ if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
+ di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
+ return ret;
+ }
+ else if (peek == 'C' || peek == 'D')
+ return d_ctor_dtor_name (di);
+/* APPLE LOCAL begin mainline 2007-05-09 5173149 */ \
+ else if (peek == 'L')
+ {
+ struct demangle_component * ret;
+
+ d_advance (di, 1);
+
+ ret = d_source_name (di);
+ if (ret == NULL)
+ return NULL;
+ if (! d_discriminator (di))
+ return NULL;
+ return ret;
+ }
+/* APPLE LOCAL end mainline 2007-05-09 5173149 */ \
+ else
+ return NULL;
+}
+
+/* <source-name> ::= <(positive length) number> <identifier> */
+
+static struct demangle_component *
+d_source_name (struct d_info *di)
+{
+ long len;
+ struct demangle_component *ret;
+
+ len = d_number (di);
+ if (len <= 0)
+ return NULL;
+ ret = d_identifier (di, len);
+ di->last_name = ret;
+ return ret;
+}
+
+/* number ::= [n] <(non-negative decimal integer)> */
+
+static long
+d_number (struct d_info *di)
+{
+ int negative;
+ char peek;
+ long ret;
+
+ negative = 0;
+ peek = d_peek_char (di);
+ if (peek == 'n')
+ {
+ negative = 1;
+ d_advance (di, 1);
+ peek = d_peek_char (di);
+ }
+
+ ret = 0;
+ while (1)
+ {
+ if (! IS_DIGIT (peek))
+ {
+ if (negative)
+ ret = - ret;
+ return ret;
+ }
+ ret = ret * 10 + peek - '0';
+ d_advance (di, 1);
+ peek = d_peek_char (di);
+ }
+}
+
+/* identifier ::= <(unqualified source code identifier)> */
+
+static struct demangle_component *
+d_identifier (struct d_info *di, int len)
+{
+ const char *name;
+
+ name = d_str (di);
+
+ if (di->send - name < len)
+ return NULL;
+
+ d_advance (di, len);
+
+ /* A Java mangled name may have a trailing '$' if it is a C++
+ keyword. This '$' is not included in the length count. We just
+ ignore the '$'. */
+ if ((di->options & DMGL_JAVA) != 0
+ && d_peek_char (di) == '$')
+ d_advance (di, 1);
+
+ /* Look for something which looks like a gcc encoding of an
+ anonymous namespace, and replace it with a more user friendly
+ name. */
+ if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
+ && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX,
+ ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0)
+ {
+ const char *s;
+
+ s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
+ if ((*s == '.' || *s == '_' || *s == '$')
+ && s[1] == 'N')
+ {
+ di->expansion -= len - sizeof "(anonymous namespace)";
+ return d_make_name (di, "(anonymous namespace)",
+ sizeof "(anonymous namespace)" - 1);
+ }
+ }
+
+ return d_make_name (di, name, len);
+}
+
+/* operator_name ::= many different two character encodings.
+ ::= cv <type>
+ ::= v <digit> <source-name>
+*/
+
+#define NL(s) s, (sizeof s) - 1
+
+CP_STATIC_IF_GLIBCPP_V3
+const struct demangle_operator_info cplus_demangle_operators[] =
+{
+ { "aN", NL ("&="), 2 },
+ { "aS", NL ("="), 2 },
+ { "aa", NL ("&&"), 2 },
+ { "ad", NL ("&"), 1 },
+ { "an", NL ("&"), 2 },
+ { "cl", NL ("()"), 0 },
+ { "cm", NL (","), 2 },
+ { "co", NL ("~"), 1 },
+ { "dV", NL ("/="), 2 },
+ { "da", NL ("delete[]"), 1 },
+ { "de", NL ("*"), 1 },
+ { "dl", NL ("delete"), 1 },
+ { "dv", NL ("/"), 2 },
+ { "eO", NL ("^="), 2 },
+ { "eo", NL ("^"), 2 },
+ { "eq", NL ("=="), 2 },
+ { "ge", NL (">="), 2 },
+ { "gt", NL (">"), 2 },
+ { "ix", NL ("[]"), 2 },
+ { "lS", NL ("<<="), 2 },
+ { "le", NL ("<="), 2 },
+ { "ls", NL ("<<"), 2 },
+ { "lt", NL ("<"), 2 },
+ { "mI", NL ("-="), 2 },
+ { "mL", NL ("*="), 2 },
+ { "mi", NL ("-"), 2 },
+ { "ml", NL ("*"), 2 },
+ { "mm", NL ("--"), 1 },
+ { "na", NL ("new[]"), 1 },
+ { "ne", NL ("!="), 2 },
+ { "ng", NL ("-"), 1 },
+ { "nt", NL ("!"), 1 },
+ { "nw", NL ("new"), 1 },
+ { "oR", NL ("|="), 2 },
+ { "oo", NL ("||"), 2 },
+ { "or", NL ("|"), 2 },
+ { "pL", NL ("+="), 2 },
+ { "pl", NL ("+"), 2 },
+ { "pm", NL ("->*"), 2 },
+ { "pp", NL ("++"), 1 },
+ { "ps", NL ("+"), 1 },
+ { "pt", NL ("->"), 2 },
+ { "qu", NL ("?"), 3 },
+ { "rM", NL ("%="), 2 },
+ { "rS", NL (">>="), 2 },
+ { "rm", NL ("%"), 2 },
+ { "rs", NL (">>"), 2 },
+ { "st", NL ("sizeof "), 1 },
+ { "sz", NL ("sizeof "), 1 },
+ { NULL, NULL, 0, 0 }
+};
+
+static struct demangle_component *
+d_operator_name (struct d_info *di)
+{
+ char c1;
+ char c2;
+
+ c1 = d_next_char (di);
+ c2 = d_next_char (di);
+ if (c1 == 'v' && IS_DIGIT (c2))
+ return d_make_extended_operator (di, c2 - '0', d_source_name (di));
+ else if (c1 == 'c' && c2 == 'v')
+ return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
+ cplus_demangle_type (di), NULL);
+ else
+ {
+ /* LOW is the inclusive lower bound. */
+ int low = 0;
+ /* HIGH is the exclusive upper bound. We subtract one to ignore
+ the sentinel at the end of the array. */
+ int high = ((sizeof (cplus_demangle_operators)
+ / sizeof (cplus_demangle_operators[0]))
+ - 1);
+
+ while (1)
+ {
+ int i;
+ const struct demangle_operator_info *p;
+
+ i = low + (high - low) / 2;
+ p = cplus_demangle_operators + i;
+
+ if (c1 == p->code[0] && c2 == p->code[1])
+ return d_make_operator (di, p);
+
+ if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1]))
+ high = i;
+ else
+ low = i + 1;
+ if (low == high)
+ return NULL;
+ }
+ }
+}
+
+/* <special-name> ::= TV <type>
+ ::= TT <type>
+ ::= TI <type>
+ ::= TS <type>
+ ::= GV <(object) name>
+ ::= T <call-offset> <(base) encoding>
+ ::= Tc <call-offset> <call-offset> <(base) encoding>
+ Also g++ extensions:
+ ::= TC <type> <(offset) number> _ <(base) type>
+ ::= TF <type>
+ ::= TJ <type>
+ ::= GR <name>
+ ::= GA <encoding>
+*/
+
+static struct demangle_component *
+d_special_name (struct d_info *di)
+{
+ char c;
+
+ di->expansion += 20;
+ c = d_next_char (di);
+ if (c == 'T')
+ {
+ switch (d_next_char (di))
+ {
+ case 'V':
+ di->expansion -= 5;
+ return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE,
+ cplus_demangle_type (di), NULL);
+ case 'T':
+ di->expansion -= 10;
+ return d_make_comp (di, DEMANGLE_COMPONENT_VTT,
+ cplus_demangle_type (di), NULL);
+ case 'I':
+ return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO,
+ cplus_demangle_type (di), NULL);
+ case 'S':
+ return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME,
+ cplus_demangle_type (di), NULL);
+
+ case 'h':
+ if (! d_call_offset (di, 'h'))
+ return NULL;
+ return d_make_comp (di, DEMANGLE_COMPONENT_THUNK,
+ d_encoding (di, 0), NULL);
+
+ case 'v':
+ if (! d_call_offset (di, 'v'))
+ return NULL;
+ return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK,
+ d_encoding (di, 0), NULL);
+
+ case 'c':
+ if (! d_call_offset (di, '\0'))
+ return NULL;
+ if (! d_call_offset (di, '\0'))
+ return NULL;
+ return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK,
+ d_encoding (di, 0), NULL);
+
+ case 'C':
+ {
+ struct demangle_component *derived_type;
+ long offset;
+ struct demangle_component *base_type;
+
+ derived_type = cplus_demangle_type (di);
+ offset = d_number (di);
+ if (offset < 0)
+ return NULL;
+ if (d_next_char (di) != '_')
+ return NULL;
+ base_type = cplus_demangle_type (di);
+ /* We don't display the offset. FIXME: We should display
+ it in verbose mode. */
+ di->expansion += 5;
+ return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE,
+ base_type, derived_type);
+ }
+
+ case 'F':
+ return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN,
+ cplus_demangle_type (di), NULL);
+ case 'J':
+ return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
+ cplus_demangle_type (di), NULL);
+
+ default:
+ return NULL;
+ }
+ }
+ else if (c == 'G')
+ {
+ switch (d_next_char (di))
+ {
+ case 'V':
+ return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL);
+
+ case 'R':
+ return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
+ NULL);
+
+ case 'A':
+ return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
+ d_encoding (di, 0), NULL);
+
+ default:
+ return NULL;
+ }
+ }
+ else
+ return NULL;
+}
+
+/* <call-offset> ::= h <nv-offset> _
+ ::= v <v-offset> _
+
+ <nv-offset> ::= <(offset) number>
+
+ <v-offset> ::= <(offset) number> _ <(virtual offset) number>
+
+ The C parameter, if not '\0', is a character we just read which is
+ the start of the <call-offset>.
+
+ We don't display the offset information anywhere. FIXME: We should
+ display it in verbose mode. */
+
+static int
+d_call_offset (struct d_info *di, int c)
+{
+ if (c == '\0')
+ c = d_next_char (di);
+
+ if (c == 'h')
+ d_number (di);
+ else if (c == 'v')
+ {
+ d_number (di);
+ if (d_next_char (di) != '_')
+ return 0;
+ d_number (di);
+ }
+ else
+ return 0;
+
+ if (d_next_char (di) != '_')
+ return 0;
+
+ return 1;
+}
+
+/* <ctor-dtor-name> ::= C1
+ ::= C2
+ ::= C3
+ ::= D0
+ ::= D1
+ ::= D2
+*/
+
+static struct demangle_component *
+d_ctor_dtor_name (struct d_info *di)
+{
+ if (di->last_name != NULL)
+ {
+ if (di->last_name->type == DEMANGLE_COMPONENT_NAME)
+ di->expansion += di->last_name->u.s_name.len;
+ else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
+ di->expansion += di->last_name->u.s_string.len;
+ }
+ switch (d_next_char (di))
+ {
+ case 'C':
+ {
+ enum gnu_v3_ctor_kinds kind;
+
+ switch (d_next_char (di))
+ {
+ case '1':
+ kind = gnu_v3_complete_object_ctor;
+ break;
+ case '2':
+ kind = gnu_v3_base_object_ctor;
+ break;
+ case '3':
+ kind = gnu_v3_complete_object_allocating_ctor;
+ break;
+ default:
+ return NULL;
+ }
+ return d_make_ctor (di, kind, di->last_name);
+ }
+
+ case 'D':
+ {
+ enum gnu_v3_dtor_kinds kind;
+
+ switch (d_next_char (di))
+ {
+ case '0':
+ kind = gnu_v3_deleting_dtor;
+ break;
+ case '1':
+ kind = gnu_v3_complete_object_dtor;
+ break;
+ case '2':
+ kind = gnu_v3_base_object_dtor;
+ break;
+ default:
+ return NULL;
+ }
+ return d_make_dtor (di, kind, di->last_name);
+ }
+
+ default:
+ return NULL;
+ }
+}
+
+/* <type> ::= <builtin-type>
+ ::= <function-type>
+ ::= <class-enum-type>
+ ::= <array-type>
+ ::= <pointer-to-member-type>
+ ::= <template-param>
+ ::= <template-template-param> <template-args>
+ ::= <substitution>
+ ::= <CV-qualifiers> <type>
+ ::= P <type>
+ ::= R <type>
+ ::= C <type>
+ ::= G <type>
+ ::= U <source-name> <type>
+
+ <builtin-type> ::= various one letter codes
+ ::= u <source-name>
+*/
+
+CP_STATIC_IF_GLIBCPP_V3
+const struct demangle_builtin_type_info
+cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
+{
+ /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_DEFAULT },
+ /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL },
+ /* c */ { NL ("char"), NL ("byte"), D_PRINT_DEFAULT },
+ /* d */ { NL ("double"), NL ("double"), D_PRINT_FLOAT },
+ /* e */ { NL ("long double"), NL ("long double"), D_PRINT_FLOAT },
+ /* f */ { NL ("float"), NL ("float"), D_PRINT_FLOAT },
+ /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_FLOAT },
+ /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT },
+ /* i */ { NL ("int"), NL ("int"), D_PRINT_INT },
+ /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_UNSIGNED },
+ /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG },
+ /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG },
+ /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT },
+ /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"),
+ D_PRINT_DEFAULT },
+ /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT },
+ /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT },
+ /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID },
+ /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT },
+ /* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG },
+ /* y */ { NL ("unsigned long long"), NL ("unsigned long long"),
+ D_PRINT_UNSIGNED_LONG_LONG },
+ /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT },
+};
+
+CP_STATIC_IF_GLIBCPP_V3
+struct demangle_component *
+cplus_demangle_type (struct d_info *di)
+{
+ char peek;
+ struct demangle_component *ret;
+ int can_subst;
+
+ /* The ABI specifies that when CV-qualifiers are used, the base type
+ is substitutable, and the fully qualified type is substitutable,
+ but the base type with a strict subset of the CV-qualifiers is
+ not substitutable. The natural recursive implementation of the
+ CV-qualifiers would cause subsets to be substitutable, so instead
+ we pull them all off now.
+
+ FIXME: The ABI says that order-insensitive vendor qualifiers
+ should be handled in the same way, but we have no way to tell
+ which vendor qualifiers are order-insensitive and which are
+ order-sensitive. So we just assume that they are all
+ order-sensitive. g++ 3.4 supports only one vendor qualifier,
+ __vector, and it treats it as order-sensitive when mangling
+ names. */
+
+ peek = d_peek_char (di);
+ if (peek == 'r' || peek == 'V' || peek == 'K')
+ {
+ struct demangle_component **pret;
+
+ pret = d_cv_qualifiers (di, &ret, 0);
+ if (pret == NULL)
+ return NULL;
+ *pret = cplus_demangle_type (di);
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ return ret;
+ }
+
+ can_subst = 1;
+
+ switch (peek)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'l': case 'm': case 'n':
+ case 'o': case 's': case 't':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ ret = d_make_builtin_type (di,
+ &cplus_demangle_builtin_types[peek - 'a']);
+ di->expansion += ret->u.s_builtin.type->len;
+ can_subst = 0;
+ d_advance (di, 1);
+ break;
+
+ case 'u':
+ d_advance (di, 1);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE,
+ d_source_name (di), NULL);
+ break;
+
+ case 'F':
+ ret = d_function_type (di);
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'N':
+ case 'Z':
+ ret = d_class_enum_type (di);
+ break;
+
+ case 'A':
+ ret = d_array_type (di);
+ break;
+
+ case 'M':
+ ret = d_pointer_to_member_type (di);
+ break;
+
+ case 'T':
+ ret = d_template_param (di);
+ if (d_peek_char (di) == 'I')
+ {
+ /* This is <template-template-param> <template-args>. The
+ <template-template-param> part is a substitution
+ candidate. */
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+ d_template_args (di));
+ }
+ break;
+
+ case 'S':
+ /* If this is a special substitution, then it is the start of
+ <class-enum-type>. */
+ {
+ char peek_next;
+
+ peek_next = d_peek_next_char (di);
+ if (IS_DIGIT (peek_next)
+ || peek_next == '_'
+ || IS_UPPER (peek_next))
+ {
+ ret = d_substitution (di, 0);
+ /* The substituted name may have been a template name and
+ may be followed by tepmlate args. */
+ if (d_peek_char (di) == 'I')
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+ d_template_args (di));
+ else
+ can_subst = 0;
+ }
+ else
+ {
+ ret = d_class_enum_type (di);
+ /* If the substitution was a complete type, then it is not
+ a new substitution candidate. However, if the
+ substitution was followed by template arguments, then
+ the whole thing is a substitution candidate. */
+ if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD)
+ can_subst = 0;
+ }
+ }
+ break;
+
+ case 'P':
+ d_advance (di, 1);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER,
+ cplus_demangle_type (di), NULL);
+ break;
+
+ case 'R':
+ d_advance (di, 1);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE,
+ cplus_demangle_type (di), NULL);
+ break;
+
+ case 'C':
+ d_advance (di, 1);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX,
+ cplus_demangle_type (di), NULL);
+ break;
+
+ case 'G':
+ d_advance (di, 1);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY,
+ cplus_demangle_type (di), NULL);
+ break;
+
+ case 'U':
+ d_advance (di, 1);
+ ret = d_source_name (di);
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
+ cplus_demangle_type (di), ret);
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (can_subst)
+ {
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ }
+
+ return ret;
+}
+
+/* <CV-qualifiers> ::= [r] [V] [K] */
+
+static struct demangle_component **
+d_cv_qualifiers (struct d_info *di,
+ struct demangle_component **pret, int member_fn)
+{
+ char peek;
+
+ peek = d_peek_char (di);
+ while (peek == 'r' || peek == 'V' || peek == 'K')
+ {
+ enum demangle_component_type t;
+
+ d_advance (di, 1);
+ if (peek == 'r')
+ {
+ t = (member_fn
+ ? DEMANGLE_COMPONENT_RESTRICT_THIS
+ : DEMANGLE_COMPONENT_RESTRICT);
+ di->expansion += sizeof "restrict";
+ }
+ else if (peek == 'V')
+ {
+ t = (member_fn
+ ? DEMANGLE_COMPONENT_VOLATILE_THIS
+ : DEMANGLE_COMPONENT_VOLATILE);
+ di->expansion += sizeof "volatile";
+ }
+ else
+ {
+ t = (member_fn
+ ? DEMANGLE_COMPONENT_CONST_THIS
+ : DEMANGLE_COMPONENT_CONST);
+ di->expansion += sizeof "const";
+ }
+
+ *pret = d_make_comp (di, t, NULL, NULL);
+ if (*pret == NULL)
+ return NULL;
+ pret = &d_left (*pret);
+
+ peek = d_peek_char (di);
+ }
+
+ return pret;
+}
+
+/* <function-type> ::= F [Y] <bare-function-type> E */
+
+static struct demangle_component *
+d_function_type (struct d_info *di)
+{
+ struct demangle_component *ret;
+
+ if (d_next_char (di) != 'F')
+ return NULL;
+ if (d_peek_char (di) == 'Y')
+ {
+ /* Function has C linkage. We don't print this information.
+ FIXME: We should print it in verbose mode. */
+ d_advance (di, 1);
+ }
+ ret = d_bare_function_type (di, 1);
+ if (d_next_char (di) != 'E')
+ return NULL;
+ return ret;
+}
+
+/* <bare-function-type> ::= [J]<type>+ */
+
+static struct demangle_component *
+d_bare_function_type (struct d_info *di, int has_return_type)
+{
+ struct demangle_component *return_type;
+ struct demangle_component *tl;
+ struct demangle_component **ptl;
+ char peek;
+
+ /* Detect special qualifier indicating that the first argument
+ is the return type. */
+ peek = d_peek_char (di);
+ if (peek == 'J')
+ {
+ d_advance (di, 1);
+ has_return_type = 1;
+ }
+
+ return_type = NULL;
+ tl = NULL;
+ ptl = &tl;
+ while (1)
+ {
+ struct demangle_component *type;
+
+ peek = d_peek_char (di);
+ if (peek == '\0' || peek == 'E')
+ break;
+ type = cplus_demangle_type (di);
+ if (type == NULL)
+ return NULL;
+ if (has_return_type)
+ {
+ return_type = type;
+ has_return_type = 0;
+ }
+ else
+ {
+ *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
+ if (*ptl == NULL)
+ return NULL;
+ ptl = &d_right (*ptl);
+ }
+ }
+
+ /* There should be at least one parameter type besides the optional
+ return type. A function which takes no arguments will have a
+ single parameter type void. */
+ if (tl == NULL)
+ return NULL;
+
+ /* If we have a single parameter type void, omit it. */
+ if (d_right (tl) == NULL
+ && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
+ && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
+ {
+ di->expansion -= d_left (tl)->u.s_builtin.type->len;
+ tl = NULL;
+ }
+
+ return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);
+}
+
+/* <class-enum-type> ::= <name> */
+
+static struct demangle_component *
+d_class_enum_type (struct d_info *di)
+{
+ return d_name (di);
+}
+
+/* <array-type> ::= A <(positive dimension) number> _ <(element) type>
+ ::= A [<(dimension) expression>] _ <(element) type>
+*/
+
+static struct demangle_component *
+d_array_type (struct d_info *di)
+{
+ char peek;
+ struct demangle_component *dim;
+
+ if (d_next_char (di) != 'A')
+ return NULL;
+
+ peek = d_peek_char (di);
+ if (peek == '_')
+ dim = NULL;
+ else if (IS_DIGIT (peek))
+ {
+ const char *s;
+
+ s = d_str (di);
+ do
+ {
+ d_advance (di, 1);
+ peek = d_peek_char (di);
+ }
+ while (IS_DIGIT (peek));
+ dim = d_make_name (di, s, d_str (di) - s);
+ if (dim == NULL)
+ return NULL;
+ }
+ else
+ {
+ dim = d_expression (di);
+ if (dim == NULL)
+ return NULL;
+ }
+
+ if (d_next_char (di) != '_')
+ return NULL;
+
+ return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
+ cplus_demangle_type (di));
+}
+
+/* <pointer-to-member-type> ::= M <(class) type> <(member) type> */
+
+static struct demangle_component *
+d_pointer_to_member_type (struct d_info *di)
+{
+ struct demangle_component *cl;
+ struct demangle_component *mem;
+ struct demangle_component **pmem;
+
+ if (d_next_char (di) != 'M')
+ return NULL;
+
+ cl = cplus_demangle_type (di);
+
+ /* The ABI specifies that any type can be a substitution source, and
+ that M is followed by two types, and that when a CV-qualified
+ type is seen both the base type and the CV-qualified types are
+ substitution sources. The ABI also specifies that for a pointer
+ to a CV-qualified member function, the qualifiers are attached to
+ the second type. Given the grammar, a plain reading of the ABI
+ suggests that both the CV-qualified member function and the
+ non-qualified member function are substitution sources. However,
+ g++ does not work that way. g++ treats only the CV-qualified
+ member function as a substitution source. FIXME. So to work
+ with g++, we need to pull off the CV-qualifiers here, in order to
+ avoid calling add_substitution() in cplus_demangle_type(). But
+ for a CV-qualified member which is not a function, g++ does
+ follow the ABI, so we need to handle that case here by calling
+ d_add_substitution ourselves. */
+
+ pmem = d_cv_qualifiers (di, &mem, 1);
+ if (pmem == NULL)
+ return NULL;
+ *pmem = cplus_demangle_type (di);
+
+ if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ if (! d_add_substitution (di, mem))
+ return NULL;
+ }
+
+ return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
+}
+
+/* <template-param> ::= T_
+ ::= T <(parameter-2 non-negative) number> _
+*/
+
+static struct demangle_component *
+d_template_param (struct d_info *di)
+{
+ long param;
+
+ if (d_next_char (di) != 'T')
+ return NULL;
+
+ if (d_peek_char (di) == '_')
+ param = 0;
+ else
+ {
+ param = d_number (di);
+ if (param < 0)
+ return NULL;
+ param += 1;
+ }
+
+ if (d_next_char (di) != '_')
+ return NULL;
+
+ ++di->did_subs;
+
+ return d_make_template_param (di, param);
+}
+
+/* <template-args> ::= I <template-arg>+ E */
+
+static struct demangle_component *
+d_template_args (struct d_info *di)
+{
+ struct demangle_component *hold_last_name;
+ struct demangle_component *al;
+ struct demangle_component **pal;
+
+ /* Preserve the last name we saw--don't let the template arguments
+ clobber it, as that would give us the wrong name for a subsequent
+ constructor or destructor. */
+ hold_last_name = di->last_name;
+
+ if (d_next_char (di) != 'I')
+ return NULL;
+
+ al = NULL;
+ pal = &al;
+ while (1)
+ {
+ struct demangle_component *a;
+
+ a = d_template_arg (di);
+ if (a == NULL)
+ return NULL;
+
+ *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL);
+ if (*pal == NULL)
+ return NULL;
+ pal = &d_right (*pal);
+
+ if (d_peek_char (di) == 'E')
+ {
+ d_advance (di, 1);
+ break;
+ }
+ }
+
+ di->last_name = hold_last_name;
+
+ return al;
+}
+
+/* <template-arg> ::= <type>
+ ::= X <expression> E
+ ::= <expr-primary>
+*/
+
+static struct demangle_component *
+d_template_arg (struct d_info *di)
+{
+ struct demangle_component *ret;
+
+ switch (d_peek_char (di))
+ {
+ case 'X':
+ d_advance (di, 1);
+ ret = d_expression (di);
+ if (d_next_char (di) != 'E')
+ return NULL;
+ return ret;
+
+ case 'L':
+ return d_expr_primary (di);
+
+ default:
+ return cplus_demangle_type (di);
+ }
+}
+
+/* <expression> ::= <(unary) operator-name> <expression>
+ ::= <(binary) operator-name> <expression> <expression>
+ ::= <(trinary) operator-name> <expression> <expression> <expression>
+ ::= st <type>
+ ::= <template-param>
+ ::= sr <type> <unqualified-name>
+ ::= sr <type> <unqualified-name> <template-args>
+ ::= <expr-primary>
+*/
+
+static struct demangle_component *
+d_expression (struct d_info *di)
+{
+ char peek;
+
+ peek = d_peek_char (di);
+ if (peek == 'L')
+ return d_expr_primary (di);
+ else if (peek == 'T')
+ return d_template_param (di);
+ else if (peek == 's' && d_peek_next_char (di) == 'r')
+ {
+ struct demangle_component *type;
+ struct demangle_component *name;
+
+ d_advance (di, 2);
+ type = cplus_demangle_type (di);
+ name = d_unqualified_name (di);
+ if (d_peek_char (di) != 'I')
+ return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
+ else
+ return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type,
+ d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
+ d_template_args (di)));
+ }
+ else
+ {
+ struct demangle_component *op;
+ int args;
+
+ op = d_operator_name (di);
+ if (op == NULL)
+ return NULL;
+
+ if (op->type == DEMANGLE_COMPONENT_OPERATOR)
+ di->expansion += op->u.s_operator.op->len - 2;
+
+ if (op->type == DEMANGLE_COMPONENT_OPERATOR
+ && strcmp (op->u.s_operator.op->code, "st") == 0)
+ return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+ cplus_demangle_type (di));
+
+ switch (op->type)
+ {
+ default:
+ return NULL;
+ case DEMANGLE_COMPONENT_OPERATOR:
+ args = op->u.s_operator.op->args;
+ break;
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ args = op->u.s_extended_operator.args;
+ break;
+ case DEMANGLE_COMPONENT_CAST:
+ args = 1;
+ break;
+ }
+
+ switch (args)
+ {
+ case 1:
+ return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+ d_expression (di));
+ case 2:
+ {
+ struct demangle_component *left;
+
+ left = d_expression (di);
+ return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
+ d_make_comp (di,
+ DEMANGLE_COMPONENT_BINARY_ARGS,
+ left,
+ d_expression (di)));
+ }
+ case 3:
+ {
+ struct demangle_component *first;
+ struct demangle_component *second;
+
+ first = d_expression (di);
+ second = d_expression (di);
+ return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
+ d_make_comp (di,
+ DEMANGLE_COMPONENT_TRINARY_ARG1,
+ first,
+ d_make_comp (di,
+ DEMANGLE_COMPONENT_TRINARY_ARG2,
+ second,
+ d_expression (di))));
+ }
+ default:
+ return NULL;
+ }
+ }
+}
+
+/* <expr-primary> ::= L <type> <(value) number> E
+ ::= L <type> <(value) float> E
+ ::= L <mangled-name> E
+*/
+
+static struct demangle_component *
+d_expr_primary (struct d_info *di)
+{
+ struct demangle_component *ret;
+
+ if (d_next_char (di) != 'L')
+ return NULL;
+ if (d_peek_char (di) == '_')
+ ret = cplus_demangle_mangled_name (di, 0);
+ else
+ {
+ struct demangle_component *type;
+ enum demangle_component_type t;
+ const char *s;
+
+ type = cplus_demangle_type (di);
+ if (type == NULL)
+ return NULL;
+
+ /* If we have a type we know how to print, we aren't going to
+ print the type name itself. */
+ if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
+ && type->u.s_builtin.type->print != D_PRINT_DEFAULT)
+ di->expansion -= type->u.s_builtin.type->len;
+
+ /* Rather than try to interpret the literal value, we just
+ collect it as a string. Note that it's possible to have a
+ floating point literal here. The ABI specifies that the
+ format of such literals is machine independent. That's fine,
+ but what's not fine is that versions of g++ up to 3.2 with
+ -fabi-version=1 used upper case letters in the hex constant,
+ and dumped out gcc's internal representation. That makes it
+ hard to tell where the constant ends, and hard to dump the
+ constant in any readable form anyhow. We don't attempt to
+ handle these cases. */
+
+ t = DEMANGLE_COMPONENT_LITERAL;
+ if (d_peek_char (di) == 'n')
+ {
+ t = DEMANGLE_COMPONENT_LITERAL_NEG;
+ d_advance (di, 1);
+ }
+ s = d_str (di);
+ while (d_peek_char (di) != 'E')
+ {
+ if (d_peek_char (di) == '\0')
+ return NULL;
+ d_advance (di, 1);
+ }
+ ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
+ }
+ if (d_next_char (di) != 'E')
+ return NULL;
+ return ret;
+}
+
+/* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
+ ::= Z <(function) encoding> E s [<discriminator>]
+*/
+
+static struct demangle_component *
+d_local_name (struct d_info *di)
+{
+ struct demangle_component *function;
+
+ if (d_next_char (di) != 'Z')
+ return NULL;
+
+ function = d_encoding (di, 0);
+
+ if (d_next_char (di) != 'E')
+ return NULL;
+
+ if (d_peek_char (di) == 's')
+ {
+ d_advance (di, 1);
+ if (! d_discriminator (di))
+ return NULL;
+ return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function,
+ d_make_name (di, "string literal",
+ sizeof "string literal" - 1));
+ }
+ else
+ {
+ struct demangle_component *name;
+
+ name = d_name (di);
+ if (! d_discriminator (di))
+ return NULL;
+ return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
+ }
+}
+
+/* <discriminator> ::= _ <(non-negative) number>
+
+ We demangle the discriminator, but we don't print it out. FIXME:
+ We should print it out in verbose mode. */
+
+static int
+d_discriminator (struct d_info *di)
+{
+ long discrim;
+
+ if (d_peek_char (di) != '_')
+ return 1;
+ d_advance (di, 1);
+ discrim = d_number (di);
+ if (discrim < 0)
+ return 0;
+ return 1;
+}
+
+/* Add a new substitution. */
+
+static int
+d_add_substitution (struct d_info *di, struct demangle_component *dc)
+{
+ if (dc == NULL)
+ return 0;
+ if (di->next_sub >= di->num_subs)
+ return 0;
+ di->subs[di->next_sub] = dc;
+ ++di->next_sub;
+ return 1;
+}
+
+/* <substitution> ::= S <seq-id> _
+ ::= S_
+ ::= St
+ ::= Sa
+ ::= Sb
+ ::= Ss
+ ::= Si
+ ::= So
+ ::= Sd
+
+ If PREFIX is non-zero, then this type is being used as a prefix in
+ a qualified name. In this case, for the standard substitutions, we
+ need to check whether we are being used as a prefix for a
+ constructor or destructor, and return a full template name.
+ Otherwise we will get something like std::iostream::~iostream()
+ which does not correspond particularly well to any function which
+ actually appears in the source.
+*/
+
+static const struct d_standard_sub_info standard_subs[] =
+{
+ { 't', NL ("std"),
+ NL ("std"),
+ NULL, 0 },
+ { 'a', NL ("std::allocator"),
+ NL ("std::allocator"),
+ NL ("allocator") },
+ { 'b', NL ("std::basic_string"),
+ NL ("std::basic_string"),
+ NL ("basic_string") },
+ { 's', NL ("std::string"),
+ NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ NL ("basic_string") },
+ { 'i', NL ("std::istream"),
+ NL ("std::basic_istream<char, std::char_traits<char> >"),
+ NL ("basic_istream") },
+ { 'o', NL ("std::ostream"),
+ NL ("std::basic_ostream<char, std::char_traits<char> >"),
+ NL ("basic_ostream") },
+ { 'd', NL ("std::iostream"),
+ NL ("std::basic_iostream<char, std::char_traits<char> >"),
+ NL ("basic_iostream") }
+};
+
+static struct demangle_component *
+d_substitution (struct d_info *di, int prefix)
+{
+ char c;
+
+ if (d_next_char (di) != 'S')
+ return NULL;
+
+ c = d_next_char (di);
+ if (c == '_' || IS_DIGIT (c) || IS_UPPER (c))
+ {
+ int id;
+
+ id = 0;
+ if (c != '_')
+ {
+ do
+ {
+ if (IS_DIGIT (c))
+ id = id * 36 + c - '0';
+ else if (IS_UPPER (c))
+ id = id * 36 + c - 'A' + 10;
+ else
+ return NULL;
+ if (id < 0)
+ return NULL;
+ c = d_next_char (di);
+ }
+ while (c != '_');
+
+ ++id;
+ }
+
+ if (id >= di->next_sub)
+ return NULL;
+
+ ++di->did_subs;
+
+ return di->subs[id];
+ }
+ else
+ {
+ int verbose;
+ const struct d_standard_sub_info *p;
+ const struct d_standard_sub_info *pend;
+
+ verbose = (di->options & DMGL_VERBOSE) != 0;
+ if (! verbose && prefix)
+ {
+ char peek;
+
+ peek = d_peek_char (di);
+ if (peek == 'C' || peek == 'D')
+ verbose = 1;
+ }
+
+ pend = (&standard_subs[0]
+ + sizeof standard_subs / sizeof standard_subs[0]);
+ for (p = &standard_subs[0]; p < pend; ++p)
+ {
+ if (c == p->code)
+ {
+ const char *s;
+ int len;
+
+ if (p->set_last_name != NULL)
+ di->last_name = d_make_sub (di, p->set_last_name,
+ p->set_last_name_len);
+ if (verbose)
+ {
+ s = p->full_expansion;
+ len = p->full_len;
+ }
+ else
+ {
+ s = p->simple_expansion;
+ len = p->simple_len;
+ }
+ di->expansion += len;
+ return d_make_sub (di, s, len);
+ }
+ }
+
+ return NULL;
+ }
+}
+
+/* Resize the print buffer. */
+
+static void
+d_print_resize (struct d_print_info *dpi, size_t add)
+{
+ size_t need;
+
+ if (dpi->buf == NULL)
+ return;
+ need = dpi->len + add;
+ while (need > dpi->alc)
+ {
+ size_t newalc;
+ char *newbuf;
+
+ newalc = dpi->alc * 2;
+ newbuf = (char *) realloc (dpi->buf, newalc);
+ if (newbuf == NULL)
+ {
+ free (dpi->buf);
+ dpi->buf = NULL;
+ dpi->allocation_failure = 1;
+ return;
+ }
+ dpi->buf = newbuf;
+ dpi->alc = newalc;
+ }
+}
+
+/* Append a character to the print buffer. */
+
+static void
+d_print_append_char (struct d_print_info *dpi, int c)
+{
+ if (dpi->buf != NULL)
+ {
+ if (dpi->len >= dpi->alc)
+ {
+ d_print_resize (dpi, 1);
+ if (dpi->buf == NULL)
+ return;
+ }
+
+ dpi->buf[dpi->len] = c;
+ ++dpi->len;
+ }
+}
+
+/* Append a buffer to the print buffer. */
+
+static void
+d_print_append_buffer (struct d_print_info *dpi, const char *s, size_t l)
+{
+ if (dpi->buf != NULL)
+ {
+ if (dpi->len + l > dpi->alc)
+ {
+ d_print_resize (dpi, l);
+ if (dpi->buf == NULL)
+ return;
+ }
+
+ memcpy (dpi->buf + dpi->len, s, l);
+ dpi->len += l;
+ }
+}
+
+/* Indicate that an error occurred during printing. */
+
+static void
+d_print_error (struct d_print_info *dpi)
+{
+ free (dpi->buf);
+ dpi->buf = NULL;
+}
+
+/* Turn components into a human readable string. OPTIONS is the
+ options bits passed to the demangler. DC is the tree to print.
+ ESTIMATE is a guess at the length of the result. This returns a
+ string allocated by malloc, or NULL on error. On success, this
+ sets *PALC to the size of the allocated buffer. On failure, this
+ sets *PALC to 0 for a bad parse, or to 1 for a memory allocation
+ failure. */
+
+CP_STATIC_IF_GLIBCPP_V3
+char *
+cplus_demangle_print (int options, const struct demangle_component *dc,
+ int estimate, size_t *palc)
+{
+ struct d_print_info dpi;
+
+ dpi.options = options;
+
+ dpi.alc = estimate + 1;
+ dpi.buf = (char *) malloc (dpi.alc);
+ if (dpi.buf == NULL)
+ {
+ *palc = 1;
+ return NULL;
+ }
+
+ dpi.len = 0;
+ dpi.templates = NULL;
+ dpi.modifiers = NULL;
+
+ dpi.allocation_failure = 0;
+
+ d_print_comp (&dpi, dc);
+
+ d_append_char (&dpi, '\0');
+
+ if (dpi.buf != NULL)
+ *palc = dpi.alc;
+ else
+ *palc = dpi.allocation_failure;
+
+ return dpi.buf;
+}
+
+/* Subroutine to handle components. */
+
+static void
+d_print_comp (struct d_print_info *dpi,
+ const struct demangle_component *dc)
+{
+ if (dc == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ if (d_print_saw_error (dpi))
+ return;
+
+ switch (dc->type)
+ {
+ case DEMANGLE_COMPONENT_NAME:
+ if ((dpi->options & DMGL_JAVA) == 0)
+ d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
+ else
+ d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
+ return;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ d_print_comp (dpi, d_left (dc));
+ if ((dpi->options & DMGL_JAVA) == 0)
+ d_append_string_constant (dpi, "::");
+ else
+ d_append_char (dpi, '.');
+ d_print_comp (dpi, d_right (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ {
+ struct d_print_mod *hold_modifiers;
+ struct demangle_component *typed_name;
+ struct d_print_mod adpm[4];
+ unsigned int i;
+ struct d_print_template dpt;
+
+ /* Pass the name down to the type so that it can be printed in
+ the right place for the type. We also have to pass down
+ any CV-qualifiers, which apply to the this parameter. */
+ hold_modifiers = dpi->modifiers;
+ i = 0;
+ typed_name = d_left (dc);
+ while (typed_name != NULL)
+ {
+ if (i >= sizeof adpm / sizeof adpm[0])
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ adpm[i].next = dpi->modifiers;
+ dpi->modifiers = &adpm[i];
+ adpm[i].mod = typed_name;
+ adpm[i].printed = 0;
+ adpm[i].templates = dpi->templates;
+ ++i;
+
+ if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
+ && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
+ && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
+ break;
+
+ typed_name = d_left (typed_name);
+ }
+
+ /* If typed_name is a template, then it applies to the
+ function type as well. */
+ if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
+ {
+ dpt.next = dpi->templates;
+ dpi->templates = &dpt;
+ dpt.template_decl = typed_name;
+ }
+
+ /* If typed_name 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 (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME)
+ {
+ struct demangle_component *local_name;
+
+ local_name = d_right (typed_name);
+ while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
+ {
+ if (i >= sizeof adpm / sizeof adpm[0])
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ adpm[i] = adpm[i - 1];
+ adpm[i].next = &adpm[i - 1];
+ dpi->modifiers = &adpm[i];
+
+ adpm[i - 1].mod = local_name;
+ adpm[i - 1].printed = 0;
+ adpm[i - 1].templates = dpi->templates;
+ ++i;
+
+ local_name = d_left (local_name);
+ }
+ }
+
+ d_print_comp (dpi, d_right (dc));
+
+ if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
+ dpi->templates = dpt.next;
+
+ /* If the modifiers didn't get printed by the type, print them
+ now. */
+ while (i > 0)
+ {
+ --i;
+ if (! adpm[i].printed)
+ {
+ d_append_char (dpi, ' ');
+ d_print_mod (dpi, adpm[i].mod);
+ }
+ }
+
+ dpi->modifiers = hold_modifiers;
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ {
+ struct d_print_mod *hold_dpm;
+
+ /* Don't push modifiers into a template definition. Doing so
+ could give the wrong definition for a template argument.
+ Instead, treat the template essentially as a name. */
+
+ hold_dpm = dpi->modifiers;
+ dpi->modifiers = NULL;
+
+ d_print_comp (dpi, d_left (dc));
+ if (d_last_char (dpi) == '<')
+ d_append_char (dpi, ' ');
+ d_append_char (dpi, '<');
+ d_print_comp (dpi, d_right (dc));
+ /* Avoid generating two consecutive '>' characters, to avoid
+ the C++ syntactic ambiguity. */
+ if (d_last_char (dpi) == '>')
+ d_append_char (dpi, ' ');
+ d_append_char (dpi, '>');
+
+ dpi->modifiers = hold_dpm;
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ {
+ long i;
+ struct demangle_component *a;
+ struct d_print_template *hold_dpt;
+
+ if (dpi->templates == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ i = dc->u.s_number.number;
+ for (a = d_right (dpi->templates->template_decl);
+ a != NULL;
+ a = d_right (a))
+ {
+ if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ if (i <= 0)
+ break;
+ --i;
+ }
+ if (i != 0 || a == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ /* While processing this parameter, we need to pop the list of
+ templates. This is because the template parameter may
+ itself be a reference to a parameter of an outer
+ template. */
+
+ hold_dpt = dpi->templates;
+ dpi->templates = hold_dpt->next;
+
+ d_print_comp (dpi, d_left (a));
+
+ dpi->templates = hold_dpt;
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_CTOR:
+ d_print_comp (dpi, dc->u.s_ctor.name);
+ return;
+
+ case DEMANGLE_COMPONENT_DTOR:
+ d_append_char (dpi, '~');
+ d_print_comp (dpi, dc->u.s_dtor.name);
+ return;
+
+ case DEMANGLE_COMPONENT_VTABLE:
+ d_append_string_constant (dpi, "vtable for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_VTT:
+ d_append_string_constant (dpi, "VTT for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+ d_append_string_constant (dpi, "construction vtable for ");
+ d_print_comp (dpi, d_left (dc));
+ d_append_string_constant (dpi, "-in-");
+ d_print_comp (dpi, d_right (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_TYPEINFO:
+ d_append_string_constant (dpi, "typeinfo for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+ d_append_string_constant (dpi, "typeinfo name for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_TYPEINFO_FN:
+ d_append_string_constant (dpi, "typeinfo fn for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_THUNK:
+ d_append_string_constant (dpi, "non-virtual thunk to ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+ d_append_string_constant (dpi, "virtual thunk to ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+ d_append_string_constant (dpi, "covariant return thunk to ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_JAVA_CLASS:
+ d_append_string_constant (dpi, "java Class for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_GUARD:
+ d_append_string_constant (dpi, "guard variable for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_REFTEMP:
+ d_append_string_constant (dpi, "reference temporary for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+ d_append_string_constant (dpi, "hidden alias for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_SUB_STD:
+ d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
+ return;
+
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ {
+ struct d_print_mod *pdpm;
+
+ /* When printing arrays, it's possible to have cases where the
+ same CV-qualifier gets pushed on the stack multiple times.
+ We only need to print it once. */
+
+ for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next)
+ {
+ if (! pdpm->printed)
+ {
+ if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT
+ && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE
+ && pdpm->mod->type != DEMANGLE_COMPONENT_CONST)
+ break;
+ if (pdpm->mod->type == dc->type)
+ {
+ d_print_comp (dpi, d_left (dc));
+ return;
+ }
+ }
+ }
+ }
+ /* Fall through. */
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ {
+ /* We keep a list of modifiers on the stack. */
+ struct d_print_mod dpm;
+
+ dpm.next = dpi->modifiers;
+ dpi->modifiers = &dpm;
+ dpm.mod = dc;
+ dpm.printed = 0;
+ dpm.templates = dpi->templates;
+
+ d_print_comp (dpi, d_left (dc));
+
+ /* If the modifier didn't get printed by the type, print it
+ now. */
+ if (! dpm.printed)
+ d_print_mod (dpi, dc);
+
+ dpi->modifiers = dpm.next;
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ if ((dpi->options & DMGL_JAVA) == 0)
+ d_append_buffer (dpi, dc->u.s_builtin.type->name,
+ dc->u.s_builtin.type->len);
+ else
+ d_append_buffer (dpi, dc->u.s_builtin.type->java_name,
+ dc->u.s_builtin.type->java_len);
+ return;
+
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ d_print_comp (dpi, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ {
+ if ((dpi->options & DMGL_RET_POSTFIX) != 0)
+ d_print_function_type (dpi, dc, dpi->modifiers);
+
+ /* Print return type if present */
+ if (d_left (dc) != NULL)
+ {
+ struct d_print_mod dpm;
+
+ /* We must pass this type down as a modifier in order to
+ print it in the right location. */
+ dpm.next = dpi->modifiers;
+ dpi->modifiers = &dpm;
+ dpm.mod = dc;
+ dpm.printed = 0;
+ dpm.templates = dpi->templates;
+
+ d_print_comp (dpi, d_left (dc));
+
+ dpi->modifiers = dpm.next;
+
+ if (dpm.printed)
+ return;
+
+ /* In standard prefix notation, there is a space between the
+ return type and the function signature. */
+ if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+ d_append_char (dpi, ' ');
+ }
+
+ if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+ d_print_function_type (dpi, dc, dpi->modifiers);
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ {
+ struct d_print_mod *hold_modifiers;
+ struct d_print_mod adpm[4];
+ unsigned int i;
+ struct d_print_mod *pdpm;
+
+ /* We must pass this type down as a modifier in order to print
+ multi-dimensional arrays correctly. If the array itself is
+ CV-qualified, we act as though the element type were
+ CV-qualified. We do this by copying the modifiers down
+ rather than fiddling pointers, so that we don't wind up
+ with a d_print_mod higher on the stack pointing into our
+ stack frame after we return. */
+
+ hold_modifiers = dpi->modifiers;
+
+ adpm[0].next = hold_modifiers;
+ dpi->modifiers = &adpm[0];
+ adpm[0].mod = dc;
+ adpm[0].printed = 0;
+ adpm[0].templates = dpi->templates;
+
+ i = 1;
+ pdpm = hold_modifiers;
+ while (pdpm != NULL
+ && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT
+ || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE
+ || pdpm->mod->type == DEMANGLE_COMPONENT_CONST))
+ {
+ if (! pdpm->printed)
+ {
+ if (i >= sizeof adpm / sizeof adpm[0])
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ adpm[i] = *pdpm;
+ adpm[i].next = dpi->modifiers;
+ dpi->modifiers = &adpm[i];
+ pdpm->printed = 1;
+ ++i;
+ }
+
+ pdpm = pdpm->next;
+ }
+
+ d_print_comp (dpi, d_right (dc));
+
+ dpi->modifiers = hold_modifiers;
+
+ if (adpm[0].printed)
+ return;
+
+ while (i > 1)
+ {
+ --i;
+ d_print_mod (dpi, adpm[i].mod);
+ }
+
+ d_print_array_type (dpi, dc, dpi->modifiers);
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ {
+ struct d_print_mod dpm;
+
+ dpm.next = dpi->modifiers;
+ dpi->modifiers = &dpm;
+ dpm.mod = dc;
+ dpm.printed = 0;
+ dpm.templates = dpi->templates;
+
+ d_print_comp (dpi, d_right (dc));
+
+ /* If the modifier didn't get printed by the type, print it
+ now. */
+ if (! dpm.printed)
+ {
+ d_append_char (dpi, ' ');
+ d_print_comp (dpi, d_left (dc));
+ d_append_string_constant (dpi, "::*");
+ }
+
+ dpi->modifiers = dpm.next;
+
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_ARGLIST:
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+ d_print_comp (dpi, d_left (dc));
+ if (d_right (dc) != NULL)
+ {
+ d_append_string_constant (dpi, ", ");
+ d_print_comp (dpi, d_right (dc));
+ }
+ return;
+
+ case DEMANGLE_COMPONENT_OPERATOR:
+ {
+ char c;
+
+ d_append_string_constant (dpi, "operator");
+ c = dc->u.s_operator.op->name[0];
+ if (IS_LOWER (c))
+ d_append_char (dpi, ' ');
+ d_append_buffer (dpi, dc->u.s_operator.op->name,
+ dc->u.s_operator.op->len);
+ return;
+ }
+
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ d_append_string_constant (dpi, "operator ");
+ d_print_comp (dpi, dc->u.s_extended_operator.name);
+ return;
+
+ case DEMANGLE_COMPONENT_CAST:
+ d_append_string_constant (dpi, "operator ");
+ d_print_cast (dpi, dc);
+ return;
+
+ case DEMANGLE_COMPONENT_UNARY:
+ if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
+ d_print_expr_op (dpi, d_left (dc));
+ else
+ {
+ d_append_char (dpi, '(');
+ d_print_cast (dpi, d_left (dc));
+ d_append_char (dpi, ')');
+ }
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, d_right (dc));
+ d_append_char (dpi, ')');
+ return;
+
+ case DEMANGLE_COMPONENT_BINARY:
+ if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS)
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ /* We wrap an expression which uses the greater-than operator in
+ an extra layer of parens so that it does not get confused
+ with the '>' which ends the template parameters. */
+ if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
+ && d_left (dc)->u.s_operator.op->len == 1
+ && d_left (dc)->u.s_operator.op->name[0] == '>')
+ d_append_char (dpi, '(');
+
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, d_left (d_right (dc)));
+ d_append_string_constant (dpi, ") ");
+ d_print_expr_op (dpi, d_left (dc));
+ d_append_string_constant (dpi, " (");
+ d_print_comp (dpi, d_right (d_right (dc)));
+ d_append_char (dpi, ')');
+
+ if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
+ && d_left (dc)->u.s_operator.op->len == 1
+ && d_left (dc)->u.s_operator.op->name[0] == '>')
+ d_append_char (dpi, ')');
+
+ return;
+
+ case DEMANGLE_COMPONENT_BINARY_ARGS:
+ /* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */
+ d_print_error (dpi);
+ return;
+
+ case DEMANGLE_COMPONENT_TRINARY:
+ if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1
+ || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, d_left (d_right (dc)));
+ d_append_string_constant (dpi, ") ");
+ d_print_expr_op (dpi, d_left (dc));
+ d_append_string_constant (dpi, " (");
+ d_print_comp (dpi, d_left (d_right (d_right (dc))));
+ d_append_string_constant (dpi, ") : (");
+ d_print_comp (dpi, d_right (d_right (d_right (dc))));
+ d_append_char (dpi, ')');
+ return;
+
+ case DEMANGLE_COMPONENT_TRINARY_ARG1:
+ case DEMANGLE_COMPONENT_TRINARY_ARG2:
+ /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY. */
+ d_print_error (dpi);
+ return;
+
+ case DEMANGLE_COMPONENT_LITERAL:
+ case DEMANGLE_COMPONENT_LITERAL_NEG:
+ {
+ enum d_builtin_type_print tp;
+
+ /* For some builtin types, produce simpler output. */
+ tp = D_PRINT_DEFAULT;
+ if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)
+ {
+ tp = d_left (dc)->u.s_builtin.type->print;
+ switch (tp)
+ {
+ case D_PRINT_INT:
+ case D_PRINT_UNSIGNED:
+ case D_PRINT_LONG:
+ case D_PRINT_UNSIGNED_LONG:
+ case D_PRINT_LONG_LONG:
+ case D_PRINT_UNSIGNED_LONG_LONG:
+ if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME)
+ {
+ if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
+ d_append_char (dpi, '-');
+ d_print_comp (dpi, d_right (dc));
+ switch (tp)
+ {
+ default:
+ break;
+ case D_PRINT_UNSIGNED:
+ d_append_char (dpi, 'u');
+ break;
+ case D_PRINT_LONG:
+ d_append_char (dpi, 'l');
+ break;
+ case D_PRINT_UNSIGNED_LONG:
+ d_append_string_constant (dpi, "ul");
+ break;
+ case D_PRINT_LONG_LONG:
+ d_append_string_constant (dpi, "ll");
+ break;
+ case D_PRINT_UNSIGNED_LONG_LONG:
+ d_append_string_constant (dpi, "ull");
+ break;
+ }
+ return;
+ }
+ break;
+
+ case D_PRINT_BOOL:
+ if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME
+ && d_right (dc)->u.s_name.len == 1
+ && dc->type == DEMANGLE_COMPONENT_LITERAL)
+ {
+ switch (d_right (dc)->u.s_name.s[0])
+ {
+ case '0':
+ d_append_string_constant (dpi, "false");
+ return;
+ case '1':
+ d_append_string_constant (dpi, "true");
+ return;
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, d_left (dc));
+ d_append_char (dpi, ')');
+ if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
+ d_append_char (dpi, '-');
+ if (tp == D_PRINT_FLOAT)
+ d_append_char (dpi, '[');
+ d_print_comp (dpi, d_right (dc));
+ if (tp == D_PRINT_FLOAT)
+ d_append_char (dpi, ']');
+ }
+ return;
+
+ default:
+ d_print_error (dpi);
+ return;
+ }
+}
+
+/* Print a Java dentifier. For Java we try to handle encoded extended
+ Unicode characters. The C++ ABI doesn't mention Unicode encoding,
+ so we don't it for C++. Characters are encoded as
+ __U<hex-char>+_. */
+
+static void
+d_print_java_identifier (struct d_print_info *dpi, const char *name, int len)
+{
+ const char *p;
+ const char *end;
+
+ end = name + len;
+ for (p = name; p < end; ++p)
+ {
+ if (end - p > 3
+ && p[0] == '_'
+ && p[1] == '_'
+ && p[2] == 'U')
+ {
+ unsigned long c;
+ const char *q;
+
+ c = 0;
+ for (q = p + 3; q < end; ++q)
+ {
+ int dig;
+
+ if (IS_DIGIT (*q))
+ dig = *q - '0';
+ else if (*q >= 'A' && *q <= 'F')
+ dig = *q - 'A' + 10;
+ else if (*q >= 'a' && *q <= 'f')
+ dig = *q - 'a' + 10;
+ else
+ break;
+
+ c = c * 16 + dig;
+ }
+ /* If the Unicode character is larger than 256, we don't try
+ to deal with it here. FIXME. */
+ if (q < end && *q == '_' && c < 256)
+ {
+ d_append_char (dpi, c);
+ p = q;
+ continue;
+ }
+ }
+
+ d_append_char (dpi, *p);
+ }
+}
+
+/* Print a list of modifiers. SUFFIX is 1 if we are printing
+ qualifiers on this after printing a function. */
+
+static void
+d_print_mod_list (struct d_print_info *dpi,
+ struct d_print_mod *mods, int suffix)
+{
+ struct d_print_template *hold_dpt;
+
+ if (mods == NULL || d_print_saw_error (dpi))
+ return;
+
+ if (mods->printed
+ || (! suffix
+ && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
+ {
+ d_print_mod_list (dpi, mods->next, suffix);
+ return;
+ }
+
+ mods->printed = 1;
+
+ hold_dpt = dpi->templates;
+ dpi->templates = mods->templates;
+
+ if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ d_print_function_type (dpi, mods->mod, mods->next);
+ dpi->templates = hold_dpt;
+ return;
+ }
+ else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
+ {
+ d_print_array_type (dpi, mods->mod, mods->next);
+ dpi->templates = hold_dpt;
+ return;
+ }
+ else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME)
+ {
+ struct d_print_mod *hold_modifiers;
+ struct demangle_component *dc;
+
+ /* When this is on the modifier stack, we have pulled any
+ qualifiers off the right argument already. Otherwise, we
+ print it as usual, but don't let the left argument see any
+ modifiers. */
+
+ hold_modifiers = dpi->modifiers;
+ dpi->modifiers = NULL;
+ d_print_comp (dpi, d_left (mods->mod));
+ dpi->modifiers = hold_modifiers;
+
+ if ((dpi->options & DMGL_JAVA) == 0)
+ d_append_string_constant (dpi, "::");
+ else
+ d_append_char (dpi, '.');
+
+ dc = d_right (mods->mod);
+ while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+ dc = d_left (dc);
+
+ d_print_comp (dpi, dc);
+
+ dpi->templates = hold_dpt;
+ return;
+ }
+
+ d_print_mod (dpi, mods->mod);
+
+ dpi->templates = hold_dpt;
+
+ d_print_mod_list (dpi, mods->next, suffix);
+}
+
+/* Print a modifier. */
+
+static void
+d_print_mod (struct d_print_info *dpi,
+ const struct demangle_component *mod)
+{
+ switch (mod->type)
+ {
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ d_append_string_constant (dpi, " restrict");
+ return;
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ d_append_string_constant (dpi, " volatile");
+ return;
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ d_append_string_constant (dpi, " const");
+ return;
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ d_append_char (dpi, ' ');
+ d_print_comp (dpi, d_right (mod));
+ return;
+ case DEMANGLE_COMPONENT_POINTER:
+ /* There is no pointer symbol in Java. */
+ if ((dpi->options & DMGL_JAVA) == 0)
+ d_append_char (dpi, '*');
+ return;
+ case DEMANGLE_COMPONENT_REFERENCE:
+ d_append_char (dpi, '&');
+ return;
+ case DEMANGLE_COMPONENT_COMPLEX:
+ d_append_string_constant (dpi, "complex ");
+ return;
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ d_append_string_constant (dpi, "imaginary ");
+ return;
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ if (d_last_char (dpi) != '(')
+ d_append_char (dpi, ' ');
+ d_print_comp (dpi, d_left (mod));
+ d_append_string_constant (dpi, "::*");
+ return;
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ d_print_comp (dpi, d_left (mod));
+ return;
+ default:
+ /* Otherwise, we have something that won't go back on the
+ modifier stack, so we can just print it. */
+ d_print_comp (dpi, mod);
+ return;
+ }
+}
+
+/* Print a function type, except for the return type. */
+
+static void
+d_print_function_type (struct d_print_info *dpi,
+ const struct demangle_component *dc,
+ struct d_print_mod *mods)
+{
+ int need_paren;
+ int saw_mod;
+ int need_space;
+ struct d_print_mod *p;
+ struct d_print_mod *hold_modifiers;
+
+ need_paren = 0;
+ saw_mod = 0;
+ need_space = 0;
+ for (p = mods; p != NULL; p = p->next)
+ {
+ if (p->printed)
+ break;
+
+ saw_mod = 1;
+ switch (p->mod->type)
+ {
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ need_paren = 1;
+ break;
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ need_space = 1;
+ need_paren = 1;
+ break;
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ break;
+ default:
+ break;
+ }
+ if (need_paren)
+ break;
+ }
+
+ if (d_left (dc) != NULL && ! saw_mod)
+ need_paren = 1;
+
+ if (need_paren)
+ {
+ if (! need_space)
+ {
+ if (d_last_char (dpi) != '('
+ && d_last_char (dpi) != '*')
+ need_space = 1;
+ }
+ if (need_space && d_last_char (dpi) != ' ')
+ d_append_char (dpi, ' ');
+ d_append_char (dpi, '(');
+ }
+
+ hold_modifiers = dpi->modifiers;
+ dpi->modifiers = NULL;
+
+ d_print_mod_list (dpi, mods, 0);
+
+ if (need_paren)
+ d_append_char (dpi, ')');
+
+ d_append_char (dpi, '(');
+
+ if (d_right (dc) != NULL)
+ d_print_comp (dpi, d_right (dc));
+
+ d_append_char (dpi, ')');
+
+ d_print_mod_list (dpi, mods, 1);
+
+ dpi->modifiers = hold_modifiers;
+}
+
+/* Print an array type, except for the element type. */
+
+static void
+d_print_array_type (struct d_print_info *dpi,
+ const struct demangle_component *dc,
+ struct d_print_mod *mods)
+{
+ int need_space;
+
+ need_space = 1;
+ if (mods != NULL)
+ {
+ int need_paren;
+ struct d_print_mod *p;
+
+ need_paren = 0;
+ for (p = mods; p != NULL; p = p->next)
+ {
+ if (! p->printed)
+ {
+ if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
+ {
+ need_space = 0;
+ break;
+ }
+ else
+ {
+ need_paren = 1;
+ need_space = 1;
+ break;
+ }
+ }
+ }
+
+ if (need_paren)
+ d_append_string_constant (dpi, " (");
+
+ d_print_mod_list (dpi, mods, 0);
+
+ if (need_paren)
+ d_append_char (dpi, ')');
+ }
+
+ if (need_space)
+ d_append_char (dpi, ' ');
+
+ d_append_char (dpi, '[');
+
+ if (d_left (dc) != NULL)
+ d_print_comp (dpi, d_left (dc));
+
+ d_append_char (dpi, ']');
+}
+
+/* Print an operator in an expression. */
+
+static void
+d_print_expr_op (struct d_print_info *dpi,
+ const struct demangle_component *dc)
+{
+ if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
+ d_append_buffer (dpi, dc->u.s_operator.op->name,
+ dc->u.s_operator.op->len);
+ else
+ d_print_comp (dpi, dc);
+}
+
+/* Print a cast. */
+
+static void
+d_print_cast (struct d_print_info *dpi,
+ const struct demangle_component *dc)
+{
+ if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
+ d_print_comp (dpi, d_left (dc));
+ else
+ {
+ struct d_print_mod *hold_dpm;
+ struct d_print_template dpt;
+
+ /* It appears that for a templated cast operator, we need to put
+ the template parameters in scope for the operator name, but
+ not for the parameters. The effect is that we need to handle
+ the template printing here. */
+
+ hold_dpm = dpi->modifiers;
+ dpi->modifiers = NULL;
+
+ dpt.next = dpi->templates;
+ dpi->templates = &dpt;
+ dpt.template_decl = d_left (dc);
+
+ d_print_comp (dpi, d_left (d_left (dc)));
+
+ dpi->templates = dpt.next;
+
+ if (d_last_char (dpi) == '<')
+ d_append_char (dpi, ' ');
+ d_append_char (dpi, '<');
+ d_print_comp (dpi, d_right (d_left (dc)));
+ /* Avoid generating two consecutive '>' characters, to avoid
+ the C++ syntactic ambiguity. */
+ if (d_last_char (dpi) == '>')
+ d_append_char (dpi, ' ');
+ d_append_char (dpi, '>');
+
+ dpi->modifiers = hold_dpm;
+ }
+}
+
+/* Initialize the information structure we use to pass around
+ information. */
+
+CP_STATIC_IF_GLIBCPP_V3
+void
+cplus_demangle_init_info (const char *mangled, int options, size_t len,
+ struct d_info *di)
+{
+ di->s = mangled;
+ di->send = mangled + len;
+ di->options = options;
+
+ di->n = mangled;
+
+ /* We can not need more components than twice the number of chars in
+ the mangled string. Most components correspond directly to
+ chars, but the ARGLIST types are exceptions. */
+ di->num_comps = 2 * len;
+ di->next_comp = 0;
+
+ /* Similarly, we can not need more substitutions than there are
+ chars in the mangled string. */
+ di->num_subs = len;
+ di->next_sub = 0;
+ di->did_subs = 0;
+
+ di->last_name = NULL;
+
+ di->expansion = 0;
+}
+
+/* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled
+ name, return a buffer allocated with malloc holding the demangled
+ name. OPTIONS is the usual libiberty demangler options. On
+ success, this sets *PALC to the allocated size of the returned
+ buffer. On failure, this sets *PALC to 0 for a bad name, or 1 for
+ a memory allocation failure. On failure, this returns NULL. */
+
+static char *
+d_demangle (const char* mangled, int options, size_t *palc)
+{
+ size_t len;
+ int type;
+ struct d_info di;
+ struct demangle_component *dc;
+ int estimate;
+ char *ret;
+
+ *palc = 0;
+
+ len = strlen (mangled);
+
+ if (mangled[0] == '_' && mangled[1] == 'Z')
+ type = 0;
+ else if (strncmp (mangled, "_GLOBAL_", 8) == 0
+ && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
+ && (mangled[9] == 'D' || mangled[9] == 'I')
+ && mangled[10] == '_')
+ {
+ char *r;
+
+ r = (char *) malloc (40 + len - 11);
+ if (r == NULL)
+ *palc = 1;
+ else
+ {
+ if (mangled[9] == 'I')
+ strcpy (r, "global constructors keyed to ");
+ else
+ strcpy (r, "global destructors keyed to ");
+ strcat (r, mangled + 11);
+ }
+ return r;
+ }
+ else
+ {
+ if ((options & DMGL_TYPES) == 0)
+ return NULL;
+ type = 1;
+ }
+
+ cplus_demangle_init_info (mangled, options, len, &di);
+
+ {
+#ifdef CP_DYNAMIC_ARRAYS
+ __extension__ struct demangle_component comps[di.num_comps];
+ __extension__ struct demangle_component *subs[di.num_subs];
+
+ di.comps = &comps[0];
+ di.subs = &subs[0];
+#else
+ di.comps = ((struct demangle_component *)
+ malloc (di.num_comps * sizeof (struct demangle_component)));
+ di.subs = ((struct demangle_component **)
+ malloc (di.num_subs * sizeof (struct demangle_component *)));
+ if (di.comps == NULL || di.subs == NULL)
+ {
+ if (di.comps != NULL)
+ free (di.comps);
+ if (di.subs != NULL)
+ free (di.subs);
+ *palc = 1;
+ return NULL;
+ }
+#endif
+
+ if (! type)
+ dc = cplus_demangle_mangled_name (&di, 1);
+ else
+ dc = cplus_demangle_type (&di);
+
+ /* If DMGL_PARAMS is set, then if we didn't consume the entire
+ mangled string, then we didn't successfully demangle it. If
+ DMGL_PARAMS is not set, we didn't look at the trailing
+ parameters. */
+ if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
+ dc = NULL;
+
+#ifdef CP_DEMANGLE_DEBUG
+ if (dc == NULL)
+ printf ("failed demangling\n");
+ else
+ d_dump (dc, 0);
+#endif
+
+ /* We try to guess the length of the demangled string, to minimize
+ calls to realloc during demangling. */
+ estimate = len + di.expansion + 10 * di.did_subs;
+ estimate += estimate / 8;
+
+ ret = NULL;
+ if (dc != NULL)
+ ret = cplus_demangle_print (options, dc, estimate, palc);
+
+#ifndef CP_DYNAMIC_ARRAYS
+ free (di.comps);
+ free (di.subs);
+#endif
+
+#ifdef CP_DEMANGLE_DEBUG
+ if (ret != NULL)
+ {
+ int rlen;
+
+ rlen = strlen (ret);
+ if (rlen > 2 * estimate)
+ printf ("*** Length %d much greater than estimate %d\n",
+ rlen, estimate);
+ else if (rlen > estimate)
+ printf ("*** Length %d greater than estimate %d\n",
+ rlen, estimate);
+ else if (rlen < estimate / 2)
+ printf ("*** Length %d much less than estimate %d\n",
+ rlen, estimate);
+ }
+#endif
+ }
+
+ return ret;
+}
+
+#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
+
+extern char *__cxa_demangle (const char *, char *, size_t *, int *);
+
+/* ia64 ABI-mandated entry point in the C++ runtime library for
+ performing demangling. MANGLED_NAME is a NUL-terminated character
+ string containing the name to be demangled.
+
+ OUTPUT_BUFFER is a region of memory, allocated with malloc, of
+ *LENGTH bytes, into which the demangled name is stored. If
+ OUTPUT_BUFFER is not long enough, it is expanded using realloc.
+ OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
+ is placed in a region of memory allocated with malloc.
+
+ If LENGTH is non-NULL, the length of the buffer conaining the
+ demangled name, is placed in *LENGTH.
+
+ The return value is a pointer to the start of the NUL-terminated
+ demangled name, or NULL if the demangling fails. The caller is
+ responsible for deallocating this memory using free.
+
+ *STATUS is set to one of the following values:
+ 0: The demangling operation succeeded.
+ -1: A memory allocation failure occurred.
+ -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
+ -3: One of the arguments is invalid.
+
+ The demangling is performed using the C++ ABI mangling rules, with
+ GNU extensions. */
+
+char *
+__cxa_demangle (const char *mangled_name, char *output_buffer,
+ size_t *length, int *status)
+{
+ char *demangled;
+ size_t alc;
+
+ if (mangled_name == NULL)
+ {
+ if (status != NULL)
+ *status = -3;
+ return NULL;
+ }
+
+ if (output_buffer != NULL && length == NULL)
+ {
+ if (status != NULL)
+ *status = -3;
+ return NULL;
+ }
+
+ demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc);
+
+ if (demangled == NULL)
+ {
+ if (status != NULL)
+ {
+ if (alc == 1)
+ *status = -1;
+ else
+ *status = -2;
+ }
+ return NULL;
+ }
+
+ if (output_buffer == NULL)
+ {
+ if (length != NULL)
+ *length = alc;
+ }
+ else
+ {
+ if (strlen (demangled) < *length)
+ {
+ strcpy (output_buffer, demangled);
+ free (demangled);
+ demangled = output_buffer;
+ }
+ else
+ {
+ free (output_buffer);
+ *length = alc;
+ }
+ }
+
+ if (status != NULL)
+ *status = 0;
+
+ return demangled;
+}
+
+#else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
+
+/* Entry point for libiberty demangler. If MANGLED is a g++ v3 ABI
+ mangled name, return a buffer allocated with malloc holding the
+ demangled name. Otherwise, return NULL. */
+
+char *
+cplus_demangle_v3 (const char* mangled, int options)
+{
+ size_t alc;
+
+ return d_demangle (mangled, options, &alc);
+}
+
+/* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
+ conventions, but the output formatting is a little different.
+ This instructs the C++ demangler not to emit pointer characters ("*"), and
+ to use Java's namespace separator symbol ("." instead of "::"). It then
+ does an additional pass over the demangled output to replace instances
+ of JArray<TYPE> with TYPE[]. */
+
+char *
+java_demangle_v3 (const char* mangled)
+{
+ size_t alc;
+ char *demangled;
+ int nesting;
+ char *from;
+ char *to;
+
+ demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX,
+ &alc);
+
+ if (demangled == NULL)
+ return NULL;
+
+ nesting = 0;
+ from = demangled;
+ to = from;
+ while (*from != '\0')
+ {
+ if (strncmp (from, "JArray<", 7) == 0)
+ {
+ from += 7;
+ ++nesting;
+ }
+ else if (nesting > 0 && *from == '>')
+ {
+ while (to > demangled && to[-1] == ' ')
+ --to;
+ *to++ = '[';
+ *to++ = ']';
+ --nesting;
+ ++from;
+ }
+ else
+ *to++ = *from++;
+ }
+
+ *to = '\0';
+
+ return demangled;
+}
+
+#endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
+
+#ifndef IN_GLIBCPP_V3
+
+/* Demangle a string in order to find out whether it is a constructor
+ or destructor. Return non-zero on success. Set *CTOR_KIND and
+ *DTOR_KIND appropriately. */
+
+static int
+is_ctor_or_dtor (const char *mangled,
+ enum gnu_v3_ctor_kinds *ctor_kind,
+ enum gnu_v3_dtor_kinds *dtor_kind)
+{
+ struct d_info di;
+ struct demangle_component *dc;
+ int ret;
+
+ *ctor_kind = (enum gnu_v3_ctor_kinds) 0;
+ *dtor_kind = (enum gnu_v3_dtor_kinds) 0;
+
+ cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
+
+ {
+#ifdef CP_DYNAMIC_ARRAYS
+ __extension__ struct demangle_component comps[di.num_comps];
+ __extension__ struct demangle_component *subs[di.num_subs];
+
+ di.comps = &comps[0];
+ di.subs = &subs[0];
+#else
+ di.comps = ((struct demangle_component *)
+ malloc (di.num_comps * sizeof (struct demangle_component)));
+ di.subs = ((struct demangle_component **)
+ malloc (di.num_subs * sizeof (struct demangle_component *)));
+ if (di.comps == NULL || di.subs == NULL)
+ {
+ if (di.comps != NULL)
+ free (di.comps);
+ if (di.subs != NULL)
+ free (di.subs);
+ return 0;
+ }
+#endif
+
+ dc = cplus_demangle_mangled_name (&di, 1);
+
+ /* Note that because we did not pass DMGL_PARAMS, we don't expect
+ to demangle the entire string. */
+
+ ret = 0;
+ while (dc != NULL)
+ {
+ switch (dc->type)
+ {
+ default:
+ dc = NULL;
+ break;
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ dc = d_left (dc);
+ break;
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ dc = d_right (dc);
+ break;
+ case DEMANGLE_COMPONENT_CTOR:
+ *ctor_kind = dc->u.s_ctor.kind;
+ ret = 1;
+ dc = NULL;
+ break;
+ case DEMANGLE_COMPONENT_DTOR:
+ *dtor_kind = dc->u.s_dtor.kind;
+ ret = 1;
+ dc = NULL;
+ break;
+ }
+ }
+
+#ifndef CP_DYNAMIC_ARRAYS
+ free (di.subs);
+ free (di.comps);
+#endif
+ }
+
+ return ret;
+}
+
+/* Return whether NAME is the mangled form of a g++ V3 ABI constructor
+ name. A non-zero return indicates the type of constructor. */
+
+enum gnu_v3_ctor_kinds
+is_gnu_v3_mangled_ctor (const char *name)
+{
+ enum gnu_v3_ctor_kinds ctor_kind;
+ enum gnu_v3_dtor_kinds dtor_kind;
+
+ if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
+ return (enum gnu_v3_ctor_kinds) 0;
+ return ctor_kind;
+}
+
+
+/* Return whether NAME is the mangled form of a g++ V3 ABI destructor
+ name. A non-zero return indicates the type of destructor. */
+
+enum gnu_v3_dtor_kinds
+is_gnu_v3_mangled_dtor (const char *name)
+{
+ enum gnu_v3_ctor_kinds ctor_kind;
+ enum gnu_v3_dtor_kinds dtor_kind;
+
+ if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
+ return (enum gnu_v3_dtor_kinds) 0;
+ return dtor_kind;
+}
+
+#endif /* IN_GLIBCPP_V3 */
+
diff --git a/third_party/libiberty.h b/third_party/libiberty.h
new file mode 100644
index 00000000..70f8b104
--- /dev/null
+++ b/third_party/libiberty.h
@@ -0,0 +1,634 @@
+/* Function declarations for libiberty.
+
+ Copyright 2001, 2002, 2005 Free Software Foundation, Inc.
+
+ Note - certain prototypes declared in this header file are for
+ functions whoes implementation copyright does not belong to the
+ FSF. Those prototypes are present in this file for reference
+ purposes only and their presence in this file should not construed
+ as an indication of ownership by the FSF of the implementation of
+ those functions in any way or form whatsoever.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ 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.
+
+ Written by Cygnus Support, 1994.
+
+ The libiberty library provides a number of functions which are
+ missing on some operating systems. We do not declare those here,
+ to avoid conflicts with the system header files on operating
+ systems that do support those functions. In this file we only
+ declare those functions which are specific to libiberty. */
+
+#ifndef LIBIBERTY_H
+#define LIBIBERTY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+
+/* Get a definition for size_t. */
+#include <stddef.h>
+/* Get a definition for va_list. */
+#include <stdarg.h>
+
+#include <stdio.h>
+
+/* If the OS supports it, ensure that the supplied stream is setup to
+ avoid any multi-threaded locking. Otherwise leave the FILE pointer
+ unchanged. If the stream is NULL do nothing. */
+
+extern void unlock_stream (FILE *);
+
+/* If the OS supports it, ensure that the standard I/O streams, stdin,
+ stdout and stderr are setup to avoid any multi-threaded locking.
+ Otherwise do nothing. */
+
+extern void unlock_std_streams (void);
+
+/* Open and return a FILE pointer. If the OS supports it, ensure that
+ the stream is setup to avoid any multi-threaded locking. Otherwise
+ return the FILE pointer unchanged. */
+
+extern FILE *fopen_unlocked (const char *, const char *);
+extern FILE *fdopen_unlocked (int, const char *);
+extern FILE *freopen_unlocked (const char *, const char *, FILE *);
+
+/* Build an argument vector from a string. Allocates memory using
+ malloc. Use freeargv to free the vector. */
+
+extern char **buildargv (const char *) ATTRIBUTE_MALLOC;
+
+/* Free a vector returned by buildargv. */
+
+extern void freeargv (char **);
+
+/* Duplicate an argument vector. Allocates memory using malloc. Use
+ freeargv to free the vector. */
+
+extern char **dupargv (char **) ATTRIBUTE_MALLOC;
+
+/* Expand "@file" arguments in argv. */
+
+extern void expandargv PARAMS ((int *, char ***));
+
+/* Return the last component of a path name. Note that we can't use a
+ prototype here because the parameter is declared inconsistently
+ across different systems, sometimes as "char *" and sometimes as
+ "const char *" */
+
+/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is
+ undefined, we haven't run the autoconf check so provide the
+ declaration without arguments. If it is 0, we checked and failed
+ to find the declaration so provide a fully prototyped one. If it
+ is 1, we found it so don't provide any declaration at all. */
+#if !HAVE_DECL_BASENAME
+#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME)
+extern char *basename (const char *);
+#else
+/* Do not allow basename to be used if there is no prototype seen. We
+ either need to use the above prototype or have one from
+ autoconf which would result in HAVE_DECL_BASENAME being set. */
+#define basename basename_cannot_be_used_without_a_prototype
+#endif
+#endif
+
+/* A well-defined basename () that is always compiled in. */
+
+extern const char *lbasename (const char *);
+
+/* A well-defined realpath () that is always compiled in. */
+
+extern char *lrealpath (const char *);
+
+/* Concatenate an arbitrary number of strings. You must pass NULL as
+ the last argument of this function, to terminate the list of
+ strings. Allocates memory using xmalloc. */
+
+extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+
+/* Concatenate an arbitrary number of strings. You must pass NULL as
+ the last argument of this function, to terminate the list of
+ strings. Allocates memory using xmalloc. The first argument is
+ not one of the strings to be concatenated, but if not NULL is a
+ pointer to be freed after the new string is created, similar to the
+ way xrealloc works. */
+
+extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+
+/* Determine the length of concatenating an arbitrary number of
+ strings. You must pass NULL as the last argument of this function,
+ to terminate the list of strings. */
+
+extern unsigned long concat_length (const char *, ...) ATTRIBUTE_SENTINEL;
+
+/* Concatenate an arbitrary number of strings into a SUPPLIED area of
+ memory. You must pass NULL as the last argument of this function,
+ to terminate the list of strings. The supplied memory is assumed
+ to be large enough. */
+
+extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_SENTINEL;
+
+/* Concatenate an arbitrary number of strings into a GLOBAL area of
+ memory. You must pass NULL as the last argument of this function,
+ to terminate the list of strings. The supplied memory is assumed
+ to be large enough. */
+
+extern char *concat_copy2 (const char *, ...) ATTRIBUTE_SENTINEL;
+
+/* This is the global area used by concat_copy2. */
+
+extern char *libiberty_concat_ptr;
+
+/* Concatenate an arbitrary number of strings. You must pass NULL as
+ the last argument of this function, to terminate the list of
+ strings. Allocates memory using alloca. The arguments are
+ evaluated twice! */
+#define ACONCAT(ACONCAT_PARAMS) \
+ (libiberty_concat_ptr = (char *) alloca (concat_length ACONCAT_PARAMS + 1), \
+ concat_copy2 ACONCAT_PARAMS)
+
+/* Check whether two file descriptors refer to the same file. */
+
+extern int fdmatch (int fd1, int fd2);
+
+/* Return the position of the first bit set in the argument. */
+/* Prototypes vary from system to system, so we only provide a
+ prototype on systems where we know that we need it. */
+#if defined (HAVE_DECL_FFS) && !HAVE_DECL_FFS
+extern int ffs(int);
+#endif
+
+/* Get the working directory. The result is cached, so don't call
+ chdir() between calls to getpwd(). */
+
+extern char * getpwd (void);
+
+/* Get the current time. */
+/* Prototypes vary from system to system, so we only provide a
+ prototype on systems where we know that we need it. */
+#ifdef __MINGW32__
+/* Forward declaration to avoid #include <sys/time.h>. */
+struct timeval;
+extern int gettimeofday (struct timeval *, void *);
+#endif
+
+/* Get the amount of time the process has run, in microseconds. */
+
+extern long get_run_time (void);
+
+/* Generate a relocated path to some installation directory. Allocates
+ return value using malloc. */
+
+extern char *make_relative_prefix (const char *, const char *,
+ const char *) ATTRIBUTE_MALLOC;
+
+/* LLVM LOCAL begin */
+/* Generate a relocated path to some installation directory without
+ attempting to follow any soft links. Allocates
+ return value using malloc. */
+
+extern char *make_relative_prefix_ignore_links (const char *, const char *,
+ const char *) ATTRIBUTE_MALLOC;
+/* LLVM LOCAL end */
+
+/* Choose a temporary directory to use for scratch files. */
+
+extern char *choose_temp_base (void) ATTRIBUTE_MALLOC;
+
+/* Return a temporary file name or NULL if unable to create one. */
+
+extern char *make_temp_file (const char *) ATTRIBUTE_MALLOC;
+
+/* Remove a link to a file unless it is special. */
+
+extern int unlink_if_ordinary (const char *);
+
+/* Allocate memory filled with spaces. Allocates using malloc. */
+
+extern const char *spaces (int count);
+
+/* Return the maximum error number for which strerror will return a
+ string. */
+
+extern int errno_max (void);
+
+/* Return the name of an errno value (e.g., strerrno (EINVAL) returns
+ "EINVAL"). */
+
+extern const char *strerrno (int);
+
+/* Given the name of an errno value, return the value. */
+
+extern int strtoerrno (const char *);
+
+/* ANSI's strerror(), but more robust. */
+
+extern char *xstrerror (int);
+
+/* Return the maximum signal number for which strsignal will return a
+ string. */
+
+extern int signo_max (void);
+
+/* Return a signal message string for a signal number
+ (e.g., strsignal (SIGHUP) returns something like "Hangup"). */
+/* This is commented out as it can conflict with one in system headers.
+ We still document its existence though. */
+
+/*extern const char *strsignal (int);*/
+
+/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns
+ "SIGHUP"). */
+
+extern const char *strsigno (int);
+
+/* Given the name of a signal, return its number. */
+
+extern int strtosigno (const char *);
+
+/* Register a function to be run by xexit. Returns 0 on success. */
+
+extern int xatexit (void (*fn) (void));
+
+/* Exit, calling all the functions registered with xatexit. */
+
+extern void xexit (int status) ATTRIBUTE_NORETURN;
+
+/* Set the program name used by xmalloc. */
+
+extern void xmalloc_set_program_name (const char *);
+
+/* Report an allocation failure. */
+extern void xmalloc_failed (size_t) ATTRIBUTE_NORETURN;
+
+/* Allocate memory without fail. If malloc fails, this will print a
+ message to stderr (using the name set by xmalloc_set_program_name,
+ if any) and then call xexit. */
+
+extern void *xmalloc (size_t) ATTRIBUTE_MALLOC;
+
+/* Reallocate memory without fail. This works like xmalloc. Note,
+ realloc type functions are not suitable for attribute malloc since
+ they may return the same address across multiple calls. */
+
+extern void *xrealloc (void *, size_t);
+
+/* Allocate memory without fail and set it to zero. This works like
+ xmalloc. */
+
+extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
+
+/* Copy a string into a memory buffer without fail. */
+
+extern char *xstrdup (const char *) ATTRIBUTE_MALLOC;
+
+/* Copy at most N characters from string into a buffer without fail. */
+
+extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC;
+
+/* Copy an existing memory buffer to a new memory buffer without fail. */
+
+extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC;
+
+/* APPLE LOCAL begin retune gc params 6124839 */
+extern unsigned int ncpu_available (void);
+/* APPLE LOCAL end retune gc params 6124839 */
+
+/* Physical memory routines. Return values are in BYTES. */
+extern double physmem_total (void);
+extern double physmem_available (void);
+
+
+/* These macros provide a K&R/C89/C++-friendly way of allocating structures
+ with nice encapsulation. The XDELETE*() macros are technically
+ superfluous, but provided here for symmetry. Using them consistently
+ makes it easier to update client code to use different allocators such
+ as new/delete and new[]/delete[]. */
+
+/* Scalar allocators. */
+
+#define XNEW(T) ((T *) xmalloc (sizeof (T)))
+#define XCNEW(T) ((T *) xcalloc (1, sizeof (T)))
+#define XDELETE(P) free ((void*) (P))
+
+/* Array allocators. */
+
+#define XNEWVEC(T, N) ((T *) xmalloc (sizeof (T) * (N)))
+#define XCNEWVEC(T, N) ((T *) xcalloc ((N), sizeof (T)))
+#define XRESIZEVEC(T, P, N) ((T *) xrealloc ((void *) (P), sizeof (T) * (N)))
+#define XDELETEVEC(P) free ((void*) (P))
+
+/* Allocators for variable-sized structures and raw buffers. */
+
+#define XNEWVAR(T, S) ((T *) xmalloc ((S)))
+#define XCNEWVAR(T, S) ((T *) xcalloc (1, (S)))
+#define XRESIZEVAR(T, P, S) ((T *) xrealloc ((P), (S)))
+
+/* Type-safe obstack allocator. */
+
+#define XOBNEW(O, T) ((T *) obstack_alloc ((O), sizeof (T)))
+#define XOBFINISH(O, T) ((T) obstack_finish ((O)))
+
+/* hex character manipulation routines */
+
+#define _hex_array_size 256
+#define _hex_bad 99
+extern const unsigned char _hex_value[_hex_array_size];
+extern void hex_init (void);
+#define hex_p(c) (hex_value (c) != _hex_bad)
+/* If you change this, note well: Some code relies on side effects in
+ the argument being performed exactly once. */
+#define hex_value(c) ((unsigned int) _hex_value[(unsigned char) (c)])
+
+/* Flags for pex_init. These are bits to be or'ed together. */
+
+/* Record subprocess times, if possible. */
+#define PEX_RECORD_TIMES 0x1
+
+/* Use pipes for communication between processes, if possible. */
+#define PEX_USE_PIPES 0x2
+
+/* Save files used for communication between processes. */
+#define PEX_SAVE_TEMPS 0x4
+
+/* Prepare to execute one or more programs, with standard output of
+ each program fed to standard input of the next.
+ FLAGS As above.
+ PNAME The name of the program to report in error messages.
+ TEMPBASE A base name to use for temporary files; may be NULL to
+ use a random name.
+ Returns NULL on error. */
+
+extern struct pex_obj *pex_init (int flags, const char *pname,
+ const char *tempbase);
+
+/* Flags for pex_run. These are bits to be or'ed together. */
+
+/* Last program in pipeline. Standard output of program goes to
+ OUTNAME, or, if OUTNAME is NULL, to standard output of caller. Do
+ not set this if you want to call pex_read_output. After this is
+ set, pex_run may no longer be called with the same struct
+ pex_obj. */
+#define PEX_LAST 0x1
+
+/* Search for program in executable search path. */
+#define PEX_SEARCH 0x2
+
+/* OUTNAME is a suffix. */
+#define PEX_SUFFIX 0x4
+
+/* Send program's standard error to standard output. */
+#define PEX_STDERR_TO_STDOUT 0x8
+
+/* Input file should be opened in binary mode. This flag is ignored
+ on Unix. */
+#define PEX_BINARY_INPUT 0x10
+
+/* Output file should be opened in binary mode. This flag is ignored
+ on Unix. For proper behaviour PEX_BINARY_INPUT and
+ PEX_BINARY_OUTPUT have to match appropriately--i.e., a call using
+ PEX_BINARY_OUTPUT should be followed by a call using
+ PEX_BINARY_INPUT. */
+#define PEX_BINARY_OUTPUT 0x20
+
+/* Execute one program. Returns NULL on success. On error returns an
+ error string (typically just the name of a system call); the error
+ string is statically allocated.
+
+ OBJ Returned by pex_init.
+
+ FLAGS As above.
+
+ EXECUTABLE The program to execute.
+
+ ARGV NULL terminated array of arguments to pass to the program.
+
+ OUTNAME Sets the output file name as follows:
+
+ PEX_SUFFIX set (OUTNAME may not be NULL):
+ TEMPBASE parameter to pex_init not NULL:
+ Output file name is the concatenation of TEMPBASE
+ and OUTNAME.
+ TEMPBASE is NULL:
+ Output file name is a random file name ending in
+ OUTNAME.
+ PEX_SUFFIX not set:
+ OUTNAME not NULL:
+ Output file name is OUTNAME.
+ OUTNAME NULL, TEMPBASE not NULL:
+ Output file name is randomly chosen using
+ TEMPBASE.
+ OUTNAME NULL, TEMPBASE NULL:
+ Output file name is randomly chosen.
+
+ If PEX_LAST is not set, the output file name is the
+ name to use for a temporary file holding stdout, if
+ any (there will not be a file if PEX_USE_PIPES is set
+ and the system supports pipes). If a file is used, it
+ will be removed when no longer needed unless
+ PEX_SAVE_TEMPS is set.
+
+ If PEX_LAST is set, and OUTNAME is not NULL, standard
+ output is written to the output file name. The file
+ will not be removed. If PEX_LAST and PEX_SUFFIX are
+ both set, TEMPBASE may not be NULL.
+
+ ERRNAME If not NULL, this is the name of a file to which
+ standard error is written. If NULL, standard error of
+ the program is standard error of the caller.
+
+ ERR On an error return, *ERR is set to an errno value, or
+ to 0 if there is no relevant errno.
+*/
+
+extern const char *pex_run (struct pex_obj *obj, int flags,
+ const char *executable, char * const *argv,
+ const char *outname, const char *errname,
+ int *err);
+
+/* As for pex_run (), but takes an extra parameter to enable the
+ environment for the child process to be specified.
+
+ ENV The environment for the child process, specified as
+ an array of character pointers. Each element of the
+ array should point to a string of the form VAR=VALUE,
+ with the exception of the last element which must be
+ a null pointer.
+*/
+
+extern const char *pex_run_in_environment (struct pex_obj *obj, int flags,
+ const char *executable,
+ char * const *argv,
+ char * const *env,
+ const char *outname,
+ const char *errname, int *err);
+
+/* Return a stream for a temporary file to pass to the first program
+ in the pipeline as input. The file name is chosen as for pex_run.
+ pex_run closes the file automatically; don't close it yourself. */
+
+extern FILE *pex_input_file (struct pex_obj *obj, int flags,
+ const char *in_name);
+
+/* Return a stream for a pipe connected to the standard input of the
+ first program in the pipeline. You must have passed
+ `PEX_USE_PIPES' to `pex_init'. Close the returned stream
+ yourself. */
+
+extern FILE *pex_input_pipe (struct pex_obj *obj, int binary);
+
+/* Read the standard output of the last program to be executed.
+ pex_run can not be called after this. BINARY should be non-zero if
+ the file should be opened in binary mode; this is ignored on Unix.
+ Returns NULL on error. Don't call fclose on the returned FILE; it
+ will be closed by pex_free. */
+
+extern FILE *pex_read_output (struct pex_obj *, int binary);
+
+/* Return exit status of all programs in VECTOR. COUNT indicates the
+ size of VECTOR. The status codes in the vector are in the order of
+ the calls to pex_run. Returns 0 on error, 1 on success. */
+
+extern int pex_get_status (struct pex_obj *, int count, int *vector);
+
+/* Return times of all programs in VECTOR. COUNT indicates the size
+ of VECTOR. struct pex_time is really just struct timeval, but that
+ is not portable to all systems. Returns 0 on error, 1 on
+ success. */
+
+struct pex_time
+{
+ unsigned long user_seconds;
+ unsigned long user_microseconds;
+ unsigned long system_seconds;
+ unsigned long system_microseconds;
+};
+
+extern int pex_get_times (struct pex_obj *, int count,
+ struct pex_time *vector);
+
+/* Clean up a pex_obj. */
+
+extern void pex_free (struct pex_obj *);
+
+/* Just execute one program. Return value is as for pex_run.
+ FLAGS Combination of PEX_SEARCH and PEX_STDERR_TO_STDOUT.
+ EXECUTABLE As for pex_run.
+ ARGV As for pex_run.
+ PNAME As for pex_init.
+ OUTNAME As for pex_run when PEX_LAST is set.
+ ERRNAME As for pex_run.
+ STATUS Set to exit status on success.
+ ERR As for pex_run.
+*/
+
+extern const char *pex_one (int flags, const char *executable,
+ char * const *argv, const char *pname,
+ const char *outname, const char *errname,
+ int *status, int *err);
+
+/* pexecute and pwait are the old pexecute interface, still here for
+ backward compatibility. Don't use these for new code. Instead,
+ use pex_init/pex_run/pex_get_status/pex_free, or pex_one. */
+
+/* Definitions used by the pexecute routine. */
+
+#define PEXECUTE_FIRST 1
+#define PEXECUTE_LAST 2
+#define PEXECUTE_ONE (PEXECUTE_FIRST + PEXECUTE_LAST)
+#define PEXECUTE_SEARCH 4
+#define PEXECUTE_VERBOSE 8
+
+/* Execute a program. */
+
+extern int pexecute (const char *, char * const *, const char *,
+ const char *, char **, char **, int);
+
+/* Wait for pexecute to finish. */
+
+extern int pwait (int, int *, int);
+
+#if !HAVE_DECL_ASPRINTF
+/* Like sprintf but provides a pointer to malloc'd storage, which must
+ be freed by the caller. */
+
+extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2;
+#endif
+
+#if !HAVE_DECL_VASPRINTF
+/* Like vsprintf but provides a pointer to malloc'd storage, which
+ must be freed by the caller. */
+
+extern int vasprintf (char **, const char *, va_list) ATTRIBUTE_PRINTF(2,0);
+#endif
+
+#if defined(HAVE_DECL_SNPRINTF) && !HAVE_DECL_SNPRINTF
+/* Like sprintf but prints at most N characters. */
+extern int snprintf (char *, size_t, const char *, ...) ATTRIBUTE_PRINTF_3;
+#endif
+
+#if defined(HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF
+/* Like vsprintf but prints at most N characters. */
+extern int vsnprintf (char *, size_t, const char *, va_list) ATTRIBUTE_PRINTF(3,0);
+#endif
+
+#if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP
+/* Compare version strings. */
+extern int strverscmp (const char *, const char *);
+#endif
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+/* Drastically simplified alloca configurator. If we're using GCC,
+ we use __builtin_alloca; otherwise we use the C alloca. The C
+ alloca is always available. You can override GCC by defining
+ USE_C_ALLOCA yourself. The canonical autoconf macro C_ALLOCA is
+ also set/unset as it is often used to indicate whether code needs
+ to call alloca(0). */
+extern void *C_alloca (size_t) ATTRIBUTE_MALLOC;
+#undef alloca
+#if GCC_VERSION >= 2000 && !defined USE_C_ALLOCA
+# define alloca(x) __builtin_alloca(x)
+# undef C_ALLOCA
+# define ASTRDUP(X) \
+ (__extension__ ({ const char *const libiberty_optr = (X); \
+ const unsigned long libiberty_len = strlen (libiberty_optr) + 1; \
+ char *const libiberty_nptr = (char *const) alloca (libiberty_len); \
+ (char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len); }))
+#else
+# define alloca(x) C_alloca(x)
+# undef USE_C_ALLOCA
+# define USE_C_ALLOCA 1
+# undef C_ALLOCA
+# define C_ALLOCA 1
+extern const char *libiberty_optr;
+extern char *libiberty_nptr;
+extern unsigned long libiberty_len;
+# define ASTRDUP(X) \
+ (libiberty_optr = (X), \
+ libiberty_len = strlen (libiberty_optr) + 1, \
+ libiberty_nptr = (char *) alloca (libiberty_len), \
+ (char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* ! defined (LIBIBERTY_H) */