Back to index

cell-binutils  2.17cvs20070401
cxxfilt.c
Go to the documentation of this file.
00001 /* Demangler for GNU C++ - main program
00002    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
00004    Written by James Clark (jjc@jclark.uucp)
00005    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
00006    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
00007 
00008    This file is part of GCC.
00009 
00010    GCC is free software; you can redistribute it and/or modify it under
00011    the terms of the GNU General Public License as published by the Free
00012    Software Foundation; either version 2, or (at your option) any later
00013    version.
00014 
00015    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00016    WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018    for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with GCC; see the file COPYING.  If not, write to the Free
00022    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00023    02110-1301, USA.  */
00024 
00025 #include "config.h"
00026 #include "bfd.h"
00027 #include "bucomm.h"
00028 #include "libiberty.h"
00029 #include "demangle.h"
00030 #include "getopt.h"
00031 #include "safe-ctype.h"
00032 
00033 static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
00034 static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
00035 
00036 static const struct option long_options[] =
00037 {
00038   {"strip-underscore", no_argument, NULL, '_'},
00039   {"format", required_argument, NULL, 's'},
00040   {"help", no_argument, NULL, 'h'},
00041   {"no-params", no_argument, NULL, 'p'},
00042   {"no-strip-underscores", no_argument, NULL, 'n'},
00043   {"no-verbose", no_argument, NULL, 'i'},
00044   {"types", no_argument, NULL, 't'},
00045   {"version", no_argument, NULL, 'v'},
00046   {NULL, no_argument, NULL, 0}
00047 };
00048 
00049 static void
00050 demangle_it (char *mangled_name)
00051 {
00052   char *result;
00053   unsigned int skip_first = 0;
00054 
00055   /* _ and $ are sometimes found at the start of function names
00056      in assembler sources in order to distinguish them from other
00057      names (eg register names).  So skip them here.  */
00058   if (mangled_name[0] == '.' || mangled_name[0] == '$')
00059     ++skip_first;
00060   if (strip_underscore && mangled_name[skip_first] == '_')
00061     ++skip_first;
00062 
00063   result = cplus_demangle (mangled_name + skip_first, flags);
00064 
00065   if (result == NULL)
00066     printf (mangled_name);
00067   else
00068     {
00069       if (mangled_name[0] == '.')
00070        putchar ('.');
00071       printf (result);
00072       free (result);
00073     }
00074 }
00075 
00076 static void
00077 print_demangler_list (FILE *stream)
00078 {
00079   const struct demangler_engine *demangler;
00080 
00081   fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
00082 
00083   for (demangler = libiberty_demanglers + 1;
00084        demangler->demangling_style != unknown_demangling;
00085        ++demangler)
00086     fprintf (stream, ",%s", demangler->demangling_style_name);
00087 
00088   fprintf (stream, "}");
00089 }
00090 
00091 static void
00092 usage (FILE *stream, int status)
00093 {
00094   fprintf (stream, "\
00095 Usage: %s [options] [mangled names]\n", program_name);
00096   fprintf (stream, "\
00097 Options are:\n\
00098   [-_|--strip-underscore]     Ignore first leading underscore%s\n",
00099           TARGET_PREPENDS_UNDERSCORE ? " (default)" : "");
00100   fprintf (stream, "\
00101   [-n|--no-strip-underscore]  Do not ignore a leading underscore%s\n",
00102           TARGET_PREPENDS_UNDERSCORE ? "" : " (default)");
00103   fprintf (stream, "\
00104   [-p|--no-params]            Do not display function arguments\n\
00105   [-i|--no-verbose]           Do not show implementation details (if any)\n\
00106   [-t|--types]                Also attempt to demangle type encodings\n\
00107   [-s|--format ");
00108   print_demangler_list (stream);
00109   fprintf (stream, "]\n");
00110 
00111   fprintf (stream, "\
00112   [@<file>]                   Read extra options from <file>\n\
00113   [-h|--help]                 Display this information\n\
00114   [-v|--version]              Show the version information\n\
00115 Demangled names are displayed to stdout.\n\
00116 If a name cannot be demangled it is just echoed to stdout.\n\
00117 If no names are provided on the command line, stdin is read.\n");
00118   if (REPORT_BUGS_TO[0] && status == 0)
00119     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
00120   exit (status);
00121 }
00122 
00123 /* Return the string of non-alnum characters that may occur
00124    as a valid symbol component, in the standard assembler symbol
00125    syntax.  */
00126 
00127 static const char *
00128 standard_symbol_characters (void)
00129 {
00130   return "_$.";
00131 }
00132 
00133 /* Return the string of non-alnum characters that may occur
00134    as a valid symbol name component in an HP object file.
00135 
00136    Note that, since HP's compiler generates object code straight from
00137    C++ source, without going through an assembler, its mangled
00138    identifiers can use all sorts of characters that no assembler would
00139    tolerate, so the alphabet this function creates is a little odd.
00140    Here are some sample mangled identifiers offered by HP:
00141 
00142        typeid*__XT24AddressIndExpClassMember_
00143        [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
00144        __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
00145 
00146    This still seems really weird to me, since nowhere else in this
00147    file is there anything to recognize curly brackets, parens, etc.
00148    I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
00149    this is right, but I still strongly suspect that there's a
00150    misunderstanding here.
00151 
00152    If we decide it's better for c++filt to use HP's assembler syntax
00153    to scrape identifiers out of its input, here's the definition of
00154    the symbol name syntax from the HP assembler manual:
00155 
00156        Symbols are composed of uppercase and lowercase letters, decimal
00157        digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
00158        underscore (_). A symbol can begin with a letter, digit underscore or
00159        dollar sign. If a symbol begins with a digit, it must contain a
00160        non-digit character.
00161 
00162    So have fun.  */
00163 static const char *
00164 hp_symbol_characters (void)
00165 {
00166   return "_$.<>#,*&[]:(){}";
00167 }
00168 
00169 extern int main (int, char **);
00170 
00171 int
00172 main (int argc, char **argv)
00173 {
00174   int c;
00175   const char *valid_symbols;
00176   enum demangling_styles style = auto_demangling;
00177 
00178   program_name = argv[0];
00179   xmalloc_set_program_name (program_name);
00180 
00181   expandargv (&argc, &argv);
00182 
00183   while ((c = getopt_long (argc, argv, "_hinps:tv", long_options, (int *) 0)) != EOF)
00184     {
00185       switch (c)
00186        {
00187        case '?':
00188          usage (stderr, 1);
00189          break;
00190        case 'h':
00191          usage (stdout, 0);
00192        case 'n':
00193          strip_underscore = 0;
00194          break;
00195        case 'p':
00196          flags &= ~ DMGL_PARAMS;
00197          break;
00198        case 't':
00199          flags |= DMGL_TYPES;
00200          break;
00201        case 'i':
00202          flags &= ~ DMGL_VERBOSE;
00203          break;
00204        case 'v':
00205          print_version ("c++filt");
00206          return 0;
00207        case '_':
00208          strip_underscore = 1;
00209          break;
00210        case 's':
00211          style = cplus_demangle_name_to_style (optarg);
00212          if (style == unknown_demangling)
00213            {
00214              fprintf (stderr, "%s: unknown demangling style `%s'\n",
00215                      program_name, optarg);
00216              return 1;
00217            }
00218          cplus_demangle_set_style (style);
00219          break;
00220        }
00221     }
00222 
00223   if (optind < argc)
00224     {
00225       for ( ; optind < argc; optind++)
00226        {
00227          demangle_it (argv[optind]);
00228          putchar ('\n');
00229        }
00230 
00231       return 0;
00232     }
00233 
00234   switch (current_demangling_style)
00235     {
00236     case gnu_demangling:
00237     case lucid_demangling:
00238     case arm_demangling:
00239     case java_demangling:
00240     case edg_demangling:
00241     case gnat_demangling:
00242     case gnu_v3_demangling:
00243     case auto_demangling:
00244       valid_symbols = standard_symbol_characters ();
00245       break;
00246     case hp_demangling:
00247       valid_symbols = hp_symbol_characters ();
00248       break;
00249     default:
00250       /* Folks should explicitly indicate the appropriate alphabet for
00251         each demangling.  Providing a default would allow the
00252         question to go unconsidered.  */
00253       fatal ("Internal error: no symbol alphabet for current style");
00254     }
00255 
00256   for (;;)
00257     {
00258       static char mbuffer[32767];
00259       unsigned i = 0;
00260 
00261       c = getchar ();
00262       /* Try to read a mangled name.  */
00263       while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
00264        {
00265          if (i >= sizeof (mbuffer) - 1)
00266            break;
00267          mbuffer[i++] = c;
00268          c = getchar ();
00269        }
00270 
00271       if (i > 0)
00272        {
00273          mbuffer[i] = 0;
00274          demangle_it (mbuffer);
00275        }
00276 
00277       if (c == EOF)
00278        break;
00279 
00280       /* Echo the whitespace characters so that the output looks
00281         like the input, only with the mangled names demangled.  */
00282       putchar (c);
00283       if (c == '\n')
00284        fflush (stdout);
00285     }
00286 
00287   fflush (stdout);
00288   return 0;
00289 }