(linenum→info "unix/slp.c:2238")

binutils/2.18/binutils/cxxfilt.c

    1: /* Demangler for GNU C++ - main program
    2:    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
    3:    2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
    4:    Written by James Clark (jjc@jclark.uucp)
    5:    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
    6:    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
    7: 
    8:    This file is part of GNU Binutils.
    9: 
   10:    This program is free software; you can redistribute it and/or modify
   11:    it under the terms of the GNU General Public License as published by
   12:    the Free Software Foundation; either version 3 of the License, or (at
   13:    your option) any later version.
   14: 
   15:    This program is distributed in the hope that it will be useful,
   16:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   17:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18:    GNU General Public License for more details.
   19: 
   20:    You should have received a copy of the GNU General Public License
   21:    along with GCC; see the file COPYING.  If not, write to the Free
   22:    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   23:    02110-1301, USA.  */
   24: 
   25: #include "sysdep.h"
   26: #include "bfd.h"
   27: #include "libiberty.h"
   28: #include "demangle.h"
   29: #include "getopt.h"
   30: #include "safe-ctype.h"
   31: #include "bucomm.h"
   32: 
   33: static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
   34: static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
   35: 
   36: static const struct option long_options[] =
   37: {
   38:   {"strip-underscore", no_argument, NULL, '_'},
   39:   {"format", required_argument, NULL, 's'},
   40:   {"help", no_argument, NULL, 'h'},
   41:   {"no-params", no_argument, NULL, 'p'},
   42:   {"no-strip-underscores", no_argument, NULL, 'n'},
   43:   {"no-verbose", no_argument, NULL, 'i'},
   44:   {"types", no_argument, NULL, 't'},
   45:   {"version", no_argument, NULL, 'v'},
   46:   {NULL, no_argument, NULL, 0}
   47: };
   48: 
   49: static void
   50: demangle_it (char *mangled_name)
   51: {
   52:   char *result;
   53:   unsigned int skip_first = 0;
   54: 
   55:   /* _ and $ are sometimes found at the start of function names
   56:      in assembler sources in order to distinguish them from other
   57:      names (eg register names).  So skip them here.  */
   58:   if (mangled_name[0] == '.' || mangled_name[0] == '$')
   59:     ++skip_first;
   60:   if (strip_underscore && mangled_name[skip_first] == '_')
   61:     ++skip_first;
   62: 
   63:   result = cplus_demangle (mangled_name + skip_first, flags);
   64: 
   65:   if (result == NULL)
   66:     printf (mangled_name);
   67:   else
   68:     {
   69:       if (mangled_name[0] == '.')
   70:         putchar ('.');
   71:       printf (result);
   72:       free (result);
   73:     }
   74: }
   75: 
   76: static void
   77: print_demangler_list (FILE *stream)
   78: {
   79:   const struct demangler_engine *demangler;
   80: 
   81:   fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
   82: 
   83:   for (demangler = libiberty_demanglers + 1;
   84:        demangler->demangling_style != unknown_demangling;
   85:        ++demangler)
   86:     fprintf (stream, ",%s", demangler->demangling_style_name);
   87: 
   88:   fprintf (stream, "}");
   89: }
   90: 
   91: static void
   92: usage (FILE *stream, int status)
   93: {
   94:   fprintf (stream, "\
   95: Usage: %s [options] [mangled names]\n", program_name);
   96:   fprintf (stream, "\
   97: Options are:\n\
   98:   [-_|--strip-underscore]     Ignore first leading underscore%s\n",
   99:            TARGET_PREPENDS_UNDERSCORE ? " (default)" : "");
  100:   fprintf (stream, "\
  101:   [-n|--no-strip-underscore]  Do not ignore a leading underscore%s\n",
  102:            TARGET_PREPENDS_UNDERSCORE ? "" : " (default)");
  103:   fprintf (stream, "\
  104:   [-p|--no-params]            Do not display function arguments\n\
  105:   [-i|--no-verbose]           Do not show implementation details (if any)\n\
  106:   [-t|--types]                Also attempt to demangle type encodings\n\
  107:   [-s|--format ");
  108:   print_demangler_list (stream);
  109:   fprintf (stream, "]\n");
  110: 
  111:   fprintf (stream, "\
  112:   [@<file>]                   Read extra options from <file>\n\
  113:   [-h|--help]                 Display this information\n\
  114:   [-v|--version]              Show the version information\n\
  115: Demangled names are displayed to stdout.\n\
  116: If a name cannot be demangled it is just echoed to stdout.\n\
  117: If no names are provided on the command line, stdin is read.\n");
  118:   if (REPORT_BUGS_TO[0] && status == 0)
  119:     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
  120:   exit (status);
  121: }
  122: 
  123: /* Return the string of non-alnum characters that may occur
  124:    as a valid symbol component, in the standard assembler symbol
  125:    syntax.  */
  126: 
  127: static const char *
  128: standard_symbol_characters (void)
  129: {
  130:   return "_$.";
  131: }
  132: 
  133: /* Return the string of non-alnum characters that may occur
  134:    as a valid symbol name component in an HP object file.
  135: 
  136:    Note that, since HP's compiler generates object code straight from
  137:    C++ source, without going through an assembler, its mangled
  138:    identifiers can use all sorts of characters that no assembler would
  139:    tolerate, so the alphabet this function creates is a little odd.
  140:    Here are some sample mangled identifiers offered by HP:
  141: 
  142:         typeid*__XT24AddressIndExpClassMember_
  143:         [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
  144:         __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
  145: 
  146:    This still seems really weird to me, since nowhere else in this
  147:    file is there anything to recognize curly brackets, parens, etc.
  148:    I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
  149:    this is right, but I still strongly suspect that there's a
  150:    misunderstanding here.
  151: 
  152:    If we decide it's better for c++filt to use HP's assembler syntax
  153:    to scrape identifiers out of its input, here's the definition of
  154:    the symbol name syntax from the HP assembler manual:
  155: 
  156:        Symbols are composed of uppercase and lowercase letters, decimal
  157:        digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
  158:        underscore (_). A symbol can begin with a letter, digit underscore or
  159:        dollar sign. If a symbol begins with a digit, it must contain a
  160:        non-digit character.
  161: 
  162:    So have fun.  */
  163: static const char *
  164: hp_symbol_characters (void)
  165: {
  166:   return "_$.<>#,*&[]:(){}";
  167: }
  168: 
  169: extern int main (int, char **);
  170: 
  171: int
  172: main (int argc, char **argv)
  173: {
  174:   int c;
  175:   const char *valid_symbols;
  176:   enum demangling_styles style = auto_demangling;
  177: 
  178:   program_name = argv[0];
  179:   xmalloc_set_program_name (program_name);
  180: 
  181:   expandargv (&argc, &argv);
  182: 
  183:   while ((c = getopt_long (argc, argv, "_hinps:tv", long_options, (int *) 0)) != EOF)
  184:     {
  185:       switch (c)
  186:         {
  187:         case '?':
  188:           usage (stderr, 1);
  189:           break;
  190:         case 'h':
  191:           usage (stdout, 0);
  192:         case 'n':
  193:           strip_underscore = 0;
  194:           break;
  195:         case 'p':
  196:           flags &= ~ DMGL_PARAMS;
  197:           break;
  198:         case 't':
  199:           flags |= DMGL_TYPES;
  200:           break;
  201:         case 'i':
  202:           flags &= ~ DMGL_VERBOSE;
  203:           break;
  204:         case 'v':
  205:           print_version ("c++filt");
  206:           return 0;
  207:         case '_':
  208:           strip_underscore = 1;
  209:           break;
  210:         case 's':
  211:           style = cplus_demangle_name_to_style (optarg);
  212:           if (style == unknown_demangling)
  213:             {
  214:               fprintf (stderr, "%s: unknown demangling style `%s'\n",
  215:                        program_name, optarg);
  216:               return 1;
  217:             }
  218:           cplus_demangle_set_style (style);
  219:           break;
  220:         }
  221:     }
  222: 
  223:   if (optind < argc)
  224:     {
  225:       for ( ; optind < argc; optind++)
  226:         {
  227:           demangle_it (argv[optind]);
  228:           putchar ('\n');
  229:         }
  230: 
  231:       return 0;
  232:     }
  233: 
  234:   switch (current_demangling_style)
  235:     {
  236:     case gnu_demangling:
  237:     case lucid_demangling:
  238:     case arm_demangling:
  239:     case java_demangling:
  240:     case edg_demangling:
  241:     case gnat_demangling:
  242:     case gnu_v3_demangling:
  243:     case auto_demangling:
  244:       valid_symbols = standard_symbol_characters ();
  245:       break;
  246:     case hp_demangling:
  247:       valid_symbols = hp_symbol_characters ();
  248:       break;
  249:     default:
  250:       /* Folks should explicitly indicate the appropriate alphabet for
  251:          each demangling.  Providing a default would allow the
  252:          question to go unconsidered.  */
  253:       fatal ("Internal error: no symbol alphabet for current style");
  254:     }
  255: 
  256:   for (;;)
  257:     {
  258:       static char mbuffer[32767];
  259:       unsigned i = 0;
  260: 
  261:       c = getchar ();
  262:       /* Try to read a mangled name.  */
  263:       while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
  264:         {
  265:           if (i >= sizeof (mbuffer) - 1)
  266:             break;
  267:           mbuffer[i++] = c;
  268:           c = getchar ();
  269:         }
  270: 
  271:       if (i > 0)
  272:         {
  273:           mbuffer[i] = 0;
  274:           demangle_it (mbuffer);
  275:         }
  276: 
  277:       if (c == EOF)
  278:         break;
  279: 
  280:       /* Echo the whitespace characters so that the output looks
  281:          like the input, only with the mangled names demangled.  */
  282:       putchar (c);
  283:       if (c == '\n')
  284:         fflush (stdout);
  285:     }
  286: 
  287:   fflush (stdout);
  288:   return 0;
  289: }
Syntax (Markdown)