cplus-dem.c revision 91041
160484Sobrien/* Demangler for GNU C++ 277298Sobrien Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 389857Sobrien 2000, 2001 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 6633965Sjdp/* In order to allow a single demangler executable to demangle strings 6733965Sjdp using various common values of CPLUS_MARKER, as well as any specific 6833965Sjdp one set at compile time, we maintain a string containing all the 6933965Sjdp commonly used ones, and check to see if the marker we are looking for 7033965Sjdp is in that string. CPLUS_MARKER is usually '$' on systems where the 7133965Sjdp assembler can deal with that. Where the assembler can't, it's usually 7233965Sjdp '.' (but on many systems '.' is used for other things). We put the 7333965Sjdp current defined CPLUS_MARKER first (which defaults to '$'), followed 7433965Sjdp by the next most common value, followed by an explicit '$' in case 7533965Sjdp the value of CPLUS_MARKER is not '$'. 7633965Sjdp 7733965Sjdp We could avoid this if we could just get g++ to tell us what the actual 7833965Sjdp cplus marker character is as part of the debug information, perhaps by 7933965Sjdp ensuring that it is the character that terminates the gcc<n>_compiled 8033965Sjdp marker symbol (FIXME). */ 8133965Sjdp 8233965Sjdp#if !defined (CPLUS_MARKER) 8333965Sjdp#define CPLUS_MARKER '$' 8433965Sjdp#endif 8533965Sjdp 8677298Sobrienenum demangling_styles current_demangling_style = auto_demangling; 8733965Sjdp 8833965Sjdpstatic char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; 8933965Sjdp 9060484Sobrienstatic char char_str[2] = { '\000', '\000' }; 9160484Sobrien 9233965Sjdpvoid 9333965Sjdpset_cplus_marker_for_demangling (ch) 9433965Sjdp int ch; 9533965Sjdp{ 9633965Sjdp cplus_markers[0] = ch; 9733965Sjdp} 9833965Sjdp 9960484Sobrientypedef struct string /* Beware: these aren't required to be */ 10060484Sobrien{ /* '\0' terminated. */ 10160484Sobrien char *b; /* pointer to start of string */ 10260484Sobrien char *p; /* pointer after last character */ 10360484Sobrien char *e; /* pointer after end of allocated space */ 10460484Sobrien} string; 10560484Sobrien 10633965Sjdp/* Stuff that is shared between sub-routines. 10733965Sjdp Using a shared structure allows cplus_demangle to be reentrant. */ 10833965Sjdp 10933965Sjdpstruct work_stuff 11033965Sjdp{ 11133965Sjdp int options; 11233965Sjdp char **typevec; 11360484Sobrien char **ktypevec; 11460484Sobrien char **btypevec; 11560484Sobrien int numk; 11660484Sobrien int numb; 11760484Sobrien int ksize; 11860484Sobrien int bsize; 11933965Sjdp int ntypes; 12033965Sjdp int typevec_size; 12133965Sjdp int constructor; 12233965Sjdp int destructor; 12333965Sjdp int static_type; /* A static member function */ 12460484Sobrien int temp_start; /* index in demangled to start of template args */ 12560484Sobrien int type_quals; /* The type qualifiers. */ 12660484Sobrien int dllimported; /* Symbol imported from a PE DLL */ 12738889Sjdp char **tmpl_argvec; /* Template function arguments. */ 12838889Sjdp int ntmpl_args; /* The number of template function arguments. */ 12960484Sobrien int forgetting_types; /* Nonzero if we are not remembering the types 13060484Sobrien we see. */ 13160484Sobrien string* previous_argument; /* The last function argument demangled. */ 13260484Sobrien int nrepeats; /* The number of times to repeat the previous 13360484Sobrien argument. */ 13433965Sjdp}; 13533965Sjdp 13633965Sjdp#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) 13733965Sjdp#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) 13833965Sjdp 13933965Sjdpstatic const struct optable 14033965Sjdp{ 14189857Sobrien const char *const in; 14289857Sobrien const char *const out; 14389857Sobrien const int flags; 14433965Sjdp} optable[] = { 14533965Sjdp {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ 14633965Sjdp {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ 14733965Sjdp {"new", " new", 0}, /* old (1.91, and 1.x) */ 14833965Sjdp {"delete", " delete", 0}, /* old (1.91, and 1.x) */ 14933965Sjdp {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ 15033965Sjdp {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ 15133965Sjdp {"as", "=", DMGL_ANSI}, /* ansi */ 15233965Sjdp {"ne", "!=", DMGL_ANSI}, /* old, ansi */ 15333965Sjdp {"eq", "==", DMGL_ANSI}, /* old, ansi */ 15433965Sjdp {"ge", ">=", DMGL_ANSI}, /* old, ansi */ 15533965Sjdp {"gt", ">", DMGL_ANSI}, /* old, ansi */ 15633965Sjdp {"le", "<=", DMGL_ANSI}, /* old, ansi */ 15733965Sjdp {"lt", "<", DMGL_ANSI}, /* old, ansi */ 15833965Sjdp {"plus", "+", 0}, /* old */ 15933965Sjdp {"pl", "+", DMGL_ANSI}, /* ansi */ 16033965Sjdp {"apl", "+=", DMGL_ANSI}, /* ansi */ 16133965Sjdp {"minus", "-", 0}, /* old */ 16233965Sjdp {"mi", "-", DMGL_ANSI}, /* ansi */ 16333965Sjdp {"ami", "-=", DMGL_ANSI}, /* ansi */ 16433965Sjdp {"mult", "*", 0}, /* old */ 16533965Sjdp {"ml", "*", DMGL_ANSI}, /* ansi */ 16633965Sjdp {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ 16733965Sjdp {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ 16833965Sjdp {"convert", "+", 0}, /* old (unary +) */ 16933965Sjdp {"negate", "-", 0}, /* old (unary -) */ 17033965Sjdp {"trunc_mod", "%", 0}, /* old */ 17133965Sjdp {"md", "%", DMGL_ANSI}, /* ansi */ 17233965Sjdp {"amd", "%=", DMGL_ANSI}, /* ansi */ 17333965Sjdp {"trunc_div", "/", 0}, /* old */ 17433965Sjdp {"dv", "/", DMGL_ANSI}, /* ansi */ 17533965Sjdp {"adv", "/=", DMGL_ANSI}, /* ansi */ 17633965Sjdp {"truth_andif", "&&", 0}, /* old */ 17733965Sjdp {"aa", "&&", DMGL_ANSI}, /* ansi */ 17833965Sjdp {"truth_orif", "||", 0}, /* old */ 17933965Sjdp {"oo", "||", DMGL_ANSI}, /* ansi */ 18033965Sjdp {"truth_not", "!", 0}, /* old */ 18133965Sjdp {"nt", "!", DMGL_ANSI}, /* ansi */ 18233965Sjdp {"postincrement","++", 0}, /* old */ 18333965Sjdp {"pp", "++", DMGL_ANSI}, /* ansi */ 18433965Sjdp {"postdecrement","--", 0}, /* old */ 18533965Sjdp {"mm", "--", DMGL_ANSI}, /* ansi */ 18633965Sjdp {"bit_ior", "|", 0}, /* old */ 18733965Sjdp {"or", "|", DMGL_ANSI}, /* ansi */ 18833965Sjdp {"aor", "|=", DMGL_ANSI}, /* ansi */ 18933965Sjdp {"bit_xor", "^", 0}, /* old */ 19033965Sjdp {"er", "^", DMGL_ANSI}, /* ansi */ 19133965Sjdp {"aer", "^=", DMGL_ANSI}, /* ansi */ 19233965Sjdp {"bit_and", "&", 0}, /* old */ 19333965Sjdp {"ad", "&", DMGL_ANSI}, /* ansi */ 19433965Sjdp {"aad", "&=", DMGL_ANSI}, /* ansi */ 19533965Sjdp {"bit_not", "~", 0}, /* old */ 19633965Sjdp {"co", "~", DMGL_ANSI}, /* ansi */ 19733965Sjdp {"call", "()", 0}, /* old */ 19833965Sjdp {"cl", "()", DMGL_ANSI}, /* ansi */ 19933965Sjdp {"alshift", "<<", 0}, /* old */ 20033965Sjdp {"ls", "<<", DMGL_ANSI}, /* ansi */ 20133965Sjdp {"als", "<<=", DMGL_ANSI}, /* ansi */ 20233965Sjdp {"arshift", ">>", 0}, /* old */ 20333965Sjdp {"rs", ">>", DMGL_ANSI}, /* ansi */ 20433965Sjdp {"ars", ">>=", DMGL_ANSI}, /* ansi */ 20533965Sjdp {"component", "->", 0}, /* old */ 20633965Sjdp {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ 20733965Sjdp {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ 20833965Sjdp {"indirect", "*", 0}, /* old */ 20933965Sjdp {"method_call", "->()", 0}, /* old */ 21033965Sjdp {"addr", "&", 0}, /* old (unary &) */ 21133965Sjdp {"array", "[]", 0}, /* old */ 21233965Sjdp {"vc", "[]", DMGL_ANSI}, /* ansi */ 21333965Sjdp {"compound", ", ", 0}, /* old */ 21433965Sjdp {"cm", ", ", DMGL_ANSI}, /* ansi */ 21533965Sjdp {"cond", "?:", 0}, /* old */ 21633965Sjdp {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ 21733965Sjdp {"max", ">?", 0}, /* old */ 21833965Sjdp {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ 21933965Sjdp {"min", "<?", 0}, /* old */ 22033965Sjdp {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ 22133965Sjdp {"nop", "", 0}, /* old (for operator=) */ 22260484Sobrien {"rm", "->*", DMGL_ANSI}, /* ansi */ 22360484Sobrien {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ 22433965Sjdp}; 22533965Sjdp 22660484Sobrien/* These values are used to indicate the various type varieties. 22760484Sobrien They are all non-zero so that they can be used as `success' 22860484Sobrien values. */ 22960484Sobrientypedef enum type_kind_t 23060484Sobrien{ 23160484Sobrien tk_none, 23260484Sobrien tk_pointer, 23360484Sobrien tk_reference, 23460484Sobrien tk_integral, 23560484Sobrien tk_bool, 23660484Sobrien tk_char, 23760484Sobrien tk_real 23860484Sobrien} type_kind_t; 23933965Sjdp 24089857Sobrienconst struct demangler_engine libiberty_demanglers[] = 24168765Sobrien{ 24268765Sobrien { 24389857Sobrien NO_DEMANGLING_STYLE_STRING, 24489857Sobrien no_demangling, 24589857Sobrien "Demangling disabled" 24689857Sobrien } 24789857Sobrien , 24889857Sobrien { 24968765Sobrien AUTO_DEMANGLING_STYLE_STRING, 25068765Sobrien auto_demangling, 25168765Sobrien "Automatic selection based on executable" 25268765Sobrien } 25368765Sobrien , 25468765Sobrien { 25568765Sobrien GNU_DEMANGLING_STYLE_STRING, 25668765Sobrien gnu_demangling, 25768765Sobrien "GNU (g++) style demangling" 25868765Sobrien } 25968765Sobrien , 26068765Sobrien { 26168765Sobrien LUCID_DEMANGLING_STYLE_STRING, 26268765Sobrien lucid_demangling, 26368765Sobrien "Lucid (lcc) style demangling" 26468765Sobrien } 26568765Sobrien , 26668765Sobrien { 26768765Sobrien ARM_DEMANGLING_STYLE_STRING, 26868765Sobrien arm_demangling, 26968765Sobrien "ARM style demangling" 27068765Sobrien } 27168765Sobrien , 27268765Sobrien { 27368765Sobrien HP_DEMANGLING_STYLE_STRING, 27468765Sobrien hp_demangling, 27568765Sobrien "HP (aCC) style demangling" 27668765Sobrien } 27768765Sobrien , 27868765Sobrien { 27968765Sobrien EDG_DEMANGLING_STYLE_STRING, 28068765Sobrien edg_demangling, 28168765Sobrien "EDG style demangling" 28268765Sobrien } 28368765Sobrien , 28468765Sobrien { 28577298Sobrien GNU_V3_DEMANGLING_STYLE_STRING, 28677298Sobrien gnu_v3_demangling, 28777298Sobrien "GNU (g++) V3 ABI-style demangling" 28868765Sobrien } 28968765Sobrien , 29068765Sobrien { 29177298Sobrien JAVA_DEMANGLING_STYLE_STRING, 29277298Sobrien java_demangling, 29377298Sobrien "Java style demangling" 29477298Sobrien } 29577298Sobrien , 29677298Sobrien { 29777298Sobrien GNAT_DEMANGLING_STYLE_STRING, 29877298Sobrien gnat_demangling, 29977298Sobrien "GNAT style demangling" 30077298Sobrien } 30177298Sobrien , 30277298Sobrien { 30368765Sobrien NULL, unknown_demangling, NULL 30468765Sobrien } 30568765Sobrien}; 30668765Sobrien 30733965Sjdp#define STRING_EMPTY(str) ((str) -> b == (str) -> p) 30833965Sjdp#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ 30933965Sjdp string_prepend(str, " ");} 31033965Sjdp#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ 31133965Sjdp string_append(str, " ");} 31260484Sobrien#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) 31333965Sjdp 31460484Sobrien/* The scope separator appropriate for the language being demangled. */ 31560484Sobrien 31660484Sobrien#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::") 31760484Sobrien 31833965Sjdp#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ 31933965Sjdp#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ 32033965Sjdp 32133965Sjdp/* Prototypes for local functions */ 32233965Sjdp 32368765Sobrienstatic void 32468765Sobriendelete_work_stuff PARAMS ((struct work_stuff *)); 32568765Sobrien 32668765Sobrienstatic void 32768765Sobriendelete_non_B_K_work_stuff PARAMS ((struct work_stuff *)); 32868765Sobrien 32933965Sjdpstatic char * 33033965Sjdpmop_up PARAMS ((struct work_stuff *, string *, int)); 33133965Sjdp 33260484Sobrienstatic void 33360484Sobriensquangle_mop_up PARAMS ((struct work_stuff *)); 33460484Sobrien 33568765Sobrienstatic void 33668765Sobrienwork_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *)); 33768765Sobrien 33833965Sjdp#if 0 33933965Sjdpstatic int 34060484Sobriendemangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); 34133965Sjdp#endif 34233965Sjdp 34360484Sobrienstatic char * 34460484Sobrieninternal_cplus_demangle PARAMS ((struct work_stuff *, const char *)); 34560484Sobrien 34633965Sjdpstatic int 34760484Sobriendemangle_template_template_parm PARAMS ((struct work_stuff *work, 34860484Sobrien const char **, string *)); 34960484Sobrien 35060484Sobrienstatic int 35133965Sjdpdemangle_template PARAMS ((struct work_stuff *work, const char **, string *, 35260484Sobrien string *, int, int)); 35333965Sjdp 35433965Sjdpstatic int 35533965Sjdparm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, 35633965Sjdp const char **)); 35733965Sjdp 35833965Sjdpstatic int 35933965Sjdpdemangle_class_name PARAMS ((struct work_stuff *, const char **, string *)); 36033965Sjdp 36133965Sjdpstatic int 36233965Sjdpdemangle_qualified PARAMS ((struct work_stuff *, const char **, string *, 36333965Sjdp int, int)); 36433965Sjdp 36533965Sjdpstatic int 36633965Sjdpdemangle_class PARAMS ((struct work_stuff *, const char **, string *)); 36733965Sjdp 36833965Sjdpstatic int 36933965Sjdpdemangle_fund_type PARAMS ((struct work_stuff *, const char **, string *)); 37033965Sjdp 37133965Sjdpstatic int 37233965Sjdpdemangle_signature PARAMS ((struct work_stuff *, const char **, string *)); 37333965Sjdp 37433965Sjdpstatic int 37533965Sjdpdemangle_prefix PARAMS ((struct work_stuff *, const char **, string *)); 37633965Sjdp 37733965Sjdpstatic int 37833965Sjdpgnu_special PARAMS ((struct work_stuff *, const char **, string *)); 37933965Sjdp 38033965Sjdpstatic int 38160484Sobrienarm_special PARAMS ((const char **, string *)); 38233965Sjdp 38333965Sjdpstatic void 38433965Sjdpstring_need PARAMS ((string *, int)); 38533965Sjdp 38633965Sjdpstatic void 38733965Sjdpstring_delete PARAMS ((string *)); 38833965Sjdp 38933965Sjdpstatic void 39033965Sjdpstring_init PARAMS ((string *)); 39133965Sjdp 39233965Sjdpstatic void 39333965Sjdpstring_clear PARAMS ((string *)); 39433965Sjdp 39533965Sjdp#if 0 39633965Sjdpstatic int 39733965Sjdpstring_empty PARAMS ((string *)); 39833965Sjdp#endif 39933965Sjdp 40033965Sjdpstatic void 40133965Sjdpstring_append PARAMS ((string *, const char *)); 40233965Sjdp 40333965Sjdpstatic void 40433965Sjdpstring_appends PARAMS ((string *, string *)); 40533965Sjdp 40633965Sjdpstatic void 40733965Sjdpstring_appendn PARAMS ((string *, const char *, int)); 40833965Sjdp 40933965Sjdpstatic void 41033965Sjdpstring_prepend PARAMS ((string *, const char *)); 41133965Sjdp 41233965Sjdpstatic void 41333965Sjdpstring_prependn PARAMS ((string *, const char *, int)); 41433965Sjdp 41560484Sobrienstatic void 41660484Sobrienstring_append_template_idx PARAMS ((string *, int)); 41760484Sobrien 41833965Sjdpstatic int 41933965Sjdpget_count PARAMS ((const char **, int *)); 42033965Sjdp 42133965Sjdpstatic int 42233965Sjdpconsume_count PARAMS ((const char **)); 42333965Sjdp 42460484Sobrienstatic int 42538889Sjdpconsume_count_with_underscores PARAMS ((const char**)); 42638889Sjdp 42733965Sjdpstatic int 42833965Sjdpdemangle_args PARAMS ((struct work_stuff *, const char **, string *)); 42933965Sjdp 43033965Sjdpstatic int 43160484Sobriendemangle_nested_args PARAMS ((struct work_stuff*, const char**, string*)); 43260484Sobrien 43360484Sobrienstatic int 43433965Sjdpdo_type PARAMS ((struct work_stuff *, const char **, string *)); 43533965Sjdp 43633965Sjdpstatic int 43733965Sjdpdo_arg PARAMS ((struct work_stuff *, const char **, string *)); 43833965Sjdp 43933965Sjdpstatic void 44033965Sjdpdemangle_function_name PARAMS ((struct work_stuff *, const char **, string *, 44133965Sjdp const char *)); 44233965Sjdp 44368765Sobrienstatic int 44468765Sobrieniterate_demangle_function PARAMS ((struct work_stuff *, 44568765Sobrien const char **, string *, const char *)); 44668765Sobrien 44733965Sjdpstatic void 44833965Sjdpremember_type PARAMS ((struct work_stuff *, const char *, int)); 44933965Sjdp 45033965Sjdpstatic void 45160484Sobrienremember_Btype PARAMS ((struct work_stuff *, const char *, int, int)); 45260484Sobrien 45360484Sobrienstatic int 45460484Sobrienregister_Btype PARAMS ((struct work_stuff *)); 45560484Sobrien 45660484Sobrienstatic void 45760484Sobrienremember_Ktype PARAMS ((struct work_stuff *, const char *, int)); 45860484Sobrien 45960484Sobrienstatic void 46033965Sjdpforget_types PARAMS ((struct work_stuff *)); 46133965Sjdp 46233965Sjdpstatic void 46360484Sobrienforget_B_and_K_types PARAMS ((struct work_stuff *)); 46460484Sobrien 46560484Sobrienstatic void 46633965Sjdpstring_prepends PARAMS ((string *, string *)); 46733965Sjdp 46860484Sobrienstatic int 46960484Sobriendemangle_template_value_parm PARAMS ((struct work_stuff*, const char**, 47060484Sobrien string*, type_kind_t)); 47133965Sjdp 47233965Sjdpstatic int 47360484Sobriendo_hpacc_template_const_value PARAMS ((struct work_stuff *, const char **, string *)); 47460484Sobrien 47560484Sobrienstatic int 47660484Sobriendo_hpacc_template_literal PARAMS ((struct work_stuff *, const char **, string *)); 47760484Sobrien 47860484Sobrienstatic int 47960484Sobriensnarf_numeric_literal PARAMS ((const char **, string *)); 48060484Sobrien 48160484Sobrien/* There is a TYPE_QUAL value for each type qualifier. They can be 48260484Sobrien combined by bitwise-or to form the complete set of qualifiers for a 48360484Sobrien type. */ 48460484Sobrien 48560484Sobrien#define TYPE_UNQUALIFIED 0x0 48660484Sobrien#define TYPE_QUAL_CONST 0x1 48760484Sobrien#define TYPE_QUAL_VOLATILE 0x2 48860484Sobrien#define TYPE_QUAL_RESTRICT 0x4 48960484Sobrien 49060484Sobrienstatic int 49160484Sobriencode_for_qualifier PARAMS ((int)); 49260484Sobrien 49360484Sobrienstatic const char* 49460484Sobrienqualifier_string PARAMS ((int)); 49560484Sobrien 49660484Sobrienstatic const char* 49760484Sobriendemangle_qualifier PARAMS ((int)); 49860484Sobrien 49960484Sobrienstatic int 50060484Sobriendemangle_expression PARAMS ((struct work_stuff *, const char **, string *, 50160484Sobrien type_kind_t)); 50260484Sobrien 50360484Sobrienstatic int 50460484Sobriendemangle_integral_value PARAMS ((struct work_stuff *, const char **, 50560484Sobrien string *)); 50660484Sobrien 50760484Sobrienstatic int 50860484Sobriendemangle_real_value PARAMS ((struct work_stuff *, const char **, string *)); 50960484Sobrien 51060484Sobrienstatic void 51160484Sobriendemangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int, 51260484Sobrien string *)); 51360484Sobrien 51460484Sobrienstatic void 51560484Sobrienrecursively_demangle PARAMS ((struct work_stuff *, const char **, string *, 51660484Sobrien int)); 51760484Sobrien 51877298Sobrienstatic void 51977298Sobriengrow_vect PARAMS ((void **, size_t *, size_t, int)); 52077298Sobrien 52160484Sobrien/* Translate count to integer, consuming tokens in the process. 52260484Sobrien Conversion terminates on the first non-digit character. 52360484Sobrien 52460484Sobrien Trying to consume something that isn't a count results in no 52560484Sobrien consumption of input and a return of -1. 52660484Sobrien 52760484Sobrien Overflow consumes the rest of the digits, and returns -1. */ 52860484Sobrien 52960484Sobrienstatic int 53033965Sjdpconsume_count (type) 53133965Sjdp const char **type; 53233965Sjdp{ 53333965Sjdp int count = 0; 53433965Sjdp 53577298Sobrien if (! ISDIGIT ((unsigned char)**type)) 53660484Sobrien return -1; 53760484Sobrien 53877298Sobrien while (ISDIGIT ((unsigned char)**type)) 53933965Sjdp { 54033965Sjdp count *= 10; 54160484Sobrien 54260484Sobrien /* Check for overflow. 54360484Sobrien We assume that count is represented using two's-complement; 54460484Sobrien no power of two is divisible by ten, so if an overflow occurs 54560484Sobrien when multiplying by ten, the result will not be a multiple of 54660484Sobrien ten. */ 54760484Sobrien if ((count % 10) != 0) 54860484Sobrien { 54977298Sobrien while (ISDIGIT ((unsigned char) **type)) 55060484Sobrien (*type)++; 55160484Sobrien return -1; 55260484Sobrien } 55360484Sobrien 55433965Sjdp count += **type - '0'; 55533965Sjdp (*type)++; 55633965Sjdp } 55760484Sobrien 55889857Sobrien if (count < 0) 55989857Sobrien count = -1; 56089857Sobrien 56133965Sjdp return (count); 56233965Sjdp} 56333965Sjdp 56438889Sjdp 56560484Sobrien/* Like consume_count, but for counts that are preceded and followed 56638889Sjdp by '_' if they are greater than 10. Also, -1 is returned for 56738889Sjdp failure, since 0 can be a valid value. */ 56838889Sjdp 56938889Sjdpstatic int 57038889Sjdpconsume_count_with_underscores (mangled) 57138889Sjdp const char **mangled; 57238889Sjdp{ 57338889Sjdp int idx; 57438889Sjdp 57538889Sjdp if (**mangled == '_') 57638889Sjdp { 57738889Sjdp (*mangled)++; 57877298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 57938889Sjdp return -1; 58038889Sjdp 58138889Sjdp idx = consume_count (mangled); 58238889Sjdp if (**mangled != '_') 58338889Sjdp /* The trailing underscore was missing. */ 58438889Sjdp return -1; 58560484Sobrien 58638889Sjdp (*mangled)++; 58738889Sjdp } 58838889Sjdp else 58938889Sjdp { 59038889Sjdp if (**mangled < '0' || **mangled > '9') 59138889Sjdp return -1; 59260484Sobrien 59338889Sjdp idx = **mangled - '0'; 59438889Sjdp (*mangled)++; 59538889Sjdp } 59638889Sjdp 59738889Sjdp return idx; 59838889Sjdp} 59938889Sjdp 60060484Sobrien/* C is the code for a type-qualifier. Return the TYPE_QUAL 60160484Sobrien corresponding to this qualifier. */ 60260484Sobrien 60360484Sobrienstatic int 60460484Sobriencode_for_qualifier (c) 60560484Sobrien int c; 60660484Sobrien{ 60760484Sobrien switch (c) 60860484Sobrien { 60960484Sobrien case 'C': 61060484Sobrien return TYPE_QUAL_CONST; 61160484Sobrien 61260484Sobrien case 'V': 61360484Sobrien return TYPE_QUAL_VOLATILE; 61460484Sobrien 61560484Sobrien case 'u': 61660484Sobrien return TYPE_QUAL_RESTRICT; 61760484Sobrien 61860484Sobrien default: 61960484Sobrien break; 62060484Sobrien } 62160484Sobrien 62260484Sobrien /* C was an invalid qualifier. */ 62360484Sobrien abort (); 62460484Sobrien} 62560484Sobrien 62660484Sobrien/* Return the string corresponding to the qualifiers given by 62760484Sobrien TYPE_QUALS. */ 62860484Sobrien 62960484Sobrienstatic const char* 63060484Sobrienqualifier_string (type_quals) 63160484Sobrien int type_quals; 63260484Sobrien{ 63360484Sobrien switch (type_quals) 63460484Sobrien { 63560484Sobrien case TYPE_UNQUALIFIED: 63660484Sobrien return ""; 63760484Sobrien 63860484Sobrien case TYPE_QUAL_CONST: 63960484Sobrien return "const"; 64060484Sobrien 64160484Sobrien case TYPE_QUAL_VOLATILE: 64260484Sobrien return "volatile"; 64360484Sobrien 64460484Sobrien case TYPE_QUAL_RESTRICT: 64560484Sobrien return "__restrict"; 64660484Sobrien 64760484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: 64860484Sobrien return "const volatile"; 64960484Sobrien 65060484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: 65160484Sobrien return "const __restrict"; 65260484Sobrien 65360484Sobrien case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 65460484Sobrien return "volatile __restrict"; 65560484Sobrien 65660484Sobrien case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: 65760484Sobrien return "const volatile __restrict"; 65860484Sobrien 65960484Sobrien default: 66060484Sobrien break; 66160484Sobrien } 66260484Sobrien 66360484Sobrien /* TYPE_QUALS was an invalid qualifier set. */ 66460484Sobrien abort (); 66560484Sobrien} 66660484Sobrien 66760484Sobrien/* C is the code for a type-qualifier. Return the string 66860484Sobrien corresponding to this qualifier. This function should only be 66960484Sobrien called with a valid qualifier code. */ 67060484Sobrien 67160484Sobrienstatic const char* 67260484Sobriendemangle_qualifier (c) 67360484Sobrien int c; 67460484Sobrien{ 67560484Sobrien return qualifier_string (code_for_qualifier (c)); 67660484Sobrien} 67760484Sobrien 67833965Sjdpint 67933965Sjdpcplus_demangle_opname (opname, result, options) 68033965Sjdp const char *opname; 68133965Sjdp char *result; 68233965Sjdp int options; 68333965Sjdp{ 68460484Sobrien int len, len1, ret; 68533965Sjdp string type; 68633965Sjdp struct work_stuff work[1]; 68733965Sjdp const char *tem; 68833965Sjdp 68933965Sjdp len = strlen(opname); 69033965Sjdp result[0] = '\0'; 69133965Sjdp ret = 0; 69260484Sobrien memset ((char *) work, 0, sizeof (work)); 69333965Sjdp work->options = options; 69460484Sobrien 69533965Sjdp if (opname[0] == '_' && opname[1] == '_' 69633965Sjdp && opname[2] == 'o' && opname[3] == 'p') 69733965Sjdp { 69833965Sjdp /* ANSI. */ 69933965Sjdp /* type conversion operator. */ 70033965Sjdp tem = opname + 4; 70133965Sjdp if (do_type (work, &tem, &type)) 70233965Sjdp { 70333965Sjdp strcat (result, "operator "); 70433965Sjdp strncat (result, type.b, type.p - type.b); 70533965Sjdp string_delete (&type); 70633965Sjdp ret = 1; 70733965Sjdp } 70833965Sjdp } 70933965Sjdp else if (opname[0] == '_' && opname[1] == '_' 71077298Sobrien && ISLOWER((unsigned char)opname[2]) 71177298Sobrien && ISLOWER((unsigned char)opname[3])) 71233965Sjdp { 71333965Sjdp if (opname[4] == '\0') 71433965Sjdp { 71533965Sjdp /* Operator. */ 71660484Sobrien size_t i; 71777298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 71833965Sjdp { 71933965Sjdp if (strlen (optable[i].in) == 2 72033965Sjdp && memcmp (optable[i].in, opname + 2, 2) == 0) 72133965Sjdp { 72233965Sjdp strcat (result, "operator"); 72333965Sjdp strcat (result, optable[i].out); 72433965Sjdp ret = 1; 72533965Sjdp break; 72633965Sjdp } 72733965Sjdp } 72833965Sjdp } 72933965Sjdp else 73033965Sjdp { 73133965Sjdp if (opname[2] == 'a' && opname[5] == '\0') 73233965Sjdp { 73333965Sjdp /* Assignment. */ 73460484Sobrien size_t i; 73577298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 73633965Sjdp { 73733965Sjdp if (strlen (optable[i].in) == 3 73833965Sjdp && memcmp (optable[i].in, opname + 2, 3) == 0) 73933965Sjdp { 74033965Sjdp strcat (result, "operator"); 74133965Sjdp strcat (result, optable[i].out); 74233965Sjdp ret = 1; 74333965Sjdp break; 74460484Sobrien } 74533965Sjdp } 74633965Sjdp } 74733965Sjdp } 74833965Sjdp } 74960484Sobrien else if (len >= 3 75033965Sjdp && opname[0] == 'o' 75133965Sjdp && opname[1] == 'p' 75233965Sjdp && strchr (cplus_markers, opname[2]) != NULL) 75333965Sjdp { 75433965Sjdp /* see if it's an assignment expression */ 75533965Sjdp if (len >= 10 /* op$assign_ */ 75633965Sjdp && memcmp (opname + 3, "assign_", 7) == 0) 75733965Sjdp { 75860484Sobrien size_t i; 75977298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 76033965Sjdp { 76133965Sjdp len1 = len - 10; 76260484Sobrien if ((int) strlen (optable[i].in) == len1 76333965Sjdp && memcmp (optable[i].in, opname + 10, len1) == 0) 76433965Sjdp { 76533965Sjdp strcat (result, "operator"); 76633965Sjdp strcat (result, optable[i].out); 76733965Sjdp strcat (result, "="); 76833965Sjdp ret = 1; 76933965Sjdp break; 77033965Sjdp } 77133965Sjdp } 77233965Sjdp } 77333965Sjdp else 77433965Sjdp { 77560484Sobrien size_t i; 77677298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 77733965Sjdp { 77833965Sjdp len1 = len - 3; 77960484Sobrien if ((int) strlen (optable[i].in) == len1 78033965Sjdp && memcmp (optable[i].in, opname + 3, len1) == 0) 78133965Sjdp { 78233965Sjdp strcat (result, "operator"); 78333965Sjdp strcat (result, optable[i].out); 78433965Sjdp ret = 1; 78533965Sjdp break; 78633965Sjdp } 78733965Sjdp } 78833965Sjdp } 78933965Sjdp } 79033965Sjdp else if (len >= 5 && memcmp (opname, "type", 4) == 0 79133965Sjdp && strchr (cplus_markers, opname[4]) != NULL) 79233965Sjdp { 79333965Sjdp /* type conversion operator */ 79433965Sjdp tem = opname + 5; 79533965Sjdp if (do_type (work, &tem, &type)) 79633965Sjdp { 79733965Sjdp strcat (result, "operator "); 79833965Sjdp strncat (result, type.b, type.p - type.b); 79933965Sjdp string_delete (&type); 80033965Sjdp ret = 1; 80133965Sjdp } 80233965Sjdp } 80360484Sobrien squangle_mop_up (work); 80433965Sjdp return ret; 80533965Sjdp 80633965Sjdp} 80768765Sobrien 80833965Sjdp/* Takes operator name as e.g. "++" and returns mangled 80933965Sjdp operator name (e.g. "postincrement_expr"), or NULL if not found. 81033965Sjdp 81133965Sjdp If OPTIONS & DMGL_ANSI == 1, return the ANSI name; 81233965Sjdp if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ 81333965Sjdp 81433965Sjdpconst char * 81533965Sjdpcplus_mangle_opname (opname, options) 81633965Sjdp const char *opname; 81733965Sjdp int options; 81833965Sjdp{ 81960484Sobrien size_t i; 82033965Sjdp int len; 82133965Sjdp 82233965Sjdp len = strlen (opname); 82377298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 82433965Sjdp { 82560484Sobrien if ((int) strlen (optable[i].out) == len 82633965Sjdp && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) 82733965Sjdp && memcmp (optable[i].out, opname, len) == 0) 82833965Sjdp return optable[i].in; 82933965Sjdp } 83033965Sjdp return (0); 83133965Sjdp} 83233965Sjdp 83368765Sobrien/* Add a routine to set the demangling style to be sure it is valid and 83468765Sobrien allow for any demangler initialization that maybe necessary. */ 83568765Sobrien 83668765Sobrienenum demangling_styles 83768765Sobriencplus_demangle_set_style (style) 83868765Sobrien enum demangling_styles style; 83968765Sobrien{ 84089857Sobrien const struct demangler_engine *demangler = libiberty_demanglers; 84168765Sobrien 84268765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 84368765Sobrien if (style == demangler->demangling_style) 84468765Sobrien { 84568765Sobrien current_demangling_style = style; 84668765Sobrien return current_demangling_style; 84768765Sobrien } 84868765Sobrien 84968765Sobrien return unknown_demangling; 85068765Sobrien} 85168765Sobrien 85268765Sobrien/* Do string name to style translation */ 85368765Sobrien 85468765Sobrienenum demangling_styles 85568765Sobriencplus_demangle_name_to_style (name) 85668765Sobrien const char *name; 85768765Sobrien{ 85889857Sobrien const struct demangler_engine *demangler = libiberty_demanglers; 85968765Sobrien 86068765Sobrien for (; demangler->demangling_style != unknown_demangling; ++demangler) 86168765Sobrien if (strcmp (name, demangler->demangling_style_name) == 0) 86268765Sobrien return demangler->demangling_style; 86368765Sobrien 86468765Sobrien return unknown_demangling; 86568765Sobrien} 86668765Sobrien 86733965Sjdp/* char *cplus_demangle (const char *mangled, int options) 86833965Sjdp 86933965Sjdp If MANGLED is a mangled function name produced by GNU C++, then 87089857Sobrien a pointer to a @code{malloc}ed string giving a C++ representation 87133965Sjdp of the name will be returned; otherwise NULL will be returned. 87233965Sjdp It is the caller's responsibility to free the string which 87333965Sjdp is returned. 87433965Sjdp 87533965Sjdp The OPTIONS arg may contain one or more of the following bits: 87633965Sjdp 87733965Sjdp DMGL_ANSI ANSI qualifiers such as `const' and `void' are 87833965Sjdp included. 87933965Sjdp DMGL_PARAMS Function parameters are included. 88033965Sjdp 88133965Sjdp For example, 88260484Sobrien 88333965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" 88433965Sjdp cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" 88533965Sjdp cplus_demangle ("foo__1Ai", 0) => "A::foo" 88633965Sjdp 88733965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" 88833965Sjdp cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" 88933965Sjdp cplus_demangle ("foo__1Afe", 0) => "A::foo" 89033965Sjdp 89133965Sjdp Note that any leading underscores, or other such characters prepended by 89233965Sjdp the compilation system, are presumed to have already been stripped from 89333965Sjdp MANGLED. */ 89433965Sjdp 89533965Sjdpchar * 89633965Sjdpcplus_demangle (mangled, options) 89733965Sjdp const char *mangled; 89833965Sjdp int options; 89933965Sjdp{ 90060484Sobrien char *ret; 90160484Sobrien struct work_stuff work[1]; 90289857Sobrien 90389857Sobrien if (current_demangling_style == no_demangling) 90489857Sobrien return xstrdup (mangled); 90589857Sobrien 90660484Sobrien memset ((char *) work, 0, sizeof (work)); 90777298Sobrien work->options = options; 90877298Sobrien if ((work->options & DMGL_STYLE_MASK) == 0) 90977298Sobrien work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; 91060484Sobrien 91177298Sobrien /* The V3 ABI demangling is implemented elsewhere. */ 91277298Sobrien if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) 91377298Sobrien { 91491041Sobrien ret = cplus_demangle_v3 (mangled, work->options); 91577298Sobrien if (ret || GNU_V3_DEMANGLING) 91677298Sobrien return ret; 91777298Sobrien } 91868765Sobrien 91989857Sobrien if (JAVA_DEMANGLING) 92089857Sobrien { 92189857Sobrien ret = java_demangle_v3 (mangled); 92289857Sobrien if (ret) 92389857Sobrien return ret; 92489857Sobrien } 92589857Sobrien 92677298Sobrien if (GNAT_DEMANGLING) 92777298Sobrien return ada_demangle(mangled,options); 92877298Sobrien 92960484Sobrien ret = internal_cplus_demangle (work, mangled); 93060484Sobrien squangle_mop_up (work); 93160484Sobrien return (ret); 93260484Sobrien} 93360484Sobrien 93460484Sobrien 93577298Sobrien/* Assuming *OLD_VECT points to an array of *SIZE objects of size 93677298Sobrien ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, 93777298Sobrien updating *OLD_VECT and *SIZE as necessary. */ 93877298Sobrien 93977298Sobrienstatic void 94077298Sobriengrow_vect (old_vect, size, min_size, element_size) 94177298Sobrien void **old_vect; 94277298Sobrien size_t *size; 94377298Sobrien size_t min_size; 94477298Sobrien int element_size; 94577298Sobrien{ 94677298Sobrien if (*size < min_size) 94777298Sobrien { 94877298Sobrien *size *= 2; 94977298Sobrien if (*size < min_size) 95077298Sobrien *size = min_size; 95177298Sobrien *old_vect = xrealloc (*old_vect, *size * element_size); 95277298Sobrien } 95377298Sobrien} 95477298Sobrien 95577298Sobrien/* Demangle ada names: 95677298Sobrien 1. Discard final __{DIGIT}+ or ${DIGIT}+ 95777298Sobrien 2. Convert other instances of embedded "__" to `.'. 95877298Sobrien 3. Discard leading _ada_. 95977298Sobrien 4. Remove everything after first ___ if it is followed by 'X'. 96077298Sobrien 5. Put symbols that should be suppressed in <...> brackets. 96177298Sobrien The resulting string is valid until the next call of ada_demangle. */ 96277298Sobrien 96377298Sobrienstatic char * 96477298Sobrienada_demangle (mangled, option) 96577298Sobrien const char *mangled; 96677298Sobrien int option ATTRIBUTE_UNUSED; 96777298Sobrien{ 96877298Sobrien int i, j; 96977298Sobrien int len0; 97077298Sobrien const char* p; 97177298Sobrien char *demangled = NULL; 97277298Sobrien int at_start_name; 97377298Sobrien int changed; 97477298Sobrien char *demangling_buffer = NULL; 97577298Sobrien size_t demangling_buffer_size = 0; 97677298Sobrien 97777298Sobrien changed = 0; 97877298Sobrien 97977298Sobrien if (strncmp (mangled, "_ada_", 5) == 0) 98077298Sobrien { 98177298Sobrien mangled += 5; 98277298Sobrien changed = 1; 98377298Sobrien } 98477298Sobrien 98577298Sobrien if (mangled[0] == '_' || mangled[0] == '<') 98677298Sobrien goto Suppress; 98777298Sobrien 98877298Sobrien p = strstr (mangled, "___"); 98977298Sobrien if (p == NULL) 99077298Sobrien len0 = strlen (mangled); 99177298Sobrien else 99277298Sobrien { 99377298Sobrien if (p[3] == 'X') 99477298Sobrien { 99577298Sobrien len0 = p - mangled; 99677298Sobrien changed = 1; 99777298Sobrien } 99877298Sobrien else 99977298Sobrien goto Suppress; 100077298Sobrien } 100177298Sobrien 100277298Sobrien /* Make demangled big enough for possible expansion by operator name. */ 100377298Sobrien grow_vect ((void **) &(demangling_buffer), 100477298Sobrien &demangling_buffer_size, 2 * len0 + 1, 100577298Sobrien sizeof (char)); 100677298Sobrien demangled = demangling_buffer; 100777298Sobrien 100877298Sobrien if (ISDIGIT ((unsigned char) mangled[len0 - 1])) { 100977298Sobrien for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1) 101077298Sobrien ; 101177298Sobrien if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') 101277298Sobrien { 101377298Sobrien len0 = i - 1; 101477298Sobrien changed = 1; 101577298Sobrien } 101677298Sobrien else if (mangled[i] == '$') 101777298Sobrien { 101877298Sobrien len0 = i; 101977298Sobrien changed = 1; 102077298Sobrien } 102177298Sobrien } 102277298Sobrien 102377298Sobrien for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]); 102477298Sobrien i += 1, j += 1) 102577298Sobrien demangled[j] = mangled[i]; 102677298Sobrien 102777298Sobrien at_start_name = 1; 102877298Sobrien while (i < len0) 102977298Sobrien { 103077298Sobrien at_start_name = 0; 103177298Sobrien 103277298Sobrien if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') 103377298Sobrien { 103477298Sobrien demangled[j] = '.'; 103577298Sobrien changed = at_start_name = 1; 103677298Sobrien i += 2; j += 1; 103777298Sobrien } 103877298Sobrien else 103977298Sobrien { 104077298Sobrien demangled[j] = mangled[i]; 104177298Sobrien i += 1; j += 1; 104277298Sobrien } 104377298Sobrien } 104477298Sobrien demangled[j] = '\000'; 104577298Sobrien 104677298Sobrien for (i = 0; demangled[i] != '\0'; i += 1) 104777298Sobrien if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ') 104877298Sobrien goto Suppress; 104977298Sobrien 105077298Sobrien if (! changed) 105177298Sobrien return NULL; 105277298Sobrien else 105377298Sobrien return demangled; 105477298Sobrien 105577298Sobrien Suppress: 105677298Sobrien grow_vect ((void **) &(demangling_buffer), 105777298Sobrien &demangling_buffer_size, strlen (mangled) + 3, 105877298Sobrien sizeof (char)); 105977298Sobrien demangled = demangling_buffer; 106077298Sobrien if (mangled[0] == '<') 106177298Sobrien strcpy (demangled, mangled); 106277298Sobrien else 106377298Sobrien sprintf (demangled, "<%s>", mangled); 106477298Sobrien 106577298Sobrien return demangled; 106677298Sobrien} 106777298Sobrien 106860484Sobrien/* This function performs most of what cplus_demangle use to do, but 106960484Sobrien to be able to demangle a name with a B, K or n code, we need to 107060484Sobrien have a longer term memory of what types have been seen. The original 107160484Sobrien now intializes and cleans up the squangle code info, while internal 107260484Sobrien calls go directly to this routine to avoid resetting that info. */ 107360484Sobrien 107460484Sobrienstatic char * 107560484Sobrieninternal_cplus_demangle (work, mangled) 107660484Sobrien struct work_stuff *work; 107760484Sobrien const char *mangled; 107860484Sobrien{ 107960484Sobrien 108033965Sjdp string decl; 108133965Sjdp int success = 0; 108233965Sjdp char *demangled = NULL; 108377298Sobrien int s1, s2, s3, s4; 108460484Sobrien s1 = work->constructor; 108560484Sobrien s2 = work->destructor; 108660484Sobrien s3 = work->static_type; 108760484Sobrien s4 = work->type_quals; 108860484Sobrien work->constructor = work->destructor = 0; 108960484Sobrien work->type_quals = TYPE_UNQUALIFIED; 109060484Sobrien work->dllimported = 0; 109133965Sjdp 109233965Sjdp if ((mangled != NULL) && (*mangled != '\0')) 109333965Sjdp { 109433965Sjdp string_init (&decl); 109533965Sjdp 109633965Sjdp /* First check to see if gnu style demangling is active and if the 109733965Sjdp string to be demangled contains a CPLUS_MARKER. If so, attempt to 109833965Sjdp recognize one of the gnu special forms rather than looking for a 109933965Sjdp standard prefix. In particular, don't worry about whether there 110033965Sjdp is a "__" string in the mangled string. Consider "_$_5__foo" for 110133965Sjdp example. */ 110233965Sjdp 110333965Sjdp if ((AUTO_DEMANGLING || GNU_DEMANGLING)) 110433965Sjdp { 110533965Sjdp success = gnu_special (work, &mangled, &decl); 110633965Sjdp } 110733965Sjdp if (!success) 110833965Sjdp { 110933965Sjdp success = demangle_prefix (work, &mangled, &decl); 111033965Sjdp } 111133965Sjdp if (success && (*mangled != '\0')) 111233965Sjdp { 111333965Sjdp success = demangle_signature (work, &mangled, &decl); 111433965Sjdp } 111533965Sjdp if (work->constructor == 2) 111633965Sjdp { 111760484Sobrien string_prepend (&decl, "global constructors keyed to "); 111833965Sjdp work->constructor = 0; 111933965Sjdp } 112033965Sjdp else if (work->destructor == 2) 112133965Sjdp { 112260484Sobrien string_prepend (&decl, "global destructors keyed to "); 112333965Sjdp work->destructor = 0; 112433965Sjdp } 112560484Sobrien else if (work->dllimported == 1) 112660484Sobrien { 112760484Sobrien string_prepend (&decl, "import stub for "); 112860484Sobrien work->dllimported = 0; 112960484Sobrien } 113033965Sjdp demangled = mop_up (work, &decl, success); 113133965Sjdp } 113260484Sobrien work->constructor = s1; 113360484Sobrien work->destructor = s2; 113460484Sobrien work->static_type = s3; 113560484Sobrien work->type_quals = s4; 113677298Sobrien return demangled; 113733965Sjdp} 113833965Sjdp 113960484Sobrien 114060484Sobrien/* Clear out and squangling related storage */ 114160484Sobrienstatic void 114260484Sobriensquangle_mop_up (work) 114360484Sobrien struct work_stuff *work; 114460484Sobrien{ 114560484Sobrien /* clean up the B and K type mangling types. */ 114660484Sobrien forget_B_and_K_types (work); 114760484Sobrien if (work -> btypevec != NULL) 114860484Sobrien { 114960484Sobrien free ((char *) work -> btypevec); 115060484Sobrien } 115160484Sobrien if (work -> ktypevec != NULL) 115260484Sobrien { 115360484Sobrien free ((char *) work -> ktypevec); 115460484Sobrien } 115560484Sobrien} 115660484Sobrien 115760484Sobrien 115868765Sobrien/* Copy the work state and storage. */ 115968765Sobrien 116068765Sobrienstatic void 116168765Sobrienwork_stuff_copy_to_from (to, from) 116268765Sobrien struct work_stuff *to; 116368765Sobrien struct work_stuff *from; 116468765Sobrien{ 116568765Sobrien int i; 116668765Sobrien 116768765Sobrien delete_work_stuff (to); 116868765Sobrien 116968765Sobrien /* Shallow-copy scalars. */ 117068765Sobrien memcpy (to, from, sizeof (*to)); 117168765Sobrien 117268765Sobrien /* Deep-copy dynamic storage. */ 117368765Sobrien if (from->typevec_size) 117468765Sobrien to->typevec 117568765Sobrien = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0])); 117668765Sobrien 117768765Sobrien for (i = 0; i < from->ntypes; i++) 117868765Sobrien { 117968765Sobrien int len = strlen (from->typevec[i]) + 1; 118068765Sobrien 118168765Sobrien to->typevec[i] = xmalloc (len); 118268765Sobrien memcpy (to->typevec[i], from->typevec[i], len); 118368765Sobrien } 118468765Sobrien 118568765Sobrien if (from->ksize) 118668765Sobrien to->ktypevec 118768765Sobrien = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0])); 118868765Sobrien 118968765Sobrien for (i = 0; i < from->numk; i++) 119068765Sobrien { 119168765Sobrien int len = strlen (from->ktypevec[i]) + 1; 119268765Sobrien 119368765Sobrien to->ktypevec[i] = xmalloc (len); 119468765Sobrien memcpy (to->ktypevec[i], from->ktypevec[i], len); 119568765Sobrien } 119668765Sobrien 119768765Sobrien if (from->bsize) 119868765Sobrien to->btypevec 119968765Sobrien = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0])); 120068765Sobrien 120168765Sobrien for (i = 0; i < from->numb; i++) 120268765Sobrien { 120368765Sobrien int len = strlen (from->btypevec[i]) + 1; 120468765Sobrien 120568765Sobrien to->btypevec[i] = xmalloc (len); 120668765Sobrien memcpy (to->btypevec[i], from->btypevec[i], len); 120768765Sobrien } 120868765Sobrien 120968765Sobrien if (from->ntmpl_args) 121068765Sobrien to->tmpl_argvec 121168765Sobrien = xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0])); 121268765Sobrien 121368765Sobrien for (i = 0; i < from->ntmpl_args; i++) 121468765Sobrien { 121568765Sobrien int len = strlen (from->tmpl_argvec[i]) + 1; 121668765Sobrien 121768765Sobrien to->tmpl_argvec[i] = xmalloc (len); 121868765Sobrien memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); 121968765Sobrien } 122068765Sobrien 122168765Sobrien if (from->previous_argument) 122268765Sobrien { 122368765Sobrien to->previous_argument = (string*) xmalloc (sizeof (string)); 122468765Sobrien string_init (to->previous_argument); 122568765Sobrien string_appends (to->previous_argument, from->previous_argument); 122668765Sobrien } 122768765Sobrien} 122868765Sobrien 122968765Sobrien 123068765Sobrien/* Delete dynamic stuff in work_stuff that is not to be re-used. */ 123168765Sobrien 123268765Sobrienstatic void 123368765Sobriendelete_non_B_K_work_stuff (work) 123433965Sjdp struct work_stuff *work; 123533965Sjdp{ 123633965Sjdp /* Discard the remembered types, if any. */ 123760484Sobrien 123833965Sjdp forget_types (work); 123933965Sjdp if (work -> typevec != NULL) 124033965Sjdp { 124133965Sjdp free ((char *) work -> typevec); 124260484Sobrien work -> typevec = NULL; 124360484Sobrien work -> typevec_size = 0; 124433965Sjdp } 124538889Sjdp if (work->tmpl_argvec) 124638889Sjdp { 124738889Sjdp int i; 124838889Sjdp 124938889Sjdp for (i = 0; i < work->ntmpl_args; i++) 125038889Sjdp if (work->tmpl_argvec[i]) 125138889Sjdp free ((char*) work->tmpl_argvec[i]); 125260484Sobrien 125338889Sjdp free ((char*) work->tmpl_argvec); 125460484Sobrien work->tmpl_argvec = NULL; 125538889Sjdp } 125660484Sobrien if (work->previous_argument) 125760484Sobrien { 125860484Sobrien string_delete (work->previous_argument); 125960484Sobrien free ((char*) work->previous_argument); 126060484Sobrien work->previous_argument = NULL; 126160484Sobrien } 126268765Sobrien} 126338889Sjdp 126468765Sobrien 126568765Sobrien/* Delete all dynamic storage in work_stuff. */ 126668765Sobrienstatic void 126768765Sobriendelete_work_stuff (work) 126868765Sobrien struct work_stuff *work; 126968765Sobrien{ 127068765Sobrien delete_non_B_K_work_stuff (work); 127168765Sobrien squangle_mop_up (work); 127268765Sobrien} 127368765Sobrien 127468765Sobrien 127568765Sobrien/* Clear out any mangled storage */ 127668765Sobrien 127768765Sobrienstatic char * 127868765Sobrienmop_up (work, declp, success) 127968765Sobrien struct work_stuff *work; 128068765Sobrien string *declp; 128168765Sobrien int success; 128268765Sobrien{ 128368765Sobrien char *demangled = NULL; 128468765Sobrien 128568765Sobrien delete_non_B_K_work_stuff (work); 128668765Sobrien 128733965Sjdp /* If demangling was successful, ensure that the demangled string is null 128833965Sjdp terminated and return it. Otherwise, free the demangling decl. */ 128960484Sobrien 129033965Sjdp if (!success) 129133965Sjdp { 129233965Sjdp string_delete (declp); 129333965Sjdp } 129433965Sjdp else 129533965Sjdp { 129633965Sjdp string_appendn (declp, "", 1); 129777298Sobrien demangled = declp->b; 129833965Sjdp } 129933965Sjdp return (demangled); 130033965Sjdp} 130133965Sjdp 130233965Sjdp/* 130333965Sjdp 130433965SjdpLOCAL FUNCTION 130533965Sjdp 130633965Sjdp demangle_signature -- demangle the signature part of a mangled name 130733965Sjdp 130833965SjdpSYNOPSIS 130933965Sjdp 131033965Sjdp static int 131133965Sjdp demangle_signature (struct work_stuff *work, const char **mangled, 131233965Sjdp string *declp); 131333965Sjdp 131433965SjdpDESCRIPTION 131533965Sjdp 131633965Sjdp Consume and demangle the signature portion of the mangled name. 131733965Sjdp 131833965Sjdp DECLP is the string where demangled output is being built. At 131933965Sjdp entry it contains the demangled root name from the mangled name 132033965Sjdp prefix. I.E. either a demangled operator name or the root function 132133965Sjdp name. In some special cases, it may contain nothing. 132233965Sjdp 132333965Sjdp *MANGLED points to the current unconsumed location in the mangled 132433965Sjdp name. As tokens are consumed and demangling is performed, the 132533965Sjdp pointer is updated to continuously point at the next token to 132633965Sjdp be consumed. 132733965Sjdp 132833965Sjdp Demangling GNU style mangled names is nasty because there is no 132933965Sjdp explicit token that marks the start of the outermost function 133033965Sjdp argument list. */ 133133965Sjdp 133233965Sjdpstatic int 133333965Sjdpdemangle_signature (work, mangled, declp) 133433965Sjdp struct work_stuff *work; 133533965Sjdp const char **mangled; 133633965Sjdp string *declp; 133733965Sjdp{ 133833965Sjdp int success = 1; 133933965Sjdp int func_done = 0; 134033965Sjdp int expect_func = 0; 134138889Sjdp int expect_return_type = 0; 134233965Sjdp const char *oldmangled = NULL; 134333965Sjdp string trawname; 134433965Sjdp string tname; 134533965Sjdp 134633965Sjdp while (success && (**mangled != '\0')) 134733965Sjdp { 134833965Sjdp switch (**mangled) 134933965Sjdp { 135033965Sjdp case 'Q': 135133965Sjdp oldmangled = *mangled; 135233965Sjdp success = demangle_qualified (work, mangled, declp, 1, 0); 135333965Sjdp if (success) 135460484Sobrien remember_type (work, oldmangled, *mangled - oldmangled); 135533965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 135660484Sobrien expect_func = 1; 135760484Sobrien oldmangled = NULL; 135860484Sobrien break; 135960484Sobrien 136060484Sobrien case 'K': 136160484Sobrien oldmangled = *mangled; 136260484Sobrien success = demangle_qualified (work, mangled, declp, 1, 0); 136360484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 136433965Sjdp { 136533965Sjdp expect_func = 1; 136633965Sjdp } 136733965Sjdp oldmangled = NULL; 136833965Sjdp break; 136960484Sobrien 137033965Sjdp case 'S': 137133965Sjdp /* Static member function */ 137233965Sjdp if (oldmangled == NULL) 137333965Sjdp { 137433965Sjdp oldmangled = *mangled; 137533965Sjdp } 137633965Sjdp (*mangled)++; 137733965Sjdp work -> static_type = 1; 137833965Sjdp break; 137933965Sjdp 138033965Sjdp case 'C': 138160484Sobrien case 'V': 138260484Sobrien case 'u': 138360484Sobrien work->type_quals |= code_for_qualifier (**mangled); 138460484Sobrien 138560484Sobrien /* a qualified member function */ 138633965Sjdp if (oldmangled == NULL) 138760484Sobrien oldmangled = *mangled; 138860484Sobrien (*mangled)++; 138960484Sobrien break; 139060484Sobrien 139160484Sobrien case 'L': 139260484Sobrien /* Local class name follows after "Lnnn_" */ 139360484Sobrien if (HP_DEMANGLING) 139433965Sjdp { 139560484Sobrien while (**mangled && (**mangled != '_')) 139660484Sobrien (*mangled)++; 139760484Sobrien if (!**mangled) 139860484Sobrien success = 0; 139960484Sobrien else 140060484Sobrien (*mangled)++; 140133965Sjdp } 140260484Sobrien else 140360484Sobrien success = 0; 140433965Sjdp break; 140560484Sobrien 140633965Sjdp case '0': case '1': case '2': case '3': case '4': 140733965Sjdp case '5': case '6': case '7': case '8': case '9': 140833965Sjdp if (oldmangled == NULL) 140933965Sjdp { 141033965Sjdp oldmangled = *mangled; 141133965Sjdp } 141260484Sobrien work->temp_start = -1; /* uppermost call to demangle_class */ 141333965Sjdp success = demangle_class (work, mangled, declp); 141433965Sjdp if (success) 141533965Sjdp { 141633965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 141733965Sjdp } 141860484Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) 141933965Sjdp { 142060484Sobrien /* EDG and others will have the "F", so we let the loop cycle 142160484Sobrien if we are looking at one. */ 142260484Sobrien if (**mangled != 'F') 142360484Sobrien expect_func = 1; 142433965Sjdp } 142533965Sjdp oldmangled = NULL; 142633965Sjdp break; 142760484Sobrien 142860484Sobrien case 'B': 142960484Sobrien { 143060484Sobrien string s; 143160484Sobrien success = do_type (work, mangled, &s); 143260484Sobrien if (success) 143360484Sobrien { 143460484Sobrien string_append (&s, SCOPE_STRING (work)); 143560484Sobrien string_prepends (declp, &s); 143660484Sobrien } 143760484Sobrien oldmangled = NULL; 143860484Sobrien expect_func = 1; 143960484Sobrien } 144060484Sobrien break; 144160484Sobrien 144233965Sjdp case 'F': 144333965Sjdp /* Function */ 144460484Sobrien /* ARM/HP style demangling includes a specific 'F' character after 144533965Sjdp the class name. For GNU style, it is just implied. So we can 144633965Sjdp safely just consume any 'F' at this point and be compatible 144733965Sjdp with either style. */ 144833965Sjdp 144933965Sjdp oldmangled = NULL; 145033965Sjdp func_done = 1; 145133965Sjdp (*mangled)++; 145233965Sjdp 145360484Sobrien /* For lucid/ARM/HP style we have to forget any types we might 145433965Sjdp have remembered up to this point, since they were not argument 145533965Sjdp types. GNU style considers all types seen as available for 145633965Sjdp back references. See comment in demangle_args() */ 145733965Sjdp 145860484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 145933965Sjdp { 146033965Sjdp forget_types (work); 146133965Sjdp } 146233965Sjdp success = demangle_args (work, mangled, declp); 146360484Sobrien /* After picking off the function args, we expect to either 146460484Sobrien find the function return type (preceded by an '_') or the 146560484Sobrien end of the string. */ 146660484Sobrien if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') 146760484Sobrien { 146860484Sobrien ++(*mangled); 146960484Sobrien /* At this level, we do not care about the return type. */ 147060484Sobrien success = do_type (work, mangled, &tname); 147160484Sobrien string_delete (&tname); 147260484Sobrien } 147360484Sobrien 147433965Sjdp break; 147560484Sobrien 147633965Sjdp case 't': 147733965Sjdp /* G++ Template */ 147860484Sobrien string_init(&trawname); 147933965Sjdp string_init(&tname); 148033965Sjdp if (oldmangled == NULL) 148133965Sjdp { 148233965Sjdp oldmangled = *mangled; 148333965Sjdp } 148460484Sobrien success = demangle_template (work, mangled, &tname, 148560484Sobrien &trawname, 1, 1); 148633965Sjdp if (success) 148733965Sjdp { 148833965Sjdp remember_type (work, oldmangled, *mangled - oldmangled); 148933965Sjdp } 149060484Sobrien string_append (&tname, SCOPE_STRING (work)); 149160484Sobrien 149233965Sjdp string_prepends(declp, &tname); 149333965Sjdp if (work -> destructor & 1) 149433965Sjdp { 149533965Sjdp string_prepend (&trawname, "~"); 149633965Sjdp string_appends (declp, &trawname); 149733965Sjdp work->destructor -= 1; 149833965Sjdp } 149933965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 150033965Sjdp { 150133965Sjdp string_appends (declp, &trawname); 150233965Sjdp work->constructor -= 1; 150333965Sjdp } 150433965Sjdp string_delete(&trawname); 150533965Sjdp string_delete(&tname); 150633965Sjdp oldmangled = NULL; 150733965Sjdp expect_func = 1; 150833965Sjdp break; 150933965Sjdp 151033965Sjdp case '_': 151168765Sobrien if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) 151238889Sjdp { 151338889Sjdp /* Read the return type. */ 151438889Sjdp string return_type; 151538889Sjdp string_init (&return_type); 151638889Sjdp 151738889Sjdp (*mangled)++; 151838889Sjdp success = do_type (work, mangled, &return_type); 151938889Sjdp APPEND_BLANK (&return_type); 152038889Sjdp 152138889Sjdp string_prepends (declp, &return_type); 152238889Sjdp string_delete (&return_type); 152338889Sjdp break; 152438889Sjdp } 152538889Sjdp else 152638889Sjdp /* At the outermost level, we cannot have a return type specified, 152738889Sjdp so if we run into another '_' at this point we are dealing with 152838889Sjdp a mangled name that is either bogus, or has been mangled by 152938889Sjdp some algorithm we don't know how to deal with. So just 153038889Sjdp reject the entire demangling. */ 153160484Sobrien /* However, "_nnn" is an expected suffix for alternate entry point 153260484Sobrien numbered nnn for a function, with HP aCC, so skip over that 153360484Sobrien without reporting failure. pai/1997-09-04 */ 153460484Sobrien if (HP_DEMANGLING) 153560484Sobrien { 153660484Sobrien (*mangled)++; 153777298Sobrien while (**mangled && ISDIGIT ((unsigned char)**mangled)) 153860484Sobrien (*mangled)++; 153960484Sobrien } 154060484Sobrien else 154160484Sobrien success = 0; 154233965Sjdp break; 154333965Sjdp 154438889Sjdp case 'H': 154568765Sobrien if (AUTO_DEMANGLING || GNU_DEMANGLING) 154638889Sjdp { 154738889Sjdp /* A G++ template function. Read the template arguments. */ 154860484Sobrien success = demangle_template (work, mangled, declp, 0, 0, 154960484Sobrien 0); 155038889Sjdp if (!(work->constructor & 1)) 155138889Sjdp expect_return_type = 1; 155238889Sjdp (*mangled)++; 155338889Sjdp break; 155438889Sjdp } 155538889Sjdp else 155638889Sjdp /* fall through */ 155760484Sobrien {;} 155838889Sjdp 155933965Sjdp default: 156033965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 156133965Sjdp { 156233965Sjdp /* Assume we have stumbled onto the first outermost function 156333965Sjdp argument token, and start processing args. */ 156433965Sjdp func_done = 1; 156533965Sjdp success = demangle_args (work, mangled, declp); 156633965Sjdp } 156733965Sjdp else 156833965Sjdp { 156933965Sjdp /* Non-GNU demanglers use a specific token to mark the start 157033965Sjdp of the outermost function argument tokens. Typically 'F', 157160484Sobrien for ARM/HP-demangling, for example. So if we find something 157233965Sjdp we are not prepared for, it must be an error. */ 157333965Sjdp success = 0; 157433965Sjdp } 157533965Sjdp break; 157633965Sjdp } 157733965Sjdp /* 157833965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 157933965Sjdp */ 158033965Sjdp { 158133965Sjdp if (success && expect_func) 158233965Sjdp { 158333965Sjdp func_done = 1; 158460484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) 158560484Sobrien { 158660484Sobrien forget_types (work); 158760484Sobrien } 158833965Sjdp success = demangle_args (work, mangled, declp); 158938889Sjdp /* Since template include the mangling of their return types, 159038889Sjdp we must set expect_func to 0 so that we don't try do 159138889Sjdp demangle more arguments the next time we get here. */ 159238889Sjdp expect_func = 0; 159333965Sjdp } 159433965Sjdp } 159533965Sjdp } 159633965Sjdp if (success && !func_done) 159733965Sjdp { 159833965Sjdp if (AUTO_DEMANGLING || GNU_DEMANGLING) 159933965Sjdp { 160033965Sjdp /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and 160133965Sjdp bar__3fooi is 'foo::bar(int)'. We get here when we find the 160233965Sjdp first case, and need to ensure that the '(void)' gets added to 160360484Sobrien the current declp. Note that with ARM/HP, the first case 160433965Sjdp represents the name of a static data member 'foo::bar', 160533965Sjdp which is in the current declp, so we leave it alone. */ 160633965Sjdp success = demangle_args (work, mangled, declp); 160733965Sjdp } 160833965Sjdp } 160960484Sobrien if (success && PRINT_ARG_TYPES) 161033965Sjdp { 161160484Sobrien if (work->static_type) 161260484Sobrien string_append (declp, " static"); 161360484Sobrien if (work->type_quals != TYPE_UNQUALIFIED) 161460484Sobrien { 161560484Sobrien APPEND_BLANK (declp); 161660484Sobrien string_append (declp, qualifier_string (work->type_quals)); 161760484Sobrien } 161833965Sjdp } 161960484Sobrien 162033965Sjdp return (success); 162133965Sjdp} 162233965Sjdp 162333965Sjdp#if 0 162433965Sjdp 162533965Sjdpstatic int 162633965Sjdpdemangle_method_args (work, mangled, declp) 162733965Sjdp struct work_stuff *work; 162833965Sjdp const char **mangled; 162933965Sjdp string *declp; 163033965Sjdp{ 163133965Sjdp int success = 0; 163233965Sjdp 163333965Sjdp if (work -> static_type) 163433965Sjdp { 163533965Sjdp string_append (declp, *mangled + 1); 163633965Sjdp *mangled += strlen (*mangled); 163733965Sjdp success = 1; 163833965Sjdp } 163933965Sjdp else 164033965Sjdp { 164133965Sjdp success = demangle_args (work, mangled, declp); 164233965Sjdp } 164333965Sjdp return (success); 164433965Sjdp} 164533965Sjdp 164633965Sjdp#endif 164733965Sjdp 164833965Sjdpstatic int 164960484Sobriendemangle_template_template_parm (work, mangled, tname) 165033965Sjdp struct work_stuff *work; 165133965Sjdp const char **mangled; 165233965Sjdp string *tname; 165360484Sobrien{ 165460484Sobrien int i; 165560484Sobrien int r; 165660484Sobrien int need_comma = 0; 165760484Sobrien int success = 1; 165860484Sobrien string temp; 165960484Sobrien 166060484Sobrien string_append (tname, "template <"); 166160484Sobrien /* get size of template parameter list */ 166260484Sobrien if (get_count (mangled, &r)) 166360484Sobrien { 166460484Sobrien for (i = 0; i < r; i++) 166560484Sobrien { 166660484Sobrien if (need_comma) 166760484Sobrien { 166860484Sobrien string_append (tname, ", "); 166960484Sobrien } 167060484Sobrien 167160484Sobrien /* Z for type parameters */ 167260484Sobrien if (**mangled == 'Z') 167360484Sobrien { 167460484Sobrien (*mangled)++; 167560484Sobrien string_append (tname, "class"); 167660484Sobrien } 167760484Sobrien /* z for template parameters */ 167860484Sobrien else if (**mangled == 'z') 167960484Sobrien { 168060484Sobrien (*mangled)++; 168160484Sobrien success = 168260484Sobrien demangle_template_template_parm (work, mangled, tname); 168360484Sobrien if (!success) 168460484Sobrien { 168560484Sobrien break; 168660484Sobrien } 168760484Sobrien } 168860484Sobrien else 168960484Sobrien { 169060484Sobrien /* temp is initialized in do_type */ 169160484Sobrien success = do_type (work, mangled, &temp); 169260484Sobrien if (success) 169360484Sobrien { 169460484Sobrien string_appends (tname, &temp); 169560484Sobrien } 169660484Sobrien string_delete(&temp); 169760484Sobrien if (!success) 169860484Sobrien { 169960484Sobrien break; 170060484Sobrien } 170160484Sobrien } 170260484Sobrien need_comma = 1; 170360484Sobrien } 170460484Sobrien 170560484Sobrien } 170660484Sobrien if (tname->p[-1] == '>') 170760484Sobrien string_append (tname, " "); 170860484Sobrien string_append (tname, "> class"); 170960484Sobrien return (success); 171060484Sobrien} 171160484Sobrien 171260484Sobrienstatic int 171360484Sobriendemangle_expression (work, mangled, s, tk) 171460484Sobrien struct work_stuff *work; 171560484Sobrien const char** mangled; 171660484Sobrien string* s; 171760484Sobrien type_kind_t tk; 171860484Sobrien{ 171960484Sobrien int need_operator = 0; 172060484Sobrien int success; 172160484Sobrien 172260484Sobrien success = 1; 172360484Sobrien string_appendn (s, "(", 1); 172460484Sobrien (*mangled)++; 172560484Sobrien while (success && **mangled != 'W' && **mangled != '\0') 172660484Sobrien { 172760484Sobrien if (need_operator) 172860484Sobrien { 172960484Sobrien size_t i; 173060484Sobrien size_t len; 173160484Sobrien 173260484Sobrien success = 0; 173360484Sobrien 173460484Sobrien len = strlen (*mangled); 173560484Sobrien 173677298Sobrien for (i = 0; i < ARRAY_SIZE (optable); ++i) 173760484Sobrien { 173860484Sobrien size_t l = strlen (optable[i].in); 173960484Sobrien 174060484Sobrien if (l <= len 174160484Sobrien && memcmp (optable[i].in, *mangled, l) == 0) 174260484Sobrien { 174360484Sobrien string_appendn (s, " ", 1); 174460484Sobrien string_append (s, optable[i].out); 174560484Sobrien string_appendn (s, " ", 1); 174660484Sobrien success = 1; 174760484Sobrien (*mangled) += l; 174860484Sobrien break; 174960484Sobrien } 175060484Sobrien } 175160484Sobrien 175260484Sobrien if (!success) 175360484Sobrien break; 175460484Sobrien } 175560484Sobrien else 175660484Sobrien need_operator = 1; 175760484Sobrien 175860484Sobrien success = demangle_template_value_parm (work, mangled, s, tk); 175960484Sobrien } 176060484Sobrien 176160484Sobrien if (**mangled != 'W') 176260484Sobrien success = 0; 176360484Sobrien else 176460484Sobrien { 176560484Sobrien string_appendn (s, ")", 1); 176660484Sobrien (*mangled)++; 176760484Sobrien } 176860484Sobrien 176960484Sobrien return success; 177060484Sobrien} 177160484Sobrien 177260484Sobrienstatic int 177360484Sobriendemangle_integral_value (work, mangled, s) 177460484Sobrien struct work_stuff *work; 177560484Sobrien const char** mangled; 177660484Sobrien string* s; 177760484Sobrien{ 177860484Sobrien int success; 177960484Sobrien 178060484Sobrien if (**mangled == 'E') 178160484Sobrien success = demangle_expression (work, mangled, s, tk_integral); 178260484Sobrien else if (**mangled == 'Q' || **mangled == 'K') 178360484Sobrien success = demangle_qualified (work, mangled, s, 0, 1); 178460484Sobrien else 178560484Sobrien { 178660484Sobrien int value; 178760484Sobrien 178868765Sobrien /* By default, we let the number decide whether we shall consume an 178968765Sobrien underscore. */ 179068765Sobrien int consume_following_underscore = 0; 179168765Sobrien int leave_following_underscore = 0; 179268765Sobrien 179360484Sobrien success = 0; 179460484Sobrien 179560484Sobrien /* Negative numbers are indicated with a leading `m'. */ 179660484Sobrien if (**mangled == 'm') 179760484Sobrien { 179860484Sobrien string_appendn (s, "-", 1); 179960484Sobrien (*mangled)++; 180060484Sobrien } 180168765Sobrien else if (mangled[0][0] == '_' && mangled[0][1] == 'm') 180268765Sobrien { 180368765Sobrien /* Since consume_count_with_underscores does not handle the 180468765Sobrien `m'-prefix we must do it here, using consume_count and 180568765Sobrien adjusting underscores: we have to consume the underscore 180668765Sobrien matching the prepended one. */ 180768765Sobrien consume_following_underscore = 1; 180868765Sobrien string_appendn (s, "-", 1); 180968765Sobrien (*mangled) += 2; 181068765Sobrien } 181168765Sobrien else if (**mangled == '_') 181268765Sobrien { 181368765Sobrien /* Do not consume a following underscore; 181468765Sobrien consume_following_underscore will consume what should be 181568765Sobrien consumed. */ 181668765Sobrien leave_following_underscore = 1; 181768765Sobrien } 181860484Sobrien 181968765Sobrien /* We must call consume_count if we expect to remove a trailing 182068765Sobrien underscore, since consume_count_with_underscores expects 182168765Sobrien the leading underscore (that we consumed) if it is to handle 182268765Sobrien multi-digit numbers. */ 182368765Sobrien if (consume_following_underscore) 182468765Sobrien value = consume_count (mangled); 182568765Sobrien else 182668765Sobrien value = consume_count_with_underscores (mangled); 182768765Sobrien 182860484Sobrien if (value != -1) 182960484Sobrien { 183060484Sobrien char buf[INTBUF_SIZE]; 183160484Sobrien sprintf (buf, "%d", value); 183260484Sobrien string_append (s, buf); 183360484Sobrien 183468765Sobrien /* Numbers not otherwise delimited, might have an underscore 183568765Sobrien appended as a delimeter, which we should skip. 183668765Sobrien 183768765Sobrien ??? This used to always remove a following underscore, which 183868765Sobrien is wrong. If other (arbitrary) cases are followed by an 183968765Sobrien underscore, we need to do something more radical. */ 184068765Sobrien 184168765Sobrien if ((value > 9 || consume_following_underscore) 184268765Sobrien && ! leave_following_underscore 184368765Sobrien && **mangled == '_') 184460484Sobrien (*mangled)++; 184560484Sobrien 184660484Sobrien /* All is well. */ 184760484Sobrien success = 1; 184860484Sobrien } 184960484Sobrien } 185060484Sobrien 185160484Sobrien return success; 185260484Sobrien} 185360484Sobrien 185460484Sobrien/* Demangle the real value in MANGLED. */ 185560484Sobrien 185660484Sobrienstatic int 185760484Sobriendemangle_real_value (work, mangled, s) 185860484Sobrien struct work_stuff *work; 185960484Sobrien const char **mangled; 186060484Sobrien string* s; 186160484Sobrien{ 186260484Sobrien if (**mangled == 'E') 186360484Sobrien return demangle_expression (work, mangled, s, tk_real); 186460484Sobrien 186560484Sobrien if (**mangled == 'm') 186660484Sobrien { 186760484Sobrien string_appendn (s, "-", 1); 186860484Sobrien (*mangled)++; 186960484Sobrien } 187077298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 187160484Sobrien { 187260484Sobrien string_appendn (s, *mangled, 1); 187360484Sobrien (*mangled)++; 187460484Sobrien } 187560484Sobrien if (**mangled == '.') /* fraction */ 187660484Sobrien { 187760484Sobrien string_appendn (s, ".", 1); 187860484Sobrien (*mangled)++; 187977298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 188060484Sobrien { 188160484Sobrien string_appendn (s, *mangled, 1); 188260484Sobrien (*mangled)++; 188360484Sobrien } 188460484Sobrien } 188560484Sobrien if (**mangled == 'e') /* exponent */ 188660484Sobrien { 188760484Sobrien string_appendn (s, "e", 1); 188860484Sobrien (*mangled)++; 188977298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 189060484Sobrien { 189160484Sobrien string_appendn (s, *mangled, 1); 189260484Sobrien (*mangled)++; 189360484Sobrien } 189460484Sobrien } 189560484Sobrien 189660484Sobrien return 1; 189760484Sobrien} 189860484Sobrien 189960484Sobrienstatic int 190060484Sobriendemangle_template_value_parm (work, mangled, s, tk) 190160484Sobrien struct work_stuff *work; 190260484Sobrien const char **mangled; 190360484Sobrien string* s; 190460484Sobrien type_kind_t tk; 190560484Sobrien{ 190660484Sobrien int success = 1; 190760484Sobrien 190860484Sobrien if (**mangled == 'Y') 190960484Sobrien { 191060484Sobrien /* The next argument is a template parameter. */ 191160484Sobrien int idx; 191260484Sobrien 191360484Sobrien (*mangled)++; 191460484Sobrien idx = consume_count_with_underscores (mangled); 191560484Sobrien if (idx == -1 191660484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 191760484Sobrien || consume_count_with_underscores (mangled) == -1) 191860484Sobrien return -1; 191960484Sobrien if (work->tmpl_argvec) 192060484Sobrien string_append (s, work->tmpl_argvec[idx]); 192160484Sobrien else 192260484Sobrien string_append_template_idx (s, idx); 192360484Sobrien } 192460484Sobrien else if (tk == tk_integral) 192560484Sobrien success = demangle_integral_value (work, mangled, s); 192660484Sobrien else if (tk == tk_char) 192760484Sobrien { 192860484Sobrien char tmp[2]; 192960484Sobrien int val; 193060484Sobrien if (**mangled == 'm') 193160484Sobrien { 193260484Sobrien string_appendn (s, "-", 1); 193360484Sobrien (*mangled)++; 193460484Sobrien } 193560484Sobrien string_appendn (s, "'", 1); 193660484Sobrien val = consume_count(mangled); 193760484Sobrien if (val <= 0) 193860484Sobrien success = 0; 193960484Sobrien else 194060484Sobrien { 194160484Sobrien tmp[0] = (char)val; 194260484Sobrien tmp[1] = '\0'; 194360484Sobrien string_appendn (s, &tmp[0], 1); 194460484Sobrien string_appendn (s, "'", 1); 194560484Sobrien } 194660484Sobrien } 194760484Sobrien else if (tk == tk_bool) 194860484Sobrien { 194960484Sobrien int val = consume_count (mangled); 195060484Sobrien if (val == 0) 195160484Sobrien string_appendn (s, "false", 5); 195260484Sobrien else if (val == 1) 195360484Sobrien string_appendn (s, "true", 4); 195460484Sobrien else 195560484Sobrien success = 0; 195660484Sobrien } 195760484Sobrien else if (tk == tk_real) 195860484Sobrien success = demangle_real_value (work, mangled, s); 195960484Sobrien else if (tk == tk_pointer || tk == tk_reference) 196060484Sobrien { 196160484Sobrien if (**mangled == 'Q') 196260484Sobrien success = demangle_qualified (work, mangled, s, 196360484Sobrien /*isfuncname=*/0, 196460484Sobrien /*append=*/1); 196560484Sobrien else 196660484Sobrien { 196760484Sobrien int symbol_len = consume_count (mangled); 196860484Sobrien if (symbol_len == -1) 196960484Sobrien return -1; 197060484Sobrien if (symbol_len == 0) 197160484Sobrien string_appendn (s, "0", 1); 197260484Sobrien else 197360484Sobrien { 197460484Sobrien char *p = xmalloc (symbol_len + 1), *q; 197560484Sobrien strncpy (p, *mangled, symbol_len); 197660484Sobrien p [symbol_len] = '\0'; 197760484Sobrien /* We use cplus_demangle here, rather than 197860484Sobrien internal_cplus_demangle, because the name of the entity 197960484Sobrien mangled here does not make use of any of the squangling 198060484Sobrien or type-code information we have built up thus far; it is 198160484Sobrien mangled independently. */ 198260484Sobrien q = cplus_demangle (p, work->options); 198360484Sobrien if (tk == tk_pointer) 198460484Sobrien string_appendn (s, "&", 1); 198560484Sobrien /* FIXME: Pointer-to-member constants should get a 198660484Sobrien qualifying class name here. */ 198760484Sobrien if (q) 198860484Sobrien { 198960484Sobrien string_append (s, q); 199060484Sobrien free (q); 199160484Sobrien } 199260484Sobrien else 199360484Sobrien string_append (s, p); 199460484Sobrien free (p); 199560484Sobrien } 199660484Sobrien *mangled += symbol_len; 199760484Sobrien } 199860484Sobrien } 199960484Sobrien 200060484Sobrien return success; 200160484Sobrien} 200260484Sobrien 200360484Sobrien/* Demangle the template name in MANGLED. The full name of the 200460484Sobrien template (e.g., S<int>) is placed in TNAME. The name without the 200560484Sobrien template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is 200660484Sobrien non-NULL. If IS_TYPE is nonzero, this template is a type template, 200760484Sobrien not a function template. If both IS_TYPE and REMEMBER are nonzero, 200868765Sobrien the template is remembered in the list of back-referenceable 200960484Sobrien types. */ 201060484Sobrien 201160484Sobrienstatic int 201260484Sobriendemangle_template (work, mangled, tname, trawname, is_type, remember) 201360484Sobrien struct work_stuff *work; 201460484Sobrien const char **mangled; 201560484Sobrien string *tname; 201633965Sjdp string *trawname; 201738889Sjdp int is_type; 201860484Sobrien int remember; 201933965Sjdp{ 202033965Sjdp int i; 202133965Sjdp int r; 202233965Sjdp int need_comma = 0; 202333965Sjdp int success = 0; 202433965Sjdp const char *start; 202538889Sjdp int is_java_array = 0; 202633965Sjdp string temp; 202760484Sobrien int bindex = 0; 202833965Sjdp 202933965Sjdp (*mangled)++; 203038889Sjdp if (is_type) 203133965Sjdp { 203260484Sobrien if (remember) 203360484Sobrien bindex = register_Btype (work); 203438889Sjdp start = *mangled; 203538889Sjdp /* get template name */ 203660484Sobrien if (**mangled == 'z') 203738889Sjdp { 203860484Sobrien int idx; 203960484Sobrien (*mangled)++; 204060484Sobrien (*mangled)++; 204160484Sobrien 204260484Sobrien idx = consume_count_with_underscores (mangled); 204360484Sobrien if (idx == -1 204460484Sobrien || (work->tmpl_argvec && idx >= work->ntmpl_args) 204560484Sobrien || consume_count_with_underscores (mangled) == -1) 204660484Sobrien return (0); 204760484Sobrien 204860484Sobrien if (work->tmpl_argvec) 204960484Sobrien { 205060484Sobrien string_append (tname, work->tmpl_argvec[idx]); 205160484Sobrien if (trawname) 205260484Sobrien string_append (trawname, work->tmpl_argvec[idx]); 205360484Sobrien } 205460484Sobrien else 205560484Sobrien { 205660484Sobrien string_append_template_idx (tname, idx); 205760484Sobrien if (trawname) 205860484Sobrien string_append_template_idx (trawname, idx); 205960484Sobrien } 206038889Sjdp } 206160484Sobrien else 206238889Sjdp { 206360484Sobrien if ((r = consume_count (mangled)) <= 0 206460484Sobrien || (int) strlen (*mangled) < r) 206560484Sobrien { 206660484Sobrien return (0); 206760484Sobrien } 206860484Sobrien is_java_array = (work -> options & DMGL_JAVA) 206960484Sobrien && strncmp (*mangled, "JArray1Z", 8) == 0; 207060484Sobrien if (! is_java_array) 207160484Sobrien { 207260484Sobrien string_appendn (tname, *mangled, r); 207360484Sobrien } 207460484Sobrien if (trawname) 207560484Sobrien string_appendn (trawname, *mangled, r); 207660484Sobrien *mangled += r; 207738889Sjdp } 207833965Sjdp } 207938889Sjdp if (!is_java_array) 208038889Sjdp string_append (tname, "<"); 208133965Sjdp /* get size of template parameter list */ 208233965Sjdp if (!get_count (mangled, &r)) 208333965Sjdp { 208433965Sjdp return (0); 208533965Sjdp } 208638889Sjdp if (!is_type) 208738889Sjdp { 208838889Sjdp /* Create an array for saving the template argument values. */ 208938889Sjdp work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); 209038889Sjdp work->ntmpl_args = r; 209138889Sjdp for (i = 0; i < r; i++) 209238889Sjdp work->tmpl_argvec[i] = 0; 209338889Sjdp } 209433965Sjdp for (i = 0; i < r; i++) 209533965Sjdp { 209633965Sjdp if (need_comma) 209733965Sjdp { 209833965Sjdp string_append (tname, ", "); 209933965Sjdp } 210033965Sjdp /* Z for type parameters */ 210133965Sjdp if (**mangled == 'Z') 210233965Sjdp { 210333965Sjdp (*mangled)++; 210433965Sjdp /* temp is initialized in do_type */ 210533965Sjdp success = do_type (work, mangled, &temp); 210633965Sjdp if (success) 210733965Sjdp { 210833965Sjdp string_appends (tname, &temp); 210938889Sjdp 211038889Sjdp if (!is_type) 211138889Sjdp { 211238889Sjdp /* Save the template argument. */ 211338889Sjdp int len = temp.p - temp.b; 211438889Sjdp work->tmpl_argvec[i] = xmalloc (len + 1); 211538889Sjdp memcpy (work->tmpl_argvec[i], temp.b, len); 211638889Sjdp work->tmpl_argvec[i][len] = '\0'; 211738889Sjdp } 211833965Sjdp } 211933965Sjdp string_delete(&temp); 212033965Sjdp if (!success) 212133965Sjdp { 212233965Sjdp break; 212333965Sjdp } 212433965Sjdp } 212560484Sobrien /* z for template parameters */ 212660484Sobrien else if (**mangled == 'z') 212760484Sobrien { 212860484Sobrien int r2; 212960484Sobrien (*mangled)++; 213060484Sobrien success = demangle_template_template_parm (work, mangled, tname); 213160484Sobrien 213260484Sobrien if (success 213360484Sobrien && (r2 = consume_count (mangled)) > 0 213460484Sobrien && (int) strlen (*mangled) >= r2) 213560484Sobrien { 213660484Sobrien string_append (tname, " "); 213760484Sobrien string_appendn (tname, *mangled, r2); 213860484Sobrien if (!is_type) 213960484Sobrien { 214060484Sobrien /* Save the template argument. */ 214160484Sobrien int len = r2; 214260484Sobrien work->tmpl_argvec[i] = xmalloc (len + 1); 214360484Sobrien memcpy (work->tmpl_argvec[i], *mangled, len); 214460484Sobrien work->tmpl_argvec[i][len] = '\0'; 214560484Sobrien } 214660484Sobrien *mangled += r2; 214760484Sobrien } 214860484Sobrien if (!success) 214960484Sobrien { 215060484Sobrien break; 215160484Sobrien } 215260484Sobrien } 215333965Sjdp else 215433965Sjdp { 215538889Sjdp string param; 215638889Sjdp string* s; 215738889Sjdp 215833965Sjdp /* otherwise, value parameter */ 215960484Sobrien 216033965Sjdp /* temp is initialized in do_type */ 216133965Sjdp success = do_type (work, mangled, &temp); 216233965Sjdp string_delete(&temp); 216333965Sjdp if (!success) 216460484Sobrien break; 216538889Sjdp 216638889Sjdp if (!is_type) 216738889Sjdp { 216838889Sjdp s = ¶m; 216938889Sjdp string_init (s); 217038889Sjdp } 217138889Sjdp else 217238889Sjdp s = tname; 217338889Sjdp 217460484Sobrien success = demangle_template_value_parm (work, mangled, s, 217560484Sobrien (type_kind_t) success); 217638889Sjdp 217760484Sobrien if (!success) 217838889Sjdp { 217960484Sobrien if (!is_type) 218060484Sobrien string_delete (s); 218160484Sobrien success = 0; 218260484Sobrien break; 218333965Sjdp } 218460484Sobrien 218538889Sjdp if (!is_type) 218638889Sjdp { 218738889Sjdp int len = s->p - s->b; 218838889Sjdp work->tmpl_argvec[i] = xmalloc (len + 1); 218938889Sjdp memcpy (work->tmpl_argvec[i], s->b, len); 219038889Sjdp work->tmpl_argvec[i][len] = '\0'; 219160484Sobrien 219238889Sjdp string_appends (tname, s); 219338889Sjdp string_delete (s); 219438889Sjdp } 219533965Sjdp } 219633965Sjdp need_comma = 1; 219733965Sjdp } 219838889Sjdp if (is_java_array) 219938889Sjdp { 220038889Sjdp string_append (tname, "[]"); 220138889Sjdp } 220238889Sjdp else 220338889Sjdp { 220438889Sjdp if (tname->p[-1] == '>') 220538889Sjdp string_append (tname, " "); 220638889Sjdp string_append (tname, ">"); 220738889Sjdp } 220860484Sobrien 220960484Sobrien if (is_type && remember) 221060484Sobrien remember_Btype (work, tname->b, LEN_STRING (tname), bindex); 221160484Sobrien 221233965Sjdp /* 221333965Sjdp if (work -> static_type) 221433965Sjdp { 221533965Sjdp string_append (declp, *mangled + 1); 221633965Sjdp *mangled += strlen (*mangled); 221733965Sjdp success = 1; 221833965Sjdp } 221933965Sjdp else 222033965Sjdp { 222133965Sjdp success = demangle_args (work, mangled, declp); 222233965Sjdp } 222333965Sjdp } 222433965Sjdp */ 222533965Sjdp return (success); 222633965Sjdp} 222733965Sjdp 222833965Sjdpstatic int 222933965Sjdparm_pt (work, mangled, n, anchor, args) 223033965Sjdp struct work_stuff *work; 223133965Sjdp const char *mangled; 223233965Sjdp int n; 223333965Sjdp const char **anchor, **args; 223433965Sjdp{ 223560484Sobrien /* Check if ARM template with "__pt__" in it ("parameterized type") */ 223660484Sobrien /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ 223789857Sobrien if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) 223833965Sjdp { 223933965Sjdp int len; 224033965Sjdp *args = *anchor + 6; 224133965Sjdp len = consume_count (args); 224260484Sobrien if (len == -1) 224360484Sobrien return 0; 224433965Sjdp if (*args + len == mangled + n && **args == '_') 224533965Sjdp { 224633965Sjdp ++*args; 224733965Sjdp return 1; 224833965Sjdp } 224933965Sjdp } 225060484Sobrien if (AUTO_DEMANGLING || EDG_DEMANGLING) 225160484Sobrien { 225289857Sobrien if ((*anchor = strstr (mangled, "__tm__")) 225389857Sobrien || (*anchor = strstr (mangled, "__ps__")) 225489857Sobrien || (*anchor = strstr (mangled, "__pt__"))) 225560484Sobrien { 225660484Sobrien int len; 225760484Sobrien *args = *anchor + 6; 225860484Sobrien len = consume_count (args); 225960484Sobrien if (len == -1) 226060484Sobrien return 0; 226160484Sobrien if (*args + len == mangled + n && **args == '_') 226260484Sobrien { 226360484Sobrien ++*args; 226460484Sobrien return 1; 226560484Sobrien } 226660484Sobrien } 226789857Sobrien else if ((*anchor = strstr (mangled, "__S"))) 226860484Sobrien { 226960484Sobrien int len; 227060484Sobrien *args = *anchor + 3; 227160484Sobrien len = consume_count (args); 227260484Sobrien if (len == -1) 227360484Sobrien return 0; 227460484Sobrien if (*args + len == mangled + n && **args == '_') 227560484Sobrien { 227660484Sobrien ++*args; 227760484Sobrien return 1; 227860484Sobrien } 227960484Sobrien } 228060484Sobrien } 228160484Sobrien 228233965Sjdp return 0; 228333965Sjdp} 228433965Sjdp 228533965Sjdpstatic void 228660484Sobriendemangle_arm_hp_template (work, mangled, n, declp) 228733965Sjdp struct work_stuff *work; 228833965Sjdp const char **mangled; 228933965Sjdp int n; 229033965Sjdp string *declp; 229133965Sjdp{ 229233965Sjdp const char *p; 229333965Sjdp const char *args; 229433965Sjdp const char *e = *mangled + n; 229560484Sobrien string arg; 229633965Sjdp 229760484Sobrien /* Check for HP aCC template spec: classXt1t2 where t1, t2 are 229860484Sobrien template args */ 229960484Sobrien if (HP_DEMANGLING && ((*mangled)[n] == 'X')) 230033965Sjdp { 230160484Sobrien char *start_spec_args = NULL; 230260484Sobrien 230360484Sobrien /* First check for and omit template specialization pseudo-arguments, 230460484Sobrien such as in "Spec<#1,#1.*>" */ 230560484Sobrien start_spec_args = strchr (*mangled, '<'); 230660484Sobrien if (start_spec_args && (start_spec_args - *mangled < n)) 230760484Sobrien string_appendn (declp, *mangled, start_spec_args - *mangled); 230860484Sobrien else 230960484Sobrien string_appendn (declp, *mangled, n); 231060484Sobrien (*mangled) += n + 1; 231133965Sjdp string_init (&arg); 231260484Sobrien if (work->temp_start == -1) /* non-recursive call */ 231360484Sobrien work->temp_start = declp->p - declp->b; 231460484Sobrien string_append (declp, "<"); 231560484Sobrien while (1) 231660484Sobrien { 231760484Sobrien string_clear (&arg); 231860484Sobrien switch (**mangled) 231960484Sobrien { 232060484Sobrien case 'T': 232160484Sobrien /* 'T' signals a type parameter */ 232260484Sobrien (*mangled)++; 232360484Sobrien if (!do_type (work, mangled, &arg)) 232460484Sobrien goto hpacc_template_args_done; 232560484Sobrien break; 232660484Sobrien 232760484Sobrien case 'U': 232860484Sobrien case 'S': 232960484Sobrien /* 'U' or 'S' signals an integral value */ 233060484Sobrien if (!do_hpacc_template_const_value (work, mangled, &arg)) 233160484Sobrien goto hpacc_template_args_done; 233260484Sobrien break; 233360484Sobrien 233460484Sobrien case 'A': 233560484Sobrien /* 'A' signals a named constant expression (literal) */ 233660484Sobrien if (!do_hpacc_template_literal (work, mangled, &arg)) 233760484Sobrien goto hpacc_template_args_done; 233860484Sobrien break; 233960484Sobrien 234060484Sobrien default: 234160484Sobrien /* Today, 1997-09-03, we have only the above types 234260484Sobrien of template parameters */ 234360484Sobrien /* FIXME: maybe this should fail and return null */ 234460484Sobrien goto hpacc_template_args_done; 234560484Sobrien } 234660484Sobrien string_appends (declp, &arg); 234760484Sobrien /* Check if we're at the end of template args. 234860484Sobrien 0 if at end of static member of template class, 234960484Sobrien _ if done with template args for a function */ 235060484Sobrien if ((**mangled == '\000') || (**mangled == '_')) 235160484Sobrien break; 235260484Sobrien else 235360484Sobrien string_append (declp, ","); 235460484Sobrien } 235560484Sobrien hpacc_template_args_done: 235660484Sobrien string_append (declp, ">"); 235760484Sobrien string_delete (&arg); 235860484Sobrien if (**mangled == '_') 235960484Sobrien (*mangled)++; 236060484Sobrien return; 236160484Sobrien } 236260484Sobrien /* ARM template? (Also handles HP cfront extensions) */ 236360484Sobrien else if (arm_pt (work, *mangled, n, &p, &args)) 236460484Sobrien { 236560484Sobrien string type_str; 236660484Sobrien 236760484Sobrien string_init (&arg); 236833965Sjdp string_appendn (declp, *mangled, p - *mangled); 236960484Sobrien if (work->temp_start == -1) /* non-recursive call */ 237060484Sobrien work->temp_start = declp->p - declp->b; 237133965Sjdp string_append (declp, "<"); 237233965Sjdp /* should do error checking here */ 237333965Sjdp while (args < e) { 237433965Sjdp string_clear (&arg); 237560484Sobrien 237660484Sobrien /* Check for type or literal here */ 237760484Sobrien switch (*args) 237860484Sobrien { 237960484Sobrien /* HP cfront extensions to ARM for template args */ 238060484Sobrien /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ 238160484Sobrien /* FIXME: We handle only numeric literals for HP cfront */ 238260484Sobrien case 'X': 238360484Sobrien /* A typed constant value follows */ 238460484Sobrien args++; 238560484Sobrien if (!do_type (work, &args, &type_str)) 238660484Sobrien goto cfront_template_args_done; 238760484Sobrien string_append (&arg, "("); 238860484Sobrien string_appends (&arg, &type_str); 238960484Sobrien string_append (&arg, ")"); 239060484Sobrien if (*args != 'L') 239160484Sobrien goto cfront_template_args_done; 239260484Sobrien args++; 239360484Sobrien /* Now snarf a literal value following 'L' */ 239460484Sobrien if (!snarf_numeric_literal (&args, &arg)) 239560484Sobrien goto cfront_template_args_done; 239660484Sobrien break; 239760484Sobrien 239860484Sobrien case 'L': 239960484Sobrien /* Snarf a literal following 'L' */ 240060484Sobrien args++; 240160484Sobrien if (!snarf_numeric_literal (&args, &arg)) 240260484Sobrien goto cfront_template_args_done; 240360484Sobrien break; 240460484Sobrien default: 240560484Sobrien /* Not handling other HP cfront stuff */ 240660484Sobrien if (!do_type (work, &args, &arg)) 240760484Sobrien goto cfront_template_args_done; 240860484Sobrien } 240933965Sjdp string_appends (declp, &arg); 241033965Sjdp string_append (declp, ","); 241133965Sjdp } 241260484Sobrien cfront_template_args_done: 241333965Sjdp string_delete (&arg); 241460484Sobrien if (args >= e) 241560484Sobrien --declp->p; /* remove extra comma */ 241633965Sjdp string_append (declp, ">"); 241733965Sjdp } 241860484Sobrien else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 241960484Sobrien && (*mangled)[9] == 'N' 242060484Sobrien && (*mangled)[8] == (*mangled)[10] 242160484Sobrien && strchr (cplus_markers, (*mangled)[8])) 242260484Sobrien { 242360484Sobrien /* A member of the anonymous namespace. */ 242460484Sobrien string_append (declp, "{anonymous}"); 242560484Sobrien } 242633965Sjdp else 242733965Sjdp { 242860484Sobrien if (work->temp_start == -1) /* non-recursive call only */ 242960484Sobrien work->temp_start = 0; /* disable in recursive calls */ 243033965Sjdp string_appendn (declp, *mangled, n); 243133965Sjdp } 243233965Sjdp *mangled += n; 243333965Sjdp} 243433965Sjdp 243560484Sobrien/* Extract a class name, possibly a template with arguments, from the 243660484Sobrien mangled string; qualifiers, local class indicators, etc. have 243760484Sobrien already been dealt with */ 243860484Sobrien 243933965Sjdpstatic int 244033965Sjdpdemangle_class_name (work, mangled, declp) 244133965Sjdp struct work_stuff *work; 244233965Sjdp const char **mangled; 244333965Sjdp string *declp; 244433965Sjdp{ 244533965Sjdp int n; 244633965Sjdp int success = 0; 244733965Sjdp 244833965Sjdp n = consume_count (mangled); 244960484Sobrien if (n == -1) 245060484Sobrien return 0; 245160484Sobrien if ((int) strlen (*mangled) >= n) 245233965Sjdp { 245360484Sobrien demangle_arm_hp_template (work, mangled, n, declp); 245433965Sjdp success = 1; 245533965Sjdp } 245633965Sjdp 245733965Sjdp return (success); 245833965Sjdp} 245933965Sjdp 246033965Sjdp/* 246133965Sjdp 246233965SjdpLOCAL FUNCTION 246333965Sjdp 246433965Sjdp demangle_class -- demangle a mangled class sequence 246533965Sjdp 246633965SjdpSYNOPSIS 246733965Sjdp 246833965Sjdp static int 246933965Sjdp demangle_class (struct work_stuff *work, const char **mangled, 247033965Sjdp strint *declp) 247133965Sjdp 247233965SjdpDESCRIPTION 247333965Sjdp 247433965Sjdp DECLP points to the buffer into which demangling is being done. 247533965Sjdp 247633965Sjdp *MANGLED points to the current token to be demangled. On input, 247733965Sjdp it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) 247833965Sjdp On exit, it points to the next token after the mangled class on 247933965Sjdp success, or the first unconsumed token on failure. 248033965Sjdp 248133965Sjdp If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then 248233965Sjdp we are demangling a constructor or destructor. In this case 248333965Sjdp we prepend "class::class" or "class::~class" to DECLP. 248433965Sjdp 248533965Sjdp Otherwise, we prepend "class::" to the current DECLP. 248633965Sjdp 248733965Sjdp Reset the constructor/destructor flags once they have been 248833965Sjdp "consumed". This allows demangle_class to be called later during 248933965Sjdp the same demangling, to do normal class demangling. 249033965Sjdp 249133965Sjdp Returns 1 if demangling is successful, 0 otherwise. 249233965Sjdp 249333965Sjdp*/ 249433965Sjdp 249533965Sjdpstatic int 249633965Sjdpdemangle_class (work, mangled, declp) 249733965Sjdp struct work_stuff *work; 249833965Sjdp const char **mangled; 249933965Sjdp string *declp; 250033965Sjdp{ 250133965Sjdp int success = 0; 250260484Sobrien int btype; 250333965Sjdp string class_name; 250460484Sobrien char *save_class_name_end = 0; 250533965Sjdp 250633965Sjdp string_init (&class_name); 250760484Sobrien btype = register_Btype (work); 250833965Sjdp if (demangle_class_name (work, mangled, &class_name)) 250933965Sjdp { 251060484Sobrien save_class_name_end = class_name.p; 251133965Sjdp if ((work->constructor & 1) || (work->destructor & 1)) 251233965Sjdp { 251360484Sobrien /* adjust so we don't include template args */ 251460484Sobrien if (work->temp_start && (work->temp_start != -1)) 251560484Sobrien { 251660484Sobrien class_name.p = class_name.b + work->temp_start; 251760484Sobrien } 251833965Sjdp string_prepends (declp, &class_name); 251933965Sjdp if (work -> destructor & 1) 252033965Sjdp { 252133965Sjdp string_prepend (declp, "~"); 252233965Sjdp work -> destructor -= 1; 252333965Sjdp } 252433965Sjdp else 252533965Sjdp { 252660484Sobrien work -> constructor -= 1; 252733965Sjdp } 252833965Sjdp } 252960484Sobrien class_name.p = save_class_name_end; 253060484Sobrien remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); 253160484Sobrien remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); 253260484Sobrien string_prepend (declp, SCOPE_STRING (work)); 253333965Sjdp string_prepends (declp, &class_name); 253433965Sjdp success = 1; 253533965Sjdp } 253633965Sjdp string_delete (&class_name); 253733965Sjdp return (success); 253833965Sjdp} 253933965Sjdp 254068765Sobrien 254168765Sobrien/* Called when there's a "__" in the mangled name, with `scan' pointing to 254268765Sobrien the rightmost guess. 254368765Sobrien 254468765Sobrien Find the correct "__"-sequence where the function name ends and the 254568765Sobrien signature starts, which is ambiguous with GNU mangling. 254668765Sobrien Call demangle_signature here, so we can make sure we found the right 254768765Sobrien one; *mangled will be consumed so caller will not make further calls to 254868765Sobrien demangle_signature. */ 254968765Sobrien 255068765Sobrienstatic int 255168765Sobrieniterate_demangle_function (work, mangled, declp, scan) 255268765Sobrien struct work_stuff *work; 255368765Sobrien const char **mangled; 255468765Sobrien string *declp; 255568765Sobrien const char *scan; 255668765Sobrien{ 255768765Sobrien const char *mangle_init = *mangled; 255868765Sobrien int success = 0; 255968765Sobrien string decl_init; 256068765Sobrien struct work_stuff work_init; 256168765Sobrien 256268765Sobrien if (*(scan + 2) == '\0') 256368765Sobrien return 0; 256468765Sobrien 256568765Sobrien /* Do not iterate for some demangling modes, or if there's only one 256668765Sobrien "__"-sequence. This is the normal case. */ 256768765Sobrien if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING 256889857Sobrien || strstr (scan + 2, "__") == NULL) 256968765Sobrien { 257068765Sobrien demangle_function_name (work, mangled, declp, scan); 257168765Sobrien return 1; 257268765Sobrien } 257368765Sobrien 257468765Sobrien /* Save state so we can restart if the guess at the correct "__" was 257568765Sobrien wrong. */ 257668765Sobrien string_init (&decl_init); 257768765Sobrien string_appends (&decl_init, declp); 257868765Sobrien memset (&work_init, 0, sizeof work_init); 257968765Sobrien work_stuff_copy_to_from (&work_init, work); 258068765Sobrien 258168765Sobrien /* Iterate over occurrences of __, allowing names and types to have a 258268765Sobrien "__" sequence in them. We must start with the first (not the last) 258368765Sobrien occurrence, since "__" most often occur between independent mangled 258468765Sobrien parts, hence starting at the last occurence inside a signature 258568765Sobrien might get us a "successful" demangling of the signature. */ 258668765Sobrien 258768765Sobrien while (scan[2]) 258868765Sobrien { 258968765Sobrien demangle_function_name (work, mangled, declp, scan); 259068765Sobrien success = demangle_signature (work, mangled, declp); 259168765Sobrien if (success) 259268765Sobrien break; 259368765Sobrien 259468765Sobrien /* Reset demangle state for the next round. */ 259568765Sobrien *mangled = mangle_init; 259668765Sobrien string_clear (declp); 259768765Sobrien string_appends (declp, &decl_init); 259868765Sobrien work_stuff_copy_to_from (work, &work_init); 259968765Sobrien 260068765Sobrien /* Leave this underscore-sequence. */ 260168765Sobrien scan += 2; 260268765Sobrien 260368765Sobrien /* Scan for the next "__" sequence. */ 260468765Sobrien while (*scan && (scan[0] != '_' || scan[1] != '_')) 260568765Sobrien scan++; 260668765Sobrien 260768765Sobrien /* Move to last "__" in this sequence. */ 260868765Sobrien while (*scan && *scan == '_') 260968765Sobrien scan++; 261068765Sobrien scan -= 2; 261168765Sobrien } 261268765Sobrien 261368765Sobrien /* Delete saved state. */ 261468765Sobrien delete_work_stuff (&work_init); 261568765Sobrien string_delete (&decl_init); 261668765Sobrien 261768765Sobrien return success; 261868765Sobrien} 261968765Sobrien 262033965Sjdp/* 262133965Sjdp 262233965SjdpLOCAL FUNCTION 262333965Sjdp 262433965Sjdp demangle_prefix -- consume the mangled name prefix and find signature 262533965Sjdp 262633965SjdpSYNOPSIS 262733965Sjdp 262833965Sjdp static int 262933965Sjdp demangle_prefix (struct work_stuff *work, const char **mangled, 263033965Sjdp string *declp); 263133965Sjdp 263233965SjdpDESCRIPTION 263333965Sjdp 263433965Sjdp Consume and demangle the prefix of the mangled name. 263568765Sobrien While processing the function name root, arrange to call 263668765Sobrien demangle_signature if the root is ambiguous. 263733965Sjdp 263833965Sjdp DECLP points to the string buffer into which demangled output is 263933965Sjdp placed. On entry, the buffer is empty. On exit it contains 264033965Sjdp the root function name, the demangled operator name, or in some 264133965Sjdp special cases either nothing or the completely demangled result. 264233965Sjdp 264333965Sjdp MANGLED points to the current pointer into the mangled name. As each 264433965Sjdp token of the mangled name is consumed, it is updated. Upon entry 264533965Sjdp the current mangled name pointer points to the first character of 264633965Sjdp the mangled name. Upon exit, it should point to the first character 264733965Sjdp of the signature if demangling was successful, or to the first 264833965Sjdp unconsumed character if demangling of the prefix was unsuccessful. 264960484Sobrien 265033965Sjdp Returns 1 on success, 0 otherwise. 265133965Sjdp */ 265233965Sjdp 265333965Sjdpstatic int 265433965Sjdpdemangle_prefix (work, mangled, declp) 265533965Sjdp struct work_stuff *work; 265633965Sjdp const char **mangled; 265733965Sjdp string *declp; 265833965Sjdp{ 265933965Sjdp int success = 1; 266033965Sjdp const char *scan; 266133965Sjdp int i; 266233965Sjdp 266360484Sobrien if (strlen(*mangled) > 6 266460484Sobrien && (strncmp(*mangled, "_imp__", 6) == 0 266560484Sobrien || strncmp(*mangled, "__imp_", 6) == 0)) 266633965Sjdp { 266760484Sobrien /* it's a symbol imported from a PE dynamic library. Check for both 266860484Sobrien new style prefix _imp__ and legacy __imp_ used by older versions 266960484Sobrien of dlltool. */ 267060484Sobrien (*mangled) += 6; 267160484Sobrien work->dllimported = 1; 267260484Sobrien } 267360484Sobrien else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) 267460484Sobrien { 267533965Sjdp char *marker = strchr (cplus_markers, (*mangled)[8]); 267633965Sjdp if (marker != NULL && *marker == (*mangled)[10]) 267733965Sjdp { 267833965Sjdp if ((*mangled)[9] == 'D') 267933965Sjdp { 268033965Sjdp /* it's a GNU global destructor to be executed at program exit */ 268133965Sjdp (*mangled) += 11; 268233965Sjdp work->destructor = 2; 268333965Sjdp if (gnu_special (work, mangled, declp)) 268433965Sjdp return success; 268533965Sjdp } 268633965Sjdp else if ((*mangled)[9] == 'I') 268733965Sjdp { 268833965Sjdp /* it's a GNU global constructor to be executed at program init */ 268933965Sjdp (*mangled) += 11; 269033965Sjdp work->constructor = 2; 269133965Sjdp if (gnu_special (work, mangled, declp)) 269233965Sjdp return success; 269333965Sjdp } 269433965Sjdp } 269533965Sjdp } 269660484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) 269733965Sjdp { 269833965Sjdp /* it's a ARM global destructor to be executed at program exit */ 269933965Sjdp (*mangled) += 7; 270033965Sjdp work->destructor = 2; 270133965Sjdp } 270260484Sobrien else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) 270333965Sjdp { 270433965Sjdp /* it's a ARM global constructor to be executed at program initial */ 270533965Sjdp (*mangled) += 7; 270633965Sjdp work->constructor = 2; 270733965Sjdp } 270833965Sjdp 270933965Sjdp /* This block of code is a reduction in strength time optimization 271033965Sjdp of: 271189857Sobrien scan = strstr (*mangled, "__"); */ 271233965Sjdp 271333965Sjdp { 271433965Sjdp scan = *mangled; 271533965Sjdp 271633965Sjdp do { 271733965Sjdp scan = strchr (scan, '_'); 271833965Sjdp } while (scan != NULL && *++scan != '_'); 271933965Sjdp 272033965Sjdp if (scan != NULL) --scan; 272133965Sjdp } 272233965Sjdp 272333965Sjdp if (scan != NULL) 272433965Sjdp { 272533965Sjdp /* We found a sequence of two or more '_', ensure that we start at 272633965Sjdp the last pair in the sequence. */ 272733965Sjdp i = strspn (scan, "_"); 272833965Sjdp if (i > 2) 272933965Sjdp { 273060484Sobrien scan += (i - 2); 273133965Sjdp } 273233965Sjdp } 273360484Sobrien 273433965Sjdp if (scan == NULL) 273533965Sjdp { 273633965Sjdp success = 0; 273733965Sjdp } 273833965Sjdp else if (work -> static_type) 273933965Sjdp { 274077298Sobrien if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) 274133965Sjdp { 274233965Sjdp success = 0; 274333965Sjdp } 274433965Sjdp } 274538889Sjdp else if ((scan == *mangled) 274677298Sobrien && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') 274760484Sobrien || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) 274833965Sjdp { 274933965Sjdp /* The ARM says nothing about the mangling of local variables. 275033965Sjdp But cfront mangles local variables by prepending __<nesting_level> 275133965Sjdp to them. As an extension to ARM demangling we handle this case. */ 275260484Sobrien if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) 275377298Sobrien && ISDIGIT ((unsigned char)scan[2])) 275433965Sjdp { 275533965Sjdp *mangled = scan + 2; 275633965Sjdp consume_count (mangled); 275733965Sjdp string_append (declp, *mangled); 275833965Sjdp *mangled += strlen (*mangled); 275960484Sobrien success = 1; 276033965Sjdp } 276133965Sjdp else 276233965Sjdp { 276333965Sjdp /* A GNU style constructor starts with __[0-9Qt]. But cfront uses 276433965Sjdp names like __Q2_3foo3bar for nested type names. So don't accept 276538889Sjdp this style of constructor for cfront demangling. A GNU 276638889Sjdp style member-template constructor starts with 'H'. */ 276760484Sobrien if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) 276833965Sjdp work -> constructor += 1; 276933965Sjdp *mangled = scan + 2; 277033965Sjdp } 277133965Sjdp } 277260484Sobrien else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') 277333965Sjdp { 277460484Sobrien /* Cfront-style parameterized type. Handled later as a signature. */ 277560484Sobrien success = 1; 277660484Sobrien 277760484Sobrien /* ARM template? */ 277860484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 277960484Sobrien } 278060484Sobrien else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') 278160484Sobrien || (scan[2] == 'p' && scan[3] == 's') 278260484Sobrien || (scan[2] == 'p' && scan[3] == 't'))) 278360484Sobrien { 278460484Sobrien /* EDG-style parameterized type. Handled later as a signature. */ 278560484Sobrien success = 1; 278660484Sobrien 278760484Sobrien /* EDG template? */ 278860484Sobrien demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); 278960484Sobrien } 279077298Sobrien else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) 279160484Sobrien && (scan[2] != 't')) 279260484Sobrien { 279333965Sjdp /* Mangled name starts with "__". Skip over any leading '_' characters, 279433965Sjdp then find the next "__" that separates the prefix from the signature. 279533965Sjdp */ 279660484Sobrien if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 279760484Sobrien || (arm_special (mangled, declp) == 0)) 279833965Sjdp { 279933965Sjdp while (*scan == '_') 280033965Sjdp { 280133965Sjdp scan++; 280233965Sjdp } 280389857Sobrien if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) 280433965Sjdp { 280533965Sjdp /* No separator (I.E. "__not_mangled"), or empty signature 280633965Sjdp (I.E. "__not_mangled_either__") */ 280733965Sjdp success = 0; 280833965Sjdp } 280933965Sjdp else 281068765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 281133965Sjdp } 281233965Sjdp } 281333965Sjdp else if (*(scan + 2) != '\0') 281433965Sjdp { 281533965Sjdp /* Mangled name does not start with "__" but does have one somewhere 281633965Sjdp in there with non empty stuff after it. Looks like a global 281768765Sobrien function name. Iterate over all "__":s until the right 281868765Sobrien one is found. */ 281968765Sobrien return iterate_demangle_function (work, mangled, declp, scan); 282033965Sjdp } 282133965Sjdp else 282233965Sjdp { 282333965Sjdp /* Doesn't look like a mangled name */ 282433965Sjdp success = 0; 282533965Sjdp } 282633965Sjdp 282733965Sjdp if (!success && (work->constructor == 2 || work->destructor == 2)) 282833965Sjdp { 282933965Sjdp string_append (declp, *mangled); 283033965Sjdp *mangled += strlen (*mangled); 283133965Sjdp success = 1; 283260484Sobrien } 283333965Sjdp return (success); 283433965Sjdp} 283533965Sjdp 283633965Sjdp/* 283733965Sjdp 283833965SjdpLOCAL FUNCTION 283933965Sjdp 284033965Sjdp gnu_special -- special handling of gnu mangled strings 284133965Sjdp 284233965SjdpSYNOPSIS 284333965Sjdp 284433965Sjdp static int 284533965Sjdp gnu_special (struct work_stuff *work, const char **mangled, 284633965Sjdp string *declp); 284733965Sjdp 284833965Sjdp 284933965SjdpDESCRIPTION 285033965Sjdp 285133965Sjdp Process some special GNU style mangling forms that don't fit 285233965Sjdp the normal pattern. For example: 285333965Sjdp 285433965Sjdp _$_3foo (destructor for class foo) 285533965Sjdp _vt$foo (foo virtual table) 285633965Sjdp _vt$foo$bar (foo::bar virtual table) 285733965Sjdp __vt_foo (foo virtual table, new style with thunks) 285833965Sjdp _3foo$varname (static data member) 285933965Sjdp _Q22rs2tu$vw (static data member) 286033965Sjdp __t6vector1Zii (constructor with template) 286133965Sjdp __thunk_4__$_7ostream (virtual function thunk) 286233965Sjdp */ 286333965Sjdp 286433965Sjdpstatic int 286533965Sjdpgnu_special (work, mangled, declp) 286633965Sjdp struct work_stuff *work; 286733965Sjdp const char **mangled; 286833965Sjdp string *declp; 286933965Sjdp{ 287033965Sjdp int n; 287133965Sjdp int success = 1; 287233965Sjdp const char *p; 287333965Sjdp 287433965Sjdp if ((*mangled)[0] == '_' 287533965Sjdp && strchr (cplus_markers, (*mangled)[1]) != NULL 287633965Sjdp && (*mangled)[2] == '_') 287733965Sjdp { 287833965Sjdp /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ 287933965Sjdp (*mangled) += 3; 288033965Sjdp work -> destructor += 1; 288133965Sjdp } 288233965Sjdp else if ((*mangled)[0] == '_' 288333965Sjdp && (((*mangled)[1] == '_' 288433965Sjdp && (*mangled)[2] == 'v' 288533965Sjdp && (*mangled)[3] == 't' 288633965Sjdp && (*mangled)[4] == '_') 288733965Sjdp || ((*mangled)[1] == 'v' 288833965Sjdp && (*mangled)[2] == 't' 288933965Sjdp && strchr (cplus_markers, (*mangled)[3]) != NULL))) 289033965Sjdp { 289133965Sjdp /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" 289233965Sjdp and create the decl. Note that we consume the entire mangled 289333965Sjdp input string, which means that demangle_signature has no work 289433965Sjdp to do. */ 289533965Sjdp if ((*mangled)[2] == 'v') 289633965Sjdp (*mangled) += 5; /* New style, with thunks: "__vt_" */ 289733965Sjdp else 289833965Sjdp (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */ 289933965Sjdp while (**mangled != '\0') 290033965Sjdp { 290133965Sjdp switch (**mangled) 290233965Sjdp { 290333965Sjdp case 'Q': 290460484Sobrien case 'K': 290533965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 290633965Sjdp break; 290733965Sjdp case 't': 290860484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 290960484Sobrien 1); 291033965Sjdp break; 291133965Sjdp default: 291277298Sobrien if (ISDIGIT((unsigned char)*mangled[0])) 291333965Sjdp { 291433965Sjdp n = consume_count(mangled); 291538889Sjdp /* We may be seeing a too-large size, or else a 291638889Sjdp ".<digits>" indicating a static local symbol. In 291738889Sjdp any case, declare victory and move on; *don't* try 291838889Sjdp to use n to allocate. */ 291960484Sobrien if (n > (int) strlen (*mangled)) 292038889Sjdp { 292138889Sjdp success = 1; 292238889Sjdp break; 292338889Sjdp } 292433965Sjdp } 292533965Sjdp else 292633965Sjdp { 292733965Sjdp n = strcspn (*mangled, cplus_markers); 292833965Sjdp } 292933965Sjdp string_appendn (declp, *mangled, n); 293033965Sjdp (*mangled) += n; 293133965Sjdp } 293233965Sjdp 293360484Sobrien p = strpbrk (*mangled, cplus_markers); 293433965Sjdp if (success && ((p == NULL) || (p == *mangled))) 293533965Sjdp { 293633965Sjdp if (p != NULL) 293733965Sjdp { 293860484Sobrien string_append (declp, SCOPE_STRING (work)); 293933965Sjdp (*mangled)++; 294033965Sjdp } 294133965Sjdp } 294233965Sjdp else 294333965Sjdp { 294433965Sjdp success = 0; 294533965Sjdp break; 294633965Sjdp } 294733965Sjdp } 294833965Sjdp if (success) 294933965Sjdp string_append (declp, " virtual table"); 295033965Sjdp } 295133965Sjdp else if ((*mangled)[0] == '_' 295233965Sjdp && (strchr("0123456789Qt", (*mangled)[1]) != NULL) 295333965Sjdp && (p = strpbrk (*mangled, cplus_markers)) != NULL) 295433965Sjdp { 295533965Sjdp /* static data member, "_3foo$varname" for example */ 295633965Sjdp (*mangled)++; 295733965Sjdp switch (**mangled) 295833965Sjdp { 295933965Sjdp case 'Q': 296060484Sobrien case 'K': 296133965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 296233965Sjdp break; 296333965Sjdp case 't': 296460484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 296533965Sjdp break; 296633965Sjdp default: 296733965Sjdp n = consume_count (mangled); 296860484Sobrien if (n < 0 || n > (long) strlen (*mangled)) 296960484Sobrien { 297060484Sobrien success = 0; 297160484Sobrien break; 297260484Sobrien } 297368765Sobrien 297468765Sobrien if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 297568765Sobrien && (*mangled)[9] == 'N' 297668765Sobrien && (*mangled)[8] == (*mangled)[10] 297768765Sobrien && strchr (cplus_markers, (*mangled)[8])) 297868765Sobrien { 297968765Sobrien /* A member of the anonymous namespace. There's information 298068765Sobrien about what identifier or filename it was keyed to, but 298168765Sobrien it's just there to make the mangled name unique; we just 298268765Sobrien step over it. */ 298368765Sobrien string_append (declp, "{anonymous}"); 298468765Sobrien (*mangled) += n; 298568765Sobrien 298668765Sobrien /* Now p points to the marker before the N, so we need to 298768765Sobrien update it to the first marker after what we consumed. */ 298868765Sobrien p = strpbrk (*mangled, cplus_markers); 298968765Sobrien break; 299068765Sobrien } 299168765Sobrien 299233965Sjdp string_appendn (declp, *mangled, n); 299333965Sjdp (*mangled) += n; 299433965Sjdp } 299533965Sjdp if (success && (p == *mangled)) 299633965Sjdp { 299733965Sjdp /* Consumed everything up to the cplus_marker, append the 299833965Sjdp variable name. */ 299933965Sjdp (*mangled)++; 300060484Sobrien string_append (declp, SCOPE_STRING (work)); 300133965Sjdp n = strlen (*mangled); 300233965Sjdp string_appendn (declp, *mangled, n); 300333965Sjdp (*mangled) += n; 300433965Sjdp } 300533965Sjdp else 300633965Sjdp { 300733965Sjdp success = 0; 300833965Sjdp } 300933965Sjdp } 301033965Sjdp else if (strncmp (*mangled, "__thunk_", 8) == 0) 301133965Sjdp { 301260484Sobrien int delta; 301360484Sobrien 301460484Sobrien (*mangled) += 8; 301560484Sobrien delta = consume_count (mangled); 301660484Sobrien if (delta == -1) 301760484Sobrien success = 0; 301833965Sjdp else 301933965Sjdp { 302060484Sobrien char *method = internal_cplus_demangle (work, ++*mangled); 302160484Sobrien 302260484Sobrien if (method) 302360484Sobrien { 302460484Sobrien char buf[50]; 302560484Sobrien sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); 302660484Sobrien string_append (declp, buf); 302760484Sobrien string_append (declp, method); 302860484Sobrien free (method); 302960484Sobrien n = strlen (*mangled); 303060484Sobrien (*mangled) += n; 303160484Sobrien } 303260484Sobrien else 303360484Sobrien { 303460484Sobrien success = 0; 303560484Sobrien } 303633965Sjdp } 303733965Sjdp } 303833965Sjdp else if (strncmp (*mangled, "__t", 3) == 0 303933965Sjdp && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) 304033965Sjdp { 304133965Sjdp p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; 304233965Sjdp (*mangled) += 4; 304333965Sjdp switch (**mangled) 304433965Sjdp { 304533965Sjdp case 'Q': 304660484Sobrien case 'K': 304733965Sjdp success = demangle_qualified (work, mangled, declp, 0, 1); 304833965Sjdp break; 304933965Sjdp case 't': 305060484Sobrien success = demangle_template (work, mangled, declp, 0, 1, 1); 305133965Sjdp break; 305233965Sjdp default: 305368765Sobrien success = do_type (work, mangled, declp); 305433965Sjdp break; 305533965Sjdp } 305633965Sjdp if (success && **mangled != '\0') 305733965Sjdp success = 0; 305833965Sjdp if (success) 305933965Sjdp string_append (declp, p); 306033965Sjdp } 306133965Sjdp else 306233965Sjdp { 306333965Sjdp success = 0; 306433965Sjdp } 306533965Sjdp return (success); 306633965Sjdp} 306733965Sjdp 306860484Sobrienstatic void 306960484Sobrienrecursively_demangle(work, mangled, result, namelength) 307060484Sobrien struct work_stuff *work; 307160484Sobrien const char **mangled; 307260484Sobrien string *result; 307360484Sobrien int namelength; 307460484Sobrien{ 307560484Sobrien char * recurse = (char *)NULL; 307660484Sobrien char * recurse_dem = (char *)NULL; 307760484Sobrien 307860484Sobrien recurse = (char *) xmalloc (namelength + 1); 307960484Sobrien memcpy (recurse, *mangled, namelength); 308060484Sobrien recurse[namelength] = '\000'; 308160484Sobrien 308260484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 308360484Sobrien 308460484Sobrien if (recurse_dem) 308560484Sobrien { 308660484Sobrien string_append (result, recurse_dem); 308760484Sobrien free (recurse_dem); 308860484Sobrien } 308960484Sobrien else 309060484Sobrien { 309160484Sobrien string_appendn (result, *mangled, namelength); 309260484Sobrien } 309360484Sobrien free (recurse); 309460484Sobrien *mangled += namelength; 309560484Sobrien} 309660484Sobrien 309733965Sjdp/* 309833965Sjdp 309933965SjdpLOCAL FUNCTION 310033965Sjdp 310133965Sjdp arm_special -- special handling of ARM/lucid mangled strings 310233965Sjdp 310333965SjdpSYNOPSIS 310433965Sjdp 310533965Sjdp static int 310660484Sobrien arm_special (const char **mangled, 310760484Sobrien string *declp); 310833965Sjdp 310933965Sjdp 311033965SjdpDESCRIPTION 311133965Sjdp 311233965Sjdp Process some special ARM style mangling forms that don't fit 311333965Sjdp the normal pattern. For example: 311433965Sjdp 311533965Sjdp __vtbl__3foo (foo virtual table) 311633965Sjdp __vtbl__3foo__3bar (bar::foo virtual table) 311733965Sjdp 311833965Sjdp */ 311933965Sjdp 312033965Sjdpstatic int 312160484Sobrienarm_special (mangled, declp) 312233965Sjdp const char **mangled; 312333965Sjdp string *declp; 312433965Sjdp{ 312533965Sjdp int n; 312633965Sjdp int success = 1; 312733965Sjdp const char *scan; 312833965Sjdp 312933965Sjdp if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) 313033965Sjdp { 313133965Sjdp /* Found a ARM style virtual table, get past ARM_VTABLE_STRING 313233965Sjdp and create the decl. Note that we consume the entire mangled 313333965Sjdp input string, which means that demangle_signature has no work 313433965Sjdp to do. */ 313533965Sjdp scan = *mangled + ARM_VTABLE_STRLEN; 313633965Sjdp while (*scan != '\0') /* first check it can be demangled */ 313733965Sjdp { 313833965Sjdp n = consume_count (&scan); 313960484Sobrien if (n == -1) 314033965Sjdp { 314133965Sjdp return (0); /* no good */ 314233965Sjdp } 314333965Sjdp scan += n; 314433965Sjdp if (scan[0] == '_' && scan[1] == '_') 314533965Sjdp { 314633965Sjdp scan += 2; 314733965Sjdp } 314833965Sjdp } 314933965Sjdp (*mangled) += ARM_VTABLE_STRLEN; 315033965Sjdp while (**mangled != '\0') 315133965Sjdp { 315233965Sjdp n = consume_count (mangled); 315360484Sobrien if (n == -1 315460484Sobrien || n > (long) strlen (*mangled)) 315560484Sobrien return 0; 315633965Sjdp string_prependn (declp, *mangled, n); 315733965Sjdp (*mangled) += n; 315833965Sjdp if ((*mangled)[0] == '_' && (*mangled)[1] == '_') 315933965Sjdp { 316033965Sjdp string_prepend (declp, "::"); 316133965Sjdp (*mangled) += 2; 316233965Sjdp } 316333965Sjdp } 316433965Sjdp string_append (declp, " virtual table"); 316533965Sjdp } 316633965Sjdp else 316733965Sjdp { 316833965Sjdp success = 0; 316933965Sjdp } 317033965Sjdp return (success); 317133965Sjdp} 317233965Sjdp 317333965Sjdp/* 317433965Sjdp 317533965SjdpLOCAL FUNCTION 317633965Sjdp 317733965Sjdp demangle_qualified -- demangle 'Q' qualified name strings 317833965Sjdp 317933965SjdpSYNOPSIS 318033965Sjdp 318133965Sjdp static int 318233965Sjdp demangle_qualified (struct work_stuff *, const char *mangled, 318333965Sjdp string *result, int isfuncname, int append); 318433965Sjdp 318533965SjdpDESCRIPTION 318633965Sjdp 318733965Sjdp Demangle a qualified name, such as "Q25Outer5Inner" which is 318833965Sjdp the mangled form of "Outer::Inner". The demangled output is 318933965Sjdp prepended or appended to the result string according to the 319033965Sjdp state of the append flag. 319133965Sjdp 319233965Sjdp If isfuncname is nonzero, then the qualified name we are building 319333965Sjdp is going to be used as a member function name, so if it is a 319433965Sjdp constructor or destructor function, append an appropriate 319533965Sjdp constructor or destructor name. I.E. for the above example, 319633965Sjdp the result for use as a constructor is "Outer::Inner::Inner" 319733965Sjdp and the result for use as a destructor is "Outer::Inner::~Inner". 319833965Sjdp 319933965SjdpBUGS 320033965Sjdp 320133965Sjdp Numeric conversion is ASCII dependent (FIXME). 320233965Sjdp 320333965Sjdp */ 320433965Sjdp 320533965Sjdpstatic int 320633965Sjdpdemangle_qualified (work, mangled, result, isfuncname, append) 320733965Sjdp struct work_stuff *work; 320833965Sjdp const char **mangled; 320933965Sjdp string *result; 321033965Sjdp int isfuncname; 321133965Sjdp int append; 321233965Sjdp{ 321360484Sobrien int qualifiers = 0; 321433965Sjdp int success = 1; 321533965Sjdp char num[2]; 321633965Sjdp string temp; 321760484Sobrien string last_name; 321860484Sobrien int bindex = register_Btype (work); 321933965Sjdp 322060484Sobrien /* We only make use of ISFUNCNAME if the entity is a constructor or 322160484Sobrien destructor. */ 322260484Sobrien isfuncname = (isfuncname 322360484Sobrien && ((work->constructor & 1) || (work->destructor & 1))); 322460484Sobrien 322533965Sjdp string_init (&temp); 322660484Sobrien string_init (&last_name); 322760484Sobrien 322860484Sobrien if ((*mangled)[0] == 'K') 322933965Sjdp { 323060484Sobrien /* Squangling qualified name reuse */ 323160484Sobrien int idx; 323260484Sobrien (*mangled)++; 323360484Sobrien idx = consume_count_with_underscores (mangled); 323460484Sobrien if (idx == -1 || idx >= work -> numk) 323560484Sobrien success = 0; 323660484Sobrien else 323760484Sobrien string_append (&temp, work -> ktypevec[idx]); 323860484Sobrien } 323960484Sobrien else 324060484Sobrien switch ((*mangled)[1]) 324160484Sobrien { 324233965Sjdp case '_': 324333965Sjdp /* GNU mangled name with more than 9 classes. The count is preceded 324433965Sjdp by an underscore (to distinguish it from the <= 9 case) and followed 324533965Sjdp by an underscore. */ 324660484Sobrien (*mangled)++; 324760484Sobrien qualifiers = consume_count_with_underscores (mangled); 324860484Sobrien if (qualifiers == -1) 324933965Sjdp success = 0; 325033965Sjdp break; 325133965Sjdp 325233965Sjdp case '1': 325333965Sjdp case '2': 325433965Sjdp case '3': 325533965Sjdp case '4': 325633965Sjdp case '5': 325733965Sjdp case '6': 325833965Sjdp case '7': 325933965Sjdp case '8': 326033965Sjdp case '9': 326133965Sjdp /* The count is in a single digit. */ 326233965Sjdp num[0] = (*mangled)[1]; 326333965Sjdp num[1] = '\0'; 326433965Sjdp qualifiers = atoi (num); 326533965Sjdp 326633965Sjdp /* If there is an underscore after the digit, skip it. This is 326733965Sjdp said to be for ARM-qualified names, but the ARM makes no 326833965Sjdp mention of such an underscore. Perhaps cfront uses one. */ 326933965Sjdp if ((*mangled)[2] == '_') 327033965Sjdp { 327133965Sjdp (*mangled)++; 327233965Sjdp } 327333965Sjdp (*mangled) += 2; 327433965Sjdp break; 327533965Sjdp 327633965Sjdp case '0': 327733965Sjdp default: 327833965Sjdp success = 0; 327933965Sjdp } 328033965Sjdp 328133965Sjdp if (!success) 328233965Sjdp return success; 328333965Sjdp 328433965Sjdp /* Pick off the names and collect them in the temp buffer in the order 328533965Sjdp in which they are found, separated by '::'. */ 328633965Sjdp 328733965Sjdp while (qualifiers-- > 0) 328833965Sjdp { 328960484Sobrien int remember_K = 1; 329060484Sobrien string_clear (&last_name); 329160484Sobrien 329260484Sobrien if (*mangled[0] == '_') 329360484Sobrien (*mangled)++; 329460484Sobrien 329533965Sjdp if (*mangled[0] == 't') 329633965Sjdp { 329760484Sobrien /* Here we always append to TEMP since we will want to use 329860484Sobrien the template name without the template parameters as a 329960484Sobrien constructor or destructor name. The appropriate 330060484Sobrien (parameter-less) value is returned by demangle_template 330160484Sobrien in LAST_NAME. We do not remember the template type here, 330260484Sobrien in order to match the G++ mangling algorithm. */ 330360484Sobrien success = demangle_template(work, mangled, &temp, 330460484Sobrien &last_name, 1, 0); 330560484Sobrien if (!success) 330660484Sobrien break; 330733965Sjdp } 330860484Sobrien else if (*mangled[0] == 'K') 330938889Sjdp { 331060484Sobrien int idx; 331160484Sobrien (*mangled)++; 331260484Sobrien idx = consume_count_with_underscores (mangled); 331360484Sobrien if (idx == -1 || idx >= work->numk) 331460484Sobrien success = 0; 331560484Sobrien else 331660484Sobrien string_append (&temp, work->ktypevec[idx]); 331760484Sobrien remember_K = 0; 331860484Sobrien 331938889Sjdp if (!success) break; 332038889Sjdp } 332133965Sjdp else 332260484Sobrien { 332360484Sobrien if (EDG_DEMANGLING) 332460484Sobrien { 332560484Sobrien int namelength; 332660484Sobrien /* Now recursively demangle the qualifier 332760484Sobrien * This is necessary to deal with templates in 332860484Sobrien * mangling styles like EDG */ 332960484Sobrien namelength = consume_count (mangled); 333060484Sobrien if (namelength == -1) 333160484Sobrien { 333260484Sobrien success = 0; 333360484Sobrien break; 333460484Sobrien } 333560484Sobrien recursively_demangle(work, mangled, &temp, namelength); 333660484Sobrien } 333760484Sobrien else 333860484Sobrien { 333960484Sobrien success = do_type (work, mangled, &last_name); 334060484Sobrien if (!success) 334160484Sobrien break; 334260484Sobrien string_appends (&temp, &last_name); 334360484Sobrien } 334433965Sjdp } 334560484Sobrien 334660484Sobrien if (remember_K) 334760484Sobrien remember_Ktype (work, temp.b, LEN_STRING (&temp)); 334860484Sobrien 334933965Sjdp if (qualifiers > 0) 335060484Sobrien string_append (&temp, SCOPE_STRING (work)); 335133965Sjdp } 335233965Sjdp 335360484Sobrien remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); 335460484Sobrien 335533965Sjdp /* If we are using the result as a function name, we need to append 335633965Sjdp the appropriate '::' separated constructor or destructor name. 335733965Sjdp We do this here because this is the most convenient place, where 335833965Sjdp we already have a pointer to the name and the length of the name. */ 335933965Sjdp 336060484Sobrien if (isfuncname) 336133965Sjdp { 336260484Sobrien string_append (&temp, SCOPE_STRING (work)); 336333965Sjdp if (work -> destructor & 1) 336460484Sobrien string_append (&temp, "~"); 336560484Sobrien string_appends (&temp, &last_name); 336633965Sjdp } 336733965Sjdp 336860484Sobrien /* Now either prepend the temp buffer to the result, or append it, 336933965Sjdp depending upon the state of the append flag. */ 337033965Sjdp 337133965Sjdp if (append) 337260484Sobrien string_appends (result, &temp); 337333965Sjdp else 337433965Sjdp { 337533965Sjdp if (!STRING_EMPTY (result)) 337660484Sobrien string_append (&temp, SCOPE_STRING (work)); 337733965Sjdp string_prepends (result, &temp); 337833965Sjdp } 337933965Sjdp 338060484Sobrien string_delete (&last_name); 338133965Sjdp string_delete (&temp); 338233965Sjdp return (success); 338333965Sjdp} 338433965Sjdp 338533965Sjdp/* 338633965Sjdp 338733965SjdpLOCAL FUNCTION 338833965Sjdp 338933965Sjdp get_count -- convert an ascii count to integer, consuming tokens 339033965Sjdp 339133965SjdpSYNOPSIS 339233965Sjdp 339333965Sjdp static int 339433965Sjdp get_count (const char **type, int *count) 339533965Sjdp 339633965SjdpDESCRIPTION 339733965Sjdp 339860484Sobrien Assume that *type points at a count in a mangled name; set 339960484Sobrien *count to its value, and set *type to the next character after 340060484Sobrien the count. There are some weird rules in effect here. 340160484Sobrien 340260484Sobrien If *type does not point at a string of digits, return zero. 340360484Sobrien 340460484Sobrien If *type points at a string of digits followed by an 340560484Sobrien underscore, set *count to their value as an integer, advance 340660484Sobrien *type to point *after the underscore, and return 1. 340760484Sobrien 340860484Sobrien If *type points at a string of digits not followed by an 340960484Sobrien underscore, consume only the first digit. Set *count to its 341060484Sobrien value as an integer, leave *type pointing after that digit, 341160484Sobrien and return 1. 341260484Sobrien 341360484Sobrien The excuse for this odd behavior: in the ARM and HP demangling 341460484Sobrien styles, a type can be followed by a repeat count of the form 341560484Sobrien `Nxy', where: 341660484Sobrien 341760484Sobrien `x' is a single digit specifying how many additional copies 341860484Sobrien of the type to append to the argument list, and 341960484Sobrien 342060484Sobrien `y' is one or more digits, specifying the zero-based index of 342160484Sobrien the first repeated argument in the list. Yes, as you're 342260484Sobrien unmangling the name you can figure this out yourself, but 342360484Sobrien it's there anyway. 342460484Sobrien 342560484Sobrien So, for example, in `bar__3fooFPiN51', the first argument is a 342660484Sobrien pointer to an integer (`Pi'), and then the next five arguments 342760484Sobrien are the same (`N5'), and the first repeat is the function's 342860484Sobrien second argument (`1'). 342933965Sjdp*/ 343033965Sjdp 343133965Sjdpstatic int 343233965Sjdpget_count (type, count) 343333965Sjdp const char **type; 343433965Sjdp int *count; 343533965Sjdp{ 343633965Sjdp const char *p; 343733965Sjdp int n; 343833965Sjdp 343977298Sobrien if (!ISDIGIT ((unsigned char)**type)) 344060484Sobrien return (0); 344133965Sjdp else 344233965Sjdp { 344333965Sjdp *count = **type - '0'; 344433965Sjdp (*type)++; 344577298Sobrien if (ISDIGIT ((unsigned char)**type)) 344633965Sjdp { 344733965Sjdp p = *type; 344833965Sjdp n = *count; 344960484Sobrien do 345033965Sjdp { 345133965Sjdp n *= 10; 345233965Sjdp n += *p - '0'; 345333965Sjdp p++; 345460484Sobrien } 345577298Sobrien while (ISDIGIT ((unsigned char)*p)); 345633965Sjdp if (*p == '_') 345733965Sjdp { 345833965Sjdp *type = p + 1; 345933965Sjdp *count = n; 346033965Sjdp } 346133965Sjdp } 346233965Sjdp } 346333965Sjdp return (1); 346433965Sjdp} 346533965Sjdp 346660484Sobrien/* RESULT will be initialised here; it will be freed on failure. The 346760484Sobrien value returned is really a type_kind_t. */ 346833965Sjdp 346933965Sjdpstatic int 347033965Sjdpdo_type (work, mangled, result) 347133965Sjdp struct work_stuff *work; 347233965Sjdp const char **mangled; 347333965Sjdp string *result; 347433965Sjdp{ 347533965Sjdp int n; 347633965Sjdp int done; 347733965Sjdp int success; 347833965Sjdp string decl; 347933965Sjdp const char *remembered_type; 348060484Sobrien int type_quals; 348160484Sobrien string btype; 348260484Sobrien type_kind_t tk = tk_none; 348333965Sjdp 348460484Sobrien string_init (&btype); 348533965Sjdp string_init (&decl); 348633965Sjdp string_init (result); 348733965Sjdp 348833965Sjdp done = 0; 348933965Sjdp success = 1; 349033965Sjdp while (success && !done) 349133965Sjdp { 349233965Sjdp int member; 349333965Sjdp switch (**mangled) 349433965Sjdp { 349533965Sjdp 349633965Sjdp /* A pointer type */ 349733965Sjdp case 'P': 349833965Sjdp case 'p': 349933965Sjdp (*mangled)++; 350038889Sjdp if (! (work -> options & DMGL_JAVA)) 350138889Sjdp string_prepend (&decl, "*"); 350260484Sobrien if (tk == tk_none) 350360484Sobrien tk = tk_pointer; 350433965Sjdp break; 350533965Sjdp 350633965Sjdp /* A reference type */ 350733965Sjdp case 'R': 350833965Sjdp (*mangled)++; 350933965Sjdp string_prepend (&decl, "&"); 351060484Sobrien if (tk == tk_none) 351160484Sobrien tk = tk_reference; 351233965Sjdp break; 351333965Sjdp 351433965Sjdp /* An array */ 351533965Sjdp case 'A': 351633965Sjdp { 351760484Sobrien ++(*mangled); 351860484Sobrien if (!STRING_EMPTY (&decl) 351960484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 352033965Sjdp { 352160484Sobrien string_prepend (&decl, "("); 352260484Sobrien string_append (&decl, ")"); 352333965Sjdp } 352460484Sobrien string_append (&decl, "["); 352560484Sobrien if (**mangled != '_') 352660484Sobrien success = demangle_template_value_parm (work, mangled, &decl, 352760484Sobrien tk_integral); 352860484Sobrien if (**mangled == '_') 352960484Sobrien ++(*mangled); 353060484Sobrien string_append (&decl, "]"); 353133965Sjdp break; 353233965Sjdp } 353333965Sjdp 353433965Sjdp /* A back reference to a previously seen type */ 353533965Sjdp case 'T': 353633965Sjdp (*mangled)++; 353733965Sjdp if (!get_count (mangled, &n) || n >= work -> ntypes) 353833965Sjdp { 353933965Sjdp success = 0; 354033965Sjdp } 354133965Sjdp else 354233965Sjdp { 354333965Sjdp remembered_type = work -> typevec[n]; 354433965Sjdp mangled = &remembered_type; 354533965Sjdp } 354633965Sjdp break; 354733965Sjdp 354833965Sjdp /* A function */ 354933965Sjdp case 'F': 355033965Sjdp (*mangled)++; 355160484Sobrien if (!STRING_EMPTY (&decl) 355260484Sobrien && (decl.b[0] == '*' || decl.b[0] == '&')) 355333965Sjdp { 355433965Sjdp string_prepend (&decl, "("); 355533965Sjdp string_append (&decl, ")"); 355633965Sjdp } 355733965Sjdp /* After picking off the function args, we expect to either find the 355833965Sjdp function return type (preceded by an '_') or the end of the 355933965Sjdp string. */ 356060484Sobrien if (!demangle_nested_args (work, mangled, &decl) 356133965Sjdp || (**mangled != '_' && **mangled != '\0')) 356233965Sjdp { 356333965Sjdp success = 0; 356460484Sobrien break; 356533965Sjdp } 356633965Sjdp if (success && (**mangled == '_')) 356760484Sobrien (*mangled)++; 356833965Sjdp break; 356933965Sjdp 357033965Sjdp case 'M': 357133965Sjdp case 'O': 357233965Sjdp { 357360484Sobrien type_quals = TYPE_UNQUALIFIED; 357433965Sjdp 357533965Sjdp member = **mangled == 'M'; 357633965Sjdp (*mangled)++; 357733965Sjdp 357833965Sjdp string_append (&decl, ")"); 357960484Sobrien 358060484Sobrien /* We don't need to prepend `::' for a qualified name; 358160484Sobrien demangle_qualified will do that for us. */ 358260484Sobrien if (**mangled != 'Q') 358360484Sobrien string_prepend (&decl, SCOPE_STRING (work)); 358460484Sobrien 358577298Sobrien if (ISDIGIT ((unsigned char)**mangled)) 358633965Sjdp { 358733965Sjdp n = consume_count (mangled); 358860484Sobrien if (n == -1 358960484Sobrien || (int) strlen (*mangled) < n) 359033965Sjdp { 359133965Sjdp success = 0; 359233965Sjdp break; 359333965Sjdp } 359433965Sjdp string_prependn (&decl, *mangled, n); 359533965Sjdp *mangled += n; 359633965Sjdp } 359760484Sobrien else if (**mangled == 'X' || **mangled == 'Y') 359833965Sjdp { 359933965Sjdp string temp; 360060484Sobrien do_type (work, mangled, &temp); 360160484Sobrien string_prepends (&decl, &temp); 360260484Sobrien } 360360484Sobrien else if (**mangled == 't') 360460484Sobrien { 360560484Sobrien string temp; 360633965Sjdp string_init (&temp); 360760484Sobrien success = demangle_template (work, mangled, &temp, 360860484Sobrien NULL, 1, 1); 360933965Sjdp if (success) 361033965Sjdp { 361133965Sjdp string_prependn (&decl, temp.b, temp.p - temp.b); 361233965Sjdp string_clear (&temp); 361333965Sjdp } 361433965Sjdp else 361533965Sjdp break; 361633965Sjdp } 361760484Sobrien else if (**mangled == 'Q') 361860484Sobrien { 361960484Sobrien success = demangle_qualified (work, mangled, &decl, 362060484Sobrien /*isfuncnam=*/0, 362160484Sobrien /*append=*/0); 362260484Sobrien if (!success) 362360484Sobrien break; 362460484Sobrien } 362560484Sobrien else 362660484Sobrien { 362760484Sobrien success = 0; 362860484Sobrien break; 362960484Sobrien } 363060484Sobrien 363133965Sjdp string_prepend (&decl, "("); 363233965Sjdp if (member) 363333965Sjdp { 363460484Sobrien switch (**mangled) 363533965Sjdp { 363660484Sobrien case 'C': 363760484Sobrien case 'V': 363860484Sobrien case 'u': 363960484Sobrien type_quals |= code_for_qualifier (**mangled); 364033965Sjdp (*mangled)++; 364160484Sobrien break; 364260484Sobrien 364360484Sobrien default: 364460484Sobrien break; 364533965Sjdp } 364660484Sobrien 364733965Sjdp if (*(*mangled)++ != 'F') 364833965Sjdp { 364933965Sjdp success = 0; 365033965Sjdp break; 365133965Sjdp } 365233965Sjdp } 365360484Sobrien if ((member && !demangle_nested_args (work, mangled, &decl)) 365433965Sjdp || **mangled != '_') 365533965Sjdp { 365633965Sjdp success = 0; 365733965Sjdp break; 365833965Sjdp } 365933965Sjdp (*mangled)++; 366033965Sjdp if (! PRINT_ANSI_QUALIFIERS) 366133965Sjdp { 366233965Sjdp break; 366333965Sjdp } 366460484Sobrien if (type_quals != TYPE_UNQUALIFIED) 366533965Sjdp { 366633965Sjdp APPEND_BLANK (&decl); 366760484Sobrien string_append (&decl, qualifier_string (type_quals)); 366833965Sjdp } 366933965Sjdp break; 367033965Sjdp } 367133965Sjdp case 'G': 367233965Sjdp (*mangled)++; 367333965Sjdp break; 367433965Sjdp 367533965Sjdp case 'C': 367660484Sobrien case 'V': 367760484Sobrien case 'u': 367833965Sjdp if (PRINT_ANSI_QUALIFIERS) 367933965Sjdp { 368033965Sjdp if (!STRING_EMPTY (&decl)) 368160484Sobrien string_prepend (&decl, " "); 368260484Sobrien 368360484Sobrien string_prepend (&decl, demangle_qualifier (**mangled)); 368433965Sjdp } 368560484Sobrien (*mangled)++; 368633965Sjdp break; 368733965Sjdp /* 368833965Sjdp } 368933965Sjdp */ 369033965Sjdp 369133965Sjdp /* fall through */ 369233965Sjdp default: 369333965Sjdp done = 1; 369433965Sjdp break; 369533965Sjdp } 369633965Sjdp } 369733965Sjdp 369860484Sobrien if (success) switch (**mangled) 369933965Sjdp { 370033965Sjdp /* A qualified name, such as "Outer::Inner". */ 370133965Sjdp case 'Q': 370260484Sobrien case 'K': 370360484Sobrien { 370460484Sobrien success = demangle_qualified (work, mangled, result, 0, 1); 370560484Sobrien break; 370660484Sobrien } 370760484Sobrien 370860484Sobrien /* A back reference to a previously seen squangled type */ 370960484Sobrien case 'B': 371060484Sobrien (*mangled)++; 371160484Sobrien if (!get_count (mangled, &n) || n >= work -> numb) 371260484Sobrien success = 0; 371360484Sobrien else 371460484Sobrien string_append (result, work->btypevec[n]); 371533965Sjdp break; 371633965Sjdp 371738889Sjdp case 'X': 371838889Sjdp case 'Y': 371938889Sjdp /* A template parm. We substitute the corresponding argument. */ 372038889Sjdp { 372138889Sjdp int idx; 372238889Sjdp 372338889Sjdp (*mangled)++; 372438889Sjdp idx = consume_count_with_underscores (mangled); 372538889Sjdp 372660484Sobrien if (idx == -1 372738889Sjdp || (work->tmpl_argvec && idx >= work->ntmpl_args) 372838889Sjdp || consume_count_with_underscores (mangled) == -1) 372938889Sjdp { 373038889Sjdp success = 0; 373138889Sjdp break; 373238889Sjdp } 373338889Sjdp 373438889Sjdp if (work->tmpl_argvec) 373538889Sjdp string_append (result, work->tmpl_argvec[idx]); 373638889Sjdp else 373760484Sobrien string_append_template_idx (result, idx); 373838889Sjdp 373938889Sjdp success = 1; 374038889Sjdp } 374138889Sjdp break; 374238889Sjdp 374333965Sjdp default: 374433965Sjdp success = demangle_fund_type (work, mangled, result); 374560484Sobrien if (tk == tk_none) 374660484Sobrien tk = (type_kind_t) success; 374733965Sjdp break; 374833965Sjdp } 374933965Sjdp 375033965Sjdp if (success) 375133965Sjdp { 375233965Sjdp if (!STRING_EMPTY (&decl)) 375333965Sjdp { 375433965Sjdp string_append (result, " "); 375533965Sjdp string_appends (result, &decl); 375633965Sjdp } 375733965Sjdp } 375833965Sjdp else 375960484Sobrien string_delete (result); 376033965Sjdp string_delete (&decl); 376160484Sobrien 376260484Sobrien if (success) 376360484Sobrien /* Assume an integral type, if we're not sure. */ 376460484Sobrien return (int) ((tk == tk_none) ? tk_integral : tk); 376560484Sobrien else 376660484Sobrien return 0; 376733965Sjdp} 376833965Sjdp 376933965Sjdp/* Given a pointer to a type string that represents a fundamental type 377033965Sjdp argument (int, long, unsigned int, etc) in TYPE, a pointer to the 377133965Sjdp string in which the demangled output is being built in RESULT, and 377233965Sjdp the WORK structure, decode the types and add them to the result. 377333965Sjdp 377433965Sjdp For example: 377533965Sjdp 377633965Sjdp "Ci" => "const int" 377733965Sjdp "Sl" => "signed long" 377833965Sjdp "CUs" => "const unsigned short" 377933965Sjdp 378060484Sobrien The value returned is really a type_kind_t. */ 378133965Sjdp 378233965Sjdpstatic int 378333965Sjdpdemangle_fund_type (work, mangled, result) 378433965Sjdp struct work_stuff *work; 378533965Sjdp const char **mangled; 378633965Sjdp string *result; 378733965Sjdp{ 378833965Sjdp int done = 0; 378933965Sjdp int success = 1; 379060484Sobrien char buf[10]; 379168765Sobrien unsigned int dec = 0; 379260484Sobrien string btype; 379360484Sobrien type_kind_t tk = tk_integral; 379433965Sjdp 379560484Sobrien string_init (&btype); 379660484Sobrien 379733965Sjdp /* First pick off any type qualifiers. There can be more than one. */ 379833965Sjdp 379933965Sjdp while (!done) 380033965Sjdp { 380133965Sjdp switch (**mangled) 380233965Sjdp { 380333965Sjdp case 'C': 380460484Sobrien case 'V': 380560484Sobrien case 'u': 380633965Sjdp if (PRINT_ANSI_QUALIFIERS) 380733965Sjdp { 380860484Sobrien if (!STRING_EMPTY (result)) 380960484Sobrien string_prepend (result, " "); 381060484Sobrien string_prepend (result, demangle_qualifier (**mangled)); 381133965Sjdp } 381260484Sobrien (*mangled)++; 381333965Sjdp break; 381433965Sjdp case 'U': 381533965Sjdp (*mangled)++; 381633965Sjdp APPEND_BLANK (result); 381733965Sjdp string_append (result, "unsigned"); 381833965Sjdp break; 381933965Sjdp case 'S': /* signed char only */ 382033965Sjdp (*mangled)++; 382133965Sjdp APPEND_BLANK (result); 382233965Sjdp string_append (result, "signed"); 382333965Sjdp break; 382438889Sjdp case 'J': 382538889Sjdp (*mangled)++; 382638889Sjdp APPEND_BLANK (result); 382738889Sjdp string_append (result, "__complex"); 382838889Sjdp break; 382933965Sjdp default: 383033965Sjdp done = 1; 383133965Sjdp break; 383233965Sjdp } 383333965Sjdp } 383433965Sjdp 383533965Sjdp /* Now pick off the fundamental type. There can be only one. */ 383633965Sjdp 383733965Sjdp switch (**mangled) 383833965Sjdp { 383933965Sjdp case '\0': 384033965Sjdp case '_': 384133965Sjdp break; 384233965Sjdp case 'v': 384333965Sjdp (*mangled)++; 384433965Sjdp APPEND_BLANK (result); 384533965Sjdp string_append (result, "void"); 384633965Sjdp break; 384733965Sjdp case 'x': 384833965Sjdp (*mangled)++; 384933965Sjdp APPEND_BLANK (result); 385033965Sjdp string_append (result, "long long"); 385133965Sjdp break; 385233965Sjdp case 'l': 385333965Sjdp (*mangled)++; 385433965Sjdp APPEND_BLANK (result); 385533965Sjdp string_append (result, "long"); 385633965Sjdp break; 385733965Sjdp case 'i': 385833965Sjdp (*mangled)++; 385933965Sjdp APPEND_BLANK (result); 386033965Sjdp string_append (result, "int"); 386133965Sjdp break; 386233965Sjdp case 's': 386333965Sjdp (*mangled)++; 386433965Sjdp APPEND_BLANK (result); 386533965Sjdp string_append (result, "short"); 386633965Sjdp break; 386733965Sjdp case 'b': 386833965Sjdp (*mangled)++; 386933965Sjdp APPEND_BLANK (result); 387033965Sjdp string_append (result, "bool"); 387160484Sobrien tk = tk_bool; 387233965Sjdp break; 387333965Sjdp case 'c': 387433965Sjdp (*mangled)++; 387533965Sjdp APPEND_BLANK (result); 387633965Sjdp string_append (result, "char"); 387760484Sobrien tk = tk_char; 387833965Sjdp break; 387933965Sjdp case 'w': 388033965Sjdp (*mangled)++; 388133965Sjdp APPEND_BLANK (result); 388233965Sjdp string_append (result, "wchar_t"); 388360484Sobrien tk = tk_char; 388433965Sjdp break; 388533965Sjdp case 'r': 388633965Sjdp (*mangled)++; 388733965Sjdp APPEND_BLANK (result); 388833965Sjdp string_append (result, "long double"); 388960484Sobrien tk = tk_real; 389033965Sjdp break; 389133965Sjdp case 'd': 389233965Sjdp (*mangled)++; 389333965Sjdp APPEND_BLANK (result); 389433965Sjdp string_append (result, "double"); 389560484Sobrien tk = tk_real; 389633965Sjdp break; 389733965Sjdp case 'f': 389833965Sjdp (*mangled)++; 389933965Sjdp APPEND_BLANK (result); 390033965Sjdp string_append (result, "float"); 390160484Sobrien tk = tk_real; 390233965Sjdp break; 390333965Sjdp case 'G': 390433965Sjdp (*mangled)++; 390577298Sobrien if (!ISDIGIT ((unsigned char)**mangled)) 390633965Sjdp { 390733965Sjdp success = 0; 390833965Sjdp break; 390933965Sjdp } 391060484Sobrien case 'I': 391160484Sobrien (*mangled)++; 391260484Sobrien if (**mangled == '_') 391360484Sobrien { 391460484Sobrien int i; 391560484Sobrien (*mangled)++; 391660484Sobrien for (i = 0; 391760484Sobrien i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; 391860484Sobrien (*mangled)++, i++) 391960484Sobrien buf[i] = **mangled; 392060484Sobrien if (**mangled != '_') 392160484Sobrien { 392260484Sobrien success = 0; 392360484Sobrien break; 392460484Sobrien } 392560484Sobrien buf[i] = '\0'; 392660484Sobrien (*mangled)++; 392760484Sobrien } 392860484Sobrien else 392960484Sobrien { 393060484Sobrien strncpy (buf, *mangled, 2); 393160484Sobrien buf[2] = '\0'; 393260484Sobrien *mangled += min (strlen (*mangled), 2); 393360484Sobrien } 393460484Sobrien sscanf (buf, "%x", &dec); 393568765Sobrien sprintf (buf, "int%u_t", dec); 393660484Sobrien APPEND_BLANK (result); 393760484Sobrien string_append (result, buf); 393860484Sobrien break; 393960484Sobrien 394033965Sjdp /* fall through */ 394133965Sjdp /* An explicit type, such as "6mytype" or "7integer" */ 394233965Sjdp case '0': 394333965Sjdp case '1': 394433965Sjdp case '2': 394533965Sjdp case '3': 394633965Sjdp case '4': 394733965Sjdp case '5': 394833965Sjdp case '6': 394933965Sjdp case '7': 395033965Sjdp case '8': 395133965Sjdp case '9': 395260484Sobrien { 395360484Sobrien int bindex = register_Btype (work); 395460484Sobrien string btype; 395560484Sobrien string_init (&btype); 395660484Sobrien if (demangle_class_name (work, mangled, &btype)) { 395760484Sobrien remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); 395860484Sobrien APPEND_BLANK (result); 395960484Sobrien string_appends (result, &btype); 396060484Sobrien } 396160484Sobrien else 396260484Sobrien success = 0; 396360484Sobrien string_delete (&btype); 396460484Sobrien break; 396533965Sjdp } 396633965Sjdp case 't': 396760484Sobrien { 396860484Sobrien success = demangle_template (work, mangled, &btype, 0, 1, 1); 396960484Sobrien string_appends (result, &btype); 397060484Sobrien break; 397160484Sobrien } 397233965Sjdp default: 397333965Sjdp success = 0; 397433965Sjdp break; 397533965Sjdp } 397633965Sjdp 397760484Sobrien return success ? ((int) tk) : 0; 397833965Sjdp} 397933965Sjdp 398033965Sjdp 398160484Sobrien/* Handle a template's value parameter for HP aCC (extension from ARM) 398260484Sobrien **mangled points to 'S' or 'U' */ 398360484Sobrien 398433965Sjdpstatic int 398560484Sobriendo_hpacc_template_const_value (work, mangled, result) 398660484Sobrien struct work_stuff *work ATTRIBUTE_UNUSED; 398760484Sobrien const char **mangled; 398860484Sobrien string *result; 398960484Sobrien{ 399060484Sobrien int unsigned_const; 399160484Sobrien 399260484Sobrien if (**mangled != 'U' && **mangled != 'S') 399360484Sobrien return 0; 399460484Sobrien 399560484Sobrien unsigned_const = (**mangled == 'U'); 399660484Sobrien 399760484Sobrien (*mangled)++; 399860484Sobrien 399960484Sobrien switch (**mangled) 400060484Sobrien { 400160484Sobrien case 'N': 400260484Sobrien string_append (result, "-"); 400360484Sobrien /* fall through */ 400460484Sobrien case 'P': 400560484Sobrien (*mangled)++; 400660484Sobrien break; 400760484Sobrien case 'M': 400860484Sobrien /* special case for -2^31 */ 400960484Sobrien string_append (result, "-2147483648"); 401060484Sobrien (*mangled)++; 401160484Sobrien return 1; 401260484Sobrien default: 401360484Sobrien return 0; 401460484Sobrien } 401560484Sobrien 401660484Sobrien /* We have to be looking at an integer now */ 401777298Sobrien if (!(ISDIGIT ((unsigned char)**mangled))) 401860484Sobrien return 0; 401960484Sobrien 402060484Sobrien /* We only deal with integral values for template 402160484Sobrien parameters -- so it's OK to look only for digits */ 402277298Sobrien while (ISDIGIT ((unsigned char)**mangled)) 402360484Sobrien { 402460484Sobrien char_str[0] = **mangled; 402560484Sobrien string_append (result, char_str); 402660484Sobrien (*mangled)++; 402760484Sobrien } 402860484Sobrien 402960484Sobrien if (unsigned_const) 403060484Sobrien string_append (result, "U"); 403160484Sobrien 403260484Sobrien /* FIXME? Some day we may have 64-bit (or larger :-) ) constants 403360484Sobrien with L or LL suffixes. pai/1997-09-03 */ 403460484Sobrien 403560484Sobrien return 1; /* success */ 403660484Sobrien} 403760484Sobrien 403860484Sobrien/* Handle a template's literal parameter for HP aCC (extension from ARM) 403960484Sobrien **mangled is pointing to the 'A' */ 404060484Sobrien 404160484Sobrienstatic int 404260484Sobriendo_hpacc_template_literal (work, mangled, result) 404360484Sobrien struct work_stuff *work; 404460484Sobrien const char **mangled; 404560484Sobrien string *result; 404660484Sobrien{ 404760484Sobrien int literal_len = 0; 404860484Sobrien char * recurse; 404960484Sobrien char * recurse_dem; 405060484Sobrien 405160484Sobrien if (**mangled != 'A') 405260484Sobrien return 0; 405360484Sobrien 405460484Sobrien (*mangled)++; 405560484Sobrien 405660484Sobrien literal_len = consume_count (mangled); 405760484Sobrien 405860484Sobrien if (literal_len <= 0) 405960484Sobrien return 0; 406060484Sobrien 406160484Sobrien /* Literal parameters are names of arrays, functions, etc. and the 406260484Sobrien canonical representation uses the address operator */ 406360484Sobrien string_append (result, "&"); 406460484Sobrien 406560484Sobrien /* Now recursively demangle the literal name */ 406660484Sobrien recurse = (char *) xmalloc (literal_len + 1); 406760484Sobrien memcpy (recurse, *mangled, literal_len); 406860484Sobrien recurse[literal_len] = '\000'; 406960484Sobrien 407060484Sobrien recurse_dem = cplus_demangle (recurse, work->options); 407160484Sobrien 407260484Sobrien if (recurse_dem) 407360484Sobrien { 407460484Sobrien string_append (result, recurse_dem); 407560484Sobrien free (recurse_dem); 407660484Sobrien } 407760484Sobrien else 407860484Sobrien { 407960484Sobrien string_appendn (result, *mangled, literal_len); 408060484Sobrien } 408160484Sobrien (*mangled) += literal_len; 408260484Sobrien free (recurse); 408360484Sobrien 408460484Sobrien return 1; 408560484Sobrien} 408660484Sobrien 408760484Sobrienstatic int 408860484Sobriensnarf_numeric_literal (args, arg) 408960484Sobrien const char ** args; 409060484Sobrien string * arg; 409160484Sobrien{ 409260484Sobrien if (**args == '-') 409360484Sobrien { 409460484Sobrien char_str[0] = '-'; 409560484Sobrien string_append (arg, char_str); 409660484Sobrien (*args)++; 409760484Sobrien } 409860484Sobrien else if (**args == '+') 409960484Sobrien (*args)++; 410060484Sobrien 410177298Sobrien if (!ISDIGIT ((unsigned char)**args)) 410260484Sobrien return 0; 410360484Sobrien 410477298Sobrien while (ISDIGIT ((unsigned char)**args)) 410560484Sobrien { 410660484Sobrien char_str[0] = **args; 410760484Sobrien string_append (arg, char_str); 410860484Sobrien (*args)++; 410960484Sobrien } 411060484Sobrien 411160484Sobrien return 1; 411260484Sobrien} 411360484Sobrien 411460484Sobrien/* Demangle the next argument, given by MANGLED into RESULT, which 411560484Sobrien *should be an uninitialized* string. It will be initialized here, 411660484Sobrien and free'd should anything go wrong. */ 411760484Sobrien 411860484Sobrienstatic int 411933965Sjdpdo_arg (work, mangled, result) 412033965Sjdp struct work_stuff *work; 412133965Sjdp const char **mangled; 412233965Sjdp string *result; 412333965Sjdp{ 412460484Sobrien /* Remember where we started so that we can record the type, for 412560484Sobrien non-squangling type remembering. */ 412633965Sjdp const char *start = *mangled; 412733965Sjdp 412860484Sobrien string_init (result); 412960484Sobrien 413060484Sobrien if (work->nrepeats > 0) 413133965Sjdp { 413260484Sobrien --work->nrepeats; 413360484Sobrien 413460484Sobrien if (work->previous_argument == 0) 413560484Sobrien return 0; 413660484Sobrien 413760484Sobrien /* We want to reissue the previous type in this argument list. */ 413860484Sobrien string_appends (result, work->previous_argument); 413960484Sobrien return 1; 414033965Sjdp } 414160484Sobrien 414260484Sobrien if (**mangled == 'n') 414360484Sobrien { 414460484Sobrien /* A squangling-style repeat. */ 414560484Sobrien (*mangled)++; 414660484Sobrien work->nrepeats = consume_count(mangled); 414760484Sobrien 414860484Sobrien if (work->nrepeats <= 0) 414960484Sobrien /* This was not a repeat count after all. */ 415060484Sobrien return 0; 415160484Sobrien 415260484Sobrien if (work->nrepeats > 9) 415360484Sobrien { 415460484Sobrien if (**mangled != '_') 415560484Sobrien /* The repeat count should be followed by an '_' in this 415660484Sobrien case. */ 415760484Sobrien return 0; 415860484Sobrien else 415960484Sobrien (*mangled)++; 416060484Sobrien } 416160484Sobrien 416260484Sobrien /* Now, the repeat is all set up. */ 416360484Sobrien return do_arg (work, mangled, result); 416460484Sobrien } 416560484Sobrien 416660484Sobrien /* Save the result in WORK->previous_argument so that we can find it 416760484Sobrien if it's repeated. Note that saving START is not good enough: we 416860484Sobrien do not want to add additional types to the back-referenceable 416960484Sobrien type vector when processing a repeated type. */ 417060484Sobrien if (work->previous_argument) 417160484Sobrien string_clear (work->previous_argument); 417233965Sjdp else 417333965Sjdp { 417460484Sobrien work->previous_argument = (string*) xmalloc (sizeof (string)); 417560484Sobrien string_init (work->previous_argument); 417633965Sjdp } 417760484Sobrien 417860484Sobrien if (!do_type (work, mangled, work->previous_argument)) 417960484Sobrien return 0; 418060484Sobrien 418160484Sobrien string_appends (result, work->previous_argument); 418260484Sobrien 418360484Sobrien remember_type (work, start, *mangled - start); 418460484Sobrien return 1; 418533965Sjdp} 418633965Sjdp 418733965Sjdpstatic void 418833965Sjdpremember_type (work, start, len) 418933965Sjdp struct work_stuff *work; 419033965Sjdp const char *start; 419133965Sjdp int len; 419233965Sjdp{ 419333965Sjdp char *tem; 419433965Sjdp 419560484Sobrien if (work->forgetting_types) 419660484Sobrien return; 419760484Sobrien 419833965Sjdp if (work -> ntypes >= work -> typevec_size) 419933965Sjdp { 420033965Sjdp if (work -> typevec_size == 0) 420133965Sjdp { 420233965Sjdp work -> typevec_size = 3; 420338889Sjdp work -> typevec 420438889Sjdp = (char **) xmalloc (sizeof (char *) * work -> typevec_size); 420533965Sjdp } 420633965Sjdp else 420733965Sjdp { 420833965Sjdp work -> typevec_size *= 2; 420938889Sjdp work -> typevec 421038889Sjdp = (char **) xrealloc ((char *)work -> typevec, 421138889Sjdp sizeof (char *) * work -> typevec_size); 421233965Sjdp } 421333965Sjdp } 421433965Sjdp tem = xmalloc (len + 1); 421533965Sjdp memcpy (tem, start, len); 421633965Sjdp tem[len] = '\0'; 421733965Sjdp work -> typevec[work -> ntypes++] = tem; 421833965Sjdp} 421933965Sjdp 422060484Sobrien 422160484Sobrien/* Remember a K type class qualifier. */ 422260484Sobrienstatic void 422360484Sobrienremember_Ktype (work, start, len) 422460484Sobrien struct work_stuff *work; 422560484Sobrien const char *start; 422660484Sobrien int len; 422760484Sobrien{ 422860484Sobrien char *tem; 422960484Sobrien 423060484Sobrien if (work -> numk >= work -> ksize) 423160484Sobrien { 423260484Sobrien if (work -> ksize == 0) 423360484Sobrien { 423460484Sobrien work -> ksize = 5; 423560484Sobrien work -> ktypevec 423660484Sobrien = (char **) xmalloc (sizeof (char *) * work -> ksize); 423760484Sobrien } 423860484Sobrien else 423960484Sobrien { 424060484Sobrien work -> ksize *= 2; 424160484Sobrien work -> ktypevec 424260484Sobrien = (char **) xrealloc ((char *)work -> ktypevec, 424360484Sobrien sizeof (char *) * work -> ksize); 424460484Sobrien } 424560484Sobrien } 424660484Sobrien tem = xmalloc (len + 1); 424760484Sobrien memcpy (tem, start, len); 424860484Sobrien tem[len] = '\0'; 424960484Sobrien work -> ktypevec[work -> numk++] = tem; 425060484Sobrien} 425160484Sobrien 425260484Sobrien/* Register a B code, and get an index for it. B codes are registered 425360484Sobrien as they are seen, rather than as they are completed, so map<temp<char> > 425460484Sobrien registers map<temp<char> > as B0, and temp<char> as B1 */ 425560484Sobrien 425660484Sobrienstatic int 425760484Sobrienregister_Btype (work) 425860484Sobrien struct work_stuff *work; 425960484Sobrien{ 426060484Sobrien int ret; 426160484Sobrien 426260484Sobrien if (work -> numb >= work -> bsize) 426360484Sobrien { 426460484Sobrien if (work -> bsize == 0) 426560484Sobrien { 426660484Sobrien work -> bsize = 5; 426760484Sobrien work -> btypevec 426860484Sobrien = (char **) xmalloc (sizeof (char *) * work -> bsize); 426960484Sobrien } 427060484Sobrien else 427160484Sobrien { 427260484Sobrien work -> bsize *= 2; 427360484Sobrien work -> btypevec 427460484Sobrien = (char **) xrealloc ((char *)work -> btypevec, 427560484Sobrien sizeof (char *) * work -> bsize); 427660484Sobrien } 427760484Sobrien } 427860484Sobrien ret = work -> numb++; 427960484Sobrien work -> btypevec[ret] = NULL; 428060484Sobrien return(ret); 428160484Sobrien} 428260484Sobrien 428360484Sobrien/* Store a value into a previously registered B code type. */ 428460484Sobrien 428560484Sobrienstatic void 428660484Sobrienremember_Btype (work, start, len, index) 428760484Sobrien struct work_stuff *work; 428860484Sobrien const char *start; 428960484Sobrien int len, index; 429060484Sobrien{ 429160484Sobrien char *tem; 429260484Sobrien 429360484Sobrien tem = xmalloc (len + 1); 429460484Sobrien memcpy (tem, start, len); 429560484Sobrien tem[len] = '\0'; 429660484Sobrien work -> btypevec[index] = tem; 429760484Sobrien} 429860484Sobrien 429960484Sobrien/* Lose all the info related to B and K type codes. */ 430060484Sobrienstatic void 430160484Sobrienforget_B_and_K_types (work) 430260484Sobrien struct work_stuff *work; 430360484Sobrien{ 430460484Sobrien int i; 430560484Sobrien 430660484Sobrien while (work -> numk > 0) 430760484Sobrien { 430860484Sobrien i = --(work -> numk); 430960484Sobrien if (work -> ktypevec[i] != NULL) 431060484Sobrien { 431160484Sobrien free (work -> ktypevec[i]); 431260484Sobrien work -> ktypevec[i] = NULL; 431360484Sobrien } 431460484Sobrien } 431560484Sobrien 431660484Sobrien while (work -> numb > 0) 431760484Sobrien { 431860484Sobrien i = --(work -> numb); 431960484Sobrien if (work -> btypevec[i] != NULL) 432060484Sobrien { 432160484Sobrien free (work -> btypevec[i]); 432260484Sobrien work -> btypevec[i] = NULL; 432360484Sobrien } 432460484Sobrien } 432560484Sobrien} 432633965Sjdp/* Forget the remembered types, but not the type vector itself. */ 432733965Sjdp 432833965Sjdpstatic void 432933965Sjdpforget_types (work) 433033965Sjdp struct work_stuff *work; 433133965Sjdp{ 433233965Sjdp int i; 433333965Sjdp 433433965Sjdp while (work -> ntypes > 0) 433533965Sjdp { 433633965Sjdp i = --(work -> ntypes); 433733965Sjdp if (work -> typevec[i] != NULL) 433833965Sjdp { 433933965Sjdp free (work -> typevec[i]); 434033965Sjdp work -> typevec[i] = NULL; 434133965Sjdp } 434233965Sjdp } 434333965Sjdp} 434433965Sjdp 434533965Sjdp/* Process the argument list part of the signature, after any class spec 434633965Sjdp has been consumed, as well as the first 'F' character (if any). For 434733965Sjdp example: 434833965Sjdp 434933965Sjdp "__als__3fooRT0" => process "RT0" 435033965Sjdp "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" 435133965Sjdp 435233965Sjdp DECLP must be already initialised, usually non-empty. It won't be freed 435333965Sjdp on failure. 435433965Sjdp 435533965Sjdp Note that g++ differs significantly from ARM and lucid style mangling 435633965Sjdp with regards to references to previously seen types. For example, given 435733965Sjdp the source fragment: 435833965Sjdp 435933965Sjdp class foo { 436033965Sjdp public: 436133965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); 436233965Sjdp }; 436333965Sjdp 436433965Sjdp foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 436533965Sjdp void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } 436633965Sjdp 436733965Sjdp g++ produces the names: 436833965Sjdp 436933965Sjdp __3fooiRT0iT2iT2 437033965Sjdp foo__FiR3fooiT1iT1 437133965Sjdp 437233965Sjdp while lcc (and presumably other ARM style compilers as well) produces: 437333965Sjdp 437433965Sjdp foo__FiR3fooT1T2T1T2 437533965Sjdp __ct__3fooFiR3fooT1T2T1T2 437633965Sjdp 437760484Sobrien Note that g++ bases its type numbers starting at zero and counts all 437860484Sobrien previously seen types, while lucid/ARM bases its type numbers starting 437933965Sjdp at one and only considers types after it has seen the 'F' character 438033965Sjdp indicating the start of the function args. For lucid/ARM style, we 438133965Sjdp account for this difference by discarding any previously seen types when 438233965Sjdp we see the 'F' character, and subtracting one from the type number 438333965Sjdp reference. 438433965Sjdp 438533965Sjdp */ 438633965Sjdp 438733965Sjdpstatic int 438833965Sjdpdemangle_args (work, mangled, declp) 438933965Sjdp struct work_stuff *work; 439033965Sjdp const char **mangled; 439133965Sjdp string *declp; 439233965Sjdp{ 439333965Sjdp string arg; 439433965Sjdp int need_comma = 0; 439533965Sjdp int r; 439633965Sjdp int t; 439733965Sjdp const char *tem; 439833965Sjdp char temptype; 439933965Sjdp 440033965Sjdp if (PRINT_ARG_TYPES) 440133965Sjdp { 440233965Sjdp string_append (declp, "("); 440333965Sjdp if (**mangled == '\0') 440433965Sjdp { 440533965Sjdp string_append (declp, "void"); 440633965Sjdp } 440733965Sjdp } 440833965Sjdp 440960484Sobrien while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') 441060484Sobrien || work->nrepeats > 0) 441133965Sjdp { 441233965Sjdp if ((**mangled == 'N') || (**mangled == 'T')) 441333965Sjdp { 441433965Sjdp temptype = *(*mangled)++; 441560484Sobrien 441633965Sjdp if (temptype == 'N') 441733965Sjdp { 441833965Sjdp if (!get_count (mangled, &r)) 441933965Sjdp { 442033965Sjdp return (0); 442133965Sjdp } 442233965Sjdp } 442333965Sjdp else 442433965Sjdp { 442533965Sjdp r = 1; 442633965Sjdp } 442760484Sobrien if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) 442833965Sjdp { 442933965Sjdp /* If we have 10 or more types we might have more than a 1 digit 443033965Sjdp index so we'll have to consume the whole count here. This 443133965Sjdp will lose if the next thing is a type name preceded by a 443233965Sjdp count but it's impossible to demangle that case properly 443333965Sjdp anyway. Eg if we already have 12 types is T12Pc "(..., type1, 443433965Sjdp Pc, ...)" or "(..., type12, char *, ...)" */ 443560484Sobrien if ((t = consume_count(mangled)) <= 0) 443633965Sjdp { 443733965Sjdp return (0); 443833965Sjdp } 443933965Sjdp } 444033965Sjdp else 444133965Sjdp { 444233965Sjdp if (!get_count (mangled, &t)) 444333965Sjdp { 444433965Sjdp return (0); 444533965Sjdp } 444633965Sjdp } 444760484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 444833965Sjdp { 444933965Sjdp t--; 445033965Sjdp } 445133965Sjdp /* Validate the type index. Protect against illegal indices from 445233965Sjdp malformed type strings. */ 445333965Sjdp if ((t < 0) || (t >= work -> ntypes)) 445433965Sjdp { 445533965Sjdp return (0); 445633965Sjdp } 445760484Sobrien while (work->nrepeats > 0 || --r >= 0) 445833965Sjdp { 445933965Sjdp tem = work -> typevec[t]; 446033965Sjdp if (need_comma && PRINT_ARG_TYPES) 446133965Sjdp { 446233965Sjdp string_append (declp, ", "); 446333965Sjdp } 446433965Sjdp if (!do_arg (work, &tem, &arg)) 446533965Sjdp { 446633965Sjdp return (0); 446733965Sjdp } 446833965Sjdp if (PRINT_ARG_TYPES) 446933965Sjdp { 447033965Sjdp string_appends (declp, &arg); 447133965Sjdp } 447233965Sjdp string_delete (&arg); 447333965Sjdp need_comma = 1; 447433965Sjdp } 447533965Sjdp } 447633965Sjdp else 447733965Sjdp { 447860484Sobrien if (need_comma && PRINT_ARG_TYPES) 447960484Sobrien string_append (declp, ", "); 448033965Sjdp if (!do_arg (work, mangled, &arg)) 448160484Sobrien return (0); 448233965Sjdp if (PRINT_ARG_TYPES) 448360484Sobrien string_appends (declp, &arg); 448433965Sjdp string_delete (&arg); 448533965Sjdp need_comma = 1; 448633965Sjdp } 448733965Sjdp } 448833965Sjdp 448933965Sjdp if (**mangled == 'e') 449033965Sjdp { 449133965Sjdp (*mangled)++; 449233965Sjdp if (PRINT_ARG_TYPES) 449333965Sjdp { 449433965Sjdp if (need_comma) 449533965Sjdp { 449633965Sjdp string_append (declp, ","); 449733965Sjdp } 449833965Sjdp string_append (declp, "..."); 449933965Sjdp } 450033965Sjdp } 450133965Sjdp 450233965Sjdp if (PRINT_ARG_TYPES) 450333965Sjdp { 450433965Sjdp string_append (declp, ")"); 450533965Sjdp } 450633965Sjdp return (1); 450733965Sjdp} 450833965Sjdp 450960484Sobrien/* Like demangle_args, but for demangling the argument lists of function 451060484Sobrien and method pointers or references, not top-level declarations. */ 451160484Sobrien 451260484Sobrienstatic int 451360484Sobriendemangle_nested_args (work, mangled, declp) 451460484Sobrien struct work_stuff *work; 451560484Sobrien const char **mangled; 451660484Sobrien string *declp; 451760484Sobrien{ 451860484Sobrien string* saved_previous_argument; 451960484Sobrien int result; 452060484Sobrien int saved_nrepeats; 452160484Sobrien 452260484Sobrien /* The G++ name-mangling algorithm does not remember types on nested 452360484Sobrien argument lists, unless -fsquangling is used, and in that case the 452460484Sobrien type vector updated by remember_type is not used. So, we turn 452560484Sobrien off remembering of types here. */ 452660484Sobrien ++work->forgetting_types; 452760484Sobrien 452860484Sobrien /* For the repeat codes used with -fsquangling, we must keep track of 452960484Sobrien the last argument. */ 453060484Sobrien saved_previous_argument = work->previous_argument; 453160484Sobrien saved_nrepeats = work->nrepeats; 453260484Sobrien work->previous_argument = 0; 453360484Sobrien work->nrepeats = 0; 453460484Sobrien 453560484Sobrien /* Actually demangle the arguments. */ 453660484Sobrien result = demangle_args (work, mangled, declp); 453760484Sobrien 453860484Sobrien /* Restore the previous_argument field. */ 453960484Sobrien if (work->previous_argument) 454060484Sobrien string_delete (work->previous_argument); 454160484Sobrien work->previous_argument = saved_previous_argument; 454260484Sobrien --work->forgetting_types; 454360484Sobrien work->nrepeats = saved_nrepeats; 454460484Sobrien 454560484Sobrien return result; 454660484Sobrien} 454760484Sobrien 454833965Sjdpstatic void 454933965Sjdpdemangle_function_name (work, mangled, declp, scan) 455033965Sjdp struct work_stuff *work; 455133965Sjdp const char **mangled; 455233965Sjdp string *declp; 455333965Sjdp const char *scan; 455433965Sjdp{ 455560484Sobrien size_t i; 455633965Sjdp string type; 455733965Sjdp const char *tem; 455833965Sjdp 455933965Sjdp string_appendn (declp, (*mangled), scan - (*mangled)); 456033965Sjdp string_need (declp, 1); 456133965Sjdp *(declp -> p) = '\0'; 456233965Sjdp 456333965Sjdp /* Consume the function name, including the "__" separating the name 456433965Sjdp from the signature. We are guaranteed that SCAN points to the 456533965Sjdp separator. */ 456633965Sjdp 456733965Sjdp (*mangled) = scan + 2; 456860484Sobrien /* We may be looking at an instantiation of a template function: 456960484Sobrien foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a 457060484Sobrien following _F marks the start of the function arguments. Handle 457160484Sobrien the template arguments first. */ 457233965Sjdp 457360484Sobrien if (HP_DEMANGLING && (**mangled == 'X')) 457433965Sjdp { 457560484Sobrien demangle_arm_hp_template (work, mangled, 0, declp); 457660484Sobrien /* This leaves MANGLED pointing to the 'F' marking func args */ 457760484Sobrien } 457833965Sjdp 457960484Sobrien if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) 458060484Sobrien { 458160484Sobrien 458233965Sjdp /* See if we have an ARM style constructor or destructor operator. 458333965Sjdp If so, then just record it, clear the decl, and return. 458433965Sjdp We can't build the actual constructor/destructor decl until later, 458533965Sjdp when we recover the class name from the signature. */ 458633965Sjdp 458733965Sjdp if (strcmp (declp -> b, "__ct") == 0) 458833965Sjdp { 458933965Sjdp work -> constructor += 1; 459033965Sjdp string_clear (declp); 459133965Sjdp return; 459233965Sjdp } 459333965Sjdp else if (strcmp (declp -> b, "__dt") == 0) 459433965Sjdp { 459533965Sjdp work -> destructor += 1; 459633965Sjdp string_clear (declp); 459733965Sjdp return; 459833965Sjdp } 459933965Sjdp } 460033965Sjdp 460160484Sobrien if (declp->p - declp->b >= 3 460233965Sjdp && declp->b[0] == 'o' 460333965Sjdp && declp->b[1] == 'p' 460433965Sjdp && strchr (cplus_markers, declp->b[2]) != NULL) 460533965Sjdp { 460633965Sjdp /* see if it's an assignment expression */ 460733965Sjdp if (declp->p - declp->b >= 10 /* op$assign_ */ 460833965Sjdp && memcmp (declp->b + 3, "assign_", 7) == 0) 460933965Sjdp { 461077298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 461133965Sjdp { 461260484Sobrien int len = declp->p - declp->b - 10; 461360484Sobrien if ((int) strlen (optable[i].in) == len 461433965Sjdp && memcmp (optable[i].in, declp->b + 10, len) == 0) 461533965Sjdp { 461633965Sjdp string_clear (declp); 461733965Sjdp string_append (declp, "operator"); 461833965Sjdp string_append (declp, optable[i].out); 461933965Sjdp string_append (declp, "="); 462033965Sjdp break; 462133965Sjdp } 462233965Sjdp } 462333965Sjdp } 462433965Sjdp else 462533965Sjdp { 462677298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 462733965Sjdp { 462833965Sjdp int len = declp->p - declp->b - 3; 462960484Sobrien if ((int) strlen (optable[i].in) == len 463033965Sjdp && memcmp (optable[i].in, declp->b + 3, len) == 0) 463133965Sjdp { 463233965Sjdp string_clear (declp); 463333965Sjdp string_append (declp, "operator"); 463433965Sjdp string_append (declp, optable[i].out); 463533965Sjdp break; 463633965Sjdp } 463733965Sjdp } 463833965Sjdp } 463933965Sjdp } 464033965Sjdp else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 464133965Sjdp && strchr (cplus_markers, declp->b[4]) != NULL) 464233965Sjdp { 464333965Sjdp /* type conversion operator */ 464433965Sjdp tem = declp->b + 5; 464533965Sjdp if (do_type (work, &tem, &type)) 464633965Sjdp { 464733965Sjdp string_clear (declp); 464833965Sjdp string_append (declp, "operator "); 464933965Sjdp string_appends (declp, &type); 465033965Sjdp string_delete (&type); 465133965Sjdp } 465233965Sjdp } 465333965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 465433965Sjdp && declp->b[2] == 'o' && declp->b[3] == 'p') 465533965Sjdp { 465633965Sjdp /* ANSI. */ 465733965Sjdp /* type conversion operator. */ 465833965Sjdp tem = declp->b + 4; 465933965Sjdp if (do_type (work, &tem, &type)) 466033965Sjdp { 466133965Sjdp string_clear (declp); 466233965Sjdp string_append (declp, "operator "); 466333965Sjdp string_appends (declp, &type); 466433965Sjdp string_delete (&type); 466533965Sjdp } 466633965Sjdp } 466733965Sjdp else if (declp->b[0] == '_' && declp->b[1] == '_' 466877298Sobrien && ISLOWER((unsigned char)declp->b[2]) 466977298Sobrien && ISLOWER((unsigned char)declp->b[3])) 467033965Sjdp { 467133965Sjdp if (declp->b[4] == '\0') 467233965Sjdp { 467333965Sjdp /* Operator. */ 467477298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 467533965Sjdp { 467633965Sjdp if (strlen (optable[i].in) == 2 467733965Sjdp && memcmp (optable[i].in, declp->b + 2, 2) == 0) 467833965Sjdp { 467933965Sjdp string_clear (declp); 468033965Sjdp string_append (declp, "operator"); 468133965Sjdp string_append (declp, optable[i].out); 468233965Sjdp break; 468333965Sjdp } 468433965Sjdp } 468533965Sjdp } 468633965Sjdp else 468733965Sjdp { 468833965Sjdp if (declp->b[2] == 'a' && declp->b[5] == '\0') 468933965Sjdp { 469033965Sjdp /* Assignment. */ 469177298Sobrien for (i = 0; i < ARRAY_SIZE (optable); i++) 469233965Sjdp { 469333965Sjdp if (strlen (optable[i].in) == 3 469433965Sjdp && memcmp (optable[i].in, declp->b + 2, 3) == 0) 469533965Sjdp { 469633965Sjdp string_clear (declp); 469733965Sjdp string_append (declp, "operator"); 469833965Sjdp string_append (declp, optable[i].out); 469933965Sjdp break; 470060484Sobrien } 470133965Sjdp } 470233965Sjdp } 470333965Sjdp } 470433965Sjdp } 470533965Sjdp} 470633965Sjdp 470733965Sjdp/* a mini string-handling package */ 470833965Sjdp 470933965Sjdpstatic void 471033965Sjdpstring_need (s, n) 471133965Sjdp string *s; 471233965Sjdp int n; 471333965Sjdp{ 471433965Sjdp int tem; 471533965Sjdp 471633965Sjdp if (s->b == NULL) 471733965Sjdp { 471833965Sjdp if (n < 32) 471933965Sjdp { 472033965Sjdp n = 32; 472133965Sjdp } 472233965Sjdp s->p = s->b = xmalloc (n); 472333965Sjdp s->e = s->b + n; 472433965Sjdp } 472533965Sjdp else if (s->e - s->p < n) 472633965Sjdp { 472733965Sjdp tem = s->p - s->b; 472833965Sjdp n += tem; 472933965Sjdp n *= 2; 473033965Sjdp s->b = xrealloc (s->b, n); 473133965Sjdp s->p = s->b + tem; 473233965Sjdp s->e = s->b + n; 473333965Sjdp } 473433965Sjdp} 473533965Sjdp 473633965Sjdpstatic void 473733965Sjdpstring_delete (s) 473833965Sjdp string *s; 473933965Sjdp{ 474033965Sjdp if (s->b != NULL) 474133965Sjdp { 474233965Sjdp free (s->b); 474333965Sjdp s->b = s->e = s->p = NULL; 474433965Sjdp } 474533965Sjdp} 474633965Sjdp 474733965Sjdpstatic void 474833965Sjdpstring_init (s) 474933965Sjdp string *s; 475033965Sjdp{ 475133965Sjdp s->b = s->p = s->e = NULL; 475233965Sjdp} 475333965Sjdp 475460484Sobrienstatic void 475533965Sjdpstring_clear (s) 475633965Sjdp string *s; 475733965Sjdp{ 475833965Sjdp s->p = s->b; 475933965Sjdp} 476033965Sjdp 476133965Sjdp#if 0 476233965Sjdp 476333965Sjdpstatic int 476433965Sjdpstring_empty (s) 476533965Sjdp string *s; 476633965Sjdp{ 476733965Sjdp return (s->b == s->p); 476833965Sjdp} 476933965Sjdp 477033965Sjdp#endif 477133965Sjdp 477233965Sjdpstatic void 477333965Sjdpstring_append (p, s) 477433965Sjdp string *p; 477533965Sjdp const char *s; 477633965Sjdp{ 477733965Sjdp int n; 477833965Sjdp if (s == NULL || *s == '\0') 477933965Sjdp return; 478033965Sjdp n = strlen (s); 478133965Sjdp string_need (p, n); 478233965Sjdp memcpy (p->p, s, n); 478333965Sjdp p->p += n; 478433965Sjdp} 478533965Sjdp 478633965Sjdpstatic void 478733965Sjdpstring_appends (p, s) 478833965Sjdp string *p, *s; 478933965Sjdp{ 479033965Sjdp int n; 479133965Sjdp 479233965Sjdp if (s->b != s->p) 479333965Sjdp { 479433965Sjdp n = s->p - s->b; 479533965Sjdp string_need (p, n); 479633965Sjdp memcpy (p->p, s->b, n); 479733965Sjdp p->p += n; 479833965Sjdp } 479933965Sjdp} 480033965Sjdp 480133965Sjdpstatic void 480233965Sjdpstring_appendn (p, s, n) 480333965Sjdp string *p; 480433965Sjdp const char *s; 480533965Sjdp int n; 480633965Sjdp{ 480733965Sjdp if (n != 0) 480833965Sjdp { 480933965Sjdp string_need (p, n); 481033965Sjdp memcpy (p->p, s, n); 481133965Sjdp p->p += n; 481233965Sjdp } 481333965Sjdp} 481433965Sjdp 481533965Sjdpstatic void 481633965Sjdpstring_prepend (p, s) 481733965Sjdp string *p; 481833965Sjdp const char *s; 481933965Sjdp{ 482033965Sjdp if (s != NULL && *s != '\0') 482133965Sjdp { 482233965Sjdp string_prependn (p, s, strlen (s)); 482333965Sjdp } 482433965Sjdp} 482533965Sjdp 482633965Sjdpstatic void 482733965Sjdpstring_prepends (p, s) 482833965Sjdp string *p, *s; 482933965Sjdp{ 483033965Sjdp if (s->b != s->p) 483133965Sjdp { 483233965Sjdp string_prependn (p, s->b, s->p - s->b); 483333965Sjdp } 483433965Sjdp} 483533965Sjdp 483633965Sjdpstatic void 483733965Sjdpstring_prependn (p, s, n) 483833965Sjdp string *p; 483933965Sjdp const char *s; 484033965Sjdp int n; 484133965Sjdp{ 484233965Sjdp char *q; 484333965Sjdp 484433965Sjdp if (n != 0) 484533965Sjdp { 484633965Sjdp string_need (p, n); 484733965Sjdp for (q = p->p - 1; q >= p->b; q--) 484833965Sjdp { 484933965Sjdp q[n] = q[0]; 485033965Sjdp } 485133965Sjdp memcpy (p->b, s, n); 485233965Sjdp p->p += n; 485333965Sjdp } 485433965Sjdp} 485533965Sjdp 485660484Sobrienstatic void 485760484Sobrienstring_append_template_idx (s, idx) 485860484Sobrien string *s; 485960484Sobrien int idx; 486060484Sobrien{ 486160484Sobrien char buf[INTBUF_SIZE + 1 /* 'T' */]; 486260484Sobrien sprintf(buf, "T%d", idx); 486360484Sobrien string_append (s, buf); 486460484Sobrien} 486560484Sobrien 486633965Sjdp/* To generate a standalone demangler program for testing purposes, 486733965Sjdp just compile and link this file with -DMAIN and libiberty.a. When 486833965Sjdp run, it demangles each command line arg, or each stdin string, and 486933965Sjdp prints the result on stdout. */ 487033965Sjdp 487133965Sjdp#ifdef MAIN 487233965Sjdp 487338889Sjdp#include "getopt.h" 487438889Sjdp 487560484Sobrienstatic const char *program_name; 487660484Sobrienstatic const char *program_version = VERSION; 487791041Sobrienstatic int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE; 487838889Sjdp 487933965Sjdpstatic void demangle_it PARAMS ((char *)); 488060484Sobrienstatic void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN; 488160484Sobrienstatic void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN; 488268765Sobrienstatic void print_demangler_list PARAMS ((FILE *)); 488333965Sjdp 488433965Sjdpstatic void 488533965Sjdpdemangle_it (mangled_name) 488633965Sjdp char *mangled_name; 488733965Sjdp{ 488833965Sjdp char *result; 488933965Sjdp 489091041Sobrien /* For command line args, also try to demangle type encodings. */ 489191041Sobrien result = cplus_demangle (mangled_name, flags | DMGL_TYPES); 489233965Sjdp if (result == NULL) 489333965Sjdp { 489433965Sjdp printf ("%s\n", mangled_name); 489533965Sjdp } 489633965Sjdp else 489733965Sjdp { 489833965Sjdp printf ("%s\n", result); 489933965Sjdp free (result); 490033965Sjdp } 490133965Sjdp} 490233965Sjdp 490368765Sobrienstatic void 490468765Sobrienprint_demangler_list (stream) 490568765Sobrien FILE *stream; 490668765Sobrien{ 490789857Sobrien const struct demangler_engine *demangler; 490868765Sobrien 490968765Sobrien fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name); 491068765Sobrien 491168765Sobrien for (demangler = libiberty_demanglers + 1; 491268765Sobrien demangler->demangling_style != unknown_demangling; 491368765Sobrien ++demangler) 491468765Sobrien fprintf (stream, ",%s", demangler->demangling_style_name); 491568765Sobrien 491668765Sobrien fprintf (stream, "}"); 491768765Sobrien} 491868765Sobrien 491933965Sjdpstatic void 492033965Sjdpusage (stream, status) 492133965Sjdp FILE *stream; 492233965Sjdp int status; 492360484Sobrien{ 492433965Sjdp fprintf (stream, "\ 492568765SobrienUsage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n", 492633965Sjdp program_name); 492768765Sobrien 492868765Sobrien fprintf (stream, "\ 492968765Sobrien [-s "); 493068765Sobrien print_demangler_list (stream); 493168765Sobrien fprintf (stream, "]\n"); 493268765Sobrien 493368765Sobrien fprintf (stream, "\ 493468765Sobrien [--format "); 493568765Sobrien print_demangler_list (stream); 493668765Sobrien fprintf (stream, "]\n"); 493768765Sobrien 493868765Sobrien fprintf (stream, "\ 493968765Sobrien [--help] [--version] [arg...]\n"); 494033965Sjdp exit (status); 494133965Sjdp} 494233965Sjdp 494360484Sobrien#define MBUF_SIZE 32767 494433965Sjdpchar mbuffer[MBUF_SIZE]; 494533965Sjdp 494633965Sjdp/* Defined in the automatically-generated underscore.c. */ 494733965Sjdpextern int prepends_underscore; 494833965Sjdp 494933965Sjdpint strip_underscore = 0; 495033965Sjdp 495189857Sobrienstatic const struct option long_options[] = { 495233965Sjdp {"strip-underscores", no_argument, 0, '_'}, 495333965Sjdp {"format", required_argument, 0, 's'}, 495433965Sjdp {"help", no_argument, 0, 'h'}, 495533965Sjdp {"no-strip-underscores", no_argument, 0, 'n'}, 495633965Sjdp {"version", no_argument, 0, 'v'}, 495733965Sjdp {0, no_argument, 0, 0} 495833965Sjdp}; 495933965Sjdp 496060484Sobrien/* More 'friendly' abort that prints the line and file. 496160484Sobrien config.h can #define abort fancy_abort if you like that sort of thing. */ 496260484Sobrien 496360484Sobrienvoid 496460484Sobrienfancy_abort () 496560484Sobrien{ 496660484Sobrien fatal ("Internal gcc abort."); 496760484Sobrien} 496860484Sobrien 496960484Sobrien 497060484Sobrienstatic const char * 497160484Sobrienstandard_symbol_characters PARAMS ((void)); 497260484Sobrien 497360484Sobrienstatic const char * 497460484Sobrienhp_symbol_characters PARAMS ((void)); 497560484Sobrien 497668765Sobrienstatic const char * 497777298Sobriengnu_v3_symbol_characters PARAMS ((void)); 497868765Sobrien 497960484Sobrien/* Return the string of non-alnum characters that may occur 498060484Sobrien as a valid symbol component, in the standard assembler symbol 498160484Sobrien syntax. */ 498260484Sobrien 498360484Sobrienstatic const char * 498460484Sobrienstandard_symbol_characters () 498560484Sobrien{ 498660484Sobrien return "_$."; 498760484Sobrien} 498860484Sobrien 498960484Sobrien 499060484Sobrien/* Return the string of non-alnum characters that may occur 499160484Sobrien as a valid symbol name component in an HP object file. 499260484Sobrien 499360484Sobrien Note that, since HP's compiler generates object code straight from 499460484Sobrien C++ source, without going through an assembler, its mangled 499560484Sobrien identifiers can use all sorts of characters that no assembler would 499660484Sobrien tolerate, so the alphabet this function creates is a little odd. 499760484Sobrien Here are some sample mangled identifiers offered by HP: 499860484Sobrien 499960484Sobrien typeid*__XT24AddressIndExpClassMember_ 500060484Sobrien [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv 500160484Sobrien __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv 500260484Sobrien 500360484Sobrien This still seems really weird to me, since nowhere else in this 500460484Sobrien file is there anything to recognize curly brackets, parens, etc. 500560484Sobrien I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me 500660484Sobrien this is right, but I still strongly suspect that there's a 500760484Sobrien misunderstanding here. 500860484Sobrien 500960484Sobrien If we decide it's better for c++filt to use HP's assembler syntax 501060484Sobrien to scrape identifiers out of its input, here's the definition of 501160484Sobrien the symbol name syntax from the HP assembler manual: 501260484Sobrien 501360484Sobrien Symbols are composed of uppercase and lowercase letters, decimal 501460484Sobrien digits, dollar symbol, period (.), ampersand (&), pound sign(#) and 501560484Sobrien underscore (_). A symbol can begin with a letter, digit underscore or 501660484Sobrien dollar sign. If a symbol begins with a digit, it must contain a 501760484Sobrien non-digit character. 501860484Sobrien 501960484Sobrien So have fun. */ 502060484Sobrienstatic const char * 502160484Sobrienhp_symbol_characters () 502260484Sobrien{ 502360484Sobrien return "_$.<>#,*&[]:(){}"; 502460484Sobrien} 502560484Sobrien 502660484Sobrien 502768765Sobrien/* Return the string of non-alnum characters that may occur 502877298Sobrien as a valid symbol component in the GNU C++ V3 ABI mangling 502968765Sobrien scheme. */ 503068765Sobrien 503168765Sobrienstatic const char * 503277298Sobriengnu_v3_symbol_characters () 503368765Sobrien{ 503477298Sobrien return "_$."; 503568765Sobrien} 503668765Sobrien 503768765Sobrien 503860484Sobrienextern int main PARAMS ((int, char **)); 503960484Sobrien 504033965Sjdpint 504133965Sjdpmain (argc, argv) 504233965Sjdp int argc; 504333965Sjdp char **argv; 504433965Sjdp{ 504533965Sjdp char *result; 504633965Sjdp int c; 504760484Sobrien const char *valid_symbols; 504889857Sobrien enum demangling_styles style = auto_demangling; 504933965Sjdp 505033965Sjdp program_name = argv[0]; 505133965Sjdp 505233965Sjdp strip_underscore = prepends_underscore; 505333965Sjdp 505489857Sobrien while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF) 505533965Sjdp { 505633965Sjdp switch (c) 505733965Sjdp { 505833965Sjdp case '?': 505933965Sjdp usage (stderr, 1); 506033965Sjdp break; 506133965Sjdp case 'h': 506233965Sjdp usage (stdout, 0); 506333965Sjdp case 'n': 506433965Sjdp strip_underscore = 0; 506533965Sjdp break; 506633965Sjdp case 'v': 506760484Sobrien printf ("GNU %s (C++ demangler), version %s\n", program_name, program_version); 506860484Sobrien return (0); 506933965Sjdp case '_': 507033965Sjdp strip_underscore = 1; 507133965Sjdp break; 507233965Sjdp case 's': 507368765Sobrien { 507468765Sobrien style = cplus_demangle_name_to_style (optarg); 507568765Sobrien if (style == unknown_demangling) 507668765Sobrien { 507768765Sobrien fprintf (stderr, "%s: unknown demangling style `%s'\n", 507868765Sobrien program_name, optarg); 507968765Sobrien return (1); 508068765Sobrien } 508168765Sobrien else 508268765Sobrien cplus_demangle_set_style (style); 508368765Sobrien } 508433965Sjdp break; 508533965Sjdp } 508633965Sjdp } 508733965Sjdp 508833965Sjdp if (optind < argc) 508933965Sjdp { 509033965Sjdp for ( ; optind < argc; optind++) 509133965Sjdp { 509233965Sjdp demangle_it (argv[optind]); 509333965Sjdp } 509433965Sjdp } 509533965Sjdp else 509633965Sjdp { 509760484Sobrien switch (current_demangling_style) 509860484Sobrien { 509960484Sobrien case gnu_demangling: 510060484Sobrien case lucid_demangling: 510160484Sobrien case arm_demangling: 510277298Sobrien case java_demangling: 510360484Sobrien case edg_demangling: 510477298Sobrien case gnat_demangling: 510577298Sobrien case auto_demangling: 510660484Sobrien valid_symbols = standard_symbol_characters (); 510760484Sobrien break; 510860484Sobrien case hp_demangling: 510960484Sobrien valid_symbols = hp_symbol_characters (); 511060484Sobrien break; 511177298Sobrien case gnu_v3_demangling: 511277298Sobrien valid_symbols = gnu_v3_symbol_characters (); 511368765Sobrien break; 511460484Sobrien default: 511560484Sobrien /* Folks should explicitly indicate the appropriate alphabet for 511660484Sobrien each demangling. Providing a default would allow the 511760484Sobrien question to go unconsidered. */ 511860484Sobrien abort (); 511960484Sobrien } 512060484Sobrien 512133965Sjdp for (;;) 512233965Sjdp { 512333965Sjdp int i = 0; 512433965Sjdp c = getchar (); 512533965Sjdp /* Try to read a label. */ 512677298Sobrien while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c))) 512733965Sjdp { 512833965Sjdp if (i >= MBUF_SIZE-1) 512933965Sjdp break; 513033965Sjdp mbuffer[i++] = c; 513133965Sjdp c = getchar (); 513233965Sjdp } 513333965Sjdp if (i > 0) 513433965Sjdp { 513533965Sjdp int skip_first = 0; 513633965Sjdp 513789857Sobrien if (mbuffer[0] == '.' || mbuffer[0] == '$') 513833965Sjdp ++skip_first; 513933965Sjdp if (strip_underscore && mbuffer[skip_first] == '_') 514033965Sjdp ++skip_first; 514133965Sjdp 514233965Sjdp if (skip_first > i) 514333965Sjdp skip_first = i; 514433965Sjdp 514533965Sjdp mbuffer[i] = 0; 514689857Sobrien flags |= (int) style; 514738889Sjdp result = cplus_demangle (mbuffer + skip_first, flags); 514833965Sjdp if (result) 514933965Sjdp { 515033965Sjdp if (mbuffer[0] == '.') 515133965Sjdp putc ('.', stdout); 515233965Sjdp fputs (result, stdout); 515333965Sjdp free (result); 515433965Sjdp } 515533965Sjdp else 515633965Sjdp fputs (mbuffer, stdout); 515733965Sjdp 515833965Sjdp fflush (stdout); 515933965Sjdp } 516033965Sjdp if (c == EOF) 516133965Sjdp break; 516233965Sjdp putchar (c); 516368765Sobrien fflush (stdout); 516433965Sjdp } 516533965Sjdp } 516633965Sjdp 516760484Sobrien return (0); 516833965Sjdp} 516933965Sjdp 517033965Sjdpstatic void 517133965Sjdpfatal (str) 517260484Sobrien const char *str; 517333965Sjdp{ 517433965Sjdp fprintf (stderr, "%s: %s\n", program_name, str); 517533965Sjdp exit (1); 517633965Sjdp} 517733965Sjdp 517860484SobrienPTR 517933965Sjdpxmalloc (size) 518060484Sobrien size_t size; 518133965Sjdp{ 518260484Sobrien register PTR value = (PTR) malloc (size); 518333965Sjdp if (value == 0) 518433965Sjdp fatal ("virtual memory exhausted"); 518533965Sjdp return value; 518633965Sjdp} 518733965Sjdp 518860484SobrienPTR 518933965Sjdpxrealloc (ptr, size) 519060484Sobrien PTR ptr; 519160484Sobrien size_t size; 519233965Sjdp{ 519360484Sobrien register PTR value = (PTR) realloc (ptr, size); 519433965Sjdp if (value == 0) 519533965Sjdp fatal ("virtual memory exhausted"); 519633965Sjdp return value; 519733965Sjdp} 519833965Sjdp#endif /* main */ 5199