cplus-dem.c revision 77298
160484Sobrien/* Demangler for GNU C++ 277298Sobrien Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 377298Sobrien 2000 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 1433965SjdpLibiberty is distributed in the hope that it will be useful, 1533965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1633965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1733965SjdpLibrary General Public License for more details. 1833965Sjdp 1933965SjdpYou should have received a copy of the GNU Library General Public 2033965SjdpLicense along with libiberty; see the file COPYING.LIB. If 2133965Sjdpnot, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 2233965SjdpBoston, MA 02111-1307, USA. */ 2333965Sjdp 2433965Sjdp/* This file exports two functions; cplus_mangle_opname and cplus_demangle. 2533965Sjdp 2633965Sjdp This file imports xmalloc and xrealloc, which are like malloc and 2733965Sjdp realloc except that they generate a fatal error if there is no 2833965Sjdp available memory. */ 2933965Sjdp 3033965Sjdp/* This file lives in both GCC and libiberty. When making changes, please 3133965Sjdp try not to break either. */ 3233965Sjdp 3360484Sobrien#ifdef HAVE_CONFIG_H 3460484Sobrien#include "config.h" 3560484Sobrien#endif 3660484Sobrien 3777298Sobrien#include "safe-ctype.h" 3877298Sobrien 3960484Sobrien#include <sys/types.h> 4033965Sjdp#include <string.h> 4133965Sjdp#include <stdio.h> 4233965Sjdp 4360484Sobrien#ifdef HAVE_STDLIB_H 4460484Sobrien#include <stdlib.h> 4560484Sobrien#else 4660484Sobrienchar * malloc (); 4760484Sobrienchar * realloc (); 4860484Sobrien#endif 4960484Sobrien 5033965Sjdp#include <demangle.h> 5133965Sjdp#undef CURRENT_DEMANGLING_STYLE 5233965Sjdp#define CURRENT_DEMANGLING_STYLE work->options 5333965Sjdp 5460484Sobrien#include "libiberty.h" 5533965Sjdp 5677298Sobrienstatic char *ada_demangle PARAMS ((const char *, int)); 5777298Sobrien 5860484Sobrien#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) 5960484Sobrien 6060484Sobrien/* A value at least one greater than the maximum number of characters 6160484Sobrien that will be output when using the `%d' format with `printf'. */ 6260484Sobrien#define INTBUF_SIZE 32 6360484Sobrien 6460484Sobrienextern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN; 6560484Sobrien 6633965Sjdpstatic const char *mystrstr PARAMS ((const char *, const char *)); 6733965Sjdp 6833965Sjdpstatic const char * 6933965Sjdpmystrstr (s1, s2) 7033965Sjdp const char *s1, *s2; 7133965Sjdp{ 7233965Sjdp register const char *p = s1; 7333965Sjdp register int len = strlen (s2); 7433965Sjdp 7533965Sjdp for (; (p = strchr (p, *s2)) != 0; p++) 7633965Sjdp { 7733965Sjdp if (strncmp (p, s2, len) == 0) 7833965Sjdp { 7933965Sjdp return (p); 8033965Sjdp } 8133965Sjdp } 8233965Sjdp return (0); 8333965Sjdp} 8433965Sjdp 8533965Sjdp/* In order to allow a single demangler executable to demangle strings 8633965Sjdp using various common values of CPLUS_MARKER, as well as any specific 8733965Sjdp one set at compile time, we maintain a string containing all the 8833965Sjdp commonly used ones, and check to see if the marker we are looking for 8933965Sjdp is in that string. CPLUS_MARKER is usually '$' on systems where the 9033965Sjdp assembler can deal with that. Where the assembler can't, it's usually 9133965Sjdp '.' (but on many systems '.' is used for other things). We put the 9233965Sjdp current defined CPLUS_MARKER first (which defaults to '$'), followed 9333965Sjdp by the next most common value, followed by an explicit '$' in case 9433965Sjdp the value of CPLUS_MARKER is not '$'. 9533965Sjdp 9633965Sjdp We could avoid this if we could just get g++ to tell us what the actual 9733965Sjdp cplus marker character is as part of the debug information, perhaps by 9833965Sjdp ensuring that it is the character that terminates the gcc<n>_compiled 9933965Sjdp marker symbol (FIXME). */ 10033965Sjdp 10133965Sjdp#if !defined (CPLUS_MARKER) 10233965Sjdp#define CPLUS_MARKER '$' 10333965Sjdp#endif 10433965Sjdp 10577298Sobrienenum demangling_styles current_demangling_style = auto_demangling; 10633965Sjdp 10733965Sjdpstatic char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; 10833965Sjdp 10960484Sobrienstatic char char_str[2] = { '\000', '\000' }; 11060484Sobrien 11133965Sjdpvoid 11233965Sjdpset_cplus_marker_for_demangling (ch) 11333965Sjdp int ch; 11433965Sjdp{ 11533965Sjdp cplus_markers[0] = ch; 11633965Sjdp} 11733965Sjdp 11860484Sobrientypedef struct string /* Beware: these aren't required to be */ 11960484Sobrien{ /* '\0' terminated. */ 12060484Sobrien char *b; /* pointer to start of string */ 12160484Sobrien char *p; /* pointer after last character */ 12260484Sobrien char *e; /* pointer after end of allocated space */ 12360484Sobrien} string; 12460484Sobrien 12533965Sjdp/* Stuff that is shared between sub-routines. 12633965Sjdp Using a shared structure allows cplus_demangle to be reentrant. */ 12733965Sjdp 12833965Sjdpstruct work_stuff 12933965Sjdp{ 13033965Sjdp int options; 13133965Sjdp char **typevec; 13260484Sobrien char **ktypevec; 13360484Sobrien char **btypevec; 13460484Sobrien int numk; 13560484Sobrien int numb; 13660484Sobrien int ksize; 13760484Sobrien int bsize; 13833965Sjdp int ntypes; 13933965Sjdp int typevec_size; 14033965Sjdp int constructor; 14133965Sjdp int destructor; 14233965Sjdp int static_type; /* A static member function */ 14360484Sobrien int temp_start; /* index in demangled to start of template args */ 14460484Sobrien int type_quals; /* The type qualifiers. */ 14560484Sobrien int dllimported; /* Symbol imported from a PE DLL */ 14638889Sjdp char **tmpl_argvec; /* Template function arguments. */ 14738889Sjdp int ntmpl_args; /* The number of template function arguments. */ 14860484Sobrien int forgetting_types; /* Nonzero if we are not remembering the types 14960484Sobrien we see. */ 15060484Sobrien string* previous_argument; /* The last function argument demangled. */ 15160484Sobrien int nrepeats; /* The number of times to repeat the previous 15260484Sobrien argument. */ 15333965Sjdp}; 15433965Sjdp 15533965Sjdp#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) 15633965Sjdp#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) 15733965Sjdp 15833965Sjdpstatic const struct optable 15933965Sjdp{ 16033965Sjdp const char *in; 16133965Sjdp const char *out; 16233965Sjdp int flags; 16333965Sjdp} optable[] = { 16433965Sjdp {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ 16533965Sjdp {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ 16633965Sjdp {"new", " new", 0}, /* old (1.91, and 1.x) */ 16733965Sjdp {"delete", " delete", 0}, /* old (1.91, and 1.x) */ 16833965Sjdp {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ 16933965Sjdp {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ 17033965Sjdp {"as", "=", DMGL_ANSI}, /* ansi */ 17133965Sjdp {"ne", "!=", DMGL_ANSI}, /* old, ansi */ 17233965Sjdp {"eq", "==", DMGL_ANSI}, /* old, ansi */ 17333965Sjdp {"ge", ">=", DMGL_ANSI}, /* old, ansi */ 17433965Sjdp {"gt", ">", DMGL_ANSI}, /* old, ansi */ 17533965Sjdp {"le", "<=", DMGL_ANSI}, /* old, ansi */ 17633965Sjdp {"lt", "<", DMGL_ANSI}, /* old, ansi */ 17733965Sjdp {"plus", "+", 0}, /* old */ 17833965Sjdp {"pl", "+", DMGL_ANSI}, /* ansi */ 17933965Sjdp {"apl", "+=", DMGL_ANSI}, /* ansi */ 18033965Sjdp {"minus", "-", 0}, /* old */ 18133965Sjdp {"mi", "-", DMGL_ANSI}, /* ansi */ 18233965Sjdp {"ami", "-=", DMGL_ANSI}, /* ansi */ 18333965Sjdp {"mult", "*", 0}, /* old */ 18433965Sjdp {"ml", "*", DMGL_ANSI}, /* ansi */ 18533965Sjdp {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ 18633965Sjdp {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ 18733965Sjdp {"convert", "+", 0}, /* old (unary +) */ 18833965Sjdp {"negate", "-", 0}, /* old (unary -) */ 18933965Sjdp {"trunc_mod", "%", 0}, /* old */ 19033965Sjdp {"md", "%", DMGL_ANSI}, /* ansi */ 19133965Sjdp {"amd", "%=", DMGL_ANSI}, /* ansi */ 19233965Sjdp {"trunc_div", "/", 0}, /* old */ 19333965Sjdp {"dv", "/", DMGL_ANSI}, /* ansi */ 19433965Sjdp {"adv", "/=", DMGL_ANSI}, /* ansi */ 19533965Sjdp {"truth_andif", "&&", 0}, /* old */ 19633965Sjdp {"aa", "&&", DMGL_ANSI}, /* ansi */ 19733965Sjdp {"truth_orif", "||", 0}, /* old */ 19833965Sjdp {"oo", "||", DMGL_ANSI}, /* ansi */ 19933965Sjdp {"truth_not", "!", 0}, /* old */ 20033965Sjdp {"nt", "!", DMGL_ANSI}, /* ansi */ 20133965Sjdp {"postincrement","++", 0}, /* old */ 20233965Sjdp {"pp", "++", DMGL_ANSI}, /* ansi */ 20333965Sjdp {"postdecrement","--", 0}, /* old */ 20433965Sjdp {"mm", "--", DMGL_ANSI}, /* ansi */ 20533965Sjdp {"bit_ior", "|", 0}, /* old */ 20633965Sjdp {"or", "|", DMGL_ANSI}, /* ansi */ 20733965Sjdp {"aor", "|=", DMGL_ANSI}, /* ansi */ 20833965Sjdp {"bit_xor", "^", 0}, /* old */ 20933965Sjdp {"er", "^", DMGL_ANSI}, /* ansi */ 21033965Sjdp {"aer", "^=", DMGL_ANSI}, /* ansi */ 21133965Sjdp {"bit_and", "&", 0}, /* old */ 21233965Sjdp {"ad", "&", DMGL_ANSI}, /* ansi */ 21333965Sjdp {"aad", "&=", DMGL_ANSI}, /* ansi */ 21433965Sjdp {"bit_not", "~", 0}, /* old */ 21533965Sjdp {"co", "~", DMGL_ANSI}, /* ansi */ 21633965Sjdp {"call", "()", 0}, /* old */ 21733965Sjdp {"cl", "()", DMGL_ANSI}, /* ansi */ 21833965Sjdp {"alshift", "<<", 0}, /* old */ 21933965Sjdp {"ls", "<<", DMGL_ANSI}, /* ansi */ 22033965Sjdp {"als", "<<=", DMGL_ANSI}, /* ansi */ 22133965Sjdp {"arshift", ">>", 0}, /* old */ 22233965Sjdp {"rs", ">>", DMGL_ANSI}, /* ansi */ 22333965Sjdp {"ars", ">>=", DMGL_ANSI}, /* ansi */ 22433965Sjdp {"component", "->", 0}, /* old */ 22533965Sjdp {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ 22633965Sjdp {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ 22733965Sjdp {"indirect", "*", 0}, /* old */ 22833965Sjdp {"method_call", "->()", 0}, /* old */ 22933965Sjdp {"addr", "&", 0}, /* old (unary &) */ 23033965Sjdp {"array", "[]", 0}, /* old */ 23133965Sjdp {"vc", "[]", DMGL_ANSI}, /* ansi */ 23233965Sjdp {"compound", ", ", 0}, /* old */ 23333965Sjdp {"cm", ", ", DMGL_ANSI}, /* ansi */ 23433965Sjdp {"cond", "?:", 0}, /* old */ 23533965Sjdp {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ 23633965Sjdp {"max", ">?", 0}, /* old */ 23733965Sjdp {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ 23833965Sjdp {"min", "<?", 0}, /* old */ 23933965Sjdp {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ 24033965Sjdp {"nop", "", 0}, /* old (for operator=) */ 24160484Sobrien {"rm", "->*", DMGL_ANSI}, /* ansi */ 24260484Sobrien {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ 24333965Sjdp}; 24433965Sjdp 24560484Sobrien/* These values are used to indicate the various type varieties. 24660484Sobrien They are all non-zero so that they can be used as `success' 24760484Sobrien values. */ 24860484Sobrientypedef enum type_kind_t 24960484Sobrien{ 25060484Sobrien tk_none, 25160484Sobrien tk_pointer, 25260484Sobrien tk_reference, 25360484Sobrien tk_integral, 25460484Sobrien tk_bool, 25560484Sobrien tk_char, 25660484Sobrien tk_real 25760484Sobrien} type_kind_t; 25833965Sjdp 25968765Sobrienstruct demangler_engine libiberty_demanglers[] = 26068765Sobrien{ 26168765Sobrien { 26268765Sobrien AUTO_DEMANGLING_STYLE_STRING, 26368765Sobrien auto_demangling, 26468765Sobrien "Automatic selection based on executable" 26568765Sobrien } 26668765Sobrien , 26768765Sobrien { 26868765Sobrien GNU_DEMANGLING_STYLE_STRING, 26968765Sobrien gnu_demangling, 27068765Sobrien "GNU (g++) style demangling" 27168765Sobrien } 27268765Sobrien , 27368765Sobrien { 27468765Sobrien LUCID_DEMANGLING_STYLE_STRING, 27568765Sobrien lucid_demangling, 27668765Sobrien "Lucid (lcc) style demangling" 27768765Sobrien } 27868765Sobrien , 27968765Sobrien { 28068765Sobrien ARM_DEMANGLING_STYLE_STRING, 28168765Sobrien arm_demangling, 28268765Sobrien "ARM style demangling" 28368765Sobrien } 28468765Sobrien , 28568765Sobrien { 28668765Sobrien HP_DEMANGLING_STYLE_STRING, 28768765Sobrien hp_demangling, 28868765Sobrien "HP (aCC) style demangling" 28968765Sobrien } 29068765Sobrien , 29168765Sobrien { 29268765Sobrien EDG_DEMANGLING_STYLE_STRING, 29368765Sobrien edg_demangling, 29468765Sobrien "EDG style demangling" 29568765Sobrien } 29668765Sobrien , 29768765Sobrien { 29877298Sobrien GNU_V3_DEMANGLING_STYLE_STRING, 29977298Sobrien gnu_v3_demangling, 30077298Sobrien "GNU (g++) V3 ABI-style demangling" 30168765Sobrien } 30268765Sobrien , 30368765Sobrien { 30477298Sobrien JAVA_DEMANGLING_STYLE_STRING, 30577298Sobrien java_demangling, 30677298Sobrien "Java style demangling" 30777298Sobrien } 30877298Sobrien , 30977298Sobrien { 31077298Sobrien GNAT_DEMANGLING_STYLE_STRING, 31177298Sobrien gnat_demangling, 31277298Sobrien "GNAT style demangling" 31377298Sobrien } 31477298Sobrien , 31577298Sobrien { 31668765Sobrien NULL, unknown_demangling, NULL 31768765Sobrien } 31868765Sobrien}; 31968765Sobrien 32033965Sjdp#define STRING_EMPTY(str) ((str) -> b == (str) -> p) 32133965Sjdp#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ 32233965Sjdp string_prepend(str, " ");} 32333965Sjdp#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ 32433965Sjdp string_append(str, " ");} 32560484Sobrien#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) 32633965Sjdp 32760484Sobrien/* The scope separator appropriate for the language being demangled. */ 32860484Sobrien 32960484Sobrien#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::") 33060484Sobrien 33133965Sjdp#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ 33233965Sjdp#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ 33333965Sjdp 33433965Sjdp/* Prototypes for local functions */ 33533965Sjdp 33668765Sobrienstatic void 33768765Sobriendelete_work_stuff PARAMS ((struct work_stuff *)); 33868765Sobrien 33968765Sobrienstatic void 34068765Sobriendelete_non_B_K_work_stuff PARAMS ((struct work_stuff *)); 34168765Sobrien 34233965Sjdpstatic char * 34333965Sjdpmop_up PARAMS ((struct work_stuff *, string *, int)); 34433965Sjdp 34560484Sobrienstatic void 34660484Sobriensquangle_mop_up PARAMS ((struct work_stuff *)); 34760484Sobrien 34868765Sobrienstatic void 34968765Sobrienwork_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *)); 35068765Sobrien 35133965Sjdp#if 0 35233965Sjdpstatic int 35360484Sobriendemangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); 35433965Sjdp#endif 35533965Sjdp 35660484Sobrienstatic char * 35760484Sobrieninternal_cplus_demangle PARAMS ((struct work_stuff *, const char *)); 35860484Sobrien 35933965Sjdpstatic int 36060484Sobriendemangle_template_template_parm PARAMS ((struct work_stuff *work, 36160484Sobrien const char **, string *)); 36260484Sobrien 36360484Sobrienstatic int 36433965Sjdpdemangle_template PARAMS ((struct work_stuff *work, const char **, string *, 36560484Sobrien string *, int, int)); 36633965Sjdp 36733965Sjdpstatic int 36833965Sjdparm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, 36933965Sjdp const char **)); 37033965Sjdp 37133965Sjdpstatic int 37233965Sjdpdemangle_class_name PARAMS ((struct work_stuff *, const char **, string *)); 37333965Sjdp 37433965Sjdpstatic int 37533965Sjdpdemangle_qualified PARAMS ((struct work_stuff *, const char **, string *, 37633965Sjdp int, int)); 37733965Sjdp 37833965Sjdpstatic int 37933965Sjdpdemangle_class PARAMS ((struct work_stuff *, const char **, string *)); 38033965Sjdp 38133965Sjdpstatic int 38233965Sjdpdemangle_fund_type PARAMS ((struct work_stuff *, const char **, string *)); 38333965Sjdp 38433965Sjdpstatic int 38533965Sjdpdemangle_signature PARAMS ((struct work_stuff *, const char **, string *)); 38633965Sjdp 38733965Sjdpstatic int 38833965Sjdpdemangle_prefix PARAMS ((struct work_stuff *, const char **, string *)); 38933965Sjdp 39033965Sjdpstatic int 39133965Sjdpgnu_special PARAMS ((struct work_stuff *, const char **, string *)); 39233965Sjdp 39333965Sjdpstatic int 39460484Sobrienarm_special PARAMS ((const char **, string *)); 39533965Sjdp 39633965Sjdpstatic void 39733965Sjdpstring_need PARAMS ((string *, int)); 39833965Sjdp 39933965Sjdpstatic void 40033965Sjdpstring_delete PARAMS ((string *)); 40133965Sjdp 40233965Sjdpstatic void 40333965Sjdpstring_init PARAMS ((string *)); 40433965Sjdp 40533965Sjdpstatic void 40633965Sjdpstring_clear PARAMS ((string *)); 40733965Sjdp 40833965Sjdp#if 0 40933965Sjdpstatic int 41033965Sjdpstring_empty PARAMS ((string *)); 41133965Sjdp#endif 41233965Sjdp 41333965Sjdpstatic void 41433965Sjdpstring_append PARAMS ((string *, const char *)); 41533965Sjdp 41633965Sjdpstatic void 41733965Sjdpstring_appends PARAMS ((string *, string *)); 41833965Sjdp 41933965Sjdpstatic void 42033965Sjdpstring_appendn PARAMS ((string *, const char *, int)); 42133965Sjdp 42233965Sjdpstatic void 42333965Sjdpstring_prepend PARAMS ((string *, const char *)); 42433965Sjdp 42533965Sjdpstatic void 42633965Sjdpstring_prependn PARAMS ((string *, const char *, int)); 42733965Sjdp 42860484Sobrienstatic void 42960484Sobrienstring_append_template_idx PARAMS ((string *, int)); 43060484Sobrien 43133965Sjdpstatic int 43233965Sjdpget_count PARAMS ((const char **, int *)); 43333965Sjdp 43433965Sjdpstatic int 43533965Sjdpconsume_count PARAMS ((const char **)); 43633965Sjdp 43760484Sobrienstatic int 43838889Sjdpconsume_count_with_underscores PARAMS ((const char**)); 43938889Sjdp 44033965Sjdpstatic int 44133965Sjdpdemangle_args PARAMS ((struct work_stuff *, const char **, string *)); 44233965Sjdp 44333965Sjdpstatic int 44460484Sobriendemangle_nested_args PARAMS ((struct work_stuff*, const char**, string*)); 44560484Sobrien 44660484Sobrienstatic int 44733965Sjdpdo_type PARAMS ((struct work_stuff *, const char **, string *)); 44833965Sjdp 44933965Sjdpstatic int 45033965Sjdpdo_arg PARAMS ((struct work_stuff *, const char **, string *)); 45133965Sjdp 45233965Sjdpstatic void 45333965Sjdpdemangle_function_name PARAMS ((struct work_stuff *, const char **, string *, 45433965Sjdp const char *)); 45533965Sjdp 45668765Sobrienstatic int 45768765Sobrieniterate_demangle_function PARAMS ((struct work_stuff *, 45868765Sobrien const char **, string *, const char *)); 45968765Sobrien 46033965Sjdpstatic void 46133965Sjdpremember_type PARAMS ((struct work_stuff *, const char *, int)); 46233965Sjdp 46333965Sjdpstatic void 46460484Sobrienremember_Btype PARAMS ((struct work_stuff *, const char *, int, int)); 46560484Sobrien 46660484Sobrienstatic int 46760484Sobrienregister_Btype PARAMS ((struct work_stuff *)); 46860484Sobrien 46960484Sobrienstatic void 47060484Sobrienremember_Ktype PARAMS ((struct work_stuff *, const char *, int)); 47160484Sobrien 47260484Sobrienstatic void 47333965Sjdpforget_types PARAMS ((struct work_stuff *)); 47433965Sjdp 47533965Sjdpstatic void 47660484Sobrienforget_B_and_K_types PARAMS ((struct work_stuff *)); 47760484Sobrien 47860484Sobrienstatic void 47933965Sjdpstring_prepends PARAMS ((string *, string *)); 48033965Sjdp 48160484Sobrienstatic int 48260484Sobriendemangle_template_value_parm PARAMS ((struct work_stuff*, const char**, 48360484Sobrien string*, type_kind_t)); 48433965Sjdp 48533965Sjdpstatic int 48660484Sobriendo_hpacc_template_const_value PARAMS ((struct work_stuff *, const char **, string *)); 48760484Sobrien 48860484Sobrienstatic int 48960484Sobriendo_hpacc_template_literal PARAMS ((struct work_stuff *, const char **, string *)); 49060484Sobrien 49160484Sobrienstatic int 49260484Sobriensnarf_numeric_literal PARAMS ((const char **, string *)); 49360484Sobrien 49460484Sobrien/* There is a TYPE_QUAL value for each type qualifier. They can be 49560484Sobrien combined by bitwise-or to form the complete set of qualifiers for a 49660484Sobrien type. */ 49760484Sobrien 49860484Sobrien#define TYPE_UNQUALIFIED 0x0 49960484Sobrien#define TYPE_QUAL_CONST 0x1 50060484Sobrien#define TYPE_QUAL_VOLATILE 0x2 50160484Sobrien#define TYPE_QUAL_RESTRICT 0x4 50260484Sobrien 50360484Sobrienstatic int 50460484Sobriencode_for_qualifier PARAMS ((int)); 50560484Sobrien 50660484Sobrienstatic const char* 50760484Sobrienqualifier_string PARAMS ((int)); 50860484Sobrien 50960484Sobrienstatic const char* 51060484Sobriendemangle_qualifier PARAMS ((int)); 51160484Sobrien 51260484Sobrienstatic int 51360484Sobriendemangle_expression PARAMS ((struct work_stuff *, const char **, string *, 51460484Sobrien type_kind_t)); 51560484Sobrien 51660484Sobrienstatic int 51760484Sobriendemangle_integral_value PARAMS ((struct work_stuff *, const char **, 51860484Sobrien string *)); 51960484Sobrien 52060484Sobrienstatic int 52160484Sobriendemangle_real_value PARAMS ((struct work_stuff *, const char **, string *)); 52260484Sobrien 52360484Sobrienstatic void 52460484Sobriendemangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int, 52560484Sobrien string *)); 52660484Sobrien 52760484Sobrienstatic void 52860484Sobrienrecursively_demangle PARAMS ((struct work_stuff *, const char **, string *, 52960484Sobrien int)); 53060484Sobrien 53177298Sobrienstatic void 53277298Sobriengrow_vect PARAMS ((void **, size_t *, size_t, int)); 53377298Sobrien 53460484Sobrien/* Translate count to integer, consuming tokens in the process. 53560484Sobrien Conversion terminates on the first non-digit character. 53660484Sobrien 53760484Sobrien Trying to consume something that isn't a count results in no 53860484Sobrien consumption of input and a return of -1. 53960484Sobrien 54060484Sobrien Overflow consumes the rest of the digits, and returns -1. */ 54160484Sobrien 54260484Sobrienstatic int 54333965Sjdpconsume_count (type) 54433965Sjdp const char **type; 54533965Sjdp{ 54633965Sjdp int count = 0; 54733965Sjdp 54877298Sobrien if (! ISDIGIT ((unsigned char)**type)) 54960484Sobrien return -1; 55060484Sobrien 55177298Sobrien while (ISDIGIT ((unsigned char)**type)) 55233965Sjdp { 55333965Sjdp count *= 10; 55460484Sobrien 55560484Sobrien /* Check for overflow. 55660484Sobrien We assume that count is represented using two's-complement; 55760484Sobrien no power of two is divisible by ten, so if an overflow occurs 55860484Sobrien when multiplying by ten, the result will not be a multiple of 55960484Sobrien ten. */ 56060484Sobrien if ((count % 10) != 0) 56160484Sobrien { 56277298Sobrien while (ISDIGIT ((unsigned char) **type)) 56360484Sobrien (*type)++; 56460484Sobrien return -1; 56560484Sobrien } 56660484Sobrien 56733965Sjdp count += **type - '0'; 56833965Sjdp (*type)++; 56933965Sjdp } 57060484Sobrien 57133965Sjdp return (count); 57233965Sjdp} 57333965Sjdp 57438889Sjdp 57560484Sobrien/* Like consume_count, but for counts that are preceded and followed 57638889Sjdp by '_' if they are greater than 10. Also, -1 is returned for 57738889Sjdp failure, since 0 can be a valid value. */ 57838889Sjdp 57938889Sjdpstatic int 58038889Sjdpconsume_count_with_underscores (mangled) 58138889Sjdp const char **mangled; 58238889Sjdp{ 58338889Sjdp int idx; 58438889Sjdp 58538889Sjdp if (**mangled == '_') 58638889Sjdp { 58738889Sjdp (*mangled)++; 58877298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 58938889Sjdp return -1; 59038889Sjdp 59138889Sjdp idx = consume_count (mangled); 59238889Sjdp if (**mangled != '_') 59338889Sjdp /* The trailing underscore was missing. */ 59438889Sjdp return -1; 59560484Sobrien 59638889Sjdp (*mangled)++; 59738889Sjdp } 59838889Sjdp else 59938889Sjdp { 60038889Sjdp if (**mangled < '0' || **mangled > '9') 60138889Sjdp return -1; 60260484Sobrien 60338889Sjdp idx = **mangled - '0'; 60438889Sjdp (*mangled)++; 60538889Sjdp } 60638889Sjdp 60738889Sjdp return idx; 60838889Sjdp} 60938889Sjdp 61060484Sobrien/* C is the code for a type-qualifier. Return the TYPE_QUAL 61160484Sobrien corresponding to this qualifier. */ 61260484Sobrien 61360484Sobrienstatic int 61460484Sobriencode_for_qualifier (c) 61560484Sobrien int c; 61660484Sobrien{ 61760484Sobrien switch (c) 61860484Sobrien { 61960484Sobrien case 'C': 62060484Sobrien return TYPE_QUAL_CONST; 62160484Sobrien 62260484Sobrien case 'V': 62360484Sobrien return TYPE_QUAL_VOLATILE; 62460484Sobrien 62560484Sobrien case 'u': 62660484Sobrien return TYPE_QUAL_RESTRICT; 62760484Sobrien 62860484Sobrien default: 62960484Sobrien break; 63060484Sobrien } 63160484Sobrien 63260484Sobrien /* C was an invalid qualifier. */ 63360484Sobrien abort (); 63460484Sobrien} 63560484Sobrien 63660484Sobrien/* Return the string corresponding to the qualifiers given by 63760484Sobrien TYPE_QUALS. */ 63860484Sobrien 63960484Sobrienstatic const char* 64060484Sobrienqualifier_string (type_quals) 64160484Sobrien int type_quals; 64260484Sobrien{ 64360484Sobrien switch (type_quals) 64460484Sobrien { 64560484Sobrien case TYPE_UNQUALIFIED: 64660484Sobrien return ""; 64760484Sobrien 64860484Sobrien case TYPE_QUAL_CONST: 64960484Sobrien return "const"; 65060484Sobrien 65160484Sobrien case TYPE_QUAL_VOLATILE: 65260484Sobrien return "volatile"; 65360484Sobrien 65460484Sobrien case TYPE_QUAL_RESTRICT: 65560484Sobrien return "__restrict"; 65660484Sobrien 65760484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: 65860484Sobrien return "const volatile"; 65960484Sobrien 66060484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: 66160484Sobrien return "const __restrict"; 66260484Sobrien 66360484Sobrien case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 66460484Sobrien return "volatile __restrict"; 66560484Sobrien 66660484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 66760484Sobrien return "const volatile __restrict"; 66860484Sobrien 66960484Sobrien default: 67060484Sobrien break; 67160484Sobrien } 67260484Sobrien 67360484Sobrien /* TYPE_QUALS was an invalid qualifier set. */ 67460484Sobrien abort (); 67560484Sobrien} 67660484Sobrien 67760484Sobrien/* C is the code for a type-qualifier. Return the string 67860484Sobrien corresponding to this qualifier. This function should only be 67960484Sobrien called with a valid qualifier code. */ 68060484Sobrien 68160484Sobrienstatic const char* 68260484Sobriendemangle_qualifier (c) 68360484Sobrien int c; 68460484Sobrien{ 68560484Sobrien return qualifier_string (code_for_qualifier (c)); 68660484Sobrien} 68760484Sobrien 68833965Sjdpint 68933965Sjdpcplus_demangle_opname (opname, result, options) 69033965Sjdp const char *opname; 69133965Sjdp char *result; 69233965Sjdp int options; 69333965Sjdp{ 69460484Sobrien int len, len1, ret; 69533965Sjdp string type; 69633965Sjdp struct work_stuff work[1]; 69733965Sjdp const char *tem; 69833965Sjdp 69933965Sjdp len = strlen(opname); 70033965Sjdp result[0] = '\0'; 70133965Sjdp ret = 0; 70260484Sobrien memset ((char *) work, 0, sizeof (work)); 70333965Sjdp work->options = options; 70460484Sobrien 70533965Sjdp if (opname[0] == '_' && opname[1] == '_' 70633965Sjdp && opname[2] == 'o' && opname[3] == 'p') 70733965Sjdp { 70833965Sjdp /* ANSI. */ 70933965Sjdp /* type conversion operator. */ 71033965Sjdp tem = opname + 4; 71133965Sjdp if (do_type (work, &tem, &type)) 71233965Sjdp { 71333965Sjdp strcat (result, "operator "); 71433965Sjdp strncat (result, type.b, type.p - type.b); 71533965Sjdp string_delete (&type); 71633965Sjdp ret = 1; 71733965Sjdp } 71833965Sjdp } 71933965Sjdp else if (opname[0] == '_' && opname[1] == '_' 72077298Sobrien && ISLOWER((unsigned char)opname[2]) 72177298Sobrien && ISLOWER((unsigned char)opname[3])) 72233965Sjdp { 72333965Sjdp if (opname[4] == '\0') 72433965Sjdp { 72533965Sjdp /* Operator. */ 72660484Sobrien size_t i; 72777298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 72833965Sjdp { 72933965Sjdp if (strlen (optable[i].in) == 2 73033965Sjdp && memcmp (optable[i].in, opname + 2, 2) == 0) 73133965Sjdp { 73233965Sjdp strcat (result, "operator"); 73333965Sjdp strcat (result, optable[i].out); 73433965Sjdp ret = 1; 73533965Sjdp break; 73633965Sjdp } 73733965Sjdp } 73833965Sjdp } 73933965Sjdp else 74033965Sjdp { 74133965Sjdp if (opname[2] == 'a' && opname[5] == '\0') 74233965Sjdp { 74333965Sjdp /* Assignment. */ 74460484Sobrien size_t i; 74577298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 74633965Sjdp { 74733965Sjdp if (strlen (optable[i].in) == 3 74833965Sjdp && memcmp (optable[i].in, opname + 2, 3) == 0) 74933965Sjdp { 75033965Sjdp strcat (result, "operator"); 75133965Sjdp strcat (result, optable[i].out); 75233965Sjdp ret = 1; 75333965Sjdp break; 75460484Sobrien } 75533965Sjdp } 75633965Sjdp } 75733965Sjdp } 75833965Sjdp } 75960484Sobrien else if (len >= 3 76033965Sjdp && opname[0] == 'o' 76133965Sjdp && opname[1] == 'p' 76233965Sjdp && strchr (cplus_markers, opname[2]) != NULL) 76333965Sjdp { 76433965Sjdp /* see if it's an assignment expression */ 76533965Sjdp if (len >= 10 /* op$assign_ */ 76633965Sjdp && memcmp (opname + 3, "assign_", 7) == 0) 76733965Sjdp { 76860484Sobrien size_t i; 76977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 77033965Sjdp { 77133965Sjdp len1 = len - 10; 77260484Sobrien if ((int) strlen (optable[i].in) == len1 77333965Sjdp && memcmp (optable[i].in, opname + 10, len1) == 0) 77433965Sjdp { 77533965Sjdp strcat (result, "operator"); 77633965Sjdp strcat (result, optable[i].out); 77733965Sjdp strcat (result, "="); 77833965Sjdp ret = 1; 77933965Sjdp break; 78033965Sjdp } 78133965Sjdp } 78233965Sjdp } 78333965Sjdp else 78433965Sjdp { 78560484Sobrien size_t i; 78677298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 78733965Sjdp { 78833965Sjdp len1 = len - 3; 78960484Sobrien if ((int) strlen (optable[i].in) == len1 79033965Sjdp && memcmp (optable[i].in, opname + 3, len1) == 0) 79133965Sjdp { 79233965Sjdp strcat (result, "operator"); 79333965Sjdp strcat (result, optable[i].out); 79433965Sjdp ret = 1; 79533965Sjdp break; 79633965Sjdp } 79733965Sjdp } 79833965Sjdp } 79933965Sjdp } 80033965Sjdp else if (len >= 5 && memcmp (opname, "type", 4) == 0 80133965Sjdp && strchr (cplus_markers, opname[4]) != NULL) 80233965Sjdp { 80333965Sjdp /* type conversion operator */ 80433965Sjdp tem = opname + 5; 80533965Sjdp if (do_type (work, &tem, &type)) 80633965Sjdp { 80733965Sjdp strcat (result, "operator "); 80833965Sjdp strncat (result, type.b, type.p - type.b); 80933965Sjdp string_delete (&type); 81033965Sjdp ret = 1; 81133965Sjdp } 81233965Sjdp } 81360484Sobrien squangle_mop_up (work); 81433965Sjdp return ret; 81533965Sjdp 81633965Sjdp} 81768765Sobrien 81833965Sjdp/* Takes operator name as e.g. "++" and returns mangled 81933965Sjdp operator name (e.g. "postincrement_expr"), or NULL if not found. 82033965Sjdp 82133965Sjdp If OPTIONS & DMGL_ANSI == 1, return the ANSI name; 82233965Sjdp if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ 82333965Sjdp 82433965Sjdpconst char * 82533965Sjdpcplus_mangle_opname (opname, options) 82633965Sjdp const char *opname; 82733965Sjdp int options; 82833965Sjdp{ 82960484Sobrien size_t i; 83033965Sjdp int len; 83133965Sjdp 83233965Sjdp len = strlen (opname); 83377298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 83433965Sjdp { 83560484Sobrien if ((int) strlen (optable[i].out) == len 83633965Sjdp && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) 83733965Sjdp && memcmp (optable[i].out, opname, len) == 0) 83833965Sjdp return optable[i].in; 83933965Sjdp } 84033965Sjdp return (0); 84133965Sjdp} 84233965Sjdp 84368765Sobrien/* Add a routine to set the demangling style to be sure it is valid and 84468765Sobrien allow for any demangler initialization that maybe necessary. */ 84568765Sobrien 84668765Sobrienenum demangling_styles 84768765Sobriencplus_demangle_set_style (style) 84868765Sobrien enum demangling_styles style; 84968765Sobrien{ 85068765Sobrien struct demangler_engine *demangler = libiberty_demanglers; 85168765Sobrien 85268765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 85368765Sobrien if (style == demangler->demangling_style) 85468765Sobrien { 85568765Sobrien current_demangling_style = style; 85668765Sobrien return current_demangling_style; 85768765Sobrien } 85868765Sobrien 85968765Sobrien return unknown_demangling; 86068765Sobrien} 86168765Sobrien 86268765Sobrien/* Do string name to style translation */ 86368765Sobrien 86468765Sobrienenum demangling_styles 86568765Sobriencplus_demangle_name_to_style (name) 86668765Sobrien const char *name; 86768765Sobrien{ 86868765Sobrien struct demangler_engine *demangler = libiberty_demanglers; 86968765Sobrien 87068765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 87168765Sobrien if (strcmp (name, demangler->demangling_style_name) == 0) 87268765Sobrien return demangler->demangling_style; 87368765Sobrien 87468765Sobrien return unknown_demangling; 87568765Sobrien} 87668765Sobrien 87733965Sjdp/* char *cplus_demangle (const char *mangled, int options) 87833965Sjdp 87933965Sjdp If MANGLED is a mangled function name produced by GNU C++, then 88033965Sjdp a pointer to a malloced string giving a C++ representation 88133965Sjdp of the name will be returned; otherwise NULL will be returned. 88233965Sjdp It is the caller's responsibility to free the string which 88333965Sjdp is returned. 88433965Sjdp 88533965Sjdp The OPTIONS arg may contain one or more of the following bits: 88633965Sjdp 88733965Sjdp DMGL_ANSI ANSI qualifiers such as `const' and `void' are 88833965Sjdp included. 88933965Sjdp DMGL_PARAMS Function parameters are included. 89033965Sjdp 89133965Sjdp For example, 89260484Sobrien 89333965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" 89433965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" 89533965Sjdp cplus_demangle ("foo__1Ai", 0) => "A::foo" 89633965Sjdp 89733965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" 89833965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" 89933965Sjdp cplus_demangle ("foo__1Afe", 0) => "A::foo" 90033965Sjdp 90133965Sjdp Note that any leading underscores, or other such characters prepended by 90233965Sjdp the compilation system, are presumed to have already been stripped from 90333965Sjdp MANGLED. */ 90433965Sjdp 90533965Sjdpchar * 90633965Sjdpcplus_demangle (mangled, options) 90733965Sjdp const char *mangled; 90833965Sjdp int options; 90933965Sjdp{ 91060484Sobrien char *ret; 91160484Sobrien struct work_stuff work[1]; 91260484Sobrien memset ((char *) work, 0, sizeof (work)); 91377298Sobrien work->options = options; 91477298Sobrien if ((work->options & DMGL_STYLE_MASK) == 0) 91577298Sobrien work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; 91660484Sobrien 91777298Sobrien /* The V3 ABI demangling is implemented elsewhere. */ 91877298Sobrien if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) 91977298Sobrien { 92077298Sobrien ret = cplus_demangle_v3 (mangled); 92177298Sobrien if (ret || GNU_V3_DEMANGLING) 92277298Sobrien return ret; 92377298Sobrien } 92468765Sobrien 92577298Sobrien if (GNAT_DEMANGLING) 92677298Sobrien return ada_demangle(mangled,options); 92777298Sobrien 92860484Sobrien ret = internal_cplus_demangle (work, mangled); 92960484Sobrien squangle_mop_up (work); 93060484Sobrien return (ret); 93160484Sobrien} 93260484Sobrien 93360484Sobrien 93477298Sobrien/* Assuming *OLD_VECT points to an array of *SIZE objects of size 93577298Sobrien ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, 93677298Sobrien updating *OLD_VECT and *SIZE as necessary. */ 93777298Sobrien 93877298Sobrienstatic void 93977298Sobriengrow_vect (old_vect, size, min_size, element_size) 94077298Sobrien void **old_vect; 94177298Sobrien size_t *size; 94277298Sobrien size_t min_size; 94377298Sobrien int element_size; 94477298Sobrien{ 94577298Sobrien if (*size < min_size) 94677298Sobrien { 94777298Sobrien *size *= 2; 94877298Sobrien if (*size < min_size) 94977298Sobrien *size = min_size; 95077298Sobrien *old_vect = xrealloc (*old_vect, *size * element_size); 95177298Sobrien } 95277298Sobrien} 95377298Sobrien 95477298Sobrien/* Demangle ada names: 95577298Sobrien 1. Discard final __{DIGIT}+ or ${DIGIT}+ 95677298Sobrien 2. Convert other instances of embedded "__" to `.'. 95777298Sobrien 3. Discard leading _ada_. 95877298Sobrien 4. Remove everything after first ___ if it is followed by 'X'. 95977298Sobrien 5. Put symbols that should be suppressed in <...> brackets. 96077298Sobrien The resulting string is valid until the next call of ada_demangle. */ 96177298Sobrien 96277298Sobrienstatic char * 96377298Sobrienada_demangle (mangled, option) 96477298Sobrien const char *mangled; 96577298Sobrien int option ATTRIBUTE_UNUSED; 96677298Sobrien{ 96777298Sobrien int i, j; 96877298Sobrien int len0; 96977298Sobrien const char* p; 97077298Sobrien char *demangled = NULL; 97177298Sobrien int at_start_name; 97277298Sobrien int changed; 97377298Sobrien char *demangling_buffer = NULL; 97477298Sobrien size_t demangling_buffer_size = 0; 97577298Sobrien 97677298Sobrien changed = 0; 97777298Sobrien 97877298Sobrien if (strncmp (mangled, "_ada_", 5) == 0) 97977298Sobrien { 98077298Sobrien mangled += 5; 98177298Sobrien changed = 1; 98277298Sobrien } 98377298Sobrien 98477298Sobrien if (mangled[0] == '_' || mangled[0] == '<') 98577298Sobrien goto Suppress; 98677298Sobrien 98777298Sobrien p = strstr (mangled, "___"); 98877298Sobrien if (p == NULL) 98977298Sobrien len0 = strlen (mangled); 99077298Sobrien else 99177298Sobrien { 99277298Sobrien if (p[3] == 'X') 99377298Sobrien { 99477298Sobrien len0 = p - mangled; 99577298Sobrien changed = 1; 99677298Sobrien } 99777298Sobrien else 99877298Sobrien goto Suppress; 99977298Sobrien } 100077298Sobrien 100177298Sobrien /* Make demangled big enough for possible expansion by operator name. */ 100277298Sobrien grow_vect ((void **) &(demangling_buffer), 100377298Sobrien &demangling_buffer_size, 2 * len0 + 1, 100477298Sobrien sizeof (char)); 100577298Sobrien demangled = demangling_buffer; 100677298Sobrien 100777298Sobrien if (ISDIGIT ((unsigned char) mangled[len0 - 1])) { 100877298Sobrien for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1) 100977298Sobrien ; 101077298Sobrien if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') 101177298Sobrien { 101277298Sobrien len0 = i - 1; 101377298Sobrien changed = 1; 101477298Sobrien } 101577298Sobrien else if (mangled[i] == '$') 101677298Sobrien { 101777298Sobrien len0 = i; 101877298Sobrien changed = 1; 101977298Sobrien } 102077298Sobrien } 102177298Sobrien 102277298Sobrien for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]); 102377298Sobrien i += 1, j += 1) 102477298Sobrien demangled[j] = mangled[i]; 102577298Sobrien 102677298Sobrien at_start_name = 1; 102777298Sobrien while (i < len0) 102877298Sobrien { 102977298Sobrien at_start_name = 0; 103077298Sobrien 103177298Sobrien if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') 103277298Sobrien { 103377298Sobrien demangled[j] = '.'; 103477298Sobrien changed = at_start_name = 1; 103577298Sobrien i += 2; j += 1; 103677298Sobrien } 103777298Sobrien else 103877298Sobrien { 103977298Sobrien demangled[j] = mangled[i]; 104077298Sobrien i += 1; j += 1; 104177298Sobrien } 104277298Sobrien } 104377298Sobrien demangled[j] = '\000'; 104477298Sobrien 104577298Sobrien for (i = 0; demangled[i] != '\0'; i += 1) 104677298Sobrien if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ') 104777298Sobrien goto Suppress; 104877298Sobrien 104977298Sobrien if (! changed) 105077298Sobrien return NULL; 105177298Sobrien else 105277298Sobrien return demangled; 105377298Sobrien 105477298Sobrien Suppress: 105577298Sobrien grow_vect ((void **) &(demangling_buffer), 105677298Sobrien &demangling_buffer_size, strlen (mangled) + 3, 105777298Sobrien sizeof (char)); 105877298Sobrien demangled = demangling_buffer; 105977298Sobrien if (mangled[0] == '<') 106077298Sobrien strcpy (demangled, mangled); 106177298Sobrien else 106277298Sobrien sprintf (demangled, "<%s>", mangled); 106377298Sobrien 106477298Sobrien return demangled; 106577298Sobrien} 106677298Sobrien 106760484Sobrien/* This function performs most of what cplus_demangle use to do, but 106860484Sobrien to be able to demangle a name with a B, K or n code, we need to 106960484Sobrien have a longer term memory of what types have been seen. The original 107060484Sobrien now intializes and cleans up the squangle code info, while internal 107160484Sobrien calls go directly to this routine to avoid resetting that info. */ 107260484Sobrien 107360484Sobrienstatic char * 107460484Sobrieninternal_cplus_demangle (work, mangled) 107560484Sobrien struct work_stuff *work; 107660484Sobrien const char *mangled; 107760484Sobrien{ 107860484Sobrien 107933965Sjdp string decl; 108033965Sjdp int success = 0; 108133965Sjdp char *demangled = NULL; 108277298Sobrien int s1, s2, s3, s4; 108360484Sobrien s1 = work->constructor; 108460484Sobrien s2 = work->destructor; 108560484Sobrien s3 = work->static_type; 108660484Sobrien s4 = work->type_quals; 108760484Sobrien work->constructor = work->destructor = 0; 108860484Sobrien work->type_quals = TYPE_UNQUALIFIED; 108960484Sobrien work->dllimported = 0; 109033965Sjdp 109133965Sjdp if ((mangled != NULL) && (*mangled != '\0')) 109233965Sjdp { 109333965Sjdp string_init (&decl); 109433965Sjdp 109533965Sjdp /* First check to see if gnu style demangling is active and if the 109633965Sjdp string to be demangled contains a CPLUS_MARKER. If so, attempt to 109733965Sjdp recognize one of the gnu special forms rather than looking for a 109833965Sjdp standard prefix. In particular, don't worry about whether there 109933965Sjdp is a "__" string in the mangled string. Consider "_$_5__foo" for 110033965Sjdp example. */ 110133965Sjdp 110233965Sjdp if ((AUTO_DEMANGLING || GNU_DEMANGLING)) 110333965Sjdp { 110433965Sjdp success = gnu_special (work, &mangled, &decl); 110533965Sjdp } 110633965Sjdp if (!success) 110733965Sjdp { 110833965Sjdp success = demangle_prefix (work, &mangled, &decl); 110933965Sjdp } 111033965Sjdp if (success && (*mangled != '\0')) 111133965Sjdp { 111233965Sjdp success = demangle_signature (work, &mangled, &decl); 111333965Sjdp } 111433965Sjdp if (work->constructor == 2) 111533965Sjdp { 111660484Sobrien string_prepend (&decl, "global constructors keyed to "); 111733965Sjdp work->constructor = 0; 111833965Sjdp } 111933965Sjdp else if (work->destructor == 2) 112033965Sjdp { 112160484Sobrien string_prepend (&decl, "global destructors keyed to "); 112233965Sjdp work->destructor = 0; 112333965Sjdp } 112460484Sobrien else if (work->dllimported == 1) 112560484Sobrien { 112660484Sobrien string_prepend (&decl, "import stub for "); 112760484Sobrien work->dllimported = 0; 112860484Sobrien } 112933965Sjdp demangled = mop_up (work, &decl, success); 113033965Sjdp } 113160484Sobrien work->constructor = s1; 113260484Sobrien work->destructor = s2; 113360484Sobrien work->static_type = s3; 113460484Sobrien work->type_quals = s4; 113577298Sobrien return demangled; 113633965Sjdp} 113733965Sjdp 113860484Sobrien 113960484Sobrien/* Clear out and squangling related storage */ 114060484Sobrienstatic void 114160484Sobriensquangle_mop_up (work) 114260484Sobrien struct work_stuff *work; 114360484Sobrien{ 114460484Sobrien /* clean up the B and K type mangling types. */ 114560484Sobrien forget_B_and_K_types (work); 114660484Sobrien if (work -> btypevec != NULL) 114760484Sobrien { 114860484Sobrien free ((char *) work -> btypevec); 114960484Sobrien } 115060484Sobrien if (work -> ktypevec != NULL) 115160484Sobrien { 115260484Sobrien free ((char *) work -> ktypevec); 115360484Sobrien } 115460484Sobrien} 115560484Sobrien 115660484Sobrien 115768765Sobrien/* Copy the work state and storage. */ 115868765Sobrien 115968765Sobrienstatic void 116068765Sobrienwork_stuff_copy_to_from (to, from) 116168765Sobrien struct work_stuff *to; 116268765Sobrien struct work_stuff *from; 116368765Sobrien{ 116468765Sobrien int i; 116568765Sobrien 116668765Sobrien delete_work_stuff (to); 116768765Sobrien 116868765Sobrien /* Shallow-copy scalars. */ 116968765Sobrien memcpy (to, from, sizeof (*to)); 117068765Sobrien 117168765Sobrien /* Deep-copy dynamic storage. */ 117268765Sobrien if (from->typevec_size) 117368765Sobrien to->typevec 117468765Sobrien = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0])); 117568765Sobrien 117668765Sobrien for (i = 0; i < from->ntypes; i++) 117768765Sobrien { 117868765Sobrien int len = strlen (from->typevec[i]) + 1; 117968765Sobrien 118068765Sobrien to->typevec[i] = xmalloc (len); 118168765Sobrien memcpy (to->typevec[i], from->typevec[i], len); 118268765Sobrien } 118368765Sobrien 118468765Sobrien if (from->ksize) 118568765Sobrien to->ktypevec 118668765Sobrien = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0])); 118768765Sobrien 118868765Sobrien for (i = 0; i < from->numk; i++) 118968765Sobrien { 119068765Sobrien int len = strlen (from->ktypevec[i]) + 1; 119168765Sobrien 119268765Sobrien to->ktypevec[i] = xmalloc (len); 119368765Sobrien memcpy (to->ktypevec[i], from->ktypevec[i], len); 119468765Sobrien } 119568765Sobrien 119668765Sobrien if (from->bsize) 119768765Sobrien to->btypevec 119868765Sobrien = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0])); 119968765Sobrien 120068765Sobrien for (i = 0; i < from->numb; i++) 120168765Sobrien { 120268765Sobrien int len = strlen (from->btypevec[i]) + 1; 120368765Sobrien 120468765Sobrien to->btypevec[i] = xmalloc (len); 120568765Sobrien memcpy (to->btypevec[i], from->btypevec[i], len); 120668765Sobrien } 120768765Sobrien 120868765Sobrien if (from->ntmpl_args) 120968765Sobrien to->tmpl_argvec 121068765Sobrien = xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0])); 121168765Sobrien 121268765Sobrien for (i = 0; i < from->ntmpl_args; i++) 121368765Sobrien { 121468765Sobrien int len = strlen (from->tmpl_argvec[i]) + 1; 121568765Sobrien 121668765Sobrien to->tmpl_argvec[i] = xmalloc (len); 121768765Sobrien memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); 121868765Sobrien } 121968765Sobrien 122068765Sobrien if (from->previous_argument) 122168765Sobrien { 122268765Sobrien to->previous_argument = (string*) xmalloc (sizeof (string)); 122368765Sobrien string_init (to->previous_argument); 122468765Sobrien string_appends (to->previous_argument, from->previous_argument); 122568765Sobrien } 122668765Sobrien} 122768765Sobrien 122868765Sobrien 122968765Sobrien/* Delete dynamic stuff in work_stuff that is not to be re-used. */ 123068765Sobrien 123168765Sobrienstatic void 123268765Sobriendelete_non_B_K_work_stuff (work) 123333965Sjdp struct work_stuff *work; 123433965Sjdp{ 123533965Sjdp /* Discard the remembered types, if any. */ 123660484Sobrien 123733965Sjdp forget_types (work); 123833965Sjdp if (work -> typevec != NULL) 123933965Sjdp { 124033965Sjdp free ((char *) work -> typevec); 124160484Sobrien work -> typevec = NULL; 124260484Sobrien work -> typevec_size = 0; 124333965Sjdp } 124438889Sjdp if (work->tmpl_argvec) 124538889Sjdp { 124638889Sjdp int i; 124738889Sjdp 124838889Sjdp for (i = 0; i < work->ntmpl_args; i++) 124938889Sjdp if (work->tmpl_argvec[i]) 125038889Sjdp free ((char*) work->tmpl_argvec[i]); 125160484Sobrien 125238889Sjdp free ((char*) work->tmpl_argvec); 125360484Sobrien work->tmpl_argvec = NULL; 125438889Sjdp } 125560484Sobrien if (work->previous_argument) 125660484Sobrien { 125760484Sobrien string_delete (work->previous_argument); 125860484Sobrien free ((char*) work->previous_argument); 125960484Sobrien work->previous_argument = NULL; 126060484Sobrien } 126168765Sobrien} 126238889Sjdp 126368765Sobrien 126468765Sobrien/* Delete all dynamic storage in work_stuff. */ 126568765Sobrienstatic void 126668765Sobriendelete_work_stuff (work) 126768765Sobrien struct work_stuff *work; 126868765Sobrien{ 126968765Sobrien delete_non_B_K_work_stuff (work); 127068765Sobrien squangle_mop_up (work); 127168765Sobrien} 127268765Sobrien 127368765Sobrien 127468765Sobrien/* Clear out any mangled storage */ 127568765Sobrien 127668765Sobrienstatic char * 127768765Sobrienmop_up (work, declp, success) 127868765Sobrien struct work_stuff *work; 127968765Sobrien string *declp; 128068765Sobrien int success; 128168765Sobrien{ 128268765Sobrien char *demangled = NULL; 128368765Sobrien 128468765Sobrien delete_non_B_K_work_stuff (work); 128568765Sobrien 128633965Sjdp /* If demangling was successful, ensure that the demangled string is null 128733965Sjdp terminated and return it. Otherwise, free the demangling decl. */ 128860484Sobrien 128933965Sjdp if (!success) 129033965Sjdp { 129133965Sjdp string_delete (declp); 129233965Sjdp } 129333965Sjdp else 129433965Sjdp { 129533965Sjdp string_appendn (declp, "", 1); 129677298Sobrien demangled = declp->b; 129733965Sjdp } 129833965Sjdp return (demangled); 129933965Sjdp} 130033965Sjdp 130133965Sjdp/* 130233965Sjdp 130333965SjdpLOCAL FUNCTION 130433965Sjdp 130533965Sjdp demangle_signature -- demangle the signature part of a mangled name 130633965Sjdp 130733965SjdpSYNOPSIS 130833965Sjdp 130933965Sjdp static int 131033965Sjdp demangle_signature (struct work_stuff *work, const char **mangled, 131133965Sjdp string *declp); 131233965Sjdp 131333965SjdpDESCRIPTION 131433965Sjdp 131533965Sjdp Consume and demangle the signature portion of the mangled name. 131633965Sjdp 131733965Sjdp DECLP is the string where demangled output is being built. At 131833965Sjdp entry it contains the demangled root name from the mangled name 131933965Sjdp prefix. I.E. either a demangled operator name or the root function 132033965Sjdp name. In some special cases, it may contain nothing. 132133965Sjdp 132233965Sjdp *MANGLED points to the current unconsumed location in the mangled 132333965Sjdp name. As tokens are consumed and demangling is performed, the 132433965Sjdp pointer is updated to continuously point at the next token to 132533965Sjdp be consumed. 132633965Sjdp 132733965Sjdp Demangling GNU style mangled names is nasty because there is no 132833965Sjdp explicit token that marks the start of the outermost function 132933965Sjdp argument list. */ 133033965Sjdp 133133965Sjdpstatic int 133233965Sjdpdemangle_signature (work, mangled, declp) 133333965Sjdp struct work_stuff *work; 133433965Sjdp const char **mangled; 133533965Sjdp string *declp; 133633965Sjdp{ 133733965Sjdp int success = 1; 133833965Sjdp int func_done = 0; 133933965Sjdp int expect_func = 0; 134038889Sjdp int expect_return_type = 0; 134133965Sjdp const char *oldmangled = NULL; 134233965Sjdp string trawname; 134333965Sjdp string tname; 134433965Sjdp 134533965Sjdp while (success && (**mangled != '\0')) 134633965Sjdp { 134733965Sjdp switch (**mangled) 134833965Sjdp { 134933965Sjdp case 'Q': 135033965Sjdp oldmangled = *mangled; 135133965Sjdp success = demangle_qualified (work, mangled, declp, 1, 0); 135233965Sjdp if (success) 135360484Sobrien remember_type (work, oldmangled, *mangled - oldmangled); 135433965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 135560484Sobrien expect_func = 1; 135660484Sobrien oldmangled = NULL; 135760484Sobrien break; 135860484Sobrien 135960484Sobrien case 'K': 136060484Sobrien oldmangled = *mangled; 136160484Sobrien success = demangle_qualified (work, mangled, declp, 1, 0); 136260484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 136333965Sjdp { 136433965Sjdp expect_func = 1; 136533965Sjdp } 136633965Sjdp oldmangled = NULL; 136733965Sjdp break; 136860484Sobrien 136933965Sjdp case 'S': 137033965Sjdp /* Static member function */ 137133965Sjdp if (oldmangled == NULL) 137233965Sjdp { 137333965Sjdp oldmangled = *mangled; 137433965Sjdp } 137533965Sjdp (*mangled)++; 137633965Sjdp work -> static_type = 1; 137733965Sjdp break; 137833965Sjdp 137933965Sjdp case 'C': 138060484Sobrien case 'V': 138160484Sobrien case 'u': 138260484Sobrien work->type_quals |= code_for_qualifier (**mangled); 138360484Sobrien 138460484Sobrien /* a qualified member function */ 138533965Sjdp if (oldmangled == NULL) 138660484Sobrien oldmangled = *mangled; 138760484Sobrien (*mangled)++; 138860484Sobrien break; 138960484Sobrien 139060484Sobrien case 'L': 139160484Sobrien /* Local class name follows after "Lnnn_" */ 139260484Sobrien if (HP_DEMANGLING) 139333965Sjdp { 139460484Sobrien while (**mangled && (**mangled != '_')) 139560484Sobrien (*mangled)++; 139660484Sobrien if (!**mangled) 139760484Sobrien success = 0; 139860484Sobrien else 139960484Sobrien (*mangled)++; 140033965Sjdp } 140160484Sobrien else 140260484Sobrien success = 0; 140333965Sjdp break; 140460484Sobrien 140533965Sjdp case '0': case '1': case '2': case '3': case '4': 140633965Sjdp case '5': case '6': case '7': case '8': case '9': 140733965Sjdp if (oldmangled == NULL) 140833965Sjdp { 140933965Sjdp oldmangled = *mangled; 141033965Sjdp } 141160484Sobrien work->temp_start = -1; /* uppermost call to demangle_class */ 141233965Sjdp success = demangle_class (work, mangled, declp); 141333965Sjdp if (success) 141433965Sjdp { 141533965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 141633965Sjdp } 141760484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) 141833965Sjdp { 141960484Sobrien /* EDG and others will have the "F", so we let the loop cycle 142060484Sobrien if we are looking at one. */ 142160484Sobrien if (**mangled != 'F') 142260484Sobrien expect_func = 1; 142333965Sjdp } 142433965Sjdp oldmangled = NULL; 142533965Sjdp break; 142660484Sobrien 142760484Sobrien case 'B': 142860484Sobrien { 142960484Sobrien string s; 143060484Sobrien success = do_type (work, mangled, &s); 143160484Sobrien if (success) 143260484Sobrien { 143360484Sobrien string_append (&s, SCOPE_STRING (work)); 143460484Sobrien string_prepends (declp, &s); 143560484Sobrien } 143660484Sobrien oldmangled = NULL; 143760484Sobrien expect_func = 1; 143860484Sobrien } 143960484Sobrien break; 144060484Sobrien 144133965Sjdp case 'F': 144233965Sjdp /* Function */ 144360484Sobrien /* ARM/HP style demangling includes a specific 'F' character after 144433965Sjdp the class name. For GNU style, it is just implied. So we can 144533965Sjdp safely just consume any 'F' at this point and be compatible 144633965Sjdp with either style. */ 144733965Sjdp 144833965Sjdp oldmangled = NULL; 144933965Sjdp func_done = 1; 145033965Sjdp (*mangled)++; 145133965Sjdp 145260484Sobrien /* For lucid/ARM/HP style we have to forget any types we might 145333965Sjdp have remembered up to this point, since they were not argument 145433965Sjdp types. GNU style considers all types seen as available for 145533965Sjdp back references. See comment in demangle_args() */ 145633965Sjdp 145760484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 145833965Sjdp { 145933965Sjdp forget_types (work); 146033965Sjdp } 146133965Sjdp success = demangle_args (work, mangled, declp); 146260484Sobrien /* After picking off the function args, we expect to either 146360484Sobrien find the function return type (preceded by an '_') or the 146460484Sobrien end of the string. */ 146560484Sobrien if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') 146660484Sobrien { 146760484Sobrien ++(*mangled); 146860484Sobrien /* At this level, we do not care about the return type. */ 146960484Sobrien success = do_type (work, mangled, &tname); 147060484Sobrien string_delete (&tname); 147160484Sobrien } 147260484Sobrien 147333965Sjdp break; 147460484Sobrien 147533965Sjdp case 't': 147633965Sjdp /* G++ Template */ 147760484Sobrien string_init(&trawname); 147833965Sjdp string_init(&tname); 147933965Sjdp if (oldmangled == NULL) 148033965Sjdp { 148133965Sjdp oldmangled = *mangled; 148233965Sjdp } 148360484Sobrien success = demangle_template (work, mangled, &tname, 148460484Sobrien &trawname, 1, 1); 148533965Sjdp if (success) 148633965Sjdp { 148733965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 148833965Sjdp } 148960484Sobrien string_append (&tname, SCOPE_STRING (work)); 149060484Sobrien 149133965Sjdp string_prepends(declp, &tname); 149233965Sjdp if (work -> destructor & 1) 149333965Sjdp { 149433965Sjdp string_prepend (&trawname, "~"); 149533965Sjdp string_appends (declp, &trawname); 149633965Sjdp work->destructor -= 1; 149733965Sjdp } 149833965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 149933965Sjdp { 150033965Sjdp string_appends (declp, &trawname); 150133965Sjdp work->constructor -= 1; 150233965Sjdp } 150333965Sjdp string_delete(&trawname); 150433965Sjdp string_delete(&tname); 150533965Sjdp oldmangled = NULL; 150633965Sjdp expect_func = 1; 150733965Sjdp break; 150833965Sjdp 150933965Sjdp case '_': 151068765Sobrien if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) 151138889Sjdp { 151238889Sjdp /* Read the return type. */ 151338889Sjdp string return_type; 151438889Sjdp string_init (&return_type); 151538889Sjdp 151638889Sjdp (*mangled)++; 151738889Sjdp success = do_type (work, mangled, &return_type); 151838889Sjdp APPEND_BLANK (&return_type); 151938889Sjdp 152038889Sjdp string_prepends (declp, &return_type); 152138889Sjdp string_delete (&return_type); 152238889Sjdp break; 152338889Sjdp } 152438889Sjdp else 152538889Sjdp /* At the outermost level, we cannot have a return type specified, 152638889Sjdp so if we run into another '_' at this point we are dealing with 152738889Sjdp a mangled name that is either bogus, or has been mangled by 152838889Sjdp some algorithm we don't know how to deal with. So just 152938889Sjdp reject the entire demangling. */ 153060484Sobrien /* However, "_nnn" is an expected suffix for alternate entry point 153160484Sobrien numbered nnn for a function, with HP aCC, so skip over that 153260484Sobrien without reporting failure. pai/1997-09-04 */ 153360484Sobrien if (HP_DEMANGLING) 153460484Sobrien { 153560484Sobrien (*mangled)++; 153677298Sobrien while (**mangled && ISDIGIT ((unsigned char)**mangled)) 153760484Sobrien (*mangled)++; 153860484Sobrien } 153960484Sobrien else 154060484Sobrien success = 0; 154133965Sjdp break; 154233965Sjdp 154338889Sjdp case 'H': 154468765Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 154538889Sjdp { 154638889Sjdp /* A G++ template function. Read the template arguments. */ 154760484Sobrien success = demangle_template (work, mangled, declp, 0, 0, 154860484Sobrien 0); 154938889Sjdp if (!(work->constructor & 1)) 155038889Sjdp expect_return_type = 1; 155138889Sjdp (*mangled)++; 155238889Sjdp break; 155338889Sjdp } 155438889Sjdp else 155538889Sjdp /* fall through */ 155660484Sobrien {;} 155738889Sjdp 155833965Sjdp default: 155933965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 156033965Sjdp { 156133965Sjdp /* Assume we have stumbled onto the first outermost function 156233965Sjdp argument token, and start processing args. */ 156333965Sjdp func_done = 1; 156433965Sjdp success = demangle_args (work, mangled, declp); 156533965Sjdp } 156633965Sjdp else 156733965Sjdp { 156833965Sjdp /* Non-GNU demanglers use a specific token to mark the start 156933965Sjdp of the outermost function argument tokens. Typically 'F', 157060484Sobrien for ARM/HP-demangling, for example. So if we find something 157133965Sjdp we are not prepared for, it must be an error. */ 157233965Sjdp success = 0; 157333965Sjdp } 157433965Sjdp break; 157533965Sjdp } 157633965Sjdp /* 157733965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 157833965Sjdp */ 157933965Sjdp { 158033965Sjdp if (success && expect_func) 158133965Sjdp { 158233965Sjdp func_done = 1; 158360484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) 158460484Sobrien { 158560484Sobrien forget_types (work); 158660484Sobrien } 158733965Sjdp success = demangle_args (work, mangled, declp); 158838889Sjdp /* Since template include the mangling of their return types, 158938889Sjdp we must set expect_func to 0 so that we don't try do 159038889Sjdp demangle more arguments the next time we get here. */ 159138889Sjdp expect_func = 0; 159233965Sjdp } 159333965Sjdp } 159433965Sjdp } 159533965Sjdp if (success && !func_done) 159633965Sjdp { 159733965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 159833965Sjdp { 159933965Sjdp /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and 160033965Sjdp bar__3fooi is 'foo::bar(int)'. We get here when we find the 160133965Sjdp first case, and need to ensure that the '(void)' gets added to 160260484Sobrien the current declp. Note that with ARM/HP, the first case 160333965Sjdp represents the name of a static data member 'foo::bar', 160433965Sjdp which is in the current declp, so we leave it alone. */ 160533965Sjdp success = demangle_args (work, mangled, declp); 160633965Sjdp } 160733965Sjdp } 160860484Sobrien if (success && PRINT_ARG_TYPES) 160933965Sjdp { 161060484Sobrien if (work->static_type) 161160484Sobrien string_append (declp, " static"); 161260484Sobrien if (work->type_quals != TYPE_UNQUALIFIED) 161360484Sobrien { 161460484Sobrien APPEND_BLANK (declp); 161560484Sobrien string_append (declp, qualifier_string (work->type_quals)); 161660484Sobrien } 161733965Sjdp } 161860484Sobrien 161933965Sjdp return (success); 162033965Sjdp} 162133965Sjdp 162233965Sjdp#if 0 162333965Sjdp 162433965Sjdpstatic int 162533965Sjdpdemangle_method_args (work, mangled, declp) 162633965Sjdp struct work_stuff *work; 162733965Sjdp const char **mangled; 162833965Sjdp string *declp; 162933965Sjdp{ 163033965Sjdp int success = 0; 163133965Sjdp 163233965Sjdp if (work -> static_type) 163333965Sjdp { 163433965Sjdp string_append (declp, *mangled + 1); 163533965Sjdp *mangled += strlen (*mangled); 163633965Sjdp success = 1; 163733965Sjdp } 163833965Sjdp else 163933965Sjdp { 164033965Sjdp success = demangle_args (work, mangled, declp); 164133965Sjdp } 164233965Sjdp return (success); 164333965Sjdp} 164433965Sjdp 164533965Sjdp#endif 164633965Sjdp 164733965Sjdpstatic int 164860484Sobriendemangle_template_template_parm (work, mangled, tname) 164933965Sjdp struct work_stuff *work; 165033965Sjdp const char **mangled; 165133965Sjdp string *tname; 165260484Sobrien{ 165360484Sobrien int i; 165460484Sobrien int r; 165560484Sobrien int need_comma = 0; 165660484Sobrien int success = 1; 165760484Sobrien string temp; 165860484Sobrien 165960484Sobrien string_append (tname, "template <"); 166060484Sobrien /* get size of template parameter list */ 166160484Sobrien if (get_count (mangled, &r)) 166260484Sobrien { 166360484Sobrien for (i = 0; i < r; i++) 166460484Sobrien { 166560484Sobrien if (need_comma) 166660484Sobrien { 166760484Sobrien string_append (tname, ", "); 166860484Sobrien } 166960484Sobrien 167060484Sobrien /* Z for type parameters */ 167160484Sobrien if (**mangled == 'Z') 167260484Sobrien { 167360484Sobrien (*mangled)++; 167460484Sobrien string_append (tname, "class"); 167560484Sobrien } 167660484Sobrien /* z for template parameters */ 167760484Sobrien else if (**mangled == 'z') 167860484Sobrien { 167960484Sobrien (*mangled)++; 168060484Sobrien success = 168160484Sobrien demangle_template_template_parm (work, mangled, tname); 168260484Sobrien if (!success) 168360484Sobrien { 168460484Sobrien break; 168560484Sobrien } 168660484Sobrien } 168760484Sobrien else 168860484Sobrien { 168960484Sobrien /* temp is initialized in do_type */ 169060484Sobrien success = do_type (work, mangled, &temp); 169160484Sobrien if (success) 169260484Sobrien { 169360484Sobrien string_appends (tname, &temp); 169460484Sobrien } 169560484Sobrien string_delete(&temp); 169660484Sobrien if (!success) 169760484Sobrien { 169860484Sobrien break; 169960484Sobrien } 170060484Sobrien } 170160484Sobrien need_comma = 1; 170260484Sobrien } 170360484Sobrien 170460484Sobrien } 170560484Sobrien if (tname->p[-1] == '>') 170660484Sobrien string_append (tname, " "); 170760484Sobrien string_append (tname, "> class"); 170860484Sobrien return (success); 170960484Sobrien} 171060484Sobrien 171160484Sobrienstatic int 171260484Sobriendemangle_expression (work, mangled, s, tk) 171360484Sobrien struct work_stuff *work; 171460484Sobrien const char** mangled; 171560484Sobrien string* s; 171660484Sobrien type_kind_t tk; 171760484Sobrien{ 171860484Sobrien int need_operator = 0; 171960484Sobrien int success; 172060484Sobrien 172160484Sobrien success = 1; 172260484Sobrien string_appendn (s, "(", 1); 172360484Sobrien (*mangled)++; 172460484Sobrien while (success && **mangled != 'W' && **mangled != '\0') 172560484Sobrien { 172660484Sobrien if (need_operator) 172760484Sobrien { 172860484Sobrien size_t i; 172960484Sobrien size_t len; 173060484Sobrien 173160484Sobrien success = 0; 173260484Sobrien 173360484Sobrien len = strlen (*mangled); 173460484Sobrien 173577298Sobrien for (i = 0; i < ARRAY_SIZE (optable); ++i) 173660484Sobrien { 173760484Sobrien size_t l = strlen (optable[i].in); 173860484Sobrien 173960484Sobrien if (l <= len 174060484Sobrien && memcmp (optable[i].in, *mangled, l) == 0) 174160484Sobrien { 174260484Sobrien string_appendn (s, " ", 1); 174360484Sobrien string_append (s, optable[i].out); 174460484Sobrien string_appendn (s, " ", 1); 174560484Sobrien success = 1; 174660484Sobrien (*mangled) += l; 174760484Sobrien break; 174860484Sobrien } 174960484Sobrien } 175060484Sobrien 175160484Sobrien if (!success) 175260484Sobrien break; 175360484Sobrien } 175460484Sobrien else 175560484Sobrien need_operator = 1; 175660484Sobrien 175760484Sobrien success = demangle_template_value_parm (work, mangled, s, tk); 175860484Sobrien } 175960484Sobrien 176060484Sobrien if (**mangled != 'W') 176160484Sobrien success = 0; 176260484Sobrien else 176360484Sobrien { 176460484Sobrien string_appendn (s, ")", 1); 176560484Sobrien (*mangled)++; 176660484Sobrien } 176760484Sobrien 176860484Sobrien return success; 176960484Sobrien} 177060484Sobrien 177160484Sobrienstatic int 177260484Sobriendemangle_integral_value (work, mangled, s) 177360484Sobrien struct work_stuff *work; 177460484Sobrien const char** mangled; 177560484Sobrien string* s; 177660484Sobrien{ 177760484Sobrien int success; 177860484Sobrien 177960484Sobrien if (**mangled == 'E') 178060484Sobrien success = demangle_expression (work, mangled, s, tk_integral); 178160484Sobrien else if (**mangled == 'Q' || **mangled == 'K') 178260484Sobrien success = demangle_qualified (work, mangled, s, 0, 1); 178360484Sobrien else 178460484Sobrien { 178560484Sobrien int value; 178660484Sobrien 178768765Sobrien /* By default, we let the number decide whether we shall consume an 178868765Sobrien underscore. */ 178968765Sobrien int consume_following_underscore = 0; 179068765Sobrien int leave_following_underscore = 0; 179168765Sobrien 179260484Sobrien success = 0; 179360484Sobrien 179460484Sobrien /* Negative numbers are indicated with a leading `m'. */ 179560484Sobrien if (**mangled == 'm') 179660484Sobrien { 179760484Sobrien string_appendn (s, "-", 1); 179860484Sobrien (*mangled)++; 179960484Sobrien } 180068765Sobrien else if (mangled[0][0] == '_' && mangled[0][1] == 'm') 180168765Sobrien { 180268765Sobrien /* Since consume_count_with_underscores does not handle the 180368765Sobrien `m'-prefix we must do it here, using consume_count and 180468765Sobrien adjusting underscores: we have to consume the underscore 180568765Sobrien matching the prepended one. */ 180668765Sobrien consume_following_underscore = 1; 180768765Sobrien string_appendn (s, "-", 1); 180868765Sobrien (*mangled) += 2; 180968765Sobrien } 181068765Sobrien else if (**mangled == '_') 181168765Sobrien { 181268765Sobrien /* Do not consume a following underscore; 181368765Sobrien consume_following_underscore will consume what should be 181468765Sobrien consumed. */ 181568765Sobrien leave_following_underscore = 1; 181668765Sobrien } 181760484Sobrien 181868765Sobrien /* We must call consume_count if we expect to remove a trailing 181968765Sobrien underscore, since consume_count_with_underscores expects 182068765Sobrien the leading underscore (that we consumed) if it is to handle 182168765Sobrien multi-digit numbers. */ 182268765Sobrien if (consume_following_underscore) 182368765Sobrien value = consume_count (mangled); 182468765Sobrien else 182568765Sobrien value = consume_count_with_underscores (mangled); 182668765Sobrien 182760484Sobrien if (value != -1) 182860484Sobrien { 182960484Sobrien char buf[INTBUF_SIZE]; 183060484Sobrien sprintf (buf, "%d", value); 183160484Sobrien string_append (s, buf); 183260484Sobrien 183368765Sobrien /* Numbers not otherwise delimited, might have an underscore 183468765Sobrien appended as a delimeter, which we should skip. 183568765Sobrien 183668765Sobrien ??? This used to always remove a following underscore, which 183768765Sobrien is wrong. If other (arbitrary) cases are followed by an 183868765Sobrien underscore, we need to do something more radical. */ 183968765Sobrien 184068765Sobrien if ((value > 9 || consume_following_underscore) 184168765Sobrien && ! leave_following_underscore 184268765Sobrien && **mangled == '_') 184360484Sobrien (*mangled)++; 184460484Sobrien 184560484Sobrien /* All is well. */ 184660484Sobrien success = 1; 184760484Sobrien } 184860484Sobrien } 184960484Sobrien 185060484Sobrien return success; 185160484Sobrien} 185260484Sobrien 185360484Sobrien/* Demangle the real value in MANGLED. */ 185460484Sobrien 185560484Sobrienstatic int 185660484Sobriendemangle_real_value (work, mangled, s) 185760484Sobrien struct work_stuff *work; 185860484Sobrien const char **mangled; 185960484Sobrien string* s; 186060484Sobrien{ 186160484Sobrien if (**mangled == 'E') 186260484Sobrien return demangle_expression (work, mangled, s, tk_real); 186360484Sobrien 186460484Sobrien if (**mangled == 'm') 186560484Sobrien { 186660484Sobrien string_appendn (s, "-", 1); 186760484Sobrien (*mangled)++; 186860484Sobrien } 186977298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 187060484Sobrien { 187160484Sobrien string_appendn (s, *mangled, 1); 187260484Sobrien (*mangled)++; 187360484Sobrien } 187460484Sobrien if (**mangled == '.') /* fraction */ 187560484Sobrien { 187660484Sobrien string_appendn (s, ".", 1); 187760484Sobrien (*mangled)++; 187877298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 187960484Sobrien { 188060484Sobrien string_appendn (s, *mangled, 1); 188160484Sobrien (*mangled)++; 188260484Sobrien } 188360484Sobrien } 188460484Sobrien if (**mangled == 'e') /* exponent */ 188560484Sobrien { 188660484Sobrien string_appendn (s, "e", 1); 188760484Sobrien (*mangled)++; 188877298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 188960484Sobrien { 189060484Sobrien string_appendn (s, *mangled, 1); 189160484Sobrien (*mangled)++; 189260484Sobrien } 189360484Sobrien } 189460484Sobrien 189560484Sobrien return 1; 189660484Sobrien} 189760484Sobrien 189860484Sobrienstatic int 189960484Sobriendemangle_template_value_parm (work, mangled, s, tk) 190060484Sobrien struct work_stuff *work; 190160484Sobrien const char **mangled; 190260484Sobrien string* s; 190360484Sobrien type_kind_t tk; 190460484Sobrien{ 190560484Sobrien int success = 1; 190660484Sobrien 190760484Sobrien if (**mangled == 'Y') 190860484Sobrien { 190960484Sobrien /* The next argument is a template parameter. */ 191060484Sobrien int idx; 191160484Sobrien 191260484Sobrien (*mangled)++; 191360484Sobrien idx = consume_count_with_underscores (mangled); 191460484Sobrien if (idx == -1 191560484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 191660484Sobrien || consume_count_with_underscores (mangled) == -1) 191760484Sobrien return -1; 191860484Sobrien if (work->tmpl_argvec) 191960484Sobrien string_append (s, work->tmpl_argvec[idx]); 192060484Sobrien else 192160484Sobrien string_append_template_idx (s, idx); 192260484Sobrien } 192360484Sobrien else if (tk == tk_integral) 192460484Sobrien success = demangle_integral_value (work, mangled, s); 192560484Sobrien else if (tk == tk_char) 192660484Sobrien { 192760484Sobrien char tmp[2]; 192860484Sobrien int val; 192960484Sobrien if (**mangled == 'm') 193060484Sobrien { 193160484Sobrien string_appendn (s, "-", 1); 193260484Sobrien (*mangled)++; 193360484Sobrien } 193460484Sobrien string_appendn (s, "'", 1); 193560484Sobrien val = consume_count(mangled); 193660484Sobrien if (val <= 0) 193760484Sobrien success = 0; 193860484Sobrien else 193960484Sobrien { 194060484Sobrien tmp[0] = (char)val; 194160484Sobrien tmp[1] = '\0'; 194260484Sobrien string_appendn (s, &tmp[0], 1); 194360484Sobrien string_appendn (s, "'", 1); 194460484Sobrien } 194560484Sobrien } 194660484Sobrien else if (tk == tk_bool) 194760484Sobrien { 194860484Sobrien int val = consume_count (mangled); 194960484Sobrien if (val == 0) 195060484Sobrien string_appendn (s, "false", 5); 195160484Sobrien else if (val == 1) 195260484Sobrien string_appendn (s, "true", 4); 195360484Sobrien else 195460484Sobrien success = 0; 195560484Sobrien } 195660484Sobrien else if (tk == tk_real) 195760484Sobrien success = demangle_real_value (work, mangled, s); 195860484Sobrien else if (tk == tk_pointer || tk == tk_reference) 195960484Sobrien { 196060484Sobrien if (**mangled == 'Q') 196160484Sobrien success = demangle_qualified (work, mangled, s, 196260484Sobrien /*isfuncname=*/0, 196360484Sobrien /*append=*/1); 196460484Sobrien else 196560484Sobrien { 196660484Sobrien int symbol_len = consume_count (mangled); 196760484Sobrien if (symbol_len == -1) 196860484Sobrien return -1; 196960484Sobrien if (symbol_len == 0) 197060484Sobrien string_appendn (s, "0", 1); 197160484Sobrien else 197260484Sobrien { 197360484Sobrien char *p = xmalloc (symbol_len + 1), *q; 197460484Sobrien strncpy (p, *mangled, symbol_len); 197560484Sobrien p [symbol_len] = '\0'; 197660484Sobrien /* We use cplus_demangle here, rather than 197760484Sobrien internal_cplus_demangle, because the name of the entity 197860484Sobrien mangled here does not make use of any of the squangling 197960484Sobrien or type-code information we have built up thus far; it is 198060484Sobrien mangled independently. */ 198160484Sobrien q = cplus_demangle (p, work->options); 198260484Sobrien if (tk == tk_pointer) 198360484Sobrien string_appendn (s, "&", 1); 198460484Sobrien /* FIXME: Pointer-to-member constants should get a 198560484Sobrien qualifying class name here. */ 198660484Sobrien if (q) 198760484Sobrien { 198860484Sobrien string_append (s, q); 198960484Sobrien free (q); 199060484Sobrien } 199160484Sobrien else 199260484Sobrien string_append (s, p); 199360484Sobrien free (p); 199460484Sobrien } 199560484Sobrien *mangled += symbol_len; 199660484Sobrien } 199760484Sobrien } 199860484Sobrien 199960484Sobrien return success; 200060484Sobrien} 200160484Sobrien 200260484Sobrien/* Demangle the template name in MANGLED. The full name of the 200360484Sobrien template (e.g., S<int>) is placed in TNAME. The name without the 200460484Sobrien template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is 200560484Sobrien non-NULL. If IS_TYPE is nonzero, this template is a type template, 200660484Sobrien not a function template. If both IS_TYPE and REMEMBER are nonzero, 200768765Sobrien the template is remembered in the list of back-referenceable 200860484Sobrien types. */ 200960484Sobrien 201060484Sobrienstatic int 201160484Sobriendemangle_template (work, mangled, tname, trawname, is_type, remember) 201260484Sobrien struct work_stuff *work; 201360484Sobrien const char **mangled; 201460484Sobrien string *tname; 201533965Sjdp string *trawname; 201638889Sjdp int is_type; 201760484Sobrien int remember; 201833965Sjdp{ 201933965Sjdp int i; 202033965Sjdp int r; 202133965Sjdp int need_comma = 0; 202233965Sjdp int success = 0; 202333965Sjdp const char *start; 202438889Sjdp int is_java_array = 0; 202533965Sjdp string temp; 202660484Sobrien int bindex = 0; 202733965Sjdp 202833965Sjdp (*mangled)++; 202938889Sjdp if (is_type) 203033965Sjdp { 203160484Sobrien if (remember) 203260484Sobrien bindex = register_Btype (work); 203338889Sjdp start = *mangled; 203438889Sjdp /* get template name */ 203560484Sobrien if (**mangled == 'z') 203638889Sjdp { 203760484Sobrien int idx; 203860484Sobrien (*mangled)++; 203960484Sobrien (*mangled)++; 204060484Sobrien 204160484Sobrien idx = consume_count_with_underscores (mangled); 204260484Sobrien if (idx == -1 204360484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 204460484Sobrien || consume_count_with_underscores (mangled) == -1) 204560484Sobrien return (0); 204660484Sobrien 204760484Sobrien if (work->tmpl_argvec) 204860484Sobrien { 204960484Sobrien string_append (tname, work->tmpl_argvec[idx]); 205060484Sobrien if (trawname) 205160484Sobrien string_append (trawname, work->tmpl_argvec[idx]); 205260484Sobrien } 205360484Sobrien else 205460484Sobrien { 205560484Sobrien string_append_template_idx (tname, idx); 205660484Sobrien if (trawname) 205760484Sobrien string_append_template_idx (trawname, idx); 205860484Sobrien } 205938889Sjdp } 206060484Sobrien else 206138889Sjdp { 206260484Sobrien if ((r = consume_count (mangled)) <= 0 206360484Sobrien || (int) strlen (*mangled) < r) 206460484Sobrien { 206560484Sobrien return (0); 206660484Sobrien } 206760484Sobrien is_java_array = (work -> options & DMGL_JAVA) 206860484Sobrien && strncmp (*mangled, "JArray1Z", 8) == 0; 206960484Sobrien if (! is_java_array) 207060484Sobrien { 207160484Sobrien string_appendn (tname, *mangled, r); 207260484Sobrien } 207360484Sobrien if (trawname) 207460484Sobrien string_appendn (trawname, *mangled, r); 207560484Sobrien *mangled += r; 207638889Sjdp } 207733965Sjdp } 207838889Sjdp if (!is_java_array) 207938889Sjdp string_append (tname, "<"); 208033965Sjdp /* get size of template parameter list */ 208133965Sjdp if (!get_count (mangled, &r)) 208233965Sjdp { 208333965Sjdp return (0); 208433965Sjdp } 208538889Sjdp if (!is_type) 208638889Sjdp { 208738889Sjdp /* Create an array for saving the template argument values. */ 208838889Sjdp work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); 208938889Sjdp work->ntmpl_args = r; 209038889Sjdp for (i = 0; i < r; i++) 209138889Sjdp work->tmpl_argvec[i] = 0; 209238889Sjdp } 209333965Sjdp for (i = 0; i < r; i++) 209433965Sjdp { 209533965Sjdp if (need_comma) 209633965Sjdp { 209733965Sjdp string_append (tname, ", "); 209833965Sjdp } 209933965Sjdp /* Z for type parameters */ 210033965Sjdp if (**mangled == 'Z') 210133965Sjdp { 210233965Sjdp (*mangled)++; 210333965Sjdp /* temp is initialized in do_type */ 210433965Sjdp success = do_type (work, mangled, &temp); 210533965Sjdp if (success) 210633965Sjdp { 210733965Sjdp string_appends (tname, &temp); 210838889Sjdp 210938889Sjdp if (!is_type) 211038889Sjdp { 211138889Sjdp /* Save the template argument. */ 211238889Sjdp int len = temp.p - temp.b; 211338889Sjdp work->tmpl_argvec[i] = xmalloc (len + 1); 211438889Sjdp memcpy (work->tmpl_argvec[i], temp.b, len); 211538889Sjdp work->tmpl_argvec[i][len] = '\0'; 211638889Sjdp } 211733965Sjdp } 211833965Sjdp string_delete(&temp); 211933965Sjdp if (!success) 212033965Sjdp { 212133965Sjdp break; 212233965Sjdp } 212333965Sjdp } 212460484Sobrien /* z for template parameters */ 212560484Sobrien else if (**mangled == 'z') 212660484Sobrien { 212760484Sobrien int r2; 212860484Sobrien (*mangled)++; 212960484Sobrien success = demangle_template_template_parm (work, mangled, tname); 213060484Sobrien 213160484Sobrien if (success 213260484Sobrien && (r2 = consume_count (mangled)) > 0 213360484Sobrien && (int) strlen (*mangled) >= r2) 213460484Sobrien { 213560484Sobrien string_append (tname, " "); 213660484Sobrien string_appendn (tname, *mangled, r2); 213760484Sobrien if (!is_type) 213860484Sobrien { 213960484Sobrien /* Save the template argument. */ 214060484Sobrien int len = r2; 214160484Sobrien work->tmpl_argvec[i] = xmalloc (len + 1); 214260484Sobrien memcpy (work->tmpl_argvec[i], *mangled, len); 214360484Sobrien work->tmpl_argvec[i][len] = '\0'; 214460484Sobrien } 214560484Sobrien *mangled += r2; 214660484Sobrien } 214760484Sobrien if (!success) 214860484Sobrien { 214960484Sobrien break; 215060484Sobrien } 215160484Sobrien } 215233965Sjdp else 215333965Sjdp { 215438889Sjdp string param; 215538889Sjdp string* s; 215638889Sjdp 215733965Sjdp /* otherwise, value parameter */ 215860484Sobrien 215933965Sjdp /* temp is initialized in do_type */ 216033965Sjdp success = do_type (work, mangled, &temp); 216133965Sjdp string_delete(&temp); 216233965Sjdp if (!success) 216360484Sobrien break; 216438889Sjdp 216538889Sjdp if (!is_type) 216638889Sjdp { 216738889Sjdp s = ¶m; 216838889Sjdp string_init (s); 216938889Sjdp } 217038889Sjdp else 217138889Sjdp s = tname; 217238889Sjdp 217360484Sobrien success = demangle_template_value_parm (work, mangled, s, 217460484Sobrien (type_kind_t) success); 217538889Sjdp 217660484Sobrien if (!success) 217738889Sjdp { 217860484Sobrien if (!is_type) 217960484Sobrien string_delete (s); 218060484Sobrien success = 0; 218160484Sobrien break; 218233965Sjdp } 218360484Sobrien 218438889Sjdp if (!is_type) 218538889Sjdp { 218638889Sjdp int len = s->p - s->b; 218738889Sjdp work->tmpl_argvec[i] = xmalloc (len + 1); 218838889Sjdp memcpy (work->tmpl_argvec[i], s->b, len); 218938889Sjdp work->tmpl_argvec[i][len] = '\0'; 219060484Sobrien 219138889Sjdp string_appends (tname, s); 219238889Sjdp string_delete (s); 219338889Sjdp } 219433965Sjdp } 219533965Sjdp need_comma = 1; 219633965Sjdp } 219738889Sjdp if (is_java_array) 219838889Sjdp { 219938889Sjdp string_append (tname, "[]"); 220038889Sjdp } 220138889Sjdp else 220238889Sjdp { 220338889Sjdp if (tname->p[-1] == '>') 220438889Sjdp string_append (tname, " "); 220538889Sjdp string_append (tname, ">"); 220638889Sjdp } 220760484Sobrien 220860484Sobrien if (is_type && remember) 220960484Sobrien remember_Btype (work, tname->b, LEN_STRING (tname), bindex); 221060484Sobrien 221133965Sjdp /* 221233965Sjdp if (work -> static_type) 221333965Sjdp { 221433965Sjdp string_append (declp, *mangled + 1); 221533965Sjdp *mangled += strlen (*mangled); 221633965Sjdp success = 1; 221733965Sjdp } 221833965Sjdp else 221933965Sjdp { 222033965Sjdp success = demangle_args (work, mangled, declp); 222133965Sjdp } 222233965Sjdp } 222333965Sjdp */ 222433965Sjdp return (success); 222533965Sjdp} 222633965Sjdp 222733965Sjdpstatic int 222833965Sjdparm_pt (work, mangled, n, anchor, args) 222933965Sjdp struct work_stuff *work; 223033965Sjdp const char *mangled; 223133965Sjdp int n; 223233965Sjdp const char **anchor, **args; 223333965Sjdp{ 223460484Sobrien /* Check if ARM template with "__pt__" in it ("parameterized type") */ 223560484Sobrien /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ 223660484Sobrien if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = mystrstr (mangled, "__pt__"))) 223733965Sjdp { 223833965Sjdp int len; 223933965Sjdp *args = *anchor + 6; 224033965Sjdp len = consume_count (args); 224160484Sobrien if (len == -1) 224260484Sobrien return 0; 224333965Sjdp if (*args + len == mangled + n && **args == '_') 224433965Sjdp { 224533965Sjdp ++*args; 224633965Sjdp return 1; 224733965Sjdp } 224833965Sjdp } 224960484Sobrien if (AUTO_DEMANGLING || EDG_DEMANGLING) 225060484Sobrien { 225160484Sobrien if ((*anchor = mystrstr (mangled, "__tm__")) 225260484Sobrien || (*anchor = mystrstr (mangled, "__ps__")) 225360484Sobrien || (*anchor = mystrstr (mangled, "__pt__"))) 225460484Sobrien { 225560484Sobrien int len; 225660484Sobrien *args = *anchor + 6; 225760484Sobrien len = consume_count (args); 225860484Sobrien if (len == -1) 225960484Sobrien return 0; 226060484Sobrien if (*args + len == mangled + n && **args == '_') 226160484Sobrien { 226260484Sobrien ++*args; 226360484Sobrien return 1; 226460484Sobrien } 226560484Sobrien } 226660484Sobrien else if ((*anchor = mystrstr (mangled, "__S"))) 226760484Sobrien { 226860484Sobrien int len; 226960484Sobrien *args = *anchor + 3; 227060484Sobrien len = consume_count (args); 227160484Sobrien if (len == -1) 227260484Sobrien return 0; 227360484Sobrien if (*args + len == mangled + n && **args == '_') 227460484Sobrien { 227560484Sobrien ++*args; 227660484Sobrien return 1; 227760484Sobrien } 227860484Sobrien } 227960484Sobrien } 228060484Sobrien 228133965Sjdp return 0; 228233965Sjdp} 228333965Sjdp 228433965Sjdpstatic void 228560484Sobriendemangle_arm_hp_template (work, mangled, n, declp) 228633965Sjdp struct work_stuff *work; 228733965Sjdp const char **mangled; 228833965Sjdp int n; 228933965Sjdp string *declp; 229033965Sjdp{ 229133965Sjdp const char *p; 229233965Sjdp const char *args; 229333965Sjdp const char *e = *mangled + n; 229460484Sobrien string arg; 229533965Sjdp 229660484Sobrien /* Check for HP aCC template spec: classXt1t2 where t1, t2 are 229760484Sobrien template args */ 229860484Sobrien if (HP_DEMANGLING && ((*mangled)[n] == 'X')) 229933965Sjdp { 230060484Sobrien char *start_spec_args = NULL; 230160484Sobrien 230260484Sobrien /* First check for and omit template specialization pseudo-arguments, 230360484Sobrien such as in "Spec<#1,#1.*>" */ 230460484Sobrien start_spec_args = strchr (*mangled, '<'); 230560484Sobrien if (start_spec_args && (start_spec_args - *mangled < n)) 230660484Sobrien string_appendn (declp, *mangled, start_spec_args - *mangled); 230760484Sobrien else 230860484Sobrien string_appendn (declp, *mangled, n); 230960484Sobrien (*mangled) += n + 1; 231033965Sjdp string_init (&arg); 231160484Sobrien if (work->temp_start == -1) /* non-recursive call */ 231260484Sobrien work->temp_start = declp->p - declp->b; 231360484Sobrien string_append (declp, "<"); 231460484Sobrien while (1) 231560484Sobrien { 231660484Sobrien string_clear (&arg); 231760484Sobrien switch (**mangled) 231860484Sobrien { 231960484Sobrien case 'T': 232060484Sobrien /* 'T' signals a type parameter */ 232160484Sobrien (*mangled)++; 232260484Sobrien if (!do_type (work, mangled, &arg)) 232360484Sobrien goto hpacc_template_args_done; 232460484Sobrien break; 232560484Sobrien 232660484Sobrien case 'U': 232760484Sobrien case 'S': 232860484Sobrien /* 'U' or 'S' signals an integral value */ 232960484Sobrien if (!do_hpacc_template_const_value (work, mangled, &arg)) 233060484Sobrien goto hpacc_template_args_done; 233160484Sobrien break; 233260484Sobrien 233360484Sobrien case 'A': 233460484Sobrien /* 'A' signals a named constant expression (literal) */ 233560484Sobrien if (!do_hpacc_template_literal (work, mangled, &arg)) 233660484Sobrien goto hpacc_template_args_done; 233760484Sobrien break; 233860484Sobrien 233960484Sobrien default: 234060484Sobrien /* Today, 1997-09-03, we have only the above types 234160484Sobrien of template parameters */ 234260484Sobrien /* FIXME: maybe this should fail and return null */ 234360484Sobrien goto hpacc_template_args_done; 234460484Sobrien } 234560484Sobrien string_appends (declp, &arg); 234660484Sobrien /* Check if we're at the end of template args. 234760484Sobrien 0 if at end of static member of template class, 234860484Sobrien _ if done with template args for a function */ 234960484Sobrien if ((**mangled == '\000') || (**mangled == '_')) 235060484Sobrien break; 235160484Sobrien else 235260484Sobrien string_append (declp, ","); 235360484Sobrien } 235460484Sobrien hpacc_template_args_done: 235560484Sobrien string_append (declp, ">"); 235660484Sobrien string_delete (&arg); 235760484Sobrien if (**mangled == '_') 235860484Sobrien (*mangled)++; 235960484Sobrien return; 236060484Sobrien } 236160484Sobrien /* ARM template? (Also handles HP cfront extensions) */ 236260484Sobrien else if (arm_pt (work, *mangled, n, &p, &args)) 236360484Sobrien { 236460484Sobrien string type_str; 236560484Sobrien 236660484Sobrien string_init (&arg); 236733965Sjdp string_appendn (declp, *mangled, p - *mangled); 236860484Sobrien if (work->temp_start == -1) /* non-recursive call */ 236960484Sobrien work->temp_start = declp->p - declp->b; 237033965Sjdp string_append (declp, "<"); 237133965Sjdp /* should do error checking here */ 237233965Sjdp while (args < e) { 237333965Sjdp string_clear (&arg); 237460484Sobrien 237560484Sobrien /* Check for type or literal here */ 237660484Sobrien switch (*args) 237760484Sobrien { 237860484Sobrien /* HP cfront extensions to ARM for template args */ 237960484Sobrien /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ 238060484Sobrien /* FIXME: We handle only numeric literals for HP cfront */ 238160484Sobrien case 'X': 238260484Sobrien /* A typed constant value follows */ 238360484Sobrien args++; 238460484Sobrien if (!do_type (work, &args, &type_str)) 238560484Sobrien goto cfront_template_args_done; 238660484Sobrien string_append (&arg, "("); 238760484Sobrien string_appends (&arg, &type_str); 238860484Sobrien string_append (&arg, ")"); 238960484Sobrien if (*args != 'L') 239060484Sobrien goto cfront_template_args_done; 239160484Sobrien args++; 239260484Sobrien /* Now snarf a literal value following 'L' */ 239360484Sobrien if (!snarf_numeric_literal (&args, &arg)) 239460484Sobrien goto cfront_template_args_done; 239560484Sobrien break; 239660484Sobrien 239760484Sobrien case 'L': 239860484Sobrien /* Snarf a literal following 'L' */ 239960484Sobrien args++; 240060484Sobrien if (!snarf_numeric_literal (&args, &arg)) 240160484Sobrien goto cfront_template_args_done; 240260484Sobrien break; 240360484Sobrien default: 240460484Sobrien /* Not handling other HP cfront stuff */ 240560484Sobrien if (!do_type (work, &args, &arg)) 240660484Sobrien goto cfront_template_args_done; 240760484Sobrien } 240833965Sjdp string_appends (declp, &arg); 240933965Sjdp string_append (declp, ","); 241033965Sjdp } 241160484Sobrien cfront_template_args_done: 241233965Sjdp string_delete (&arg); 241360484Sobrien if (args >= e) 241460484Sobrien --declp->p; /* remove extra comma */ 241533965Sjdp string_append (declp, ">"); 241633965Sjdp } 241760484Sobrien else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 241860484Sobrien && (*mangled)[9] == 'N' 241960484Sobrien && (*mangled)[8] == (*mangled)[10] 242060484Sobrien && strchr (cplus_markers, (*mangled)[8])) 242160484Sobrien { 242260484Sobrien /* A member of the anonymous namespace. */ 242360484Sobrien string_append (declp, "{anonymous}"); 242460484Sobrien } 242533965Sjdp else 242633965Sjdp { 242760484Sobrien if (work->temp_start == -1) /* non-recursive call only */ 242860484Sobrien work->temp_start = 0; /* disable in recursive calls */ 242933965Sjdp string_appendn (declp, *mangled, n); 243033965Sjdp } 243133965Sjdp *mangled += n; 243233965Sjdp} 243333965Sjdp 243460484Sobrien/* Extract a class name, possibly a template with arguments, from the 243560484Sobrien mangled string; qualifiers, local class indicators, etc. have 243660484Sobrien already been dealt with */ 243760484Sobrien 243833965Sjdpstatic int 243933965Sjdpdemangle_class_name (work, mangled, declp) 244033965Sjdp struct work_stuff *work; 244133965Sjdp const char **mangled; 244233965Sjdp string *declp; 244333965Sjdp{ 244433965Sjdp int n; 244533965Sjdp int success = 0; 244633965Sjdp 244733965Sjdp n = consume_count (mangled); 244860484Sobrien if (n == -1) 244960484Sobrien return 0; 245060484Sobrien if ((int) strlen (*mangled) >= n) 245133965Sjdp { 245260484Sobrien demangle_arm_hp_template (work, mangled, n, declp); 245333965Sjdp success = 1; 245433965Sjdp } 245533965Sjdp 245633965Sjdp return (success); 245733965Sjdp} 245833965Sjdp 245933965Sjdp/* 246033965Sjdp 246133965SjdpLOCAL FUNCTION 246233965Sjdp 246333965Sjdp demangle_class -- demangle a mangled class sequence 246433965Sjdp 246533965SjdpSYNOPSIS 246633965Sjdp 246733965Sjdp static int 246833965Sjdp demangle_class (struct work_stuff *work, const char **mangled, 246933965Sjdp strint *declp) 247033965Sjdp 247133965SjdpDESCRIPTION 247233965Sjdp 247333965Sjdp DECLP points to the buffer into which demangling is being done. 247433965Sjdp 247533965Sjdp *MANGLED points to the current token to be demangled. On input, 247633965Sjdp it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) 247733965Sjdp On exit, it points to the next token after the mangled class on 247833965Sjdp success, or the first unconsumed token on failure. 247933965Sjdp 248033965Sjdp If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then 248133965Sjdp we are demangling a constructor or destructor. In this case 248233965Sjdp we prepend "class::class" or "class::~class" to DECLP. 248333965Sjdp 248433965Sjdp Otherwise, we prepend "class::" to the current DECLP. 248533965Sjdp 248633965Sjdp Reset the constructor/destructor flags once they have been 248733965Sjdp "consumed". This allows demangle_class to be called later during 248833965Sjdp the same demangling, to do normal class demangling. 248933965Sjdp 249033965Sjdp Returns 1 if demangling is successful, 0 otherwise. 249133965Sjdp 249233965Sjdp*/ 249333965Sjdp 249433965Sjdpstatic int 249533965Sjdpdemangle_class (work, mangled, declp) 249633965Sjdp struct work_stuff *work; 249733965Sjdp const char **mangled; 249833965Sjdp string *declp; 249933965Sjdp{ 250033965Sjdp int success = 0; 250160484Sobrien int btype; 250233965Sjdp string class_name; 250360484Sobrien char *save_class_name_end = 0; 250433965Sjdp 250533965Sjdp string_init (&class_name); 250660484Sobrien btype = register_Btype (work); 250733965Sjdp if (demangle_class_name (work, mangled, &class_name)) 250833965Sjdp { 250960484Sobrien save_class_name_end = class_name.p; 251033965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 251133965Sjdp { 251260484Sobrien /* adjust so we don't include template args */ 251360484Sobrien if (work->temp_start && (work->temp_start != -1)) 251460484Sobrien { 251560484Sobrien class_name.p = class_name.b + work->temp_start; 251660484Sobrien } 251733965Sjdp string_prepends (declp, &class_name); 251833965Sjdp if (work -> destructor & 1) 251933965Sjdp { 252033965Sjdp string_prepend (declp, "~"); 252133965Sjdp work -> destructor -= 1; 252233965Sjdp } 252333965Sjdp else 252433965Sjdp { 252560484Sobrien work -> constructor -= 1; 252633965Sjdp } 252733965Sjdp } 252860484Sobrien class_name.p = save_class_name_end; 252960484Sobrien remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); 253060484Sobrien remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); 253160484Sobrien string_prepend (declp, SCOPE_STRING (work)); 253233965Sjdp string_prepends (declp, &class_name); 253333965Sjdp success = 1; 253433965Sjdp } 253533965Sjdp string_delete (&class_name); 253633965Sjdp return (success); 253733965Sjdp} 253833965Sjdp 253968765Sobrien 254068765Sobrien/* Called when there's a "__" in the mangled name, with `scan' pointing to 254168765Sobrien the rightmost guess. 254268765Sobrien 254368765Sobrien Find the correct "__"-sequence where the function name ends and the 254468765Sobrien signature starts, which is ambiguous with GNU mangling. 254568765Sobrien Call demangle_signature here, so we can make sure we found the right 254668765Sobrien one; *mangled will be consumed so caller will not make further calls to 254768765Sobrien demangle_signature. */ 254868765Sobrien 254968765Sobrienstatic int 255068765Sobrieniterate_demangle_function (work, mangled, declp, scan) 255168765Sobrien struct work_stuff *work; 255268765Sobrien const char **mangled; 255368765Sobrien string *declp; 255468765Sobrien const char *scan; 255568765Sobrien{ 255668765Sobrien const char *mangle_init = *mangled; 255768765Sobrien int success = 0; 255868765Sobrien string decl_init; 255968765Sobrien struct work_stuff work_init; 256068765Sobrien 256168765Sobrien if (*(scan + 2) == '\0') 256268765Sobrien return 0; 256368765Sobrien 256468765Sobrien /* Do not iterate for some demangling modes, or if there's only one 256568765Sobrien "__"-sequence. This is the normal case. */ 256668765Sobrien if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING 256768765Sobrien || mystrstr (scan + 2, "__") == NULL) 256868765Sobrien { 256968765Sobrien demangle_function_name (work, mangled, declp, scan); 257068765Sobrien return 1; 257168765Sobrien } 257268765Sobrien 257368765Sobrien /* Save state so we can restart if the guess at the correct "__" was 257468765Sobrien wrong. */ 257568765Sobrien string_init (&decl_init); 257668765Sobrien string_appends (&decl_init, declp); 257768765Sobrien memset (&work_init, 0, sizeof work_init); 257868765Sobrien work_stuff_copy_to_from (&work_init, work); 257968765Sobrien 258068765Sobrien /* Iterate over occurrences of __, allowing names and types to have a 258168765Sobrien "__" sequence in them. We must start with the first (not the last) 258268765Sobrien occurrence, since "__" most often occur between independent mangled 258368765Sobrien parts, hence starting at the last occurence inside a signature 258468765Sobrien might get us a "successful" demangling of the signature. */ 258568765Sobrien 258668765Sobrien while (scan[2]) 258768765Sobrien { 258868765Sobrien demangle_function_name (work, mangled, declp, scan); 258968765Sobrien success = demangle_signature (work, mangled, declp); 259068765Sobrien if (success) 259168765Sobrien break; 259268765Sobrien 259368765Sobrien /* Reset demangle state for the next round. */ 259468765Sobrien *mangled = mangle_init; 259568765Sobrien string_clear (declp); 259668765Sobrien string_appends (declp, &decl_init); 259768765Sobrien work_stuff_copy_to_from (work, &work_init); 259868765Sobrien 259968765Sobrien /* Leave this underscore-sequence. */ 260068765Sobrien scan += 2; 260168765Sobrien 260268765Sobrien /* Scan for the next "__" sequence. */ 260368765Sobrien while (*scan && (scan[0] != '_' || scan[1] != '_')) 260468765Sobrien scan++; 260568765Sobrien 260668765Sobrien /* Move to last "__" in this sequence. */ 260768765Sobrien while (*scan && *scan == '_') 260868765Sobrien scan++; 260968765Sobrien scan -= 2; 261068765Sobrien } 261168765Sobrien 261268765Sobrien /* Delete saved state. */ 261368765Sobrien delete_work_stuff (&work_init); 261468765Sobrien string_delete (&decl_init); 261568765Sobrien 261668765Sobrien return success; 261768765Sobrien} 261868765Sobrien 261933965Sjdp/* 262033965Sjdp 262133965SjdpLOCAL FUNCTION 262233965Sjdp 262333965Sjdp demangle_prefix -- consume the mangled name prefix and find signature 262433965Sjdp 262533965SjdpSYNOPSIS 262633965Sjdp 262733965Sjdp static int 262833965Sjdp demangle_prefix (struct work_stuff *work, const char **mangled, 262933965Sjdp string *declp); 263033965Sjdp 263133965SjdpDESCRIPTION 263233965Sjdp 263333965Sjdp Consume and demangle the prefix of the mangled name. 263468765Sobrien While processing the function name root, arrange to call 263568765Sobrien demangle_signature if the root is ambiguous. 263633965Sjdp 263733965Sjdp DECLP points to the string buffer into which demangled output is 263833965Sjdp placed. On entry, the buffer is empty. On exit it contains 263933965Sjdp the root function name, the demangled operator name, or in some 264033965Sjdp special cases either nothing or the completely demangled result. 264133965Sjdp 264233965Sjdp MANGLED points to the current pointer into the mangled name. As each 264333965Sjdp token of the mangled name is consumed, it is updated. Upon entry 264433965Sjdp the current mangled name pointer points to the first character of 264533965Sjdp the mangled name. Upon exit, it should point to the first character 264633965Sjdp of the signature if demangling was successful, or to the first 264733965Sjdp unconsumed character if demangling of the prefix was unsuccessful. 264860484Sobrien 264933965Sjdp Returns 1 on success, 0 otherwise. 265033965Sjdp */ 265133965Sjdp 265233965Sjdpstatic int 265333965Sjdpdemangle_prefix (work, mangled, declp) 265433965Sjdp struct work_stuff *work; 265533965Sjdp const char **mangled; 265633965Sjdp string *declp; 265733965Sjdp{ 265833965Sjdp int success = 1; 265933965Sjdp const char *scan; 266033965Sjdp int i; 266133965Sjdp 266260484Sobrien if (strlen(*mangled) > 6 266360484Sobrien && (strncmp(*mangled, "_imp__", 6) == 0 266460484Sobrien || strncmp(*mangled, "__imp_", 6) == 0)) 266533965Sjdp { 266660484Sobrien /* it's a symbol imported from a PE dynamic library. Check for both 266760484Sobrien new style prefix _imp__ and legacy __imp_ used by older versions 266860484Sobrien of dlltool. */ 266960484Sobrien (*mangled) += 6; 267060484Sobrien work->dllimported = 1; 267160484Sobrien } 267260484Sobrien else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) 267360484Sobrien { 267433965Sjdp char *marker = strchr (cplus_markers, (*mangled)[8]); 267533965Sjdp if (marker != NULL && *marker == (*mangled)[10]) 267633965Sjdp { 267733965Sjdp if ((*mangled)[9] == 'D') 267833965Sjdp { 267933965Sjdp /* it's a GNU global destructor to be executed at program exit */ 268033965Sjdp (*mangled) += 11; 268133965Sjdp work->destructor = 2; 268233965Sjdp if (gnu_special (work, mangled, declp)) 268333965Sjdp return success; 268433965Sjdp } 268533965Sjdp else if ((*mangled)[9] == 'I') 268633965Sjdp { 268733965Sjdp /* it's a GNU global constructor to be executed at program init */ 268833965Sjdp (*mangled) += 11; 268933965Sjdp work->constructor = 2; 269033965Sjdp if (gnu_special (work, mangled, declp)) 269133965Sjdp return success; 269233965Sjdp } 269333965Sjdp } 269433965Sjdp } 269560484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) 269633965Sjdp { 269733965Sjdp /* it's a ARM global destructor to be executed at program exit */ 269833965Sjdp (*mangled) += 7; 269933965Sjdp work->destructor = 2; 270033965Sjdp } 270160484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) 270233965Sjdp { 270333965Sjdp /* it's a ARM global constructor to be executed at program initial */ 270433965Sjdp (*mangled) += 7; 270533965Sjdp work->constructor = 2; 270633965Sjdp } 270733965Sjdp 270833965Sjdp /* This block of code is a reduction in strength time optimization 270933965Sjdp of: 271033965Sjdp scan = mystrstr (*mangled, "__"); */ 271133965Sjdp 271233965Sjdp { 271333965Sjdp scan = *mangled; 271433965Sjdp 271533965Sjdp do { 271633965Sjdp scan = strchr (scan, '_'); 271733965Sjdp } while (scan != NULL && *++scan != '_'); 271833965Sjdp 271933965Sjdp if (scan != NULL) --scan; 272033965Sjdp } 272133965Sjdp 272233965Sjdp if (scan != NULL) 272333965Sjdp { 272433965Sjdp /* We found a sequence of two or more '_', ensure that we start at 272533965Sjdp the last pair in the sequence. */ 272633965Sjdp i = strspn (scan, "_"); 272733965Sjdp if (i > 2) 272833965Sjdp { 272960484Sobrien scan += (i - 2); 273033965Sjdp } 273133965Sjdp } 273260484Sobrien 273333965Sjdp if (scan == NULL) 273433965Sjdp { 273533965Sjdp success = 0; 273633965Sjdp } 273733965Sjdp else if (work -> static_type) 273833965Sjdp { 273977298Sobrien if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) 274033965Sjdp { 274133965Sjdp success = 0; 274233965Sjdp } 274333965Sjdp } 274438889Sjdp else if ((scan == *mangled) 274577298Sobrien && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') 274660484Sobrien || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) 274733965Sjdp { 274833965Sjdp /* The ARM says nothing about the mangling of local variables. 274933965Sjdp But cfront mangles local variables by prepending __<nesting_level> 275033965Sjdp to them. As an extension to ARM demangling we handle this case. */ 275160484Sobrien if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) 275277298Sobrien && ISDIGIT ((unsigned char)scan[2])) 275333965Sjdp { 275433965Sjdp *mangled = scan + 2; 275533965Sjdp consume_count (mangled); 275633965Sjdp string_append (declp, *mangled); 275733965Sjdp *mangled += strlen (*mangled); 275860484Sobrien success = 1; 275933965Sjdp } 276033965Sjdp else 276133965Sjdp { 276233965Sjdp /* A GNU style constructor starts with __[0-9Qt]. But cfront uses 276333965Sjdp names like __Q2_3foo3bar for nested type names. So don't accept 276438889Sjdp this style of constructor for cfront demangling. A GNU 276538889Sjdp style member-template constructor starts with 'H'. */ 276660484Sobrien if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) 276733965Sjdp work -> constructor += 1; 276833965Sjdp *mangled = scan + 2; 276933965Sjdp } 277033965Sjdp } 277160484Sobrien else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') 277233965Sjdp { 277360484Sobrien /* Cfront-style parameterized type. Handled later as a signature. */ 277460484Sobrien success = 1; 277560484Sobrien 277660484Sobrien /* ARM template? */ 277760484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 277860484Sobrien } 277960484Sobrien else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') 278060484Sobrien || (scan[2] == 'p' && scan[3] == 's') 278160484Sobrien || (scan[2] == 'p' && scan[3] == 't'))) 278260484Sobrien { 278360484Sobrien /* EDG-style parameterized type. Handled later as a signature. */ 278460484Sobrien success = 1; 278560484Sobrien 278660484Sobrien /* EDG template? */ 278760484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 278860484Sobrien } 278977298Sobrien else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) 279060484Sobrien && (scan[2] != 't')) 279160484Sobrien { 279233965Sjdp /* Mangled name starts with "__". Skip over any leading '_' characters, 279333965Sjdp then find the next "__" that separates the prefix from the signature. 279433965Sjdp */ 279560484Sobrien if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 279660484Sobrien || (arm_special (mangled, declp) == 0)) 279733965Sjdp { 279833965Sjdp while (*scan == '_') 279933965Sjdp { 280033965Sjdp scan++; 280133965Sjdp } 280233965Sjdp if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) 280333965Sjdp { 280433965Sjdp /* No separator (I.E. "__not_mangled"), or empty signature 280533965Sjdp (I.E. "__not_mangled_either__") */ 280633965Sjdp success = 0; 280733965Sjdp } 280833965Sjdp else 280968765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 281033965Sjdp } 281133965Sjdp } 281233965Sjdp else if (*(scan + 2) != '\0') 281333965Sjdp { 281433965Sjdp /* Mangled name does not start with "__" but does have one somewhere 281533965Sjdp in there with non empty stuff after it. Looks like a global 281668765Sobrien function name. Iterate over all "__":s until the right 281768765Sobrien one is found. */ 281868765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 281933965Sjdp } 282033965Sjdp else 282133965Sjdp { 282233965Sjdp /* Doesn't look like a mangled name */ 282333965Sjdp success = 0; 282433965Sjdp } 282533965Sjdp 282633965Sjdp if (!success && (work->constructor == 2 || work->destructor == 2)) 282733965Sjdp { 282833965Sjdp string_append (declp, *mangled); 282933965Sjdp *mangled += strlen (*mangled); 283033965Sjdp success = 1; 283160484Sobrien } 283233965Sjdp return (success); 283333965Sjdp} 283433965Sjdp 283533965Sjdp/* 283633965Sjdp 283733965SjdpLOCAL FUNCTION 283833965Sjdp 283933965Sjdp gnu_special -- special handling of gnu mangled strings 284033965Sjdp 284133965SjdpSYNOPSIS 284233965Sjdp 284333965Sjdp static int 284433965Sjdp gnu_special (struct work_stuff *work, const char **mangled, 284533965Sjdp string *declp); 284633965Sjdp 284733965Sjdp 284833965SjdpDESCRIPTION 284933965Sjdp 285033965Sjdp Process some special GNU style mangling forms that don't fit 285133965Sjdp the normal pattern. For example: 285233965Sjdp 285333965Sjdp _$_3foo (destructor for class foo) 285433965Sjdp _vt$foo (foo virtual table) 285533965Sjdp _vt$foo$bar (foo::bar virtual table) 285633965Sjdp __vt_foo (foo virtual table, new style with thunks) 285733965Sjdp _3foo$varname (static data member) 285833965Sjdp _Q22rs2tu$vw (static data member) 285933965Sjdp __t6vector1Zii (constructor with template) 286033965Sjdp __thunk_4__$_7ostream (virtual function thunk) 286133965Sjdp */ 286233965Sjdp 286333965Sjdpstatic int 286433965Sjdpgnu_special (work, mangled, declp) 286533965Sjdp struct work_stuff *work; 286633965Sjdp const char **mangled; 286733965Sjdp string *declp; 286833965Sjdp{ 286933965Sjdp int n; 287033965Sjdp int success = 1; 287133965Sjdp const char *p; 287233965Sjdp 287333965Sjdp if ((*mangled)[0] == '_' 287433965Sjdp && strchr (cplus_markers, (*mangled)[1]) != NULL 287533965Sjdp && (*mangled)[2] == '_') 287633965Sjdp { 287733965Sjdp /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ 287833965Sjdp (*mangled) += 3; 287933965Sjdp work -> destructor += 1; 288033965Sjdp } 288133965Sjdp else if ((*mangled)[0] == '_' 288233965Sjdp && (((*mangled)[1] == '_' 288333965Sjdp && (*mangled)[2] == 'v' 288433965Sjdp && (*mangled)[3] == 't' 288533965Sjdp && (*mangled)[4] == '_') 288633965Sjdp || ((*mangled)[1] == 'v' 288733965Sjdp && (*mangled)[2] == 't' 288833965Sjdp && strchr (cplus_markers, (*mangled)[3]) != NULL))) 288933965Sjdp { 289033965Sjdp /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" 289133965Sjdp and create the decl. Note that we consume the entire mangled 289233965Sjdp input string, which means that demangle_signature has no work 289333965Sjdp to do. */ 289433965Sjdp if ((*mangled)[2] == 'v') 289533965Sjdp (*mangled) += 5; /* New style, with thunks: "__vt_" */ 289633965Sjdp else 289733965Sjdp (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */ 289833965Sjdp while (**mangled != '\0') 289933965Sjdp { 290033965Sjdp switch (**mangled) 290133965Sjdp { 290233965Sjdp case 'Q': 290360484Sobrien case 'K': 290433965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 290533965Sjdp break; 290633965Sjdp case 't': 290760484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 290860484Sobrien 1); 290933965Sjdp break; 291033965Sjdp default: 291177298Sobrien if (ISDIGIT((unsigned char)*mangled[0])) 291233965Sjdp { 291333965Sjdp n = consume_count(mangled); 291438889Sjdp /* We may be seeing a too-large size, or else a 291538889Sjdp ".<digits>" indicating a static local symbol. In 291638889Sjdp any case, declare victory and move on; *don't* try 291738889Sjdp to use n to allocate. */ 291860484Sobrien if (n > (int) strlen (*mangled)) 291938889Sjdp { 292038889Sjdp success = 1; 292138889Sjdp break; 292238889Sjdp } 292333965Sjdp } 292433965Sjdp else 292533965Sjdp { 292633965Sjdp n = strcspn (*mangled, cplus_markers); 292733965Sjdp } 292833965Sjdp string_appendn (declp, *mangled, n); 292933965Sjdp (*mangled) += n; 293033965Sjdp } 293133965Sjdp 293260484Sobrien p = strpbrk (*mangled, cplus_markers); 293333965Sjdp if (success && ((p == NULL) || (p == *mangled))) 293433965Sjdp { 293533965Sjdp if (p != NULL) 293633965Sjdp { 293760484Sobrien string_append (declp, SCOPE_STRING (work)); 293833965Sjdp (*mangled)++; 293933965Sjdp } 294033965Sjdp } 294133965Sjdp else 294233965Sjdp { 294333965Sjdp success = 0; 294433965Sjdp break; 294533965Sjdp } 294633965Sjdp } 294733965Sjdp if (success) 294833965Sjdp string_append (declp, " virtual table"); 294933965Sjdp } 295033965Sjdp else if ((*mangled)[0] == '_' 295133965Sjdp && (strchr("0123456789Qt", (*mangled)[1]) != NULL) 295233965Sjdp && (p = strpbrk (*mangled, cplus_markers)) != NULL) 295333965Sjdp { 295433965Sjdp /* static data member, "_3foo$varname" for example */ 295533965Sjdp (*mangled)++; 295633965Sjdp switch (**mangled) 295733965Sjdp { 295833965Sjdp case 'Q': 295960484Sobrien case 'K': 296033965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 296133965Sjdp break; 296233965Sjdp case 't': 296360484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 296433965Sjdp break; 296533965Sjdp default: 296633965Sjdp n = consume_count (mangled); 296760484Sobrien if (n < 0 || n > (long) strlen (*mangled)) 296860484Sobrien { 296960484Sobrien success = 0; 297060484Sobrien break; 297160484Sobrien } 297268765Sobrien 297368765Sobrien if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 297468765Sobrien && (*mangled)[9] == 'N' 297568765Sobrien && (*mangled)[8] == (*mangled)[10] 297668765Sobrien && strchr (cplus_markers, (*mangled)[8])) 297768765Sobrien { 297868765Sobrien /* A member of the anonymous namespace. There's information 297968765Sobrien about what identifier or filename it was keyed to, but 298068765Sobrien it's just there to make the mangled name unique; we just 298168765Sobrien step over it. */ 298268765Sobrien string_append (declp, "{anonymous}"); 298368765Sobrien (*mangled) += n; 298468765Sobrien 298568765Sobrien /* Now p points to the marker before the N, so we need to 298668765Sobrien update it to the first marker after what we consumed. */ 298768765Sobrien p = strpbrk (*mangled, cplus_markers); 298868765Sobrien break; 298968765Sobrien } 299068765Sobrien 299133965Sjdp string_appendn (declp, *mangled, n); 299233965Sjdp (*mangled) += n; 299333965Sjdp } 299433965Sjdp if (success && (p == *mangled)) 299533965Sjdp { 299633965Sjdp /* Consumed everything up to the cplus_marker, append the 299733965Sjdp variable name. */ 299833965Sjdp (*mangled)++; 299960484Sobrien string_append (declp, SCOPE_STRING (work)); 300033965Sjdp n = strlen (*mangled); 300133965Sjdp string_appendn (declp, *mangled, n); 300233965Sjdp (*mangled) += n; 300333965Sjdp } 300433965Sjdp else 300533965Sjdp { 300633965Sjdp success = 0; 300733965Sjdp } 300833965Sjdp } 300933965Sjdp else if (strncmp (*mangled, "__thunk_", 8) == 0) 301033965Sjdp { 301160484Sobrien int delta; 301260484Sobrien 301360484Sobrien (*mangled) += 8; 301460484Sobrien delta = consume_count (mangled); 301560484Sobrien if (delta == -1) 301660484Sobrien success = 0; 301733965Sjdp else 301833965Sjdp { 301960484Sobrien char *method = internal_cplus_demangle (work, ++*mangled); 302060484Sobrien 302160484Sobrien if (method) 302260484Sobrien { 302360484Sobrien char buf[50]; 302460484Sobrien sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); 302560484Sobrien string_append (declp, buf); 302660484Sobrien string_append (declp, method); 302760484Sobrien free (method); 302860484Sobrien n = strlen (*mangled); 302960484Sobrien (*mangled) += n; 303060484Sobrien } 303160484Sobrien else 303260484Sobrien { 303360484Sobrien success = 0; 303460484Sobrien } 303533965Sjdp } 303633965Sjdp } 303733965Sjdp else if (strncmp (*mangled, "__t", 3) == 0 303833965Sjdp && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) 303933965Sjdp { 304033965Sjdp p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; 304133965Sjdp (*mangled) += 4; 304233965Sjdp switch (**mangled) 304333965Sjdp { 304433965Sjdp case 'Q': 304560484Sobrien case 'K': 304633965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 304733965Sjdp break; 304833965Sjdp case 't': 304960484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 305033965Sjdp break; 305133965Sjdp default: 305268765Sobrien success = do_type (work, mangled, declp); 305333965Sjdp break; 305433965Sjdp } 305533965Sjdp if (success && **mangled != '\0') 305633965Sjdp success = 0; 305733965Sjdp if (success) 305833965Sjdp string_append (declp, p); 305933965Sjdp } 306033965Sjdp else 306133965Sjdp { 306233965Sjdp success = 0; 306333965Sjdp } 306433965Sjdp return (success); 306533965Sjdp} 306633965Sjdp 306760484Sobrienstatic void 306860484Sobrienrecursively_demangle(work, mangled, result, namelength) 306960484Sobrien struct work_stuff *work; 307060484Sobrien const char **mangled; 307160484Sobrien string *result; 307260484Sobrien int namelength; 307360484Sobrien{ 307460484Sobrien char * recurse = (char *)NULL; 307560484Sobrien char * recurse_dem = (char *)NULL; 307660484Sobrien 307760484Sobrien recurse = (char *) xmalloc (namelength + 1); 307860484Sobrien memcpy (recurse, *mangled, namelength); 307960484Sobrien recurse[namelength] = '\000'; 308060484Sobrien 308160484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 308260484Sobrien 308360484Sobrien if (recurse_dem) 308460484Sobrien { 308560484Sobrien string_append (result, recurse_dem); 308660484Sobrien free (recurse_dem); 308760484Sobrien } 308860484Sobrien else 308960484Sobrien { 309060484Sobrien string_appendn (result, *mangled, namelength); 309160484Sobrien } 309260484Sobrien free (recurse); 309360484Sobrien *mangled += namelength; 309460484Sobrien} 309560484Sobrien 309633965Sjdp/* 309733965Sjdp 309833965SjdpLOCAL FUNCTION 309933965Sjdp 310033965Sjdp arm_special -- special handling of ARM/lucid mangled strings 310133965Sjdp 310233965SjdpSYNOPSIS 310333965Sjdp 310433965Sjdp static int 310560484Sobrien arm_special (const char **mangled, 310660484Sobrien string *declp); 310733965Sjdp 310833965Sjdp 310933965SjdpDESCRIPTION 311033965Sjdp 311133965Sjdp Process some special ARM style mangling forms that don't fit 311233965Sjdp the normal pattern. For example: 311333965Sjdp 311433965Sjdp __vtbl__3foo (foo virtual table) 311533965Sjdp __vtbl__3foo__3bar (bar::foo virtual table) 311633965Sjdp 311733965Sjdp */ 311833965Sjdp 311933965Sjdpstatic int 312060484Sobrienarm_special (mangled, declp) 312133965Sjdp const char **mangled; 312233965Sjdp string *declp; 312333965Sjdp{ 312433965Sjdp int n; 312533965Sjdp int success = 1; 312633965Sjdp const char *scan; 312733965Sjdp 312833965Sjdp if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) 312933965Sjdp { 313033965Sjdp /* Found a ARM style virtual table, get past ARM_VTABLE_STRING 313133965Sjdp and create the decl. Note that we consume the entire mangled 313233965Sjdp input string, which means that demangle_signature has no work 313333965Sjdp to do. */ 313433965Sjdp scan = *mangled + ARM_VTABLE_STRLEN; 313533965Sjdp while (*scan != '\0') /* first check it can be demangled */ 313633965Sjdp { 313733965Sjdp n = consume_count (&scan); 313860484Sobrien if (n == -1) 313933965Sjdp { 314033965Sjdp return (0); /* no good */ 314133965Sjdp } 314233965Sjdp scan += n; 314333965Sjdp if (scan[0] == '_' && scan[1] == '_') 314433965Sjdp { 314533965Sjdp scan += 2; 314633965Sjdp } 314733965Sjdp } 314833965Sjdp (*mangled) += ARM_VTABLE_STRLEN; 314933965Sjdp while (**mangled != '\0') 315033965Sjdp { 315133965Sjdp n = consume_count (mangled); 315260484Sobrien if (n == -1 315360484Sobrien || n > (long) strlen (*mangled)) 315460484Sobrien return 0; 315533965Sjdp string_prependn (declp, *mangled, n); 315633965Sjdp (*mangled) += n; 315733965Sjdp if ((*mangled)[0] == '_' && (*mangled)[1] == '_') 315833965Sjdp { 315933965Sjdp string_prepend (declp, "::"); 316033965Sjdp (*mangled) += 2; 316133965Sjdp } 316233965Sjdp } 316333965Sjdp string_append (declp, " virtual table"); 316433965Sjdp } 316533965Sjdp else 316633965Sjdp { 316733965Sjdp success = 0; 316833965Sjdp } 316933965Sjdp return (success); 317033965Sjdp} 317133965Sjdp 317233965Sjdp/* 317333965Sjdp 317433965SjdpLOCAL FUNCTION 317533965Sjdp 317633965Sjdp demangle_qualified -- demangle 'Q' qualified name strings 317733965Sjdp 317833965SjdpSYNOPSIS 317933965Sjdp 318033965Sjdp static int 318133965Sjdp demangle_qualified (struct work_stuff *, const char *mangled, 318233965Sjdp string *result, int isfuncname, int append); 318333965Sjdp 318433965SjdpDESCRIPTION 318533965Sjdp 318633965Sjdp Demangle a qualified name, such as "Q25Outer5Inner" which is 318733965Sjdp the mangled form of "Outer::Inner". The demangled output is 318833965Sjdp prepended or appended to the result string according to the 318933965Sjdp state of the append flag. 319033965Sjdp 319133965Sjdp If isfuncname is nonzero, then the qualified name we are building 319233965Sjdp is going to be used as a member function name, so if it is a 319333965Sjdp constructor or destructor function, append an appropriate 319433965Sjdp constructor or destructor name. I.E. for the above example, 319533965Sjdp the result for use as a constructor is "Outer::Inner::Inner" 319633965Sjdp and the result for use as a destructor is "Outer::Inner::~Inner". 319733965Sjdp 319833965SjdpBUGS 319933965Sjdp 320033965Sjdp Numeric conversion is ASCII dependent (FIXME). 320133965Sjdp 320233965Sjdp */ 320333965Sjdp 320433965Sjdpstatic int 320533965Sjdpdemangle_qualified (work, mangled, result, isfuncname, append) 320633965Sjdp struct work_stuff *work; 320733965Sjdp const char **mangled; 320833965Sjdp string *result; 320933965Sjdp int isfuncname; 321033965Sjdp int append; 321133965Sjdp{ 321260484Sobrien int qualifiers = 0; 321333965Sjdp int success = 1; 321433965Sjdp char num[2]; 321533965Sjdp string temp; 321660484Sobrien string last_name; 321760484Sobrien int bindex = register_Btype (work); 321833965Sjdp 321960484Sobrien /* We only make use of ISFUNCNAME if the entity is a constructor or 322060484Sobrien destructor. */ 322160484Sobrien isfuncname = (isfuncname 322260484Sobrien && ((work->constructor & 1) || (work->destructor & 1))); 322360484Sobrien 322433965Sjdp string_init (&temp); 322560484Sobrien string_init (&last_name); 322660484Sobrien 322760484Sobrien if ((*mangled)[0] == 'K') 322833965Sjdp { 322960484Sobrien /* Squangling qualified name reuse */ 323060484Sobrien int idx; 323160484Sobrien (*mangled)++; 323260484Sobrien idx = consume_count_with_underscores (mangled); 323360484Sobrien if (idx == -1 || idx >= work -> numk) 323460484Sobrien success = 0; 323560484Sobrien else 323660484Sobrien string_append (&temp, work -> ktypevec[idx]); 323760484Sobrien } 323860484Sobrien else 323960484Sobrien switch ((*mangled)[1]) 324060484Sobrien { 324133965Sjdp case '_': 324233965Sjdp /* GNU mangled name with more than 9 classes. The count is preceded 324333965Sjdp by an underscore (to distinguish it from the <= 9 case) and followed 324433965Sjdp by an underscore. */ 324560484Sobrien (*mangled)++; 324660484Sobrien qualifiers = consume_count_with_underscores (mangled); 324760484Sobrien if (qualifiers == -1) 324833965Sjdp success = 0; 324933965Sjdp break; 325033965Sjdp 325133965Sjdp case '1': 325233965Sjdp case '2': 325333965Sjdp case '3': 325433965Sjdp case '4': 325533965Sjdp case '5': 325633965Sjdp case '6': 325733965Sjdp case '7': 325833965Sjdp case '8': 325933965Sjdp case '9': 326033965Sjdp /* The count is in a single digit. */ 326133965Sjdp num[0] = (*mangled)[1]; 326233965Sjdp num[1] = '\0'; 326333965Sjdp qualifiers = atoi (num); 326433965Sjdp 326533965Sjdp /* If there is an underscore after the digit, skip it. This is 326633965Sjdp said to be for ARM-qualified names, but the ARM makes no 326733965Sjdp mention of such an underscore. Perhaps cfront uses one. */ 326833965Sjdp if ((*mangled)[2] == '_') 326933965Sjdp { 327033965Sjdp (*mangled)++; 327133965Sjdp } 327233965Sjdp (*mangled) += 2; 327333965Sjdp break; 327433965Sjdp 327533965Sjdp case '0': 327633965Sjdp default: 327733965Sjdp success = 0; 327833965Sjdp } 327933965Sjdp 328033965Sjdp if (!success) 328133965Sjdp return success; 328233965Sjdp 328333965Sjdp /* Pick off the names and collect them in the temp buffer in the order 328433965Sjdp in which they are found, separated by '::'. */ 328533965Sjdp 328633965Sjdp while (qualifiers-- > 0) 328733965Sjdp { 328860484Sobrien int remember_K = 1; 328960484Sobrien string_clear (&last_name); 329060484Sobrien 329160484Sobrien if (*mangled[0] == '_') 329260484Sobrien (*mangled)++; 329360484Sobrien 329433965Sjdp if (*mangled[0] == 't') 329533965Sjdp { 329660484Sobrien /* Here we always append to TEMP since we will want to use 329760484Sobrien the template name without the template parameters as a 329860484Sobrien constructor or destructor name. The appropriate 329960484Sobrien (parameter-less) value is returned by demangle_template 330060484Sobrien in LAST_NAME. We do not remember the template type here, 330160484Sobrien in order to match the G++ mangling algorithm. */ 330260484Sobrien success = demangle_template(work, mangled, &temp, 330360484Sobrien &last_name, 1, 0); 330460484Sobrien if (!success) 330560484Sobrien break; 330633965Sjdp } 330760484Sobrien else if (*mangled[0] == 'K') 330838889Sjdp { 330960484Sobrien int idx; 331060484Sobrien (*mangled)++; 331160484Sobrien idx = consume_count_with_underscores (mangled); 331260484Sobrien if (idx == -1 || idx >= work->numk) 331360484Sobrien success = 0; 331460484Sobrien else 331560484Sobrien string_append (&temp, work->ktypevec[idx]); 331660484Sobrien remember_K = 0; 331760484Sobrien 331838889Sjdp if (!success) break; 331938889Sjdp } 332033965Sjdp else 332160484Sobrien { 332260484Sobrien if (EDG_DEMANGLING) 332360484Sobrien { 332460484Sobrien int namelength; 332560484Sobrien /* Now recursively demangle the qualifier 332660484Sobrien * This is necessary to deal with templates in 332760484Sobrien * mangling styles like EDG */ 332860484Sobrien namelength = consume_count (mangled); 332960484Sobrien if (namelength == -1) 333060484Sobrien { 333160484Sobrien success = 0; 333260484Sobrien break; 333360484Sobrien } 333460484Sobrien recursively_demangle(work, mangled, &temp, namelength); 333560484Sobrien } 333660484Sobrien else 333760484Sobrien { 333860484Sobrien success = do_type (work, mangled, &last_name); 333960484Sobrien if (!success) 334060484Sobrien break; 334160484Sobrien string_appends (&temp, &last_name); 334260484Sobrien } 334333965Sjdp } 334460484Sobrien 334560484Sobrien if (remember_K) 334660484Sobrien remember_Ktype (work, temp.b, LEN_STRING (&temp)); 334760484Sobrien 334833965Sjdp if (qualifiers > 0) 334960484Sobrien string_append (&temp, SCOPE_STRING (work)); 335033965Sjdp } 335133965Sjdp 335260484Sobrien remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); 335360484Sobrien 335433965Sjdp /* If we are using the result as a function name, we need to append 335533965Sjdp the appropriate '::' separated constructor or destructor name. 335633965Sjdp We do this here because this is the most convenient place, where 335733965Sjdp we already have a pointer to the name and the length of the name. */ 335833965Sjdp 335960484Sobrien if (isfuncname) 336033965Sjdp { 336160484Sobrien string_append (&temp, SCOPE_STRING (work)); 336233965Sjdp if (work -> destructor & 1) 336360484Sobrien string_append (&temp, "~"); 336460484Sobrien string_appends (&temp, &last_name); 336533965Sjdp } 336633965Sjdp 336760484Sobrien /* Now either prepend the temp buffer to the result, or append it, 336833965Sjdp depending upon the state of the append flag. */ 336933965Sjdp 337033965Sjdp if (append) 337160484Sobrien string_appends (result, &temp); 337233965Sjdp else 337333965Sjdp { 337433965Sjdp if (!STRING_EMPTY (result)) 337560484Sobrien string_append (&temp, SCOPE_STRING (work)); 337633965Sjdp string_prepends (result, &temp); 337733965Sjdp } 337833965Sjdp 337960484Sobrien string_delete (&last_name); 338033965Sjdp string_delete (&temp); 338133965Sjdp return (success); 338233965Sjdp} 338333965Sjdp 338433965Sjdp/* 338533965Sjdp 338633965SjdpLOCAL FUNCTION 338733965Sjdp 338833965Sjdp get_count -- convert an ascii count to integer, consuming tokens 338933965Sjdp 339033965SjdpSYNOPSIS 339133965Sjdp 339233965Sjdp static int 339333965Sjdp get_count (const char **type, int *count) 339433965Sjdp 339533965SjdpDESCRIPTION 339633965Sjdp 339760484Sobrien Assume that *type points at a count in a mangled name; set 339860484Sobrien *count to its value, and set *type to the next character after 339960484Sobrien the count. There are some weird rules in effect here. 340060484Sobrien 340160484Sobrien If *type does not point at a string of digits, return zero. 340260484Sobrien 340360484Sobrien If *type points at a string of digits followed by an 340460484Sobrien underscore, set *count to their value as an integer, advance 340560484Sobrien *type to point *after the underscore, and return 1. 340660484Sobrien 340760484Sobrien If *type points at a string of digits not followed by an 340860484Sobrien underscore, consume only the first digit. Set *count to its 340960484Sobrien value as an integer, leave *type pointing after that digit, 341060484Sobrien and return 1. 341160484Sobrien 341260484Sobrien The excuse for this odd behavior: in the ARM and HP demangling 341360484Sobrien styles, a type can be followed by a repeat count of the form 341460484Sobrien `Nxy', where: 341560484Sobrien 341660484Sobrien `x' is a single digit specifying how many additional copies 341760484Sobrien of the type to append to the argument list, and 341860484Sobrien 341960484Sobrien `y' is one or more digits, specifying the zero-based index of 342060484Sobrien the first repeated argument in the list. Yes, as you're 342160484Sobrien unmangling the name you can figure this out yourself, but 342260484Sobrien it's there anyway. 342360484Sobrien 342460484Sobrien So, for example, in `bar__3fooFPiN51', the first argument is a 342560484Sobrien pointer to an integer (`Pi'), and then the next five arguments 342660484Sobrien are the same (`N5'), and the first repeat is the function's 342760484Sobrien second argument (`1'). 342833965Sjdp*/ 342933965Sjdp 343033965Sjdpstatic int 343133965Sjdpget_count (type, count) 343233965Sjdp const char **type; 343333965Sjdp int *count; 343433965Sjdp{ 343533965Sjdp const char *p; 343633965Sjdp int n; 343733965Sjdp 343877298Sobrien if (!ISDIGIT ((unsigned char)**type)) 343960484Sobrien return (0); 344033965Sjdp else 344133965Sjdp { 344233965Sjdp *count = **type - '0'; 344333965Sjdp (*type)++; 344477298Sobrien if (ISDIGIT ((unsigned char)**type)) 344533965Sjdp { 344633965Sjdp p = *type; 344733965Sjdp n = *count; 344860484Sobrien do 344933965Sjdp { 345033965Sjdp n *= 10; 345133965Sjdp n += *p - '0'; 345233965Sjdp p++; 345360484Sobrien } 345477298Sobrien while (ISDIGIT ((unsigned char)*p)); 345533965Sjdp if (*p == '_') 345633965Sjdp { 345733965Sjdp *type = p + 1; 345833965Sjdp *count = n; 345933965Sjdp } 346033965Sjdp } 346133965Sjdp } 346233965Sjdp return (1); 346333965Sjdp} 346433965Sjdp 346560484Sobrien/* RESULT will be initialised here; it will be freed on failure. The 346660484Sobrien value returned is really a type_kind_t. */ 346733965Sjdp 346833965Sjdpstatic int 346933965Sjdpdo_type (work, mangled, result) 347033965Sjdp struct work_stuff *work; 347133965Sjdp const char **mangled; 347233965Sjdp string *result; 347333965Sjdp{ 347433965Sjdp int n; 347533965Sjdp int done; 347633965Sjdp int success; 347733965Sjdp string decl; 347833965Sjdp const char *remembered_type; 347960484Sobrien int type_quals; 348060484Sobrien string btype; 348160484Sobrien type_kind_t tk = tk_none; 348233965Sjdp 348360484Sobrien string_init (&btype); 348433965Sjdp string_init (&decl); 348533965Sjdp string_init (result); 348633965Sjdp 348733965Sjdp done = 0; 348833965Sjdp success = 1; 348933965Sjdp while (success && !done) 349033965Sjdp { 349133965Sjdp int member; 349233965Sjdp switch (**mangled) 349333965Sjdp { 349433965Sjdp 349533965Sjdp /* A pointer type */ 349633965Sjdp case 'P': 349733965Sjdp case 'p': 349833965Sjdp (*mangled)++; 349938889Sjdp if (! (work -> options & DMGL_JAVA)) 350038889Sjdp string_prepend (&decl, "*"); 350160484Sobrien if (tk == tk_none) 350260484Sobrien tk = tk_pointer; 350333965Sjdp break; 350433965Sjdp 350533965Sjdp /* A reference type */ 350633965Sjdp case 'R': 350733965Sjdp (*mangled)++; 350833965Sjdp string_prepend (&decl, "&"); 350960484Sobrien if (tk == tk_none) 351060484Sobrien tk = tk_reference; 351133965Sjdp break; 351233965Sjdp 351333965Sjdp /* An array */ 351433965Sjdp case 'A': 351533965Sjdp { 351660484Sobrien ++(*mangled); 351760484Sobrien if (!STRING_EMPTY (&decl) 351860484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 351933965Sjdp { 352060484Sobrien string_prepend (&decl, "("); 352160484Sobrien string_append (&decl, ")"); 352233965Sjdp } 352360484Sobrien string_append (&decl, "["); 352460484Sobrien if (**mangled != '_') 352560484Sobrien success = demangle_template_value_parm (work, mangled, &decl, 352660484Sobrien tk_integral); 352760484Sobrien if (**mangled == '_') 352860484Sobrien ++(*mangled); 352960484Sobrien string_append (&decl, "]"); 353033965Sjdp break; 353133965Sjdp } 353233965Sjdp 353333965Sjdp /* A back reference to a previously seen type */ 353433965Sjdp case 'T': 353533965Sjdp (*mangled)++; 353633965Sjdp if (!get_count (mangled, &n) || n >= work -> ntypes) 353733965Sjdp { 353833965Sjdp success = 0; 353933965Sjdp } 354033965Sjdp else 354133965Sjdp { 354233965Sjdp remembered_type = work -> typevec[n]; 354333965Sjdp mangled = &remembered_type; 354433965Sjdp } 354533965Sjdp break; 354633965Sjdp 354733965Sjdp /* A function */ 354833965Sjdp case 'F': 354933965Sjdp (*mangled)++; 355060484Sobrien if (!STRING_EMPTY (&decl) 355160484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 355233965Sjdp { 355333965Sjdp string_prepend (&decl, "("); 355433965Sjdp string_append (&decl, ")"); 355533965Sjdp } 355633965Sjdp /* After picking off the function args, we expect to either find the 355733965Sjdp function return type (preceded by an '_') or the end of the 355833965Sjdp string. */ 355960484Sobrien if (!demangle_nested_args (work, mangled, &decl) 356033965Sjdp || (**mangled != '_' && **mangled != '\0')) 356133965Sjdp { 356233965Sjdp success = 0; 356360484Sobrien break; 356433965Sjdp } 356533965Sjdp if (success && (**mangled == '_')) 356660484Sobrien (*mangled)++; 356733965Sjdp break; 356833965Sjdp 356933965Sjdp case 'M': 357033965Sjdp case 'O': 357133965Sjdp { 357260484Sobrien type_quals = TYPE_UNQUALIFIED; 357333965Sjdp 357433965Sjdp member = **mangled == 'M'; 357533965Sjdp (*mangled)++; 357633965Sjdp 357733965Sjdp string_append (&decl, ")"); 357860484Sobrien 357960484Sobrien /* We don't need to prepend `::' for a qualified name; 358060484Sobrien demangle_qualified will do that for us. */ 358160484Sobrien if (**mangled != 'Q') 358260484Sobrien string_prepend (&decl, SCOPE_STRING (work)); 358360484Sobrien 358477298Sobrien if (ISDIGIT ((unsigned char)**mangled)) 358533965Sjdp { 358633965Sjdp n = consume_count (mangled); 358760484Sobrien if (n == -1 358860484Sobrien || (int) strlen (*mangled) < n) 358933965Sjdp { 359033965Sjdp success = 0; 359133965Sjdp break; 359233965Sjdp } 359333965Sjdp string_prependn (&decl, *mangled, n); 359433965Sjdp *mangled += n; 359533965Sjdp } 359660484Sobrien else if (**mangled == 'X' || **mangled == 'Y') 359733965Sjdp { 359833965Sjdp string temp; 359960484Sobrien do_type (work, mangled, &temp); 360060484Sobrien string_prepends (&decl, &temp); 360160484Sobrien } 360260484Sobrien else if (**mangled == 't') 360360484Sobrien { 360460484Sobrien string temp; 360533965Sjdp string_init (&temp); 360660484Sobrien success = demangle_template (work, mangled, &temp, 360760484Sobrien NULL, 1, 1); 360833965Sjdp if (success) 360933965Sjdp { 361033965Sjdp string_prependn (&decl, temp.b, temp.p - temp.b); 361133965Sjdp string_clear (&temp); 361233965Sjdp } 361333965Sjdp else 361433965Sjdp break; 361533965Sjdp } 361660484Sobrien else if (**mangled == 'Q') 361760484Sobrien { 361860484Sobrien success = demangle_qualified (work, mangled, &decl, 361960484Sobrien /*isfuncnam=*/0, 362060484Sobrien /*append=*/0); 362160484Sobrien if (!success) 362260484Sobrien break; 362360484Sobrien } 362460484Sobrien else 362560484Sobrien { 362660484Sobrien success = 0; 362760484Sobrien break; 362860484Sobrien } 362960484Sobrien 363033965Sjdp string_prepend (&decl, "("); 363133965Sjdp if (member) 363233965Sjdp { 363360484Sobrien switch (**mangled) 363433965Sjdp { 363560484Sobrien case 'C': 363660484Sobrien case 'V': 363760484Sobrien case 'u': 363860484Sobrien type_quals |= code_for_qualifier (**mangled); 363933965Sjdp (*mangled)++; 364060484Sobrien break; 364160484Sobrien 364260484Sobrien default: 364360484Sobrien break; 364433965Sjdp } 364560484Sobrien 364633965Sjdp if (*(*mangled)++ != 'F') 364733965Sjdp { 364833965Sjdp success = 0; 364933965Sjdp break; 365033965Sjdp } 365133965Sjdp } 365260484Sobrien if ((member && !demangle_nested_args (work, mangled, &decl)) 365333965Sjdp || **mangled != '_') 365433965Sjdp { 365533965Sjdp success = 0; 365633965Sjdp break; 365733965Sjdp } 365833965Sjdp (*mangled)++; 365933965Sjdp if (! PRINT_ANSI_QUALIFIERS) 366033965Sjdp { 366133965Sjdp break; 366233965Sjdp } 366360484Sobrien if (type_quals != TYPE_UNQUALIFIED) 366433965Sjdp { 366533965Sjdp APPEND_BLANK (&decl); 366660484Sobrien string_append (&decl, qualifier_string (type_quals)); 366733965Sjdp } 366833965Sjdp break; 366933965Sjdp } 367033965Sjdp case 'G': 367133965Sjdp (*mangled)++; 367233965Sjdp break; 367333965Sjdp 367433965Sjdp case 'C': 367560484Sobrien case 'V': 367660484Sobrien case 'u': 367733965Sjdp if (PRINT_ANSI_QUALIFIERS) 367833965Sjdp { 367933965Sjdp if (!STRING_EMPTY (&decl)) 368060484Sobrien string_prepend (&decl, " "); 368160484Sobrien 368260484Sobrien string_prepend (&decl, demangle_qualifier (**mangled)); 368333965Sjdp } 368460484Sobrien (*mangled)++; 368533965Sjdp break; 368633965Sjdp /* 368733965Sjdp } 368833965Sjdp */ 368933965Sjdp 369033965Sjdp /* fall through */ 369133965Sjdp default: 369233965Sjdp done = 1; 369333965Sjdp break; 369433965Sjdp } 369533965Sjdp } 369633965Sjdp 369760484Sobrien if (success) switch (**mangled) 369833965Sjdp { 369933965Sjdp /* A qualified name, such as "Outer::Inner". */ 370033965Sjdp case 'Q': 370160484Sobrien case 'K': 370260484Sobrien { 370360484Sobrien success = demangle_qualified (work, mangled, result, 0, 1); 370460484Sobrien break; 370560484Sobrien } 370660484Sobrien 370760484Sobrien /* A back reference to a previously seen squangled type */ 370860484Sobrien case 'B': 370960484Sobrien (*mangled)++; 371060484Sobrien if (!get_count (mangled, &n) || n >= work -> numb) 371160484Sobrien success = 0; 371260484Sobrien else 371360484Sobrien string_append (result, work->btypevec[n]); 371433965Sjdp break; 371533965Sjdp 371638889Sjdp case 'X': 371738889Sjdp case 'Y': 371838889Sjdp /* A template parm. We substitute the corresponding argument. */ 371938889Sjdp { 372038889Sjdp int idx; 372138889Sjdp 372238889Sjdp (*mangled)++; 372338889Sjdp idx = consume_count_with_underscores (mangled); 372438889Sjdp 372560484Sobrien if (idx == -1 372638889Sjdp || (work->tmpl_argvec && idx >= work->ntmpl_args) 372738889Sjdp || consume_count_with_underscores (mangled) == -1) 372838889Sjdp { 372938889Sjdp success = 0; 373038889Sjdp break; 373138889Sjdp } 373238889Sjdp 373338889Sjdp if (work->tmpl_argvec) 373438889Sjdp string_append (result, work->tmpl_argvec[idx]); 373538889Sjdp else 373660484Sobrien string_append_template_idx (result, idx); 373738889Sjdp 373838889Sjdp success = 1; 373938889Sjdp } 374038889Sjdp break; 374138889Sjdp 374233965Sjdp default: 374333965Sjdp success = demangle_fund_type (work, mangled, result); 374460484Sobrien if (tk == tk_none) 374560484Sobrien tk = (type_kind_t) success; 374633965Sjdp break; 374733965Sjdp } 374833965Sjdp 374933965Sjdp if (success) 375033965Sjdp { 375133965Sjdp if (!STRING_EMPTY (&decl)) 375233965Sjdp { 375333965Sjdp string_append (result, " "); 375433965Sjdp string_appends (result, &decl); 375533965Sjdp } 375633965Sjdp } 375733965Sjdp else 375860484Sobrien string_delete (result); 375933965Sjdp string_delete (&decl); 376060484Sobrien 376160484Sobrien if (success) 376260484Sobrien /* Assume an integral type, if we're not sure. */ 376360484Sobrien return (int) ((tk == tk_none) ? tk_integral : tk); 376460484Sobrien else 376560484Sobrien return 0; 376633965Sjdp} 376733965Sjdp 376833965Sjdp/* Given a pointer to a type string that represents a fundamental type 376933965Sjdp argument (int, long, unsigned int, etc) in TYPE, a pointer to the 377033965Sjdp string in which the demangled output is being built in RESULT, and 377133965Sjdp the WORK structure, decode the types and add them to the result. 377233965Sjdp 377333965Sjdp For example: 377433965Sjdp 377533965Sjdp "Ci" => "const int" 377633965Sjdp "Sl" => "signed long" 377733965Sjdp "CUs" => "const unsigned short" 377833965Sjdp 377960484Sobrien The value returned is really a type_kind_t. */ 378033965Sjdp 378133965Sjdpstatic int 378233965Sjdpdemangle_fund_type (work, mangled, result) 378333965Sjdp struct work_stuff *work; 378433965Sjdp const char **mangled; 378533965Sjdp string *result; 378633965Sjdp{ 378733965Sjdp int done = 0; 378833965Sjdp int success = 1; 378960484Sobrien char buf[10]; 379068765Sobrien unsigned int dec = 0; 379160484Sobrien string btype; 379260484Sobrien type_kind_t tk = tk_integral; 379333965Sjdp 379460484Sobrien string_init (&btype); 379560484Sobrien 379633965Sjdp /* First pick off any type qualifiers. There can be more than one. */ 379733965Sjdp 379833965Sjdp while (!done) 379933965Sjdp { 380033965Sjdp switch (**mangled) 380133965Sjdp { 380233965Sjdp case 'C': 380360484Sobrien case 'V': 380460484Sobrien case 'u': 380533965Sjdp if (PRINT_ANSI_QUALIFIERS) 380633965Sjdp { 380760484Sobrien if (!STRING_EMPTY (result)) 380860484Sobrien string_prepend (result, " "); 380960484Sobrien string_prepend (result, demangle_qualifier (**mangled)); 381033965Sjdp } 381160484Sobrien (*mangled)++; 381233965Sjdp break; 381333965Sjdp case 'U': 381433965Sjdp (*mangled)++; 381533965Sjdp APPEND_BLANK (result); 381633965Sjdp string_append (result, "unsigned"); 381733965Sjdp break; 381833965Sjdp case 'S': /* signed char only */ 381933965Sjdp (*mangled)++; 382033965Sjdp APPEND_BLANK (result); 382133965Sjdp string_append (result, "signed"); 382233965Sjdp break; 382338889Sjdp case 'J': 382438889Sjdp (*mangled)++; 382538889Sjdp APPEND_BLANK (result); 382638889Sjdp string_append (result, "__complex"); 382738889Sjdp break; 382833965Sjdp default: 382933965Sjdp done = 1; 383033965Sjdp break; 383133965Sjdp } 383233965Sjdp } 383333965Sjdp 383433965Sjdp /* Now pick off the fundamental type. There can be only one. */ 383533965Sjdp 383633965Sjdp switch (**mangled) 383733965Sjdp { 383833965Sjdp case '\0': 383933965Sjdp case '_': 384033965Sjdp break; 384133965Sjdp case 'v': 384233965Sjdp (*mangled)++; 384333965Sjdp APPEND_BLANK (result); 384433965Sjdp string_append (result, "void"); 384533965Sjdp break; 384633965Sjdp case 'x': 384733965Sjdp (*mangled)++; 384833965Sjdp APPEND_BLANK (result); 384933965Sjdp string_append (result, "long long"); 385033965Sjdp break; 385133965Sjdp case 'l': 385233965Sjdp (*mangled)++; 385333965Sjdp APPEND_BLANK (result); 385433965Sjdp string_append (result, "long"); 385533965Sjdp break; 385633965Sjdp case 'i': 385733965Sjdp (*mangled)++; 385833965Sjdp APPEND_BLANK (result); 385933965Sjdp string_append (result, "int"); 386033965Sjdp break; 386133965Sjdp case 's': 386233965Sjdp (*mangled)++; 386333965Sjdp APPEND_BLANK (result); 386433965Sjdp string_append (result, "short"); 386533965Sjdp break; 386633965Sjdp case 'b': 386733965Sjdp (*mangled)++; 386833965Sjdp APPEND_BLANK (result); 386933965Sjdp string_append (result, "bool"); 387060484Sobrien tk = tk_bool; 387133965Sjdp break; 387233965Sjdp case 'c': 387333965Sjdp (*mangled)++; 387433965Sjdp APPEND_BLANK (result); 387533965Sjdp string_append (result, "char"); 387660484Sobrien tk = tk_char; 387733965Sjdp break; 387833965Sjdp case 'w': 387933965Sjdp (*mangled)++; 388033965Sjdp APPEND_BLANK (result); 388133965Sjdp string_append (result, "wchar_t"); 388260484Sobrien tk = tk_char; 388333965Sjdp break; 388433965Sjdp case 'r': 388533965Sjdp (*mangled)++; 388633965Sjdp APPEND_BLANK (result); 388733965Sjdp string_append (result, "long double"); 388860484Sobrien tk = tk_real; 388933965Sjdp break; 389033965Sjdp case 'd': 389133965Sjdp (*mangled)++; 389233965Sjdp APPEND_BLANK (result); 389333965Sjdp string_append (result, "double"); 389460484Sobrien tk = tk_real; 389533965Sjdp break; 389633965Sjdp case 'f': 389733965Sjdp (*mangled)++; 389833965Sjdp APPEND_BLANK (result); 389933965Sjdp string_append (result, "float"); 390060484Sobrien tk = tk_real; 390133965Sjdp break; 390233965Sjdp case 'G': 390333965Sjdp (*mangled)++; 390477298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 390533965Sjdp { 390633965Sjdp success = 0; 390733965Sjdp break; 390833965Sjdp } 390960484Sobrien case 'I': 391060484Sobrien (*mangled)++; 391160484Sobrien if (**mangled == '_') 391260484Sobrien { 391360484Sobrien int i; 391460484Sobrien (*mangled)++; 391560484Sobrien for (i = 0; 391660484Sobrien i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; 391760484Sobrien (*mangled)++, i++) 391860484Sobrien buf[i] = **mangled; 391960484Sobrien if (**mangled != '_') 392060484Sobrien { 392160484Sobrien success = 0; 392260484Sobrien break; 392360484Sobrien } 392460484Sobrien buf[i] = '\0'; 392560484Sobrien (*mangled)++; 392660484Sobrien } 392760484Sobrien else 392860484Sobrien { 392960484Sobrien strncpy (buf, *mangled, 2); 393060484Sobrien buf[2] = '\0'; 393160484Sobrien *mangled += min (strlen (*mangled), 2); 393260484Sobrien } 393360484Sobrien sscanf (buf, "%x", &dec); 393468765Sobrien sprintf (buf, "int%u_t", dec); 393560484Sobrien APPEND_BLANK (result); 393660484Sobrien string_append (result, buf); 393760484Sobrien break; 393860484Sobrien 393933965Sjdp /* fall through */ 394033965Sjdp /* An explicit type, such as "6mytype" or "7integer" */ 394133965Sjdp case '0': 394233965Sjdp case '1': 394333965Sjdp case '2': 394433965Sjdp case '3': 394533965Sjdp case '4': 394633965Sjdp case '5': 394733965Sjdp case '6': 394833965Sjdp case '7': 394933965Sjdp case '8': 395033965Sjdp case '9': 395160484Sobrien { 395260484Sobrien int bindex = register_Btype (work); 395360484Sobrien string btype; 395460484Sobrien string_init (&btype); 395560484Sobrien if (demangle_class_name (work, mangled, &btype)) { 395660484Sobrien remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); 395760484Sobrien APPEND_BLANK (result); 395860484Sobrien string_appends (result, &btype); 395960484Sobrien } 396060484Sobrien else 396160484Sobrien success = 0; 396260484Sobrien string_delete (&btype); 396360484Sobrien break; 396433965Sjdp } 396533965Sjdp case 't': 396660484Sobrien { 396760484Sobrien success = demangle_template (work, mangled, &btype, 0, 1, 1); 396860484Sobrien string_appends (result, &btype); 396960484Sobrien break; 397060484Sobrien } 397133965Sjdp default: 397233965Sjdp success = 0; 397333965Sjdp break; 397433965Sjdp } 397533965Sjdp 397660484Sobrien return success ? ((int) tk) : 0; 397733965Sjdp} 397833965Sjdp 397933965Sjdp 398060484Sobrien/* Handle a template's value parameter for HP aCC (extension from ARM) 398160484Sobrien **mangled points to 'S' or 'U' */ 398260484Sobrien 398333965Sjdpstatic int 398460484Sobriendo_hpacc_template_const_value (work, mangled, result) 398560484Sobrien struct work_stuff *work ATTRIBUTE_UNUSED; 398660484Sobrien const char **mangled; 398760484Sobrien string *result; 398860484Sobrien{ 398960484Sobrien int unsigned_const; 399060484Sobrien 399160484Sobrien if (**mangled != 'U' && **mangled != 'S') 399260484Sobrien return 0; 399360484Sobrien 399460484Sobrien unsigned_const = (**mangled == 'U'); 399560484Sobrien 399660484Sobrien (*mangled)++; 399760484Sobrien 399860484Sobrien switch (**mangled) 399960484Sobrien { 400060484Sobrien case 'N': 400160484Sobrien string_append (result, "-"); 400260484Sobrien /* fall through */ 400360484Sobrien case 'P': 400460484Sobrien (*mangled)++; 400560484Sobrien break; 400660484Sobrien case 'M': 400760484Sobrien /* special case for -2^31 */ 400860484Sobrien string_append (result, "-2147483648"); 400960484Sobrien (*mangled)++; 401060484Sobrien return 1; 401160484Sobrien default: 401260484Sobrien return 0; 401360484Sobrien } 401460484Sobrien 401560484Sobrien /* We have to be looking at an integer now */ 401677298Sobrien if (!(ISDIGIT ((unsigned char)**mangled))) 401760484Sobrien return 0; 401860484Sobrien 401960484Sobrien /* We only deal with integral values for template 402060484Sobrien parameters -- so it's OK to look only for digits */ 402177298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 402260484Sobrien { 402360484Sobrien char_str[0] = **mangled; 402460484Sobrien string_append (result, char_str); 402560484Sobrien (*mangled)++; 402660484Sobrien } 402760484Sobrien 402860484Sobrien if (unsigned_const) 402960484Sobrien string_append (result, "U"); 403060484Sobrien 403160484Sobrien /* FIXME? Some day we may have 64-bit (or larger :-) ) constants 403260484Sobrien with L or LL suffixes. pai/1997-09-03 */ 403360484Sobrien 403460484Sobrien return 1; /* success */ 403560484Sobrien} 403660484Sobrien 403760484Sobrien/* Handle a template's literal parameter for HP aCC (extension from ARM) 403860484Sobrien **mangled is pointing to the 'A' */ 403960484Sobrien 404060484Sobrienstatic int 404160484Sobriendo_hpacc_template_literal (work, mangled, result) 404260484Sobrien struct work_stuff *work; 404360484Sobrien const char **mangled; 404460484Sobrien string *result; 404560484Sobrien{ 404660484Sobrien int literal_len = 0; 404760484Sobrien char * recurse; 404860484Sobrien char * recurse_dem; 404960484Sobrien 405060484Sobrien if (**mangled != 'A') 405160484Sobrien return 0; 405260484Sobrien 405360484Sobrien (*mangled)++; 405460484Sobrien 405560484Sobrien literal_len = consume_count (mangled); 405660484Sobrien 405760484Sobrien if (literal_len <= 0) 405860484Sobrien return 0; 405960484Sobrien 406060484Sobrien /* Literal parameters are names of arrays, functions, etc. and the 406160484Sobrien canonical representation uses the address operator */ 406260484Sobrien string_append (result, "&"); 406360484Sobrien 406460484Sobrien /* Now recursively demangle the literal name */ 406560484Sobrien recurse = (char *) xmalloc (literal_len + 1); 406660484Sobrien memcpy (recurse, *mangled, literal_len); 406760484Sobrien recurse[literal_len] = '\000'; 406860484Sobrien 406960484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 407060484Sobrien 407160484Sobrien if (recurse_dem) 407260484Sobrien { 407360484Sobrien string_append (result, recurse_dem); 407460484Sobrien free (recurse_dem); 407560484Sobrien } 407660484Sobrien else 407760484Sobrien { 407860484Sobrien string_appendn (result, *mangled, literal_len); 407960484Sobrien } 408060484Sobrien (*mangled) += literal_len; 408160484Sobrien free (recurse); 408260484Sobrien 408360484Sobrien return 1; 408460484Sobrien} 408560484Sobrien 408660484Sobrienstatic int 408760484Sobriensnarf_numeric_literal (args, arg) 408860484Sobrien const char ** args; 408960484Sobrien string * arg; 409060484Sobrien{ 409160484Sobrien if (**args == '-') 409260484Sobrien { 409360484Sobrien char_str[0] = '-'; 409460484Sobrien string_append (arg, char_str); 409560484Sobrien (*args)++; 409660484Sobrien } 409760484Sobrien else if (**args == '+') 409860484Sobrien (*args)++; 409960484Sobrien 410077298Sobrien if (!ISDIGIT ((unsigned char)**args)) 410160484Sobrien return 0; 410260484Sobrien 410377298Sobrien while (ISDIGIT ((unsigned char)**args)) 410460484Sobrien { 410560484Sobrien char_str[0] = **args; 410660484Sobrien string_append (arg, char_str); 410760484Sobrien (*args)++; 410860484Sobrien } 410960484Sobrien 411060484Sobrien return 1; 411160484Sobrien} 411260484Sobrien 411360484Sobrien/* Demangle the next argument, given by MANGLED into RESULT, which 411460484Sobrien *should be an uninitialized* string. It will be initialized here, 411560484Sobrien and free'd should anything go wrong. */ 411660484Sobrien 411760484Sobrienstatic int 411833965Sjdpdo_arg (work, mangled, result) 411933965Sjdp struct work_stuff *work; 412033965Sjdp const char **mangled; 412133965Sjdp string *result; 412233965Sjdp{ 412360484Sobrien /* Remember where we started so that we can record the type, for 412460484Sobrien non-squangling type remembering. */ 412533965Sjdp const char *start = *mangled; 412633965Sjdp 412760484Sobrien string_init (result); 412860484Sobrien 412960484Sobrien if (work->nrepeats > 0) 413033965Sjdp { 413160484Sobrien --work->nrepeats; 413260484Sobrien 413360484Sobrien if (work->previous_argument == 0) 413460484Sobrien return 0; 413560484Sobrien 413660484Sobrien /* We want to reissue the previous type in this argument list. */ 413760484Sobrien string_appends (result, work->previous_argument); 413860484Sobrien return 1; 413933965Sjdp } 414060484Sobrien 414160484Sobrien if (**mangled == 'n') 414260484Sobrien { 414360484Sobrien /* A squangling-style repeat. */ 414460484Sobrien (*mangled)++; 414560484Sobrien work->nrepeats = consume_count(mangled); 414660484Sobrien 414760484Sobrien if (work->nrepeats <= 0) 414860484Sobrien /* This was not a repeat count after all. */ 414960484Sobrien return 0; 415060484Sobrien 415160484Sobrien if (work->nrepeats > 9) 415260484Sobrien { 415360484Sobrien if (**mangled != '_') 415460484Sobrien /* The repeat count should be followed by an '_' in this 415560484Sobrien case. */ 415660484Sobrien return 0; 415760484Sobrien else 415860484Sobrien (*mangled)++; 415960484Sobrien } 416060484Sobrien 416160484Sobrien /* Now, the repeat is all set up. */ 416260484Sobrien return do_arg (work, mangled, result); 416360484Sobrien } 416460484Sobrien 416560484Sobrien /* Save the result in WORK->previous_argument so that we can find it 416660484Sobrien if it's repeated. Note that saving START is not good enough: we 416760484Sobrien do not want to add additional types to the back-referenceable 416860484Sobrien type vector when processing a repeated type. */ 416960484Sobrien if (work->previous_argument) 417060484Sobrien string_clear (work->previous_argument); 417133965Sjdp else 417233965Sjdp { 417360484Sobrien work->previous_argument = (string*) xmalloc (sizeof (string)); 417460484Sobrien string_init (work->previous_argument); 417533965Sjdp } 417660484Sobrien 417760484Sobrien if (!do_type (work, mangled, work->previous_argument)) 417860484Sobrien return 0; 417960484Sobrien 418060484Sobrien string_appends (result, work->previous_argument); 418160484Sobrien 418260484Sobrien remember_type (work, start, *mangled - start); 418360484Sobrien return 1; 418433965Sjdp} 418533965Sjdp 418633965Sjdpstatic void 418733965Sjdpremember_type (work, start, len) 418833965Sjdp struct work_stuff *work; 418933965Sjdp const char *start; 419033965Sjdp int len; 419133965Sjdp{ 419233965Sjdp char *tem; 419333965Sjdp 419460484Sobrien if (work->forgetting_types) 419560484Sobrien return; 419660484Sobrien 419733965Sjdp if (work -> ntypes >= work -> typevec_size) 419833965Sjdp { 419933965Sjdp if (work -> typevec_size == 0) 420033965Sjdp { 420133965Sjdp work -> typevec_size = 3; 420238889Sjdp work -> typevec 420338889Sjdp = (char **) xmalloc (sizeof (char *) * work -> typevec_size); 420433965Sjdp } 420533965Sjdp else 420633965Sjdp { 420733965Sjdp work -> typevec_size *= 2; 420838889Sjdp work -> typevec 420938889Sjdp = (char **) xrealloc ((char *)work -> typevec, 421038889Sjdp sizeof (char *) * work -> typevec_size); 421133965Sjdp } 421233965Sjdp } 421333965Sjdp tem = xmalloc (len + 1); 421433965Sjdp memcpy (tem, start, len); 421533965Sjdp tem[len] = '\0'; 421633965Sjdp work -> typevec[work -> ntypes++] = tem; 421733965Sjdp} 421833965Sjdp 421960484Sobrien 422060484Sobrien/* Remember a K type class qualifier. */ 422160484Sobrienstatic void 422260484Sobrienremember_Ktype (work, start, len) 422360484Sobrien struct work_stuff *work; 422460484Sobrien const char *start; 422560484Sobrien int len; 422660484Sobrien{ 422760484Sobrien char *tem; 422860484Sobrien 422960484Sobrien if (work -> numk >= work -> ksize) 423060484Sobrien { 423160484Sobrien if (work -> ksize == 0) 423260484Sobrien { 423360484Sobrien work -> ksize = 5; 423460484Sobrien work -> ktypevec 423560484Sobrien = (char **) xmalloc (sizeof (char *) * work -> ksize); 423660484Sobrien } 423760484Sobrien else 423860484Sobrien { 423960484Sobrien work -> ksize *= 2; 424060484Sobrien work -> ktypevec 424160484Sobrien = (char **) xrealloc ((char *)work -> ktypevec, 424260484Sobrien sizeof (char *) * work -> ksize); 424360484Sobrien } 424460484Sobrien } 424560484Sobrien tem = xmalloc (len + 1); 424660484Sobrien memcpy (tem, start, len); 424760484Sobrien tem[len] = '\0'; 424860484Sobrien work -> ktypevec[work -> numk++] = tem; 424960484Sobrien} 425060484Sobrien 425160484Sobrien/* Register a B code, and get an index for it. B codes are registered 425260484Sobrien as they are seen, rather than as they are completed, so map<temp<char> > 425360484Sobrien registers map<temp<char> > as B0, and temp<char> as B1 */ 425460484Sobrien 425560484Sobrienstatic int 425660484Sobrienregister_Btype (work) 425760484Sobrien struct work_stuff *work; 425860484Sobrien{ 425960484Sobrien int ret; 426060484Sobrien 426160484Sobrien if (work -> numb >= work -> bsize) 426260484Sobrien { 426360484Sobrien if (work -> bsize == 0) 426460484Sobrien { 426560484Sobrien work -> bsize = 5; 426660484Sobrien work -> btypevec 426760484Sobrien = (char **) xmalloc (sizeof (char *) * work -> bsize); 426860484Sobrien } 426960484Sobrien else 427060484Sobrien { 427160484Sobrien work -> bsize *= 2; 427260484Sobrien work -> btypevec 427360484Sobrien = (char **) xrealloc ((char *)work -> btypevec, 427460484Sobrien sizeof (char *) * work -> bsize); 427560484Sobrien } 427660484Sobrien } 427760484Sobrien ret = work -> numb++; 427860484Sobrien work -> btypevec[ret] = NULL; 427960484Sobrien return(ret); 428060484Sobrien} 428160484Sobrien 428260484Sobrien/* Store a value into a previously registered B code type. */ 428360484Sobrien 428460484Sobrienstatic void 428560484Sobrienremember_Btype (work, start, len, index) 428660484Sobrien struct work_stuff *work; 428760484Sobrien const char *start; 428860484Sobrien int len, index; 428960484Sobrien{ 429060484Sobrien char *tem; 429160484Sobrien 429260484Sobrien tem = xmalloc (len + 1); 429360484Sobrien memcpy (tem, start, len); 429460484Sobrien tem[len] = '\0'; 429560484Sobrien work -> btypevec[index] = tem; 429660484Sobrien} 429760484Sobrien 429860484Sobrien/* Lose all the info related to B and K type codes. */ 429960484Sobrienstatic void 430060484Sobrienforget_B_and_K_types (work) 430160484Sobrien struct work_stuff *work; 430260484Sobrien{ 430360484Sobrien int i; 430460484Sobrien 430560484Sobrien while (work -> numk > 0) 430660484Sobrien { 430760484Sobrien i = --(work -> numk); 430860484Sobrien if (work -> ktypevec[i] != NULL) 430960484Sobrien { 431060484Sobrien free (work -> ktypevec[i]); 431160484Sobrien work -> ktypevec[i] = NULL; 431260484Sobrien } 431360484Sobrien } 431460484Sobrien 431560484Sobrien while (work -> numb > 0) 431660484Sobrien { 431760484Sobrien i = --(work -> numb); 431860484Sobrien if (work -> btypevec[i] != NULL) 431960484Sobrien { 432060484Sobrien free (work -> btypevec[i]); 432160484Sobrien work -> btypevec[i] = NULL; 432260484Sobrien } 432360484Sobrien } 432460484Sobrien} 432533965Sjdp/* Forget the remembered types, but not the type vector itself. */ 432633965Sjdp 432733965Sjdpstatic void 432833965Sjdpforget_types (work) 432933965Sjdp struct work_stuff *work; 433033965Sjdp{ 433133965Sjdp int i; 433233965Sjdp 433333965Sjdp while (work -> ntypes > 0) 433433965Sjdp { 433533965Sjdp i = --(work -> ntypes); 433633965Sjdp if (work -> typevec[i] != NULL) 433733965Sjdp { 433833965Sjdp free (work -> typevec[i]); 433933965Sjdp work -> typevec[i] = NULL; 434033965Sjdp } 434133965Sjdp } 434233965Sjdp} 434333965Sjdp 434433965Sjdp/* Process the argument list part of the signature, after any class spec 434533965Sjdp has been consumed, as well as the first 'F' character (if any). For 434633965Sjdp example: 434733965Sjdp 434833965Sjdp "__als__3fooRT0" => process "RT0" 434933965Sjdp "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" 435033965Sjdp 435133965Sjdp DECLP must be already initialised, usually non-empty. It won't be freed 435233965Sjdp on failure. 435333965Sjdp 435433965Sjdp Note that g++ differs significantly from ARM and lucid style mangling 435533965Sjdp with regards to references to previously seen types. For example, given 435633965Sjdp the source fragment: 435733965Sjdp 435833965Sjdp class foo { 435933965Sjdp public: 436033965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); 436133965Sjdp }; 436233965Sjdp 436333965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 436433965Sjdp void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 436533965Sjdp 436633965Sjdp g++ produces the names: 436733965Sjdp 436833965Sjdp __3fooiRT0iT2iT2 436933965Sjdp foo__FiR3fooiT1iT1 437033965Sjdp 437133965Sjdp while lcc (and presumably other ARM style compilers as well) produces: 437233965Sjdp 437333965Sjdp foo__FiR3fooT1T2T1T2 437433965Sjdp __ct__3fooFiR3fooT1T2T1T2 437533965Sjdp 437660484Sobrien Note that g++ bases its type numbers starting at zero and counts all 437760484Sobrien previously seen types, while lucid/ARM bases its type numbers starting 437833965Sjdp at one and only considers types after it has seen the 'F' character 437933965Sjdp indicating the start of the function args. For lucid/ARM style, we 438033965Sjdp account for this difference by discarding any previously seen types when 438133965Sjdp we see the 'F' character, and subtracting one from the type number 438233965Sjdp reference. 438333965Sjdp 438433965Sjdp */ 438533965Sjdp 438633965Sjdpstatic int 438733965Sjdpdemangle_args (work, mangled, declp) 438833965Sjdp struct work_stuff *work; 438933965Sjdp const char **mangled; 439033965Sjdp string *declp; 439133965Sjdp{ 439233965Sjdp string arg; 439333965Sjdp int need_comma = 0; 439433965Sjdp int r; 439533965Sjdp int t; 439633965Sjdp const char *tem; 439733965Sjdp char temptype; 439833965Sjdp 439933965Sjdp if (PRINT_ARG_TYPES) 440033965Sjdp { 440133965Sjdp string_append (declp, "("); 440233965Sjdp if (**mangled == '\0') 440333965Sjdp { 440433965Sjdp string_append (declp, "void"); 440533965Sjdp } 440633965Sjdp } 440733965Sjdp 440860484Sobrien while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') 440960484Sobrien || work->nrepeats > 0) 441033965Sjdp { 441133965Sjdp if ((**mangled == 'N') || (**mangled == 'T')) 441233965Sjdp { 441333965Sjdp temptype = *(*mangled)++; 441460484Sobrien 441533965Sjdp if (temptype == 'N') 441633965Sjdp { 441733965Sjdp if (!get_count (mangled, &r)) 441833965Sjdp { 441933965Sjdp return (0); 442033965Sjdp } 442133965Sjdp } 442233965Sjdp else 442333965Sjdp { 442433965Sjdp r = 1; 442533965Sjdp } 442660484Sobrien if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) 442733965Sjdp { 442833965Sjdp /* If we have 10 or more types we might have more than a 1 digit 442933965Sjdp index so we'll have to consume the whole count here. This 443033965Sjdp will lose if the next thing is a type name preceded by a 443133965Sjdp count but it's impossible to demangle that case properly 443233965Sjdp anyway. Eg if we already have 12 types is T12Pc "(..., type1, 443333965Sjdp Pc, ...)" or "(..., type12, char *, ...)" */ 443460484Sobrien if ((t = consume_count(mangled)) <= 0) 443533965Sjdp { 443633965Sjdp return (0); 443733965Sjdp } 443833965Sjdp } 443933965Sjdp else 444033965Sjdp { 444133965Sjdp if (!get_count (mangled, &t)) 444233965Sjdp { 444333965Sjdp return (0); 444433965Sjdp } 444533965Sjdp } 444660484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 444733965Sjdp { 444833965Sjdp t--; 444933965Sjdp } 445033965Sjdp /* Validate the type index. Protect against illegal indices from 445133965Sjdp malformed type strings. */ 445233965Sjdp if ((t < 0) || (t >= work -> ntypes)) 445333965Sjdp { 445433965Sjdp return (0); 445533965Sjdp } 445660484Sobrien while (work->nrepeats > 0 || --r >= 0) 445733965Sjdp { 445833965Sjdp tem = work -> typevec[t]; 445933965Sjdp if (need_comma && PRINT_ARG_TYPES) 446033965Sjdp { 446133965Sjdp string_append (declp, ", "); 446233965Sjdp } 446333965Sjdp if (!do_arg (work, &tem, &arg)) 446433965Sjdp { 446533965Sjdp return (0); 446633965Sjdp } 446733965Sjdp if (PRINT_ARG_TYPES) 446833965Sjdp { 446933965Sjdp string_appends (declp, &arg); 447033965Sjdp } 447133965Sjdp string_delete (&arg); 447233965Sjdp need_comma = 1; 447333965Sjdp } 447433965Sjdp } 447533965Sjdp else 447633965Sjdp { 447760484Sobrien if (need_comma && PRINT_ARG_TYPES) 447860484Sobrien string_append (declp, ", "); 447933965Sjdp if (!do_arg (work, mangled, &arg)) 448060484Sobrien return (0); 448133965Sjdp if (PRINT_ARG_TYPES) 448260484Sobrien string_appends (declp, &arg); 448333965Sjdp string_delete (&arg); 448433965Sjdp need_comma = 1; 448533965Sjdp } 448633965Sjdp } 448733965Sjdp 448833965Sjdp if (**mangled == 'e') 448933965Sjdp { 449033965Sjdp (*mangled)++; 449133965Sjdp if (PRINT_ARG_TYPES) 449233965Sjdp { 449333965Sjdp if (need_comma) 449433965Sjdp { 449533965Sjdp string_append (declp, ","); 449633965Sjdp } 449733965Sjdp string_append (declp, "..."); 449833965Sjdp } 449933965Sjdp } 450033965Sjdp 450133965Sjdp if (PRINT_ARG_TYPES) 450233965Sjdp { 450333965Sjdp string_append (declp, ")"); 450433965Sjdp } 450533965Sjdp return (1); 450633965Sjdp} 450733965Sjdp 450860484Sobrien/* Like demangle_args, but for demangling the argument lists of function 450960484Sobrien and method pointers or references, not top-level declarations. */ 451060484Sobrien 451160484Sobrienstatic int 451260484Sobriendemangle_nested_args (work, mangled, declp) 451360484Sobrien struct work_stuff *work; 451460484Sobrien const char **mangled; 451560484Sobrien string *declp; 451660484Sobrien{ 451760484Sobrien string* saved_previous_argument; 451860484Sobrien int result; 451960484Sobrien int saved_nrepeats; 452060484Sobrien 452160484Sobrien /* The G++ name-mangling algorithm does not remember types on nested 452260484Sobrien argument lists, unless -fsquangling is used, and in that case the 452360484Sobrien type vector updated by remember_type is not used. So, we turn 452460484Sobrien off remembering of types here. */ 452560484Sobrien ++work->forgetting_types; 452660484Sobrien 452760484Sobrien /* For the repeat codes used with -fsquangling, we must keep track of 452860484Sobrien the last argument. */ 452960484Sobrien saved_previous_argument = work->previous_argument; 453060484Sobrien saved_nrepeats = work->nrepeats; 453160484Sobrien work->previous_argument = 0; 453260484Sobrien work->nrepeats = 0; 453360484Sobrien 453460484Sobrien /* Actually demangle the arguments. */ 453560484Sobrien result = demangle_args (work, mangled, declp); 453660484Sobrien 453760484Sobrien /* Restore the previous_argument field. */ 453860484Sobrien if (work->previous_argument) 453960484Sobrien string_delete (work->previous_argument); 454060484Sobrien work->previous_argument = saved_previous_argument; 454160484Sobrien --work->forgetting_types; 454260484Sobrien work->nrepeats = saved_nrepeats; 454360484Sobrien 454460484Sobrien return result; 454560484Sobrien} 454660484Sobrien 454733965Sjdpstatic void 454833965Sjdpdemangle_function_name (work, mangled, declp, scan) 454933965Sjdp struct work_stuff *work; 455033965Sjdp const char **mangled; 455133965Sjdp string *declp; 455233965Sjdp const char *scan; 455333965Sjdp{ 455460484Sobrien size_t i; 455533965Sjdp string type; 455633965Sjdp const char *tem; 455733965Sjdp 455833965Sjdp string_appendn (declp, (*mangled), scan - (*mangled)); 455933965Sjdp string_need (declp, 1); 456033965Sjdp *(declp -> p) = '\0'; 456133965Sjdp 456233965Sjdp /* Consume the function name, including the "__" separating the name 456333965Sjdp from the signature. We are guaranteed that SCAN points to the 456433965Sjdp separator. */ 456533965Sjdp 456633965Sjdp (*mangled) = scan + 2; 456760484Sobrien /* We may be looking at an instantiation of a template function: 456860484Sobrien foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a 456960484Sobrien following _F marks the start of the function arguments. Handle 457060484Sobrien the template arguments first. */ 457133965Sjdp 457260484Sobrien if (HP_DEMANGLING && (**mangled == 'X')) 457333965Sjdp { 457460484Sobrien demangle_arm_hp_template (work, mangled, 0, declp); 457560484Sobrien /* This leaves MANGLED pointing to the 'F' marking func args */ 457660484Sobrien } 457733965Sjdp 457860484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 457960484Sobrien { 458060484Sobrien 458133965Sjdp /* See if we have an ARM style constructor or destructor operator. 458233965Sjdp If so, then just record it, clear the decl, and return. 458333965Sjdp We can't build the actual constructor/destructor decl until later, 458433965Sjdp when we recover the class name from the signature. */ 458533965Sjdp 458633965Sjdp if (strcmp (declp -> b, "__ct") == 0) 458733965Sjdp { 458833965Sjdp work -> constructor += 1; 458933965Sjdp string_clear (declp); 459033965Sjdp return; 459133965Sjdp } 459233965Sjdp else if (strcmp (declp -> b, "__dt") == 0) 459333965Sjdp { 459433965Sjdp work -> destructor += 1; 459533965Sjdp string_clear (declp); 459633965Sjdp return; 459733965Sjdp } 459833965Sjdp } 459933965Sjdp 460060484Sobrien if (declp->p - declp->b >= 3 460133965Sjdp && declp->b[0] == 'o' 460233965Sjdp && declp->b[1] == 'p' 460333965Sjdp && strchr (cplus_markers, declp->b[2]) != NULL) 460433965Sjdp { 460533965Sjdp /* see if it's an assignment expression */ 460633965Sjdp if (declp->p - declp->b >= 10 /* op$assign_ */ 460733965Sjdp && memcmp (declp->b + 3, "assign_", 7) == 0) 460833965Sjdp { 460977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 461033965Sjdp { 461160484Sobrien int len = declp->p - declp->b - 10; 461260484Sobrien if ((int) strlen (optable[i].in) == len 461333965Sjdp && memcmp (optable[i].in, declp->b + 10, len) == 0) 461433965Sjdp { 461533965Sjdp string_clear (declp); 461633965Sjdp string_append (declp, "operator"); 461733965Sjdp string_append (declp, optable[i].out); 461833965Sjdp string_append (declp, "="); 461933965Sjdp break; 462033965Sjdp } 462133965Sjdp } 462233965Sjdp } 462333965Sjdp else 462433965Sjdp { 462577298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 462633965Sjdp { 462733965Sjdp int len = declp->p - declp->b - 3; 462860484Sobrien if ((int) strlen (optable[i].in) == len 462933965Sjdp && memcmp (optable[i].in, declp->b + 3, len) == 0) 463033965Sjdp { 463133965Sjdp string_clear (declp); 463233965Sjdp string_append (declp, "operator"); 463333965Sjdp string_append (declp, optable[i].out); 463433965Sjdp break; 463533965Sjdp } 463633965Sjdp } 463733965Sjdp } 463833965Sjdp } 463933965Sjdp else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 464033965Sjdp && strchr (cplus_markers, declp->b[4]) != NULL) 464133965Sjdp { 464233965Sjdp /* type conversion operator */ 464333965Sjdp tem = declp->b + 5; 464433965Sjdp if (do_type (work, &tem, &type)) 464533965Sjdp { 464633965Sjdp string_clear (declp); 464733965Sjdp string_append (declp, "operator "); 464833965Sjdp string_appends (declp, &type); 464933965Sjdp string_delete (&type); 465033965Sjdp } 465133965Sjdp } 465233965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 465333965Sjdp && declp->b[2] == 'o' && declp->b[3] == 'p') 465433965Sjdp { 465533965Sjdp /* ANSI. */ 465633965Sjdp /* type conversion operator. */ 465733965Sjdp tem = declp->b + 4; 465833965Sjdp if (do_type (work, &tem, &type)) 465933965Sjdp { 466033965Sjdp string_clear (declp); 466133965Sjdp string_append (declp, "operator "); 466233965Sjdp string_appends (declp, &type); 466333965Sjdp string_delete (&type); 466433965Sjdp } 466533965Sjdp } 466633965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 466777298Sobrien && ISLOWER((unsigned char)declp->b[2]) 466877298Sobrien && ISLOWER((unsigned char)declp->b[3])) 466933965Sjdp { 467033965Sjdp if (declp->b[4] == '\0') 467133965Sjdp { 467233965Sjdp /* Operator. */ 467377298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 467433965Sjdp { 467533965Sjdp if (strlen (optable[i].in) == 2 467633965Sjdp && memcmp (optable[i].in, declp->b + 2, 2) == 0) 467733965Sjdp { 467833965Sjdp string_clear (declp); 467933965Sjdp string_append (declp, "operator"); 468033965Sjdp string_append (declp, optable[i].out); 468133965Sjdp break; 468233965Sjdp } 468333965Sjdp } 468433965Sjdp } 468533965Sjdp else 468633965Sjdp { 468733965Sjdp if (declp->b[2] == 'a' && declp->b[5] == '\0') 468833965Sjdp { 468933965Sjdp /* Assignment. */ 469077298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 469133965Sjdp { 469233965Sjdp if (strlen (optable[i].in) == 3 469333965Sjdp && memcmp (optable[i].in, declp->b + 2, 3) == 0) 469433965Sjdp { 469533965Sjdp string_clear (declp); 469633965Sjdp string_append (declp, "operator"); 469733965Sjdp string_append (declp, optable[i].out); 469833965Sjdp break; 469960484Sobrien } 470033965Sjdp } 470133965Sjdp } 470233965Sjdp } 470333965Sjdp } 470433965Sjdp} 470533965Sjdp 470633965Sjdp/* a mini string-handling package */ 470733965Sjdp 470833965Sjdpstatic void 470933965Sjdpstring_need (s, n) 471033965Sjdp string *s; 471133965Sjdp int n; 471233965Sjdp{ 471333965Sjdp int tem; 471433965Sjdp 471533965Sjdp if (s->b == NULL) 471633965Sjdp { 471733965Sjdp if (n < 32) 471833965Sjdp { 471933965Sjdp n = 32; 472033965Sjdp } 472133965Sjdp s->p = s->b = xmalloc (n); 472233965Sjdp s->e = s->b + n; 472333965Sjdp } 472433965Sjdp else if (s->e - s->p < n) 472533965Sjdp { 472633965Sjdp tem = s->p - s->b; 472733965Sjdp n += tem; 472833965Sjdp n *= 2; 472933965Sjdp s->b = xrealloc (s->b, n); 473033965Sjdp s->p = s->b + tem; 473133965Sjdp s->e = s->b + n; 473233965Sjdp } 473333965Sjdp} 473433965Sjdp 473533965Sjdpstatic void 473633965Sjdpstring_delete (s) 473733965Sjdp string *s; 473833965Sjdp{ 473933965Sjdp if (s->b != NULL) 474033965Sjdp { 474133965Sjdp free (s->b); 474233965Sjdp s->b = s->e = s->p = NULL; 474333965Sjdp } 474433965Sjdp} 474533965Sjdp 474633965Sjdpstatic void 474733965Sjdpstring_init (s) 474833965Sjdp string *s; 474933965Sjdp{ 475033965Sjdp s->b = s->p = s->e = NULL; 475133965Sjdp} 475233965Sjdp 475360484Sobrienstatic void 475433965Sjdpstring_clear (s) 475533965Sjdp string *s; 475633965Sjdp{ 475733965Sjdp s->p = s->b; 475833965Sjdp} 475933965Sjdp 476033965Sjdp#if 0 476133965Sjdp 476233965Sjdpstatic int 476333965Sjdpstring_empty (s) 476433965Sjdp string *s; 476533965Sjdp{ 476633965Sjdp return (s->b == s->p); 476733965Sjdp} 476833965Sjdp 476933965Sjdp#endif 477033965Sjdp 477133965Sjdpstatic void 477233965Sjdpstring_append (p, s) 477333965Sjdp string *p; 477433965Sjdp const char *s; 477533965Sjdp{ 477633965Sjdp int n; 477733965Sjdp if (s == NULL || *s == '\0') 477833965Sjdp return; 477933965Sjdp n = strlen (s); 478033965Sjdp string_need (p, n); 478133965Sjdp memcpy (p->p, s, n); 478233965Sjdp p->p += n; 478333965Sjdp} 478433965Sjdp 478533965Sjdpstatic void 478633965Sjdpstring_appends (p, s) 478733965Sjdp string *p, *s; 478833965Sjdp{ 478933965Sjdp int n; 479033965Sjdp 479133965Sjdp if (s->b != s->p) 479233965Sjdp { 479333965Sjdp n = s->p - s->b; 479433965Sjdp string_need (p, n); 479533965Sjdp memcpy (p->p, s->b, n); 479633965Sjdp p->p += n; 479733965Sjdp } 479833965Sjdp} 479933965Sjdp 480033965Sjdpstatic void 480133965Sjdpstring_appendn (p, s, n) 480233965Sjdp string *p; 480333965Sjdp const char *s; 480433965Sjdp int n; 480533965Sjdp{ 480633965Sjdp if (n != 0) 480733965Sjdp { 480833965Sjdp string_need (p, n); 480933965Sjdp memcpy (p->p, s, n); 481033965Sjdp p->p += n; 481133965Sjdp } 481233965Sjdp} 481333965Sjdp 481433965Sjdpstatic void 481533965Sjdpstring_prepend (p, s) 481633965Sjdp string *p; 481733965Sjdp const char *s; 481833965Sjdp{ 481933965Sjdp if (s != NULL && *s != '\0') 482033965Sjdp { 482133965Sjdp string_prependn (p, s, strlen (s)); 482233965Sjdp } 482333965Sjdp} 482433965Sjdp 482533965Sjdpstatic void 482633965Sjdpstring_prepends (p, s) 482733965Sjdp string *p, *s; 482833965Sjdp{ 482933965Sjdp if (s->b != s->p) 483033965Sjdp { 483133965Sjdp string_prependn (p, s->b, s->p - s->b); 483233965Sjdp } 483333965Sjdp} 483433965Sjdp 483533965Sjdpstatic void 483633965Sjdpstring_prependn (p, s, n) 483733965Sjdp string *p; 483833965Sjdp const char *s; 483933965Sjdp int n; 484033965Sjdp{ 484133965Sjdp char *q; 484233965Sjdp 484333965Sjdp if (n != 0) 484433965Sjdp { 484533965Sjdp string_need (p, n); 484633965Sjdp for (q = p->p - 1; q >= p->b; q--) 484733965Sjdp { 484833965Sjdp q[n] = q[0]; 484933965Sjdp } 485033965Sjdp memcpy (p->b, s, n); 485133965Sjdp p->p += n; 485233965Sjdp } 485333965Sjdp} 485433965Sjdp 485560484Sobrienstatic void 485660484Sobrienstring_append_template_idx (s, idx) 485760484Sobrien string *s; 485860484Sobrien int idx; 485960484Sobrien{ 486060484Sobrien char buf[INTBUF_SIZE + 1 /* 'T' */]; 486160484Sobrien sprintf(buf, "T%d", idx); 486260484Sobrien string_append (s, buf); 486360484Sobrien} 486460484Sobrien 486533965Sjdp/* To generate a standalone demangler program for testing purposes, 486633965Sjdp just compile and link this file with -DMAIN and libiberty.a. When 486733965Sjdp run, it demangles each command line arg, or each stdin string, and 486833965Sjdp prints the result on stdout. */ 486933965Sjdp 487033965Sjdp#ifdef MAIN 487133965Sjdp 487238889Sjdp#include "getopt.h" 487338889Sjdp 487460484Sobrienstatic const char *program_name; 487560484Sobrienstatic const char *program_version = VERSION; 487638889Sjdpstatic int flags = DMGL_PARAMS | DMGL_ANSI; 487738889Sjdp 487833965Sjdpstatic void demangle_it PARAMS ((char *)); 487960484Sobrienstatic void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN; 488060484Sobrienstatic void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN; 488168765Sobrienstatic void print_demangler_list PARAMS ((FILE *)); 488233965Sjdp 488333965Sjdpstatic void 488433965Sjdpdemangle_it (mangled_name) 488533965Sjdp char *mangled_name; 488633965Sjdp{ 488733965Sjdp char *result; 488833965Sjdp 488938889Sjdp result = cplus_demangle (mangled_name, flags); 489033965Sjdp if (result == NULL) 489133965Sjdp { 489233965Sjdp printf ("%s\n", mangled_name); 489333965Sjdp } 489433965Sjdp else 489533965Sjdp { 489633965Sjdp printf ("%s\n", result); 489733965Sjdp free (result); 489833965Sjdp } 489933965Sjdp} 490033965Sjdp 490168765Sobrienstatic void 490268765Sobrienprint_demangler_list (stream) 490368765Sobrien FILE *stream; 490468765Sobrien{ 490568765Sobrien struct demangler_engine *demangler; 490668765Sobrien 490768765Sobrien fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name); 490868765Sobrien 490968765Sobrien for (demangler = libiberty_demanglers + 1; 491068765Sobrien demangler->demangling_style != unknown_demangling; 491168765Sobrien ++demangler) 491268765Sobrien fprintf (stream, ",%s", demangler->demangling_style_name); 491368765Sobrien 491468765Sobrien fprintf (stream, "}"); 491568765Sobrien} 491668765Sobrien 491733965Sjdpstatic void 491833965Sjdpusage (stream, status) 491933965Sjdp FILE *stream; 492033965Sjdp int status; 492160484Sobrien{ 492233965Sjdp fprintf (stream, "\ 492368765SobrienUsage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n", 492433965Sjdp program_name); 492568765Sobrien 492668765Sobrien fprintf (stream, "\ 492768765Sobrien [-s "); 492868765Sobrien print_demangler_list (stream); 492968765Sobrien fprintf (stream, "]\n"); 493068765Sobrien 493168765Sobrien fprintf (stream, "\ 493268765Sobrien [--format "); 493368765Sobrien print_demangler_list (stream); 493468765Sobrien fprintf (stream, "]\n"); 493568765Sobrien 493668765Sobrien fprintf (stream, "\ 493768765Sobrien [--help] [--version] [arg...]\n"); 493833965Sjdp exit (status); 493933965Sjdp} 494033965Sjdp 494160484Sobrien#define MBUF_SIZE 32767 494233965Sjdpchar mbuffer[MBUF_SIZE]; 494333965Sjdp 494433965Sjdp/* Defined in the automatically-generated underscore.c. */ 494533965Sjdpextern int prepends_underscore; 494633965Sjdp 494733965Sjdpint strip_underscore = 0; 494833965Sjdp 494933965Sjdpstatic struct option long_options[] = { 495033965Sjdp {"strip-underscores", no_argument, 0, '_'}, 495133965Sjdp {"format", required_argument, 0, 's'}, 495233965Sjdp {"help", no_argument, 0, 'h'}, 495338889Sjdp {"java", no_argument, 0, 'j'}, 495433965Sjdp {"no-strip-underscores", no_argument, 0, 'n'}, 495533965Sjdp {"version", no_argument, 0, 'v'}, 495633965Sjdp {0, no_argument, 0, 0} 495733965Sjdp}; 495833965Sjdp 495960484Sobrien/* More 'friendly' abort that prints the line and file. 496060484Sobrien config.h can #define abort fancy_abort if you like that sort of thing. */ 496160484Sobrien 496260484Sobrienvoid 496360484Sobrienfancy_abort () 496460484Sobrien{ 496560484Sobrien fatal ("Internal gcc abort."); 496660484Sobrien} 496760484Sobrien 496860484Sobrien 496960484Sobrienstatic const char * 497060484Sobrienstandard_symbol_characters PARAMS ((void)); 497160484Sobrien 497260484Sobrienstatic const char * 497360484Sobrienhp_symbol_characters PARAMS ((void)); 497460484Sobrien 497568765Sobrienstatic const char * 497677298Sobriengnu_v3_symbol_characters PARAMS ((void)); 497768765Sobrien 497860484Sobrien/* Return the string of non-alnum characters that may occur 497960484Sobrien as a valid symbol component, in the standard assembler symbol 498060484Sobrien syntax. */ 498160484Sobrien 498260484Sobrienstatic const char * 498360484Sobrienstandard_symbol_characters () 498460484Sobrien{ 498560484Sobrien return "_$."; 498660484Sobrien} 498760484Sobrien 498860484Sobrien 498960484Sobrien/* Return the string of non-alnum characters that may occur 499060484Sobrien as a valid symbol name component in an HP object file. 499160484Sobrien 499260484Sobrien Note that, since HP's compiler generates object code straight from 499360484Sobrien C++ source, without going through an assembler, its mangled 499460484Sobrien identifiers can use all sorts of characters that no assembler would 499560484Sobrien tolerate, so the alphabet this function creates is a little odd. 499660484Sobrien Here are some sample mangled identifiers offered by HP: 499760484Sobrien 499860484Sobrien typeid*__XT24AddressIndExpClassMember_ 499960484Sobrien [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv 500060484Sobrien __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv 500160484Sobrien 500260484Sobrien This still seems really weird to me, since nowhere else in this 500360484Sobrien file is there anything to recognize curly brackets, parens, etc. 500460484Sobrien I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me 500560484Sobrien this is right, but I still strongly suspect that there's a 500660484Sobrien misunderstanding here. 500760484Sobrien 500860484Sobrien If we decide it's better for c++filt to use HP's assembler syntax 500960484Sobrien to scrape identifiers out of its input, here's the definition of 501060484Sobrien the symbol name syntax from the HP assembler manual: 501160484Sobrien 501260484Sobrien Symbols are composed of uppercase and lowercase letters, decimal 501360484Sobrien digits, dollar symbol, period (.), ampersand (&), pound sign(#) and 501460484Sobrien underscore (_). A symbol can begin with a letter, digit underscore or 501560484Sobrien dollar sign. If a symbol begins with a digit, it must contain a 501660484Sobrien non-digit character. 501760484Sobrien 501860484Sobrien So have fun. */ 501960484Sobrienstatic const char * 502060484Sobrienhp_symbol_characters () 502160484Sobrien{ 502260484Sobrien return "_$.<>#,*&[]:(){}"; 502360484Sobrien} 502460484Sobrien 502560484Sobrien 502668765Sobrien/* Return the string of non-alnum characters that may occur 502777298Sobrien as a valid symbol component in the GNU C++ V3 ABI mangling 502868765Sobrien scheme. */ 502968765Sobrien 503068765Sobrienstatic const char * 503177298Sobriengnu_v3_symbol_characters () 503268765Sobrien{ 503377298Sobrien return "_$."; 503468765Sobrien} 503568765Sobrien 503668765Sobrien 503760484Sobrienextern int main PARAMS ((int, char **)); 503860484Sobrien 503933965Sjdpint 504033965Sjdpmain (argc, argv) 504133965Sjdp int argc; 504233965Sjdp char **argv; 504333965Sjdp{ 504433965Sjdp char *result; 504533965Sjdp int c; 504660484Sobrien const char *valid_symbols; 504733965Sjdp 504833965Sjdp program_name = argv[0]; 504933965Sjdp 505033965Sjdp strip_underscore = prepends_underscore; 505133965Sjdp 505238889Sjdp while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF) 505333965Sjdp { 505433965Sjdp switch (c) 505533965Sjdp { 505633965Sjdp case '?': 505733965Sjdp usage (stderr, 1); 505833965Sjdp break; 505933965Sjdp case 'h': 506033965Sjdp usage (stdout, 0); 506133965Sjdp case 'n': 506233965Sjdp strip_underscore = 0; 506333965Sjdp break; 506433965Sjdp case 'v': 506560484Sobrien printf ("GNU %s (C++ demangler), version %s\n", program_name, program_version); 506660484Sobrien return (0); 506733965Sjdp case '_': 506833965Sjdp strip_underscore = 1; 506933965Sjdp break; 507038889Sjdp case 'j': 507138889Sjdp flags |= DMGL_JAVA; 507238889Sjdp break; 507333965Sjdp case 's': 507468765Sobrien { 507568765Sobrien enum demangling_styles style; 507668765Sobrien 507768765Sobrien style = cplus_demangle_name_to_style (optarg); 507868765Sobrien if (style == unknown_demangling) 507968765Sobrien { 508068765Sobrien fprintf (stderr, "%s: unknown demangling style `%s'\n", 508168765Sobrien program_name, optarg); 508268765Sobrien return (1); 508368765Sobrien } 508468765Sobrien else 508568765Sobrien cplus_demangle_set_style (style); 508668765Sobrien } 508733965Sjdp break; 508833965Sjdp } 508933965Sjdp } 509033965Sjdp 509133965Sjdp if (optind < argc) 509233965Sjdp { 509333965Sjdp for ( ; optind < argc; optind++) 509433965Sjdp { 509533965Sjdp demangle_it (argv[optind]); 509633965Sjdp } 509733965Sjdp } 509833965Sjdp else 509933965Sjdp { 510060484Sobrien switch (current_demangling_style) 510160484Sobrien { 510260484Sobrien case gnu_demangling: 510360484Sobrien case lucid_demangling: 510460484Sobrien case arm_demangling: 510577298Sobrien case java_demangling: 510660484Sobrien case edg_demangling: 510777298Sobrien case gnat_demangling: 510877298Sobrien case auto_demangling: 510960484Sobrien valid_symbols = standard_symbol_characters (); 511060484Sobrien break; 511160484Sobrien case hp_demangling: 511260484Sobrien valid_symbols = hp_symbol_characters (); 511360484Sobrien break; 511477298Sobrien case gnu_v3_demangling: 511577298Sobrien valid_symbols = gnu_v3_symbol_characters (); 511668765Sobrien break; 511760484Sobrien default: 511860484Sobrien /* Folks should explicitly indicate the appropriate alphabet for 511960484Sobrien each demangling. Providing a default would allow the 512060484Sobrien question to go unconsidered. */ 512160484Sobrien abort (); 512260484Sobrien } 512360484Sobrien 512433965Sjdp for (;;) 512533965Sjdp { 512633965Sjdp int i = 0; 512733965Sjdp c = getchar (); 512833965Sjdp /* Try to read a label. */ 512977298Sobrien while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c))) 513033965Sjdp { 513133965Sjdp if (i >= MBUF_SIZE-1) 513233965Sjdp break; 513333965Sjdp mbuffer[i++] = c; 513433965Sjdp c = getchar (); 513533965Sjdp } 513633965Sjdp if (i > 0) 513733965Sjdp { 513833965Sjdp int skip_first = 0; 513933965Sjdp 514033965Sjdp if (mbuffer[0] == '.') 514133965Sjdp ++skip_first; 514233965Sjdp if (strip_underscore && mbuffer[skip_first] == '_') 514333965Sjdp ++skip_first; 514433965Sjdp 514533965Sjdp if (skip_first > i) 514633965Sjdp skip_first = i; 514733965Sjdp 514833965Sjdp mbuffer[i] = 0; 514960484Sobrien 515038889Sjdp result = cplus_demangle (mbuffer + skip_first, flags); 515133965Sjdp if (result) 515233965Sjdp { 515333965Sjdp if (mbuffer[0] == '.') 515433965Sjdp putc ('.', stdout); 515533965Sjdp fputs (result, stdout); 515633965Sjdp free (result); 515733965Sjdp } 515833965Sjdp else 515933965Sjdp fputs (mbuffer, stdout); 516033965Sjdp 516133965Sjdp fflush (stdout); 516233965Sjdp } 516333965Sjdp if (c == EOF) 516433965Sjdp break; 516533965Sjdp putchar (c); 516668765Sobrien fflush (stdout); 516733965Sjdp } 516833965Sjdp } 516933965Sjdp 517060484Sobrien return (0); 517133965Sjdp} 517233965Sjdp 517333965Sjdpstatic void 517433965Sjdpfatal (str) 517560484Sobrien const char *str; 517633965Sjdp{ 517733965Sjdp fprintf (stderr, "%s: %s\n", program_name, str); 517833965Sjdp exit (1); 517933965Sjdp} 518033965Sjdp 518160484SobrienPTR 518233965Sjdpxmalloc (size) 518360484Sobrien size_t size; 518433965Sjdp{ 518560484Sobrien register PTR value = (PTR) malloc (size); 518633965Sjdp if (value == 0) 518733965Sjdp fatal ("virtual memory exhausted"); 518833965Sjdp return value; 518933965Sjdp} 519033965Sjdp 519160484SobrienPTR 519233965Sjdpxrealloc (ptr, size) 519360484Sobrien PTR ptr; 519460484Sobrien size_t size; 519533965Sjdp{ 519660484Sobrien register PTR value = (PTR) realloc (ptr, size); 519733965Sjdp if (value == 0) 519833965Sjdp fatal ("virtual memory exhausted"); 519933965Sjdp return value; 520033965Sjdp} 520133965Sjdp#endif /* main */ 5202