1130561Sobrien/* Demangler for g++ V3 ABI. 2218822Sdim Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 3130561Sobrien Written by Ian Lance Taylor <ian@wasabisystems.com>. 468765Sobrien 5130561Sobrien This file is part of the libiberty library, which is part of GCC. 677298Sobrien 7130561Sobrien This file is free software; you can redistribute it and/or modify 868765Sobrien it under the terms of the GNU General Public License as published by 968765Sobrien the Free Software Foundation; either version 2 of the License, or 1068765Sobrien (at your option) any later version. 1168765Sobrien 12104834Sobrien In addition to the permissions in the GNU General Public License, the 13104834Sobrien Free Software Foundation gives you unlimited permission to link the 14104834Sobrien compiled version of this file into combinations with other programs, 15104834Sobrien and to distribute those combinations without any restriction coming 16104834Sobrien from the use of this file. (The General Public License restrictions 17104834Sobrien do apply in other respects; for example, they cover modification of 18104834Sobrien the file, and distribution when not linked into a combined 19104834Sobrien executable.) 20104834Sobrien 2168765Sobrien This program is distributed in the hope that it will be useful, 2268765Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 2368765Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2468765Sobrien GNU General Public License for more details. 2568765Sobrien 2668765Sobrien You should have received a copy of the GNU General Public License 2768765Sobrien along with this program; if not, write to the Free Software 28218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 2968765Sobrien*/ 3068765Sobrien 31130561Sobrien/* This code implements a demangler for the g++ V3 ABI. The ABI is 32130561Sobrien described on this web page: 33130561Sobrien http://www.codesourcery.com/cxx-abi/abi.html#mangling 3468765Sobrien 35130561Sobrien This code was written while looking at the demangler written by 36130561Sobrien Alex Samuel <samuel@codesourcery.com>. 37130561Sobrien 38130561Sobrien This code first pulls the mangled name apart into a list of 39130561Sobrien components, and then walks the list generating the demangled 40130561Sobrien name. 41130561Sobrien 42130561Sobrien This file will normally define the following functions, q.v.: 43130561Sobrien char *cplus_demangle_v3(const char *mangled, int options) 44130561Sobrien char *java_demangle_v3(const char *mangled) 45218822Sdim int cplus_demangle_v3_callback(const char *mangled, int options, 46218822Sdim demangle_callbackref callback) 47218822Sdim int java_demangle_v3_callback(const char *mangled, 48218822Sdim demangle_callbackref callback) 49130561Sobrien enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name) 50130561Sobrien enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name) 51130561Sobrien 52130561Sobrien Also, the interface to the component list is public, and defined in 53130561Sobrien demangle.h. The interface consists of these types, which are 54130561Sobrien defined in demangle.h: 55130561Sobrien enum demangle_component_type 56130561Sobrien struct demangle_component 57218822Sdim demangle_callbackref 58130561Sobrien and these functions defined in this file: 59130561Sobrien cplus_demangle_fill_name 60130561Sobrien cplus_demangle_fill_extended_operator 61130561Sobrien cplus_demangle_fill_ctor 62130561Sobrien cplus_demangle_fill_dtor 63130561Sobrien cplus_demangle_print 64218822Sdim cplus_demangle_print_callback 65130561Sobrien and other functions defined in the file cp-demint.c. 66130561Sobrien 67130561Sobrien This file also defines some other functions and variables which are 68130561Sobrien only to be used by the file cp-demint.c. 69130561Sobrien 70130561Sobrien Preprocessor macros you can define while compiling this file: 71130561Sobrien 72130561Sobrien IN_LIBGCC2 73218822Sdim If defined, this file defines the following functions, q.v.: 74130561Sobrien char *__cxa_demangle (const char *mangled, char *buf, size_t *len, 75130561Sobrien int *status) 76218822Sdim int __gcclibcxx_demangle_callback (const char *, 77218822Sdim void (*) 78218822Sdim (const char *, size_t, void *), 79218822Sdim void *) 80218822Sdim instead of cplus_demangle_v3[_callback]() and 81218822Sdim java_demangle_v3[_callback](). 82130561Sobrien 83130561Sobrien IN_GLIBCPP_V3 84218822Sdim If defined, this file defines only __cxa_demangle() and 85218822Sdim __gcclibcxx_demangle_callback(), and no other publically visible 86218822Sdim functions or variables. 87130561Sobrien 88130561Sobrien STANDALONE_DEMANGLER 89130561Sobrien If defined, this file defines a main() function which demangles 90130561Sobrien any arguments, or, if none, demangles stdin. 91130561Sobrien 92130561Sobrien CP_DEMANGLE_DEBUG 93130561Sobrien If defined, turns on debugging mode, which prints information on 94130561Sobrien stdout about the mangled string. This is not generally useful. 95130561Sobrien*/ 96130561Sobrien 97218822Sdim#if defined (_AIX) && !defined (__GNUC__) 98218822Sdim #pragma alloca 99218822Sdim#endif 100218822Sdim 10168765Sobrien#ifdef HAVE_CONFIG_H 10268765Sobrien#include "config.h" 10368765Sobrien#endif 10468765Sobrien 105130561Sobrien#include <stdio.h> 10668765Sobrien 10768765Sobrien#ifdef HAVE_STDLIB_H 10868765Sobrien#include <stdlib.h> 10968765Sobrien#endif 11068765Sobrien#ifdef HAVE_STRING_H 11168765Sobrien#include <string.h> 11268765Sobrien#endif 11368765Sobrien 114218822Sdim#ifdef HAVE_ALLOCA_H 115218822Sdim# include <alloca.h> 116218822Sdim#else 117218822Sdim# ifndef alloca 118218822Sdim# ifdef __GNUC__ 119218822Sdim# define alloca __builtin_alloca 120218822Sdim# else 121218822Sdimextern char *alloca (); 122218822Sdim# endif /* __GNUC__ */ 123218822Sdim# endif /* alloca */ 124218822Sdim#endif /* HAVE_ALLOCA_H */ 125218822Sdim 12668765Sobrien#include "ansidecl.h" 12768765Sobrien#include "libiberty.h" 12868765Sobrien#include "demangle.h" 129130561Sobrien#include "cp-demangle.h" 13068765Sobrien 131130561Sobrien/* If IN_GLIBCPP_V3 is defined, some functions are made static. We 132130561Sobrien also rename them via #define to avoid compiler errors when the 133130561Sobrien static definition conflicts with the extern declaration in a header 134130561Sobrien file. */ 135130561Sobrien#ifdef IN_GLIBCPP_V3 136130561Sobrien 137130561Sobrien#define CP_STATIC_IF_GLIBCPP_V3 static 138130561Sobrien 139130561Sobrien#define cplus_demangle_fill_name d_fill_name 140218822Sdimstatic int d_fill_name (struct demangle_component *, const char *, int); 141130561Sobrien 142130561Sobrien#define cplus_demangle_fill_extended_operator d_fill_extended_operator 143130561Sobrienstatic int 144218822Sdimd_fill_extended_operator (struct demangle_component *, int, 145218822Sdim struct demangle_component *); 146130561Sobrien 147130561Sobrien#define cplus_demangle_fill_ctor d_fill_ctor 148130561Sobrienstatic int 149218822Sdimd_fill_ctor (struct demangle_component *, enum gnu_v3_ctor_kinds, 150218822Sdim struct demangle_component *); 151130561Sobrien 152130561Sobrien#define cplus_demangle_fill_dtor d_fill_dtor 153130561Sobrienstatic int 154218822Sdimd_fill_dtor (struct demangle_component *, enum gnu_v3_dtor_kinds, 155218822Sdim struct demangle_component *); 156130561Sobrien 157130561Sobrien#define cplus_demangle_mangled_name d_mangled_name 158218822Sdimstatic struct demangle_component *d_mangled_name (struct d_info *, int); 159130561Sobrien 160130561Sobrien#define cplus_demangle_type d_type 161218822Sdimstatic struct demangle_component *d_type (struct d_info *); 162130561Sobrien 163130561Sobrien#define cplus_demangle_print d_print 164218822Sdimstatic char *d_print (int, const struct demangle_component *, int, size_t *); 165130561Sobrien 166218822Sdim#define cplus_demangle_print_callback d_print_callback 167218822Sdimstatic int d_print_callback (int, const struct demangle_component *, 168218822Sdim demangle_callbackref, void *); 169218822Sdim 170130561Sobrien#define cplus_demangle_init_info d_init_info 171218822Sdimstatic void d_init_info (const char *, int, size_t, struct d_info *); 172130561Sobrien 173130561Sobrien#else /* ! defined(IN_GLIBCPP_V3) */ 174130561Sobrien#define CP_STATIC_IF_GLIBCPP_V3 175130561Sobrien#endif /* ! defined(IN_GLIBCPP_V3) */ 176130561Sobrien 177130561Sobrien/* See if the compiler supports dynamic arrays. */ 178130561Sobrien 179130561Sobrien#ifdef __GNUC__ 180130561Sobrien#define CP_DYNAMIC_ARRAYS 18168765Sobrien#else 182130561Sobrien#ifdef __STDC__ 183130561Sobrien#ifdef __STDC_VERSION__ 184130561Sobrien#if __STDC_VERSION__ >= 199901L 185130561Sobrien#define CP_DYNAMIC_ARRAYS 186130561Sobrien#endif /* __STDC__VERSION >= 199901L */ 187130561Sobrien#endif /* defined (__STDC_VERSION__) */ 188130561Sobrien#endif /* defined (__STDC__) */ 189130561Sobrien#endif /* ! defined (__GNUC__) */ 19068765Sobrien 191130561Sobrien/* We avoid pulling in the ctype tables, to prevent pulling in 192130561Sobrien additional unresolved symbols when this code is used in a library. 193130561Sobrien FIXME: Is this really a valid reason? This comes from the original 194130561Sobrien V3 demangler code. 19568765Sobrien 196130561Sobrien As of this writing this file has the following undefined references 197218822Sdim when compiled with -DIN_GLIBCPP_V3: realloc, free, memcpy, strcpy, 198218822Sdim strcat, strlen. */ 199130561Sobrien 200130561Sobrien#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 201130561Sobrien#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') 202130561Sobrien#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') 203130561Sobrien 20477298Sobrien/* The prefix prepended by GCC to an identifier represnting the 20577298Sobrien anonymous namespace. */ 20677298Sobrien#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_" 207130561Sobrien#define ANONYMOUS_NAMESPACE_PREFIX_LEN \ 208130561Sobrien (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1) 20977298Sobrien 210130561Sobrien/* Information we keep for the standard substitutions. */ 21189857Sobrien 212130561Sobrienstruct d_standard_sub_info 213130561Sobrien{ 214130561Sobrien /* The code for this substitution. */ 215130561Sobrien char code; 216130561Sobrien /* The simple string it expands to. */ 217130561Sobrien const char *simple_expansion; 218130561Sobrien /* The length of the simple expansion. */ 219130561Sobrien int simple_len; 220130561Sobrien /* The results of a full, verbose, expansion. This is used when 221130561Sobrien qualifying a constructor/destructor, or when in verbose mode. */ 222130561Sobrien const char *full_expansion; 223130561Sobrien /* The length of the full expansion. */ 224130561Sobrien int full_len; 225130561Sobrien /* What to set the last_name field of d_info to; NULL if we should 226130561Sobrien not set it. This is only relevant when qualifying a 227130561Sobrien constructor/destructor. */ 228130561Sobrien const char *set_last_name; 229130561Sobrien /* The length of set_last_name. */ 230130561Sobrien int set_last_name_len; 231130561Sobrien}; 23268765Sobrien 233130561Sobrien/* Accessors for subtrees of struct demangle_component. */ 23468765Sobrien 235130561Sobrien#define d_left(dc) ((dc)->u.s_binary.left) 236130561Sobrien#define d_right(dc) ((dc)->u.s_binary.right) 23768765Sobrien 238130561Sobrien/* A list of templates. This is used while printing. */ 239130561Sobrien 240130561Sobrienstruct d_print_template 24168765Sobrien{ 242130561Sobrien /* Next template on the list. */ 243130561Sobrien struct d_print_template *next; 244130561Sobrien /* This template. */ 245218822Sdim const struct demangle_component *template_decl; 246130561Sobrien}; 24777298Sobrien 248130561Sobrien/* A list of type modifiers. This is used while printing. */ 24977298Sobrien 250130561Sobrienstruct d_print_mod 251130561Sobrien{ 252130561Sobrien /* Next modifier on the list. These are in the reverse of the order 253130561Sobrien in which they appeared in the mangled string. */ 254130561Sobrien struct d_print_mod *next; 255130561Sobrien /* The modifier. */ 256130561Sobrien const struct demangle_component *mod; 257130561Sobrien /* Whether this modifier was printed. */ 258130561Sobrien int printed; 259130561Sobrien /* The list of templates which applies to this modifier. */ 260130561Sobrien struct d_print_template *templates; 26168765Sobrien}; 26268765Sobrien 263218822Sdim/* We use these structures to hold information during printing. */ 26468765Sobrien 265218822Sdimstruct d_growable_string 26668765Sobrien{ 267130561Sobrien /* Buffer holding the result. */ 268130561Sobrien char *buf; 269130561Sobrien /* Current length of data in buffer. */ 270130561Sobrien size_t len; 271130561Sobrien /* Allocated size of buffer. */ 272130561Sobrien size_t alc; 273218822Sdim /* Set to 1 if we had a memory allocation failure. */ 274218822Sdim int allocation_failure; 275218822Sdim}; 276218822Sdim 277218822Sdimenum { D_PRINT_BUFFER_LENGTH = 256 }; 278218822Sdimstruct d_print_info 279218822Sdim{ 280218822Sdim /* The options passed to the demangler. */ 281218822Sdim int options; 282218822Sdim /* Fixed-length allocated buffer for demangled data, flushed to the 283218822Sdim callback with a NUL termination once full. */ 284218822Sdim char buf[D_PRINT_BUFFER_LENGTH]; 285218822Sdim /* Current length of data in buffer. */ 286218822Sdim size_t len; 287218822Sdim /* The last character printed, saved individually so that it survives 288218822Sdim any buffer flush. */ 289218822Sdim char last_char; 290218822Sdim /* Callback function to handle demangled buffer flush. */ 291218822Sdim demangle_callbackref callback; 292218822Sdim /* Opaque callback argument. */ 293218822Sdim void *opaque; 294130561Sobrien /* The current list of templates, if any. */ 295130561Sobrien struct d_print_template *templates; 296130561Sobrien /* The current list of modifiers (e.g., pointer, reference, etc.), 297130561Sobrien if any. */ 298130561Sobrien struct d_print_mod *modifiers; 299218822Sdim /* Set to 1 if we saw a demangling error. */ 300218822Sdim int demangle_failure; 30168765Sobrien}; 30268765Sobrien 303130561Sobrien#ifdef CP_DEMANGLE_DEBUG 304218822Sdimstatic void d_dump (struct demangle_component *, int); 305130561Sobrien#endif 30668765Sobrien 307130561Sobrienstatic struct demangle_component * 308218822Sdimd_make_empty (struct d_info *); 30968765Sobrien 310130561Sobrienstatic struct demangle_component * 311218822Sdimd_make_comp (struct d_info *, enum demangle_component_type, 312218822Sdim struct demangle_component *, 313218822Sdim struct demangle_component *); 31468765Sobrien 315130561Sobrienstatic struct demangle_component * 316218822Sdimd_make_name (struct d_info *, const char *, int); 31768765Sobrien 318130561Sobrienstatic struct demangle_component * 319218822Sdimd_make_builtin_type (struct d_info *, 320218822Sdim const struct demangle_builtin_type_info *); 32168765Sobrien 322130561Sobrienstatic struct demangle_component * 323218822Sdimd_make_operator (struct d_info *, 324218822Sdim const struct demangle_operator_info *); 32568765Sobrien 326130561Sobrienstatic struct demangle_component * 327218822Sdimd_make_extended_operator (struct d_info *, int, 328218822Sdim struct demangle_component *); 32968765Sobrien 330130561Sobrienstatic struct demangle_component * 331218822Sdimd_make_ctor (struct d_info *, enum gnu_v3_ctor_kinds, 332218822Sdim struct demangle_component *); 33368765Sobrien 334130561Sobrienstatic struct demangle_component * 335218822Sdimd_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds, 336218822Sdim struct demangle_component *); 33768765Sobrien 338130561Sobrienstatic struct demangle_component * 339218822Sdimd_make_template_param (struct d_info *, long); 34068765Sobrien 341130561Sobrienstatic struct demangle_component * 342218822Sdimd_make_sub (struct d_info *, const char *, int); 34368765Sobrien 344130561Sobrienstatic int 345218822Sdimhas_return_type (struct demangle_component *); 34689857Sobrien 347130561Sobrienstatic int 348218822Sdimis_ctor_dtor_or_conversion (struct demangle_component *); 34989857Sobrien 350218822Sdimstatic struct demangle_component *d_encoding (struct d_info *, int); 35189857Sobrien 352218822Sdimstatic struct demangle_component *d_name (struct d_info *); 35368765Sobrien 354218822Sdimstatic struct demangle_component *d_nested_name (struct d_info *); 35568765Sobrien 356218822Sdimstatic struct demangle_component *d_prefix (struct d_info *); 35768765Sobrien 358218822Sdimstatic struct demangle_component *d_unqualified_name (struct d_info *); 35968765Sobrien 360218822Sdimstatic struct demangle_component *d_source_name (struct d_info *); 36168765Sobrien 362218822Sdimstatic long d_number (struct d_info *); 36368765Sobrien 364218822Sdimstatic struct demangle_component *d_identifier (struct d_info *, int); 36568765Sobrien 366218822Sdimstatic struct demangle_component *d_operator_name (struct d_info *); 36768765Sobrien 368218822Sdimstatic struct demangle_component *d_special_name (struct d_info *); 36968765Sobrien 370218822Sdimstatic int d_call_offset (struct d_info *, int); 37168765Sobrien 372218822Sdimstatic struct demangle_component *d_ctor_dtor_name (struct d_info *); 37368765Sobrien 374130561Sobrienstatic struct demangle_component ** 375218822Sdimd_cv_qualifiers (struct d_info *, struct demangle_component **, int); 37668765Sobrien 377130561Sobrienstatic struct demangle_component * 378218822Sdimd_function_type (struct d_info *); 37968765Sobrien 380130561Sobrienstatic struct demangle_component * 381218822Sdimd_bare_function_type (struct d_info *, int); 38268765Sobrien 383130561Sobrienstatic struct demangle_component * 384218822Sdimd_class_enum_type (struct d_info *); 38568765Sobrien 386218822Sdimstatic struct demangle_component *d_array_type (struct d_info *); 38768765Sobrien 388130561Sobrienstatic struct demangle_component * 389218822Sdimd_pointer_to_member_type (struct d_info *); 39068765Sobrien 391130561Sobrienstatic struct demangle_component * 392218822Sdimd_template_param (struct d_info *); 39377298Sobrien 394218822Sdimstatic struct demangle_component *d_template_args (struct d_info *); 39568765Sobrien 396130561Sobrienstatic struct demangle_component * 397218822Sdimd_template_arg (struct d_info *); 39868765Sobrien 399218822Sdimstatic struct demangle_component *d_expression (struct d_info *); 40068765Sobrien 401218822Sdimstatic struct demangle_component *d_expr_primary (struct d_info *); 40277298Sobrien 403218822Sdimstatic struct demangle_component *d_local_name (struct d_info *); 40477298Sobrien 405218822Sdimstatic int d_discriminator (struct d_info *); 40677298Sobrien 407130561Sobrienstatic int 408218822Sdimd_add_substitution (struct d_info *, struct demangle_component *); 40968765Sobrien 410218822Sdimstatic struct demangle_component *d_substitution (struct d_info *, int); 41168765Sobrien 412218822Sdimstatic void d_growable_string_init (struct d_growable_string *, size_t); 41368765Sobrien 414218822Sdimstatic inline void 415218822Sdimd_growable_string_resize (struct d_growable_string *, size_t); 41668765Sobrien 417218822Sdimstatic inline void 418218822Sdimd_growable_string_append_buffer (struct d_growable_string *, 419218822Sdim const char *, size_t); 420130561Sobrienstatic void 421218822Sdimd_growable_string_callback_adapter (const char *, size_t, void *); 42268765Sobrien 423130561Sobrienstatic void 424218822Sdimd_print_init (struct d_print_info *, int, demangle_callbackref, void *); 42568765Sobrien 426218822Sdimstatic inline void d_print_error (struct d_print_info *); 427218822Sdim 428218822Sdimstatic inline int d_print_saw_error (struct d_print_info *); 429218822Sdim 430218822Sdimstatic inline void d_print_flush (struct d_print_info *); 431218822Sdim 432218822Sdimstatic inline void d_append_char (struct d_print_info *, char); 433218822Sdim 434218822Sdimstatic inline void d_append_buffer (struct d_print_info *, 435218822Sdim const char *, size_t); 436218822Sdim 437218822Sdimstatic inline void d_append_string (struct d_print_info *, const char *); 438218822Sdim 439218822Sdimstatic inline char d_last_char (struct d_print_info *); 440218822Sdim 441130561Sobrienstatic void 442218822Sdimd_print_comp (struct d_print_info *, const struct demangle_component *); 44368765Sobrien 444130561Sobrienstatic void 445218822Sdimd_print_java_identifier (struct d_print_info *, const char *, int); 44668765Sobrien 447130561Sobrienstatic void 448218822Sdimd_print_mod_list (struct d_print_info *, struct d_print_mod *, int); 44968765Sobrien 450130561Sobrienstatic void 451218822Sdimd_print_mod (struct d_print_info *, const struct demangle_component *); 45268765Sobrien 453130561Sobrienstatic void 454218822Sdimd_print_function_type (struct d_print_info *, 455218822Sdim const struct demangle_component *, 456218822Sdim struct d_print_mod *); 45768765Sobrien 458130561Sobrienstatic void 459218822Sdimd_print_array_type (struct d_print_info *, 460218822Sdim const struct demangle_component *, 461218822Sdim struct d_print_mod *); 46268765Sobrien 463130561Sobrienstatic void 464218822Sdimd_print_expr_op (struct d_print_info *, const struct demangle_component *); 46568765Sobrien 46668765Sobrienstatic void 467218822Sdimd_print_cast (struct d_print_info *, const struct demangle_component *); 46868765Sobrien 469218822Sdimstatic int d_demangle_callback (const char *, int, 470218822Sdim demangle_callbackref, void *); 471218822Sdimstatic char *d_demangle (const char *, int, size_t *); 47268765Sobrien 473130561Sobrien#ifdef CP_DEMANGLE_DEBUG 474130561Sobrien 475130561Sobrienstatic void 476218822Sdimd_dump (struct demangle_component *dc, int indent) 47768765Sobrien{ 478130561Sobrien int i; 47968765Sobrien 480130561Sobrien if (dc == NULL) 481218822Sdim { 482218822Sdim if (indent == 0) 483218822Sdim printf ("failed demangling\n"); 484218822Sdim return; 485218822Sdim } 48668765Sobrien 487130561Sobrien for (i = 0; i < indent; ++i) 488130561Sobrien putchar (' '); 48968765Sobrien 490130561Sobrien switch (dc->type) 491130561Sobrien { 492130561Sobrien case DEMANGLE_COMPONENT_NAME: 493130561Sobrien printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s); 494130561Sobrien return; 495130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE_PARAM: 496130561Sobrien printf ("template parameter %ld\n", dc->u.s_number.number); 497130561Sobrien return; 498130561Sobrien case DEMANGLE_COMPONENT_CTOR: 499130561Sobrien printf ("constructor %d\n", (int) dc->u.s_ctor.kind); 500130561Sobrien d_dump (dc->u.s_ctor.name, indent + 2); 501130561Sobrien return; 502130561Sobrien case DEMANGLE_COMPONENT_DTOR: 503130561Sobrien printf ("destructor %d\n", (int) dc->u.s_dtor.kind); 504130561Sobrien d_dump (dc->u.s_dtor.name, indent + 2); 505130561Sobrien return; 506130561Sobrien case DEMANGLE_COMPONENT_SUB_STD: 507130561Sobrien printf ("standard substitution %s\n", dc->u.s_string.string); 508130561Sobrien return; 509130561Sobrien case DEMANGLE_COMPONENT_BUILTIN_TYPE: 510130561Sobrien printf ("builtin type %s\n", dc->u.s_builtin.type->name); 511130561Sobrien return; 512130561Sobrien case DEMANGLE_COMPONENT_OPERATOR: 513130561Sobrien printf ("operator %s\n", dc->u.s_operator.op->name); 514130561Sobrien return; 515130561Sobrien case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: 516130561Sobrien printf ("extended operator with %d args\n", 517130561Sobrien dc->u.s_extended_operator.args); 518130561Sobrien d_dump (dc->u.s_extended_operator.name, indent + 2); 519130561Sobrien return; 52068765Sobrien 521130561Sobrien case DEMANGLE_COMPONENT_QUAL_NAME: 522130561Sobrien printf ("qualified name\n"); 523130561Sobrien break; 524130561Sobrien case DEMANGLE_COMPONENT_LOCAL_NAME: 525130561Sobrien printf ("local name\n"); 526130561Sobrien break; 527130561Sobrien case DEMANGLE_COMPONENT_TYPED_NAME: 528130561Sobrien printf ("typed name\n"); 529130561Sobrien break; 530130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE: 531130561Sobrien printf ("template\n"); 532130561Sobrien break; 533130561Sobrien case DEMANGLE_COMPONENT_VTABLE: 534130561Sobrien printf ("vtable\n"); 535130561Sobrien break; 536130561Sobrien case DEMANGLE_COMPONENT_VTT: 537130561Sobrien printf ("VTT\n"); 538130561Sobrien break; 539130561Sobrien case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: 540130561Sobrien printf ("construction vtable\n"); 541130561Sobrien break; 542130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO: 543130561Sobrien printf ("typeinfo\n"); 544130561Sobrien break; 545130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_NAME: 546130561Sobrien printf ("typeinfo name\n"); 547130561Sobrien break; 548130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_FN: 549130561Sobrien printf ("typeinfo function\n"); 550130561Sobrien break; 551130561Sobrien case DEMANGLE_COMPONENT_THUNK: 552130561Sobrien printf ("thunk\n"); 553130561Sobrien break; 554130561Sobrien case DEMANGLE_COMPONENT_VIRTUAL_THUNK: 555130561Sobrien printf ("virtual thunk\n"); 556130561Sobrien break; 557130561Sobrien case DEMANGLE_COMPONENT_COVARIANT_THUNK: 558130561Sobrien printf ("covariant thunk\n"); 559130561Sobrien break; 560130561Sobrien case DEMANGLE_COMPONENT_JAVA_CLASS: 561130561Sobrien printf ("java class\n"); 562130561Sobrien break; 563130561Sobrien case DEMANGLE_COMPONENT_GUARD: 564130561Sobrien printf ("guard\n"); 565130561Sobrien break; 566130561Sobrien case DEMANGLE_COMPONENT_REFTEMP: 567130561Sobrien printf ("reference temporary\n"); 568130561Sobrien break; 569218822Sdim case DEMANGLE_COMPONENT_HIDDEN_ALIAS: 570218822Sdim printf ("hidden alias\n"); 571218822Sdim break; 572130561Sobrien case DEMANGLE_COMPONENT_RESTRICT: 573130561Sobrien printf ("restrict\n"); 574130561Sobrien break; 575130561Sobrien case DEMANGLE_COMPONENT_VOLATILE: 576130561Sobrien printf ("volatile\n"); 577130561Sobrien break; 578130561Sobrien case DEMANGLE_COMPONENT_CONST: 579130561Sobrien printf ("const\n"); 580130561Sobrien break; 581130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 582130561Sobrien printf ("restrict this\n"); 583130561Sobrien break; 584130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 585130561Sobrien printf ("volatile this\n"); 586130561Sobrien break; 587130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 588130561Sobrien printf ("const this\n"); 589130561Sobrien break; 590130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 591130561Sobrien printf ("vendor type qualifier\n"); 592130561Sobrien break; 593130561Sobrien case DEMANGLE_COMPONENT_POINTER: 594130561Sobrien printf ("pointer\n"); 595130561Sobrien break; 596130561Sobrien case DEMANGLE_COMPONENT_REFERENCE: 597130561Sobrien printf ("reference\n"); 598130561Sobrien break; 599130561Sobrien case DEMANGLE_COMPONENT_COMPLEX: 600130561Sobrien printf ("complex\n"); 601130561Sobrien break; 602130561Sobrien case DEMANGLE_COMPONENT_IMAGINARY: 603130561Sobrien printf ("imaginary\n"); 604130561Sobrien break; 605130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE: 606130561Sobrien printf ("vendor type\n"); 607130561Sobrien break; 608130561Sobrien case DEMANGLE_COMPONENT_FUNCTION_TYPE: 609130561Sobrien printf ("function type\n"); 610130561Sobrien break; 611130561Sobrien case DEMANGLE_COMPONENT_ARRAY_TYPE: 612130561Sobrien printf ("array type\n"); 613130561Sobrien break; 614130561Sobrien case DEMANGLE_COMPONENT_PTRMEM_TYPE: 615130561Sobrien printf ("pointer to member type\n"); 616130561Sobrien break; 617130561Sobrien case DEMANGLE_COMPONENT_ARGLIST: 618130561Sobrien printf ("argument list\n"); 619130561Sobrien break; 620130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: 621130561Sobrien printf ("template argument list\n"); 622130561Sobrien break; 623130561Sobrien case DEMANGLE_COMPONENT_CAST: 624130561Sobrien printf ("cast\n"); 625130561Sobrien break; 626130561Sobrien case DEMANGLE_COMPONENT_UNARY: 627130561Sobrien printf ("unary operator\n"); 628130561Sobrien break; 629130561Sobrien case DEMANGLE_COMPONENT_BINARY: 630130561Sobrien printf ("binary operator\n"); 631130561Sobrien break; 632130561Sobrien case DEMANGLE_COMPONENT_BINARY_ARGS: 633130561Sobrien printf ("binary operator arguments\n"); 634130561Sobrien break; 635130561Sobrien case DEMANGLE_COMPONENT_TRINARY: 636130561Sobrien printf ("trinary operator\n"); 637130561Sobrien break; 638130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG1: 639130561Sobrien printf ("trinary operator arguments 1\n"); 640130561Sobrien break; 641130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG2: 642130561Sobrien printf ("trinary operator arguments 1\n"); 643130561Sobrien break; 644130561Sobrien case DEMANGLE_COMPONENT_LITERAL: 645130561Sobrien printf ("literal\n"); 646130561Sobrien break; 647130561Sobrien case DEMANGLE_COMPONENT_LITERAL_NEG: 648130561Sobrien printf ("negative literal\n"); 649130561Sobrien break; 650130561Sobrien } 65168765Sobrien 652130561Sobrien d_dump (d_left (dc), indent + 2); 653130561Sobrien d_dump (d_right (dc), indent + 2); 65468765Sobrien} 65568765Sobrien 656130561Sobrien#endif /* CP_DEMANGLE_DEBUG */ 65768765Sobrien 658130561Sobrien/* Fill in a DEMANGLE_COMPONENT_NAME. */ 659130561Sobrien 660130561SobrienCP_STATIC_IF_GLIBCPP_V3 661130561Sobrienint 662218822Sdimcplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) 66368765Sobrien{ 664130561Sobrien if (p == NULL || s == NULL || len == 0) 665130561Sobrien return 0; 666130561Sobrien p->type = DEMANGLE_COMPONENT_NAME; 667130561Sobrien p->u.s_name.s = s; 668130561Sobrien p->u.s_name.len = len; 669130561Sobrien return 1; 67068765Sobrien} 67168765Sobrien 672130561Sobrien/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ 67377298Sobrien 674130561SobrienCP_STATIC_IF_GLIBCPP_V3 675130561Sobrienint 676218822Sdimcplus_demangle_fill_extended_operator (struct demangle_component *p, int args, 677218822Sdim struct demangle_component *name) 67877298Sobrien{ 679130561Sobrien if (p == NULL || args < 0 || name == NULL) 680130561Sobrien return 0; 681130561Sobrien p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; 682130561Sobrien p->u.s_extended_operator.args = args; 683130561Sobrien p->u.s_extended_operator.name = name; 684130561Sobrien return 1; 68577298Sobrien} 68677298Sobrien 687130561Sobrien/* Fill in a DEMANGLE_COMPONENT_CTOR. */ 68877298Sobrien 689130561SobrienCP_STATIC_IF_GLIBCPP_V3 690130561Sobrienint 691218822Sdimcplus_demangle_fill_ctor (struct demangle_component *p, 692218822Sdim enum gnu_v3_ctor_kinds kind, 693218822Sdim struct demangle_component *name) 69477298Sobrien{ 695130561Sobrien if (p == NULL 696130561Sobrien || name == NULL 697130561Sobrien || (kind < gnu_v3_complete_object_ctor 698130561Sobrien && kind > gnu_v3_complete_object_allocating_ctor)) 699130561Sobrien return 0; 700130561Sobrien p->type = DEMANGLE_COMPONENT_CTOR; 701130561Sobrien p->u.s_ctor.kind = kind; 702130561Sobrien p->u.s_ctor.name = name; 703130561Sobrien return 1; 70477298Sobrien} 70577298Sobrien 706130561Sobrien/* Fill in a DEMANGLE_COMPONENT_DTOR. */ 70777298Sobrien 708130561SobrienCP_STATIC_IF_GLIBCPP_V3 709130561Sobrienint 710218822Sdimcplus_demangle_fill_dtor (struct demangle_component *p, 711218822Sdim enum gnu_v3_dtor_kinds kind, 712218822Sdim struct demangle_component *name) 71377298Sobrien{ 714130561Sobrien if (p == NULL 715130561Sobrien || name == NULL 716130561Sobrien || (kind < gnu_v3_deleting_dtor 717130561Sobrien && kind > gnu_v3_base_object_dtor)) 718130561Sobrien return 0; 719130561Sobrien p->type = DEMANGLE_COMPONENT_DTOR; 720130561Sobrien p->u.s_dtor.kind = kind; 721130561Sobrien p->u.s_dtor.name = name; 722130561Sobrien return 1; 72377298Sobrien} 72477298Sobrien 725130561Sobrien/* Add a new component. */ 72677298Sobrien 727130561Sobrienstatic struct demangle_component * 728218822Sdimd_make_empty (struct d_info *di) 72977298Sobrien{ 730130561Sobrien struct demangle_component *p; 731130561Sobrien 732130561Sobrien if (di->next_comp >= di->num_comps) 733130561Sobrien return NULL; 734130561Sobrien p = &di->comps[di->next_comp]; 735130561Sobrien ++di->next_comp; 736130561Sobrien return p; 73777298Sobrien} 73877298Sobrien 739130561Sobrien/* Add a new generic component. */ 74068765Sobrien 741130561Sobrienstatic struct demangle_component * 742218822Sdimd_make_comp (struct d_info *di, enum demangle_component_type type, 743218822Sdim struct demangle_component *left, 744218822Sdim struct demangle_component *right) 74568765Sobrien{ 746130561Sobrien struct demangle_component *p; 74768765Sobrien 748130561Sobrien /* We check for errors here. A typical error would be a NULL return 749130561Sobrien from a subroutine. We catch those here, and return NULL 750130561Sobrien upward. */ 751130561Sobrien switch (type) 752130561Sobrien { 753130561Sobrien /* These types require two parameters. */ 754130561Sobrien case DEMANGLE_COMPONENT_QUAL_NAME: 755130561Sobrien case DEMANGLE_COMPONENT_LOCAL_NAME: 756130561Sobrien case DEMANGLE_COMPONENT_TYPED_NAME: 757130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE: 758130561Sobrien case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: 759130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 760130561Sobrien case DEMANGLE_COMPONENT_PTRMEM_TYPE: 761130561Sobrien case DEMANGLE_COMPONENT_UNARY: 762130561Sobrien case DEMANGLE_COMPONENT_BINARY: 763130561Sobrien case DEMANGLE_COMPONENT_BINARY_ARGS: 764130561Sobrien case DEMANGLE_COMPONENT_TRINARY: 765130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG1: 766130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG2: 767130561Sobrien case DEMANGLE_COMPONENT_LITERAL: 768130561Sobrien case DEMANGLE_COMPONENT_LITERAL_NEG: 769130561Sobrien if (left == NULL || right == NULL) 770130561Sobrien return NULL; 771130561Sobrien break; 77268765Sobrien 773130561Sobrien /* These types only require one parameter. */ 774130561Sobrien case DEMANGLE_COMPONENT_VTABLE: 775130561Sobrien case DEMANGLE_COMPONENT_VTT: 776130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO: 777130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_NAME: 778130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_FN: 779130561Sobrien case DEMANGLE_COMPONENT_THUNK: 780130561Sobrien case DEMANGLE_COMPONENT_VIRTUAL_THUNK: 781130561Sobrien case DEMANGLE_COMPONENT_COVARIANT_THUNK: 782130561Sobrien case DEMANGLE_COMPONENT_JAVA_CLASS: 783130561Sobrien case DEMANGLE_COMPONENT_GUARD: 784130561Sobrien case DEMANGLE_COMPONENT_REFTEMP: 785218822Sdim case DEMANGLE_COMPONENT_HIDDEN_ALIAS: 786130561Sobrien case DEMANGLE_COMPONENT_POINTER: 787130561Sobrien case DEMANGLE_COMPONENT_REFERENCE: 788130561Sobrien case DEMANGLE_COMPONENT_COMPLEX: 789130561Sobrien case DEMANGLE_COMPONENT_IMAGINARY: 790130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE: 791130561Sobrien case DEMANGLE_COMPONENT_ARGLIST: 792130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: 793130561Sobrien case DEMANGLE_COMPONENT_CAST: 794130561Sobrien if (left == NULL) 795130561Sobrien return NULL; 796130561Sobrien break; 79768765Sobrien 798130561Sobrien /* This needs a right parameter, but the left parameter can be 799130561Sobrien empty. */ 800130561Sobrien case DEMANGLE_COMPONENT_ARRAY_TYPE: 801130561Sobrien if (right == NULL) 802130561Sobrien return NULL; 803130561Sobrien break; 80468765Sobrien 805130561Sobrien /* These are allowed to have no parameters--in some cases they 806130561Sobrien will be filled in later. */ 807130561Sobrien case DEMANGLE_COMPONENT_FUNCTION_TYPE: 808130561Sobrien case DEMANGLE_COMPONENT_RESTRICT: 809130561Sobrien case DEMANGLE_COMPONENT_VOLATILE: 810130561Sobrien case DEMANGLE_COMPONENT_CONST: 811130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 812130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 813130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 814130561Sobrien break; 815130561Sobrien 816130561Sobrien /* Other types should not be seen here. */ 817130561Sobrien default: 818130561Sobrien return NULL; 81968765Sobrien } 82068765Sobrien 821130561Sobrien p = d_make_empty (di); 822130561Sobrien if (p != NULL) 82368765Sobrien { 824130561Sobrien p->type = type; 825130561Sobrien p->u.s_binary.left = left; 826130561Sobrien p->u.s_binary.right = right; 82768765Sobrien } 828130561Sobrien return p; 829130561Sobrien} 83068765Sobrien 831130561Sobrien/* Add a new name component. */ 83268765Sobrien 833130561Sobrienstatic struct demangle_component * 834218822Sdimd_make_name (struct d_info *di, const char *s, int len) 835130561Sobrien{ 836130561Sobrien struct demangle_component *p; 83768765Sobrien 838130561Sobrien p = d_make_empty (di); 839130561Sobrien if (! cplus_demangle_fill_name (p, s, len)) 840130561Sobrien return NULL; 841130561Sobrien return p; 84268765Sobrien} 84368765Sobrien 844130561Sobrien/* Add a new builtin type component. */ 84568765Sobrien 846130561Sobrienstatic struct demangle_component * 847218822Sdimd_make_builtin_type (struct d_info *di, 848218822Sdim const struct demangle_builtin_type_info *type) 84968765Sobrien{ 850130561Sobrien struct demangle_component *p; 85168765Sobrien 852130561Sobrien if (type == NULL) 85368765Sobrien return NULL; 854130561Sobrien p = d_make_empty (di); 855130561Sobrien if (p != NULL) 856130561Sobrien { 857130561Sobrien p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE; 858130561Sobrien p->u.s_builtin.type = type; 859130561Sobrien } 860130561Sobrien return p; 86168765Sobrien} 86268765Sobrien 863130561Sobrien/* Add a new operator component. */ 86468765Sobrien 865130561Sobrienstatic struct demangle_component * 866218822Sdimd_make_operator (struct d_info *di, const struct demangle_operator_info *op) 86768765Sobrien{ 868130561Sobrien struct demangle_component *p; 86968765Sobrien 870130561Sobrien p = d_make_empty (di); 871130561Sobrien if (p != NULL) 87268765Sobrien { 873130561Sobrien p->type = DEMANGLE_COMPONENT_OPERATOR; 874130561Sobrien p->u.s_operator.op = op; 87568765Sobrien } 876130561Sobrien return p; 87768765Sobrien} 87868765Sobrien 879130561Sobrien/* Add a new extended operator component. */ 88068765Sobrien 881130561Sobrienstatic struct demangle_component * 882218822Sdimd_make_extended_operator (struct d_info *di, int args, 883218822Sdim struct demangle_component *name) 884130561Sobrien{ 885130561Sobrien struct demangle_component *p; 88668765Sobrien 887130561Sobrien p = d_make_empty (di); 888130561Sobrien if (! cplus_demangle_fill_extended_operator (p, args, name)) 88968765Sobrien return NULL; 890130561Sobrien return p; 89168765Sobrien} 89268765Sobrien 893130561Sobrien/* Add a new constructor component. */ 89468765Sobrien 895130561Sobrienstatic struct demangle_component * 896218822Sdimd_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind, 897218822Sdim struct demangle_component *name) 89868765Sobrien{ 899130561Sobrien struct demangle_component *p; 900130561Sobrien 901130561Sobrien p = d_make_empty (di); 902130561Sobrien if (! cplus_demangle_fill_ctor (p, kind, name)) 903130561Sobrien return NULL; 904130561Sobrien return p; 90568765Sobrien} 90668765Sobrien 907130561Sobrien/* Add a new destructor component. */ 90868765Sobrien 909130561Sobrienstatic struct demangle_component * 910218822Sdimd_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, 911218822Sdim struct demangle_component *name) 91268765Sobrien{ 913130561Sobrien struct demangle_component *p; 91468765Sobrien 915130561Sobrien p = d_make_empty (di); 916130561Sobrien if (! cplus_demangle_fill_dtor (p, kind, name)) 917130561Sobrien return NULL; 918130561Sobrien return p; 91968765Sobrien} 92068765Sobrien 921130561Sobrien/* Add a new template parameter. */ 92268765Sobrien 923130561Sobrienstatic struct demangle_component * 924218822Sdimd_make_template_param (struct d_info *di, long i) 92568765Sobrien{ 926130561Sobrien struct demangle_component *p; 92768765Sobrien 928130561Sobrien p = d_make_empty (di); 929130561Sobrien if (p != NULL) 93068765Sobrien { 931130561Sobrien p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM; 932130561Sobrien p->u.s_number.number = i; 93368765Sobrien } 934130561Sobrien return p; 93568765Sobrien} 93668765Sobrien 937130561Sobrien/* Add a new standard substitution component. */ 93868765Sobrien 939130561Sobrienstatic struct demangle_component * 940218822Sdimd_make_sub (struct d_info *di, const char *name, int len) 94168765Sobrien{ 942130561Sobrien struct demangle_component *p; 94368765Sobrien 944130561Sobrien p = d_make_empty (di); 945130561Sobrien if (p != NULL) 94668765Sobrien { 947130561Sobrien p->type = DEMANGLE_COMPONENT_SUB_STD; 948130561Sobrien p->u.s_string.string = name; 949130561Sobrien p->u.s_string.len = len; 95068765Sobrien } 951130561Sobrien return p; 95268765Sobrien} 95368765Sobrien 954130561Sobrien/* <mangled-name> ::= _Z <encoding> 95568765Sobrien 956130561Sobrien TOP_LEVEL is non-zero when called at the top level. */ 95768765Sobrien 958130561SobrienCP_STATIC_IF_GLIBCPP_V3 959130561Sobrienstruct demangle_component * 960218822Sdimcplus_demangle_mangled_name (struct d_info *di, int top_level) 96168765Sobrien{ 962218822Sdim if (! d_check_char (di, '_')) 963130561Sobrien return NULL; 964218822Sdim if (! d_check_char (di, 'Z')) 965130561Sobrien return NULL; 966130561Sobrien return d_encoding (di, top_level); 96768765Sobrien} 96868765Sobrien 969130561Sobrien/* Return whether a function should have a return type. The argument 970130561Sobrien is the function name, which may be qualified in various ways. The 971130561Sobrien rules are that template functions have return types with some 972130561Sobrien exceptions, function types which are not part of a function name 973130561Sobrien mangling have return types with some exceptions, and non-template 974130561Sobrien function names do not have return types. The exceptions are that 975130561Sobrien constructors, destructors, and conversion operators do not have 976130561Sobrien return types. */ 97768765Sobrien 978130561Sobrienstatic int 979218822Sdimhas_return_type (struct demangle_component *dc) 98068765Sobrien{ 981130561Sobrien if (dc == NULL) 982130561Sobrien return 0; 983130561Sobrien switch (dc->type) 98468765Sobrien { 985130561Sobrien default: 986130561Sobrien return 0; 987130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE: 988130561Sobrien return ! is_ctor_dtor_or_conversion (d_left (dc)); 989130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 990130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 991130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 992130561Sobrien return has_return_type (d_left (dc)); 99368765Sobrien } 99468765Sobrien} 99568765Sobrien 996130561Sobrien/* Return whether a name is a constructor, a destructor, or a 997130561Sobrien conversion operator. */ 99868765Sobrien 999130561Sobrienstatic int 1000218822Sdimis_ctor_dtor_or_conversion (struct demangle_component *dc) 100168765Sobrien{ 1002130561Sobrien if (dc == NULL) 1003130561Sobrien return 0; 1004130561Sobrien switch (dc->type) 100568765Sobrien { 1006130561Sobrien default: 1007130561Sobrien return 0; 1008130561Sobrien case DEMANGLE_COMPONENT_QUAL_NAME: 1009130561Sobrien case DEMANGLE_COMPONENT_LOCAL_NAME: 1010130561Sobrien return is_ctor_dtor_or_conversion (d_right (dc)); 1011130561Sobrien case DEMANGLE_COMPONENT_CTOR: 1012130561Sobrien case DEMANGLE_COMPONENT_DTOR: 1013130561Sobrien case DEMANGLE_COMPONENT_CAST: 1014130561Sobrien return 1; 101568765Sobrien } 101668765Sobrien} 101768765Sobrien 1018130561Sobrien/* <encoding> ::= <(function) name> <bare-function-type> 1019130561Sobrien ::= <(data) name> 1020130561Sobrien ::= <special-name> 102168765Sobrien 1022130561Sobrien TOP_LEVEL is non-zero when called at the top level, in which case 1023130561Sobrien if DMGL_PARAMS is not set we do not demangle the function 1024130561Sobrien parameters. We only set this at the top level, because otherwise 1025130561Sobrien we would not correctly demangle names in local scopes. */ 102668765Sobrien 1027130561Sobrienstatic struct demangle_component * 1028218822Sdimd_encoding (struct d_info *di, int top_level) 102968765Sobrien{ 1030130561Sobrien char peek = d_peek_char (di); 103168765Sobrien 1032130561Sobrien if (peek == 'G' || peek == 'T') 1033130561Sobrien return d_special_name (di); 103468765Sobrien else 103568765Sobrien { 1036130561Sobrien struct demangle_component *dc; 103768765Sobrien 1038130561Sobrien dc = d_name (di); 103968765Sobrien 1040130561Sobrien if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) 1041130561Sobrien { 1042130561Sobrien /* Strip off any initial CV-qualifiers, as they really apply 1043130561Sobrien to the `this' parameter, and they were not output by the 1044130561Sobrien v2 demangler without DMGL_PARAMS. */ 1045130561Sobrien while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS 1046130561Sobrien || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS 1047130561Sobrien || dc->type == DEMANGLE_COMPONENT_CONST_THIS) 1048130561Sobrien dc = d_left (dc); 104968765Sobrien 1050130561Sobrien /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then 1051130561Sobrien there may be CV-qualifiers on its right argument which 1052130561Sobrien really apply here; this happens when parsing a class 1053130561Sobrien which is local to a function. */ 1054130561Sobrien if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) 1055130561Sobrien { 1056130561Sobrien struct demangle_component *dcr; 105768765Sobrien 1058130561Sobrien dcr = d_right (dc); 1059130561Sobrien while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS 1060130561Sobrien || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS 1061130561Sobrien || dcr->type == DEMANGLE_COMPONENT_CONST_THIS) 1062130561Sobrien dcr = d_left (dcr); 1063130561Sobrien dc->u.s_binary.right = dcr; 1064130561Sobrien } 106568765Sobrien 1066130561Sobrien return dc; 1067130561Sobrien } 106868765Sobrien 1069130561Sobrien peek = d_peek_char (di); 1070218822Sdim if (dc == NULL || peek == '\0' || peek == 'E') 1071130561Sobrien return dc; 1072130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc, 1073130561Sobrien d_bare_function_type (di, has_return_type (dc))); 107468765Sobrien } 107568765Sobrien} 107668765Sobrien 1077130561Sobrien/* <name> ::= <nested-name> 1078130561Sobrien ::= <unscoped-name> 1079130561Sobrien ::= <unscoped-template-name> <template-args> 1080130561Sobrien ::= <local-name> 108168765Sobrien 1082130561Sobrien <unscoped-name> ::= <unqualified-name> 1083130561Sobrien ::= St <unqualified-name> 108468765Sobrien 1085130561Sobrien <unscoped-template-name> ::= <unscoped-name> 1086130561Sobrien ::= <substitution> 1087130561Sobrien*/ 108868765Sobrien 1089130561Sobrienstatic struct demangle_component * 1090218822Sdimd_name (struct d_info *di) 109168765Sobrien{ 1092130561Sobrien char peek = d_peek_char (di); 1093130561Sobrien struct demangle_component *dc; 109468765Sobrien 109577298Sobrien switch (peek) 109668765Sobrien { 109768765Sobrien case 'N': 1098130561Sobrien return d_nested_name (di); 109968765Sobrien 110068765Sobrien case 'Z': 1101130561Sobrien return d_local_name (di); 110268765Sobrien 1103218822Sdim case 'L': 1104218822Sdim return d_unqualified_name (di); 1105218822Sdim 110668765Sobrien case 'S': 1107130561Sobrien { 1108130561Sobrien int subst; 110977298Sobrien 1110130561Sobrien if (d_peek_next_char (di) != 't') 1111130561Sobrien { 1112130561Sobrien dc = d_substitution (di, 0); 1113130561Sobrien subst = 1; 1114130561Sobrien } 1115130561Sobrien else 1116130561Sobrien { 1117130561Sobrien d_advance (di, 2); 1118130561Sobrien dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, 1119130561Sobrien d_make_name (di, "std", 3), 1120130561Sobrien d_unqualified_name (di)); 1121130561Sobrien di->expansion += 3; 1122130561Sobrien subst = 0; 1123130561Sobrien } 112468765Sobrien 1125130561Sobrien if (d_peek_char (di) != 'I') 1126130561Sobrien { 1127130561Sobrien /* The grammar does not permit this case to occur if we 1128130561Sobrien called d_substitution() above (i.e., subst == 1). We 1129130561Sobrien don't bother to check. */ 1130130561Sobrien } 1131130561Sobrien else 1132130561Sobrien { 1133130561Sobrien /* This is <template-args>, which means that we just saw 1134130561Sobrien <unscoped-template-name>, which is a substitution 1135130561Sobrien candidate if we didn't just get it from a 1136130561Sobrien substitution. */ 1137130561Sobrien if (! subst) 1138130561Sobrien { 1139130561Sobrien if (! d_add_substitution (di, dc)) 1140130561Sobrien return NULL; 1141130561Sobrien } 1142130561Sobrien dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, 1143130561Sobrien d_template_args (di)); 1144130561Sobrien } 1145130561Sobrien 1146130561Sobrien return dc; 1147130561Sobrien } 1148130561Sobrien 114968765Sobrien default: 1150130561Sobrien dc = d_unqualified_name (di); 1151130561Sobrien if (d_peek_char (di) == 'I') 115268765Sobrien { 1153130561Sobrien /* This is <template-args>, which means that we just saw 1154130561Sobrien <unscoped-template-name>, which is a substitution 1155130561Sobrien candidate. */ 1156130561Sobrien if (! d_add_substitution (di, dc)) 1157130561Sobrien return NULL; 1158130561Sobrien dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, 1159130561Sobrien d_template_args (di)); 116068765Sobrien } 1161130561Sobrien return dc; 116268765Sobrien } 116368765Sobrien} 116468765Sobrien 1165130561Sobrien/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E 1166130561Sobrien ::= N [<CV-qualifiers>] <template-prefix> <template-args> E 1167130561Sobrien*/ 116868765Sobrien 1169130561Sobrienstatic struct demangle_component * 1170218822Sdimd_nested_name (struct d_info *di) 117168765Sobrien{ 1172130561Sobrien struct demangle_component *ret; 1173130561Sobrien struct demangle_component **pret; 117468765Sobrien 1175218822Sdim if (! d_check_char (di, 'N')) 1176130561Sobrien return NULL; 117768765Sobrien 1178130561Sobrien pret = d_cv_qualifiers (di, &ret, 1); 1179130561Sobrien if (pret == NULL) 1180130561Sobrien return NULL; 118168765Sobrien 1182130561Sobrien *pret = d_prefix (di); 1183130561Sobrien if (*pret == NULL) 1184130561Sobrien return NULL; 118568765Sobrien 1186218822Sdim if (! d_check_char (di, 'E')) 1187130561Sobrien return NULL; 118868765Sobrien 1189130561Sobrien return ret; 119068765Sobrien} 119168765Sobrien 1192130561Sobrien/* <prefix> ::= <prefix> <unqualified-name> 1193130561Sobrien ::= <template-prefix> <template-args> 1194130561Sobrien ::= <template-param> 1195130561Sobrien ::= 1196130561Sobrien ::= <substitution> 119768765Sobrien 1198130561Sobrien <template-prefix> ::= <prefix> <(template) unqualified-name> 1199130561Sobrien ::= <template-param> 1200130561Sobrien ::= <substitution> 1201130561Sobrien*/ 120268765Sobrien 1203130561Sobrienstatic struct demangle_component * 1204218822Sdimd_prefix (struct d_info *di) 120568765Sobrien{ 1206130561Sobrien struct demangle_component *ret = NULL; 120768765Sobrien 120868765Sobrien while (1) 120968765Sobrien { 121068765Sobrien char peek; 1211130561Sobrien enum demangle_component_type comb_type; 1212130561Sobrien struct demangle_component *dc; 121368765Sobrien 1214130561Sobrien peek = d_peek_char (di); 1215130561Sobrien if (peek == '\0') 1216130561Sobrien return NULL; 121768765Sobrien 1218130561Sobrien /* The older code accepts a <local-name> here, but I don't see 1219130561Sobrien that in the grammar. The older code does not accept a 1220130561Sobrien <template-param> here. */ 122177298Sobrien 1222130561Sobrien comb_type = DEMANGLE_COMPONENT_QUAL_NAME; 1223130561Sobrien if (IS_DIGIT (peek) 1224130561Sobrien || IS_LOWER (peek) 1225130561Sobrien || peek == 'C' 1226218822Sdim || peek == 'D' 1227218822Sdim || peek == 'L') 1228130561Sobrien dc = d_unqualified_name (di); 1229130561Sobrien else if (peek == 'S') 1230130561Sobrien dc = d_substitution (di, 1); 123168765Sobrien else if (peek == 'I') 123268765Sobrien { 1233130561Sobrien if (ret == NULL) 1234130561Sobrien return NULL; 1235130561Sobrien comb_type = DEMANGLE_COMPONENT_TEMPLATE; 1236130561Sobrien dc = d_template_args (di); 123768765Sobrien } 1238130561Sobrien else if (peek == 'T') 1239130561Sobrien dc = d_template_param (di); 124068765Sobrien else if (peek == 'E') 1241130561Sobrien return ret; 124268765Sobrien else 1243130561Sobrien return NULL; 124468765Sobrien 1245130561Sobrien if (ret == NULL) 1246130561Sobrien ret = dc; 1247130561Sobrien else 1248130561Sobrien ret = d_make_comp (di, comb_type, ret, dc); 1249130561Sobrien 1250130561Sobrien if (peek != 'S' && d_peek_char (di) != 'E') 1251130561Sobrien { 1252130561Sobrien if (! d_add_substitution (di, ret)) 1253130561Sobrien return NULL; 1254130561Sobrien } 125568765Sobrien } 125668765Sobrien} 125768765Sobrien 1258130561Sobrien/* <unqualified-name> ::= <operator-name> 1259130561Sobrien ::= <ctor-dtor-name> 1260130561Sobrien ::= <source-name> 1261218822Sdim ::= <local-source-name> 1262218822Sdim 1263218822Sdim <local-source-name> ::= L <source-name> <discriminator> 1264130561Sobrien*/ 126568765Sobrien 1266130561Sobrienstatic struct demangle_component * 1267218822Sdimd_unqualified_name (struct d_info *di) 126868765Sobrien{ 1269130561Sobrien char peek; 127068765Sobrien 1271130561Sobrien peek = d_peek_char (di); 1272130561Sobrien if (IS_DIGIT (peek)) 1273130561Sobrien return d_source_name (di); 1274130561Sobrien else if (IS_LOWER (peek)) 127568765Sobrien { 1276130561Sobrien struct demangle_component *ret; 127777298Sobrien 1278130561Sobrien ret = d_operator_name (di); 1279130561Sobrien if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) 1280130561Sobrien di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; 1281130561Sobrien return ret; 128268765Sobrien } 128368765Sobrien else if (peek == 'C' || peek == 'D') 1284130561Sobrien return d_ctor_dtor_name (di); 1285218822Sdim else if (peek == 'L') 1286218822Sdim { 1287218822Sdim struct demangle_component * ret; 1288218822Sdim 1289218822Sdim d_advance (di, 1); 1290218822Sdim 1291218822Sdim ret = d_source_name (di); 1292218822Sdim if (ret == NULL) 1293218822Sdim return NULL; 1294218822Sdim if (! d_discriminator (di)) 1295218822Sdim return NULL; 1296218822Sdim return ret; 1297218822Sdim } 129868765Sobrien else 1299130561Sobrien return NULL; 130068765Sobrien} 130168765Sobrien 1302130561Sobrien/* <source-name> ::= <(positive length) number> <identifier> */ 130368765Sobrien 1304130561Sobrienstatic struct demangle_component * 1305218822Sdimd_source_name (struct d_info *di) 130668765Sobrien{ 1307130561Sobrien long len; 1308130561Sobrien struct demangle_component *ret; 130968765Sobrien 1310130561Sobrien len = d_number (di); 1311130561Sobrien if (len <= 0) 1312130561Sobrien return NULL; 1313130561Sobrien ret = d_identifier (di, len); 1314130561Sobrien di->last_name = ret; 1315130561Sobrien return ret; 1316130561Sobrien} 131768765Sobrien 1318130561Sobrien/* number ::= [n] <(non-negative decimal integer)> */ 131968765Sobrien 1320130561Sobrienstatic long 1321218822Sdimd_number (struct d_info *di) 1322130561Sobrien{ 1323130561Sobrien int negative; 1324130561Sobrien char peek; 1325130561Sobrien long ret; 132668765Sobrien 1327130561Sobrien negative = 0; 1328130561Sobrien peek = d_peek_char (di); 1329130561Sobrien if (peek == 'n') 1330130561Sobrien { 1331130561Sobrien negative = 1; 1332130561Sobrien d_advance (di, 1); 1333130561Sobrien peek = d_peek_char (di); 1334130561Sobrien } 133568765Sobrien 1336130561Sobrien ret = 0; 1337130561Sobrien while (1) 1338130561Sobrien { 1339130561Sobrien if (! IS_DIGIT (peek)) 1340130561Sobrien { 1341130561Sobrien if (negative) 1342130561Sobrien ret = - ret; 1343130561Sobrien return ret; 1344130561Sobrien } 1345130561Sobrien ret = ret * 10 + peek - '0'; 1346130561Sobrien d_advance (di, 1); 1347130561Sobrien peek = d_peek_char (di); 1348130561Sobrien } 134968765Sobrien} 135068765Sobrien 1351130561Sobrien/* identifier ::= <(unqualified source code identifier)> */ 135268765Sobrien 1353130561Sobrienstatic struct demangle_component * 1354218822Sdimd_identifier (struct d_info *di, int len) 1355130561Sobrien{ 1356130561Sobrien const char *name; 135768765Sobrien 1358130561Sobrien name = d_str (di); 135968765Sobrien 1360130561Sobrien if (di->send - name < len) 1361130561Sobrien return NULL; 136268765Sobrien 1363130561Sobrien d_advance (di, len); 136468765Sobrien 1365130561Sobrien /* A Java mangled name may have a trailing '$' if it is a C++ 1366130561Sobrien keyword. This '$' is not included in the length count. We just 1367130561Sobrien ignore the '$'. */ 1368130561Sobrien if ((di->options & DMGL_JAVA) != 0 1369130561Sobrien && d_peek_char (di) == '$') 1370130561Sobrien d_advance (di, 1); 137168765Sobrien 1372130561Sobrien /* Look for something which looks like a gcc encoding of an 1373130561Sobrien anonymous namespace, and replace it with a more user friendly 1374130561Sobrien name. */ 1375130561Sobrien if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 1376130561Sobrien && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX, 1377130561Sobrien ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0) 1378130561Sobrien { 1379130561Sobrien const char *s; 138068765Sobrien 1381130561Sobrien s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN; 1382130561Sobrien if ((*s == '.' || *s == '_' || *s == '$') 1383130561Sobrien && s[1] == 'N') 1384130561Sobrien { 1385130561Sobrien di->expansion -= len - sizeof "(anonymous namespace)"; 1386130561Sobrien return d_make_name (di, "(anonymous namespace)", 1387130561Sobrien sizeof "(anonymous namespace)" - 1); 1388130561Sobrien } 1389130561Sobrien } 1390130561Sobrien 1391130561Sobrien return d_make_name (di, name, len); 139268765Sobrien} 139368765Sobrien 1394130561Sobrien/* operator_name ::= many different two character encodings. 1395130561Sobrien ::= cv <type> 1396130561Sobrien ::= v <digit> <source-name> 1397130561Sobrien*/ 139868765Sobrien 1399130561Sobrien#define NL(s) s, (sizeof s) - 1 1400130561Sobrien 1401130561SobrienCP_STATIC_IF_GLIBCPP_V3 1402130561Sobrienconst struct demangle_operator_info cplus_demangle_operators[] = 140368765Sobrien{ 1404130561Sobrien { "aN", NL ("&="), 2 }, 1405130561Sobrien { "aS", NL ("="), 2 }, 1406130561Sobrien { "aa", NL ("&&"), 2 }, 1407130561Sobrien { "ad", NL ("&"), 1 }, 1408130561Sobrien { "an", NL ("&"), 2 }, 1409130561Sobrien { "cl", NL ("()"), 0 }, 1410130561Sobrien { "cm", NL (","), 2 }, 1411130561Sobrien { "co", NL ("~"), 1 }, 1412130561Sobrien { "dV", NL ("/="), 2 }, 1413130561Sobrien { "da", NL ("delete[]"), 1 }, 1414130561Sobrien { "de", NL ("*"), 1 }, 1415130561Sobrien { "dl", NL ("delete"), 1 }, 1416130561Sobrien { "dv", NL ("/"), 2 }, 1417130561Sobrien { "eO", NL ("^="), 2 }, 1418130561Sobrien { "eo", NL ("^"), 2 }, 1419130561Sobrien { "eq", NL ("=="), 2 }, 1420130561Sobrien { "ge", NL (">="), 2 }, 1421130561Sobrien { "gt", NL (">"), 2 }, 1422130561Sobrien { "ix", NL ("[]"), 2 }, 1423130561Sobrien { "lS", NL ("<<="), 2 }, 1424130561Sobrien { "le", NL ("<="), 2 }, 1425130561Sobrien { "ls", NL ("<<"), 2 }, 1426130561Sobrien { "lt", NL ("<"), 2 }, 1427130561Sobrien { "mI", NL ("-="), 2 }, 1428130561Sobrien { "mL", NL ("*="), 2 }, 1429130561Sobrien { "mi", NL ("-"), 2 }, 1430130561Sobrien { "ml", NL ("*"), 2 }, 1431130561Sobrien { "mm", NL ("--"), 1 }, 1432130561Sobrien { "na", NL ("new[]"), 1 }, 1433130561Sobrien { "ne", NL ("!="), 2 }, 1434130561Sobrien { "ng", NL ("-"), 1 }, 1435130561Sobrien { "nt", NL ("!"), 1 }, 1436130561Sobrien { "nw", NL ("new"), 1 }, 1437130561Sobrien { "oR", NL ("|="), 2 }, 1438130561Sobrien { "oo", NL ("||"), 2 }, 1439130561Sobrien { "or", NL ("|"), 2 }, 1440130561Sobrien { "pL", NL ("+="), 2 }, 1441130561Sobrien { "pl", NL ("+"), 2 }, 1442130561Sobrien { "pm", NL ("->*"), 2 }, 1443130561Sobrien { "pp", NL ("++"), 1 }, 1444130561Sobrien { "ps", NL ("+"), 1 }, 1445130561Sobrien { "pt", NL ("->"), 2 }, 1446130561Sobrien { "qu", NL ("?"), 3 }, 1447130561Sobrien { "rM", NL ("%="), 2 }, 1448130561Sobrien { "rS", NL (">>="), 2 }, 1449130561Sobrien { "rm", NL ("%"), 2 }, 1450130561Sobrien { "rs", NL (">>"), 2 }, 1451130561Sobrien { "st", NL ("sizeof "), 1 }, 1452130561Sobrien { "sz", NL ("sizeof "), 1 }, 1453130561Sobrien { NULL, NULL, 0, 0 } 1454130561Sobrien}; 145568765Sobrien 1456130561Sobrienstatic struct demangle_component * 1457218822Sdimd_operator_name (struct d_info *di) 1458130561Sobrien{ 1459130561Sobrien char c1; 1460130561Sobrien char c2; 146168765Sobrien 1462130561Sobrien c1 = d_next_char (di); 1463130561Sobrien c2 = d_next_char (di); 1464130561Sobrien if (c1 == 'v' && IS_DIGIT (c2)) 1465130561Sobrien return d_make_extended_operator (di, c2 - '0', d_source_name (di)); 1466130561Sobrien else if (c1 == 'c' && c2 == 'v') 1467130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_CAST, 1468130561Sobrien cplus_demangle_type (di), NULL); 1469130561Sobrien else 147068765Sobrien { 1471130561Sobrien /* LOW is the inclusive lower bound. */ 1472130561Sobrien int low = 0; 1473130561Sobrien /* HIGH is the exclusive upper bound. We subtract one to ignore 1474130561Sobrien the sentinel at the end of the array. */ 1475130561Sobrien int high = ((sizeof (cplus_demangle_operators) 1476130561Sobrien / sizeof (cplus_demangle_operators[0])) 1477130561Sobrien - 1); 147868765Sobrien 1479130561Sobrien while (1) 148068765Sobrien { 1481130561Sobrien int i; 1482130561Sobrien const struct demangle_operator_info *p; 1483130561Sobrien 1484130561Sobrien i = low + (high - low) / 2; 1485130561Sobrien p = cplus_demangle_operators + i; 1486130561Sobrien 1487130561Sobrien if (c1 == p->code[0] && c2 == p->code[1]) 1488130561Sobrien return d_make_operator (di, p); 1489130561Sobrien 1490130561Sobrien if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1])) 1491130561Sobrien high = i; 1492130561Sobrien else 1493130561Sobrien low = i + 1; 1494130561Sobrien if (low == high) 1495130561Sobrien return NULL; 149668765Sobrien } 149768765Sobrien } 149868765Sobrien} 149968765Sobrien 1500130561Sobrien/* <special-name> ::= TV <type> 1501130561Sobrien ::= TT <type> 1502130561Sobrien ::= TI <type> 1503130561Sobrien ::= TS <type> 1504130561Sobrien ::= GV <(object) name> 1505130561Sobrien ::= T <call-offset> <(base) encoding> 1506130561Sobrien ::= Tc <call-offset> <call-offset> <(base) encoding> 1507130561Sobrien Also g++ extensions: 1508130561Sobrien ::= TC <type> <(offset) number> _ <(base) type> 1509130561Sobrien ::= TF <type> 1510130561Sobrien ::= TJ <type> 1511130561Sobrien ::= GR <name> 1512218822Sdim ::= GA <encoding> 1513130561Sobrien*/ 151468765Sobrien 1515130561Sobrienstatic struct demangle_component * 1516218822Sdimd_special_name (struct d_info *di) 151768765Sobrien{ 1518130561Sobrien di->expansion += 20; 1519218822Sdim if (d_check_char (di, 'T')) 152068765Sobrien { 1521130561Sobrien switch (d_next_char (di)) 1522130561Sobrien { 1523130561Sobrien case 'V': 1524130561Sobrien di->expansion -= 5; 1525130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE, 1526130561Sobrien cplus_demangle_type (di), NULL); 1527130561Sobrien case 'T': 1528130561Sobrien di->expansion -= 10; 1529130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_VTT, 1530130561Sobrien cplus_demangle_type (di), NULL); 1531130561Sobrien case 'I': 1532130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO, 1533130561Sobrien cplus_demangle_type (di), NULL); 1534130561Sobrien case 'S': 1535130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME, 1536130561Sobrien cplus_demangle_type (di), NULL); 1537104834Sobrien 1538130561Sobrien case 'h': 1539130561Sobrien if (! d_call_offset (di, 'h')) 1540130561Sobrien return NULL; 1541130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_THUNK, 1542130561Sobrien d_encoding (di, 0), NULL); 1543130561Sobrien 1544130561Sobrien case 'v': 1545130561Sobrien if (! d_call_offset (di, 'v')) 1546130561Sobrien return NULL; 1547130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK, 1548130561Sobrien d_encoding (di, 0), NULL); 1549130561Sobrien 1550130561Sobrien case 'c': 1551130561Sobrien if (! d_call_offset (di, '\0')) 1552130561Sobrien return NULL; 1553130561Sobrien if (! d_call_offset (di, '\0')) 1554130561Sobrien return NULL; 1555130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK, 1556130561Sobrien d_encoding (di, 0), NULL); 1557130561Sobrien 1558130561Sobrien case 'C': 1559130561Sobrien { 1560130561Sobrien struct demangle_component *derived_type; 1561130561Sobrien long offset; 1562130561Sobrien struct demangle_component *base_type; 1563130561Sobrien 1564130561Sobrien derived_type = cplus_demangle_type (di); 1565130561Sobrien offset = d_number (di); 1566130561Sobrien if (offset < 0) 1567130561Sobrien return NULL; 1568218822Sdim if (! d_check_char (di, '_')) 1569130561Sobrien return NULL; 1570130561Sobrien base_type = cplus_demangle_type (di); 1571130561Sobrien /* We don't display the offset. FIXME: We should display 1572130561Sobrien it in verbose mode. */ 1573130561Sobrien di->expansion += 5; 1574130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, 1575130561Sobrien base_type, derived_type); 1576130561Sobrien } 1577130561Sobrien 1578130561Sobrien case 'F': 1579130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN, 1580130561Sobrien cplus_demangle_type (di), NULL); 1581130561Sobrien case 'J': 1582130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS, 1583130561Sobrien cplus_demangle_type (di), NULL); 1584130561Sobrien 1585130561Sobrien default: 1586130561Sobrien return NULL; 1587104834Sobrien } 158868765Sobrien } 1589218822Sdim else if (d_check_char (di, 'G')) 159077298Sobrien { 1591130561Sobrien switch (d_next_char (di)) 1592130561Sobrien { 1593130561Sobrien case 'V': 1594130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL); 159577298Sobrien 1596130561Sobrien case 'R': 1597130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di), 1598130561Sobrien NULL); 1599130561Sobrien 1600218822Sdim case 'A': 1601218822Sdim return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, 1602218822Sdim d_encoding (di, 0), NULL); 1603218822Sdim 1604130561Sobrien default: 1605130561Sobrien return NULL; 160677298Sobrien } 160777298Sobrien } 1608130561Sobrien else 1609130561Sobrien return NULL; 161068765Sobrien} 161168765Sobrien 1612130561Sobrien/* <call-offset> ::= h <nv-offset> _ 1613130561Sobrien ::= v <v-offset> _ 161468765Sobrien 1615130561Sobrien <nv-offset> ::= <(offset) number> 161668765Sobrien 1617130561Sobrien <v-offset> ::= <(offset) number> _ <(virtual offset) number> 161868765Sobrien 1619130561Sobrien The C parameter, if not '\0', is a character we just read which is 1620130561Sobrien the start of the <call-offset>. 162168765Sobrien 1622130561Sobrien We don't display the offset information anywhere. FIXME: We should 1623130561Sobrien display it in verbose mode. */ 162468765Sobrien 1625130561Sobrienstatic int 1626218822Sdimd_call_offset (struct d_info *di, int c) 1627130561Sobrien{ 1628130561Sobrien if (c == '\0') 1629130561Sobrien c = d_next_char (di); 163068765Sobrien 1631130561Sobrien if (c == 'h') 1632218822Sdim d_number (di); 1633130561Sobrien else if (c == 'v') 163468765Sobrien { 1635218822Sdim d_number (di); 1636218822Sdim if (! d_check_char (di, '_')) 1637130561Sobrien return 0; 1638218822Sdim d_number (di); 163968765Sobrien } 1640130561Sobrien else 1641130561Sobrien return 0; 164268765Sobrien 1643218822Sdim if (! d_check_char (di, '_')) 1644130561Sobrien return 0; 164568765Sobrien 1646130561Sobrien return 1; 1647130561Sobrien} 1648130561Sobrien 1649130561Sobrien/* <ctor-dtor-name> ::= C1 1650130561Sobrien ::= C2 1651130561Sobrien ::= C3 1652130561Sobrien ::= D0 1653130561Sobrien ::= D1 1654130561Sobrien ::= D2 1655130561Sobrien*/ 1656130561Sobrien 1657130561Sobrienstatic struct demangle_component * 1658218822Sdimd_ctor_dtor_name (struct d_info *di) 1659130561Sobrien{ 1660130561Sobrien if (di->last_name != NULL) 1661104834Sobrien { 1662130561Sobrien if (di->last_name->type == DEMANGLE_COMPONENT_NAME) 1663130561Sobrien di->expansion += di->last_name->u.s_name.len; 1664130561Sobrien else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD) 1665130561Sobrien di->expansion += di->last_name->u.s_string.len; 1666104834Sobrien } 1667218822Sdim switch (d_peek_char (di)) 166868765Sobrien { 1669130561Sobrien case 'C': 1670130561Sobrien { 1671130561Sobrien enum gnu_v3_ctor_kinds kind; 167268765Sobrien 1673218822Sdim switch (d_peek_next_char (di)) 1674130561Sobrien { 1675130561Sobrien case '1': 1676130561Sobrien kind = gnu_v3_complete_object_ctor; 1677130561Sobrien break; 1678130561Sobrien case '2': 1679130561Sobrien kind = gnu_v3_base_object_ctor; 1680130561Sobrien break; 1681130561Sobrien case '3': 1682130561Sobrien kind = gnu_v3_complete_object_allocating_ctor; 1683130561Sobrien break; 1684130561Sobrien default: 1685130561Sobrien return NULL; 1686130561Sobrien } 1687218822Sdim d_advance (di, 2); 1688130561Sobrien return d_make_ctor (di, kind, di->last_name); 1689130561Sobrien } 169068765Sobrien 1691130561Sobrien case 'D': 1692130561Sobrien { 1693130561Sobrien enum gnu_v3_dtor_kinds kind; 169468765Sobrien 1695218822Sdim switch (d_peek_next_char (di)) 1696130561Sobrien { 1697130561Sobrien case '0': 1698130561Sobrien kind = gnu_v3_deleting_dtor; 1699130561Sobrien break; 1700130561Sobrien case '1': 1701130561Sobrien kind = gnu_v3_complete_object_dtor; 1702130561Sobrien break; 1703130561Sobrien case '2': 1704130561Sobrien kind = gnu_v3_base_object_dtor; 1705130561Sobrien break; 1706130561Sobrien default: 1707130561Sobrien return NULL; 1708130561Sobrien } 1709218822Sdim d_advance (di, 2); 1710130561Sobrien return d_make_dtor (di, kind, di->last_name); 1711130561Sobrien } 171268765Sobrien 1713130561Sobrien default: 1714130561Sobrien return NULL; 171568765Sobrien } 171668765Sobrien} 171768765Sobrien 1718130561Sobrien/* <type> ::= <builtin-type> 1719130561Sobrien ::= <function-type> 1720130561Sobrien ::= <class-enum-type> 1721130561Sobrien ::= <array-type> 1722130561Sobrien ::= <pointer-to-member-type> 1723130561Sobrien ::= <template-param> 1724130561Sobrien ::= <template-template-param> <template-args> 1725130561Sobrien ::= <substitution> 1726130561Sobrien ::= <CV-qualifiers> <type> 1727130561Sobrien ::= P <type> 1728130561Sobrien ::= R <type> 1729130561Sobrien ::= C <type> 1730130561Sobrien ::= G <type> 1731130561Sobrien ::= U <source-name> <type> 173277298Sobrien 1733130561Sobrien <builtin-type> ::= various one letter codes 1734130561Sobrien ::= u <source-name> 1735130561Sobrien*/ 173677298Sobrien 1737130561SobrienCP_STATIC_IF_GLIBCPP_V3 1738130561Sobrienconst struct demangle_builtin_type_info 1739130561Sobriencplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = 174077298Sobrien{ 1741218822Sdim /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_DEFAULT }, 1742130561Sobrien /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL }, 1743218822Sdim /* c */ { NL ("char"), NL ("byte"), D_PRINT_DEFAULT }, 1744218822Sdim /* d */ { NL ("double"), NL ("double"), D_PRINT_FLOAT }, 1745218822Sdim /* e */ { NL ("long double"), NL ("long double"), D_PRINT_FLOAT }, 1746218822Sdim /* f */ { NL ("float"), NL ("float"), D_PRINT_FLOAT }, 1747218822Sdim /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_FLOAT }, 1748218822Sdim /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT }, 1749130561Sobrien /* i */ { NL ("int"), NL ("int"), D_PRINT_INT }, 1750218822Sdim /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_UNSIGNED }, 1751130561Sobrien /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, 1752130561Sobrien /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG }, 1753218822Sdim /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG }, 1754130561Sobrien /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT }, 1755218822Sdim /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), 1756218822Sdim D_PRINT_DEFAULT }, 1757130561Sobrien /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, 1758130561Sobrien /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, 1759130561Sobrien /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, 1760218822Sdim /* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT }, 1761218822Sdim /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT }, 1762130561Sobrien /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, 1763130561Sobrien /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID }, 1764218822Sdim /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT }, 1765218822Sdim /* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG }, 1766218822Sdim /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), 1767218822Sdim D_PRINT_UNSIGNED_LONG_LONG }, 1768130561Sobrien /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT }, 1769130561Sobrien}; 177077298Sobrien 1771130561SobrienCP_STATIC_IF_GLIBCPP_V3 1772130561Sobrienstruct demangle_component * 1773218822Sdimcplus_demangle_type (struct d_info *di) 1774130561Sobrien{ 1775130561Sobrien char peek; 1776130561Sobrien struct demangle_component *ret; 1777130561Sobrien int can_subst; 177877298Sobrien 1779130561Sobrien /* The ABI specifies that when CV-qualifiers are used, the base type 1780130561Sobrien is substitutable, and the fully qualified type is substitutable, 1781130561Sobrien but the base type with a strict subset of the CV-qualifiers is 1782130561Sobrien not substitutable. The natural recursive implementation of the 1783130561Sobrien CV-qualifiers would cause subsets to be substitutable, so instead 1784130561Sobrien we pull them all off now. 178577298Sobrien 1786130561Sobrien FIXME: The ABI says that order-insensitive vendor qualifiers 1787130561Sobrien should be handled in the same way, but we have no way to tell 1788130561Sobrien which vendor qualifiers are order-insensitive and which are 1789130561Sobrien order-sensitive. So we just assume that they are all 1790130561Sobrien order-sensitive. g++ 3.4 supports only one vendor qualifier, 1791130561Sobrien __vector, and it treats it as order-sensitive when mangling 1792130561Sobrien names. */ 1793130561Sobrien 1794130561Sobrien peek = d_peek_char (di); 1795130561Sobrien if (peek == 'r' || peek == 'V' || peek == 'K') 179677298Sobrien { 1797130561Sobrien struct demangle_component **pret; 1798130561Sobrien 1799130561Sobrien pret = d_cv_qualifiers (di, &ret, 0); 1800130561Sobrien if (pret == NULL) 1801130561Sobrien return NULL; 1802130561Sobrien *pret = cplus_demangle_type (di); 1803218822Sdim if (! *pret || ! d_add_substitution (di, ret)) 1804130561Sobrien return NULL; 1805130561Sobrien return ret; 180677298Sobrien } 180777298Sobrien 1808130561Sobrien can_subst = 1; 180977298Sobrien 1810130561Sobrien switch (peek) 1811130561Sobrien { 1812130561Sobrien case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': 1813130561Sobrien case 'h': case 'i': case 'j': case 'l': case 'm': case 'n': 1814130561Sobrien case 'o': case 's': case 't': 1815130561Sobrien case 'v': case 'w': case 'x': case 'y': case 'z': 1816130561Sobrien ret = d_make_builtin_type (di, 1817130561Sobrien &cplus_demangle_builtin_types[peek - 'a']); 1818130561Sobrien di->expansion += ret->u.s_builtin.type->len; 1819130561Sobrien can_subst = 0; 1820130561Sobrien d_advance (di, 1); 1821130561Sobrien break; 182277298Sobrien 1823130561Sobrien case 'u': 1824130561Sobrien d_advance (di, 1); 1825130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE, 1826130561Sobrien d_source_name (di), NULL); 1827130561Sobrien break; 182877298Sobrien 1829130561Sobrien case 'F': 1830130561Sobrien ret = d_function_type (di); 1831130561Sobrien break; 183277298Sobrien 1833130561Sobrien case '0': case '1': case '2': case '3': case '4': 1834130561Sobrien case '5': case '6': case '7': case '8': case '9': 1835130561Sobrien case 'N': 1836130561Sobrien case 'Z': 1837130561Sobrien ret = d_class_enum_type (di); 1838130561Sobrien break; 183977298Sobrien 1840130561Sobrien case 'A': 1841130561Sobrien ret = d_array_type (di); 1842130561Sobrien break; 184377298Sobrien 1844130561Sobrien case 'M': 1845130561Sobrien ret = d_pointer_to_member_type (di); 1846130561Sobrien break; 184777298Sobrien 1848130561Sobrien case 'T': 1849130561Sobrien ret = d_template_param (di); 1850130561Sobrien if (d_peek_char (di) == 'I') 1851130561Sobrien { 1852130561Sobrien /* This is <template-template-param> <template-args>. The 1853130561Sobrien <template-template-param> part is a substitution 1854130561Sobrien candidate. */ 1855130561Sobrien if (! d_add_substitution (di, ret)) 1856130561Sobrien return NULL; 1857130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, 1858130561Sobrien d_template_args (di)); 1859130561Sobrien } 1860130561Sobrien break; 186177298Sobrien 1862130561Sobrien case 'S': 1863130561Sobrien /* If this is a special substitution, then it is the start of 1864130561Sobrien <class-enum-type>. */ 1865130561Sobrien { 1866130561Sobrien char peek_next; 186777298Sobrien 1868130561Sobrien peek_next = d_peek_next_char (di); 1869130561Sobrien if (IS_DIGIT (peek_next) 1870130561Sobrien || peek_next == '_' 1871130561Sobrien || IS_UPPER (peek_next)) 1872130561Sobrien { 1873130561Sobrien ret = d_substitution (di, 0); 1874130561Sobrien /* The substituted name may have been a template name and 1875130561Sobrien may be followed by tepmlate args. */ 1876130561Sobrien if (d_peek_char (di) == 'I') 1877130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, 1878130561Sobrien d_template_args (di)); 1879130561Sobrien else 1880130561Sobrien can_subst = 0; 1881130561Sobrien } 1882130561Sobrien else 1883130561Sobrien { 1884130561Sobrien ret = d_class_enum_type (di); 1885130561Sobrien /* If the substitution was a complete type, then it is not 1886130561Sobrien a new substitution candidate. However, if the 1887130561Sobrien substitution was followed by template arguments, then 1888130561Sobrien the whole thing is a substitution candidate. */ 1889130561Sobrien if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) 1890130561Sobrien can_subst = 0; 1891130561Sobrien } 1892130561Sobrien } 1893130561Sobrien break; 1894130561Sobrien 1895130561Sobrien case 'P': 1896130561Sobrien d_advance (di, 1); 1897130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER, 1898130561Sobrien cplus_demangle_type (di), NULL); 1899130561Sobrien break; 1900130561Sobrien 1901130561Sobrien case 'R': 1902130561Sobrien d_advance (di, 1); 1903130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE, 1904130561Sobrien cplus_demangle_type (di), NULL); 1905130561Sobrien break; 1906130561Sobrien 1907130561Sobrien case 'C': 1908130561Sobrien d_advance (di, 1); 1909130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX, 1910130561Sobrien cplus_demangle_type (di), NULL); 1911130561Sobrien break; 1912130561Sobrien 1913130561Sobrien case 'G': 1914130561Sobrien d_advance (di, 1); 1915130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY, 1916130561Sobrien cplus_demangle_type (di), NULL); 1917130561Sobrien break; 1918130561Sobrien 1919130561Sobrien case 'U': 1920130561Sobrien d_advance (di, 1); 1921130561Sobrien ret = d_source_name (di); 1922130561Sobrien ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, 1923130561Sobrien cplus_demangle_type (di), ret); 1924130561Sobrien break; 1925130561Sobrien 1926130561Sobrien default: 1927130561Sobrien return NULL; 1928130561Sobrien } 1929130561Sobrien 1930130561Sobrien if (can_subst) 193177298Sobrien { 1932130561Sobrien if (! d_add_substitution (di, ret)) 1933130561Sobrien return NULL; 193477298Sobrien } 193577298Sobrien 1936130561Sobrien return ret; 193777298Sobrien} 193877298Sobrien 1939130561Sobrien/* <CV-qualifiers> ::= [r] [V] [K] */ 194077298Sobrien 1941130561Sobrienstatic struct demangle_component ** 1942218822Sdimd_cv_qualifiers (struct d_info *di, 1943218822Sdim struct demangle_component **pret, int member_fn) 194477298Sobrien{ 1945130561Sobrien char peek; 194677298Sobrien 1947130561Sobrien peek = d_peek_char (di); 1948130561Sobrien while (peek == 'r' || peek == 'V' || peek == 'K') 194977298Sobrien { 1950130561Sobrien enum demangle_component_type t; 195177298Sobrien 1952130561Sobrien d_advance (di, 1); 1953130561Sobrien if (peek == 'r') 1954130561Sobrien { 1955130561Sobrien t = (member_fn 1956130561Sobrien ? DEMANGLE_COMPONENT_RESTRICT_THIS 1957130561Sobrien : DEMANGLE_COMPONENT_RESTRICT); 1958130561Sobrien di->expansion += sizeof "restrict"; 1959130561Sobrien } 1960130561Sobrien else if (peek == 'V') 1961130561Sobrien { 1962130561Sobrien t = (member_fn 1963130561Sobrien ? DEMANGLE_COMPONENT_VOLATILE_THIS 1964130561Sobrien : DEMANGLE_COMPONENT_VOLATILE); 1965130561Sobrien di->expansion += sizeof "volatile"; 1966130561Sobrien } 1967130561Sobrien else 1968130561Sobrien { 1969130561Sobrien t = (member_fn 1970130561Sobrien ? DEMANGLE_COMPONENT_CONST_THIS 1971130561Sobrien : DEMANGLE_COMPONENT_CONST); 1972130561Sobrien di->expansion += sizeof "const"; 1973130561Sobrien } 197477298Sobrien 1975130561Sobrien *pret = d_make_comp (di, t, NULL, NULL); 1976130561Sobrien if (*pret == NULL) 1977130561Sobrien return NULL; 1978130561Sobrien pret = &d_left (*pret); 1979130561Sobrien 1980130561Sobrien peek = d_peek_char (di); 198177298Sobrien } 198277298Sobrien 1983130561Sobrien return pret; 198477298Sobrien} 198577298Sobrien 1986130561Sobrien/* <function-type> ::= F [Y] <bare-function-type> E */ 198768765Sobrien 1988130561Sobrienstatic struct demangle_component * 1989218822Sdimd_function_type (struct d_info *di) 1990130561Sobrien{ 1991130561Sobrien struct demangle_component *ret; 199268765Sobrien 1993218822Sdim if (! d_check_char (di, 'F')) 1994130561Sobrien return NULL; 1995130561Sobrien if (d_peek_char (di) == 'Y') 1996130561Sobrien { 1997130561Sobrien /* Function has C linkage. We don't print this information. 1998130561Sobrien FIXME: We should print it in verbose mode. */ 1999130561Sobrien d_advance (di, 1); 2000130561Sobrien } 2001130561Sobrien ret = d_bare_function_type (di, 1); 2002218822Sdim if (! d_check_char (di, 'E')) 2003130561Sobrien return NULL; 2004130561Sobrien return ret; 2005130561Sobrien} 200677298Sobrien 2007218822Sdim/* <bare-function-type> ::= [J]<type>+ */ 200877298Sobrien 2009130561Sobrienstatic struct demangle_component * 2010218822Sdimd_bare_function_type (struct d_info *di, int has_return_type) 2011130561Sobrien{ 2012130561Sobrien struct demangle_component *return_type; 2013130561Sobrien struct demangle_component *tl; 2014130561Sobrien struct demangle_component **ptl; 2015218822Sdim char peek; 201677298Sobrien 2017218822Sdim /* Detect special qualifier indicating that the first argument 2018218822Sdim is the return type. */ 2019218822Sdim peek = d_peek_char (di); 2020218822Sdim if (peek == 'J') 2021218822Sdim { 2022218822Sdim d_advance (di, 1); 2023218822Sdim has_return_type = 1; 2024218822Sdim } 2025218822Sdim 2026130561Sobrien return_type = NULL; 2027130561Sobrien tl = NULL; 2028130561Sobrien ptl = &tl; 2029130561Sobrien while (1) 2030130561Sobrien { 2031130561Sobrien struct demangle_component *type; 203277298Sobrien 2033130561Sobrien peek = d_peek_char (di); 2034130561Sobrien if (peek == '\0' || peek == 'E') 2035130561Sobrien break; 2036130561Sobrien type = cplus_demangle_type (di); 2037130561Sobrien if (type == NULL) 2038130561Sobrien return NULL; 2039130561Sobrien if (has_return_type) 2040130561Sobrien { 2041130561Sobrien return_type = type; 2042130561Sobrien has_return_type = 0; 2043130561Sobrien } 2044130561Sobrien else 2045130561Sobrien { 2046130561Sobrien *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); 2047130561Sobrien if (*ptl == NULL) 2048130561Sobrien return NULL; 2049130561Sobrien ptl = &d_right (*ptl); 2050130561Sobrien } 2051130561Sobrien } 205277298Sobrien 2053130561Sobrien /* There should be at least one parameter type besides the optional 2054130561Sobrien return type. A function which takes no arguments will have a 2055130561Sobrien single parameter type void. */ 2056130561Sobrien if (tl == NULL) 2057130561Sobrien return NULL; 205868765Sobrien 2059130561Sobrien /* If we have a single parameter type void, omit it. */ 2060130561Sobrien if (d_right (tl) == NULL 2061130561Sobrien && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE 2062130561Sobrien && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) 2063130561Sobrien { 2064130561Sobrien di->expansion -= d_left (tl)->u.s_builtin.type->len; 2065130561Sobrien tl = NULL; 2066130561Sobrien } 206768765Sobrien 2068130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl); 2069130561Sobrien} 2070130561Sobrien 2071130561Sobrien/* <class-enum-type> ::= <name> */ 2072130561Sobrien 2073130561Sobrienstatic struct demangle_component * 2074218822Sdimd_class_enum_type (struct d_info *di) 207568765Sobrien{ 2076130561Sobrien return d_name (di); 2077130561Sobrien} 207868765Sobrien 2079130561Sobrien/* <array-type> ::= A <(positive dimension) number> _ <(element) type> 2080130561Sobrien ::= A [<(dimension) expression>] _ <(element) type> 2081130561Sobrien*/ 208268765Sobrien 2083130561Sobrienstatic struct demangle_component * 2084218822Sdimd_array_type (struct d_info *di) 2085130561Sobrien{ 2086130561Sobrien char peek; 2087130561Sobrien struct demangle_component *dim; 2088130561Sobrien 2089218822Sdim if (! d_check_char (di, 'A')) 2090130561Sobrien return NULL; 2091130561Sobrien 2092130561Sobrien peek = d_peek_char (di); 2093130561Sobrien if (peek == '_') 2094130561Sobrien dim = NULL; 2095130561Sobrien else if (IS_DIGIT (peek)) 209668765Sobrien { 2097130561Sobrien const char *s; 2098130561Sobrien 2099130561Sobrien s = d_str (di); 2100130561Sobrien do 210189857Sobrien { 2102130561Sobrien d_advance (di, 1); 2103130561Sobrien peek = d_peek_char (di); 210489857Sobrien } 2105130561Sobrien while (IS_DIGIT (peek)); 2106130561Sobrien dim = d_make_name (di, s, d_str (di) - s); 2107130561Sobrien if (dim == NULL) 2108130561Sobrien return NULL; 210968765Sobrien } 2110130561Sobrien else 211168765Sobrien { 2112130561Sobrien dim = d_expression (di); 2113130561Sobrien if (dim == NULL) 2114130561Sobrien return NULL; 2115130561Sobrien } 211668765Sobrien 2117218822Sdim if (! d_check_char (di, '_')) 2118130561Sobrien return NULL; 211968765Sobrien 2120130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, 2121130561Sobrien cplus_demangle_type (di)); 2122130561Sobrien} 212368765Sobrien 2124130561Sobrien/* <pointer-to-member-type> ::= M <(class) type> <(member) type> */ 212568765Sobrien 2126130561Sobrienstatic struct demangle_component * 2127218822Sdimd_pointer_to_member_type (struct d_info *di) 2128130561Sobrien{ 2129130561Sobrien struct demangle_component *cl; 2130130561Sobrien struct demangle_component *mem; 2131130561Sobrien struct demangle_component **pmem; 213268765Sobrien 2133218822Sdim if (! d_check_char (di, 'M')) 2134130561Sobrien return NULL; 213568765Sobrien 2136130561Sobrien cl = cplus_demangle_type (di); 213768765Sobrien 2138130561Sobrien /* The ABI specifies that any type can be a substitution source, and 2139130561Sobrien that M is followed by two types, and that when a CV-qualified 2140130561Sobrien type is seen both the base type and the CV-qualified types are 2141130561Sobrien substitution sources. The ABI also specifies that for a pointer 2142130561Sobrien to a CV-qualified member function, the qualifiers are attached to 2143130561Sobrien the second type. Given the grammar, a plain reading of the ABI 2144130561Sobrien suggests that both the CV-qualified member function and the 2145130561Sobrien non-qualified member function are substitution sources. However, 2146130561Sobrien g++ does not work that way. g++ treats only the CV-qualified 2147130561Sobrien member function as a substitution source. FIXME. So to work 2148130561Sobrien with g++, we need to pull off the CV-qualifiers here, in order to 2149218822Sdim avoid calling add_substitution() in cplus_demangle_type(). But 2150218822Sdim for a CV-qualified member which is not a function, g++ does 2151218822Sdim follow the ABI, so we need to handle that case here by calling 2152218822Sdim d_add_substitution ourselves. */ 215368765Sobrien 2154130561Sobrien pmem = d_cv_qualifiers (di, &mem, 1); 2155130561Sobrien if (pmem == NULL) 2156130561Sobrien return NULL; 2157130561Sobrien *pmem = cplus_demangle_type (di); 2158218822Sdim if (*pmem == NULL) 2159218822Sdim return NULL; 216068765Sobrien 2161218822Sdim if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) 2162218822Sdim { 2163218822Sdim if (! d_add_substitution (di, mem)) 2164218822Sdim return NULL; 2165218822Sdim } 2166218822Sdim 2167130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); 2168130561Sobrien} 216968765Sobrien 2170130561Sobrien/* <template-param> ::= T_ 2171130561Sobrien ::= T <(parameter-2 non-negative) number> _ 2172130561Sobrien*/ 217377298Sobrien 2174130561Sobrienstatic struct demangle_component * 2175218822Sdimd_template_param (struct d_info *di) 2176130561Sobrien{ 2177130561Sobrien long param; 217868765Sobrien 2179218822Sdim if (! d_check_char (di, 'T')) 2180130561Sobrien return NULL; 218168765Sobrien 2182130561Sobrien if (d_peek_char (di) == '_') 2183130561Sobrien param = 0; 2184130561Sobrien else 2185130561Sobrien { 2186130561Sobrien param = d_number (di); 2187130561Sobrien if (param < 0) 2188130561Sobrien return NULL; 2189130561Sobrien param += 1; 2190130561Sobrien } 219168765Sobrien 2192218822Sdim if (! d_check_char (di, '_')) 2193130561Sobrien return NULL; 219468765Sobrien 2195130561Sobrien ++di->did_subs; 219668765Sobrien 2197130561Sobrien return d_make_template_param (di, param); 2198130561Sobrien} 219968765Sobrien 2200130561Sobrien/* <template-args> ::= I <template-arg>+ E */ 220168765Sobrien 2202130561Sobrienstatic struct demangle_component * 2203218822Sdimd_template_args (struct d_info *di) 2204130561Sobrien{ 2205130561Sobrien struct demangle_component *hold_last_name; 2206130561Sobrien struct demangle_component *al; 2207130561Sobrien struct demangle_component **pal; 2208130561Sobrien 2209130561Sobrien /* Preserve the last name we saw--don't let the template arguments 2210130561Sobrien clobber it, as that would give us the wrong name for a subsequent 2211130561Sobrien constructor or destructor. */ 2212130561Sobrien hold_last_name = di->last_name; 2213130561Sobrien 2214218822Sdim if (! d_check_char (di, 'I')) 2215130561Sobrien return NULL; 2216130561Sobrien 2217130561Sobrien al = NULL; 2218130561Sobrien pal = &al; 2219130561Sobrien while (1) 2220130561Sobrien { 2221130561Sobrien struct demangle_component *a; 2222130561Sobrien 2223130561Sobrien a = d_template_arg (di); 2224130561Sobrien if (a == NULL) 2225130561Sobrien return NULL; 2226130561Sobrien 2227130561Sobrien *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL); 2228130561Sobrien if (*pal == NULL) 2229130561Sobrien return NULL; 2230130561Sobrien pal = &d_right (*pal); 2231130561Sobrien 2232130561Sobrien if (d_peek_char (di) == 'E') 2233130561Sobrien { 2234130561Sobrien d_advance (di, 1); 2235130561Sobrien break; 223668765Sobrien } 223768765Sobrien } 223868765Sobrien 2239130561Sobrien di->last_name = hold_last_name; 2240130561Sobrien 2241130561Sobrien return al; 224268765Sobrien} 224368765Sobrien 2244130561Sobrien/* <template-arg> ::= <type> 2245130561Sobrien ::= X <expression> E 2246130561Sobrien ::= <expr-primary> 2247130561Sobrien*/ 224868765Sobrien 2249130561Sobrienstatic struct demangle_component * 2250218822Sdimd_template_arg (struct d_info *di) 225168765Sobrien{ 2252130561Sobrien struct demangle_component *ret; 225368765Sobrien 2254130561Sobrien switch (d_peek_char (di)) 2255130561Sobrien { 2256130561Sobrien case 'X': 2257130561Sobrien d_advance (di, 1); 2258130561Sobrien ret = d_expression (di); 2259218822Sdim if (! d_check_char (di, 'E')) 2260130561Sobrien return NULL; 2261130561Sobrien return ret; 226268765Sobrien 2263130561Sobrien case 'L': 2264130561Sobrien return d_expr_primary (di); 2265130561Sobrien 2266130561Sobrien default: 2267130561Sobrien return cplus_demangle_type (di); 2268130561Sobrien } 2269130561Sobrien} 2270130561Sobrien 2271130561Sobrien/* <expression> ::= <(unary) operator-name> <expression> 2272130561Sobrien ::= <(binary) operator-name> <expression> <expression> 2273130561Sobrien ::= <(trinary) operator-name> <expression> <expression> <expression> 2274130561Sobrien ::= st <type> 2275130561Sobrien ::= <template-param> 2276130561Sobrien ::= sr <type> <unqualified-name> 2277130561Sobrien ::= sr <type> <unqualified-name> <template-args> 2278130561Sobrien ::= <expr-primary> 2279130561Sobrien*/ 2280130561Sobrien 2281130561Sobrienstatic struct demangle_component * 2282218822Sdimd_expression (struct d_info *di) 2283130561Sobrien{ 2284130561Sobrien char peek; 2285130561Sobrien 2286130561Sobrien peek = d_peek_char (di); 2287130561Sobrien if (peek == 'L') 2288130561Sobrien return d_expr_primary (di); 2289130561Sobrien else if (peek == 'T') 2290130561Sobrien return d_template_param (di); 2291130561Sobrien else if (peek == 's' && d_peek_next_char (di) == 'r') 229268765Sobrien { 2293130561Sobrien struct demangle_component *type; 2294130561Sobrien struct demangle_component *name; 2295130561Sobrien 2296130561Sobrien d_advance (di, 2); 2297130561Sobrien type = cplus_demangle_type (di); 2298130561Sobrien name = d_unqualified_name (di); 2299130561Sobrien if (d_peek_char (di) != 'I') 2300130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); 2301130561Sobrien else 2302130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, 2303130561Sobrien d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, 2304130561Sobrien d_template_args (di))); 230568765Sobrien } 2306130561Sobrien else 230768765Sobrien { 2308130561Sobrien struct demangle_component *op; 2309130561Sobrien int args; 2310130561Sobrien 2311130561Sobrien op = d_operator_name (di); 2312130561Sobrien if (op == NULL) 2313130561Sobrien return NULL; 2314130561Sobrien 2315130561Sobrien if (op->type == DEMANGLE_COMPONENT_OPERATOR) 2316130561Sobrien di->expansion += op->u.s_operator.op->len - 2; 2317130561Sobrien 2318130561Sobrien if (op->type == DEMANGLE_COMPONENT_OPERATOR 2319130561Sobrien && strcmp (op->u.s_operator.op->code, "st") == 0) 2320130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, 2321130561Sobrien cplus_demangle_type (di)); 2322130561Sobrien 2323130561Sobrien switch (op->type) 232489857Sobrien { 2325130561Sobrien default: 2326130561Sobrien return NULL; 2327130561Sobrien case DEMANGLE_COMPONENT_OPERATOR: 2328130561Sobrien args = op->u.s_operator.op->args; 232989857Sobrien break; 2330130561Sobrien case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: 2331130561Sobrien args = op->u.s_extended_operator.args; 233289857Sobrien break; 2333130561Sobrien case DEMANGLE_COMPONENT_CAST: 2334130561Sobrien args = 1; 233589857Sobrien break; 233689857Sobrien } 2337130561Sobrien 2338130561Sobrien switch (args) 233968765Sobrien { 2340130561Sobrien case 1: 2341130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, 2342130561Sobrien d_expression (di)); 2343130561Sobrien case 2: 2344130561Sobrien { 2345130561Sobrien struct demangle_component *left; 2346130561Sobrien 2347130561Sobrien left = d_expression (di); 2348130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, 2349130561Sobrien d_make_comp (di, 2350130561Sobrien DEMANGLE_COMPONENT_BINARY_ARGS, 2351130561Sobrien left, 2352130561Sobrien d_expression (di))); 2353130561Sobrien } 2354130561Sobrien case 3: 2355130561Sobrien { 2356130561Sobrien struct demangle_component *first; 2357130561Sobrien struct demangle_component *second; 2358130561Sobrien 2359130561Sobrien first = d_expression (di); 2360130561Sobrien second = d_expression (di); 2361130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op, 2362130561Sobrien d_make_comp (di, 2363130561Sobrien DEMANGLE_COMPONENT_TRINARY_ARG1, 2364130561Sobrien first, 2365130561Sobrien d_make_comp (di, 2366130561Sobrien DEMANGLE_COMPONENT_TRINARY_ARG2, 2367130561Sobrien second, 2368130561Sobrien d_expression (di)))); 2369130561Sobrien } 2370130561Sobrien default: 2371130561Sobrien return NULL; 237268765Sobrien } 237368765Sobrien } 2374130561Sobrien} 2375130561Sobrien 2376130561Sobrien/* <expr-primary> ::= L <type> <(value) number> E 2377130561Sobrien ::= L <type> <(value) float> E 2378130561Sobrien ::= L <mangled-name> E 2379130561Sobrien*/ 2380130561Sobrien 2381130561Sobrienstatic struct demangle_component * 2382218822Sdimd_expr_primary (struct d_info *di) 2383130561Sobrien{ 2384130561Sobrien struct demangle_component *ret; 2385130561Sobrien 2386218822Sdim if (! d_check_char (di, 'L')) 2387130561Sobrien return NULL; 2388130561Sobrien if (d_peek_char (di) == '_') 2389130561Sobrien ret = cplus_demangle_mangled_name (di, 0); 239068765Sobrien else 2391130561Sobrien { 2392130561Sobrien struct demangle_component *type; 2393130561Sobrien enum demangle_component_type t; 2394130561Sobrien const char *s; 239568765Sobrien 2396130561Sobrien type = cplus_demangle_type (di); 2397175790Sobrien if (type == NULL) 2398175790Sobrien return NULL; 239968765Sobrien 2400130561Sobrien /* If we have a type we know how to print, we aren't going to 2401130561Sobrien print the type name itself. */ 2402130561Sobrien if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE 2403130561Sobrien && type->u.s_builtin.type->print != D_PRINT_DEFAULT) 2404130561Sobrien di->expansion -= type->u.s_builtin.type->len; 240568765Sobrien 2406130561Sobrien /* Rather than try to interpret the literal value, we just 2407130561Sobrien collect it as a string. Note that it's possible to have a 2408130561Sobrien floating point literal here. The ABI specifies that the 2409130561Sobrien format of such literals is machine independent. That's fine, 2410130561Sobrien but what's not fine is that versions of g++ up to 3.2 with 2411130561Sobrien -fabi-version=1 used upper case letters in the hex constant, 2412130561Sobrien and dumped out gcc's internal representation. That makes it 2413130561Sobrien hard to tell where the constant ends, and hard to dump the 2414130561Sobrien constant in any readable form anyhow. We don't attempt to 2415130561Sobrien handle these cases. */ 241677298Sobrien 2417130561Sobrien t = DEMANGLE_COMPONENT_LITERAL; 2418130561Sobrien if (d_peek_char (di) == 'n') 2419130561Sobrien { 2420130561Sobrien t = DEMANGLE_COMPONENT_LITERAL_NEG; 2421130561Sobrien d_advance (di, 1); 2422130561Sobrien } 2423130561Sobrien s = d_str (di); 2424130561Sobrien while (d_peek_char (di) != 'E') 2425218822Sdim { 2426218822Sdim if (d_peek_char (di) == '\0') 2427218822Sdim return NULL; 2428218822Sdim d_advance (di, 1); 2429218822Sdim } 2430130561Sobrien ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s)); 2431130561Sobrien } 2432218822Sdim if (! d_check_char (di, 'E')) 2433130561Sobrien return NULL; 2434130561Sobrien return ret; 2435130561Sobrien} 243677298Sobrien 2437130561Sobrien/* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] 2438130561Sobrien ::= Z <(function) encoding> E s [<discriminator>] 2439130561Sobrien*/ 244068765Sobrien 2441130561Sobrienstatic struct demangle_component * 2442218822Sdimd_local_name (struct d_info *di) 244368765Sobrien{ 2444130561Sobrien struct demangle_component *function; 244568765Sobrien 2446218822Sdim if (! d_check_char (di, 'Z')) 2447130561Sobrien return NULL; 244868765Sobrien 2449130561Sobrien function = d_encoding (di, 0); 245068765Sobrien 2451218822Sdim if (! d_check_char (di, 'E')) 2452130561Sobrien return NULL; 245368765Sobrien 2454130561Sobrien if (d_peek_char (di) == 's') 245577298Sobrien { 2456130561Sobrien d_advance (di, 1); 2457130561Sobrien if (! d_discriminator (di)) 2458130561Sobrien return NULL; 2459130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, 2460130561Sobrien d_make_name (di, "string literal", 2461130561Sobrien sizeof "string literal" - 1)); 2462130561Sobrien } 2463130561Sobrien else 2464130561Sobrien { 2465130561Sobrien struct demangle_component *name; 246668765Sobrien 2467130561Sobrien name = d_name (di); 2468130561Sobrien if (! d_discriminator (di)) 2469130561Sobrien return NULL; 2470130561Sobrien return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name); 2471130561Sobrien } 2472130561Sobrien} 247368765Sobrien 2474130561Sobrien/* <discriminator> ::= _ <(non-negative) number> 247568765Sobrien 2476130561Sobrien We demangle the discriminator, but we don't print it out. FIXME: 2477130561Sobrien We should print it out in verbose mode. */ 247877298Sobrien 2479130561Sobrienstatic int 2480218822Sdimd_discriminator (struct d_info *di) 2481130561Sobrien{ 2482130561Sobrien long discrim; 248377298Sobrien 2484130561Sobrien if (d_peek_char (di) != '_') 2485130561Sobrien return 1; 2486130561Sobrien d_advance (di, 1); 2487130561Sobrien discrim = d_number (di); 2488130561Sobrien if (discrim < 0) 2489130561Sobrien return 0; 2490130561Sobrien return 1; 2491130561Sobrien} 249277298Sobrien 2493130561Sobrien/* Add a new substitution. */ 2494130561Sobrien 2495130561Sobrienstatic int 2496218822Sdimd_add_substitution (struct d_info *di, struct demangle_component *dc) 2497130561Sobrien{ 2498130561Sobrien if (dc == NULL) 2499130561Sobrien return 0; 2500130561Sobrien if (di->next_sub >= di->num_subs) 2501130561Sobrien return 0; 2502130561Sobrien di->subs[di->next_sub] = dc; 2503130561Sobrien ++di->next_sub; 2504130561Sobrien return 1; 250568765Sobrien} 250668765Sobrien 2507130561Sobrien/* <substitution> ::= S <seq-id> _ 2508130561Sobrien ::= S_ 2509130561Sobrien ::= St 2510130561Sobrien ::= Sa 2511130561Sobrien ::= Sb 2512130561Sobrien ::= Ss 2513130561Sobrien ::= Si 2514130561Sobrien ::= So 2515130561Sobrien ::= Sd 251668765Sobrien 2517130561Sobrien If PREFIX is non-zero, then this type is being used as a prefix in 2518130561Sobrien a qualified name. In this case, for the standard substitutions, we 2519130561Sobrien need to check whether we are being used as a prefix for a 2520130561Sobrien constructor or destructor, and return a full template name. 2521130561Sobrien Otherwise we will get something like std::iostream::~iostream() 2522130561Sobrien which does not correspond particularly well to any function which 2523130561Sobrien actually appears in the source. 2524130561Sobrien*/ 252568765Sobrien 2526130561Sobrienstatic const struct d_standard_sub_info standard_subs[] = 252768765Sobrien{ 2528130561Sobrien { 't', NL ("std"), 2529130561Sobrien NL ("std"), 2530130561Sobrien NULL, 0 }, 2531130561Sobrien { 'a', NL ("std::allocator"), 2532130561Sobrien NL ("std::allocator"), 2533130561Sobrien NL ("allocator") }, 2534130561Sobrien { 'b', NL ("std::basic_string"), 2535130561Sobrien NL ("std::basic_string"), 2536130561Sobrien NL ("basic_string") }, 2537130561Sobrien { 's', NL ("std::string"), 2538130561Sobrien NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"), 2539130561Sobrien NL ("basic_string") }, 2540130561Sobrien { 'i', NL ("std::istream"), 2541130561Sobrien NL ("std::basic_istream<char, std::char_traits<char> >"), 2542130561Sobrien NL ("basic_istream") }, 2543130561Sobrien { 'o', NL ("std::ostream"), 2544130561Sobrien NL ("std::basic_ostream<char, std::char_traits<char> >"), 2545130561Sobrien NL ("basic_ostream") }, 2546130561Sobrien { 'd', NL ("std::iostream"), 2547130561Sobrien NL ("std::basic_iostream<char, std::char_traits<char> >"), 2548130561Sobrien NL ("basic_iostream") } 2549130561Sobrien}; 255068765Sobrien 2551130561Sobrienstatic struct demangle_component * 2552218822Sdimd_substitution (struct d_info *di, int prefix) 2553130561Sobrien{ 2554130561Sobrien char c; 255577298Sobrien 2556218822Sdim if (! d_check_char (di, 'S')) 2557130561Sobrien return NULL; 255868765Sobrien 2559130561Sobrien c = d_next_char (di); 2560130561Sobrien if (c == '_' || IS_DIGIT (c) || IS_UPPER (c)) 256168765Sobrien { 2562130561Sobrien int id; 2563130561Sobrien 2564130561Sobrien id = 0; 2565130561Sobrien if (c != '_') 256668765Sobrien { 2567130561Sobrien do 2568130561Sobrien { 2569130561Sobrien if (IS_DIGIT (c)) 2570130561Sobrien id = id * 36 + c - '0'; 2571130561Sobrien else if (IS_UPPER (c)) 2572130561Sobrien id = id * 36 + c - 'A' + 10; 2573130561Sobrien else 2574130561Sobrien return NULL; 2575218822Sdim if (id < 0) 2576218822Sdim return NULL; 2577130561Sobrien c = d_next_char (di); 2578130561Sobrien } 2579130561Sobrien while (c != '_'); 258068765Sobrien 2581130561Sobrien ++id; 2582130561Sobrien } 258368765Sobrien 2584130561Sobrien if (id >= di->next_sub) 2585130561Sobrien return NULL; 258668765Sobrien 2587130561Sobrien ++di->did_subs; 258868765Sobrien 2589130561Sobrien return di->subs[id]; 2590130561Sobrien } 2591130561Sobrien else 2592130561Sobrien { 2593130561Sobrien int verbose; 2594130561Sobrien const struct d_standard_sub_info *p; 2595130561Sobrien const struct d_standard_sub_info *pend; 259668765Sobrien 2597130561Sobrien verbose = (di->options & DMGL_VERBOSE) != 0; 2598130561Sobrien if (! verbose && prefix) 2599130561Sobrien { 2600130561Sobrien char peek; 260168765Sobrien 2602130561Sobrien peek = d_peek_char (di); 2603130561Sobrien if (peek == 'C' || peek == 'D') 2604130561Sobrien verbose = 1; 2605130561Sobrien } 260668765Sobrien 2607130561Sobrien pend = (&standard_subs[0] 2608130561Sobrien + sizeof standard_subs / sizeof standard_subs[0]); 2609130561Sobrien for (p = &standard_subs[0]; p < pend; ++p) 2610130561Sobrien { 2611130561Sobrien if (c == p->code) 2612130561Sobrien { 2613130561Sobrien const char *s; 2614130561Sobrien int len; 261577298Sobrien 2616130561Sobrien if (p->set_last_name != NULL) 2617130561Sobrien di->last_name = d_make_sub (di, p->set_last_name, 2618130561Sobrien p->set_last_name_len); 2619130561Sobrien if (verbose) 2620130561Sobrien { 2621130561Sobrien s = p->full_expansion; 2622130561Sobrien len = p->full_len; 2623130561Sobrien } 2624130561Sobrien else 2625130561Sobrien { 2626130561Sobrien s = p->simple_expansion; 2627130561Sobrien len = p->simple_len; 2628130561Sobrien } 2629130561Sobrien di->expansion += len; 2630130561Sobrien return d_make_sub (di, s, len); 2631130561Sobrien } 2632130561Sobrien } 263377298Sobrien 2634130561Sobrien return NULL; 2635130561Sobrien } 2636130561Sobrien} 263777298Sobrien 2638218822Sdim/* Initialize a growable string. */ 263968765Sobrien 2640130561Sobrienstatic void 2641218822Sdimd_growable_string_init (struct d_growable_string *dgs, size_t estimate) 2642130561Sobrien{ 2643218822Sdim dgs->buf = NULL; 2644218822Sdim dgs->len = 0; 2645218822Sdim dgs->alc = 0; 2646218822Sdim dgs->allocation_failure = 0; 264777298Sobrien 2648218822Sdim if (estimate > 0) 2649218822Sdim d_growable_string_resize (dgs, estimate); 2650218822Sdim} 2651218822Sdim 2652218822Sdim/* Grow a growable string to a given size. */ 2653218822Sdim 2654218822Sdimstatic inline void 2655218822Sdimd_growable_string_resize (struct d_growable_string *dgs, size_t need) 2656218822Sdim{ 2657218822Sdim size_t newalc; 2658218822Sdim char *newbuf; 2659218822Sdim 2660218822Sdim if (dgs->allocation_failure) 2661130561Sobrien return; 2662218822Sdim 2663218822Sdim /* Start allocation at two bytes to avoid any possibility of confusion 2664218822Sdim with the special value of 1 used as a return in *palc to indicate 2665218822Sdim allocation failures. */ 2666218822Sdim newalc = dgs->alc > 0 ? dgs->alc : 2; 2667218822Sdim while (newalc < need) 2668218822Sdim newalc <<= 1; 2669218822Sdim 2670218822Sdim newbuf = (char *) realloc (dgs->buf, newalc); 2671218822Sdim if (newbuf == NULL) 2672130561Sobrien { 2673218822Sdim free (dgs->buf); 2674218822Sdim dgs->buf = NULL; 2675218822Sdim dgs->len = 0; 2676218822Sdim dgs->alc = 0; 2677218822Sdim dgs->allocation_failure = 1; 2678218822Sdim return; 2679130561Sobrien } 2680218822Sdim dgs->buf = newbuf; 2681218822Sdim dgs->alc = newalc; 2682130561Sobrien} 268368765Sobrien 2684218822Sdim/* Append a buffer to a growable string. */ 268568765Sobrien 2686218822Sdimstatic inline void 2687218822Sdimd_growable_string_append_buffer (struct d_growable_string *dgs, 2688218822Sdim const char *s, size_t l) 2689130561Sobrien{ 2690218822Sdim size_t need; 269168765Sobrien 2692218822Sdim need = dgs->len + l + 1; 2693218822Sdim if (need > dgs->alc) 2694218822Sdim d_growable_string_resize (dgs, need); 2695218822Sdim 2696218822Sdim if (dgs->allocation_failure) 2697218822Sdim return; 2698218822Sdim 2699218822Sdim memcpy (dgs->buf + dgs->len, s, l); 2700218822Sdim dgs->buf[dgs->len + l] = '\0'; 2701218822Sdim dgs->len += l; 2702130561Sobrien} 270368765Sobrien 2704218822Sdim/* Bridge growable strings to the callback mechanism. */ 270568765Sobrien 2706130561Sobrienstatic void 2707218822Sdimd_growable_string_callback_adapter (const char *s, size_t l, void *opaque) 2708130561Sobrien{ 2709218822Sdim struct d_growable_string *dgs = (struct d_growable_string*) opaque; 271068765Sobrien 2711218822Sdim d_growable_string_append_buffer (dgs, s, l); 2712130561Sobrien} 271368765Sobrien 2714218822Sdim/* Initialize a print information structure. */ 271568765Sobrien 2716130561Sobrienstatic void 2717218822Sdimd_print_init (struct d_print_info *dpi, int options, 2718218822Sdim demangle_callbackref callback, void *opaque) 2719130561Sobrien{ 2720218822Sdim dpi->options = options; 2721218822Sdim dpi->len = 0; 2722218822Sdim dpi->last_char = '\0'; 2723218822Sdim dpi->templates = NULL; 2724218822Sdim dpi->modifiers = NULL; 2725218822Sdim 2726218822Sdim dpi->callback = callback; 2727218822Sdim dpi->opaque = opaque; 2728218822Sdim 2729218822Sdim dpi->demangle_failure = 0; 273068765Sobrien} 273168765Sobrien 2732218822Sdim/* Indicate that an error occurred during printing, and test for error. */ 2733218822Sdim 2734218822Sdimstatic inline void 2735218822Sdimd_print_error (struct d_print_info *dpi) 2736218822Sdim{ 2737218822Sdim dpi->demangle_failure = 1; 2738218822Sdim} 2739218822Sdim 2740218822Sdimstatic inline int 2741218822Sdimd_print_saw_error (struct d_print_info *dpi) 2742218822Sdim{ 2743218822Sdim return dpi->demangle_failure != 0; 2744218822Sdim} 2745218822Sdim 2746218822Sdim/* Flush buffered characters to the callback. */ 2747218822Sdim 2748218822Sdimstatic inline void 2749218822Sdimd_print_flush (struct d_print_info *dpi) 2750218822Sdim{ 2751218822Sdim dpi->buf[dpi->len] = '\0'; 2752218822Sdim dpi->callback (dpi->buf, dpi->len, dpi->opaque); 2753218822Sdim dpi->len = 0; 2754218822Sdim} 2755218822Sdim 2756218822Sdim/* Append characters and buffers for printing. */ 2757218822Sdim 2758218822Sdimstatic inline void 2759218822Sdimd_append_char (struct d_print_info *dpi, char c) 2760218822Sdim{ 2761218822Sdim if (dpi->len == sizeof (dpi->buf) - 1) 2762218822Sdim d_print_flush (dpi); 2763218822Sdim 2764218822Sdim dpi->buf[dpi->len++] = c; 2765218822Sdim dpi->last_char = c; 2766218822Sdim} 2767218822Sdim 2768218822Sdimstatic inline void 2769218822Sdimd_append_buffer (struct d_print_info *dpi, const char *s, size_t l) 2770218822Sdim{ 2771218822Sdim size_t i; 2772218822Sdim 2773218822Sdim for (i = 0; i < l; i++) 2774218822Sdim d_append_char (dpi, s[i]); 2775218822Sdim} 2776218822Sdim 2777218822Sdimstatic inline void 2778218822Sdimd_append_string (struct d_print_info *dpi, const char *s) 2779218822Sdim{ 2780218822Sdim d_append_buffer (dpi, s, strlen (s)); 2781218822Sdim} 2782218822Sdim 2783218822Sdimstatic inline char 2784218822Sdimd_last_char (struct d_print_info *dpi) 2785218822Sdim{ 2786218822Sdim return dpi->last_char; 2787218822Sdim} 2788218822Sdim 2789130561Sobrien/* Turn components into a human readable string. OPTIONS is the 2790130561Sobrien options bits passed to the demangler. DC is the tree to print. 2791218822Sdim CALLBACK is a function to call to flush demangled string segments 2792218822Sdim as they fill the intermediate buffer, and OPAQUE is a generalized 2793218822Sdim callback argument. On success, this returns 1. On failure, 2794218822Sdim it returns 0, indicating a bad parse. It does not use heap 2795218822Sdim memory to build an output string, so cannot encounter memory 2796218822Sdim allocation failure. */ 2797218822Sdim 2798218822SdimCP_STATIC_IF_GLIBCPP_V3 2799218822Sdimint 2800218822Sdimcplus_demangle_print_callback (int options, 2801218822Sdim const struct demangle_component *dc, 2802218822Sdim demangle_callbackref callback, void *opaque) 2803218822Sdim{ 2804218822Sdim struct d_print_info dpi; 2805218822Sdim 2806218822Sdim d_print_init (&dpi, options, callback, opaque); 2807218822Sdim 2808218822Sdim d_print_comp (&dpi, dc); 2809218822Sdim 2810218822Sdim d_print_flush (&dpi); 2811218822Sdim 2812218822Sdim return ! d_print_saw_error (&dpi); 2813218822Sdim} 2814218822Sdim 2815218822Sdim/* Turn components into a human readable string. OPTIONS is the 2816218822Sdim options bits passed to the demangler. DC is the tree to print. 2817130561Sobrien ESTIMATE is a guess at the length of the result. This returns a 2818130561Sobrien string allocated by malloc, or NULL on error. On success, this 2819130561Sobrien sets *PALC to the size of the allocated buffer. On failure, this 2820130561Sobrien sets *PALC to 0 for a bad parse, or to 1 for a memory allocation 2821130561Sobrien failure. */ 282268765Sobrien 2823130561SobrienCP_STATIC_IF_GLIBCPP_V3 2824130561Sobrienchar * 2825218822Sdimcplus_demangle_print (int options, const struct demangle_component *dc, 2826218822Sdim int estimate, size_t *palc) 282789857Sobrien{ 2828218822Sdim struct d_growable_string dgs; 282989857Sobrien 2830218822Sdim d_growable_string_init (&dgs, estimate); 283168765Sobrien 2832218822Sdim if (! cplus_demangle_print_callback (options, dc, 2833218822Sdim d_growable_string_callback_adapter, 2834218822Sdim &dgs)) 2835130561Sobrien { 2836218822Sdim free (dgs.buf); 2837218822Sdim *palc = 0; 2838130561Sobrien return NULL; 2839130561Sobrien } 284068765Sobrien 2841218822Sdim *palc = dgs.allocation_failure ? 1 : dgs.alc; 2842218822Sdim return dgs.buf; 284368765Sobrien} 284468765Sobrien 2845130561Sobrien/* Subroutine to handle components. */ 284668765Sobrien 2847130561Sobrienstatic void 2848218822Sdimd_print_comp (struct d_print_info *dpi, 2849218822Sdim const struct demangle_component *dc) 285068765Sobrien{ 2851130561Sobrien if (dc == NULL) 2852130561Sobrien { 2853130561Sobrien d_print_error (dpi); 2854130561Sobrien return; 2855130561Sobrien } 2856130561Sobrien if (d_print_saw_error (dpi)) 2857130561Sobrien return; 285868765Sobrien 2859130561Sobrien switch (dc->type) 286068765Sobrien { 2861130561Sobrien case DEMANGLE_COMPONENT_NAME: 2862130561Sobrien if ((dpi->options & DMGL_JAVA) == 0) 2863130561Sobrien d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len); 2864130561Sobrien else 2865130561Sobrien d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); 2866130561Sobrien return; 286768765Sobrien 2868130561Sobrien case DEMANGLE_COMPONENT_QUAL_NAME: 2869130561Sobrien case DEMANGLE_COMPONENT_LOCAL_NAME: 2870130561Sobrien d_print_comp (dpi, d_left (dc)); 2871130561Sobrien if ((dpi->options & DMGL_JAVA) == 0) 2872218822Sdim d_append_string (dpi, "::"); 2873130561Sobrien else 2874130561Sobrien d_append_char (dpi, '.'); 2875130561Sobrien d_print_comp (dpi, d_right (dc)); 2876130561Sobrien return; 287768765Sobrien 2878130561Sobrien case DEMANGLE_COMPONENT_TYPED_NAME: 2879130561Sobrien { 2880130561Sobrien struct d_print_mod *hold_modifiers; 2881130561Sobrien struct demangle_component *typed_name; 2882130561Sobrien struct d_print_mod adpm[4]; 2883130561Sobrien unsigned int i; 2884130561Sobrien struct d_print_template dpt; 288568765Sobrien 2886130561Sobrien /* Pass the name down to the type so that it can be printed in 2887130561Sobrien the right place for the type. We also have to pass down 2888130561Sobrien any CV-qualifiers, which apply to the this parameter. */ 2889130561Sobrien hold_modifiers = dpi->modifiers; 2890130561Sobrien i = 0; 2891130561Sobrien typed_name = d_left (dc); 2892130561Sobrien while (typed_name != NULL) 2893130561Sobrien { 2894130561Sobrien if (i >= sizeof adpm / sizeof adpm[0]) 2895130561Sobrien { 2896130561Sobrien d_print_error (dpi); 2897130561Sobrien return; 2898130561Sobrien } 289968765Sobrien 2900130561Sobrien adpm[i].next = dpi->modifiers; 2901130561Sobrien dpi->modifiers = &adpm[i]; 2902130561Sobrien adpm[i].mod = typed_name; 2903130561Sobrien adpm[i].printed = 0; 2904130561Sobrien adpm[i].templates = dpi->templates; 2905130561Sobrien ++i; 290668765Sobrien 2907130561Sobrien if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS 2908130561Sobrien && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS 2909130561Sobrien && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS) 2910130561Sobrien break; 291168765Sobrien 2912130561Sobrien typed_name = d_left (typed_name); 2913130561Sobrien } 291468765Sobrien 2915130561Sobrien /* If typed_name is a template, then it applies to the 2916130561Sobrien function type as well. */ 2917130561Sobrien if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) 2918130561Sobrien { 2919130561Sobrien dpt.next = dpi->templates; 2920130561Sobrien dpi->templates = &dpt; 2921218822Sdim dpt.template_decl = typed_name; 2922130561Sobrien } 292368765Sobrien 2924130561Sobrien /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then 2925130561Sobrien there may be CV-qualifiers on its right argument which 2926130561Sobrien really apply here; this happens when parsing a class which 2927130561Sobrien is local to a function. */ 2928130561Sobrien if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME) 2929130561Sobrien { 2930130561Sobrien struct demangle_component *local_name; 293168765Sobrien 2932130561Sobrien local_name = d_right (typed_name); 2933130561Sobrien while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS 2934130561Sobrien || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS 2935130561Sobrien || local_name->type == DEMANGLE_COMPONENT_CONST_THIS) 2936130561Sobrien { 2937130561Sobrien if (i >= sizeof adpm / sizeof adpm[0]) 2938130561Sobrien { 2939130561Sobrien d_print_error (dpi); 2940130561Sobrien return; 2941130561Sobrien } 294268765Sobrien 2943130561Sobrien adpm[i] = adpm[i - 1]; 2944130561Sobrien adpm[i].next = &adpm[i - 1]; 2945130561Sobrien dpi->modifiers = &adpm[i]; 294668765Sobrien 2947130561Sobrien adpm[i - 1].mod = local_name; 2948130561Sobrien adpm[i - 1].printed = 0; 2949130561Sobrien adpm[i - 1].templates = dpi->templates; 2950130561Sobrien ++i; 295168765Sobrien 2952130561Sobrien local_name = d_left (local_name); 2953130561Sobrien } 2954130561Sobrien } 295568765Sobrien 2956130561Sobrien d_print_comp (dpi, d_right (dc)); 295768765Sobrien 2958130561Sobrien if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) 2959130561Sobrien dpi->templates = dpt.next; 296068765Sobrien 2961130561Sobrien /* If the modifiers didn't get printed by the type, print them 2962130561Sobrien now. */ 2963130561Sobrien while (i > 0) 2964130561Sobrien { 2965130561Sobrien --i; 2966130561Sobrien if (! adpm[i].printed) 2967130561Sobrien { 2968130561Sobrien d_append_char (dpi, ' '); 2969130561Sobrien d_print_mod (dpi, adpm[i].mod); 2970130561Sobrien } 2971130561Sobrien } 297268765Sobrien 2973130561Sobrien dpi->modifiers = hold_modifiers; 297468765Sobrien 2975130561Sobrien return; 2976130561Sobrien } 297777298Sobrien 2978130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE: 2979130561Sobrien { 2980130561Sobrien struct d_print_mod *hold_dpm; 2981218822Sdim struct demangle_component *dcl; 298268765Sobrien 2983130561Sobrien /* Don't push modifiers into a template definition. Doing so 2984130561Sobrien could give the wrong definition for a template argument. 2985130561Sobrien Instead, treat the template essentially as a name. */ 298668765Sobrien 2987130561Sobrien hold_dpm = dpi->modifiers; 2988130561Sobrien dpi->modifiers = NULL; 298968765Sobrien 2990218822Sdim dcl = d_left (dc); 299168765Sobrien 2992218822Sdim if ((dpi->options & DMGL_JAVA) != 0 2993218822Sdim && dcl->type == DEMANGLE_COMPONENT_NAME 2994218822Sdim && dcl->u.s_name.len == 6 2995218822Sdim && strncmp (dcl->u.s_name.s, "JArray", 6) == 0) 2996218822Sdim { 2997218822Sdim /* Special-case Java arrays, so that JArray<TYPE> appears 2998218822Sdim instead as TYPE[]. */ 2999218822Sdim 3000218822Sdim d_print_comp (dpi, d_right (dc)); 3001218822Sdim d_append_string (dpi, "[]"); 3002218822Sdim } 3003218822Sdim else 3004218822Sdim { 3005218822Sdim d_print_comp (dpi, dcl); 3006218822Sdim if (d_last_char (dpi) == '<') 3007218822Sdim d_append_char (dpi, ' '); 3008218822Sdim d_append_char (dpi, '<'); 3009218822Sdim d_print_comp (dpi, d_right (dc)); 3010218822Sdim /* Avoid generating two consecutive '>' characters, to avoid 3011218822Sdim the C++ syntactic ambiguity. */ 3012218822Sdim if (d_last_char (dpi) == '>') 3013218822Sdim d_append_char (dpi, ' '); 3014218822Sdim d_append_char (dpi, '>'); 3015218822Sdim } 3016218822Sdim 3017130561Sobrien dpi->modifiers = hold_dpm; 301868765Sobrien 3019130561Sobrien return; 3020130561Sobrien } 302168765Sobrien 3022130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE_PARAM: 3023130561Sobrien { 3024130561Sobrien long i; 3025130561Sobrien struct demangle_component *a; 3026130561Sobrien struct d_print_template *hold_dpt; 302768765Sobrien 3028130561Sobrien if (dpi->templates == NULL) 3029130561Sobrien { 3030130561Sobrien d_print_error (dpi); 3031130561Sobrien return; 3032130561Sobrien } 3033130561Sobrien i = dc->u.s_number.number; 3034218822Sdim for (a = d_right (dpi->templates->template_decl); 3035130561Sobrien a != NULL; 3036130561Sobrien a = d_right (a)) 3037130561Sobrien { 3038130561Sobrien if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) 3039130561Sobrien { 3040130561Sobrien d_print_error (dpi); 3041130561Sobrien return; 3042130561Sobrien } 3043130561Sobrien if (i <= 0) 3044130561Sobrien break; 3045130561Sobrien --i; 3046130561Sobrien } 3047130561Sobrien if (i != 0 || a == NULL) 3048130561Sobrien { 3049130561Sobrien d_print_error (dpi); 3050130561Sobrien return; 3051130561Sobrien } 305277298Sobrien 3053130561Sobrien /* While processing this parameter, we need to pop the list of 3054130561Sobrien templates. This is because the template parameter may 3055130561Sobrien itself be a reference to a parameter of an outer 3056130561Sobrien template. */ 305777298Sobrien 3058130561Sobrien hold_dpt = dpi->templates; 3059130561Sobrien dpi->templates = hold_dpt->next; 306068765Sobrien 3061130561Sobrien d_print_comp (dpi, d_left (a)); 306268765Sobrien 3063130561Sobrien dpi->templates = hold_dpt; 306468765Sobrien 3065130561Sobrien return; 3066130561Sobrien } 306768765Sobrien 3068130561Sobrien case DEMANGLE_COMPONENT_CTOR: 3069130561Sobrien d_print_comp (dpi, dc->u.s_ctor.name); 3070130561Sobrien return; 307168765Sobrien 3072130561Sobrien case DEMANGLE_COMPONENT_DTOR: 3073130561Sobrien d_append_char (dpi, '~'); 3074130561Sobrien d_print_comp (dpi, dc->u.s_dtor.name); 3075130561Sobrien return; 307677298Sobrien 3077130561Sobrien case DEMANGLE_COMPONENT_VTABLE: 3078218822Sdim d_append_string (dpi, "vtable for "); 3079130561Sobrien d_print_comp (dpi, d_left (dc)); 3080130561Sobrien return; 308168765Sobrien 3082130561Sobrien case DEMANGLE_COMPONENT_VTT: 3083218822Sdim d_append_string (dpi, "VTT for "); 3084130561Sobrien d_print_comp (dpi, d_left (dc)); 3085130561Sobrien return; 308668765Sobrien 3087130561Sobrien case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: 3088218822Sdim d_append_string (dpi, "construction vtable for "); 3089130561Sobrien d_print_comp (dpi, d_left (dc)); 3090218822Sdim d_append_string (dpi, "-in-"); 3091130561Sobrien d_print_comp (dpi, d_right (dc)); 3092130561Sobrien return; 309368765Sobrien 3094130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO: 3095218822Sdim d_append_string (dpi, "typeinfo for "); 3096130561Sobrien d_print_comp (dpi, d_left (dc)); 3097130561Sobrien return; 309868765Sobrien 3099130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_NAME: 3100218822Sdim d_append_string (dpi, "typeinfo name for "); 3101130561Sobrien d_print_comp (dpi, d_left (dc)); 3102130561Sobrien return; 310368765Sobrien 3104130561Sobrien case DEMANGLE_COMPONENT_TYPEINFO_FN: 3105218822Sdim d_append_string (dpi, "typeinfo fn for "); 3106130561Sobrien d_print_comp (dpi, d_left (dc)); 3107130561Sobrien return; 310868765Sobrien 3109130561Sobrien case DEMANGLE_COMPONENT_THUNK: 3110218822Sdim d_append_string (dpi, "non-virtual thunk to "); 3111130561Sobrien d_print_comp (dpi, d_left (dc)); 3112130561Sobrien return; 311368765Sobrien 3114130561Sobrien case DEMANGLE_COMPONENT_VIRTUAL_THUNK: 3115218822Sdim d_append_string (dpi, "virtual thunk to "); 3116130561Sobrien d_print_comp (dpi, d_left (dc)); 3117130561Sobrien return; 311868765Sobrien 3119130561Sobrien case DEMANGLE_COMPONENT_COVARIANT_THUNK: 3120218822Sdim d_append_string (dpi, "covariant return thunk to "); 3121130561Sobrien d_print_comp (dpi, d_left (dc)); 3122130561Sobrien return; 312368765Sobrien 3124130561Sobrien case DEMANGLE_COMPONENT_JAVA_CLASS: 3125218822Sdim d_append_string (dpi, "java Class for "); 3126130561Sobrien d_print_comp (dpi, d_left (dc)); 3127130561Sobrien return; 312868765Sobrien 3129130561Sobrien case DEMANGLE_COMPONENT_GUARD: 3130218822Sdim d_append_string (dpi, "guard variable for "); 3131130561Sobrien d_print_comp (dpi, d_left (dc)); 3132130561Sobrien return; 313368765Sobrien 3134130561Sobrien case DEMANGLE_COMPONENT_REFTEMP: 3135218822Sdim d_append_string (dpi, "reference temporary for "); 3136130561Sobrien d_print_comp (dpi, d_left (dc)); 3137130561Sobrien return; 313868765Sobrien 3139218822Sdim case DEMANGLE_COMPONENT_HIDDEN_ALIAS: 3140218822Sdim d_append_string (dpi, "hidden alias for "); 3141218822Sdim d_print_comp (dpi, d_left (dc)); 3142218822Sdim return; 3143218822Sdim 3144130561Sobrien case DEMANGLE_COMPONENT_SUB_STD: 3145130561Sobrien d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len); 3146130561Sobrien return; 314768765Sobrien 3148130561Sobrien case DEMANGLE_COMPONENT_RESTRICT: 3149130561Sobrien case DEMANGLE_COMPONENT_VOLATILE: 3150130561Sobrien case DEMANGLE_COMPONENT_CONST: 3151218822Sdim { 3152218822Sdim struct d_print_mod *pdpm; 3153218822Sdim 3154218822Sdim /* When printing arrays, it's possible to have cases where the 3155218822Sdim same CV-qualifier gets pushed on the stack multiple times. 3156218822Sdim We only need to print it once. */ 3157218822Sdim 3158218822Sdim for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next) 3159218822Sdim { 3160218822Sdim if (! pdpm->printed) 3161218822Sdim { 3162218822Sdim if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT 3163218822Sdim && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE 3164218822Sdim && pdpm->mod->type != DEMANGLE_COMPONENT_CONST) 3165218822Sdim break; 3166218822Sdim if (pdpm->mod->type == dc->type) 3167218822Sdim { 3168218822Sdim d_print_comp (dpi, d_left (dc)); 3169218822Sdim return; 3170218822Sdim } 3171218822Sdim } 3172218822Sdim } 3173218822Sdim } 3174218822Sdim /* Fall through. */ 3175130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 3176130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 3177130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 3178130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 3179130561Sobrien case DEMANGLE_COMPONENT_POINTER: 3180130561Sobrien case DEMANGLE_COMPONENT_REFERENCE: 3181130561Sobrien case DEMANGLE_COMPONENT_COMPLEX: 3182130561Sobrien case DEMANGLE_COMPONENT_IMAGINARY: 3183130561Sobrien { 3184130561Sobrien /* We keep a list of modifiers on the stack. */ 3185130561Sobrien struct d_print_mod dpm; 318668765Sobrien 3187130561Sobrien dpm.next = dpi->modifiers; 3188130561Sobrien dpi->modifiers = &dpm; 3189130561Sobrien dpm.mod = dc; 3190130561Sobrien dpm.printed = 0; 3191130561Sobrien dpm.templates = dpi->templates; 319268765Sobrien 3193130561Sobrien d_print_comp (dpi, d_left (dc)); 319468765Sobrien 3195130561Sobrien /* If the modifier didn't get printed by the type, print it 3196130561Sobrien now. */ 3197130561Sobrien if (! dpm.printed) 3198130561Sobrien d_print_mod (dpi, dc); 319968765Sobrien 3200130561Sobrien dpi->modifiers = dpm.next; 320168765Sobrien 3202130561Sobrien return; 3203130561Sobrien } 3204130561Sobrien 3205130561Sobrien case DEMANGLE_COMPONENT_BUILTIN_TYPE: 3206130561Sobrien if ((dpi->options & DMGL_JAVA) == 0) 3207130561Sobrien d_append_buffer (dpi, dc->u.s_builtin.type->name, 3208130561Sobrien dc->u.s_builtin.type->len); 320968765Sobrien else 3210130561Sobrien d_append_buffer (dpi, dc->u.s_builtin.type->java_name, 3211130561Sobrien dc->u.s_builtin.type->java_len); 3212130561Sobrien return; 321368765Sobrien 3214130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE: 3215130561Sobrien d_print_comp (dpi, d_left (dc)); 3216130561Sobrien return; 321768765Sobrien 3218130561Sobrien case DEMANGLE_COMPONENT_FUNCTION_TYPE: 3219130561Sobrien { 3220218822Sdim if ((dpi->options & DMGL_RET_POSTFIX) != 0) 3221218822Sdim d_print_function_type (dpi, dc, dpi->modifiers); 3222218822Sdim 3223218822Sdim /* Print return type if present */ 3224130561Sobrien if (d_left (dc) != NULL) 3225130561Sobrien { 3226130561Sobrien struct d_print_mod dpm; 322768765Sobrien 3228130561Sobrien /* We must pass this type down as a modifier in order to 3229130561Sobrien print it in the right location. */ 3230130561Sobrien dpm.next = dpi->modifiers; 3231130561Sobrien dpi->modifiers = &dpm; 3232130561Sobrien dpm.mod = dc; 3233130561Sobrien dpm.printed = 0; 3234130561Sobrien dpm.templates = dpi->templates; 323568765Sobrien 3236130561Sobrien d_print_comp (dpi, d_left (dc)); 323768765Sobrien 3238130561Sobrien dpi->modifiers = dpm.next; 323968765Sobrien 3240130561Sobrien if (dpm.printed) 3241130561Sobrien return; 324268765Sobrien 3243218822Sdim /* In standard prefix notation, there is a space between the 3244218822Sdim return type and the function signature. */ 3245218822Sdim if ((dpi->options & DMGL_RET_POSTFIX) == 0) 3246218822Sdim d_append_char (dpi, ' '); 3247130561Sobrien } 324868765Sobrien 3249218822Sdim if ((dpi->options & DMGL_RET_POSTFIX) == 0) 3250218822Sdim d_print_function_type (dpi, dc, dpi->modifiers); 325168765Sobrien 3252130561Sobrien return; 3253130561Sobrien } 325468765Sobrien 3255130561Sobrien case DEMANGLE_COMPONENT_ARRAY_TYPE: 3256130561Sobrien { 3257218822Sdim struct d_print_mod *hold_modifiers; 3258218822Sdim struct d_print_mod adpm[4]; 3259218822Sdim unsigned int i; 3260218822Sdim struct d_print_mod *pdpm; 326168765Sobrien 3262130561Sobrien /* We must pass this type down as a modifier in order to print 3263218822Sdim multi-dimensional arrays correctly. If the array itself is 3264218822Sdim CV-qualified, we act as though the element type were 3265218822Sdim CV-qualified. We do this by copying the modifiers down 3266218822Sdim rather than fiddling pointers, so that we don't wind up 3267218822Sdim with a d_print_mod higher on the stack pointing into our 3268218822Sdim stack frame after we return. */ 326968765Sobrien 3270218822Sdim hold_modifiers = dpi->modifiers; 327168765Sobrien 3272218822Sdim adpm[0].next = hold_modifiers; 3273218822Sdim dpi->modifiers = &adpm[0]; 3274218822Sdim adpm[0].mod = dc; 3275218822Sdim adpm[0].printed = 0; 3276218822Sdim adpm[0].templates = dpi->templates; 3277218822Sdim 3278218822Sdim i = 1; 3279218822Sdim pdpm = hold_modifiers; 3280218822Sdim while (pdpm != NULL 3281218822Sdim && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT 3282218822Sdim || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE 3283218822Sdim || pdpm->mod->type == DEMANGLE_COMPONENT_CONST)) 3284218822Sdim { 3285218822Sdim if (! pdpm->printed) 3286218822Sdim { 3287218822Sdim if (i >= sizeof adpm / sizeof adpm[0]) 3288218822Sdim { 3289218822Sdim d_print_error (dpi); 3290218822Sdim return; 3291218822Sdim } 3292218822Sdim 3293218822Sdim adpm[i] = *pdpm; 3294218822Sdim adpm[i].next = dpi->modifiers; 3295218822Sdim dpi->modifiers = &adpm[i]; 3296218822Sdim pdpm->printed = 1; 3297218822Sdim ++i; 3298218822Sdim } 3299218822Sdim 3300218822Sdim pdpm = pdpm->next; 3301218822Sdim } 3302218822Sdim 3303130561Sobrien d_print_comp (dpi, d_right (dc)); 330468765Sobrien 3305218822Sdim dpi->modifiers = hold_modifiers; 3306130561Sobrien 3307218822Sdim if (adpm[0].printed) 3308130561Sobrien return; 3309130561Sobrien 3310218822Sdim while (i > 1) 3311218822Sdim { 3312218822Sdim --i; 3313218822Sdim d_print_mod (dpi, adpm[i].mod); 3314218822Sdim } 3315218822Sdim 3316130561Sobrien d_print_array_type (dpi, dc, dpi->modifiers); 3317130561Sobrien 3318130561Sobrien return; 3319130561Sobrien } 3320130561Sobrien 3321130561Sobrien case DEMANGLE_COMPONENT_PTRMEM_TYPE: 3322130561Sobrien { 3323130561Sobrien struct d_print_mod dpm; 3324130561Sobrien 3325130561Sobrien dpm.next = dpi->modifiers; 3326130561Sobrien dpi->modifiers = &dpm; 3327130561Sobrien dpm.mod = dc; 3328130561Sobrien dpm.printed = 0; 3329130561Sobrien dpm.templates = dpi->templates; 3330130561Sobrien 3331130561Sobrien d_print_comp (dpi, d_right (dc)); 3332130561Sobrien 3333130561Sobrien /* If the modifier didn't get printed by the type, print it 3334130561Sobrien now. */ 3335130561Sobrien if (! dpm.printed) 3336130561Sobrien { 3337130561Sobrien d_append_char (dpi, ' '); 3338130561Sobrien d_print_comp (dpi, d_left (dc)); 3339218822Sdim d_append_string (dpi, "::*"); 3340130561Sobrien } 3341130561Sobrien 3342130561Sobrien dpi->modifiers = dpm.next; 3343130561Sobrien 3344130561Sobrien return; 3345130561Sobrien } 3346130561Sobrien 3347130561Sobrien case DEMANGLE_COMPONENT_ARGLIST: 3348130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: 3349130561Sobrien d_print_comp (dpi, d_left (dc)); 3350130561Sobrien if (d_right (dc) != NULL) 335168765Sobrien { 3352218822Sdim d_append_string (dpi, ", "); 3353130561Sobrien d_print_comp (dpi, d_right (dc)); 335468765Sobrien } 3355130561Sobrien return; 335668765Sobrien 3357130561Sobrien case DEMANGLE_COMPONENT_OPERATOR: 3358130561Sobrien { 3359130561Sobrien char c; 336068765Sobrien 3361218822Sdim d_append_string (dpi, "operator"); 3362130561Sobrien c = dc->u.s_operator.op->name[0]; 3363130561Sobrien if (IS_LOWER (c)) 3364130561Sobrien d_append_char (dpi, ' '); 3365130561Sobrien d_append_buffer (dpi, dc->u.s_operator.op->name, 3366130561Sobrien dc->u.s_operator.op->len); 3367130561Sobrien return; 3368130561Sobrien } 336968765Sobrien 3370130561Sobrien case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: 3371218822Sdim d_append_string (dpi, "operator "); 3372130561Sobrien d_print_comp (dpi, dc->u.s_extended_operator.name); 3373130561Sobrien return; 3374130561Sobrien 3375130561Sobrien case DEMANGLE_COMPONENT_CAST: 3376218822Sdim d_append_string (dpi, "operator "); 3377130561Sobrien d_print_cast (dpi, dc); 3378130561Sobrien return; 3379130561Sobrien 3380130561Sobrien case DEMANGLE_COMPONENT_UNARY: 3381130561Sobrien if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST) 3382130561Sobrien d_print_expr_op (dpi, d_left (dc)); 3383130561Sobrien else 3384130561Sobrien { 3385218822Sdim d_append_char (dpi, '('); 3386130561Sobrien d_print_cast (dpi, d_left (dc)); 3387130561Sobrien d_append_char (dpi, ')'); 338868765Sobrien } 3389130561Sobrien d_append_char (dpi, '('); 3390130561Sobrien d_print_comp (dpi, d_right (dc)); 3391130561Sobrien d_append_char (dpi, ')'); 3392130561Sobrien return; 339368765Sobrien 3394130561Sobrien case DEMANGLE_COMPONENT_BINARY: 3395130561Sobrien if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS) 3396130561Sobrien { 3397130561Sobrien d_print_error (dpi); 3398130561Sobrien return; 3399130561Sobrien } 340068765Sobrien 3401130561Sobrien /* We wrap an expression which uses the greater-than operator in 3402130561Sobrien an extra layer of parens so that it does not get confused 3403130561Sobrien with the '>' which ends the template parameters. */ 3404130561Sobrien if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR 3405130561Sobrien && d_left (dc)->u.s_operator.op->len == 1 3406130561Sobrien && d_left (dc)->u.s_operator.op->name[0] == '>') 3407130561Sobrien d_append_char (dpi, '('); 340868765Sobrien 3409130561Sobrien d_append_char (dpi, '('); 3410130561Sobrien d_print_comp (dpi, d_left (d_right (dc))); 3411218822Sdim d_append_string (dpi, ") "); 3412130561Sobrien d_print_expr_op (dpi, d_left (dc)); 3413218822Sdim d_append_string (dpi, " ("); 3414130561Sobrien d_print_comp (dpi, d_right (d_right (dc))); 3415130561Sobrien d_append_char (dpi, ')'); 341668765Sobrien 3417130561Sobrien if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR 3418130561Sobrien && d_left (dc)->u.s_operator.op->len == 1 3419130561Sobrien && d_left (dc)->u.s_operator.op->name[0] == '>') 3420130561Sobrien d_append_char (dpi, ')'); 342168765Sobrien 3422130561Sobrien return; 342368765Sobrien 3424130561Sobrien case DEMANGLE_COMPONENT_BINARY_ARGS: 3425130561Sobrien /* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */ 3426130561Sobrien d_print_error (dpi); 3427130561Sobrien return; 342868765Sobrien 3429130561Sobrien case DEMANGLE_COMPONENT_TRINARY: 3430130561Sobrien if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1 3431130561Sobrien || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2) 3432130561Sobrien { 3433130561Sobrien d_print_error (dpi); 3434130561Sobrien return; 3435130561Sobrien } 3436130561Sobrien d_append_char (dpi, '('); 3437130561Sobrien d_print_comp (dpi, d_left (d_right (dc))); 3438218822Sdim d_append_string (dpi, ") "); 3439130561Sobrien d_print_expr_op (dpi, d_left (dc)); 3440218822Sdim d_append_string (dpi, " ("); 3441130561Sobrien d_print_comp (dpi, d_left (d_right (d_right (dc)))); 3442218822Sdim d_append_string (dpi, ") : ("); 3443130561Sobrien d_print_comp (dpi, d_right (d_right (d_right (dc)))); 3444130561Sobrien d_append_char (dpi, ')'); 3445130561Sobrien return; 344668765Sobrien 3447130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG1: 3448130561Sobrien case DEMANGLE_COMPONENT_TRINARY_ARG2: 3449130561Sobrien /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY. */ 3450130561Sobrien d_print_error (dpi); 3451130561Sobrien return; 345268765Sobrien 3453130561Sobrien case DEMANGLE_COMPONENT_LITERAL: 3454130561Sobrien case DEMANGLE_COMPONENT_LITERAL_NEG: 3455218822Sdim { 3456218822Sdim enum d_builtin_type_print tp; 3457130561Sobrien 3458218822Sdim /* For some builtin types, produce simpler output. */ 3459218822Sdim tp = D_PRINT_DEFAULT; 3460218822Sdim if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE) 3461218822Sdim { 3462218822Sdim tp = d_left (dc)->u.s_builtin.type->print; 3463218822Sdim switch (tp) 3464218822Sdim { 3465218822Sdim case D_PRINT_INT: 3466218822Sdim case D_PRINT_UNSIGNED: 3467218822Sdim case D_PRINT_LONG: 3468218822Sdim case D_PRINT_UNSIGNED_LONG: 3469218822Sdim case D_PRINT_LONG_LONG: 3470218822Sdim case D_PRINT_UNSIGNED_LONG_LONG: 3471218822Sdim if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME) 3472218822Sdim { 3473218822Sdim if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) 3474218822Sdim d_append_char (dpi, '-'); 3475218822Sdim d_print_comp (dpi, d_right (dc)); 3476218822Sdim switch (tp) 3477218822Sdim { 3478218822Sdim default: 3479218822Sdim break; 3480218822Sdim case D_PRINT_UNSIGNED: 3481218822Sdim d_append_char (dpi, 'u'); 3482218822Sdim break; 3483218822Sdim case D_PRINT_LONG: 3484218822Sdim d_append_char (dpi, 'l'); 3485218822Sdim break; 3486218822Sdim case D_PRINT_UNSIGNED_LONG: 3487218822Sdim d_append_string (dpi, "ul"); 3488218822Sdim break; 3489218822Sdim case D_PRINT_LONG_LONG: 3490218822Sdim d_append_string (dpi, "ll"); 3491218822Sdim break; 3492218822Sdim case D_PRINT_UNSIGNED_LONG_LONG: 3493218822Sdim d_append_string (dpi, "ull"); 3494218822Sdim break; 3495218822Sdim } 3496218822Sdim return; 3497218822Sdim } 3498218822Sdim break; 3499130561Sobrien 3500218822Sdim case D_PRINT_BOOL: 3501218822Sdim if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME 3502218822Sdim && d_right (dc)->u.s_name.len == 1 3503218822Sdim && dc->type == DEMANGLE_COMPONENT_LITERAL) 3504218822Sdim { 3505218822Sdim switch (d_right (dc)->u.s_name.s[0]) 3506218822Sdim { 3507218822Sdim case '0': 3508218822Sdim d_append_string (dpi, "false"); 3509218822Sdim return; 3510218822Sdim case '1': 3511218822Sdim d_append_string (dpi, "true"); 3512218822Sdim return; 3513218822Sdim default: 3514218822Sdim break; 3515218822Sdim } 3516218822Sdim } 3517218822Sdim break; 3518130561Sobrien 3519218822Sdim default: 3520218822Sdim break; 3521218822Sdim } 3522218822Sdim } 352368765Sobrien 3524218822Sdim d_append_char (dpi, '('); 3525218822Sdim d_print_comp (dpi, d_left (dc)); 3526218822Sdim d_append_char (dpi, ')'); 3527218822Sdim if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) 3528218822Sdim d_append_char (dpi, '-'); 3529218822Sdim if (tp == D_PRINT_FLOAT) 3530218822Sdim d_append_char (dpi, '['); 3531218822Sdim d_print_comp (dpi, d_right (dc)); 3532218822Sdim if (tp == D_PRINT_FLOAT) 3533218822Sdim d_append_char (dpi, ']'); 3534218822Sdim } 3535130561Sobrien return; 353668765Sobrien 353768765Sobrien default: 3538130561Sobrien d_print_error (dpi); 3539130561Sobrien return; 354068765Sobrien } 354168765Sobrien} 354268765Sobrien 3543130561Sobrien/* Print a Java dentifier. For Java we try to handle encoded extended 3544130561Sobrien Unicode characters. The C++ ABI doesn't mention Unicode encoding, 3545130561Sobrien so we don't it for C++. Characters are encoded as 3546130561Sobrien __U<hex-char>+_. */ 354768765Sobrien 3548130561Sobrienstatic void 3549218822Sdimd_print_java_identifier (struct d_print_info *dpi, const char *name, int len) 355068765Sobrien{ 3551130561Sobrien const char *p; 3552130561Sobrien const char *end; 355368765Sobrien 3554130561Sobrien end = name + len; 3555130561Sobrien for (p = name; p < end; ++p) 355668765Sobrien { 3557130561Sobrien if (end - p > 3 3558130561Sobrien && p[0] == '_' 3559130561Sobrien && p[1] == '_' 3560130561Sobrien && p[2] == 'U') 3561130561Sobrien { 3562130561Sobrien unsigned long c; 3563130561Sobrien const char *q; 356468765Sobrien 3565130561Sobrien c = 0; 3566130561Sobrien for (q = p + 3; q < end; ++q) 3567130561Sobrien { 3568130561Sobrien int dig; 356968765Sobrien 3570130561Sobrien if (IS_DIGIT (*q)) 3571130561Sobrien dig = *q - '0'; 3572130561Sobrien else if (*q >= 'A' && *q <= 'F') 3573130561Sobrien dig = *q - 'A' + 10; 3574130561Sobrien else if (*q >= 'a' && *q <= 'f') 3575130561Sobrien dig = *q - 'a' + 10; 3576130561Sobrien else 3577130561Sobrien break; 3578130561Sobrien 3579130561Sobrien c = c * 16 + dig; 3580130561Sobrien } 3581130561Sobrien /* If the Unicode character is larger than 256, we don't try 3582130561Sobrien to deal with it here. FIXME. */ 3583130561Sobrien if (q < end && *q == '_' && c < 256) 3584130561Sobrien { 3585130561Sobrien d_append_char (dpi, c); 3586130561Sobrien p = q; 3587130561Sobrien continue; 3588130561Sobrien } 358968765Sobrien } 359068765Sobrien 3591130561Sobrien d_append_char (dpi, *p); 359268765Sobrien } 359368765Sobrien} 359468765Sobrien 3595130561Sobrien/* Print a list of modifiers. SUFFIX is 1 if we are printing 3596130561Sobrien qualifiers on this after printing a function. */ 359768765Sobrien 3598130561Sobrienstatic void 3599218822Sdimd_print_mod_list (struct d_print_info *dpi, 3600218822Sdim struct d_print_mod *mods, int suffix) 360168765Sobrien{ 3602130561Sobrien struct d_print_template *hold_dpt; 360368765Sobrien 3604130561Sobrien if (mods == NULL || d_print_saw_error (dpi)) 3605130561Sobrien return; 360668765Sobrien 3607130561Sobrien if (mods->printed 3608130561Sobrien || (! suffix 3609130561Sobrien && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS 3610130561Sobrien || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS 3611130561Sobrien || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS))) 3612130561Sobrien { 3613130561Sobrien d_print_mod_list (dpi, mods->next, suffix); 3614130561Sobrien return; 3615130561Sobrien } 361668765Sobrien 3617130561Sobrien mods->printed = 1; 361868765Sobrien 3619130561Sobrien hold_dpt = dpi->templates; 3620130561Sobrien dpi->templates = mods->templates; 362168765Sobrien 3622130561Sobrien if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) 362368765Sobrien { 3624130561Sobrien d_print_function_type (dpi, mods->mod, mods->next); 3625130561Sobrien dpi->templates = hold_dpt; 3626130561Sobrien return; 3627130561Sobrien } 3628130561Sobrien else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) 3629130561Sobrien { 3630130561Sobrien d_print_array_type (dpi, mods->mod, mods->next); 3631130561Sobrien dpi->templates = hold_dpt; 3632130561Sobrien return; 3633130561Sobrien } 3634130561Sobrien else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME) 3635130561Sobrien { 3636130561Sobrien struct d_print_mod *hold_modifiers; 3637130561Sobrien struct demangle_component *dc; 363868765Sobrien 3639130561Sobrien /* When this is on the modifier stack, we have pulled any 3640130561Sobrien qualifiers off the right argument already. Otherwise, we 3641130561Sobrien print it as usual, but don't let the left argument see any 3642130561Sobrien modifiers. */ 3643130561Sobrien 3644130561Sobrien hold_modifiers = dpi->modifiers; 3645130561Sobrien dpi->modifiers = NULL; 3646130561Sobrien d_print_comp (dpi, d_left (mods->mod)); 3647130561Sobrien dpi->modifiers = hold_modifiers; 3648130561Sobrien 3649130561Sobrien if ((dpi->options & DMGL_JAVA) == 0) 3650218822Sdim d_append_string (dpi, "::"); 365168765Sobrien else 3652130561Sobrien d_append_char (dpi, '.'); 365368765Sobrien 3654130561Sobrien dc = d_right (mods->mod); 3655130561Sobrien while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS 3656130561Sobrien || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS 3657130561Sobrien || dc->type == DEMANGLE_COMPONENT_CONST_THIS) 3658130561Sobrien dc = d_left (dc); 3659130561Sobrien 3660130561Sobrien d_print_comp (dpi, dc); 3661130561Sobrien 3662130561Sobrien dpi->templates = hold_dpt; 3663130561Sobrien return; 366468765Sobrien } 366568765Sobrien 3666130561Sobrien d_print_mod (dpi, mods->mod); 366768765Sobrien 3668130561Sobrien dpi->templates = hold_dpt; 366968765Sobrien 3670130561Sobrien d_print_mod_list (dpi, mods->next, suffix); 3671130561Sobrien} 367268765Sobrien 3673130561Sobrien/* Print a modifier. */ 367468765Sobrien 3675130561Sobrienstatic void 3676218822Sdimd_print_mod (struct d_print_info *dpi, 3677218822Sdim const struct demangle_component *mod) 367868765Sobrien{ 3679130561Sobrien switch (mod->type) 3680130561Sobrien { 3681130561Sobrien case DEMANGLE_COMPONENT_RESTRICT: 3682130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 3683218822Sdim d_append_string (dpi, " restrict"); 3684130561Sobrien return; 3685130561Sobrien case DEMANGLE_COMPONENT_VOLATILE: 3686130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 3687218822Sdim d_append_string (dpi, " volatile"); 3688130561Sobrien return; 3689130561Sobrien case DEMANGLE_COMPONENT_CONST: 3690130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 3691218822Sdim d_append_string (dpi, " const"); 3692130561Sobrien return; 3693130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 3694130561Sobrien d_append_char (dpi, ' '); 3695130561Sobrien d_print_comp (dpi, d_right (mod)); 3696130561Sobrien return; 3697130561Sobrien case DEMANGLE_COMPONENT_POINTER: 3698130561Sobrien /* There is no pointer symbol in Java. */ 3699130561Sobrien if ((dpi->options & DMGL_JAVA) == 0) 3700130561Sobrien d_append_char (dpi, '*'); 3701130561Sobrien return; 3702130561Sobrien case DEMANGLE_COMPONENT_REFERENCE: 3703130561Sobrien d_append_char (dpi, '&'); 3704130561Sobrien return; 3705130561Sobrien case DEMANGLE_COMPONENT_COMPLEX: 3706218822Sdim d_append_string (dpi, "complex "); 3707130561Sobrien return; 3708130561Sobrien case DEMANGLE_COMPONENT_IMAGINARY: 3709218822Sdim d_append_string (dpi, "imaginary "); 3710130561Sobrien return; 3711130561Sobrien case DEMANGLE_COMPONENT_PTRMEM_TYPE: 3712130561Sobrien if (d_last_char (dpi) != '(') 3713130561Sobrien d_append_char (dpi, ' '); 3714130561Sobrien d_print_comp (dpi, d_left (mod)); 3715218822Sdim d_append_string (dpi, "::*"); 3716130561Sobrien return; 3717130561Sobrien case DEMANGLE_COMPONENT_TYPED_NAME: 3718130561Sobrien d_print_comp (dpi, d_left (mod)); 3719130561Sobrien return; 3720130561Sobrien default: 3721130561Sobrien /* Otherwise, we have something that won't go back on the 3722130561Sobrien modifier stack, so we can just print it. */ 3723130561Sobrien d_print_comp (dpi, mod); 3724130561Sobrien return; 3725130561Sobrien } 3726130561Sobrien} 372768765Sobrien 3728130561Sobrien/* Print a function type, except for the return type. */ 372968765Sobrien 3730130561Sobrienstatic void 3731218822Sdimd_print_function_type (struct d_print_info *dpi, 3732218822Sdim const struct demangle_component *dc, 3733218822Sdim struct d_print_mod *mods) 3734130561Sobrien{ 3735130561Sobrien int need_paren; 3736130561Sobrien int saw_mod; 3737218822Sdim int need_space; 3738130561Sobrien struct d_print_mod *p; 3739130561Sobrien struct d_print_mod *hold_modifiers; 374068765Sobrien 3741130561Sobrien need_paren = 0; 3742130561Sobrien saw_mod = 0; 3743218822Sdim need_space = 0; 3744130561Sobrien for (p = mods; p != NULL; p = p->next) 374568765Sobrien { 3746130561Sobrien if (p->printed) 3747130561Sobrien break; 374868765Sobrien 3749130561Sobrien saw_mod = 1; 3750130561Sobrien switch (p->mod->type) 375168765Sobrien { 3752218822Sdim case DEMANGLE_COMPONENT_POINTER: 3753218822Sdim case DEMANGLE_COMPONENT_REFERENCE: 3754218822Sdim need_paren = 1; 3755218822Sdim break; 3756130561Sobrien case DEMANGLE_COMPONENT_RESTRICT: 3757130561Sobrien case DEMANGLE_COMPONENT_VOLATILE: 3758130561Sobrien case DEMANGLE_COMPONENT_CONST: 3759130561Sobrien case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: 3760130561Sobrien case DEMANGLE_COMPONENT_COMPLEX: 3761130561Sobrien case DEMANGLE_COMPONENT_IMAGINARY: 3762130561Sobrien case DEMANGLE_COMPONENT_PTRMEM_TYPE: 3763218822Sdim need_space = 1; 3764130561Sobrien need_paren = 1; 376568765Sobrien break; 3766130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 3767130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 3768130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 376968765Sobrien break; 3770130561Sobrien default: 377168765Sobrien break; 3772130561Sobrien } 3773130561Sobrien if (need_paren) 3774130561Sobrien break; 3775130561Sobrien } 377668765Sobrien 3777130561Sobrien if (d_left (dc) != NULL && ! saw_mod) 3778130561Sobrien need_paren = 1; 3779130561Sobrien 3780130561Sobrien if (need_paren) 3781130561Sobrien { 3782218822Sdim if (! need_space) 3783130561Sobrien { 3784218822Sdim if (d_last_char (dpi) != '(' 3785218822Sdim && d_last_char (dpi) != '*') 3786218822Sdim need_space = 1; 3787130561Sobrien } 3788218822Sdim if (need_space && d_last_char (dpi) != ' ') 3789218822Sdim d_append_char (dpi, ' '); 3790130561Sobrien d_append_char (dpi, '('); 3791130561Sobrien } 3792130561Sobrien 3793130561Sobrien hold_modifiers = dpi->modifiers; 3794130561Sobrien dpi->modifiers = NULL; 3795130561Sobrien 3796130561Sobrien d_print_mod_list (dpi, mods, 0); 3797130561Sobrien 3798130561Sobrien if (need_paren) 3799130561Sobrien d_append_char (dpi, ')'); 3800130561Sobrien 3801130561Sobrien d_append_char (dpi, '('); 3802130561Sobrien 3803130561Sobrien if (d_right (dc) != NULL) 3804130561Sobrien d_print_comp (dpi, d_right (dc)); 3805130561Sobrien 3806130561Sobrien d_append_char (dpi, ')'); 3807130561Sobrien 3808130561Sobrien d_print_mod_list (dpi, mods, 1); 3809130561Sobrien 3810130561Sobrien dpi->modifiers = hold_modifiers; 3811130561Sobrien} 3812130561Sobrien 3813130561Sobrien/* Print an array type, except for the element type. */ 3814130561Sobrien 3815130561Sobrienstatic void 3816218822Sdimd_print_array_type (struct d_print_info *dpi, 3817218822Sdim const struct demangle_component *dc, 3818218822Sdim struct d_print_mod *mods) 3819130561Sobrien{ 3820130561Sobrien int need_space; 3821130561Sobrien 3822130561Sobrien need_space = 1; 3823130561Sobrien if (mods != NULL) 3824130561Sobrien { 3825130561Sobrien int need_paren; 3826130561Sobrien struct d_print_mod *p; 3827130561Sobrien 3828130561Sobrien need_paren = 0; 3829130561Sobrien for (p = mods; p != NULL; p = p->next) 3830130561Sobrien { 3831218822Sdim if (! p->printed) 383268765Sobrien { 3833218822Sdim if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) 3834218822Sdim { 3835218822Sdim need_space = 0; 3836218822Sdim break; 3837218822Sdim } 3838218822Sdim else 3839218822Sdim { 3840218822Sdim need_paren = 1; 3841218822Sdim need_space = 1; 3842218822Sdim break; 3843218822Sdim } 384468765Sobrien } 384568765Sobrien } 384668765Sobrien 3847130561Sobrien if (need_paren) 3848218822Sdim d_append_string (dpi, " ("); 384968765Sobrien 3850130561Sobrien d_print_mod_list (dpi, mods, 0); 3851130561Sobrien 3852130561Sobrien if (need_paren) 3853130561Sobrien d_append_char (dpi, ')'); 385468765Sobrien } 385568765Sobrien 3856130561Sobrien if (need_space) 3857130561Sobrien d_append_char (dpi, ' '); 385868765Sobrien 3859130561Sobrien d_append_char (dpi, '['); 386068765Sobrien 3861130561Sobrien if (d_left (dc) != NULL) 3862130561Sobrien d_print_comp (dpi, d_left (dc)); 3863130561Sobrien 3864130561Sobrien d_append_char (dpi, ']'); 386568765Sobrien} 386668765Sobrien 3867130561Sobrien/* Print an operator in an expression. */ 386868765Sobrien 3869130561Sobrienstatic void 3870218822Sdimd_print_expr_op (struct d_print_info *dpi, 3871218822Sdim const struct demangle_component *dc) 387268765Sobrien{ 3873130561Sobrien if (dc->type == DEMANGLE_COMPONENT_OPERATOR) 3874130561Sobrien d_append_buffer (dpi, dc->u.s_operator.op->name, 3875130561Sobrien dc->u.s_operator.op->len); 3876130561Sobrien else 3877130561Sobrien d_print_comp (dpi, dc); 3878130561Sobrien} 387968765Sobrien 3880130561Sobrien/* Print a cast. */ 388168765Sobrien 3882130561Sobrienstatic void 3883218822Sdimd_print_cast (struct d_print_info *dpi, 3884218822Sdim const struct demangle_component *dc) 3885130561Sobrien{ 3886130561Sobrien if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) 3887130561Sobrien d_print_comp (dpi, d_left (dc)); 388868765Sobrien else 388968765Sobrien { 3890130561Sobrien struct d_print_mod *hold_dpm; 3891130561Sobrien struct d_print_template dpt; 389268765Sobrien 3893130561Sobrien /* It appears that for a templated cast operator, we need to put 3894130561Sobrien the template parameters in scope for the operator name, but 3895130561Sobrien not for the parameters. The effect is that we need to handle 3896130561Sobrien the template printing here. */ 389768765Sobrien 3898130561Sobrien hold_dpm = dpi->modifiers; 3899130561Sobrien dpi->modifiers = NULL; 390068765Sobrien 3901130561Sobrien dpt.next = dpi->templates; 3902130561Sobrien dpi->templates = &dpt; 3903218822Sdim dpt.template_decl = d_left (dc); 390468765Sobrien 3905130561Sobrien d_print_comp (dpi, d_left (d_left (dc))); 390668765Sobrien 3907130561Sobrien dpi->templates = dpt.next; 3908130561Sobrien 3909130561Sobrien if (d_last_char (dpi) == '<') 3910130561Sobrien d_append_char (dpi, ' '); 3911130561Sobrien d_append_char (dpi, '<'); 3912130561Sobrien d_print_comp (dpi, d_right (d_left (dc))); 3913130561Sobrien /* Avoid generating two consecutive '>' characters, to avoid 3914130561Sobrien the C++ syntactic ambiguity. */ 3915130561Sobrien if (d_last_char (dpi) == '>') 3916130561Sobrien d_append_char (dpi, ' '); 3917130561Sobrien d_append_char (dpi, '>'); 3918130561Sobrien 3919130561Sobrien dpi->modifiers = hold_dpm; 392068765Sobrien } 3921130561Sobrien} 392268765Sobrien 3923130561Sobrien/* Initialize the information structure we use to pass around 3924130561Sobrien information. */ 3925130561Sobrien 3926130561SobrienCP_STATIC_IF_GLIBCPP_V3 3927130561Sobrienvoid 3928218822Sdimcplus_demangle_init_info (const char *mangled, int options, size_t len, 3929218822Sdim struct d_info *di) 3930130561Sobrien{ 3931130561Sobrien di->s = mangled; 3932130561Sobrien di->send = mangled + len; 3933130561Sobrien di->options = options; 3934130561Sobrien 3935130561Sobrien di->n = mangled; 3936130561Sobrien 3937130561Sobrien /* We can not need more components than twice the number of chars in 3938130561Sobrien the mangled string. Most components correspond directly to 3939130561Sobrien chars, but the ARGLIST types are exceptions. */ 3940130561Sobrien di->num_comps = 2 * len; 3941130561Sobrien di->next_comp = 0; 3942130561Sobrien 3943130561Sobrien /* Similarly, we can not need more substitutions than there are 3944130561Sobrien chars in the mangled string. */ 3945130561Sobrien di->num_subs = len; 3946130561Sobrien di->next_sub = 0; 3947130561Sobrien di->did_subs = 0; 3948130561Sobrien 3949130561Sobrien di->last_name = NULL; 3950130561Sobrien 3951130561Sobrien di->expansion = 0; 395268765Sobrien} 395368765Sobrien 3954218822Sdim/* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI 3955218822Sdim mangled name, return strings in repeated callback giving the demangled 3956218822Sdim name. OPTIONS is the usual libiberty demangler options. On success, 3957218822Sdim this returns 1. On failure, returns 0. */ 395868765Sobrien 3959218822Sdimstatic int 3960218822Sdimd_demangle_callback (const char *mangled, int options, 3961218822Sdim demangle_callbackref callback, void *opaque) 396268765Sobrien{ 3963130561Sobrien int type; 3964130561Sobrien struct d_info di; 3965130561Sobrien struct demangle_component *dc; 3966218822Sdim int status; 396768765Sobrien 3968130561Sobrien if (mangled[0] == '_' && mangled[1] == 'Z') 3969130561Sobrien type = 0; 3970130561Sobrien else if (strncmp (mangled, "_GLOBAL_", 8) == 0 3971130561Sobrien && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') 3972130561Sobrien && (mangled[9] == 'D' || mangled[9] == 'I') 3973130561Sobrien && mangled[10] == '_') 397468765Sobrien { 3975218822Sdim const char *intro; 397668765Sobrien 3977218822Sdim intro = (mangled[9] == 'I') 3978218822Sdim ? "global constructors keyed to " 3979218822Sdim : "global destructors keyed to "; 3980218822Sdim 3981218822Sdim callback (intro, strlen (intro), opaque); 3982218822Sdim callback (mangled + 11, strlen (mangled + 11), opaque); 3983218822Sdim return 1; 398468765Sobrien } 398568765Sobrien else 398668765Sobrien { 3987130561Sobrien if ((options & DMGL_TYPES) == 0) 3988218822Sdim return 0; 3989130561Sobrien type = 1; 399068765Sobrien } 399168765Sobrien 3992218822Sdim cplus_demangle_init_info (mangled, options, strlen (mangled), &di); 399368765Sobrien 3994130561Sobrien { 3995130561Sobrien#ifdef CP_DYNAMIC_ARRAYS 3996130561Sobrien __extension__ struct demangle_component comps[di.num_comps]; 3997130561Sobrien __extension__ struct demangle_component *subs[di.num_subs]; 399868765Sobrien 3999218822Sdim di.comps = comps; 4000218822Sdim di.subs = subs; 4001130561Sobrien#else 4002218822Sdim di.comps = alloca (di.num_comps * sizeof (*di.comps)); 4003218822Sdim di.subs = alloca (di.num_subs * sizeof (*di.subs)); 4004130561Sobrien#endif 400568765Sobrien 4006218822Sdim if (type) 4007218822Sdim dc = cplus_demangle_type (&di); 4008218822Sdim else 4009130561Sobrien dc = cplus_demangle_mangled_name (&di, 1); 401068765Sobrien 4011130561Sobrien /* If DMGL_PARAMS is set, then if we didn't consume the entire 4012130561Sobrien mangled string, then we didn't successfully demangle it. If 4013130561Sobrien DMGL_PARAMS is not set, we didn't look at the trailing 4014130561Sobrien parameters. */ 4015130561Sobrien if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') 4016130561Sobrien dc = NULL; 401768765Sobrien 4018130561Sobrien#ifdef CP_DEMANGLE_DEBUG 4019218822Sdim d_dump (dc, 0); 4020130561Sobrien#endif 402168765Sobrien 4022218822Sdim status = (dc != NULL) 4023218822Sdim ? cplus_demangle_print_callback (options, dc, callback, opaque) 4024218822Sdim : 0; 4025218822Sdim } 402668765Sobrien 4027218822Sdim return status; 4028218822Sdim} 4029130561Sobrien 4030218822Sdim/* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled 4031218822Sdim name, return a buffer allocated with malloc holding the demangled 4032218822Sdim name. OPTIONS is the usual libiberty demangler options. On 4033218822Sdim success, this sets *PALC to the allocated size of the returned 4034218822Sdim buffer. On failure, this sets *PALC to 0 for a bad name, or 1 for 4035218822Sdim a memory allocation failure, and returns NULL. */ 4036130561Sobrien 4037218822Sdimstatic char * 4038218822Sdimd_demangle (const char *mangled, int options, size_t *palc) 4039218822Sdim{ 4040218822Sdim struct d_growable_string dgs; 4041218822Sdim int status; 4042130561Sobrien 4043218822Sdim d_growable_string_init (&dgs, 0); 4044130561Sobrien 4045218822Sdim status = d_demangle_callback (mangled, options, 4046218822Sdim d_growable_string_callback_adapter, &dgs); 4047218822Sdim if (status == 0) 4048218822Sdim { 4049218822Sdim free (dgs.buf); 4050218822Sdim *palc = 0; 4051218822Sdim return NULL; 4052218822Sdim } 4053218822Sdim 4054218822Sdim *palc = dgs.allocation_failure ? 1 : 0; 4055218822Sdim return dgs.buf; 405668765Sobrien} 405768765Sobrien 4058104834Sobrien#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3) 4059130561Sobrien 4060218822Sdimextern char *__cxa_demangle (const char *, char *, size_t *, int *); 406168765Sobrien 4062130561Sobrien/* ia64 ABI-mandated entry point in the C++ runtime library for 4063130561Sobrien performing demangling. MANGLED_NAME is a NUL-terminated character 4064130561Sobrien string containing the name to be demangled. 406568765Sobrien 406668765Sobrien OUTPUT_BUFFER is a region of memory, allocated with malloc, of 406768765Sobrien *LENGTH bytes, into which the demangled name is stored. If 406868765Sobrien OUTPUT_BUFFER is not long enough, it is expanded using realloc. 406968765Sobrien OUTPUT_BUFFER may instead be NULL; in that case, the demangled name 4070130561Sobrien is placed in a region of memory allocated with malloc. 407168765Sobrien 4072218822Sdim If LENGTH is non-NULL, the length of the buffer containing the 4073130561Sobrien demangled name, is placed in *LENGTH. 407468765Sobrien 407568765Sobrien The return value is a pointer to the start of the NUL-terminated 407668765Sobrien demangled name, or NULL if the demangling fails. The caller is 4077130561Sobrien responsible for deallocating this memory using free. 407868765Sobrien 407968765Sobrien *STATUS is set to one of the following values: 408068765Sobrien 0: The demangling operation succeeded. 4081130561Sobrien -1: A memory allocation failure occurred. 408268765Sobrien -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules. 408368765Sobrien -3: One of the arguments is invalid. 408468765Sobrien 4085130561Sobrien The demangling is performed using the C++ ABI mangling rules, with 408668765Sobrien GNU extensions. */ 408768765Sobrien 408868765Sobrienchar * 4089218822Sdim__cxa_demangle (const char *mangled_name, char *output_buffer, 4090218822Sdim size_t *length, int *status) 409168765Sobrien{ 4092130561Sobrien char *demangled; 4093130561Sobrien size_t alc; 409468765Sobrien 4095130561Sobrien if (mangled_name == NULL) 4096130561Sobrien { 4097218822Sdim if (status != NULL) 4098218822Sdim *status = -3; 4099130561Sobrien return NULL; 4100130561Sobrien } 410168765Sobrien 4102130561Sobrien if (output_buffer != NULL && length == NULL) 4103130561Sobrien { 4104218822Sdim if (status != NULL) 4105218822Sdim *status = -3; 410668765Sobrien return NULL; 410768765Sobrien } 410868765Sobrien 4109218822Sdim demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc); 411068765Sobrien 4111130561Sobrien if (demangled == NULL) 411268765Sobrien { 4113218822Sdim if (status != NULL) 4114218822Sdim { 4115218822Sdim if (alc == 1) 4116218822Sdim *status = -1; 4117218822Sdim else 4118218822Sdim *status = -2; 4119218822Sdim } 4120130561Sobrien return NULL; 412168765Sobrien } 4122130561Sobrien 4123130561Sobrien if (output_buffer == NULL) 412468765Sobrien { 4125130561Sobrien if (length != NULL) 4126130561Sobrien *length = alc; 412768765Sobrien } 412868765Sobrien else 412968765Sobrien { 4130130561Sobrien if (strlen (demangled) < *length) 4131130561Sobrien { 4132130561Sobrien strcpy (output_buffer, demangled); 4133130561Sobrien free (demangled); 4134130561Sobrien demangled = output_buffer; 4135130561Sobrien } 4136130561Sobrien else 4137130561Sobrien { 4138130561Sobrien free (output_buffer); 4139130561Sobrien *length = alc; 4140130561Sobrien } 414168765Sobrien } 4142130561Sobrien 4143218822Sdim if (status != NULL) 4144218822Sdim *status = 0; 4145130561Sobrien 4146130561Sobrien return demangled; 414768765Sobrien} 414868765Sobrien 4149218822Sdimextern int __gcclibcxx_demangle_callback (const char *, 4150218822Sdim void (*) 4151218822Sdim (const char *, size_t, void *), 4152218822Sdim void *); 4153218822Sdim 4154218822Sdim/* Alternative, allocationless entry point in the C++ runtime library 4155218822Sdim for performing demangling. MANGLED_NAME is a NUL-terminated character 4156218822Sdim string containing the name to be demangled. 4157218822Sdim 4158218822Sdim CALLBACK is a callback function, called with demangled string 4159218822Sdim segments as demangling progresses; it is called at least once, 4160218822Sdim but may be called more than once. OPAQUE is a generalized pointer 4161218822Sdim used as a callback argument. 4162218822Sdim 4163218822Sdim The return code is one of the following values, equivalent to 4164218822Sdim the STATUS values of __cxa_demangle() (excluding -1, since this 4165218822Sdim function performs no memory allocations): 4166218822Sdim 0: The demangling operation succeeded. 4167218822Sdim -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules. 4168218822Sdim -3: One of the arguments is invalid. 4169218822Sdim 4170218822Sdim The demangling is performed using the C++ ABI mangling rules, with 4171218822Sdim GNU extensions. */ 4172218822Sdim 4173218822Sdimint 4174218822Sdim__gcclibcxx_demangle_callback (const char *mangled_name, 4175218822Sdim void (*callback) (const char *, size_t, void *), 4176218822Sdim void *opaque) 4177218822Sdim{ 4178218822Sdim int status; 4179218822Sdim 4180218822Sdim if (mangled_name == NULL || callback == NULL) 4181218822Sdim return -3; 4182218822Sdim 4183218822Sdim status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES, 4184218822Sdim callback, opaque); 4185218822Sdim if (status == 0) 4186218822Sdim return -2; 4187218822Sdim 4188218822Sdim return 0; 4189218822Sdim} 4190218822Sdim 4191104834Sobrien#else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */ 419268765Sobrien 4193130561Sobrien/* Entry point for libiberty demangler. If MANGLED is a g++ v3 ABI 4194130561Sobrien mangled name, return a buffer allocated with malloc holding the 4195130561Sobrien demangled name. Otherwise, return NULL. */ 419668765Sobrien 419768765Sobrienchar * 4198218822Sdimcplus_demangle_v3 (const char *mangled, int options) 419968765Sobrien{ 4200130561Sobrien size_t alc; 420177298Sobrien 4202130561Sobrien return d_demangle (mangled, options, &alc); 420368765Sobrien} 420468765Sobrien 4205218822Sdimint 4206218822Sdimcplus_demangle_v3_callback (const char *mangled, int options, 4207218822Sdim demangle_callbackref callback, void *opaque) 4208218822Sdim{ 4209218822Sdim return d_demangle_callback (mangled, options, callback, opaque); 4210218822Sdim} 4211218822Sdim 421289857Sobrien/* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling 421389857Sobrien conventions, but the output formatting is a little different. 4214218822Sdim This instructs the C++ demangler not to emit pointer characters ("*"), to 4215218822Sdim use Java's namespace separator symbol ("." instead of "::"), and to output 4216218822Sdim JArray<TYPE> as TYPE[]. */ 421789857Sobrien 421889857Sobrienchar * 4219218822Sdimjava_demangle_v3 (const char *mangled) 422089857Sobrien{ 4221130561Sobrien size_t alc; 422289857Sobrien 4223218822Sdim return d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, &alc); 4224218822Sdim} 422589857Sobrien 4226218822Sdimint 4227218822Sdimjava_demangle_v3_callback (const char *mangled, 4228218822Sdim demangle_callbackref callback, void *opaque) 4229218822Sdim{ 4230218822Sdim return d_demangle_callback (mangled, 4231218822Sdim DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX, 4232218822Sdim callback, opaque); 423389857Sobrien} 423489857Sobrien 4235104834Sobrien#endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */ 423668765Sobrien 4237130561Sobrien#ifndef IN_GLIBCPP_V3 423889857Sobrien 4239130561Sobrien/* Demangle a string in order to find out whether it is a constructor 4240130561Sobrien or destructor. Return non-zero on success. Set *CTOR_KIND and 4241130561Sobrien *DTOR_KIND appropriately. */ 4242130561Sobrien 4243130561Sobrienstatic int 4244218822Sdimis_ctor_or_dtor (const char *mangled, 4245218822Sdim enum gnu_v3_ctor_kinds *ctor_kind, 4246218822Sdim enum gnu_v3_dtor_kinds *dtor_kind) 424789857Sobrien{ 4248130561Sobrien struct d_info di; 4249130561Sobrien struct demangle_component *dc; 4250130561Sobrien int ret; 425189857Sobrien 4252130561Sobrien *ctor_kind = (enum gnu_v3_ctor_kinds) 0; 4253130561Sobrien *dtor_kind = (enum gnu_v3_dtor_kinds) 0; 425489857Sobrien 4255130561Sobrien cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di); 425689857Sobrien 4257130561Sobrien { 4258130561Sobrien#ifdef CP_DYNAMIC_ARRAYS 4259130561Sobrien __extension__ struct demangle_component comps[di.num_comps]; 4260130561Sobrien __extension__ struct demangle_component *subs[di.num_subs]; 426189857Sobrien 4262218822Sdim di.comps = comps; 4263218822Sdim di.subs = subs; 4264130561Sobrien#else 4265218822Sdim di.comps = alloca (di.num_comps * sizeof (*di.comps)); 4266218822Sdim di.subs = alloca (di.num_subs * sizeof (*di.subs)); 4267130561Sobrien#endif 426889857Sobrien 4269130561Sobrien dc = cplus_demangle_mangled_name (&di, 1); 4270130561Sobrien 4271130561Sobrien /* Note that because we did not pass DMGL_PARAMS, we don't expect 4272130561Sobrien to demangle the entire string. */ 4273130561Sobrien 4274130561Sobrien ret = 0; 4275130561Sobrien while (dc != NULL) 4276130561Sobrien { 4277130561Sobrien switch (dc->type) 4278130561Sobrien { 4279130561Sobrien default: 4280130561Sobrien dc = NULL; 4281130561Sobrien break; 4282130561Sobrien case DEMANGLE_COMPONENT_TYPED_NAME: 4283130561Sobrien case DEMANGLE_COMPONENT_TEMPLATE: 4284130561Sobrien case DEMANGLE_COMPONENT_RESTRICT_THIS: 4285130561Sobrien case DEMANGLE_COMPONENT_VOLATILE_THIS: 4286130561Sobrien case DEMANGLE_COMPONENT_CONST_THIS: 4287130561Sobrien dc = d_left (dc); 4288130561Sobrien break; 4289130561Sobrien case DEMANGLE_COMPONENT_QUAL_NAME: 4290130561Sobrien case DEMANGLE_COMPONENT_LOCAL_NAME: 4291130561Sobrien dc = d_right (dc); 4292130561Sobrien break; 4293130561Sobrien case DEMANGLE_COMPONENT_CTOR: 4294130561Sobrien *ctor_kind = dc->u.s_ctor.kind; 4295130561Sobrien ret = 1; 4296130561Sobrien dc = NULL; 4297130561Sobrien break; 4298130561Sobrien case DEMANGLE_COMPONENT_DTOR: 4299130561Sobrien *dtor_kind = dc->u.s_dtor.kind; 4300130561Sobrien ret = 1; 4301130561Sobrien dc = NULL; 4302130561Sobrien break; 4303130561Sobrien } 4304130561Sobrien } 4305130561Sobrien } 4306130561Sobrien 4307130561Sobrien return ret; 430889857Sobrien} 430989857Sobrien 4310130561Sobrien/* Return whether NAME is the mangled form of a g++ V3 ABI constructor 4311130561Sobrien name. A non-zero return indicates the type of constructor. */ 431289857Sobrien 431389857Sobrienenum gnu_v3_ctor_kinds 4314218822Sdimis_gnu_v3_mangled_ctor (const char *name) 431589857Sobrien{ 4316130561Sobrien enum gnu_v3_ctor_kinds ctor_kind; 4317130561Sobrien enum gnu_v3_dtor_kinds dtor_kind; 431889857Sobrien 4319130561Sobrien if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) 4320130561Sobrien return (enum gnu_v3_ctor_kinds) 0; 4321130561Sobrien return ctor_kind; 432289857Sobrien} 432389857Sobrien 432489857Sobrien 4325130561Sobrien/* Return whether NAME is the mangled form of a g++ V3 ABI destructor 4326130561Sobrien name. A non-zero return indicates the type of destructor. */ 4327130561Sobrien 432889857Sobrienenum gnu_v3_dtor_kinds 4329218822Sdimis_gnu_v3_mangled_dtor (const char *name) 433089857Sobrien{ 4331130561Sobrien enum gnu_v3_ctor_kinds ctor_kind; 4332130561Sobrien enum gnu_v3_dtor_kinds dtor_kind; 433389857Sobrien 4334130561Sobrien if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) 4335130561Sobrien return (enum gnu_v3_dtor_kinds) 0; 4336130561Sobrien return dtor_kind; 433789857Sobrien} 4338130561Sobrien 4339104834Sobrien#endif /* IN_GLIBCPP_V3 */ 434089857Sobrien 434168765Sobrien#ifdef STANDALONE_DEMANGLER 434268765Sobrien 434368765Sobrien#include "getopt.h" 4344130561Sobrien#include "dyn-string.h" 434568765Sobrien 4346218822Sdimstatic void print_usage (FILE* fp, int exit_value); 434768765Sobrien 4348130561Sobrien#define IS_ALPHA(CHAR) \ 4349130561Sobrien (((CHAR) >= 'a' && (CHAR) <= 'z') \ 4350130561Sobrien || ((CHAR) >= 'A' && (CHAR) <= 'Z')) 4351130561Sobrien 435268765Sobrien/* Non-zero if CHAR is a character than can occur in a mangled name. */ 435368765Sobrien#define is_mangled_char(CHAR) \ 435477298Sobrien (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \ 435577298Sobrien || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$') 435668765Sobrien 435768765Sobrien/* The name of this program, as invoked. */ 435868765Sobrienconst char* program_name; 435968765Sobrien 436068765Sobrien/* Prints usage summary to FP and then exits with EXIT_VALUE. */ 436168765Sobrien 436268765Sobrienstatic void 4363218822Sdimprint_usage (FILE* fp, int exit_value) 436468765Sobrien{ 436568765Sobrien fprintf (fp, "Usage: %s [options] [names ...]\n", program_name); 436677298Sobrien fprintf (fp, "Options:\n"); 436768765Sobrien fprintf (fp, " -h,--help Display this message.\n"); 4368130561Sobrien fprintf (fp, " -p,--no-params Don't display function parameters\n"); 436968765Sobrien fprintf (fp, " -v,--verbose Produce verbose demanglings.\n"); 437068765Sobrien fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n"); 437168765Sobrien 437268765Sobrien exit (exit_value); 437368765Sobrien} 437468765Sobrien 437568765Sobrien/* Option specification for getopt_long. */ 437689857Sobrienstatic const struct option long_options[] = 437768765Sobrien{ 4378130561Sobrien { "help", no_argument, NULL, 'h' }, 4379130561Sobrien { "no-params", no_argument, NULL, 'p' }, 4380130561Sobrien { "verbose", no_argument, NULL, 'v' }, 4381130561Sobrien { NULL, no_argument, NULL, 0 }, 438268765Sobrien}; 438368765Sobrien 438468765Sobrien/* Main entry for a demangling filter executable. It will demangle 438568765Sobrien its command line arguments, if any. If none are provided, it will 438668765Sobrien filter stdin to stdout, replacing any recognized mangled C++ names 438768765Sobrien with their demangled equivalents. */ 438868765Sobrien 438968765Sobrienint 4390218822Sdimmain (int argc, char *argv[]) 439168765Sobrien{ 439268765Sobrien int i; 439368765Sobrien int opt_char; 4394130561Sobrien int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; 439568765Sobrien 439668765Sobrien /* Use the program name of this program, as invoked. */ 439768765Sobrien program_name = argv[0]; 439868765Sobrien 439968765Sobrien /* Parse options. */ 440068765Sobrien do 440168765Sobrien { 4402130561Sobrien opt_char = getopt_long (argc, argv, "hpv", long_options, NULL); 440368765Sobrien switch (opt_char) 440468765Sobrien { 440568765Sobrien case '?': /* Unrecognized option. */ 440668765Sobrien print_usage (stderr, 1); 440768765Sobrien break; 440868765Sobrien 440968765Sobrien case 'h': 441068765Sobrien print_usage (stdout, 0); 441168765Sobrien break; 441268765Sobrien 4413130561Sobrien case 'p': 4414130561Sobrien options &= ~ DMGL_PARAMS; 441568765Sobrien break; 441668765Sobrien 441768765Sobrien case 'v': 4418130561Sobrien options |= DMGL_VERBOSE; 441968765Sobrien break; 442068765Sobrien } 442168765Sobrien } 442268765Sobrien while (opt_char != -1); 442368765Sobrien 442468765Sobrien if (optind == argc) 442568765Sobrien /* No command line arguments were provided. Filter stdin. */ 442668765Sobrien { 442768765Sobrien dyn_string_t mangled = dyn_string_new (3); 4428130561Sobrien char *s; 442968765Sobrien 443068765Sobrien /* Read all of input. */ 443168765Sobrien while (!feof (stdin)) 443268765Sobrien { 4433130561Sobrien char c; 443468765Sobrien 443568765Sobrien /* Pile characters into mangled until we hit one that can't 443668765Sobrien occur in a mangled name. */ 443768765Sobrien c = getchar (); 443868765Sobrien while (!feof (stdin) && is_mangled_char (c)) 443968765Sobrien { 444068765Sobrien dyn_string_append_char (mangled, c); 444168765Sobrien if (feof (stdin)) 444268765Sobrien break; 444368765Sobrien c = getchar (); 444468765Sobrien } 444568765Sobrien 4446130561Sobrien if (dyn_string_length (mangled) > 0) 4447130561Sobrien { 4448218822Sdim#ifdef IN_GLIBCPP_V3 4449218822Sdim s = __cxa_demangle (dyn_string_buf (mangled), NULL, NULL, NULL); 4450218822Sdim#else 4451130561Sobrien s = cplus_demangle_v3 (dyn_string_buf (mangled), options); 4452218822Sdim#endif 445368765Sobrien 4454130561Sobrien if (s != NULL) 4455130561Sobrien { 4456130561Sobrien fputs (s, stdout); 4457130561Sobrien free (s); 4458130561Sobrien } 4459130561Sobrien else 4460130561Sobrien { 4461130561Sobrien /* It might not have been a mangled name. Print the 4462130561Sobrien original text. */ 4463130561Sobrien fputs (dyn_string_buf (mangled), stdout); 4464130561Sobrien } 4465130561Sobrien 4466130561Sobrien dyn_string_clear (mangled); 446768765Sobrien } 446868765Sobrien 446968765Sobrien /* If we haven't hit EOF yet, we've read one character that 447068765Sobrien can't occur in a mangled name, so print it out. */ 447168765Sobrien if (!feof (stdin)) 447268765Sobrien putchar (c); 447368765Sobrien } 447468765Sobrien 447568765Sobrien dyn_string_delete (mangled); 447668765Sobrien } 447768765Sobrien else 447868765Sobrien /* Demangle command line arguments. */ 447968765Sobrien { 448068765Sobrien /* Loop over command line arguments. */ 448168765Sobrien for (i = optind; i < argc; ++i) 448268765Sobrien { 4483130561Sobrien char *s; 4484218822Sdim#ifdef IN_GLIBCPP_V3 4485218822Sdim int status; 4486218822Sdim#endif 4487130561Sobrien 448868765Sobrien /* Attempt to demangle. */ 4489218822Sdim#ifdef IN_GLIBCPP_V3 4490218822Sdim s = __cxa_demangle (argv[i], NULL, NULL, &status); 4491218822Sdim#else 4492130561Sobrien s = cplus_demangle_v3 (argv[i], options); 4493218822Sdim#endif 449468765Sobrien 449568765Sobrien /* If it worked, print the demangled name. */ 4496130561Sobrien if (s != NULL) 449768765Sobrien { 4498130561Sobrien printf ("%s\n", s); 4499130561Sobrien free (s); 450068765Sobrien } 4501130561Sobrien else 4502218822Sdim { 4503218822Sdim#ifdef IN_GLIBCPP_V3 4504218822Sdim fprintf (stderr, "Failed: %s (status %d)\n", argv[i], status); 4505218822Sdim#else 4506218822Sdim fprintf (stderr, "Failed: %s\n", argv[i]); 4507218822Sdim#endif 4508218822Sdim } 450968765Sobrien } 451068765Sobrien } 451168765Sobrien 451268765Sobrien return 0; 451368765Sobrien} 451468765Sobrien 451568765Sobrien#endif /* STANDALONE_DEMANGLER */ 4516