160484Sobrien/* Demangler for GNU C++ 277298Sobrien Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 3130561Sobrien 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 433965Sjdp Written by James Clark (jjc@jclark.uucp) 533965Sjdp Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling 660484Sobrien Modified by Satish Pai (pai@apollo.hp.com) for HP demangling 760484Sobrien 833965SjdpThis file is part of the libiberty library. 933965SjdpLibiberty is free software; you can redistribute it and/or 1033965Sjdpmodify it under the terms of the GNU Library General Public 1133965SjdpLicense as published by the Free Software Foundation; either 1233965Sjdpversion 2 of the License, or (at your option) any later version. 1333965Sjdp 14130561SobrienIn addition to the permissions in the GNU Library General Public 15130561SobrienLicense, the Free Software Foundation gives you unlimited permission 16130561Sobriento link the compiled version of this file into combinations with other 17130561Sobrienprograms, and to distribute those combinations without any restriction 18130561Sobriencoming from the use of this file. (The Library Public License 19130561Sobrienrestrictions do apply in other respects; for example, they cover 20130561Sobrienmodification of the file, and distribution when not linked into a 21130561Sobriencombined executable.) 22130561Sobrien 2333965SjdpLibiberty is distributed in the hope that it will be useful, 2433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 2533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2633965SjdpLibrary General Public License for more details. 2733965Sjdp 2833965SjdpYou should have received a copy of the GNU Library General Public 2933965SjdpLicense along with libiberty; see the file COPYING.LIB. If 30218822Sdimnot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 31218822SdimBoston, MA 02110-1301, USA. */ 3233965Sjdp 3333965Sjdp/* This file exports two functions; cplus_mangle_opname and cplus_demangle. 3433965Sjdp 3533965Sjdp This file imports xmalloc and xrealloc, which are like malloc and 3633965Sjdp realloc except that they generate a fatal error if there is no 3733965Sjdp available memory. */ 3833965Sjdp 3933965Sjdp/* This file lives in both GCC and libiberty. When making changes, please 4033965Sjdp try not to break either. */ 4133965Sjdp 4260484Sobrien#ifdef HAVE_CONFIG_H 4360484Sobrien#include "config.h" 4460484Sobrien#endif 4560484Sobrien 4677298Sobrien#include "safe-ctype.h" 4777298Sobrien 4860484Sobrien#include <sys/types.h> 4933965Sjdp#include <string.h> 5033965Sjdp#include <stdio.h> 5133965Sjdp 5260484Sobrien#ifdef HAVE_STDLIB_H 5360484Sobrien#include <stdlib.h> 5460484Sobrien#else 5560484Sobrienchar * malloc (); 5660484Sobrienchar * realloc (); 5760484Sobrien#endif 5860484Sobrien 5933965Sjdp#include <demangle.h> 6033965Sjdp#undef CURRENT_DEMANGLING_STYLE 6133965Sjdp#define CURRENT_DEMANGLING_STYLE work->options 6233965Sjdp 6360484Sobrien#include "libiberty.h" 6433965Sjdp 65218822Sdimstatic char *ada_demangle (const char *, int); 6677298Sobrien 6760484Sobrien#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) 6860484Sobrien 6960484Sobrien/* A value at least one greater than the maximum number of characters 7060484Sobrien that will be output when using the `%d' format with `printf'. */ 7160484Sobrien#define INTBUF_SIZE 32 7260484Sobrien 73218822Sdimextern void fancy_abort (void) ATTRIBUTE_NORETURN; 7460484Sobrien 7533965Sjdp/* In order to allow a single demangler executable to demangle strings 7633965Sjdp using various common values of CPLUS_MARKER, as well as any specific 7733965Sjdp one set at compile time, we maintain a string containing all the 7833965Sjdp commonly used ones, and check to see if the marker we are looking for 7933965Sjdp is in that string. CPLUS_MARKER is usually '$' on systems where the 8033965Sjdp assembler can deal with that. Where the assembler can't, it's usually 8133965Sjdp '.' (but on many systems '.' is used for other things). We put the 8233965Sjdp current defined CPLUS_MARKER first (which defaults to '$'), followed 8333965Sjdp by the next most common value, followed by an explicit '$' in case 8433965Sjdp the value of CPLUS_MARKER is not '$'. 8533965Sjdp 8633965Sjdp We could avoid this if we could just get g++ to tell us what the actual 8733965Sjdp cplus marker character is as part of the debug information, perhaps by 8833965Sjdp ensuring that it is the character that terminates the gcc<n>_compiled 8933965Sjdp marker symbol (FIXME). */ 9033965Sjdp 9133965Sjdp#if !defined (CPLUS_MARKER) 9233965Sjdp#define CPLUS_MARKER '$' 9333965Sjdp#endif 9433965Sjdp 9577298Sobrienenum demangling_styles current_demangling_style = auto_demangling; 9633965Sjdp 9733965Sjdpstatic char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; 9833965Sjdp 9960484Sobrienstatic char char_str[2] = { '\000', '\000' }; 10060484Sobrien 10133965Sjdpvoid 102218822Sdimset_cplus_marker_for_demangling (int ch) 10333965Sjdp{ 10433965Sjdp cplus_markers[0] = ch; 10533965Sjdp} 10633965Sjdp 10760484Sobrientypedef struct string /* Beware: these aren't required to be */ 10860484Sobrien{ /* '\0' terminated. */ 10960484Sobrien char *b; /* pointer to start of string */ 11060484Sobrien char *p; /* pointer after last character */ 11160484Sobrien char *e; /* pointer after end of allocated space */ 11260484Sobrien} string; 11360484Sobrien 11433965Sjdp/* Stuff that is shared between sub-routines. 11533965Sjdp Using a shared structure allows cplus_demangle to be reentrant. */ 11633965Sjdp 11733965Sjdpstruct work_stuff 11833965Sjdp{ 11933965Sjdp int options; 12033965Sjdp char **typevec; 12160484Sobrien char **ktypevec; 12260484Sobrien char **btypevec; 12360484Sobrien int numk; 12460484Sobrien int numb; 12560484Sobrien int ksize; 12660484Sobrien int bsize; 12733965Sjdp int ntypes; 12833965Sjdp int typevec_size; 12933965Sjdp int constructor; 13033965Sjdp int destructor; 13133965Sjdp int static_type; /* A static member function */ 13260484Sobrien int temp_start; /* index in demangled to start of template args */ 13360484Sobrien int type_quals; /* The type qualifiers. */ 13460484Sobrien int dllimported; /* Symbol imported from a PE DLL */ 13538889Sjdp char **tmpl_argvec; /* Template function arguments. */ 13638889Sjdp int ntmpl_args; /* The number of template function arguments. */ 13760484Sobrien int forgetting_types; /* Nonzero if we are not remembering the types 13860484Sobrien we see. */ 13960484Sobrien string* previous_argument; /* The last function argument demangled. */ 14060484Sobrien int nrepeats; /* The number of times to repeat the previous 14160484Sobrien argument. */ 14233965Sjdp}; 14333965Sjdp 14433965Sjdp#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) 14533965Sjdp#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) 14633965Sjdp 14733965Sjdpstatic const struct optable 14833965Sjdp{ 14989857Sobrien const char *const in; 15089857Sobrien const char *const out; 15189857Sobrien const int flags; 15233965Sjdp} optable[] = { 15333965Sjdp {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ 15433965Sjdp {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ 15533965Sjdp {"new", " new", 0}, /* old (1.91, and 1.x) */ 15633965Sjdp {"delete", " delete", 0}, /* old (1.91, and 1.x) */ 15733965Sjdp {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ 15833965Sjdp {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ 15933965Sjdp {"as", "=", DMGL_ANSI}, /* ansi */ 16033965Sjdp {"ne", "!=", DMGL_ANSI}, /* old, ansi */ 16133965Sjdp {"eq", "==", DMGL_ANSI}, /* old, ansi */ 16233965Sjdp {"ge", ">=", DMGL_ANSI}, /* old, ansi */ 16333965Sjdp {"gt", ">", DMGL_ANSI}, /* old, ansi */ 16433965Sjdp {"le", "<=", DMGL_ANSI}, /* old, ansi */ 16533965Sjdp {"lt", "<", DMGL_ANSI}, /* old, ansi */ 16633965Sjdp {"plus", "+", 0}, /* old */ 16733965Sjdp {"pl", "+", DMGL_ANSI}, /* ansi */ 16833965Sjdp {"apl", "+=", DMGL_ANSI}, /* ansi */ 16933965Sjdp {"minus", "-", 0}, /* old */ 17033965Sjdp {"mi", "-", DMGL_ANSI}, /* ansi */ 17133965Sjdp {"ami", "-=", DMGL_ANSI}, /* ansi */ 17233965Sjdp {"mult", "*", 0}, /* old */ 17333965Sjdp {"ml", "*", DMGL_ANSI}, /* ansi */ 17433965Sjdp {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ 17533965Sjdp {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ 17633965Sjdp {"convert", "+", 0}, /* old (unary +) */ 17733965Sjdp {"negate", "-", 0}, /* old (unary -) */ 17833965Sjdp {"trunc_mod", "%", 0}, /* old */ 17933965Sjdp {"md", "%", DMGL_ANSI}, /* ansi */ 18033965Sjdp {"amd", "%=", DMGL_ANSI}, /* ansi */ 18133965Sjdp {"trunc_div", "/", 0}, /* old */ 18233965Sjdp {"dv", "/", DMGL_ANSI}, /* ansi */ 18333965Sjdp {"adv", "/=", DMGL_ANSI}, /* ansi */ 18433965Sjdp {"truth_andif", "&&", 0}, /* old */ 18533965Sjdp {"aa", "&&", DMGL_ANSI}, /* ansi */ 18633965Sjdp {"truth_orif", "||", 0}, /* old */ 18733965Sjdp {"oo", "||", DMGL_ANSI}, /* ansi */ 18833965Sjdp {"truth_not", "!", 0}, /* old */ 18933965Sjdp {"nt", "!", DMGL_ANSI}, /* ansi */ 19033965Sjdp {"postincrement","++", 0}, /* old */ 19133965Sjdp {"pp", "++", DMGL_ANSI}, /* ansi */ 19233965Sjdp {"postdecrement","--", 0}, /* old */ 19333965Sjdp {"mm", "--", DMGL_ANSI}, /* ansi */ 19433965Sjdp {"bit_ior", "|", 0}, /* old */ 19533965Sjdp {"or", "|", DMGL_ANSI}, /* ansi */ 19633965Sjdp {"aor", "|=", DMGL_ANSI}, /* ansi */ 19733965Sjdp {"bit_xor", "^", 0}, /* old */ 19833965Sjdp {"er", "^", DMGL_ANSI}, /* ansi */ 19933965Sjdp {"aer", "^=", DMGL_ANSI}, /* ansi */ 20033965Sjdp {"bit_and", "&", 0}, /* old */ 20133965Sjdp {"ad", "&", DMGL_ANSI}, /* ansi */ 20233965Sjdp {"aad", "&=", DMGL_ANSI}, /* ansi */ 20333965Sjdp {"bit_not", "~", 0}, /* old */ 20433965Sjdp {"co", "~", DMGL_ANSI}, /* ansi */ 20533965Sjdp {"call", "()", 0}, /* old */ 20633965Sjdp {"cl", "()", DMGL_ANSI}, /* ansi */ 20733965Sjdp {"alshift", "<<", 0}, /* old */ 20833965Sjdp {"ls", "<<", DMGL_ANSI}, /* ansi */ 20933965Sjdp {"als", "<<=", DMGL_ANSI}, /* ansi */ 21033965Sjdp {"arshift", ">>", 0}, /* old */ 21133965Sjdp {"rs", ">>", DMGL_ANSI}, /* ansi */ 21233965Sjdp {"ars", ">>=", DMGL_ANSI}, /* ansi */ 21333965Sjdp {"component", "->", 0}, /* old */ 21433965Sjdp {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ 21533965Sjdp {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ 21633965Sjdp {"indirect", "*", 0}, /* old */ 21733965Sjdp {"method_call", "->()", 0}, /* old */ 21833965Sjdp {"addr", "&", 0}, /* old (unary &) */ 21933965Sjdp {"array", "[]", 0}, /* old */ 22033965Sjdp {"vc", "[]", DMGL_ANSI}, /* ansi */ 22133965Sjdp {"compound", ", ", 0}, /* old */ 22233965Sjdp {"cm", ", ", DMGL_ANSI}, /* ansi */ 22333965Sjdp {"cond", "?:", 0}, /* old */ 22433965Sjdp {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ 22533965Sjdp {"max", ">?", 0}, /* old */ 22633965Sjdp {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ 22733965Sjdp {"min", "<?", 0}, /* old */ 22833965Sjdp {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ 22933965Sjdp {"nop", "", 0}, /* old (for operator=) */ 23060484Sobrien {"rm", "->*", DMGL_ANSI}, /* ansi */ 23160484Sobrien {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ 23233965Sjdp}; 23333965Sjdp 23460484Sobrien/* These values are used to indicate the various type varieties. 23560484Sobrien They are all non-zero so that they can be used as `success' 23660484Sobrien values. */ 23760484Sobrientypedef enum type_kind_t 23860484Sobrien{ 23960484Sobrien tk_none, 24060484Sobrien tk_pointer, 24160484Sobrien tk_reference, 24260484Sobrien tk_integral, 24360484Sobrien tk_bool, 24460484Sobrien tk_char, 24560484Sobrien tk_real 24660484Sobrien} type_kind_t; 24733965Sjdp 24889857Sobrienconst struct demangler_engine libiberty_demanglers[] = 24968765Sobrien{ 25068765Sobrien { 25189857Sobrien NO_DEMANGLING_STYLE_STRING, 25289857Sobrien no_demangling, 25389857Sobrien "Demangling disabled" 25489857Sobrien } 25589857Sobrien , 25689857Sobrien { 25768765Sobrien AUTO_DEMANGLING_STYLE_STRING, 25868765Sobrien auto_demangling, 25968765Sobrien "Automatic selection based on executable" 26068765Sobrien } 26168765Sobrien , 26268765Sobrien { 26368765Sobrien GNU_DEMANGLING_STYLE_STRING, 26468765Sobrien gnu_demangling, 26568765Sobrien "GNU (g++) style demangling" 26668765Sobrien } 26768765Sobrien , 26868765Sobrien { 26968765Sobrien LUCID_DEMANGLING_STYLE_STRING, 27068765Sobrien lucid_demangling, 27168765Sobrien "Lucid (lcc) style demangling" 27268765Sobrien } 27368765Sobrien , 27468765Sobrien { 27568765Sobrien ARM_DEMANGLING_STYLE_STRING, 27668765Sobrien arm_demangling, 27768765Sobrien "ARM style demangling" 27868765Sobrien } 27968765Sobrien , 28068765Sobrien { 28168765Sobrien HP_DEMANGLING_STYLE_STRING, 28268765Sobrien hp_demangling, 28368765Sobrien "HP (aCC) style demangling" 28468765Sobrien } 28568765Sobrien , 28668765Sobrien { 28768765Sobrien EDG_DEMANGLING_STYLE_STRING, 28868765Sobrien edg_demangling, 28968765Sobrien "EDG style demangling" 29068765Sobrien } 29168765Sobrien , 29268765Sobrien { 29377298Sobrien GNU_V3_DEMANGLING_STYLE_STRING, 29477298Sobrien gnu_v3_demangling, 29577298Sobrien "GNU (g++) V3 ABI-style demangling" 29668765Sobrien } 29768765Sobrien , 29868765Sobrien { 29977298Sobrien JAVA_DEMANGLING_STYLE_STRING, 30077298Sobrien java_demangling, 30177298Sobrien "Java style demangling" 30277298Sobrien } 30377298Sobrien , 30477298Sobrien { 30577298Sobrien GNAT_DEMANGLING_STYLE_STRING, 30677298Sobrien gnat_demangling, 30777298Sobrien "GNAT style demangling" 30877298Sobrien } 30977298Sobrien , 31077298Sobrien { 31168765Sobrien NULL, unknown_demangling, NULL 31268765Sobrien } 31368765Sobrien}; 31468765Sobrien 31533965Sjdp#define STRING_EMPTY(str) ((str) -> b == (str) -> p) 31633965Sjdp#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ 31733965Sjdp string_append(str, " ");} 31860484Sobrien#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) 31933965Sjdp 32060484Sobrien/* The scope separator appropriate for the language being demangled. */ 32160484Sobrien 32260484Sobrien#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::") 32360484Sobrien 32433965Sjdp#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ 32533965Sjdp#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ 32633965Sjdp 32733965Sjdp/* Prototypes for local functions */ 32833965Sjdp 329218822Sdimstatic void delete_work_stuff (struct work_stuff *); 33068765Sobrien 331218822Sdimstatic void delete_non_B_K_work_stuff (struct work_stuff *); 33268765Sobrien 333218822Sdimstatic char *mop_up (struct work_stuff *, string *, int); 33433965Sjdp 335218822Sdimstatic void squangle_mop_up (struct work_stuff *); 33660484Sobrien 337218822Sdimstatic void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *); 33868765Sobrien 33933965Sjdp#if 0 34033965Sjdpstatic int 341218822Sdimdemangle_method_args (struct work_stuff *, const char **, string *); 34233965Sjdp#endif 34333965Sjdp 34460484Sobrienstatic char * 345218822Sdiminternal_cplus_demangle (struct work_stuff *, const char *); 34660484Sobrien 34733965Sjdpstatic int 348218822Sdimdemangle_template_template_parm (struct work_stuff *work, 349218822Sdim const char **, string *); 35060484Sobrien 35160484Sobrienstatic int 352218822Sdimdemangle_template (struct work_stuff *work, const char **, string *, 353218822Sdim string *, int, int); 35433965Sjdp 35533965Sjdpstatic int 356218822Sdimarm_pt (struct work_stuff *, const char *, int, const char **, 357218822Sdim const char **); 35833965Sjdp 35933965Sjdpstatic int 360218822Sdimdemangle_class_name (struct work_stuff *, const char **, string *); 36133965Sjdp 36233965Sjdpstatic int 363218822Sdimdemangle_qualified (struct work_stuff *, const char **, string *, 364218822Sdim int, int); 36533965Sjdp 366218822Sdimstatic int demangle_class (struct work_stuff *, const char **, string *); 36733965Sjdp 368218822Sdimstatic int demangle_fund_type (struct work_stuff *, const char **, string *); 36933965Sjdp 370218822Sdimstatic int demangle_signature (struct work_stuff *, const char **, string *); 37133965Sjdp 372218822Sdimstatic int demangle_prefix (struct work_stuff *, const char **, string *); 37333965Sjdp 374218822Sdimstatic int gnu_special (struct work_stuff *, const char **, string *); 37533965Sjdp 376218822Sdimstatic int arm_special (const char **, string *); 37733965Sjdp 378218822Sdimstatic void string_need (string *, int); 37933965Sjdp 380218822Sdimstatic void string_delete (string *); 38133965Sjdp 38233965Sjdpstatic void 383218822Sdimstring_init (string *); 38433965Sjdp 385218822Sdimstatic void string_clear (string *); 38633965Sjdp 38733965Sjdp#if 0 388218822Sdimstatic int string_empty (string *); 38933965Sjdp#endif 39033965Sjdp 391218822Sdimstatic void string_append (string *, const char *); 39233965Sjdp 393218822Sdimstatic void string_appends (string *, string *); 39433965Sjdp 395218822Sdimstatic void string_appendn (string *, const char *, int); 39633965Sjdp 397218822Sdimstatic void string_prepend (string *, const char *); 39833965Sjdp 399218822Sdimstatic void string_prependn (string *, const char *, int); 40033965Sjdp 401218822Sdimstatic void string_append_template_idx (string *, int); 40260484Sobrien 403218822Sdimstatic int get_count (const char **, int *); 40433965Sjdp 405218822Sdimstatic int consume_count (const char **); 40633965Sjdp 407218822Sdimstatic int consume_count_with_underscores (const char**); 40838889Sjdp 409218822Sdimstatic int demangle_args (struct work_stuff *, const char **, string *); 41033965Sjdp 411218822Sdimstatic int demangle_nested_args (struct work_stuff*, const char**, string*); 41260484Sobrien 413218822Sdimstatic int do_type (struct work_stuff *, const char **, string *); 41433965Sjdp 415218822Sdimstatic int do_arg (struct work_stuff *, const char **, string *); 41633965Sjdp 41733965Sjdpstatic void 418218822Sdimdemangle_function_name (struct work_stuff *, const char **, string *, 419218822Sdim const char *); 42033965Sjdp 42168765Sobrienstatic int 422218822Sdimiterate_demangle_function (struct work_stuff *, 423218822Sdim const char **, string *, const char *); 42468765Sobrien 425218822Sdimstatic void remember_type (struct work_stuff *, const char *, int); 42633965Sjdp 427218822Sdimstatic void remember_Btype (struct work_stuff *, const char *, int, int); 42860484Sobrien 429218822Sdimstatic int register_Btype (struct work_stuff *); 43060484Sobrien 431218822Sdimstatic void remember_Ktype (struct work_stuff *, const char *, int); 43260484Sobrien 433218822Sdimstatic void forget_types (struct work_stuff *); 43433965Sjdp 435218822Sdimstatic void forget_B_and_K_types (struct work_stuff *); 43660484Sobrien 437218822Sdimstatic void string_prepends (string *, string *); 43833965Sjdp 43960484Sobrienstatic int 440218822Sdimdemangle_template_value_parm (struct work_stuff*, const char**, 441218822Sdim string*, type_kind_t); 44233965Sjdp 44333965Sjdpstatic int 444218822Sdimdo_hpacc_template_const_value (struct work_stuff *, const char **, string *); 44560484Sobrien 44660484Sobrienstatic int 447218822Sdimdo_hpacc_template_literal (struct work_stuff *, const char **, string *); 44860484Sobrien 449218822Sdimstatic int snarf_numeric_literal (const char **, string *); 45060484Sobrien 45160484Sobrien/* There is a TYPE_QUAL value for each type qualifier. They can be 45260484Sobrien combined by bitwise-or to form the complete set of qualifiers for a 45360484Sobrien type. */ 45460484Sobrien 45560484Sobrien#define TYPE_UNQUALIFIED 0x0 45660484Sobrien#define TYPE_QUAL_CONST 0x1 45760484Sobrien#define TYPE_QUAL_VOLATILE 0x2 45860484Sobrien#define TYPE_QUAL_RESTRICT 0x4 45960484Sobrien 460218822Sdimstatic int code_for_qualifier (int); 46160484Sobrien 462218822Sdimstatic const char* qualifier_string (int); 46360484Sobrien 464218822Sdimstatic const char* demangle_qualifier (int); 46560484Sobrien 466218822Sdimstatic int demangle_expression (struct work_stuff *, const char **, string *, 467218822Sdim type_kind_t); 46860484Sobrien 46960484Sobrienstatic int 470218822Sdimdemangle_integral_value (struct work_stuff *, const char **, string *); 47160484Sobrien 47260484Sobrienstatic int 473218822Sdimdemangle_real_value (struct work_stuff *, const char **, string *); 47460484Sobrien 47560484Sobrienstatic void 476218822Sdimdemangle_arm_hp_template (struct work_stuff *, const char **, int, string *); 47760484Sobrien 47860484Sobrienstatic void 479218822Sdimrecursively_demangle (struct work_stuff *, const char **, string *, int); 48060484Sobrien 481218822Sdimstatic void grow_vect (char **, size_t *, size_t, int); 48277298Sobrien 48360484Sobrien/* Translate count to integer, consuming tokens in the process. 48460484Sobrien Conversion terminates on the first non-digit character. 48560484Sobrien 48660484Sobrien Trying to consume something that isn't a count results in no 48760484Sobrien consumption of input and a return of -1. 48860484Sobrien 48960484Sobrien Overflow consumes the rest of the digits, and returns -1. */ 49060484Sobrien 49160484Sobrienstatic int 492218822Sdimconsume_count (const char **type) 49333965Sjdp{ 49433965Sjdp int count = 0; 49533965Sjdp 49677298Sobrien if (! ISDIGIT ((unsigned char)**type)) 49760484Sobrien return -1; 49860484Sobrien 49977298Sobrien while (ISDIGIT ((unsigned char)**type)) 50033965Sjdp { 50133965Sjdp count *= 10; 50260484Sobrien 50360484Sobrien /* Check for overflow. 50460484Sobrien We assume that count is represented using two's-complement; 50560484Sobrien no power of two is divisible by ten, so if an overflow occurs 50660484Sobrien when multiplying by ten, the result will not be a multiple of 50760484Sobrien ten. */ 50860484Sobrien if ((count % 10) != 0) 50960484Sobrien { 51077298Sobrien while (ISDIGIT ((unsigned char) **type)) 51160484Sobrien (*type)++; 51260484Sobrien return -1; 51360484Sobrien } 51460484Sobrien 51533965Sjdp count += **type - '0'; 51633965Sjdp (*type)++; 51733965Sjdp } 51860484Sobrien 51989857Sobrien if (count < 0) 52089857Sobrien count = -1; 52189857Sobrien 52233965Sjdp return (count); 52333965Sjdp} 52433965Sjdp 52538889Sjdp 52660484Sobrien/* Like consume_count, but for counts that are preceded and followed 52738889Sjdp by '_' if they are greater than 10. Also, -1 is returned for 52838889Sjdp failure, since 0 can be a valid value. */ 52938889Sjdp 53038889Sjdpstatic int 531218822Sdimconsume_count_with_underscores (const char **mangled) 53238889Sjdp{ 53338889Sjdp int idx; 53438889Sjdp 53538889Sjdp if (**mangled == '_') 53638889Sjdp { 53738889Sjdp (*mangled)++; 53877298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 53938889Sjdp return -1; 54038889Sjdp 54138889Sjdp idx = consume_count (mangled); 54238889Sjdp if (**mangled != '_') 54338889Sjdp /* The trailing underscore was missing. */ 54438889Sjdp return -1; 54560484Sobrien 54638889Sjdp (*mangled)++; 54738889Sjdp } 54838889Sjdp else 54938889Sjdp { 55038889Sjdp if (**mangled < '0' || **mangled > '9') 55138889Sjdp return -1; 55260484Sobrien 55338889Sjdp idx = **mangled - '0'; 55438889Sjdp (*mangled)++; 55538889Sjdp } 55638889Sjdp 55738889Sjdp return idx; 55838889Sjdp} 55938889Sjdp 56060484Sobrien/* C is the code for a type-qualifier. Return the TYPE_QUAL 56160484Sobrien corresponding to this qualifier. */ 56260484Sobrien 56360484Sobrienstatic int 564218822Sdimcode_for_qualifier (int c) 56560484Sobrien{ 56660484Sobrien switch (c) 56760484Sobrien { 56860484Sobrien case 'C': 56960484Sobrien return TYPE_QUAL_CONST; 57060484Sobrien 57160484Sobrien case 'V': 57260484Sobrien return TYPE_QUAL_VOLATILE; 57360484Sobrien 57460484Sobrien case 'u': 57560484Sobrien return TYPE_QUAL_RESTRICT; 57660484Sobrien 57760484Sobrien default: 57860484Sobrien break; 57960484Sobrien } 58060484Sobrien 58160484Sobrien /* C was an invalid qualifier. */ 58260484Sobrien abort (); 58360484Sobrien} 58460484Sobrien 58560484Sobrien/* Return the string corresponding to the qualifiers given by 58660484Sobrien TYPE_QUALS. */ 58760484Sobrien 58860484Sobrienstatic const char* 589218822Sdimqualifier_string (int type_quals) 59060484Sobrien{ 59160484Sobrien switch (type_quals) 59260484Sobrien { 59360484Sobrien case TYPE_UNQUALIFIED: 59460484Sobrien return ""; 59560484Sobrien 59660484Sobrien case TYPE_QUAL_CONST: 59760484Sobrien return "const"; 59860484Sobrien 59960484Sobrien case TYPE_QUAL_VOLATILE: 60060484Sobrien return "volatile"; 60160484Sobrien 60260484Sobrien case TYPE_QUAL_RESTRICT: 60360484Sobrien return "__restrict"; 60460484Sobrien 60560484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: 60660484Sobrien return "const volatile"; 60760484Sobrien 60860484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: 60960484Sobrien return "const __restrict"; 61060484Sobrien 61160484Sobrien case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 61260484Sobrien return "volatile __restrict"; 61360484Sobrien 61460484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 61560484Sobrien return "const volatile __restrict"; 61660484Sobrien 61760484Sobrien default: 61860484Sobrien break; 61960484Sobrien } 62060484Sobrien 62160484Sobrien /* TYPE_QUALS was an invalid qualifier set. */ 62260484Sobrien abort (); 62360484Sobrien} 62460484Sobrien 62560484Sobrien/* C is the code for a type-qualifier. Return the string 62660484Sobrien corresponding to this qualifier. This function should only be 62760484Sobrien called with a valid qualifier code. */ 62860484Sobrien 62960484Sobrienstatic const char* 630218822Sdimdemangle_qualifier (int c) 63160484Sobrien{ 63260484Sobrien return qualifier_string (code_for_qualifier (c)); 63360484Sobrien} 63460484Sobrien 63533965Sjdpint 636218822Sdimcplus_demangle_opname (const char *opname, char *result, int options) 63733965Sjdp{ 63860484Sobrien int len, len1, ret; 63933965Sjdp string type; 64033965Sjdp struct work_stuff work[1]; 64133965Sjdp const char *tem; 64233965Sjdp 64333965Sjdp len = strlen(opname); 64433965Sjdp result[0] = '\0'; 64533965Sjdp ret = 0; 64660484Sobrien memset ((char *) work, 0, sizeof (work)); 64733965Sjdp work->options = options; 64860484Sobrien 64933965Sjdp if (opname[0] == '_' && opname[1] == '_' 65033965Sjdp && opname[2] == 'o' && opname[3] == 'p') 65133965Sjdp { 65233965Sjdp /* ANSI. */ 65333965Sjdp /* type conversion operator. */ 65433965Sjdp tem = opname + 4; 65533965Sjdp if (do_type (work, &tem, &type)) 65633965Sjdp { 65733965Sjdp strcat (result, "operator "); 65833965Sjdp strncat (result, type.b, type.p - type.b); 65933965Sjdp string_delete (&type); 66033965Sjdp ret = 1; 66133965Sjdp } 66233965Sjdp } 66333965Sjdp else if (opname[0] == '_' && opname[1] == '_' 66477298Sobrien && ISLOWER((unsigned char)opname[2]) 66577298Sobrien && ISLOWER((unsigned char)opname[3])) 66633965Sjdp { 66733965Sjdp if (opname[4] == '\0') 66833965Sjdp { 66933965Sjdp /* Operator. */ 67060484Sobrien size_t i; 67177298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 67233965Sjdp { 67333965Sjdp if (strlen (optable[i].in) == 2 67433965Sjdp && memcmp (optable[i].in, opname + 2, 2) == 0) 67533965Sjdp { 67633965Sjdp strcat (result, "operator"); 67733965Sjdp strcat (result, optable[i].out); 67833965Sjdp ret = 1; 67933965Sjdp break; 68033965Sjdp } 68133965Sjdp } 68233965Sjdp } 68333965Sjdp else 68433965Sjdp { 68533965Sjdp if (opname[2] == 'a' && opname[5] == '\0') 68633965Sjdp { 68733965Sjdp /* Assignment. */ 68860484Sobrien size_t i; 68977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 69033965Sjdp { 69133965Sjdp if (strlen (optable[i].in) == 3 69233965Sjdp && memcmp (optable[i].in, opname + 2, 3) == 0) 69333965Sjdp { 69433965Sjdp strcat (result, "operator"); 69533965Sjdp strcat (result, optable[i].out); 69633965Sjdp ret = 1; 69733965Sjdp break; 69860484Sobrien } 69933965Sjdp } 70033965Sjdp } 70133965Sjdp } 70233965Sjdp } 70360484Sobrien else if (len >= 3 70433965Sjdp && opname[0] == 'o' 70533965Sjdp && opname[1] == 'p' 70633965Sjdp && strchr (cplus_markers, opname[2]) != NULL) 70733965Sjdp { 70833965Sjdp /* see if it's an assignment expression */ 70933965Sjdp if (len >= 10 /* op$assign_ */ 71033965Sjdp && memcmp (opname + 3, "assign_", 7) == 0) 71133965Sjdp { 71260484Sobrien size_t i; 71377298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 71433965Sjdp { 71533965Sjdp len1 = len - 10; 71660484Sobrien if ((int) strlen (optable[i].in) == len1 71733965Sjdp && memcmp (optable[i].in, opname + 10, len1) == 0) 71833965Sjdp { 71933965Sjdp strcat (result, "operator"); 72033965Sjdp strcat (result, optable[i].out); 72133965Sjdp strcat (result, "="); 72233965Sjdp ret = 1; 72333965Sjdp break; 72433965Sjdp } 72533965Sjdp } 72633965Sjdp } 72733965Sjdp else 72833965Sjdp { 72960484Sobrien size_t i; 73077298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 73133965Sjdp { 73233965Sjdp len1 = len - 3; 73360484Sobrien if ((int) strlen (optable[i].in) == len1 73433965Sjdp && memcmp (optable[i].in, opname + 3, len1) == 0) 73533965Sjdp { 73633965Sjdp strcat (result, "operator"); 73733965Sjdp strcat (result, optable[i].out); 73833965Sjdp ret = 1; 73933965Sjdp break; 74033965Sjdp } 74133965Sjdp } 74233965Sjdp } 74333965Sjdp } 74433965Sjdp else if (len >= 5 && memcmp (opname, "type", 4) == 0 74533965Sjdp && strchr (cplus_markers, opname[4]) != NULL) 74633965Sjdp { 74733965Sjdp /* type conversion operator */ 74833965Sjdp tem = opname + 5; 74933965Sjdp if (do_type (work, &tem, &type)) 75033965Sjdp { 75133965Sjdp strcat (result, "operator "); 75233965Sjdp strncat (result, type.b, type.p - type.b); 75333965Sjdp string_delete (&type); 75433965Sjdp ret = 1; 75533965Sjdp } 75633965Sjdp } 75760484Sobrien squangle_mop_up (work); 75833965Sjdp return ret; 75933965Sjdp 76033965Sjdp} 76168765Sobrien 76233965Sjdp/* Takes operator name as e.g. "++" and returns mangled 76333965Sjdp operator name (e.g. "postincrement_expr"), or NULL if not found. 76433965Sjdp 76533965Sjdp If OPTIONS & DMGL_ANSI == 1, return the ANSI name; 76633965Sjdp if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ 76733965Sjdp 76833965Sjdpconst char * 769218822Sdimcplus_mangle_opname (const char *opname, int options) 77033965Sjdp{ 77160484Sobrien size_t i; 77233965Sjdp int len; 77333965Sjdp 77433965Sjdp len = strlen (opname); 77577298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 77633965Sjdp { 77760484Sobrien if ((int) strlen (optable[i].out) == len 77833965Sjdp && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) 77933965Sjdp && memcmp (optable[i].out, opname, len) == 0) 78033965Sjdp return optable[i].in; 78133965Sjdp } 78233965Sjdp return (0); 78333965Sjdp} 78433965Sjdp 78568765Sobrien/* Add a routine to set the demangling style to be sure it is valid and 78668765Sobrien allow for any demangler initialization that maybe necessary. */ 78768765Sobrien 78868765Sobrienenum demangling_styles 789218822Sdimcplus_demangle_set_style (enum demangling_styles style) 79068765Sobrien{ 79189857Sobrien const struct demangler_engine *demangler = libiberty_demanglers; 79268765Sobrien 79368765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 79468765Sobrien if (style == demangler->demangling_style) 79568765Sobrien { 79668765Sobrien current_demangling_style = style; 79768765Sobrien return current_demangling_style; 79868765Sobrien } 79968765Sobrien 80068765Sobrien return unknown_demangling; 80168765Sobrien} 80268765Sobrien 80368765Sobrien/* Do string name to style translation */ 80468765Sobrien 80568765Sobrienenum demangling_styles 806218822Sdimcplus_demangle_name_to_style (const char *name) 80768765Sobrien{ 80889857Sobrien const struct demangler_engine *demangler = libiberty_demanglers; 80968765Sobrien 81068765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 81168765Sobrien if (strcmp (name, demangler->demangling_style_name) == 0) 81268765Sobrien return demangler->demangling_style; 81368765Sobrien 81468765Sobrien return unknown_demangling; 81568765Sobrien} 81668765Sobrien 81733965Sjdp/* char *cplus_demangle (const char *mangled, int options) 81833965Sjdp 81933965Sjdp If MANGLED is a mangled function name produced by GNU C++, then 82089857Sobrien a pointer to a @code{malloc}ed string giving a C++ representation 82133965Sjdp of the name will be returned; otherwise NULL will be returned. 82233965Sjdp It is the caller's responsibility to free the string which 82333965Sjdp is returned. 82433965Sjdp 82533965Sjdp The OPTIONS arg may contain one or more of the following bits: 82633965Sjdp 82733965Sjdp DMGL_ANSI ANSI qualifiers such as `const' and `void' are 82833965Sjdp included. 82933965Sjdp DMGL_PARAMS Function parameters are included. 83033965Sjdp 83133965Sjdp For example, 83260484Sobrien 83333965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" 83433965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" 83533965Sjdp cplus_demangle ("foo__1Ai", 0) => "A::foo" 83633965Sjdp 83733965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" 83833965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" 83933965Sjdp cplus_demangle ("foo__1Afe", 0) => "A::foo" 84033965Sjdp 84133965Sjdp Note that any leading underscores, or other such characters prepended by 84233965Sjdp the compilation system, are presumed to have already been stripped from 84333965Sjdp MANGLED. */ 84433965Sjdp 84533965Sjdpchar * 846218822Sdimcplus_demangle (const char *mangled, int options) 84733965Sjdp{ 84860484Sobrien char *ret; 84960484Sobrien struct work_stuff work[1]; 85089857Sobrien 85189857Sobrien if (current_demangling_style == no_demangling) 85289857Sobrien return xstrdup (mangled); 85389857Sobrien 85460484Sobrien memset ((char *) work, 0, sizeof (work)); 85577298Sobrien work->options = options; 85677298Sobrien if ((work->options & DMGL_STYLE_MASK) == 0) 85777298Sobrien work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; 85860484Sobrien 85977298Sobrien /* The V3 ABI demangling is implemented elsewhere. */ 86077298Sobrien if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) 86177298Sobrien { 86291041Sobrien ret = cplus_demangle_v3 (mangled, work->options); 86377298Sobrien if (ret || GNU_V3_DEMANGLING) 86477298Sobrien return ret; 86577298Sobrien } 86668765Sobrien 86789857Sobrien if (JAVA_DEMANGLING) 86889857Sobrien { 86989857Sobrien ret = java_demangle_v3 (mangled); 87089857Sobrien if (ret) 87189857Sobrien return ret; 87289857Sobrien } 87389857Sobrien 87477298Sobrien if (GNAT_DEMANGLING) 87577298Sobrien return ada_demangle(mangled,options); 87677298Sobrien 87760484Sobrien ret = internal_cplus_demangle (work, mangled); 87860484Sobrien squangle_mop_up (work); 87960484Sobrien return (ret); 88060484Sobrien} 88160484Sobrien 88260484Sobrien 88377298Sobrien/* Assuming *OLD_VECT points to an array of *SIZE objects of size 88477298Sobrien ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, 88577298Sobrien updating *OLD_VECT and *SIZE as necessary. */ 88677298Sobrien 88777298Sobrienstatic void 888218822Sdimgrow_vect (char **old_vect, size_t *size, size_t min_size, int element_size) 88977298Sobrien{ 89077298Sobrien if (*size < min_size) 89177298Sobrien { 89277298Sobrien *size *= 2; 89377298Sobrien if (*size < min_size) 89477298Sobrien *size = min_size; 895218822Sdim *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size); 89677298Sobrien } 89777298Sobrien} 89877298Sobrien 89977298Sobrien/* Demangle ada names: 90077298Sobrien 1. Discard final __{DIGIT}+ or ${DIGIT}+ 90177298Sobrien 2. Convert other instances of embedded "__" to `.'. 90277298Sobrien 3. Discard leading _ada_. 90377298Sobrien 4. Remove everything after first ___ if it is followed by 'X'. 90477298Sobrien 5. Put symbols that should be suppressed in <...> brackets. 90577298Sobrien The resulting string is valid until the next call of ada_demangle. */ 90677298Sobrien 90777298Sobrienstatic char * 908218822Sdimada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) 90977298Sobrien{ 91077298Sobrien int i, j; 91177298Sobrien int len0; 91277298Sobrien const char* p; 91377298Sobrien char *demangled = NULL; 91477298Sobrien int changed; 915130561Sobrien size_t demangled_size = 0; 91677298Sobrien 91777298Sobrien changed = 0; 91877298Sobrien 91977298Sobrien if (strncmp (mangled, "_ada_", 5) == 0) 92077298Sobrien { 92177298Sobrien mangled += 5; 92277298Sobrien changed = 1; 92377298Sobrien } 92477298Sobrien 92577298Sobrien if (mangled[0] == '_' || mangled[0] == '<') 92677298Sobrien goto Suppress; 92777298Sobrien 92877298Sobrien p = strstr (mangled, "___"); 92977298Sobrien if (p == NULL) 93077298Sobrien len0 = strlen (mangled); 93177298Sobrien else 93277298Sobrien { 93377298Sobrien if (p[3] == 'X') 93477298Sobrien { 93577298Sobrien len0 = p - mangled; 93677298Sobrien changed = 1; 93777298Sobrien } 93877298Sobrien else 93977298Sobrien goto Suppress; 94077298Sobrien } 94177298Sobrien 94277298Sobrien /* Make demangled big enough for possible expansion by operator name. */ 943130561Sobrien grow_vect (&demangled, 944130561Sobrien &demangled_size, 2 * len0 + 1, 94577298Sobrien sizeof (char)); 94677298Sobrien 94777298Sobrien if (ISDIGIT ((unsigned char) mangled[len0 - 1])) { 94877298Sobrien for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1) 94977298Sobrien ; 95077298Sobrien if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') 95177298Sobrien { 95277298Sobrien len0 = i - 1; 95377298Sobrien changed = 1; 95477298Sobrien } 95577298Sobrien else if (mangled[i] == '$') 95677298Sobrien { 95777298Sobrien len0 = i; 95877298Sobrien changed = 1; 95977298Sobrien } 96077298Sobrien } 96177298Sobrien 96277298Sobrien for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]); 96377298Sobrien i += 1, j += 1) 96477298Sobrien demangled[j] = mangled[i]; 96577298Sobrien 96677298Sobrien while (i < len0) 96777298Sobrien { 96877298Sobrien if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') 96977298Sobrien { 97077298Sobrien demangled[j] = '.'; 971218822Sdim changed = 1; 97277298Sobrien i += 2; j += 1; 97377298Sobrien } 97477298Sobrien else 97577298Sobrien { 97677298Sobrien demangled[j] = mangled[i]; 97777298Sobrien i += 1; j += 1; 97877298Sobrien } 97977298Sobrien } 98077298Sobrien demangled[j] = '\000'; 98177298Sobrien 98277298Sobrien for (i = 0; demangled[i] != '\0'; i += 1) 98377298Sobrien if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ') 98477298Sobrien goto Suppress; 98577298Sobrien 98677298Sobrien if (! changed) 98777298Sobrien return NULL; 98877298Sobrien else 98977298Sobrien return demangled; 99077298Sobrien 99177298Sobrien Suppress: 992130561Sobrien grow_vect (&demangled, 993130561Sobrien &demangled_size, strlen (mangled) + 3, 99477298Sobrien sizeof (char)); 995130561Sobrien 99677298Sobrien if (mangled[0] == '<') 99777298Sobrien strcpy (demangled, mangled); 99877298Sobrien else 99977298Sobrien sprintf (demangled, "<%s>", mangled); 100077298Sobrien 100177298Sobrien return demangled; 100277298Sobrien} 100377298Sobrien 100460484Sobrien/* This function performs most of what cplus_demangle use to do, but 100560484Sobrien to be able to demangle a name with a B, K or n code, we need to 100660484Sobrien have a longer term memory of what types have been seen. The original 1007130561Sobrien now initializes and cleans up the squangle code info, while internal 100860484Sobrien calls go directly to this routine to avoid resetting that info. */ 100960484Sobrien 101060484Sobrienstatic char * 1011218822Sdiminternal_cplus_demangle (struct work_stuff *work, const char *mangled) 101260484Sobrien{ 101360484Sobrien 101433965Sjdp string decl; 101533965Sjdp int success = 0; 101633965Sjdp char *demangled = NULL; 101777298Sobrien int s1, s2, s3, s4; 101860484Sobrien s1 = work->constructor; 101960484Sobrien s2 = work->destructor; 102060484Sobrien s3 = work->static_type; 102160484Sobrien s4 = work->type_quals; 102260484Sobrien work->constructor = work->destructor = 0; 102360484Sobrien work->type_quals = TYPE_UNQUALIFIED; 102460484Sobrien work->dllimported = 0; 102533965Sjdp 102633965Sjdp if ((mangled != NULL) && (*mangled != '\0')) 102733965Sjdp { 102833965Sjdp string_init (&decl); 102933965Sjdp 103033965Sjdp /* First check to see if gnu style demangling is active and if the 103133965Sjdp string to be demangled contains a CPLUS_MARKER. If so, attempt to 103233965Sjdp recognize one of the gnu special forms rather than looking for a 103333965Sjdp standard prefix. In particular, don't worry about whether there 103433965Sjdp is a "__" string in the mangled string. Consider "_$_5__foo" for 103533965Sjdp example. */ 103633965Sjdp 103733965Sjdp if ((AUTO_DEMANGLING || GNU_DEMANGLING)) 103833965Sjdp { 103933965Sjdp success = gnu_special (work, &mangled, &decl); 104033965Sjdp } 104133965Sjdp if (!success) 104233965Sjdp { 104333965Sjdp success = demangle_prefix (work, &mangled, &decl); 104433965Sjdp } 104533965Sjdp if (success && (*mangled != '\0')) 104633965Sjdp { 104733965Sjdp success = demangle_signature (work, &mangled, &decl); 104833965Sjdp } 104933965Sjdp if (work->constructor == 2) 105033965Sjdp { 105160484Sobrien string_prepend (&decl, "global constructors keyed to "); 105233965Sjdp work->constructor = 0; 105333965Sjdp } 105433965Sjdp else if (work->destructor == 2) 105533965Sjdp { 105660484Sobrien string_prepend (&decl, "global destructors keyed to "); 105733965Sjdp work->destructor = 0; 105833965Sjdp } 105960484Sobrien else if (work->dllimported == 1) 106060484Sobrien { 106160484Sobrien string_prepend (&decl, "import stub for "); 106260484Sobrien work->dllimported = 0; 106360484Sobrien } 106433965Sjdp demangled = mop_up (work, &decl, success); 106533965Sjdp } 106660484Sobrien work->constructor = s1; 106760484Sobrien work->destructor = s2; 106860484Sobrien work->static_type = s3; 106960484Sobrien work->type_quals = s4; 107077298Sobrien return demangled; 107133965Sjdp} 107233965Sjdp 107360484Sobrien 107460484Sobrien/* Clear out and squangling related storage */ 107560484Sobrienstatic void 1076218822Sdimsquangle_mop_up (struct work_stuff *work) 107760484Sobrien{ 107860484Sobrien /* clean up the B and K type mangling types. */ 107960484Sobrien forget_B_and_K_types (work); 108060484Sobrien if (work -> btypevec != NULL) 108160484Sobrien { 108260484Sobrien free ((char *) work -> btypevec); 108360484Sobrien } 108460484Sobrien if (work -> ktypevec != NULL) 108560484Sobrien { 108660484Sobrien free ((char *) work -> ktypevec); 108760484Sobrien } 108860484Sobrien} 108960484Sobrien 109060484Sobrien 109168765Sobrien/* Copy the work state and storage. */ 109268765Sobrien 109368765Sobrienstatic void 1094218822Sdimwork_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from) 109568765Sobrien{ 109668765Sobrien int i; 109768765Sobrien 109868765Sobrien delete_work_stuff (to); 109968765Sobrien 110068765Sobrien /* Shallow-copy scalars. */ 110168765Sobrien memcpy (to, from, sizeof (*to)); 110268765Sobrien 110368765Sobrien /* Deep-copy dynamic storage. */ 110468765Sobrien if (from->typevec_size) 1105218822Sdim to->typevec = XNEWVEC (char *, from->typevec_size); 110668765Sobrien 110768765Sobrien for (i = 0; i < from->ntypes; i++) 110868765Sobrien { 110968765Sobrien int len = strlen (from->typevec[i]) + 1; 111068765Sobrien 1111218822Sdim to->typevec[i] = XNEWVEC (char, len); 111268765Sobrien memcpy (to->typevec[i], from->typevec[i], len); 111368765Sobrien } 111468765Sobrien 111568765Sobrien if (from->ksize) 1116218822Sdim to->ktypevec = XNEWVEC (char *, from->ksize); 111768765Sobrien 111868765Sobrien for (i = 0; i < from->numk; i++) 111968765Sobrien { 112068765Sobrien int len = strlen (from->ktypevec[i]) + 1; 112168765Sobrien 1122218822Sdim to->ktypevec[i] = XNEWVEC (char, len); 112368765Sobrien memcpy (to->ktypevec[i], from->ktypevec[i], len); 112468765Sobrien } 112568765Sobrien 112668765Sobrien if (from->bsize) 1127218822Sdim to->btypevec = XNEWVEC (char *, from->bsize); 112868765Sobrien 112968765Sobrien for (i = 0; i < from->numb; i++) 113068765Sobrien { 113168765Sobrien int len = strlen (from->btypevec[i]) + 1; 113268765Sobrien 1133218822Sdim to->btypevec[i] = XNEWVEC (char , len); 113468765Sobrien memcpy (to->btypevec[i], from->btypevec[i], len); 113568765Sobrien } 113668765Sobrien 113768765Sobrien if (from->ntmpl_args) 1138218822Sdim to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args); 113968765Sobrien 114068765Sobrien for (i = 0; i < from->ntmpl_args; i++) 114168765Sobrien { 114268765Sobrien int len = strlen (from->tmpl_argvec[i]) + 1; 114368765Sobrien 1144218822Sdim to->tmpl_argvec[i] = XNEWVEC (char, len); 114568765Sobrien memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); 114668765Sobrien } 114768765Sobrien 114868765Sobrien if (from->previous_argument) 114968765Sobrien { 1150218822Sdim to->previous_argument = XNEW (string); 115168765Sobrien string_init (to->previous_argument); 115268765Sobrien string_appends (to->previous_argument, from->previous_argument); 115368765Sobrien } 115468765Sobrien} 115568765Sobrien 115668765Sobrien 115768765Sobrien/* Delete dynamic stuff in work_stuff that is not to be re-used. */ 115868765Sobrien 115968765Sobrienstatic void 1160218822Sdimdelete_non_B_K_work_stuff (struct work_stuff *work) 116133965Sjdp{ 116233965Sjdp /* Discard the remembered types, if any. */ 116360484Sobrien 116433965Sjdp forget_types (work); 116533965Sjdp if (work -> typevec != NULL) 116633965Sjdp { 116733965Sjdp free ((char *) work -> typevec); 116860484Sobrien work -> typevec = NULL; 116960484Sobrien work -> typevec_size = 0; 117033965Sjdp } 117138889Sjdp if (work->tmpl_argvec) 117238889Sjdp { 117338889Sjdp int i; 117438889Sjdp 117538889Sjdp for (i = 0; i < work->ntmpl_args; i++) 117638889Sjdp if (work->tmpl_argvec[i]) 117738889Sjdp free ((char*) work->tmpl_argvec[i]); 117860484Sobrien 117938889Sjdp free ((char*) work->tmpl_argvec); 118060484Sobrien work->tmpl_argvec = NULL; 118138889Sjdp } 118260484Sobrien if (work->previous_argument) 118360484Sobrien { 118460484Sobrien string_delete (work->previous_argument); 118560484Sobrien free ((char*) work->previous_argument); 118660484Sobrien work->previous_argument = NULL; 118760484Sobrien } 118868765Sobrien} 118938889Sjdp 119068765Sobrien 119168765Sobrien/* Delete all dynamic storage in work_stuff. */ 119268765Sobrienstatic void 1193218822Sdimdelete_work_stuff (struct work_stuff *work) 119468765Sobrien{ 119568765Sobrien delete_non_B_K_work_stuff (work); 119668765Sobrien squangle_mop_up (work); 119768765Sobrien} 119868765Sobrien 119968765Sobrien 120068765Sobrien/* Clear out any mangled storage */ 120168765Sobrien 120268765Sobrienstatic char * 1203218822Sdimmop_up (struct work_stuff *work, string *declp, int success) 120468765Sobrien{ 120568765Sobrien char *demangled = NULL; 120668765Sobrien 120768765Sobrien delete_non_B_K_work_stuff (work); 120868765Sobrien 120933965Sjdp /* If demangling was successful, ensure that the demangled string is null 121033965Sjdp terminated and return it. Otherwise, free the demangling decl. */ 121160484Sobrien 121233965Sjdp if (!success) 121333965Sjdp { 121433965Sjdp string_delete (declp); 121533965Sjdp } 121633965Sjdp else 121733965Sjdp { 121833965Sjdp string_appendn (declp, "", 1); 121977298Sobrien demangled = declp->b; 122033965Sjdp } 122133965Sjdp return (demangled); 122233965Sjdp} 122333965Sjdp 122433965Sjdp/* 122533965Sjdp 122633965SjdpLOCAL FUNCTION 122733965Sjdp 122833965Sjdp demangle_signature -- demangle the signature part of a mangled name 122933965Sjdp 123033965SjdpSYNOPSIS 123133965Sjdp 123233965Sjdp static int 123333965Sjdp demangle_signature (struct work_stuff *work, const char **mangled, 123433965Sjdp string *declp); 123533965Sjdp 123633965SjdpDESCRIPTION 123733965Sjdp 123833965Sjdp Consume and demangle the signature portion of the mangled name. 123933965Sjdp 124033965Sjdp DECLP is the string where demangled output is being built. At 124133965Sjdp entry it contains the demangled root name from the mangled name 124233965Sjdp prefix. I.E. either a demangled operator name or the root function 124333965Sjdp name. In some special cases, it may contain nothing. 124433965Sjdp 124533965Sjdp *MANGLED points to the current unconsumed location in the mangled 124633965Sjdp name. As tokens are consumed and demangling is performed, the 124733965Sjdp pointer is updated to continuously point at the next token to 124833965Sjdp be consumed. 124933965Sjdp 125033965Sjdp Demangling GNU style mangled names is nasty because there is no 125133965Sjdp explicit token that marks the start of the outermost function 125233965Sjdp argument list. */ 125333965Sjdp 125433965Sjdpstatic int 1255218822Sdimdemangle_signature (struct work_stuff *work, 1256218822Sdim const char **mangled, string *declp) 125733965Sjdp{ 125833965Sjdp int success = 1; 125933965Sjdp int func_done = 0; 126033965Sjdp int expect_func = 0; 126138889Sjdp int expect_return_type = 0; 126233965Sjdp const char *oldmangled = NULL; 126333965Sjdp string trawname; 126433965Sjdp string tname; 126533965Sjdp 126633965Sjdp while (success && (**mangled != '\0')) 126733965Sjdp { 126833965Sjdp switch (**mangled) 126933965Sjdp { 127033965Sjdp case 'Q': 127133965Sjdp oldmangled = *mangled; 127233965Sjdp success = demangle_qualified (work, mangled, declp, 1, 0); 127333965Sjdp if (success) 127460484Sobrien remember_type (work, oldmangled, *mangled - oldmangled); 127533965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 127660484Sobrien expect_func = 1; 127760484Sobrien oldmangled = NULL; 127860484Sobrien break; 127960484Sobrien 128060484Sobrien case 'K': 128160484Sobrien oldmangled = *mangled; 128260484Sobrien success = demangle_qualified (work, mangled, declp, 1, 0); 128360484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 128433965Sjdp { 128533965Sjdp expect_func = 1; 128633965Sjdp } 128733965Sjdp oldmangled = NULL; 128833965Sjdp break; 128960484Sobrien 129033965Sjdp case 'S': 129133965Sjdp /* Static member function */ 129233965Sjdp if (oldmangled == NULL) 129333965Sjdp { 129433965Sjdp oldmangled = *mangled; 129533965Sjdp } 129633965Sjdp (*mangled)++; 129733965Sjdp work -> static_type = 1; 129833965Sjdp break; 129933965Sjdp 130033965Sjdp case 'C': 130160484Sobrien case 'V': 130260484Sobrien case 'u': 130360484Sobrien work->type_quals |= code_for_qualifier (**mangled); 130460484Sobrien 130560484Sobrien /* a qualified member function */ 130633965Sjdp if (oldmangled == NULL) 130760484Sobrien oldmangled = *mangled; 130860484Sobrien (*mangled)++; 130960484Sobrien break; 131060484Sobrien 131160484Sobrien case 'L': 131260484Sobrien /* Local class name follows after "Lnnn_" */ 131360484Sobrien if (HP_DEMANGLING) 131433965Sjdp { 131560484Sobrien while (**mangled && (**mangled != '_')) 131660484Sobrien (*mangled)++; 131760484Sobrien if (!**mangled) 131860484Sobrien success = 0; 131960484Sobrien else 132060484Sobrien (*mangled)++; 132133965Sjdp } 132260484Sobrien else 132360484Sobrien success = 0; 132433965Sjdp break; 132560484Sobrien 132633965Sjdp case '0': case '1': case '2': case '3': case '4': 132733965Sjdp case '5': case '6': case '7': case '8': case '9': 132833965Sjdp if (oldmangled == NULL) 132933965Sjdp { 133033965Sjdp oldmangled = *mangled; 133133965Sjdp } 133260484Sobrien work->temp_start = -1; /* uppermost call to demangle_class */ 133333965Sjdp success = demangle_class (work, mangled, declp); 133433965Sjdp if (success) 133533965Sjdp { 133633965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 133733965Sjdp } 133860484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) 133933965Sjdp { 134060484Sobrien /* EDG and others will have the "F", so we let the loop cycle 134160484Sobrien if we are looking at one. */ 134260484Sobrien if (**mangled != 'F') 134360484Sobrien expect_func = 1; 134433965Sjdp } 134533965Sjdp oldmangled = NULL; 134633965Sjdp break; 134760484Sobrien 134860484Sobrien case 'B': 134960484Sobrien { 135060484Sobrien string s; 135160484Sobrien success = do_type (work, mangled, &s); 135260484Sobrien if (success) 135360484Sobrien { 135460484Sobrien string_append (&s, SCOPE_STRING (work)); 135560484Sobrien string_prepends (declp, &s); 1356130561Sobrien string_delete (&s); 135760484Sobrien } 135860484Sobrien oldmangled = NULL; 135960484Sobrien expect_func = 1; 136060484Sobrien } 136160484Sobrien break; 136260484Sobrien 136333965Sjdp case 'F': 136433965Sjdp /* Function */ 136560484Sobrien /* ARM/HP style demangling includes a specific 'F' character after 136633965Sjdp the class name. For GNU style, it is just implied. So we can 136733965Sjdp safely just consume any 'F' at this point and be compatible 136833965Sjdp with either style. */ 136933965Sjdp 137033965Sjdp oldmangled = NULL; 137133965Sjdp func_done = 1; 137233965Sjdp (*mangled)++; 137333965Sjdp 137460484Sobrien /* For lucid/ARM/HP style we have to forget any types we might 137533965Sjdp have remembered up to this point, since they were not argument 137633965Sjdp types. GNU style considers all types seen as available for 137733965Sjdp back references. See comment in demangle_args() */ 137833965Sjdp 137960484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 138033965Sjdp { 138133965Sjdp forget_types (work); 138233965Sjdp } 138333965Sjdp success = demangle_args (work, mangled, declp); 138460484Sobrien /* After picking off the function args, we expect to either 138560484Sobrien find the function return type (preceded by an '_') or the 138660484Sobrien end of the string. */ 138760484Sobrien if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') 138860484Sobrien { 138960484Sobrien ++(*mangled); 139060484Sobrien /* At this level, we do not care about the return type. */ 139160484Sobrien success = do_type (work, mangled, &tname); 139260484Sobrien string_delete (&tname); 139360484Sobrien } 139460484Sobrien 139533965Sjdp break; 139660484Sobrien 139733965Sjdp case 't': 139833965Sjdp /* G++ Template */ 139960484Sobrien string_init(&trawname); 140033965Sjdp string_init(&tname); 140133965Sjdp if (oldmangled == NULL) 140233965Sjdp { 140333965Sjdp oldmangled = *mangled; 140433965Sjdp } 140560484Sobrien success = demangle_template (work, mangled, &tname, 140660484Sobrien &trawname, 1, 1); 140733965Sjdp if (success) 140833965Sjdp { 140933965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 141033965Sjdp } 141160484Sobrien string_append (&tname, SCOPE_STRING (work)); 141260484Sobrien 141333965Sjdp string_prepends(declp, &tname); 141433965Sjdp if (work -> destructor & 1) 141533965Sjdp { 141633965Sjdp string_prepend (&trawname, "~"); 141733965Sjdp string_appends (declp, &trawname); 141833965Sjdp work->destructor -= 1; 141933965Sjdp } 142033965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 142133965Sjdp { 142233965Sjdp string_appends (declp, &trawname); 142333965Sjdp work->constructor -= 1; 142433965Sjdp } 142533965Sjdp string_delete(&trawname); 142633965Sjdp string_delete(&tname); 142733965Sjdp oldmangled = NULL; 142833965Sjdp expect_func = 1; 142933965Sjdp break; 143033965Sjdp 143133965Sjdp case '_': 143268765Sobrien if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) 143338889Sjdp { 143438889Sjdp /* Read the return type. */ 143538889Sjdp string return_type; 143638889Sjdp 143738889Sjdp (*mangled)++; 143838889Sjdp success = do_type (work, mangled, &return_type); 143938889Sjdp APPEND_BLANK (&return_type); 144038889Sjdp 144138889Sjdp string_prepends (declp, &return_type); 144238889Sjdp string_delete (&return_type); 144338889Sjdp break; 144438889Sjdp } 144538889Sjdp else 144638889Sjdp /* At the outermost level, we cannot have a return type specified, 144738889Sjdp so if we run into another '_' at this point we are dealing with 144838889Sjdp a mangled name that is either bogus, or has been mangled by 144938889Sjdp some algorithm we don't know how to deal with. So just 145038889Sjdp reject the entire demangling. */ 145160484Sobrien /* However, "_nnn" is an expected suffix for alternate entry point 145260484Sobrien numbered nnn for a function, with HP aCC, so skip over that 145360484Sobrien without reporting failure. pai/1997-09-04 */ 145460484Sobrien if (HP_DEMANGLING) 145560484Sobrien { 145660484Sobrien (*mangled)++; 145777298Sobrien while (**mangled && ISDIGIT ((unsigned char)**mangled)) 145860484Sobrien (*mangled)++; 145960484Sobrien } 146060484Sobrien else 146160484Sobrien success = 0; 146233965Sjdp break; 146333965Sjdp 146438889Sjdp case 'H': 146568765Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 146638889Sjdp { 146738889Sjdp /* A G++ template function. Read the template arguments. */ 146860484Sobrien success = demangle_template (work, mangled, declp, 0, 0, 146960484Sobrien 0); 147038889Sjdp if (!(work->constructor & 1)) 147138889Sjdp expect_return_type = 1; 147238889Sjdp (*mangled)++; 147338889Sjdp break; 147438889Sjdp } 147538889Sjdp else 147638889Sjdp /* fall through */ 147760484Sobrien {;} 147838889Sjdp 147933965Sjdp default: 148033965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 148133965Sjdp { 148233965Sjdp /* Assume we have stumbled onto the first outermost function 148333965Sjdp argument token, and start processing args. */ 148433965Sjdp func_done = 1; 148533965Sjdp success = demangle_args (work, mangled, declp); 148633965Sjdp } 148733965Sjdp else 148833965Sjdp { 148933965Sjdp /* Non-GNU demanglers use a specific token to mark the start 149033965Sjdp of the outermost function argument tokens. Typically 'F', 149160484Sobrien for ARM/HP-demangling, for example. So if we find something 149233965Sjdp we are not prepared for, it must be an error. */ 149333965Sjdp success = 0; 149433965Sjdp } 149533965Sjdp break; 149633965Sjdp } 149733965Sjdp /* 149833965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 149933965Sjdp */ 150033965Sjdp { 150133965Sjdp if (success && expect_func) 150233965Sjdp { 150333965Sjdp func_done = 1; 150460484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) 150560484Sobrien { 150660484Sobrien forget_types (work); 150760484Sobrien } 150833965Sjdp success = demangle_args (work, mangled, declp); 150938889Sjdp /* Since template include the mangling of their return types, 151038889Sjdp we must set expect_func to 0 so that we don't try do 151138889Sjdp demangle more arguments the next time we get here. */ 151238889Sjdp expect_func = 0; 151333965Sjdp } 151433965Sjdp } 151533965Sjdp } 151633965Sjdp if (success && !func_done) 151733965Sjdp { 151833965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 151933965Sjdp { 152033965Sjdp /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and 152133965Sjdp bar__3fooi is 'foo::bar(int)'. We get here when we find the 152233965Sjdp first case, and need to ensure that the '(void)' gets added to 152360484Sobrien the current declp. Note that with ARM/HP, the first case 152433965Sjdp represents the name of a static data member 'foo::bar', 152533965Sjdp which is in the current declp, so we leave it alone. */ 152633965Sjdp success = demangle_args (work, mangled, declp); 152733965Sjdp } 152833965Sjdp } 152960484Sobrien if (success && PRINT_ARG_TYPES) 153033965Sjdp { 153160484Sobrien if (work->static_type) 153260484Sobrien string_append (declp, " static"); 153360484Sobrien if (work->type_quals != TYPE_UNQUALIFIED) 153460484Sobrien { 153560484Sobrien APPEND_BLANK (declp); 153660484Sobrien string_append (declp, qualifier_string (work->type_quals)); 153760484Sobrien } 153833965Sjdp } 153960484Sobrien 154033965Sjdp return (success); 154133965Sjdp} 154233965Sjdp 154333965Sjdp#if 0 154433965Sjdp 154533965Sjdpstatic int 1546218822Sdimdemangle_method_args (struct work_stuff *work, const char **mangled, 1547218822Sdim string *declp) 154833965Sjdp{ 154933965Sjdp int success = 0; 155033965Sjdp 155133965Sjdp if (work -> static_type) 155233965Sjdp { 155333965Sjdp string_append (declp, *mangled + 1); 155433965Sjdp *mangled += strlen (*mangled); 155533965Sjdp success = 1; 155633965Sjdp } 155733965Sjdp else 155833965Sjdp { 155933965Sjdp success = demangle_args (work, mangled, declp); 156033965Sjdp } 156133965Sjdp return (success); 156233965Sjdp} 156333965Sjdp 156433965Sjdp#endif 156533965Sjdp 156633965Sjdpstatic int 1567218822Sdimdemangle_template_template_parm (struct work_stuff *work, 1568218822Sdim const char **mangled, string *tname) 156960484Sobrien{ 157060484Sobrien int i; 157160484Sobrien int r; 157260484Sobrien int need_comma = 0; 157360484Sobrien int success = 1; 157460484Sobrien string temp; 157560484Sobrien 157660484Sobrien string_append (tname, "template <"); 157760484Sobrien /* get size of template parameter list */ 157860484Sobrien if (get_count (mangled, &r)) 157960484Sobrien { 158060484Sobrien for (i = 0; i < r; i++) 158160484Sobrien { 158260484Sobrien if (need_comma) 158360484Sobrien { 158460484Sobrien string_append (tname, ", "); 158560484Sobrien } 158660484Sobrien 158760484Sobrien /* Z for type parameters */ 158860484Sobrien if (**mangled == 'Z') 158960484Sobrien { 159060484Sobrien (*mangled)++; 159160484Sobrien string_append (tname, "class"); 159260484Sobrien } 159360484Sobrien /* z for template parameters */ 159460484Sobrien else if (**mangled == 'z') 159560484Sobrien { 159660484Sobrien (*mangled)++; 159760484Sobrien success = 159860484Sobrien demangle_template_template_parm (work, mangled, tname); 159960484Sobrien if (!success) 160060484Sobrien { 160160484Sobrien break; 160260484Sobrien } 160360484Sobrien } 160460484Sobrien else 160560484Sobrien { 160660484Sobrien /* temp is initialized in do_type */ 160760484Sobrien success = do_type (work, mangled, &temp); 160860484Sobrien if (success) 160960484Sobrien { 161060484Sobrien string_appends (tname, &temp); 161160484Sobrien } 161260484Sobrien string_delete(&temp); 161360484Sobrien if (!success) 161460484Sobrien { 161560484Sobrien break; 161660484Sobrien } 161760484Sobrien } 161860484Sobrien need_comma = 1; 161960484Sobrien } 162060484Sobrien 162160484Sobrien } 162260484Sobrien if (tname->p[-1] == '>') 162360484Sobrien string_append (tname, " "); 162460484Sobrien string_append (tname, "> class"); 162560484Sobrien return (success); 162660484Sobrien} 162760484Sobrien 162860484Sobrienstatic int 1629218822Sdimdemangle_expression (struct work_stuff *work, const char **mangled, 1630218822Sdim string *s, type_kind_t tk) 163160484Sobrien{ 163260484Sobrien int need_operator = 0; 163360484Sobrien int success; 163460484Sobrien 163560484Sobrien success = 1; 163660484Sobrien string_appendn (s, "(", 1); 163760484Sobrien (*mangled)++; 163860484Sobrien while (success && **mangled != 'W' && **mangled != '\0') 163960484Sobrien { 164060484Sobrien if (need_operator) 164160484Sobrien { 164260484Sobrien size_t i; 164360484Sobrien size_t len; 164460484Sobrien 164560484Sobrien success = 0; 164660484Sobrien 164760484Sobrien len = strlen (*mangled); 164860484Sobrien 164977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); ++i) 165060484Sobrien { 165160484Sobrien size_t l = strlen (optable[i].in); 165260484Sobrien 165360484Sobrien if (l <= len 165460484Sobrien && memcmp (optable[i].in, *mangled, l) == 0) 165560484Sobrien { 165660484Sobrien string_appendn (s, " ", 1); 165760484Sobrien string_append (s, optable[i].out); 165860484Sobrien string_appendn (s, " ", 1); 165960484Sobrien success = 1; 166060484Sobrien (*mangled) += l; 166160484Sobrien break; 166260484Sobrien } 166360484Sobrien } 166460484Sobrien 166560484Sobrien if (!success) 166660484Sobrien break; 166760484Sobrien } 166860484Sobrien else 166960484Sobrien need_operator = 1; 167060484Sobrien 167160484Sobrien success = demangle_template_value_parm (work, mangled, s, tk); 167260484Sobrien } 167360484Sobrien 167460484Sobrien if (**mangled != 'W') 167560484Sobrien success = 0; 167660484Sobrien else 167760484Sobrien { 167860484Sobrien string_appendn (s, ")", 1); 167960484Sobrien (*mangled)++; 168060484Sobrien } 168160484Sobrien 168260484Sobrien return success; 168360484Sobrien} 168460484Sobrien 168560484Sobrienstatic int 1686218822Sdimdemangle_integral_value (struct work_stuff *work, 1687218822Sdim const char **mangled, string *s) 168860484Sobrien{ 168960484Sobrien int success; 169060484Sobrien 169160484Sobrien if (**mangled == 'E') 169260484Sobrien success = demangle_expression (work, mangled, s, tk_integral); 169360484Sobrien else if (**mangled == 'Q' || **mangled == 'K') 169460484Sobrien success = demangle_qualified (work, mangled, s, 0, 1); 169560484Sobrien else 169660484Sobrien { 169760484Sobrien int value; 169860484Sobrien 169968765Sobrien /* By default, we let the number decide whether we shall consume an 170068765Sobrien underscore. */ 1701104834Sobrien int multidigit_without_leading_underscore = 0; 170268765Sobrien int leave_following_underscore = 0; 170368765Sobrien 170460484Sobrien success = 0; 170560484Sobrien 1706130561Sobrien if (**mangled == '_') 1707130561Sobrien { 1708130561Sobrien if (mangled[0][1] == 'm') 1709130561Sobrien { 1710130561Sobrien /* Since consume_count_with_underscores does not handle the 1711130561Sobrien `m'-prefix we must do it here, using consume_count and 1712130561Sobrien adjusting underscores: we have to consume the underscore 1713130561Sobrien matching the prepended one. */ 1714130561Sobrien multidigit_without_leading_underscore = 1; 1715130561Sobrien string_appendn (s, "-", 1); 1716130561Sobrien (*mangled) += 2; 1717130561Sobrien } 1718130561Sobrien else 1719130561Sobrien { 1720130561Sobrien /* Do not consume a following underscore; 1721130561Sobrien consume_count_with_underscores will consume what 1722130561Sobrien should be consumed. */ 1723130561Sobrien leave_following_underscore = 1; 1724130561Sobrien } 172560484Sobrien } 1726104834Sobrien else 1727104834Sobrien { 1728130561Sobrien /* Negative numbers are indicated with a leading `m'. */ 1729130561Sobrien if (**mangled == 'm') 1730130561Sobrien { 1731130561Sobrien string_appendn (s, "-", 1); 1732130561Sobrien (*mangled)++; 1733130561Sobrien } 1734104834Sobrien /* Since consume_count_with_underscores does not handle 1735104834Sobrien multi-digit numbers that do not start with an underscore, 1736104834Sobrien and this number can be an integer template parameter, 1737104834Sobrien we have to call consume_count. */ 1738104834Sobrien multidigit_without_leading_underscore = 1; 1739104834Sobrien /* These multi-digit numbers never end on an underscore, 1740104834Sobrien so if there is one then don't eat it. */ 1741104834Sobrien leave_following_underscore = 1; 1742104834Sobrien } 174360484Sobrien 174468765Sobrien /* We must call consume_count if we expect to remove a trailing 174568765Sobrien underscore, since consume_count_with_underscores expects 174668765Sobrien the leading underscore (that we consumed) if it is to handle 174768765Sobrien multi-digit numbers. */ 1748104834Sobrien if (multidigit_without_leading_underscore) 174968765Sobrien value = consume_count (mangled); 175068765Sobrien else 175168765Sobrien value = consume_count_with_underscores (mangled); 175268765Sobrien 175360484Sobrien if (value != -1) 175460484Sobrien { 175560484Sobrien char buf[INTBUF_SIZE]; 175660484Sobrien sprintf (buf, "%d", value); 175760484Sobrien string_append (s, buf); 175860484Sobrien 175968765Sobrien /* Numbers not otherwise delimited, might have an underscore 176068765Sobrien appended as a delimeter, which we should skip. 176168765Sobrien 176268765Sobrien ??? This used to always remove a following underscore, which 176368765Sobrien is wrong. If other (arbitrary) cases are followed by an 176468765Sobrien underscore, we need to do something more radical. */ 176568765Sobrien 1766104834Sobrien if ((value > 9 || multidigit_without_leading_underscore) 176768765Sobrien && ! leave_following_underscore 176868765Sobrien && **mangled == '_') 176960484Sobrien (*mangled)++; 177060484Sobrien 177160484Sobrien /* All is well. */ 177260484Sobrien success = 1; 177360484Sobrien } 1774130561Sobrien } 177560484Sobrien 177660484Sobrien return success; 177760484Sobrien} 177860484Sobrien 177960484Sobrien/* Demangle the real value in MANGLED. */ 178060484Sobrien 178160484Sobrienstatic int 1782218822Sdimdemangle_real_value (struct work_stuff *work, 1783218822Sdim const char **mangled, string *s) 178460484Sobrien{ 178560484Sobrien if (**mangled == 'E') 178660484Sobrien return demangle_expression (work, mangled, s, tk_real); 178760484Sobrien 178860484Sobrien if (**mangled == 'm') 178960484Sobrien { 179060484Sobrien string_appendn (s, "-", 1); 179160484Sobrien (*mangled)++; 179260484Sobrien } 179377298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 179460484Sobrien { 179560484Sobrien string_appendn (s, *mangled, 1); 179660484Sobrien (*mangled)++; 179760484Sobrien } 179860484Sobrien if (**mangled == '.') /* fraction */ 179960484Sobrien { 180060484Sobrien string_appendn (s, ".", 1); 180160484Sobrien (*mangled)++; 180277298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 180360484Sobrien { 180460484Sobrien string_appendn (s, *mangled, 1); 180560484Sobrien (*mangled)++; 180660484Sobrien } 180760484Sobrien } 180860484Sobrien if (**mangled == 'e') /* exponent */ 180960484Sobrien { 181060484Sobrien string_appendn (s, "e", 1); 181160484Sobrien (*mangled)++; 181277298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 181360484Sobrien { 181460484Sobrien string_appendn (s, *mangled, 1); 181560484Sobrien (*mangled)++; 181660484Sobrien } 181760484Sobrien } 181860484Sobrien 181960484Sobrien return 1; 182060484Sobrien} 182160484Sobrien 182260484Sobrienstatic int 1823218822Sdimdemangle_template_value_parm (struct work_stuff *work, const char **mangled, 1824218822Sdim string *s, type_kind_t tk) 182560484Sobrien{ 182660484Sobrien int success = 1; 182760484Sobrien 182860484Sobrien if (**mangled == 'Y') 182960484Sobrien { 183060484Sobrien /* The next argument is a template parameter. */ 183160484Sobrien int idx; 183260484Sobrien 183360484Sobrien (*mangled)++; 183460484Sobrien idx = consume_count_with_underscores (mangled); 183560484Sobrien if (idx == -1 183660484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 183760484Sobrien || consume_count_with_underscores (mangled) == -1) 183860484Sobrien return -1; 183960484Sobrien if (work->tmpl_argvec) 184060484Sobrien string_append (s, work->tmpl_argvec[idx]); 184160484Sobrien else 184260484Sobrien string_append_template_idx (s, idx); 184360484Sobrien } 184460484Sobrien else if (tk == tk_integral) 184560484Sobrien success = demangle_integral_value (work, mangled, s); 184660484Sobrien else if (tk == tk_char) 184760484Sobrien { 184860484Sobrien char tmp[2]; 184960484Sobrien int val; 185060484Sobrien if (**mangled == 'm') 185160484Sobrien { 185260484Sobrien string_appendn (s, "-", 1); 185360484Sobrien (*mangled)++; 185460484Sobrien } 185560484Sobrien string_appendn (s, "'", 1); 185660484Sobrien val = consume_count(mangled); 185760484Sobrien if (val <= 0) 185860484Sobrien success = 0; 185960484Sobrien else 186060484Sobrien { 186160484Sobrien tmp[0] = (char)val; 186260484Sobrien tmp[1] = '\0'; 186360484Sobrien string_appendn (s, &tmp[0], 1); 186460484Sobrien string_appendn (s, "'", 1); 186560484Sobrien } 186660484Sobrien } 186760484Sobrien else if (tk == tk_bool) 186860484Sobrien { 186960484Sobrien int val = consume_count (mangled); 187060484Sobrien if (val == 0) 187160484Sobrien string_appendn (s, "false", 5); 187260484Sobrien else if (val == 1) 187360484Sobrien string_appendn (s, "true", 4); 187460484Sobrien else 187560484Sobrien success = 0; 187660484Sobrien } 187760484Sobrien else if (tk == tk_real) 187860484Sobrien success = demangle_real_value (work, mangled, s); 187960484Sobrien else if (tk == tk_pointer || tk == tk_reference) 188060484Sobrien { 188160484Sobrien if (**mangled == 'Q') 188260484Sobrien success = demangle_qualified (work, mangled, s, 188360484Sobrien /*isfuncname=*/0, 188460484Sobrien /*append=*/1); 188560484Sobrien else 188660484Sobrien { 188760484Sobrien int symbol_len = consume_count (mangled); 188860484Sobrien if (symbol_len == -1) 188960484Sobrien return -1; 189060484Sobrien if (symbol_len == 0) 189160484Sobrien string_appendn (s, "0", 1); 189260484Sobrien else 189360484Sobrien { 1894218822Sdim char *p = XNEWVEC (char, symbol_len + 1), *q; 189560484Sobrien strncpy (p, *mangled, symbol_len); 189660484Sobrien p [symbol_len] = '\0'; 189760484Sobrien /* We use cplus_demangle here, rather than 189860484Sobrien internal_cplus_demangle, because the name of the entity 189960484Sobrien mangled here does not make use of any of the squangling 190060484Sobrien or type-code information we have built up thus far; it is 190160484Sobrien mangled independently. */ 190260484Sobrien q = cplus_demangle (p, work->options); 190360484Sobrien if (tk == tk_pointer) 190460484Sobrien string_appendn (s, "&", 1); 190560484Sobrien /* FIXME: Pointer-to-member constants should get a 190660484Sobrien qualifying class name here. */ 190760484Sobrien if (q) 190860484Sobrien { 190960484Sobrien string_append (s, q); 191060484Sobrien free (q); 191160484Sobrien } 191260484Sobrien else 191360484Sobrien string_append (s, p); 191460484Sobrien free (p); 191560484Sobrien } 191660484Sobrien *mangled += symbol_len; 191760484Sobrien } 191860484Sobrien } 191960484Sobrien 192060484Sobrien return success; 192160484Sobrien} 192260484Sobrien 192360484Sobrien/* Demangle the template name in MANGLED. The full name of the 192460484Sobrien template (e.g., S<int>) is placed in TNAME. The name without the 192560484Sobrien template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is 192660484Sobrien non-NULL. If IS_TYPE is nonzero, this template is a type template, 192760484Sobrien not a function template. If both IS_TYPE and REMEMBER are nonzero, 192868765Sobrien the template is remembered in the list of back-referenceable 192960484Sobrien types. */ 193060484Sobrien 193160484Sobrienstatic int 1932218822Sdimdemangle_template (struct work_stuff *work, const char **mangled, 1933218822Sdim string *tname, string *trawname, 1934218822Sdim int is_type, int remember) 193533965Sjdp{ 193633965Sjdp int i; 193733965Sjdp int r; 193833965Sjdp int need_comma = 0; 193933965Sjdp int success = 0; 194038889Sjdp int is_java_array = 0; 194133965Sjdp string temp; 194233965Sjdp 194333965Sjdp (*mangled)++; 194438889Sjdp if (is_type) 194533965Sjdp { 194638889Sjdp /* get template name */ 194760484Sobrien if (**mangled == 'z') 194838889Sjdp { 194960484Sobrien int idx; 195060484Sobrien (*mangled)++; 195160484Sobrien (*mangled)++; 195260484Sobrien 195360484Sobrien idx = consume_count_with_underscores (mangled); 195460484Sobrien if (idx == -1 195560484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 195660484Sobrien || consume_count_with_underscores (mangled) == -1) 195760484Sobrien return (0); 195860484Sobrien 195960484Sobrien if (work->tmpl_argvec) 196060484Sobrien { 196160484Sobrien string_append (tname, work->tmpl_argvec[idx]); 196260484Sobrien if (trawname) 196360484Sobrien string_append (trawname, work->tmpl_argvec[idx]); 196460484Sobrien } 196560484Sobrien else 196660484Sobrien { 196760484Sobrien string_append_template_idx (tname, idx); 196860484Sobrien if (trawname) 196960484Sobrien string_append_template_idx (trawname, idx); 197060484Sobrien } 197138889Sjdp } 197260484Sobrien else 197338889Sjdp { 197460484Sobrien if ((r = consume_count (mangled)) <= 0 197560484Sobrien || (int) strlen (*mangled) < r) 197660484Sobrien { 197760484Sobrien return (0); 197860484Sobrien } 197960484Sobrien is_java_array = (work -> options & DMGL_JAVA) 198060484Sobrien && strncmp (*mangled, "JArray1Z", 8) == 0; 198160484Sobrien if (! is_java_array) 198260484Sobrien { 198360484Sobrien string_appendn (tname, *mangled, r); 198460484Sobrien } 198560484Sobrien if (trawname) 198660484Sobrien string_appendn (trawname, *mangled, r); 198760484Sobrien *mangled += r; 198838889Sjdp } 198933965Sjdp } 199038889Sjdp if (!is_java_array) 199138889Sjdp string_append (tname, "<"); 199233965Sjdp /* get size of template parameter list */ 199333965Sjdp if (!get_count (mangled, &r)) 199433965Sjdp { 199533965Sjdp return (0); 199633965Sjdp } 199738889Sjdp if (!is_type) 199838889Sjdp { 199938889Sjdp /* Create an array for saving the template argument values. */ 2000218822Sdim work->tmpl_argvec = XNEWVEC (char *, r); 200138889Sjdp work->ntmpl_args = r; 200238889Sjdp for (i = 0; i < r; i++) 200338889Sjdp work->tmpl_argvec[i] = 0; 200438889Sjdp } 200533965Sjdp for (i = 0; i < r; i++) 200633965Sjdp { 200733965Sjdp if (need_comma) 200833965Sjdp { 200933965Sjdp string_append (tname, ", "); 201033965Sjdp } 201133965Sjdp /* Z for type parameters */ 201233965Sjdp if (**mangled == 'Z') 201333965Sjdp { 201433965Sjdp (*mangled)++; 201533965Sjdp /* temp is initialized in do_type */ 201633965Sjdp success = do_type (work, mangled, &temp); 201733965Sjdp if (success) 201833965Sjdp { 201933965Sjdp string_appends (tname, &temp); 202038889Sjdp 202138889Sjdp if (!is_type) 202238889Sjdp { 202338889Sjdp /* Save the template argument. */ 202438889Sjdp int len = temp.p - temp.b; 2025218822Sdim work->tmpl_argvec[i] = XNEWVEC (char, len + 1); 202638889Sjdp memcpy (work->tmpl_argvec[i], temp.b, len); 202738889Sjdp work->tmpl_argvec[i][len] = '\0'; 202838889Sjdp } 202933965Sjdp } 203033965Sjdp string_delete(&temp); 203133965Sjdp if (!success) 203233965Sjdp { 203333965Sjdp break; 203433965Sjdp } 203533965Sjdp } 203660484Sobrien /* z for template parameters */ 203760484Sobrien else if (**mangled == 'z') 203860484Sobrien { 203960484Sobrien int r2; 204060484Sobrien (*mangled)++; 204160484Sobrien success = demangle_template_template_parm (work, mangled, tname); 204260484Sobrien 204360484Sobrien if (success 204460484Sobrien && (r2 = consume_count (mangled)) > 0 204560484Sobrien && (int) strlen (*mangled) >= r2) 204660484Sobrien { 204760484Sobrien string_append (tname, " "); 204860484Sobrien string_appendn (tname, *mangled, r2); 204960484Sobrien if (!is_type) 205060484Sobrien { 205160484Sobrien /* Save the template argument. */ 205260484Sobrien int len = r2; 2053218822Sdim work->tmpl_argvec[i] = XNEWVEC (char, len + 1); 205460484Sobrien memcpy (work->tmpl_argvec[i], *mangled, len); 205560484Sobrien work->tmpl_argvec[i][len] = '\0'; 205660484Sobrien } 205760484Sobrien *mangled += r2; 205860484Sobrien } 205960484Sobrien if (!success) 206060484Sobrien { 206160484Sobrien break; 206260484Sobrien } 206360484Sobrien } 206433965Sjdp else 206533965Sjdp { 206638889Sjdp string param; 206738889Sjdp string* s; 206838889Sjdp 206933965Sjdp /* otherwise, value parameter */ 207060484Sobrien 207133965Sjdp /* temp is initialized in do_type */ 207233965Sjdp success = do_type (work, mangled, &temp); 207333965Sjdp string_delete(&temp); 207433965Sjdp if (!success) 207560484Sobrien break; 207638889Sjdp 207738889Sjdp if (!is_type) 207838889Sjdp { 207938889Sjdp s = ¶m; 208038889Sjdp string_init (s); 208138889Sjdp } 208238889Sjdp else 208338889Sjdp s = tname; 208438889Sjdp 208560484Sobrien success = demangle_template_value_parm (work, mangled, s, 208660484Sobrien (type_kind_t) success); 208738889Sjdp 208860484Sobrien if (!success) 208938889Sjdp { 209060484Sobrien if (!is_type) 209160484Sobrien string_delete (s); 209260484Sobrien success = 0; 209360484Sobrien break; 209433965Sjdp } 209560484Sobrien 209638889Sjdp if (!is_type) 209738889Sjdp { 209838889Sjdp int len = s->p - s->b; 2099218822Sdim work->tmpl_argvec[i] = XNEWVEC (char, len + 1); 210038889Sjdp memcpy (work->tmpl_argvec[i], s->b, len); 210138889Sjdp work->tmpl_argvec[i][len] = '\0'; 210260484Sobrien 210338889Sjdp string_appends (tname, s); 210438889Sjdp string_delete (s); 210538889Sjdp } 210633965Sjdp } 210733965Sjdp need_comma = 1; 210833965Sjdp } 210938889Sjdp if (is_java_array) 211038889Sjdp { 211138889Sjdp string_append (tname, "[]"); 211238889Sjdp } 211338889Sjdp else 211438889Sjdp { 211538889Sjdp if (tname->p[-1] == '>') 211638889Sjdp string_append (tname, " "); 211738889Sjdp string_append (tname, ">"); 211838889Sjdp } 211960484Sobrien 212060484Sobrien if (is_type && remember) 2121130561Sobrien { 2122130561Sobrien const int bindex = register_Btype (work); 2123130561Sobrien remember_Btype (work, tname->b, LEN_STRING (tname), bindex); 2124130561Sobrien } 212560484Sobrien 212633965Sjdp /* 212733965Sjdp if (work -> static_type) 212833965Sjdp { 212933965Sjdp string_append (declp, *mangled + 1); 213033965Sjdp *mangled += strlen (*mangled); 213133965Sjdp success = 1; 213233965Sjdp } 213333965Sjdp else 213433965Sjdp { 213533965Sjdp success = demangle_args (work, mangled, declp); 213633965Sjdp } 213733965Sjdp } 213833965Sjdp */ 213933965Sjdp return (success); 214033965Sjdp} 214133965Sjdp 214233965Sjdpstatic int 2143218822Sdimarm_pt (struct work_stuff *work, const char *mangled, 2144218822Sdim int n, const char **anchor, const char **args) 214533965Sjdp{ 214660484Sobrien /* Check if ARM template with "__pt__" in it ("parameterized type") */ 214760484Sobrien /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ 214889857Sobrien if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) 214933965Sjdp { 215033965Sjdp int len; 215133965Sjdp *args = *anchor + 6; 215233965Sjdp len = consume_count (args); 215360484Sobrien if (len == -1) 215460484Sobrien return 0; 215533965Sjdp if (*args + len == mangled + n && **args == '_') 215633965Sjdp { 215733965Sjdp ++*args; 215833965Sjdp return 1; 215933965Sjdp } 216033965Sjdp } 216160484Sobrien if (AUTO_DEMANGLING || EDG_DEMANGLING) 216260484Sobrien { 216389857Sobrien if ((*anchor = strstr (mangled, "__tm__")) 216489857Sobrien || (*anchor = strstr (mangled, "__ps__")) 216589857Sobrien || (*anchor = strstr (mangled, "__pt__"))) 216660484Sobrien { 216760484Sobrien int len; 216860484Sobrien *args = *anchor + 6; 216960484Sobrien len = consume_count (args); 217060484Sobrien if (len == -1) 217160484Sobrien return 0; 217260484Sobrien if (*args + len == mangled + n && **args == '_') 217360484Sobrien { 217460484Sobrien ++*args; 217560484Sobrien return 1; 217660484Sobrien } 217760484Sobrien } 217889857Sobrien else if ((*anchor = strstr (mangled, "__S"))) 217960484Sobrien { 218060484Sobrien int len; 218160484Sobrien *args = *anchor + 3; 218260484Sobrien len = consume_count (args); 218360484Sobrien if (len == -1) 218460484Sobrien return 0; 218560484Sobrien if (*args + len == mangled + n && **args == '_') 218660484Sobrien { 218760484Sobrien ++*args; 218860484Sobrien return 1; 218960484Sobrien } 219060484Sobrien } 219160484Sobrien } 219260484Sobrien 219333965Sjdp return 0; 219433965Sjdp} 219533965Sjdp 219633965Sjdpstatic void 2197218822Sdimdemangle_arm_hp_template (struct work_stuff *work, const char **mangled, 2198218822Sdim int n, string *declp) 219933965Sjdp{ 220033965Sjdp const char *p; 220133965Sjdp const char *args; 220233965Sjdp const char *e = *mangled + n; 220360484Sobrien string arg; 220433965Sjdp 220560484Sobrien /* Check for HP aCC template spec: classXt1t2 where t1, t2 are 220660484Sobrien template args */ 220760484Sobrien if (HP_DEMANGLING && ((*mangled)[n] == 'X')) 220833965Sjdp { 220960484Sobrien char *start_spec_args = NULL; 2210130561Sobrien int hold_options; 221160484Sobrien 221260484Sobrien /* First check for and omit template specialization pseudo-arguments, 221360484Sobrien such as in "Spec<#1,#1.*>" */ 221460484Sobrien start_spec_args = strchr (*mangled, '<'); 221560484Sobrien if (start_spec_args && (start_spec_args - *mangled < n)) 221660484Sobrien string_appendn (declp, *mangled, start_spec_args - *mangled); 221760484Sobrien else 221860484Sobrien string_appendn (declp, *mangled, n); 221960484Sobrien (*mangled) += n + 1; 222033965Sjdp string_init (&arg); 222160484Sobrien if (work->temp_start == -1) /* non-recursive call */ 222260484Sobrien work->temp_start = declp->p - declp->b; 2223130561Sobrien 2224130561Sobrien /* We want to unconditionally demangle parameter types in 2225130561Sobrien template parameters. */ 2226130561Sobrien hold_options = work->options; 2227130561Sobrien work->options |= DMGL_PARAMS; 2228130561Sobrien 222960484Sobrien string_append (declp, "<"); 223060484Sobrien while (1) 223160484Sobrien { 2232130561Sobrien string_delete (&arg); 223360484Sobrien switch (**mangled) 223460484Sobrien { 223560484Sobrien case 'T': 223660484Sobrien /* 'T' signals a type parameter */ 223760484Sobrien (*mangled)++; 223860484Sobrien if (!do_type (work, mangled, &arg)) 223960484Sobrien goto hpacc_template_args_done; 224060484Sobrien break; 224160484Sobrien 224260484Sobrien case 'U': 224360484Sobrien case 'S': 224460484Sobrien /* 'U' or 'S' signals an integral value */ 224560484Sobrien if (!do_hpacc_template_const_value (work, mangled, &arg)) 224660484Sobrien goto hpacc_template_args_done; 224760484Sobrien break; 224860484Sobrien 224960484Sobrien case 'A': 225060484Sobrien /* 'A' signals a named constant expression (literal) */ 225160484Sobrien if (!do_hpacc_template_literal (work, mangled, &arg)) 225260484Sobrien goto hpacc_template_args_done; 225360484Sobrien break; 225460484Sobrien 225560484Sobrien default: 225660484Sobrien /* Today, 1997-09-03, we have only the above types 225760484Sobrien of template parameters */ 225860484Sobrien /* FIXME: maybe this should fail and return null */ 225960484Sobrien goto hpacc_template_args_done; 226060484Sobrien } 226160484Sobrien string_appends (declp, &arg); 226260484Sobrien /* Check if we're at the end of template args. 226360484Sobrien 0 if at end of static member of template class, 226460484Sobrien _ if done with template args for a function */ 226560484Sobrien if ((**mangled == '\000') || (**mangled == '_')) 226660484Sobrien break; 226760484Sobrien else 226860484Sobrien string_append (declp, ","); 226960484Sobrien } 227060484Sobrien hpacc_template_args_done: 227160484Sobrien string_append (declp, ">"); 227260484Sobrien string_delete (&arg); 227360484Sobrien if (**mangled == '_') 227460484Sobrien (*mangled)++; 2275130561Sobrien work->options = hold_options; 227660484Sobrien return; 227760484Sobrien } 227860484Sobrien /* ARM template? (Also handles HP cfront extensions) */ 227960484Sobrien else if (arm_pt (work, *mangled, n, &p, &args)) 228060484Sobrien { 2281130561Sobrien int hold_options; 228260484Sobrien string type_str; 228360484Sobrien 228460484Sobrien string_init (&arg); 228533965Sjdp string_appendn (declp, *mangled, p - *mangled); 228660484Sobrien if (work->temp_start == -1) /* non-recursive call */ 228760484Sobrien work->temp_start = declp->p - declp->b; 2288130561Sobrien 2289130561Sobrien /* We want to unconditionally demangle parameter types in 2290130561Sobrien template parameters. */ 2291130561Sobrien hold_options = work->options; 2292130561Sobrien work->options |= DMGL_PARAMS; 2293130561Sobrien 229433965Sjdp string_append (declp, "<"); 229533965Sjdp /* should do error checking here */ 229633965Sjdp while (args < e) { 2297130561Sobrien string_delete (&arg); 229860484Sobrien 229960484Sobrien /* Check for type or literal here */ 230060484Sobrien switch (*args) 230160484Sobrien { 230260484Sobrien /* HP cfront extensions to ARM for template args */ 230360484Sobrien /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ 230460484Sobrien /* FIXME: We handle only numeric literals for HP cfront */ 230560484Sobrien case 'X': 230660484Sobrien /* A typed constant value follows */ 230760484Sobrien args++; 230860484Sobrien if (!do_type (work, &args, &type_str)) 230960484Sobrien goto cfront_template_args_done; 231060484Sobrien string_append (&arg, "("); 231160484Sobrien string_appends (&arg, &type_str); 2312130561Sobrien string_delete (&type_str); 231360484Sobrien string_append (&arg, ")"); 231460484Sobrien if (*args != 'L') 231560484Sobrien goto cfront_template_args_done; 231660484Sobrien args++; 231760484Sobrien /* Now snarf a literal value following 'L' */ 231860484Sobrien if (!snarf_numeric_literal (&args, &arg)) 231960484Sobrien goto cfront_template_args_done; 232060484Sobrien break; 232160484Sobrien 232260484Sobrien case 'L': 232360484Sobrien /* Snarf a literal following 'L' */ 232460484Sobrien args++; 232560484Sobrien if (!snarf_numeric_literal (&args, &arg)) 232660484Sobrien goto cfront_template_args_done; 232760484Sobrien break; 232860484Sobrien default: 232960484Sobrien /* Not handling other HP cfront stuff */ 2330104834Sobrien { 2331104834Sobrien const char* old_args = args; 2332104834Sobrien if (!do_type (work, &args, &arg)) 2333104834Sobrien goto cfront_template_args_done; 2334104834Sobrien 2335104834Sobrien /* Fail if we didn't make any progress: prevent infinite loop. */ 2336104834Sobrien if (args == old_args) 2337130561Sobrien { 2338130561Sobrien work->options = hold_options; 2339130561Sobrien return; 2340130561Sobrien } 2341104834Sobrien } 234260484Sobrien } 234333965Sjdp string_appends (declp, &arg); 234433965Sjdp string_append (declp, ","); 234533965Sjdp } 234660484Sobrien cfront_template_args_done: 234733965Sjdp string_delete (&arg); 234860484Sobrien if (args >= e) 234960484Sobrien --declp->p; /* remove extra comma */ 235033965Sjdp string_append (declp, ">"); 2351130561Sobrien work->options = hold_options; 235233965Sjdp } 235360484Sobrien else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 235460484Sobrien && (*mangled)[9] == 'N' 235560484Sobrien && (*mangled)[8] == (*mangled)[10] 235660484Sobrien && strchr (cplus_markers, (*mangled)[8])) 235760484Sobrien { 235860484Sobrien /* A member of the anonymous namespace. */ 235960484Sobrien string_append (declp, "{anonymous}"); 236060484Sobrien } 236133965Sjdp else 236233965Sjdp { 236360484Sobrien if (work->temp_start == -1) /* non-recursive call only */ 236460484Sobrien work->temp_start = 0; /* disable in recursive calls */ 236533965Sjdp string_appendn (declp, *mangled, n); 236633965Sjdp } 236733965Sjdp *mangled += n; 236833965Sjdp} 236933965Sjdp 237060484Sobrien/* Extract a class name, possibly a template with arguments, from the 237160484Sobrien mangled string; qualifiers, local class indicators, etc. have 237260484Sobrien already been dealt with */ 237360484Sobrien 237433965Sjdpstatic int 2375218822Sdimdemangle_class_name (struct work_stuff *work, const char **mangled, 2376218822Sdim string *declp) 237733965Sjdp{ 237833965Sjdp int n; 237933965Sjdp int success = 0; 238033965Sjdp 238133965Sjdp n = consume_count (mangled); 238260484Sobrien if (n == -1) 238360484Sobrien return 0; 238460484Sobrien if ((int) strlen (*mangled) >= n) 238533965Sjdp { 238660484Sobrien demangle_arm_hp_template (work, mangled, n, declp); 238733965Sjdp success = 1; 238833965Sjdp } 238933965Sjdp 239033965Sjdp return (success); 239133965Sjdp} 239233965Sjdp 239333965Sjdp/* 239433965Sjdp 239533965SjdpLOCAL FUNCTION 239633965Sjdp 239733965Sjdp demangle_class -- demangle a mangled class sequence 239833965Sjdp 239933965SjdpSYNOPSIS 240033965Sjdp 240133965Sjdp static int 240233965Sjdp demangle_class (struct work_stuff *work, const char **mangled, 240333965Sjdp strint *declp) 240433965Sjdp 240533965SjdpDESCRIPTION 240633965Sjdp 240733965Sjdp DECLP points to the buffer into which demangling is being done. 240833965Sjdp 240933965Sjdp *MANGLED points to the current token to be demangled. On input, 241033965Sjdp it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) 241133965Sjdp On exit, it points to the next token after the mangled class on 241233965Sjdp success, or the first unconsumed token on failure. 241333965Sjdp 241433965Sjdp If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then 241533965Sjdp we are demangling a constructor or destructor. In this case 241633965Sjdp we prepend "class::class" or "class::~class" to DECLP. 241733965Sjdp 241833965Sjdp Otherwise, we prepend "class::" to the current DECLP. 241933965Sjdp 242033965Sjdp Reset the constructor/destructor flags once they have been 242133965Sjdp "consumed". This allows demangle_class to be called later during 242233965Sjdp the same demangling, to do normal class demangling. 242333965Sjdp 242433965Sjdp Returns 1 if demangling is successful, 0 otherwise. 242533965Sjdp 242633965Sjdp*/ 242733965Sjdp 242833965Sjdpstatic int 2429218822Sdimdemangle_class (struct work_stuff *work, const char **mangled, string *declp) 243033965Sjdp{ 243133965Sjdp int success = 0; 243260484Sobrien int btype; 243333965Sjdp string class_name; 243460484Sobrien char *save_class_name_end = 0; 243533965Sjdp 243633965Sjdp string_init (&class_name); 243760484Sobrien btype = register_Btype (work); 243833965Sjdp if (demangle_class_name (work, mangled, &class_name)) 243933965Sjdp { 244060484Sobrien save_class_name_end = class_name.p; 244133965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 244233965Sjdp { 244360484Sobrien /* adjust so we don't include template args */ 244460484Sobrien if (work->temp_start && (work->temp_start != -1)) 244560484Sobrien { 244660484Sobrien class_name.p = class_name.b + work->temp_start; 244760484Sobrien } 244833965Sjdp string_prepends (declp, &class_name); 244933965Sjdp if (work -> destructor & 1) 245033965Sjdp { 245133965Sjdp string_prepend (declp, "~"); 245233965Sjdp work -> destructor -= 1; 245333965Sjdp } 245433965Sjdp else 245533965Sjdp { 245660484Sobrien work -> constructor -= 1; 245733965Sjdp } 245833965Sjdp } 245960484Sobrien class_name.p = save_class_name_end; 246060484Sobrien remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); 246160484Sobrien remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); 246260484Sobrien string_prepend (declp, SCOPE_STRING (work)); 246333965Sjdp string_prepends (declp, &class_name); 246433965Sjdp success = 1; 246533965Sjdp } 246633965Sjdp string_delete (&class_name); 246733965Sjdp return (success); 246833965Sjdp} 246933965Sjdp 247068765Sobrien 247168765Sobrien/* Called when there's a "__" in the mangled name, with `scan' pointing to 247268765Sobrien the rightmost guess. 247368765Sobrien 247468765Sobrien Find the correct "__"-sequence where the function name ends and the 247568765Sobrien signature starts, which is ambiguous with GNU mangling. 247668765Sobrien Call demangle_signature here, so we can make sure we found the right 247768765Sobrien one; *mangled will be consumed so caller will not make further calls to 247868765Sobrien demangle_signature. */ 247968765Sobrien 248068765Sobrienstatic int 2481218822Sdimiterate_demangle_function (struct work_stuff *work, const char **mangled, 2482218822Sdim string *declp, const char *scan) 248368765Sobrien{ 248468765Sobrien const char *mangle_init = *mangled; 248568765Sobrien int success = 0; 248668765Sobrien string decl_init; 248768765Sobrien struct work_stuff work_init; 248868765Sobrien 248968765Sobrien if (*(scan + 2) == '\0') 249068765Sobrien return 0; 249168765Sobrien 249268765Sobrien /* Do not iterate for some demangling modes, or if there's only one 249368765Sobrien "__"-sequence. This is the normal case. */ 249468765Sobrien if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING 249589857Sobrien || strstr (scan + 2, "__") == NULL) 249668765Sobrien { 249768765Sobrien demangle_function_name (work, mangled, declp, scan); 249868765Sobrien return 1; 249968765Sobrien } 250068765Sobrien 250168765Sobrien /* Save state so we can restart if the guess at the correct "__" was 250268765Sobrien wrong. */ 250368765Sobrien string_init (&decl_init); 250468765Sobrien string_appends (&decl_init, declp); 250568765Sobrien memset (&work_init, 0, sizeof work_init); 250668765Sobrien work_stuff_copy_to_from (&work_init, work); 250768765Sobrien 250868765Sobrien /* Iterate over occurrences of __, allowing names and types to have a 250968765Sobrien "__" sequence in them. We must start with the first (not the last) 251068765Sobrien occurrence, since "__" most often occur between independent mangled 251168765Sobrien parts, hence starting at the last occurence inside a signature 251268765Sobrien might get us a "successful" demangling of the signature. */ 251368765Sobrien 251468765Sobrien while (scan[2]) 251568765Sobrien { 251668765Sobrien demangle_function_name (work, mangled, declp, scan); 251768765Sobrien success = demangle_signature (work, mangled, declp); 251868765Sobrien if (success) 251968765Sobrien break; 252068765Sobrien 252168765Sobrien /* Reset demangle state for the next round. */ 252268765Sobrien *mangled = mangle_init; 252368765Sobrien string_clear (declp); 252468765Sobrien string_appends (declp, &decl_init); 252568765Sobrien work_stuff_copy_to_from (work, &work_init); 252668765Sobrien 252768765Sobrien /* Leave this underscore-sequence. */ 252868765Sobrien scan += 2; 252968765Sobrien 253068765Sobrien /* Scan for the next "__" sequence. */ 253168765Sobrien while (*scan && (scan[0] != '_' || scan[1] != '_')) 253268765Sobrien scan++; 253368765Sobrien 253468765Sobrien /* Move to last "__" in this sequence. */ 253568765Sobrien while (*scan && *scan == '_') 253668765Sobrien scan++; 253768765Sobrien scan -= 2; 253868765Sobrien } 253968765Sobrien 254068765Sobrien /* Delete saved state. */ 254168765Sobrien delete_work_stuff (&work_init); 254268765Sobrien string_delete (&decl_init); 254368765Sobrien 254468765Sobrien return success; 254568765Sobrien} 254668765Sobrien 254733965Sjdp/* 254833965Sjdp 254933965SjdpLOCAL FUNCTION 255033965Sjdp 255133965Sjdp demangle_prefix -- consume the mangled name prefix and find signature 255233965Sjdp 255333965SjdpSYNOPSIS 255433965Sjdp 255533965Sjdp static int 255633965Sjdp demangle_prefix (struct work_stuff *work, const char **mangled, 255733965Sjdp string *declp); 255833965Sjdp 255933965SjdpDESCRIPTION 256033965Sjdp 256133965Sjdp Consume and demangle the prefix of the mangled name. 256268765Sobrien While processing the function name root, arrange to call 256368765Sobrien demangle_signature if the root is ambiguous. 256433965Sjdp 256533965Sjdp DECLP points to the string buffer into which demangled output is 256633965Sjdp placed. On entry, the buffer is empty. On exit it contains 256733965Sjdp the root function name, the demangled operator name, or in some 256833965Sjdp special cases either nothing or the completely demangled result. 256933965Sjdp 257033965Sjdp MANGLED points to the current pointer into the mangled name. As each 257133965Sjdp token of the mangled name is consumed, it is updated. Upon entry 257233965Sjdp the current mangled name pointer points to the first character of 257333965Sjdp the mangled name. Upon exit, it should point to the first character 257433965Sjdp of the signature if demangling was successful, or to the first 257533965Sjdp unconsumed character if demangling of the prefix was unsuccessful. 257660484Sobrien 257733965Sjdp Returns 1 on success, 0 otherwise. 257833965Sjdp */ 257933965Sjdp 258033965Sjdpstatic int 2581218822Sdimdemangle_prefix (struct work_stuff *work, const char **mangled, 2582218822Sdim string *declp) 258333965Sjdp{ 258433965Sjdp int success = 1; 258533965Sjdp const char *scan; 258633965Sjdp int i; 258733965Sjdp 258860484Sobrien if (strlen(*mangled) > 6 258960484Sobrien && (strncmp(*mangled, "_imp__", 6) == 0 259060484Sobrien || strncmp(*mangled, "__imp_", 6) == 0)) 259133965Sjdp { 259260484Sobrien /* it's a symbol imported from a PE dynamic library. Check for both 259360484Sobrien new style prefix _imp__ and legacy __imp_ used by older versions 259460484Sobrien of dlltool. */ 259560484Sobrien (*mangled) += 6; 259660484Sobrien work->dllimported = 1; 259760484Sobrien } 259860484Sobrien else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) 259960484Sobrien { 260033965Sjdp char *marker = strchr (cplus_markers, (*mangled)[8]); 260133965Sjdp if (marker != NULL && *marker == (*mangled)[10]) 260233965Sjdp { 260333965Sjdp if ((*mangled)[9] == 'D') 260433965Sjdp { 260533965Sjdp /* it's a GNU global destructor to be executed at program exit */ 260633965Sjdp (*mangled) += 11; 260733965Sjdp work->destructor = 2; 260833965Sjdp if (gnu_special (work, mangled, declp)) 260933965Sjdp return success; 261033965Sjdp } 261133965Sjdp else if ((*mangled)[9] == 'I') 261233965Sjdp { 261333965Sjdp /* it's a GNU global constructor to be executed at program init */ 261433965Sjdp (*mangled) += 11; 261533965Sjdp work->constructor = 2; 261633965Sjdp if (gnu_special (work, mangled, declp)) 261733965Sjdp return success; 261833965Sjdp } 261933965Sjdp } 262033965Sjdp } 262160484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) 262233965Sjdp { 262333965Sjdp /* it's a ARM global destructor to be executed at program exit */ 262433965Sjdp (*mangled) += 7; 262533965Sjdp work->destructor = 2; 262633965Sjdp } 262760484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) 262833965Sjdp { 262933965Sjdp /* it's a ARM global constructor to be executed at program initial */ 263033965Sjdp (*mangled) += 7; 263133965Sjdp work->constructor = 2; 263233965Sjdp } 263333965Sjdp 263433965Sjdp /* This block of code is a reduction in strength time optimization 263533965Sjdp of: 263689857Sobrien scan = strstr (*mangled, "__"); */ 263733965Sjdp 263833965Sjdp { 263933965Sjdp scan = *mangled; 264033965Sjdp 264133965Sjdp do { 264233965Sjdp scan = strchr (scan, '_'); 264333965Sjdp } while (scan != NULL && *++scan != '_'); 264433965Sjdp 264533965Sjdp if (scan != NULL) --scan; 264633965Sjdp } 264733965Sjdp 264833965Sjdp if (scan != NULL) 264933965Sjdp { 265033965Sjdp /* We found a sequence of two or more '_', ensure that we start at 265133965Sjdp the last pair in the sequence. */ 265233965Sjdp i = strspn (scan, "_"); 265333965Sjdp if (i > 2) 265433965Sjdp { 265560484Sobrien scan += (i - 2); 265633965Sjdp } 265733965Sjdp } 265860484Sobrien 265933965Sjdp if (scan == NULL) 266033965Sjdp { 266133965Sjdp success = 0; 266233965Sjdp } 266333965Sjdp else if (work -> static_type) 266433965Sjdp { 266577298Sobrien if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) 266633965Sjdp { 266733965Sjdp success = 0; 266833965Sjdp } 266933965Sjdp } 267038889Sjdp else if ((scan == *mangled) 267177298Sobrien && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') 267260484Sobrien || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) 267333965Sjdp { 267433965Sjdp /* The ARM says nothing about the mangling of local variables. 267533965Sjdp But cfront mangles local variables by prepending __<nesting_level> 267633965Sjdp to them. As an extension to ARM demangling we handle this case. */ 267760484Sobrien if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) 267877298Sobrien && ISDIGIT ((unsigned char)scan[2])) 267933965Sjdp { 268033965Sjdp *mangled = scan + 2; 268133965Sjdp consume_count (mangled); 268233965Sjdp string_append (declp, *mangled); 268333965Sjdp *mangled += strlen (*mangled); 268460484Sobrien success = 1; 268533965Sjdp } 268633965Sjdp else 268733965Sjdp { 268833965Sjdp /* A GNU style constructor starts with __[0-9Qt]. But cfront uses 268933965Sjdp names like __Q2_3foo3bar for nested type names. So don't accept 269038889Sjdp this style of constructor for cfront demangling. A GNU 269138889Sjdp style member-template constructor starts with 'H'. */ 269260484Sobrien if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) 269333965Sjdp work -> constructor += 1; 269433965Sjdp *mangled = scan + 2; 269533965Sjdp } 269633965Sjdp } 269760484Sobrien else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') 269833965Sjdp { 269960484Sobrien /* Cfront-style parameterized type. Handled later as a signature. */ 270060484Sobrien success = 1; 270160484Sobrien 270260484Sobrien /* ARM template? */ 270360484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 270460484Sobrien } 270560484Sobrien else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') 270660484Sobrien || (scan[2] == 'p' && scan[3] == 's') 270760484Sobrien || (scan[2] == 'p' && scan[3] == 't'))) 270860484Sobrien { 270960484Sobrien /* EDG-style parameterized type. Handled later as a signature. */ 271060484Sobrien success = 1; 271160484Sobrien 271260484Sobrien /* EDG template? */ 271360484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 271460484Sobrien } 271577298Sobrien else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) 271660484Sobrien && (scan[2] != 't')) 271760484Sobrien { 271833965Sjdp /* Mangled name starts with "__". Skip over any leading '_' characters, 271933965Sjdp then find the next "__" that separates the prefix from the signature. 272033965Sjdp */ 272160484Sobrien if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 272260484Sobrien || (arm_special (mangled, declp) == 0)) 272333965Sjdp { 272433965Sjdp while (*scan == '_') 272533965Sjdp { 272633965Sjdp scan++; 272733965Sjdp } 272889857Sobrien if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) 272933965Sjdp { 273033965Sjdp /* No separator (I.E. "__not_mangled"), or empty signature 273133965Sjdp (I.E. "__not_mangled_either__") */ 273233965Sjdp success = 0; 273333965Sjdp } 273433965Sjdp else 273568765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 273633965Sjdp } 273733965Sjdp } 273833965Sjdp else if (*(scan + 2) != '\0') 273933965Sjdp { 274033965Sjdp /* Mangled name does not start with "__" but does have one somewhere 274133965Sjdp in there with non empty stuff after it. Looks like a global 274268765Sobrien function name. Iterate over all "__":s until the right 274368765Sobrien one is found. */ 274468765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 274533965Sjdp } 274633965Sjdp else 274733965Sjdp { 274833965Sjdp /* Doesn't look like a mangled name */ 274933965Sjdp success = 0; 275033965Sjdp } 275133965Sjdp 275233965Sjdp if (!success && (work->constructor == 2 || work->destructor == 2)) 275333965Sjdp { 275433965Sjdp string_append (declp, *mangled); 275533965Sjdp *mangled += strlen (*mangled); 275633965Sjdp success = 1; 275760484Sobrien } 275833965Sjdp return (success); 275933965Sjdp} 276033965Sjdp 276133965Sjdp/* 276233965Sjdp 276333965SjdpLOCAL FUNCTION 276433965Sjdp 276533965Sjdp gnu_special -- special handling of gnu mangled strings 276633965Sjdp 276733965SjdpSYNOPSIS 276833965Sjdp 276933965Sjdp static int 277033965Sjdp gnu_special (struct work_stuff *work, const char **mangled, 277133965Sjdp string *declp); 277233965Sjdp 277333965Sjdp 277433965SjdpDESCRIPTION 277533965Sjdp 277633965Sjdp Process some special GNU style mangling forms that don't fit 277733965Sjdp the normal pattern. For example: 277833965Sjdp 277933965Sjdp _$_3foo (destructor for class foo) 278033965Sjdp _vt$foo (foo virtual table) 278133965Sjdp _vt$foo$bar (foo::bar virtual table) 278233965Sjdp __vt_foo (foo virtual table, new style with thunks) 278333965Sjdp _3foo$varname (static data member) 278433965Sjdp _Q22rs2tu$vw (static data member) 278533965Sjdp __t6vector1Zii (constructor with template) 278633965Sjdp __thunk_4__$_7ostream (virtual function thunk) 278733965Sjdp */ 278833965Sjdp 278933965Sjdpstatic int 2790218822Sdimgnu_special (struct work_stuff *work, const char **mangled, string *declp) 279133965Sjdp{ 279233965Sjdp int n; 279333965Sjdp int success = 1; 279433965Sjdp const char *p; 279533965Sjdp 279633965Sjdp if ((*mangled)[0] == '_' 279733965Sjdp && strchr (cplus_markers, (*mangled)[1]) != NULL 279833965Sjdp && (*mangled)[2] == '_') 279933965Sjdp { 280033965Sjdp /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ 280133965Sjdp (*mangled) += 3; 280233965Sjdp work -> destructor += 1; 280333965Sjdp } 280433965Sjdp else if ((*mangled)[0] == '_' 280533965Sjdp && (((*mangled)[1] == '_' 280633965Sjdp && (*mangled)[2] == 'v' 280733965Sjdp && (*mangled)[3] == 't' 280833965Sjdp && (*mangled)[4] == '_') 280933965Sjdp || ((*mangled)[1] == 'v' 281033965Sjdp && (*mangled)[2] == 't' 281133965Sjdp && strchr (cplus_markers, (*mangled)[3]) != NULL))) 281233965Sjdp { 281333965Sjdp /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" 281433965Sjdp and create the decl. Note that we consume the entire mangled 281533965Sjdp input string, which means that demangle_signature has no work 281633965Sjdp to do. */ 281733965Sjdp if ((*mangled)[2] == 'v') 281833965Sjdp (*mangled) += 5; /* New style, with thunks: "__vt_" */ 281933965Sjdp else 282033965Sjdp (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */ 282133965Sjdp while (**mangled != '\0') 282233965Sjdp { 282333965Sjdp switch (**mangled) 282433965Sjdp { 282533965Sjdp case 'Q': 282660484Sobrien case 'K': 282733965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 282833965Sjdp break; 282933965Sjdp case 't': 283060484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 283160484Sobrien 1); 283233965Sjdp break; 283333965Sjdp default: 283477298Sobrien if (ISDIGIT((unsigned char)*mangled[0])) 283533965Sjdp { 283633965Sjdp n = consume_count(mangled); 283738889Sjdp /* We may be seeing a too-large size, or else a 283838889Sjdp ".<digits>" indicating a static local symbol. In 283938889Sjdp any case, declare victory and move on; *don't* try 284038889Sjdp to use n to allocate. */ 284160484Sobrien if (n > (int) strlen (*mangled)) 284238889Sjdp { 284338889Sjdp success = 1; 284438889Sjdp break; 284538889Sjdp } 284633965Sjdp } 284733965Sjdp else 284833965Sjdp { 284933965Sjdp n = strcspn (*mangled, cplus_markers); 285033965Sjdp } 285133965Sjdp string_appendn (declp, *mangled, n); 285233965Sjdp (*mangled) += n; 285333965Sjdp } 285433965Sjdp 285560484Sobrien p = strpbrk (*mangled, cplus_markers); 285633965Sjdp if (success && ((p == NULL) || (p == *mangled))) 285733965Sjdp { 285833965Sjdp if (p != NULL) 285933965Sjdp { 286060484Sobrien string_append (declp, SCOPE_STRING (work)); 286133965Sjdp (*mangled)++; 286233965Sjdp } 286333965Sjdp } 286433965Sjdp else 286533965Sjdp { 286633965Sjdp success = 0; 286733965Sjdp break; 286833965Sjdp } 286933965Sjdp } 287033965Sjdp if (success) 287133965Sjdp string_append (declp, " virtual table"); 287233965Sjdp } 287333965Sjdp else if ((*mangled)[0] == '_' 287433965Sjdp && (strchr("0123456789Qt", (*mangled)[1]) != NULL) 287533965Sjdp && (p = strpbrk (*mangled, cplus_markers)) != NULL) 287633965Sjdp { 287733965Sjdp /* static data member, "_3foo$varname" for example */ 287833965Sjdp (*mangled)++; 287933965Sjdp switch (**mangled) 288033965Sjdp { 288133965Sjdp case 'Q': 288260484Sobrien case 'K': 288333965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 288433965Sjdp break; 288533965Sjdp case 't': 288660484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 288733965Sjdp break; 288833965Sjdp default: 288933965Sjdp n = consume_count (mangled); 289060484Sobrien if (n < 0 || n > (long) strlen (*mangled)) 289160484Sobrien { 289260484Sobrien success = 0; 289360484Sobrien break; 289460484Sobrien } 289568765Sobrien 289668765Sobrien if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 289768765Sobrien && (*mangled)[9] == 'N' 289868765Sobrien && (*mangled)[8] == (*mangled)[10] 289968765Sobrien && strchr (cplus_markers, (*mangled)[8])) 290068765Sobrien { 290168765Sobrien /* A member of the anonymous namespace. There's information 290268765Sobrien about what identifier or filename it was keyed to, but 290368765Sobrien it's just there to make the mangled name unique; we just 290468765Sobrien step over it. */ 290568765Sobrien string_append (declp, "{anonymous}"); 290668765Sobrien (*mangled) += n; 290768765Sobrien 290868765Sobrien /* Now p points to the marker before the N, so we need to 290968765Sobrien update it to the first marker after what we consumed. */ 291068765Sobrien p = strpbrk (*mangled, cplus_markers); 291168765Sobrien break; 291268765Sobrien } 291368765Sobrien 291433965Sjdp string_appendn (declp, *mangled, n); 291533965Sjdp (*mangled) += n; 291633965Sjdp } 291733965Sjdp if (success && (p == *mangled)) 291833965Sjdp { 291933965Sjdp /* Consumed everything up to the cplus_marker, append the 292033965Sjdp variable name. */ 292133965Sjdp (*mangled)++; 292260484Sobrien string_append (declp, SCOPE_STRING (work)); 292333965Sjdp n = strlen (*mangled); 292433965Sjdp string_appendn (declp, *mangled, n); 292533965Sjdp (*mangled) += n; 292633965Sjdp } 292733965Sjdp else 292833965Sjdp { 292933965Sjdp success = 0; 293033965Sjdp } 293133965Sjdp } 293233965Sjdp else if (strncmp (*mangled, "__thunk_", 8) == 0) 293333965Sjdp { 293460484Sobrien int delta; 293560484Sobrien 293660484Sobrien (*mangled) += 8; 293760484Sobrien delta = consume_count (mangled); 293860484Sobrien if (delta == -1) 293960484Sobrien success = 0; 294033965Sjdp else 294133965Sjdp { 294260484Sobrien char *method = internal_cplus_demangle (work, ++*mangled); 294360484Sobrien 294460484Sobrien if (method) 294560484Sobrien { 294660484Sobrien char buf[50]; 294760484Sobrien sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); 294860484Sobrien string_append (declp, buf); 294960484Sobrien string_append (declp, method); 295060484Sobrien free (method); 295160484Sobrien n = strlen (*mangled); 295260484Sobrien (*mangled) += n; 295360484Sobrien } 295460484Sobrien else 295560484Sobrien { 295660484Sobrien success = 0; 295760484Sobrien } 295833965Sjdp } 295933965Sjdp } 296033965Sjdp else if (strncmp (*mangled, "__t", 3) == 0 296133965Sjdp && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) 296233965Sjdp { 296333965Sjdp p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; 296433965Sjdp (*mangled) += 4; 296533965Sjdp switch (**mangled) 296633965Sjdp { 296733965Sjdp case 'Q': 296860484Sobrien case 'K': 296933965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 297033965Sjdp break; 297133965Sjdp case 't': 297260484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 297333965Sjdp break; 297433965Sjdp default: 297568765Sobrien success = do_type (work, mangled, declp); 297633965Sjdp break; 297733965Sjdp } 297833965Sjdp if (success && **mangled != '\0') 297933965Sjdp success = 0; 298033965Sjdp if (success) 298133965Sjdp string_append (declp, p); 298233965Sjdp } 298333965Sjdp else 298433965Sjdp { 298533965Sjdp success = 0; 298633965Sjdp } 298733965Sjdp return (success); 298833965Sjdp} 298933965Sjdp 299060484Sobrienstatic void 2991218822Sdimrecursively_demangle(struct work_stuff *work, const char **mangled, 2992218822Sdim string *result, int namelength) 299360484Sobrien{ 299460484Sobrien char * recurse = (char *)NULL; 299560484Sobrien char * recurse_dem = (char *)NULL; 299660484Sobrien 2997218822Sdim recurse = XNEWVEC (char, namelength + 1); 299860484Sobrien memcpy (recurse, *mangled, namelength); 299960484Sobrien recurse[namelength] = '\000'; 300060484Sobrien 300160484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 300260484Sobrien 300360484Sobrien if (recurse_dem) 300460484Sobrien { 300560484Sobrien string_append (result, recurse_dem); 300660484Sobrien free (recurse_dem); 300760484Sobrien } 300860484Sobrien else 300960484Sobrien { 301060484Sobrien string_appendn (result, *mangled, namelength); 301160484Sobrien } 301260484Sobrien free (recurse); 301360484Sobrien *mangled += namelength; 301460484Sobrien} 301560484Sobrien 301633965Sjdp/* 301733965Sjdp 301833965SjdpLOCAL FUNCTION 301933965Sjdp 302033965Sjdp arm_special -- special handling of ARM/lucid mangled strings 302133965Sjdp 302233965SjdpSYNOPSIS 302333965Sjdp 302433965Sjdp static int 302560484Sobrien arm_special (const char **mangled, 302660484Sobrien string *declp); 302733965Sjdp 302833965Sjdp 302933965SjdpDESCRIPTION 303033965Sjdp 303133965Sjdp Process some special ARM style mangling forms that don't fit 303233965Sjdp the normal pattern. For example: 303333965Sjdp 303433965Sjdp __vtbl__3foo (foo virtual table) 303533965Sjdp __vtbl__3foo__3bar (bar::foo virtual table) 303633965Sjdp 303733965Sjdp */ 303833965Sjdp 303933965Sjdpstatic int 3040218822Sdimarm_special (const char **mangled, string *declp) 304133965Sjdp{ 304233965Sjdp int n; 304333965Sjdp int success = 1; 304433965Sjdp const char *scan; 304533965Sjdp 304633965Sjdp if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) 304733965Sjdp { 304833965Sjdp /* Found a ARM style virtual table, get past ARM_VTABLE_STRING 304933965Sjdp and create the decl. Note that we consume the entire mangled 305033965Sjdp input string, which means that demangle_signature has no work 305133965Sjdp to do. */ 305233965Sjdp scan = *mangled + ARM_VTABLE_STRLEN; 305333965Sjdp while (*scan != '\0') /* first check it can be demangled */ 305433965Sjdp { 305533965Sjdp n = consume_count (&scan); 305660484Sobrien if (n == -1) 305733965Sjdp { 305833965Sjdp return (0); /* no good */ 305933965Sjdp } 306033965Sjdp scan += n; 306133965Sjdp if (scan[0] == '_' && scan[1] == '_') 306233965Sjdp { 306333965Sjdp scan += 2; 306433965Sjdp } 306533965Sjdp } 306633965Sjdp (*mangled) += ARM_VTABLE_STRLEN; 306733965Sjdp while (**mangled != '\0') 306833965Sjdp { 306933965Sjdp n = consume_count (mangled); 307060484Sobrien if (n == -1 307160484Sobrien || n > (long) strlen (*mangled)) 307260484Sobrien return 0; 307333965Sjdp string_prependn (declp, *mangled, n); 307433965Sjdp (*mangled) += n; 307533965Sjdp if ((*mangled)[0] == '_' && (*mangled)[1] == '_') 307633965Sjdp { 307733965Sjdp string_prepend (declp, "::"); 307833965Sjdp (*mangled) += 2; 307933965Sjdp } 308033965Sjdp } 308133965Sjdp string_append (declp, " virtual table"); 308233965Sjdp } 308333965Sjdp else 308433965Sjdp { 308533965Sjdp success = 0; 308633965Sjdp } 308733965Sjdp return (success); 308833965Sjdp} 308933965Sjdp 309033965Sjdp/* 309133965Sjdp 309233965SjdpLOCAL FUNCTION 309333965Sjdp 309433965Sjdp demangle_qualified -- demangle 'Q' qualified name strings 309533965Sjdp 309633965SjdpSYNOPSIS 309733965Sjdp 309833965Sjdp static int 309933965Sjdp demangle_qualified (struct work_stuff *, const char *mangled, 310033965Sjdp string *result, int isfuncname, int append); 310133965Sjdp 310233965SjdpDESCRIPTION 310333965Sjdp 310433965Sjdp Demangle a qualified name, such as "Q25Outer5Inner" which is 310533965Sjdp the mangled form of "Outer::Inner". The demangled output is 310633965Sjdp prepended or appended to the result string according to the 310733965Sjdp state of the append flag. 310833965Sjdp 310933965Sjdp If isfuncname is nonzero, then the qualified name we are building 311033965Sjdp is going to be used as a member function name, so if it is a 311133965Sjdp constructor or destructor function, append an appropriate 311233965Sjdp constructor or destructor name. I.E. for the above example, 311333965Sjdp the result for use as a constructor is "Outer::Inner::Inner" 311433965Sjdp and the result for use as a destructor is "Outer::Inner::~Inner". 311533965Sjdp 311633965SjdpBUGS 311733965Sjdp 311833965Sjdp Numeric conversion is ASCII dependent (FIXME). 311933965Sjdp 312033965Sjdp */ 312133965Sjdp 312233965Sjdpstatic int 3123218822Sdimdemangle_qualified (struct work_stuff *work, const char **mangled, 3124218822Sdim string *result, int isfuncname, int append) 312533965Sjdp{ 312660484Sobrien int qualifiers = 0; 312733965Sjdp int success = 1; 312833965Sjdp char num[2]; 312933965Sjdp string temp; 313060484Sobrien string last_name; 313160484Sobrien int bindex = register_Btype (work); 313233965Sjdp 313360484Sobrien /* We only make use of ISFUNCNAME if the entity is a constructor or 313460484Sobrien destructor. */ 313560484Sobrien isfuncname = (isfuncname 313660484Sobrien && ((work->constructor & 1) || (work->destructor & 1))); 313760484Sobrien 313833965Sjdp string_init (&temp); 313960484Sobrien string_init (&last_name); 314060484Sobrien 314160484Sobrien if ((*mangled)[0] == 'K') 314233965Sjdp { 314360484Sobrien /* Squangling qualified name reuse */ 314460484Sobrien int idx; 314560484Sobrien (*mangled)++; 314660484Sobrien idx = consume_count_with_underscores (mangled); 314760484Sobrien if (idx == -1 || idx >= work -> numk) 314860484Sobrien success = 0; 314960484Sobrien else 315060484Sobrien string_append (&temp, work -> ktypevec[idx]); 315160484Sobrien } 315260484Sobrien else 315360484Sobrien switch ((*mangled)[1]) 315460484Sobrien { 315533965Sjdp case '_': 315633965Sjdp /* GNU mangled name with more than 9 classes. The count is preceded 315733965Sjdp by an underscore (to distinguish it from the <= 9 case) and followed 315833965Sjdp by an underscore. */ 315960484Sobrien (*mangled)++; 316060484Sobrien qualifiers = consume_count_with_underscores (mangled); 316160484Sobrien if (qualifiers == -1) 316233965Sjdp success = 0; 316333965Sjdp break; 316433965Sjdp 316533965Sjdp case '1': 316633965Sjdp case '2': 316733965Sjdp case '3': 316833965Sjdp case '4': 316933965Sjdp case '5': 317033965Sjdp case '6': 317133965Sjdp case '7': 317233965Sjdp case '8': 317333965Sjdp case '9': 317433965Sjdp /* The count is in a single digit. */ 317533965Sjdp num[0] = (*mangled)[1]; 317633965Sjdp num[1] = '\0'; 317733965Sjdp qualifiers = atoi (num); 317833965Sjdp 317933965Sjdp /* If there is an underscore after the digit, skip it. This is 318033965Sjdp said to be for ARM-qualified names, but the ARM makes no 318133965Sjdp mention of such an underscore. Perhaps cfront uses one. */ 318233965Sjdp if ((*mangled)[2] == '_') 318333965Sjdp { 318433965Sjdp (*mangled)++; 318533965Sjdp } 318633965Sjdp (*mangled) += 2; 318733965Sjdp break; 318833965Sjdp 318933965Sjdp case '0': 319033965Sjdp default: 319133965Sjdp success = 0; 319233965Sjdp } 319333965Sjdp 319433965Sjdp if (!success) 319533965Sjdp return success; 319633965Sjdp 319733965Sjdp /* Pick off the names and collect them in the temp buffer in the order 319833965Sjdp in which they are found, separated by '::'. */ 319933965Sjdp 320033965Sjdp while (qualifiers-- > 0) 320133965Sjdp { 320260484Sobrien int remember_K = 1; 320360484Sobrien string_clear (&last_name); 320460484Sobrien 320560484Sobrien if (*mangled[0] == '_') 320660484Sobrien (*mangled)++; 320760484Sobrien 320833965Sjdp if (*mangled[0] == 't') 320933965Sjdp { 321060484Sobrien /* Here we always append to TEMP since we will want to use 321160484Sobrien the template name without the template parameters as a 321260484Sobrien constructor or destructor name. The appropriate 321360484Sobrien (parameter-less) value is returned by demangle_template 321460484Sobrien in LAST_NAME. We do not remember the template type here, 321560484Sobrien in order to match the G++ mangling algorithm. */ 321660484Sobrien success = demangle_template(work, mangled, &temp, 321760484Sobrien &last_name, 1, 0); 321860484Sobrien if (!success) 321960484Sobrien break; 322033965Sjdp } 322160484Sobrien else if (*mangled[0] == 'K') 322238889Sjdp { 322360484Sobrien int idx; 322460484Sobrien (*mangled)++; 322560484Sobrien idx = consume_count_with_underscores (mangled); 322660484Sobrien if (idx == -1 || idx >= work->numk) 322760484Sobrien success = 0; 322860484Sobrien else 322960484Sobrien string_append (&temp, work->ktypevec[idx]); 323060484Sobrien remember_K = 0; 323160484Sobrien 323238889Sjdp if (!success) break; 323338889Sjdp } 323433965Sjdp else 323560484Sobrien { 323660484Sobrien if (EDG_DEMANGLING) 323760484Sobrien { 323860484Sobrien int namelength; 323960484Sobrien /* Now recursively demangle the qualifier 324060484Sobrien * This is necessary to deal with templates in 324160484Sobrien * mangling styles like EDG */ 324260484Sobrien namelength = consume_count (mangled); 324360484Sobrien if (namelength == -1) 324460484Sobrien { 324560484Sobrien success = 0; 324660484Sobrien break; 324760484Sobrien } 324860484Sobrien recursively_demangle(work, mangled, &temp, namelength); 324960484Sobrien } 325060484Sobrien else 325160484Sobrien { 3252130561Sobrien string_delete (&last_name); 325360484Sobrien success = do_type (work, mangled, &last_name); 325460484Sobrien if (!success) 325560484Sobrien break; 325660484Sobrien string_appends (&temp, &last_name); 325760484Sobrien } 325833965Sjdp } 325960484Sobrien 326060484Sobrien if (remember_K) 326160484Sobrien remember_Ktype (work, temp.b, LEN_STRING (&temp)); 326260484Sobrien 326333965Sjdp if (qualifiers > 0) 326460484Sobrien string_append (&temp, SCOPE_STRING (work)); 326533965Sjdp } 326633965Sjdp 326760484Sobrien remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); 326860484Sobrien 326933965Sjdp /* If we are using the result as a function name, we need to append 327033965Sjdp the appropriate '::' separated constructor or destructor name. 327133965Sjdp We do this here because this is the most convenient place, where 327233965Sjdp we already have a pointer to the name and the length of the name. */ 327333965Sjdp 327460484Sobrien if (isfuncname) 327533965Sjdp { 327660484Sobrien string_append (&temp, SCOPE_STRING (work)); 327733965Sjdp if (work -> destructor & 1) 327860484Sobrien string_append (&temp, "~"); 327960484Sobrien string_appends (&temp, &last_name); 328033965Sjdp } 328133965Sjdp 328260484Sobrien /* Now either prepend the temp buffer to the result, or append it, 328333965Sjdp depending upon the state of the append flag. */ 328433965Sjdp 328533965Sjdp if (append) 328660484Sobrien string_appends (result, &temp); 328733965Sjdp else 328833965Sjdp { 328933965Sjdp if (!STRING_EMPTY (result)) 329060484Sobrien string_append (&temp, SCOPE_STRING (work)); 329133965Sjdp string_prepends (result, &temp); 329233965Sjdp } 329333965Sjdp 329460484Sobrien string_delete (&last_name); 329533965Sjdp string_delete (&temp); 329633965Sjdp return (success); 329733965Sjdp} 329833965Sjdp 329933965Sjdp/* 330033965Sjdp 330133965SjdpLOCAL FUNCTION 330233965Sjdp 330333965Sjdp get_count -- convert an ascii count to integer, consuming tokens 330433965Sjdp 330533965SjdpSYNOPSIS 330633965Sjdp 330733965Sjdp static int 330833965Sjdp get_count (const char **type, int *count) 330933965Sjdp 331033965SjdpDESCRIPTION 331133965Sjdp 331260484Sobrien Assume that *type points at a count in a mangled name; set 331360484Sobrien *count to its value, and set *type to the next character after 331460484Sobrien the count. There are some weird rules in effect here. 331560484Sobrien 331660484Sobrien If *type does not point at a string of digits, return zero. 331760484Sobrien 331860484Sobrien If *type points at a string of digits followed by an 331960484Sobrien underscore, set *count to their value as an integer, advance 332060484Sobrien *type to point *after the underscore, and return 1. 332160484Sobrien 332260484Sobrien If *type points at a string of digits not followed by an 332360484Sobrien underscore, consume only the first digit. Set *count to its 332460484Sobrien value as an integer, leave *type pointing after that digit, 332560484Sobrien and return 1. 332660484Sobrien 332760484Sobrien The excuse for this odd behavior: in the ARM and HP demangling 332860484Sobrien styles, a type can be followed by a repeat count of the form 332960484Sobrien `Nxy', where: 333060484Sobrien 333160484Sobrien `x' is a single digit specifying how many additional copies 333260484Sobrien of the type to append to the argument list, and 333360484Sobrien 333460484Sobrien `y' is one or more digits, specifying the zero-based index of 333560484Sobrien the first repeated argument in the list. Yes, as you're 333660484Sobrien unmangling the name you can figure this out yourself, but 333760484Sobrien it's there anyway. 333860484Sobrien 333960484Sobrien So, for example, in `bar__3fooFPiN51', the first argument is a 334060484Sobrien pointer to an integer (`Pi'), and then the next five arguments 334160484Sobrien are the same (`N5'), and the first repeat is the function's 334260484Sobrien second argument (`1'). 334333965Sjdp*/ 334433965Sjdp 334533965Sjdpstatic int 3346218822Sdimget_count (const char **type, int *count) 334733965Sjdp{ 334833965Sjdp const char *p; 334933965Sjdp int n; 335033965Sjdp 335177298Sobrien if (!ISDIGIT ((unsigned char)**type)) 335260484Sobrien return (0); 335333965Sjdp else 335433965Sjdp { 335533965Sjdp *count = **type - '0'; 335633965Sjdp (*type)++; 335777298Sobrien if (ISDIGIT ((unsigned char)**type)) 335833965Sjdp { 335933965Sjdp p = *type; 336033965Sjdp n = *count; 336160484Sobrien do 336233965Sjdp { 336333965Sjdp n *= 10; 336433965Sjdp n += *p - '0'; 336533965Sjdp p++; 336660484Sobrien } 336777298Sobrien while (ISDIGIT ((unsigned char)*p)); 336833965Sjdp if (*p == '_') 336933965Sjdp { 337033965Sjdp *type = p + 1; 337133965Sjdp *count = n; 337233965Sjdp } 337333965Sjdp } 337433965Sjdp } 337533965Sjdp return (1); 337633965Sjdp} 337733965Sjdp 337860484Sobrien/* RESULT will be initialised here; it will be freed on failure. The 337960484Sobrien value returned is really a type_kind_t. */ 338033965Sjdp 338133965Sjdpstatic int 3382218822Sdimdo_type (struct work_stuff *work, const char **mangled, string *result) 338333965Sjdp{ 338433965Sjdp int n; 338533965Sjdp int done; 338633965Sjdp int success; 338733965Sjdp string decl; 338833965Sjdp const char *remembered_type; 338960484Sobrien int type_quals; 339060484Sobrien type_kind_t tk = tk_none; 339133965Sjdp 339233965Sjdp string_init (&decl); 339333965Sjdp string_init (result); 339433965Sjdp 339533965Sjdp done = 0; 339633965Sjdp success = 1; 339733965Sjdp while (success && !done) 339833965Sjdp { 339933965Sjdp int member; 340033965Sjdp switch (**mangled) 340133965Sjdp { 340233965Sjdp 340333965Sjdp /* A pointer type */ 340433965Sjdp case 'P': 340533965Sjdp case 'p': 340633965Sjdp (*mangled)++; 340738889Sjdp if (! (work -> options & DMGL_JAVA)) 340838889Sjdp string_prepend (&decl, "*"); 340960484Sobrien if (tk == tk_none) 341060484Sobrien tk = tk_pointer; 341133965Sjdp break; 341233965Sjdp 341333965Sjdp /* A reference type */ 341433965Sjdp case 'R': 341533965Sjdp (*mangled)++; 341633965Sjdp string_prepend (&decl, "&"); 341760484Sobrien if (tk == tk_none) 341860484Sobrien tk = tk_reference; 341933965Sjdp break; 342033965Sjdp 342133965Sjdp /* An array */ 342233965Sjdp case 'A': 342333965Sjdp { 342460484Sobrien ++(*mangled); 342560484Sobrien if (!STRING_EMPTY (&decl) 342660484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 342733965Sjdp { 342860484Sobrien string_prepend (&decl, "("); 342960484Sobrien string_append (&decl, ")"); 343033965Sjdp } 343160484Sobrien string_append (&decl, "["); 343260484Sobrien if (**mangled != '_') 343360484Sobrien success = demangle_template_value_parm (work, mangled, &decl, 343460484Sobrien tk_integral); 343560484Sobrien if (**mangled == '_') 343660484Sobrien ++(*mangled); 343760484Sobrien string_append (&decl, "]"); 343833965Sjdp break; 343933965Sjdp } 344033965Sjdp 344133965Sjdp /* A back reference to a previously seen type */ 344233965Sjdp case 'T': 344333965Sjdp (*mangled)++; 344433965Sjdp if (!get_count (mangled, &n) || n >= work -> ntypes) 344533965Sjdp { 344633965Sjdp success = 0; 344733965Sjdp } 344833965Sjdp else 344933965Sjdp { 345033965Sjdp remembered_type = work -> typevec[n]; 345133965Sjdp mangled = &remembered_type; 345233965Sjdp } 345333965Sjdp break; 345433965Sjdp 345533965Sjdp /* A function */ 345633965Sjdp case 'F': 345733965Sjdp (*mangled)++; 345860484Sobrien if (!STRING_EMPTY (&decl) 345960484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 346033965Sjdp { 346133965Sjdp string_prepend (&decl, "("); 346233965Sjdp string_append (&decl, ")"); 346333965Sjdp } 346433965Sjdp /* After picking off the function args, we expect to either find the 346533965Sjdp function return type (preceded by an '_') or the end of the 346633965Sjdp string. */ 346760484Sobrien if (!demangle_nested_args (work, mangled, &decl) 346833965Sjdp || (**mangled != '_' && **mangled != '\0')) 346933965Sjdp { 347033965Sjdp success = 0; 347160484Sobrien break; 347233965Sjdp } 347333965Sjdp if (success && (**mangled == '_')) 347460484Sobrien (*mangled)++; 347533965Sjdp break; 347633965Sjdp 347733965Sjdp case 'M': 347833965Sjdp case 'O': 347933965Sjdp { 348060484Sobrien type_quals = TYPE_UNQUALIFIED; 348133965Sjdp 348233965Sjdp member = **mangled == 'M'; 348333965Sjdp (*mangled)++; 348433965Sjdp 348533965Sjdp string_append (&decl, ")"); 348660484Sobrien 348760484Sobrien /* We don't need to prepend `::' for a qualified name; 348860484Sobrien demangle_qualified will do that for us. */ 348960484Sobrien if (**mangled != 'Q') 349060484Sobrien string_prepend (&decl, SCOPE_STRING (work)); 349160484Sobrien 349277298Sobrien if (ISDIGIT ((unsigned char)**mangled)) 349333965Sjdp { 349433965Sjdp n = consume_count (mangled); 349560484Sobrien if (n == -1 349660484Sobrien || (int) strlen (*mangled) < n) 349733965Sjdp { 349833965Sjdp success = 0; 349933965Sjdp break; 350033965Sjdp } 350133965Sjdp string_prependn (&decl, *mangled, n); 350233965Sjdp *mangled += n; 350333965Sjdp } 350460484Sobrien else if (**mangled == 'X' || **mangled == 'Y') 350533965Sjdp { 350633965Sjdp string temp; 350760484Sobrien do_type (work, mangled, &temp); 350860484Sobrien string_prepends (&decl, &temp); 3509130561Sobrien string_delete (&temp); 351060484Sobrien } 351160484Sobrien else if (**mangled == 't') 351260484Sobrien { 351360484Sobrien string temp; 351433965Sjdp string_init (&temp); 351560484Sobrien success = demangle_template (work, mangled, &temp, 351660484Sobrien NULL, 1, 1); 351733965Sjdp if (success) 351833965Sjdp { 351933965Sjdp string_prependn (&decl, temp.b, temp.p - temp.b); 3520130561Sobrien string_delete (&temp); 352133965Sjdp } 352233965Sjdp else 352333965Sjdp break; 352433965Sjdp } 352560484Sobrien else if (**mangled == 'Q') 352660484Sobrien { 352760484Sobrien success = demangle_qualified (work, mangled, &decl, 352860484Sobrien /*isfuncnam=*/0, 352960484Sobrien /*append=*/0); 353060484Sobrien if (!success) 353160484Sobrien break; 353260484Sobrien } 353360484Sobrien else 353460484Sobrien { 353560484Sobrien success = 0; 353660484Sobrien break; 353760484Sobrien } 353860484Sobrien 353933965Sjdp string_prepend (&decl, "("); 354033965Sjdp if (member) 354133965Sjdp { 354260484Sobrien switch (**mangled) 354333965Sjdp { 354460484Sobrien case 'C': 354560484Sobrien case 'V': 354660484Sobrien case 'u': 354760484Sobrien type_quals |= code_for_qualifier (**mangled); 354833965Sjdp (*mangled)++; 354960484Sobrien break; 355060484Sobrien 355160484Sobrien default: 355260484Sobrien break; 355333965Sjdp } 355460484Sobrien 355533965Sjdp if (*(*mangled)++ != 'F') 355633965Sjdp { 355733965Sjdp success = 0; 355833965Sjdp break; 355933965Sjdp } 356033965Sjdp } 356160484Sobrien if ((member && !demangle_nested_args (work, mangled, &decl)) 356233965Sjdp || **mangled != '_') 356333965Sjdp { 356433965Sjdp success = 0; 356533965Sjdp break; 356633965Sjdp } 356733965Sjdp (*mangled)++; 356833965Sjdp if (! PRINT_ANSI_QUALIFIERS) 356933965Sjdp { 357033965Sjdp break; 357133965Sjdp } 357260484Sobrien if (type_quals != TYPE_UNQUALIFIED) 357333965Sjdp { 357433965Sjdp APPEND_BLANK (&decl); 357560484Sobrien string_append (&decl, qualifier_string (type_quals)); 357633965Sjdp } 357733965Sjdp break; 357833965Sjdp } 357933965Sjdp case 'G': 358033965Sjdp (*mangled)++; 358133965Sjdp break; 358233965Sjdp 358333965Sjdp case 'C': 358460484Sobrien case 'V': 358560484Sobrien case 'u': 358633965Sjdp if (PRINT_ANSI_QUALIFIERS) 358733965Sjdp { 358833965Sjdp if (!STRING_EMPTY (&decl)) 358960484Sobrien string_prepend (&decl, " "); 359060484Sobrien 359160484Sobrien string_prepend (&decl, demangle_qualifier (**mangled)); 359233965Sjdp } 359360484Sobrien (*mangled)++; 359433965Sjdp break; 359533965Sjdp /* 359633965Sjdp } 359733965Sjdp */ 359833965Sjdp 359933965Sjdp /* fall through */ 360033965Sjdp default: 360133965Sjdp done = 1; 360233965Sjdp break; 360333965Sjdp } 360433965Sjdp } 360533965Sjdp 360660484Sobrien if (success) switch (**mangled) 360733965Sjdp { 360833965Sjdp /* A qualified name, such as "Outer::Inner". */ 360933965Sjdp case 'Q': 361060484Sobrien case 'K': 361160484Sobrien { 361260484Sobrien success = demangle_qualified (work, mangled, result, 0, 1); 361360484Sobrien break; 361460484Sobrien } 361560484Sobrien 361660484Sobrien /* A back reference to a previously seen squangled type */ 361760484Sobrien case 'B': 361860484Sobrien (*mangled)++; 361960484Sobrien if (!get_count (mangled, &n) || n >= work -> numb) 362060484Sobrien success = 0; 362160484Sobrien else 362260484Sobrien string_append (result, work->btypevec[n]); 362333965Sjdp break; 362433965Sjdp 362538889Sjdp case 'X': 362638889Sjdp case 'Y': 362738889Sjdp /* A template parm. We substitute the corresponding argument. */ 362838889Sjdp { 362938889Sjdp int idx; 363038889Sjdp 363138889Sjdp (*mangled)++; 363238889Sjdp idx = consume_count_with_underscores (mangled); 363338889Sjdp 363460484Sobrien if (idx == -1 363538889Sjdp || (work->tmpl_argvec && idx >= work->ntmpl_args) 363638889Sjdp || consume_count_with_underscores (mangled) == -1) 363738889Sjdp { 363838889Sjdp success = 0; 363938889Sjdp break; 364038889Sjdp } 364138889Sjdp 364238889Sjdp if (work->tmpl_argvec) 364338889Sjdp string_append (result, work->tmpl_argvec[idx]); 364438889Sjdp else 364560484Sobrien string_append_template_idx (result, idx); 364638889Sjdp 364738889Sjdp success = 1; 364838889Sjdp } 364938889Sjdp break; 365038889Sjdp 365133965Sjdp default: 365233965Sjdp success = demangle_fund_type (work, mangled, result); 365360484Sobrien if (tk == tk_none) 365460484Sobrien tk = (type_kind_t) success; 365533965Sjdp break; 365633965Sjdp } 365733965Sjdp 365833965Sjdp if (success) 365933965Sjdp { 366033965Sjdp if (!STRING_EMPTY (&decl)) 366133965Sjdp { 366233965Sjdp string_append (result, " "); 366333965Sjdp string_appends (result, &decl); 366433965Sjdp } 366533965Sjdp } 366633965Sjdp else 366760484Sobrien string_delete (result); 366833965Sjdp string_delete (&decl); 366960484Sobrien 367060484Sobrien if (success) 367160484Sobrien /* Assume an integral type, if we're not sure. */ 367260484Sobrien return (int) ((tk == tk_none) ? tk_integral : tk); 367360484Sobrien else 367460484Sobrien return 0; 367533965Sjdp} 367633965Sjdp 367733965Sjdp/* Given a pointer to a type string that represents a fundamental type 367833965Sjdp argument (int, long, unsigned int, etc) in TYPE, a pointer to the 367933965Sjdp string in which the demangled output is being built in RESULT, and 368033965Sjdp the WORK structure, decode the types and add them to the result. 368133965Sjdp 368233965Sjdp For example: 368333965Sjdp 368433965Sjdp "Ci" => "const int" 368533965Sjdp "Sl" => "signed long" 368633965Sjdp "CUs" => "const unsigned short" 368733965Sjdp 368860484Sobrien The value returned is really a type_kind_t. */ 368933965Sjdp 369033965Sjdpstatic int 3691218822Sdimdemangle_fund_type (struct work_stuff *work, 3692218822Sdim const char **mangled, string *result) 369333965Sjdp{ 369433965Sjdp int done = 0; 369533965Sjdp int success = 1; 3696218822Sdim char buf[INTBUF_SIZE + 5 /* 'int%u_t' */]; 369768765Sobrien unsigned int dec = 0; 369860484Sobrien type_kind_t tk = tk_integral; 369933965Sjdp 370033965Sjdp /* First pick off any type qualifiers. There can be more than one. */ 370133965Sjdp 370233965Sjdp while (!done) 370333965Sjdp { 370433965Sjdp switch (**mangled) 370533965Sjdp { 370633965Sjdp case 'C': 370760484Sobrien case 'V': 370860484Sobrien case 'u': 370933965Sjdp if (PRINT_ANSI_QUALIFIERS) 371033965Sjdp { 371160484Sobrien if (!STRING_EMPTY (result)) 371260484Sobrien string_prepend (result, " "); 371360484Sobrien string_prepend (result, demangle_qualifier (**mangled)); 371433965Sjdp } 371560484Sobrien (*mangled)++; 371633965Sjdp break; 371733965Sjdp case 'U': 371833965Sjdp (*mangled)++; 371933965Sjdp APPEND_BLANK (result); 372033965Sjdp string_append (result, "unsigned"); 372133965Sjdp break; 372233965Sjdp case 'S': /* signed char only */ 372333965Sjdp (*mangled)++; 372433965Sjdp APPEND_BLANK (result); 372533965Sjdp string_append (result, "signed"); 372633965Sjdp break; 372738889Sjdp case 'J': 372838889Sjdp (*mangled)++; 372938889Sjdp APPEND_BLANK (result); 373038889Sjdp string_append (result, "__complex"); 373138889Sjdp break; 373233965Sjdp default: 373333965Sjdp done = 1; 373433965Sjdp break; 373533965Sjdp } 373633965Sjdp } 373733965Sjdp 373833965Sjdp /* Now pick off the fundamental type. There can be only one. */ 373933965Sjdp 374033965Sjdp switch (**mangled) 374133965Sjdp { 374233965Sjdp case '\0': 374333965Sjdp case '_': 374433965Sjdp break; 374533965Sjdp case 'v': 374633965Sjdp (*mangled)++; 374733965Sjdp APPEND_BLANK (result); 374833965Sjdp string_append (result, "void"); 374933965Sjdp break; 375033965Sjdp case 'x': 375133965Sjdp (*mangled)++; 375233965Sjdp APPEND_BLANK (result); 375333965Sjdp string_append (result, "long long"); 375433965Sjdp break; 375533965Sjdp case 'l': 375633965Sjdp (*mangled)++; 375733965Sjdp APPEND_BLANK (result); 375833965Sjdp string_append (result, "long"); 375933965Sjdp break; 376033965Sjdp case 'i': 376133965Sjdp (*mangled)++; 376233965Sjdp APPEND_BLANK (result); 376333965Sjdp string_append (result, "int"); 376433965Sjdp break; 376533965Sjdp case 's': 376633965Sjdp (*mangled)++; 376733965Sjdp APPEND_BLANK (result); 376833965Sjdp string_append (result, "short"); 376933965Sjdp break; 377033965Sjdp case 'b': 377133965Sjdp (*mangled)++; 377233965Sjdp APPEND_BLANK (result); 377333965Sjdp string_append (result, "bool"); 377460484Sobrien tk = tk_bool; 377533965Sjdp break; 377633965Sjdp case 'c': 377733965Sjdp (*mangled)++; 377833965Sjdp APPEND_BLANK (result); 377933965Sjdp string_append (result, "char"); 378060484Sobrien tk = tk_char; 378133965Sjdp break; 378233965Sjdp case 'w': 378333965Sjdp (*mangled)++; 378433965Sjdp APPEND_BLANK (result); 378533965Sjdp string_append (result, "wchar_t"); 378660484Sobrien tk = tk_char; 378733965Sjdp break; 378833965Sjdp case 'r': 378933965Sjdp (*mangled)++; 379033965Sjdp APPEND_BLANK (result); 379133965Sjdp string_append (result, "long double"); 379260484Sobrien tk = tk_real; 379333965Sjdp break; 379433965Sjdp case 'd': 379533965Sjdp (*mangled)++; 379633965Sjdp APPEND_BLANK (result); 379733965Sjdp string_append (result, "double"); 379860484Sobrien tk = tk_real; 379933965Sjdp break; 380033965Sjdp case 'f': 380133965Sjdp (*mangled)++; 380233965Sjdp APPEND_BLANK (result); 380333965Sjdp string_append (result, "float"); 380460484Sobrien tk = tk_real; 380533965Sjdp break; 380633965Sjdp case 'G': 380733965Sjdp (*mangled)++; 380877298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 380933965Sjdp { 381033965Sjdp success = 0; 381133965Sjdp break; 381233965Sjdp } 381360484Sobrien case 'I': 381460484Sobrien (*mangled)++; 381560484Sobrien if (**mangled == '_') 381660484Sobrien { 381760484Sobrien int i; 381860484Sobrien (*mangled)++; 381960484Sobrien for (i = 0; 382060484Sobrien i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; 382160484Sobrien (*mangled)++, i++) 382260484Sobrien buf[i] = **mangled; 382360484Sobrien if (**mangled != '_') 382460484Sobrien { 382560484Sobrien success = 0; 382660484Sobrien break; 382760484Sobrien } 382860484Sobrien buf[i] = '\0'; 382960484Sobrien (*mangled)++; 383060484Sobrien } 383160484Sobrien else 383260484Sobrien { 383360484Sobrien strncpy (buf, *mangled, 2); 383460484Sobrien buf[2] = '\0'; 383560484Sobrien *mangled += min (strlen (*mangled), 2); 383660484Sobrien } 383760484Sobrien sscanf (buf, "%x", &dec); 383868765Sobrien sprintf (buf, "int%u_t", dec); 383960484Sobrien APPEND_BLANK (result); 384060484Sobrien string_append (result, buf); 384160484Sobrien break; 384260484Sobrien 384333965Sjdp /* fall through */ 384433965Sjdp /* An explicit type, such as "6mytype" or "7integer" */ 384533965Sjdp case '0': 384633965Sjdp case '1': 384733965Sjdp case '2': 384833965Sjdp case '3': 384933965Sjdp case '4': 385033965Sjdp case '5': 385133965Sjdp case '6': 385233965Sjdp case '7': 385333965Sjdp case '8': 385433965Sjdp case '9': 385560484Sobrien { 385660484Sobrien int bindex = register_Btype (work); 385760484Sobrien string btype; 385860484Sobrien string_init (&btype); 385960484Sobrien if (demangle_class_name (work, mangled, &btype)) { 386060484Sobrien remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); 386160484Sobrien APPEND_BLANK (result); 386260484Sobrien string_appends (result, &btype); 386360484Sobrien } 386460484Sobrien else 386560484Sobrien success = 0; 386660484Sobrien string_delete (&btype); 386760484Sobrien break; 386833965Sjdp } 386933965Sjdp case 't': 387060484Sobrien { 3871130561Sobrien string btype; 3872130561Sobrien string_init (&btype); 387360484Sobrien success = demangle_template (work, mangled, &btype, 0, 1, 1); 387460484Sobrien string_appends (result, &btype); 3875130561Sobrien string_delete (&btype); 387660484Sobrien break; 387760484Sobrien } 387833965Sjdp default: 387933965Sjdp success = 0; 388033965Sjdp break; 388133965Sjdp } 388233965Sjdp 388360484Sobrien return success ? ((int) tk) : 0; 388433965Sjdp} 388533965Sjdp 388633965Sjdp 388760484Sobrien/* Handle a template's value parameter for HP aCC (extension from ARM) 388860484Sobrien **mangled points to 'S' or 'U' */ 388960484Sobrien 389033965Sjdpstatic int 3891218822Sdimdo_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED, 3892218822Sdim const char **mangled, string *result) 389360484Sobrien{ 389460484Sobrien int unsigned_const; 389560484Sobrien 389660484Sobrien if (**mangled != 'U' && **mangled != 'S') 389760484Sobrien return 0; 389860484Sobrien 389960484Sobrien unsigned_const = (**mangled == 'U'); 390060484Sobrien 390160484Sobrien (*mangled)++; 390260484Sobrien 390360484Sobrien switch (**mangled) 390460484Sobrien { 390560484Sobrien case 'N': 390660484Sobrien string_append (result, "-"); 390760484Sobrien /* fall through */ 390860484Sobrien case 'P': 390960484Sobrien (*mangled)++; 391060484Sobrien break; 391160484Sobrien case 'M': 391260484Sobrien /* special case for -2^31 */ 391360484Sobrien string_append (result, "-2147483648"); 391460484Sobrien (*mangled)++; 391560484Sobrien return 1; 391660484Sobrien default: 391760484Sobrien return 0; 391860484Sobrien } 391960484Sobrien 392060484Sobrien /* We have to be looking at an integer now */ 392177298Sobrien if (!(ISDIGIT ((unsigned char)**mangled))) 392260484Sobrien return 0; 392360484Sobrien 392460484Sobrien /* We only deal with integral values for template 392560484Sobrien parameters -- so it's OK to look only for digits */ 392677298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 392760484Sobrien { 392860484Sobrien char_str[0] = **mangled; 392960484Sobrien string_append (result, char_str); 393060484Sobrien (*mangled)++; 393160484Sobrien } 393260484Sobrien 393360484Sobrien if (unsigned_const) 393460484Sobrien string_append (result, "U"); 393560484Sobrien 393660484Sobrien /* FIXME? Some day we may have 64-bit (or larger :-) ) constants 393760484Sobrien with L or LL suffixes. pai/1997-09-03 */ 393860484Sobrien 393960484Sobrien return 1; /* success */ 394060484Sobrien} 394160484Sobrien 394260484Sobrien/* Handle a template's literal parameter for HP aCC (extension from ARM) 394360484Sobrien **mangled is pointing to the 'A' */ 394460484Sobrien 394560484Sobrienstatic int 3946218822Sdimdo_hpacc_template_literal (struct work_stuff *work, const char **mangled, 3947218822Sdim string *result) 394860484Sobrien{ 394960484Sobrien int literal_len = 0; 395060484Sobrien char * recurse; 395160484Sobrien char * recurse_dem; 395260484Sobrien 395360484Sobrien if (**mangled != 'A') 395460484Sobrien return 0; 395560484Sobrien 395660484Sobrien (*mangled)++; 395760484Sobrien 395860484Sobrien literal_len = consume_count (mangled); 395960484Sobrien 396060484Sobrien if (literal_len <= 0) 396160484Sobrien return 0; 396260484Sobrien 396360484Sobrien /* Literal parameters are names of arrays, functions, etc. and the 396460484Sobrien canonical representation uses the address operator */ 396560484Sobrien string_append (result, "&"); 396660484Sobrien 396760484Sobrien /* Now recursively demangle the literal name */ 3968218822Sdim recurse = XNEWVEC (char, literal_len + 1); 396960484Sobrien memcpy (recurse, *mangled, literal_len); 397060484Sobrien recurse[literal_len] = '\000'; 397160484Sobrien 397260484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 397360484Sobrien 397460484Sobrien if (recurse_dem) 397560484Sobrien { 397660484Sobrien string_append (result, recurse_dem); 397760484Sobrien free (recurse_dem); 397860484Sobrien } 397960484Sobrien else 398060484Sobrien { 398160484Sobrien string_appendn (result, *mangled, literal_len); 398260484Sobrien } 398360484Sobrien (*mangled) += literal_len; 398460484Sobrien free (recurse); 398560484Sobrien 398660484Sobrien return 1; 398760484Sobrien} 398860484Sobrien 398960484Sobrienstatic int 3990218822Sdimsnarf_numeric_literal (const char **args, string *arg) 399160484Sobrien{ 399260484Sobrien if (**args == '-') 399360484Sobrien { 399460484Sobrien char_str[0] = '-'; 399560484Sobrien string_append (arg, char_str); 399660484Sobrien (*args)++; 399760484Sobrien } 399860484Sobrien else if (**args == '+') 399960484Sobrien (*args)++; 400060484Sobrien 400177298Sobrien if (!ISDIGIT ((unsigned char)**args)) 400260484Sobrien return 0; 400360484Sobrien 400477298Sobrien while (ISDIGIT ((unsigned char)**args)) 400560484Sobrien { 400660484Sobrien char_str[0] = **args; 400760484Sobrien string_append (arg, char_str); 400860484Sobrien (*args)++; 400960484Sobrien } 401060484Sobrien 401160484Sobrien return 1; 401260484Sobrien} 401360484Sobrien 401460484Sobrien/* Demangle the next argument, given by MANGLED into RESULT, which 401560484Sobrien *should be an uninitialized* string. It will be initialized here, 401660484Sobrien and free'd should anything go wrong. */ 401760484Sobrien 401860484Sobrienstatic int 4019218822Sdimdo_arg (struct work_stuff *work, const char **mangled, string *result) 402033965Sjdp{ 402160484Sobrien /* Remember where we started so that we can record the type, for 402260484Sobrien non-squangling type remembering. */ 402333965Sjdp const char *start = *mangled; 402433965Sjdp 402560484Sobrien string_init (result); 402660484Sobrien 402760484Sobrien if (work->nrepeats > 0) 402833965Sjdp { 402960484Sobrien --work->nrepeats; 403060484Sobrien 403160484Sobrien if (work->previous_argument == 0) 403260484Sobrien return 0; 403360484Sobrien 403460484Sobrien /* We want to reissue the previous type in this argument list. */ 403560484Sobrien string_appends (result, work->previous_argument); 403660484Sobrien return 1; 403733965Sjdp } 403860484Sobrien 403960484Sobrien if (**mangled == 'n') 404060484Sobrien { 404160484Sobrien /* A squangling-style repeat. */ 404260484Sobrien (*mangled)++; 404360484Sobrien work->nrepeats = consume_count(mangled); 404460484Sobrien 404560484Sobrien if (work->nrepeats <= 0) 404660484Sobrien /* This was not a repeat count after all. */ 404760484Sobrien return 0; 404860484Sobrien 404960484Sobrien if (work->nrepeats > 9) 405060484Sobrien { 405160484Sobrien if (**mangled != '_') 405260484Sobrien /* The repeat count should be followed by an '_' in this 405360484Sobrien case. */ 405460484Sobrien return 0; 405560484Sobrien else 405660484Sobrien (*mangled)++; 405760484Sobrien } 405860484Sobrien 405960484Sobrien /* Now, the repeat is all set up. */ 406060484Sobrien return do_arg (work, mangled, result); 406160484Sobrien } 406260484Sobrien 406360484Sobrien /* Save the result in WORK->previous_argument so that we can find it 406460484Sobrien if it's repeated. Note that saving START is not good enough: we 406560484Sobrien do not want to add additional types to the back-referenceable 406660484Sobrien type vector when processing a repeated type. */ 406760484Sobrien if (work->previous_argument) 4068130561Sobrien string_delete (work->previous_argument); 406933965Sjdp else 4070218822Sdim work->previous_argument = XNEW (string); 407160484Sobrien 407260484Sobrien if (!do_type (work, mangled, work->previous_argument)) 407360484Sobrien return 0; 407460484Sobrien 407560484Sobrien string_appends (result, work->previous_argument); 407660484Sobrien 407760484Sobrien remember_type (work, start, *mangled - start); 407860484Sobrien return 1; 407933965Sjdp} 408033965Sjdp 408133965Sjdpstatic void 4082218822Sdimremember_type (struct work_stuff *work, const char *start, int len) 408333965Sjdp{ 408433965Sjdp char *tem; 408533965Sjdp 408660484Sobrien if (work->forgetting_types) 408760484Sobrien return; 408860484Sobrien 408933965Sjdp if (work -> ntypes >= work -> typevec_size) 409033965Sjdp { 409133965Sjdp if (work -> typevec_size == 0) 409233965Sjdp { 409333965Sjdp work -> typevec_size = 3; 4094218822Sdim work -> typevec = XNEWVEC (char *, work->typevec_size); 409533965Sjdp } 409633965Sjdp else 409733965Sjdp { 409833965Sjdp work -> typevec_size *= 2; 409938889Sjdp work -> typevec 4100218822Sdim = XRESIZEVEC (char *, work->typevec, work->typevec_size); 410133965Sjdp } 410233965Sjdp } 4103218822Sdim tem = XNEWVEC (char, len + 1); 410433965Sjdp memcpy (tem, start, len); 410533965Sjdp tem[len] = '\0'; 410633965Sjdp work -> typevec[work -> ntypes++] = tem; 410733965Sjdp} 410833965Sjdp 410960484Sobrien 411060484Sobrien/* Remember a K type class qualifier. */ 411160484Sobrienstatic void 4112218822Sdimremember_Ktype (struct work_stuff *work, const char *start, int len) 411360484Sobrien{ 411460484Sobrien char *tem; 411560484Sobrien 411660484Sobrien if (work -> numk >= work -> ksize) 411760484Sobrien { 411860484Sobrien if (work -> ksize == 0) 411960484Sobrien { 412060484Sobrien work -> ksize = 5; 4121218822Sdim work -> ktypevec = XNEWVEC (char *, work->ksize); 412260484Sobrien } 412360484Sobrien else 412460484Sobrien { 412560484Sobrien work -> ksize *= 2; 412660484Sobrien work -> ktypevec 4127218822Sdim = XRESIZEVEC (char *, work->ktypevec, work->ksize); 412860484Sobrien } 412960484Sobrien } 4130218822Sdim tem = XNEWVEC (char, len + 1); 413160484Sobrien memcpy (tem, start, len); 413260484Sobrien tem[len] = '\0'; 413360484Sobrien work -> ktypevec[work -> numk++] = tem; 413460484Sobrien} 413560484Sobrien 413660484Sobrien/* Register a B code, and get an index for it. B codes are registered 413760484Sobrien as they are seen, rather than as they are completed, so map<temp<char> > 413860484Sobrien registers map<temp<char> > as B0, and temp<char> as B1 */ 413960484Sobrien 414060484Sobrienstatic int 4141218822Sdimregister_Btype (struct work_stuff *work) 414260484Sobrien{ 414360484Sobrien int ret; 414460484Sobrien 414560484Sobrien if (work -> numb >= work -> bsize) 414660484Sobrien { 414760484Sobrien if (work -> bsize == 0) 414860484Sobrien { 414960484Sobrien work -> bsize = 5; 4150218822Sdim work -> btypevec = XNEWVEC (char *, work->bsize); 415160484Sobrien } 415260484Sobrien else 415360484Sobrien { 415460484Sobrien work -> bsize *= 2; 415560484Sobrien work -> btypevec 4156218822Sdim = XRESIZEVEC (char *, work->btypevec, work->bsize); 415760484Sobrien } 415860484Sobrien } 415960484Sobrien ret = work -> numb++; 416060484Sobrien work -> btypevec[ret] = NULL; 416160484Sobrien return(ret); 416260484Sobrien} 416360484Sobrien 416460484Sobrien/* Store a value into a previously registered B code type. */ 416560484Sobrien 416660484Sobrienstatic void 4167218822Sdimremember_Btype (struct work_stuff *work, const char *start, 4168218822Sdim int len, int index) 416960484Sobrien{ 417060484Sobrien char *tem; 417160484Sobrien 4172218822Sdim tem = XNEWVEC (char, len + 1); 417360484Sobrien memcpy (tem, start, len); 417460484Sobrien tem[len] = '\0'; 417560484Sobrien work -> btypevec[index] = tem; 417660484Sobrien} 417760484Sobrien 417860484Sobrien/* Lose all the info related to B and K type codes. */ 417960484Sobrienstatic void 4180218822Sdimforget_B_and_K_types (struct work_stuff *work) 418160484Sobrien{ 418260484Sobrien int i; 418360484Sobrien 418460484Sobrien while (work -> numk > 0) 418560484Sobrien { 418660484Sobrien i = --(work -> numk); 418760484Sobrien if (work -> ktypevec[i] != NULL) 418860484Sobrien { 418960484Sobrien free (work -> ktypevec[i]); 419060484Sobrien work -> ktypevec[i] = NULL; 419160484Sobrien } 419260484Sobrien } 419360484Sobrien 419460484Sobrien while (work -> numb > 0) 419560484Sobrien { 419660484Sobrien i = --(work -> numb); 419760484Sobrien if (work -> btypevec[i] != NULL) 419860484Sobrien { 419960484Sobrien free (work -> btypevec[i]); 420060484Sobrien work -> btypevec[i] = NULL; 420160484Sobrien } 420260484Sobrien } 420360484Sobrien} 420433965Sjdp/* Forget the remembered types, but not the type vector itself. */ 420533965Sjdp 420633965Sjdpstatic void 4207218822Sdimforget_types (struct work_stuff *work) 420833965Sjdp{ 420933965Sjdp int i; 421033965Sjdp 421133965Sjdp while (work -> ntypes > 0) 421233965Sjdp { 421333965Sjdp i = --(work -> ntypes); 421433965Sjdp if (work -> typevec[i] != NULL) 421533965Sjdp { 421633965Sjdp free (work -> typevec[i]); 421733965Sjdp work -> typevec[i] = NULL; 421833965Sjdp } 421933965Sjdp } 422033965Sjdp} 422133965Sjdp 422233965Sjdp/* Process the argument list part of the signature, after any class spec 422333965Sjdp has been consumed, as well as the first 'F' character (if any). For 422433965Sjdp example: 422533965Sjdp 422633965Sjdp "__als__3fooRT0" => process "RT0" 422733965Sjdp "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" 422833965Sjdp 422933965Sjdp DECLP must be already initialised, usually non-empty. It won't be freed 423033965Sjdp on failure. 423133965Sjdp 423233965Sjdp Note that g++ differs significantly from ARM and lucid style mangling 423333965Sjdp with regards to references to previously seen types. For example, given 423433965Sjdp the source fragment: 423533965Sjdp 423633965Sjdp class foo { 423733965Sjdp public: 423833965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); 423933965Sjdp }; 424033965Sjdp 424133965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 424233965Sjdp void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 424333965Sjdp 424433965Sjdp g++ produces the names: 424533965Sjdp 424633965Sjdp __3fooiRT0iT2iT2 424733965Sjdp foo__FiR3fooiT1iT1 424833965Sjdp 424933965Sjdp while lcc (and presumably other ARM style compilers as well) produces: 425033965Sjdp 425133965Sjdp foo__FiR3fooT1T2T1T2 425233965Sjdp __ct__3fooFiR3fooT1T2T1T2 425333965Sjdp 425460484Sobrien Note that g++ bases its type numbers starting at zero and counts all 425560484Sobrien previously seen types, while lucid/ARM bases its type numbers starting 425633965Sjdp at one and only considers types after it has seen the 'F' character 425733965Sjdp indicating the start of the function args. For lucid/ARM style, we 425833965Sjdp account for this difference by discarding any previously seen types when 425933965Sjdp we see the 'F' character, and subtracting one from the type number 426033965Sjdp reference. 426133965Sjdp 426233965Sjdp */ 426333965Sjdp 426433965Sjdpstatic int 4265218822Sdimdemangle_args (struct work_stuff *work, const char **mangled, 4266218822Sdim string *declp) 426733965Sjdp{ 426833965Sjdp string arg; 426933965Sjdp int need_comma = 0; 427033965Sjdp int r; 427133965Sjdp int t; 427233965Sjdp const char *tem; 427333965Sjdp char temptype; 427433965Sjdp 427533965Sjdp if (PRINT_ARG_TYPES) 427633965Sjdp { 427733965Sjdp string_append (declp, "("); 427833965Sjdp if (**mangled == '\0') 427933965Sjdp { 428033965Sjdp string_append (declp, "void"); 428133965Sjdp } 428233965Sjdp } 428333965Sjdp 428460484Sobrien while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') 428560484Sobrien || work->nrepeats > 0) 428633965Sjdp { 428733965Sjdp if ((**mangled == 'N') || (**mangled == 'T')) 428833965Sjdp { 428933965Sjdp temptype = *(*mangled)++; 429060484Sobrien 429133965Sjdp if (temptype == 'N') 429233965Sjdp { 429333965Sjdp if (!get_count (mangled, &r)) 429433965Sjdp { 429533965Sjdp return (0); 429633965Sjdp } 429733965Sjdp } 429833965Sjdp else 429933965Sjdp { 430033965Sjdp r = 1; 430133965Sjdp } 430260484Sobrien if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) 430333965Sjdp { 430433965Sjdp /* If we have 10 or more types we might have more than a 1 digit 430533965Sjdp index so we'll have to consume the whole count here. This 430633965Sjdp will lose if the next thing is a type name preceded by a 430733965Sjdp count but it's impossible to demangle that case properly 430833965Sjdp anyway. Eg if we already have 12 types is T12Pc "(..., type1, 430933965Sjdp Pc, ...)" or "(..., type12, char *, ...)" */ 431060484Sobrien if ((t = consume_count(mangled)) <= 0) 431133965Sjdp { 431233965Sjdp return (0); 431333965Sjdp } 431433965Sjdp } 431533965Sjdp else 431633965Sjdp { 431733965Sjdp if (!get_count (mangled, &t)) 431833965Sjdp { 431933965Sjdp return (0); 432033965Sjdp } 432133965Sjdp } 432260484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 432333965Sjdp { 432433965Sjdp t--; 432533965Sjdp } 432633965Sjdp /* Validate the type index. Protect against illegal indices from 432733965Sjdp malformed type strings. */ 432833965Sjdp if ((t < 0) || (t >= work -> ntypes)) 432933965Sjdp { 433033965Sjdp return (0); 433133965Sjdp } 433260484Sobrien while (work->nrepeats > 0 || --r >= 0) 433333965Sjdp { 433433965Sjdp tem = work -> typevec[t]; 433533965Sjdp if (need_comma && PRINT_ARG_TYPES) 433633965Sjdp { 433733965Sjdp string_append (declp, ", "); 433833965Sjdp } 433933965Sjdp if (!do_arg (work, &tem, &arg)) 434033965Sjdp { 434133965Sjdp return (0); 434233965Sjdp } 434333965Sjdp if (PRINT_ARG_TYPES) 434433965Sjdp { 434533965Sjdp string_appends (declp, &arg); 434633965Sjdp } 434733965Sjdp string_delete (&arg); 434833965Sjdp need_comma = 1; 434933965Sjdp } 435033965Sjdp } 435133965Sjdp else 435233965Sjdp { 435360484Sobrien if (need_comma && PRINT_ARG_TYPES) 435460484Sobrien string_append (declp, ", "); 435533965Sjdp if (!do_arg (work, mangled, &arg)) 435660484Sobrien return (0); 435733965Sjdp if (PRINT_ARG_TYPES) 435860484Sobrien string_appends (declp, &arg); 435933965Sjdp string_delete (&arg); 436033965Sjdp need_comma = 1; 436133965Sjdp } 436233965Sjdp } 436333965Sjdp 436433965Sjdp if (**mangled == 'e') 436533965Sjdp { 436633965Sjdp (*mangled)++; 436733965Sjdp if (PRINT_ARG_TYPES) 436833965Sjdp { 436933965Sjdp if (need_comma) 437033965Sjdp { 437133965Sjdp string_append (declp, ","); 437233965Sjdp } 437333965Sjdp string_append (declp, "..."); 437433965Sjdp } 437533965Sjdp } 437633965Sjdp 437733965Sjdp if (PRINT_ARG_TYPES) 437833965Sjdp { 437933965Sjdp string_append (declp, ")"); 438033965Sjdp } 438133965Sjdp return (1); 438233965Sjdp} 438333965Sjdp 438460484Sobrien/* Like demangle_args, but for demangling the argument lists of function 438560484Sobrien and method pointers or references, not top-level declarations. */ 438660484Sobrien 438760484Sobrienstatic int 4388218822Sdimdemangle_nested_args (struct work_stuff *work, const char **mangled, 4389218822Sdim string *declp) 439060484Sobrien{ 439160484Sobrien string* saved_previous_argument; 439260484Sobrien int result; 439360484Sobrien int saved_nrepeats; 439460484Sobrien 439560484Sobrien /* The G++ name-mangling algorithm does not remember types on nested 439660484Sobrien argument lists, unless -fsquangling is used, and in that case the 439760484Sobrien type vector updated by remember_type is not used. So, we turn 439860484Sobrien off remembering of types here. */ 439960484Sobrien ++work->forgetting_types; 440060484Sobrien 440160484Sobrien /* For the repeat codes used with -fsquangling, we must keep track of 440260484Sobrien the last argument. */ 440360484Sobrien saved_previous_argument = work->previous_argument; 440460484Sobrien saved_nrepeats = work->nrepeats; 440560484Sobrien work->previous_argument = 0; 440660484Sobrien work->nrepeats = 0; 440760484Sobrien 440860484Sobrien /* Actually demangle the arguments. */ 440960484Sobrien result = demangle_args (work, mangled, declp); 441060484Sobrien 441160484Sobrien /* Restore the previous_argument field. */ 441260484Sobrien if (work->previous_argument) 4413130561Sobrien { 4414130561Sobrien string_delete (work->previous_argument); 4415130561Sobrien free ((char *) work->previous_argument); 4416130561Sobrien } 441760484Sobrien work->previous_argument = saved_previous_argument; 441860484Sobrien --work->forgetting_types; 441960484Sobrien work->nrepeats = saved_nrepeats; 442060484Sobrien 442160484Sobrien return result; 442260484Sobrien} 442360484Sobrien 442433965Sjdpstatic void 4425218822Sdimdemangle_function_name (struct work_stuff *work, const char **mangled, 4426218822Sdim string *declp, const char *scan) 442733965Sjdp{ 442860484Sobrien size_t i; 442933965Sjdp string type; 443033965Sjdp const char *tem; 443133965Sjdp 443233965Sjdp string_appendn (declp, (*mangled), scan - (*mangled)); 443333965Sjdp string_need (declp, 1); 443433965Sjdp *(declp -> p) = '\0'; 443533965Sjdp 443633965Sjdp /* Consume the function name, including the "__" separating the name 443733965Sjdp from the signature. We are guaranteed that SCAN points to the 443833965Sjdp separator. */ 443933965Sjdp 444033965Sjdp (*mangled) = scan + 2; 444160484Sobrien /* We may be looking at an instantiation of a template function: 444260484Sobrien foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a 444360484Sobrien following _F marks the start of the function arguments. Handle 444460484Sobrien the template arguments first. */ 444533965Sjdp 444660484Sobrien if (HP_DEMANGLING && (**mangled == 'X')) 444733965Sjdp { 444860484Sobrien demangle_arm_hp_template (work, mangled, 0, declp); 444960484Sobrien /* This leaves MANGLED pointing to the 'F' marking func args */ 445060484Sobrien } 445133965Sjdp 445260484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 445360484Sobrien { 445460484Sobrien 445533965Sjdp /* See if we have an ARM style constructor or destructor operator. 445633965Sjdp If so, then just record it, clear the decl, and return. 445733965Sjdp We can't build the actual constructor/destructor decl until later, 445833965Sjdp when we recover the class name from the signature. */ 445933965Sjdp 446033965Sjdp if (strcmp (declp -> b, "__ct") == 0) 446133965Sjdp { 446233965Sjdp work -> constructor += 1; 446333965Sjdp string_clear (declp); 446433965Sjdp return; 446533965Sjdp } 446633965Sjdp else if (strcmp (declp -> b, "__dt") == 0) 446733965Sjdp { 446833965Sjdp work -> destructor += 1; 446933965Sjdp string_clear (declp); 447033965Sjdp return; 447133965Sjdp } 447233965Sjdp } 447333965Sjdp 447460484Sobrien if (declp->p - declp->b >= 3 447533965Sjdp && declp->b[0] == 'o' 447633965Sjdp && declp->b[1] == 'p' 447733965Sjdp && strchr (cplus_markers, declp->b[2]) != NULL) 447833965Sjdp { 447933965Sjdp /* see if it's an assignment expression */ 448033965Sjdp if (declp->p - declp->b >= 10 /* op$assign_ */ 448133965Sjdp && memcmp (declp->b + 3, "assign_", 7) == 0) 448233965Sjdp { 448377298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 448433965Sjdp { 448560484Sobrien int len = declp->p - declp->b - 10; 448660484Sobrien if ((int) strlen (optable[i].in) == len 448733965Sjdp && memcmp (optable[i].in, declp->b + 10, len) == 0) 448833965Sjdp { 448933965Sjdp string_clear (declp); 449033965Sjdp string_append (declp, "operator"); 449133965Sjdp string_append (declp, optable[i].out); 449233965Sjdp string_append (declp, "="); 449333965Sjdp break; 449433965Sjdp } 449533965Sjdp } 449633965Sjdp } 449733965Sjdp else 449833965Sjdp { 449977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 450033965Sjdp { 450133965Sjdp int len = declp->p - declp->b - 3; 450260484Sobrien if ((int) strlen (optable[i].in) == len 450333965Sjdp && memcmp (optable[i].in, declp->b + 3, len) == 0) 450433965Sjdp { 450533965Sjdp string_clear (declp); 450633965Sjdp string_append (declp, "operator"); 450733965Sjdp string_append (declp, optable[i].out); 450833965Sjdp break; 450933965Sjdp } 451033965Sjdp } 451133965Sjdp } 451233965Sjdp } 451333965Sjdp else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 451433965Sjdp && strchr (cplus_markers, declp->b[4]) != NULL) 451533965Sjdp { 451633965Sjdp /* type conversion operator */ 451733965Sjdp tem = declp->b + 5; 451833965Sjdp if (do_type (work, &tem, &type)) 451933965Sjdp { 452033965Sjdp string_clear (declp); 452133965Sjdp string_append (declp, "operator "); 452233965Sjdp string_appends (declp, &type); 452333965Sjdp string_delete (&type); 452433965Sjdp } 452533965Sjdp } 452633965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 452733965Sjdp && declp->b[2] == 'o' && declp->b[3] == 'p') 452833965Sjdp { 452933965Sjdp /* ANSI. */ 453033965Sjdp /* type conversion operator. */ 453133965Sjdp tem = declp->b + 4; 453233965Sjdp if (do_type (work, &tem, &type)) 453333965Sjdp { 453433965Sjdp string_clear (declp); 453533965Sjdp string_append (declp, "operator "); 453633965Sjdp string_appends (declp, &type); 453733965Sjdp string_delete (&type); 453833965Sjdp } 453933965Sjdp } 454033965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 454177298Sobrien && ISLOWER((unsigned char)declp->b[2]) 454277298Sobrien && ISLOWER((unsigned char)declp->b[3])) 454333965Sjdp { 454433965Sjdp if (declp->b[4] == '\0') 454533965Sjdp { 454633965Sjdp /* Operator. */ 454777298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 454833965Sjdp { 454933965Sjdp if (strlen (optable[i].in) == 2 455033965Sjdp && memcmp (optable[i].in, declp->b + 2, 2) == 0) 455133965Sjdp { 455233965Sjdp string_clear (declp); 455333965Sjdp string_append (declp, "operator"); 455433965Sjdp string_append (declp, optable[i].out); 455533965Sjdp break; 455633965Sjdp } 455733965Sjdp } 455833965Sjdp } 455933965Sjdp else 456033965Sjdp { 456133965Sjdp if (declp->b[2] == 'a' && declp->b[5] == '\0') 456233965Sjdp { 456333965Sjdp /* Assignment. */ 456477298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 456533965Sjdp { 456633965Sjdp if (strlen (optable[i].in) == 3 456733965Sjdp && memcmp (optable[i].in, declp->b + 2, 3) == 0) 456833965Sjdp { 456933965Sjdp string_clear (declp); 457033965Sjdp string_append (declp, "operator"); 457133965Sjdp string_append (declp, optable[i].out); 457233965Sjdp break; 457360484Sobrien } 457433965Sjdp } 457533965Sjdp } 457633965Sjdp } 457733965Sjdp } 457833965Sjdp} 457933965Sjdp 458033965Sjdp/* a mini string-handling package */ 458133965Sjdp 458233965Sjdpstatic void 4583218822Sdimstring_need (string *s, int n) 458433965Sjdp{ 458533965Sjdp int tem; 458633965Sjdp 458733965Sjdp if (s->b == NULL) 458833965Sjdp { 458933965Sjdp if (n < 32) 459033965Sjdp { 459133965Sjdp n = 32; 459233965Sjdp } 4593218822Sdim s->p = s->b = XNEWVEC (char, n); 459433965Sjdp s->e = s->b + n; 459533965Sjdp } 459633965Sjdp else if (s->e - s->p < n) 459733965Sjdp { 459833965Sjdp tem = s->p - s->b; 459933965Sjdp n += tem; 460033965Sjdp n *= 2; 4601218822Sdim s->b = XRESIZEVEC (char, s->b, n); 460233965Sjdp s->p = s->b + tem; 460333965Sjdp s->e = s->b + n; 460433965Sjdp } 460533965Sjdp} 460633965Sjdp 460733965Sjdpstatic void 4608218822Sdimstring_delete (string *s) 460933965Sjdp{ 461033965Sjdp if (s->b != NULL) 461133965Sjdp { 461233965Sjdp free (s->b); 461333965Sjdp s->b = s->e = s->p = NULL; 461433965Sjdp } 461533965Sjdp} 461633965Sjdp 461733965Sjdpstatic void 4618218822Sdimstring_init (string *s) 461933965Sjdp{ 462033965Sjdp s->b = s->p = s->e = NULL; 462133965Sjdp} 462233965Sjdp 462360484Sobrienstatic void 4624218822Sdimstring_clear (string *s) 462533965Sjdp{ 462633965Sjdp s->p = s->b; 462733965Sjdp} 462833965Sjdp 462933965Sjdp#if 0 463033965Sjdp 463133965Sjdpstatic int 4632218822Sdimstring_empty (string *s) 463333965Sjdp{ 463433965Sjdp return (s->b == s->p); 463533965Sjdp} 463633965Sjdp 463733965Sjdp#endif 463833965Sjdp 463933965Sjdpstatic void 4640218822Sdimstring_append (string *p, const char *s) 464133965Sjdp{ 464233965Sjdp int n; 464333965Sjdp if (s == NULL || *s == '\0') 464433965Sjdp return; 464533965Sjdp n = strlen (s); 464633965Sjdp string_need (p, n); 464733965Sjdp memcpy (p->p, s, n); 464833965Sjdp p->p += n; 464933965Sjdp} 465033965Sjdp 465133965Sjdpstatic void 4652218822Sdimstring_appends (string *p, string *s) 465333965Sjdp{ 465433965Sjdp int n; 465533965Sjdp 465633965Sjdp if (s->b != s->p) 465733965Sjdp { 465833965Sjdp n = s->p - s->b; 465933965Sjdp string_need (p, n); 466033965Sjdp memcpy (p->p, s->b, n); 466133965Sjdp p->p += n; 466233965Sjdp } 466333965Sjdp} 466433965Sjdp 466533965Sjdpstatic void 4666218822Sdimstring_appendn (string *p, const char *s, int n) 466733965Sjdp{ 466833965Sjdp if (n != 0) 466933965Sjdp { 467033965Sjdp string_need (p, n); 467133965Sjdp memcpy (p->p, s, n); 467233965Sjdp p->p += n; 467333965Sjdp } 467433965Sjdp} 467533965Sjdp 467633965Sjdpstatic void 4677218822Sdimstring_prepend (string *p, const char *s) 467833965Sjdp{ 467933965Sjdp if (s != NULL && *s != '\0') 468033965Sjdp { 468133965Sjdp string_prependn (p, s, strlen (s)); 468233965Sjdp } 468333965Sjdp} 468433965Sjdp 468533965Sjdpstatic void 4686218822Sdimstring_prepends (string *p, string *s) 468733965Sjdp{ 468833965Sjdp if (s->b != s->p) 468933965Sjdp { 469033965Sjdp string_prependn (p, s->b, s->p - s->b); 469133965Sjdp } 469233965Sjdp} 469333965Sjdp 469433965Sjdpstatic void 4695218822Sdimstring_prependn (string *p, const char *s, int n) 469633965Sjdp{ 469733965Sjdp char *q; 469833965Sjdp 469933965Sjdp if (n != 0) 470033965Sjdp { 470133965Sjdp string_need (p, n); 470233965Sjdp for (q = p->p - 1; q >= p->b; q--) 470333965Sjdp { 470433965Sjdp q[n] = q[0]; 470533965Sjdp } 470633965Sjdp memcpy (p->b, s, n); 470733965Sjdp p->p += n; 470833965Sjdp } 470933965Sjdp} 471033965Sjdp 471160484Sobrienstatic void 4712218822Sdimstring_append_template_idx (string *s, int idx) 471360484Sobrien{ 471460484Sobrien char buf[INTBUF_SIZE + 1 /* 'T' */]; 471560484Sobrien sprintf(buf, "T%d", idx); 471660484Sobrien string_append (s, buf); 471760484Sobrien} 4718