1130561Sobrien/* Demangler for GNU C++ - main program 2130561Sobrien Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 3218822Sdim 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. 4130561Sobrien Written by James Clark (jjc@jclark.uucp) 5130561Sobrien Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling 6130561Sobrien Modified by Satish Pai (pai@apollo.hp.com) for HP demangling 7130561Sobrien 8218822Sdim This file is part of GCC. 9130561Sobrien 10218822Sdim GCC is free software; you can redistribute it and/or modify it under 11218822Sdim the terms of the GNU General Public License as published by the Free 12218822Sdim Software Foundation; either version 2, or (at your option) any later 13218822Sdim version. 14130561Sobrien 15218822Sdim GCC is distributed in the hope that it will be useful, but WITHOUT ANY 16218822Sdim WARRANTY; without even the implied warranty of MERCHANTABILITY or 17218822Sdim FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18218822Sdim for more details. 19130561Sobrien 20218822Sdim You should have received a copy of the GNU General Public License 21218822Sdim along with GCC; see the file COPYING. If not, write to the Free 22218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 23218822Sdim 02110-1301, USA. */ 24130561Sobrien 25218822Sdim#include "sysdep.h" 26130561Sobrien#include "bfd.h" 27130561Sobrien#include "libiberty.h" 28130561Sobrien#include "demangle.h" 29130561Sobrien#include "getopt.h" 30130561Sobrien#include "safe-ctype.h" 31218822Sdim#include "bucomm.h" 32130561Sobrien 33130561Sobrienstatic int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE; 34218822Sdimstatic int strip_underscore = TARGET_PREPENDS_UNDERSCORE; 35130561Sobrien 36218822Sdimstatic const struct option long_options[] = 37218822Sdim{ 38218822Sdim {"strip-underscore", no_argument, NULL, '_'}, 39218822Sdim {"format", required_argument, NULL, 's'}, 40218822Sdim {"help", no_argument, NULL, 'h'}, 41218822Sdim {"no-params", no_argument, NULL, 'p'}, 42218822Sdim {"no-strip-underscores", no_argument, NULL, 'n'}, 43218822Sdim {"no-verbose", no_argument, NULL, 'i'}, 44218822Sdim {"types", no_argument, NULL, 't'}, 45218822Sdim {"version", no_argument, NULL, 'v'}, 46218822Sdim {NULL, no_argument, NULL, 0} 47218822Sdim}; 48130561Sobrien 49130561Sobrienstatic void 50130561Sobriendemangle_it (char *mangled_name) 51130561Sobrien{ 52130561Sobrien char *result; 53218822Sdim unsigned int skip_first = 0; 54130561Sobrien 55218822Sdim /* _ and $ are sometimes found at the start of function names 56218822Sdim in assembler sources in order to distinguish them from other 57218822Sdim names (eg register names). So skip them here. */ 58218822Sdim if (mangled_name[0] == '.' || mangled_name[0] == '$') 59218822Sdim ++skip_first; 60218822Sdim if (strip_underscore && mangled_name[skip_first] == '_') 61218822Sdim ++skip_first; 62218822Sdim 63218822Sdim result = cplus_demangle (mangled_name + skip_first, flags); 64218822Sdim 65130561Sobrien if (result == NULL) 66259694Spfg printf ("%s",mangled_name); 67130561Sobrien else 68130561Sobrien { 69218822Sdim if (mangled_name[0] == '.') 70218822Sdim putchar ('.'); 71259694Spfg printf ("%s",result); 72130561Sobrien free (result); 73130561Sobrien } 74130561Sobrien} 75130561Sobrien 76130561Sobrienstatic void 77130561Sobrienprint_demangler_list (FILE *stream) 78130561Sobrien{ 79130561Sobrien const struct demangler_engine *demangler; 80130561Sobrien 81130561Sobrien fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name); 82130561Sobrien 83130561Sobrien for (demangler = libiberty_demanglers + 1; 84130561Sobrien demangler->demangling_style != unknown_demangling; 85130561Sobrien ++demangler) 86130561Sobrien fprintf (stream, ",%s", demangler->demangling_style_name); 87130561Sobrien 88130561Sobrien fprintf (stream, "}"); 89130561Sobrien} 90130561Sobrien 91130561Sobrienstatic void 92130561Sobrienusage (FILE *stream, int status) 93130561Sobrien{ 94130561Sobrien fprintf (stream, "\ 95218822SdimUsage: %s [options] [mangled names]\n", program_name); 96130561Sobrien fprintf (stream, "\ 97218822SdimOptions are:\n\ 98218822Sdim [-_|--strip-underscore] Ignore first leading underscore%s\n", 99218822Sdim TARGET_PREPENDS_UNDERSCORE ? " (default)" : ""); 100130561Sobrien fprintf (stream, "\ 101218822Sdim [-n|--no-strip-underscore] Do not ignore a leading underscore%s\n", 102218822Sdim TARGET_PREPENDS_UNDERSCORE ? "" : " (default)"); 103218822Sdim fprintf (stream, "\ 104218822Sdim [-p|--no-params] Do not display function arguments\n\ 105218822Sdim [-i|--no-verbose] Do not show implementation details (if any)\n\ 106218822Sdim [-t|--types] Also attempt to demangle type encodings\n\ 107218822Sdim [-s|--format "); 108130561Sobrien print_demangler_list (stream); 109130561Sobrien fprintf (stream, "]\n"); 110130561Sobrien 111130561Sobrien fprintf (stream, "\ 112218822Sdim [@<file>] Read extra options from <file>\n\ 113218822Sdim [-h|--help] Display this information\n\ 114218822Sdim [-v|--version] Show the version information\n\ 115218822SdimDemangled names are displayed to stdout.\n\ 116218822SdimIf a name cannot be demangled it is just echoed to stdout.\n\ 117218822SdimIf no names are provided on the command line, stdin is read.\n"); 118218822Sdim if (REPORT_BUGS_TO[0] && status == 0) 119218822Sdim fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); 120130561Sobrien exit (status); 121130561Sobrien} 122130561Sobrien 123130561Sobrien/* Return the string of non-alnum characters that may occur 124130561Sobrien as a valid symbol component, in the standard assembler symbol 125130561Sobrien syntax. */ 126130561Sobrien 127130561Sobrienstatic const char * 128130561Sobrienstandard_symbol_characters (void) 129130561Sobrien{ 130130561Sobrien return "_$."; 131130561Sobrien} 132130561Sobrien 133130561Sobrien/* Return the string of non-alnum characters that may occur 134130561Sobrien as a valid symbol name component in an HP object file. 135130561Sobrien 136130561Sobrien Note that, since HP's compiler generates object code straight from 137130561Sobrien C++ source, without going through an assembler, its mangled 138130561Sobrien identifiers can use all sorts of characters that no assembler would 139130561Sobrien tolerate, so the alphabet this function creates is a little odd. 140130561Sobrien Here are some sample mangled identifiers offered by HP: 141130561Sobrien 142130561Sobrien typeid*__XT24AddressIndExpClassMember_ 143130561Sobrien [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv 144130561Sobrien __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv 145130561Sobrien 146130561Sobrien This still seems really weird to me, since nowhere else in this 147130561Sobrien file is there anything to recognize curly brackets, parens, etc. 148130561Sobrien I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me 149130561Sobrien this is right, but I still strongly suspect that there's a 150130561Sobrien misunderstanding here. 151130561Sobrien 152130561Sobrien If we decide it's better for c++filt to use HP's assembler syntax 153130561Sobrien to scrape identifiers out of its input, here's the definition of 154130561Sobrien the symbol name syntax from the HP assembler manual: 155130561Sobrien 156130561Sobrien Symbols are composed of uppercase and lowercase letters, decimal 157130561Sobrien digits, dollar symbol, period (.), ampersand (&), pound sign(#) and 158130561Sobrien underscore (_). A symbol can begin with a letter, digit underscore or 159130561Sobrien dollar sign. If a symbol begins with a digit, it must contain a 160130561Sobrien non-digit character. 161130561Sobrien 162130561Sobrien So have fun. */ 163130561Sobrienstatic const char * 164130561Sobrienhp_symbol_characters (void) 165130561Sobrien{ 166130561Sobrien return "_$.<>#,*&[]:(){}"; 167130561Sobrien} 168130561Sobrien 169130561Sobrienextern int main (int, char **); 170130561Sobrien 171130561Sobrienint 172130561Sobrienmain (int argc, char **argv) 173130561Sobrien{ 174130561Sobrien int c; 175130561Sobrien const char *valid_symbols; 176130561Sobrien enum demangling_styles style = auto_demangling; 177130561Sobrien 178130561Sobrien program_name = argv[0]; 179130561Sobrien xmalloc_set_program_name (program_name); 180130561Sobrien 181218822Sdim expandargv (&argc, &argv); 182130561Sobrien 183218822Sdim while ((c = getopt_long (argc, argv, "_hinps:tv", long_options, (int *) 0)) != EOF) 184130561Sobrien { 185130561Sobrien switch (c) 186130561Sobrien { 187130561Sobrien case '?': 188130561Sobrien usage (stderr, 1); 189130561Sobrien break; 190130561Sobrien case 'h': 191130561Sobrien usage (stdout, 0); 192130561Sobrien case 'n': 193130561Sobrien strip_underscore = 0; 194130561Sobrien break; 195130561Sobrien case 'p': 196130561Sobrien flags &= ~ DMGL_PARAMS; 197130561Sobrien break; 198218822Sdim case 't': 199218822Sdim flags |= DMGL_TYPES; 200218822Sdim break; 201218822Sdim case 'i': 202218822Sdim flags &= ~ DMGL_VERBOSE; 203218822Sdim break; 204130561Sobrien case 'v': 205130561Sobrien print_version ("c++filt"); 206218822Sdim return 0; 207130561Sobrien case '_': 208130561Sobrien strip_underscore = 1; 209130561Sobrien break; 210130561Sobrien case 's': 211218822Sdim style = cplus_demangle_name_to_style (optarg); 212218822Sdim if (style == unknown_demangling) 213218822Sdim { 214218822Sdim fprintf (stderr, "%s: unknown demangling style `%s'\n", 215218822Sdim program_name, optarg); 216218822Sdim return 1; 217218822Sdim } 218218822Sdim cplus_demangle_set_style (style); 219130561Sobrien break; 220130561Sobrien } 221130561Sobrien } 222130561Sobrien 223130561Sobrien if (optind < argc) 224130561Sobrien { 225130561Sobrien for ( ; optind < argc; optind++) 226130561Sobrien { 227130561Sobrien demangle_it (argv[optind]); 228218822Sdim putchar ('\n'); 229130561Sobrien } 230218822Sdim 231218822Sdim return 0; 232130561Sobrien } 233218822Sdim 234218822Sdim switch (current_demangling_style) 235130561Sobrien { 236218822Sdim case gnu_demangling: 237218822Sdim case lucid_demangling: 238218822Sdim case arm_demangling: 239218822Sdim case java_demangling: 240218822Sdim case edg_demangling: 241218822Sdim case gnat_demangling: 242218822Sdim case gnu_v3_demangling: 243218822Sdim case auto_demangling: 244218822Sdim valid_symbols = standard_symbol_characters (); 245218822Sdim break; 246218822Sdim case hp_demangling: 247218822Sdim valid_symbols = hp_symbol_characters (); 248218822Sdim break; 249218822Sdim default: 250218822Sdim /* Folks should explicitly indicate the appropriate alphabet for 251218822Sdim each demangling. Providing a default would allow the 252218822Sdim question to go unconsidered. */ 253218822Sdim fatal ("Internal error: no symbol alphabet for current style"); 254218822Sdim } 255218822Sdim 256218822Sdim for (;;) 257218822Sdim { 258218822Sdim static char mbuffer[32767]; 259218822Sdim unsigned i = 0; 260218822Sdim 261218822Sdim c = getchar (); 262218822Sdim /* Try to read a mangled name. */ 263218822Sdim while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c))) 264130561Sobrien { 265218822Sdim if (i >= sizeof (mbuffer) - 1) 266218822Sdim break; 267218822Sdim mbuffer[i++] = c; 268218822Sdim c = getchar (); 269130561Sobrien } 270130561Sobrien 271218822Sdim if (i > 0) 272130561Sobrien { 273218822Sdim mbuffer[i] = 0; 274218822Sdim demangle_it (mbuffer); 275218822Sdim } 276130561Sobrien 277218822Sdim if (c == EOF) 278218822Sdim break; 279130561Sobrien 280218822Sdim /* Echo the whitespace characters so that the output looks 281218822Sdim like the input, only with the mangled names demangled. */ 282218822Sdim putchar (c); 283218822Sdim if (c == '\n') 284218822Sdim fflush (stdout); 285130561Sobrien } 286130561Sobrien 287218822Sdim fflush (stdout); 288218822Sdim return 0; 289130561Sobrien} 290