xref: /netbsd-src/external/gpl3/binutils.old/dist/binutils/cxxfilt.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Demangler for GNU C++ - main program
2*e992f068Schristos    Copyright (C) 1989-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Written by James Clark (jjc@jclark.uucp)
475fd0b74Schristos    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
575fd0b74Schristos    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
675fd0b74Schristos 
775fd0b74Schristos    This file is part of GNU Binutils.
875fd0b74Schristos 
975fd0b74Schristos    This program is free software; you can redistribute it and/or modify
1075fd0b74Schristos    it under the terms of the GNU General Public License as published by
1175fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or (at
1275fd0b74Schristos    your option) any later version.
1375fd0b74Schristos 
1475fd0b74Schristos    This program is distributed in the hope that it will be useful,
1575fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1675fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1775fd0b74Schristos    GNU General Public License for more details.
1875fd0b74Schristos 
1975fd0b74Schristos    You should have received a copy of the GNU General Public License
2075fd0b74Schristos    along with GCC; see the file COPYING.  If not, write to the Free
2175fd0b74Schristos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
2275fd0b74Schristos    02110-1301, USA.  */
2375fd0b74Schristos 
2475fd0b74Schristos #include "sysdep.h"
2575fd0b74Schristos #include "bfd.h"
2675fd0b74Schristos #include "libiberty.h"
2775fd0b74Schristos #include "demangle.h"
2875fd0b74Schristos #include "getopt.h"
2975fd0b74Schristos #include "safe-ctype.h"
3075fd0b74Schristos #include "bucomm.h"
3175fd0b74Schristos 
3275fd0b74Schristos static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
3375fd0b74Schristos static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
3475fd0b74Schristos 
3575fd0b74Schristos static const struct option long_options[] =
3675fd0b74Schristos {
3775fd0b74Schristos   {"strip-underscore", no_argument, NULL, '_'},
3875fd0b74Schristos   {"format", required_argument, NULL, 's'},
3975fd0b74Schristos   {"help", no_argument, NULL, 'h'},
4075fd0b74Schristos   {"no-params", no_argument, NULL, 'p'},
4175fd0b74Schristos   {"no-strip-underscores", no_argument, NULL, 'n'},
4275fd0b74Schristos   {"no-verbose", no_argument, NULL, 'i'},
4375fd0b74Schristos   {"types", no_argument, NULL, 't'},
4475fd0b74Schristos   {"version", no_argument, NULL, 'v'},
45012573ebSchristos   {"recurse-limit", no_argument, NULL, 'R'},
46012573ebSchristos   {"recursion-limit", no_argument, NULL, 'R'},
47012573ebSchristos   {"no-recurse-limit", no_argument, NULL, 'r'},
48012573ebSchristos   {"no-recursion-limit", no_argument, NULL, 'r'},
4975fd0b74Schristos   {NULL, no_argument, NULL, 0}
5075fd0b74Schristos };
5175fd0b74Schristos 
5275fd0b74Schristos static void
demangle_it(char * mangled_name)5375fd0b74Schristos demangle_it (char *mangled_name)
5475fd0b74Schristos {
5575fd0b74Schristos   char *result;
5675fd0b74Schristos   unsigned int skip_first = 0;
5775fd0b74Schristos 
5875fd0b74Schristos   /* _ and $ are sometimes found at the start of function names
5975fd0b74Schristos      in assembler sources in order to distinguish them from other
6075fd0b74Schristos      names (eg register names).  So skip them here.  */
6175fd0b74Schristos   if (mangled_name[0] == '.' || mangled_name[0] == '$')
6275fd0b74Schristos     ++skip_first;
6375fd0b74Schristos   if (strip_underscore && mangled_name[skip_first] == '_')
6475fd0b74Schristos     ++skip_first;
6575fd0b74Schristos 
6675fd0b74Schristos   result = cplus_demangle (mangled_name + skip_first, flags);
6775fd0b74Schristos 
6875fd0b74Schristos   if (result == NULL)
6975fd0b74Schristos     printf ("%s", mangled_name);
7075fd0b74Schristos   else
7175fd0b74Schristos     {
7275fd0b74Schristos       if (mangled_name[0] == '.')
7375fd0b74Schristos 	putchar ('.');
7475fd0b74Schristos       printf ("%s", result);
7575fd0b74Schristos       free (result);
7675fd0b74Schristos     }
7775fd0b74Schristos }
7875fd0b74Schristos 
7975fd0b74Schristos static void
print_demangler_list(FILE * stream)8075fd0b74Schristos print_demangler_list (FILE *stream)
8175fd0b74Schristos {
8275fd0b74Schristos   const struct demangler_engine *demangler;
8375fd0b74Schristos 
8475fd0b74Schristos   fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
8575fd0b74Schristos 
8675fd0b74Schristos   for (demangler = libiberty_demanglers + 1;
8775fd0b74Schristos        demangler->demangling_style != unknown_demangling;
8875fd0b74Schristos        ++demangler)
8975fd0b74Schristos     fprintf (stream, ",%s", demangler->demangling_style_name);
9075fd0b74Schristos 
9175fd0b74Schristos   fprintf (stream, "}");
9275fd0b74Schristos }
9375fd0b74Schristos 
94ede78133Schristos ATTRIBUTE_NORETURN static void
usage(FILE * stream,int status)9575fd0b74Schristos usage (FILE *stream, int status)
9675fd0b74Schristos {
9775fd0b74Schristos   fprintf (stream, "\
9875fd0b74Schristos Usage: %s [options] [mangled names]\n", program_name);
9975fd0b74Schristos   fprintf (stream, "\
10075fd0b74Schristos Options are:\n\
10175fd0b74Schristos   [-_|--strip-underscore]     Ignore first leading underscore%s\n",
10275fd0b74Schristos 	   TARGET_PREPENDS_UNDERSCORE ? " (default)" : "");
10375fd0b74Schristos   fprintf (stream, "\
10475fd0b74Schristos   [-n|--no-strip-underscore]  Do not ignore a leading underscore%s\n",
10575fd0b74Schristos 	   TARGET_PREPENDS_UNDERSCORE ? "" : " (default)");
10675fd0b74Schristos   fprintf (stream, "\
10775fd0b74Schristos   [-p|--no-params]            Do not display function arguments\n\
10875fd0b74Schristos   [-i|--no-verbose]           Do not show implementation details (if any)\n\
109012573ebSchristos   [-R|--recurse-limit]        Enable a limit on recursion whilst demangling.  [Default]\n\
110012573ebSchristos   ]-r|--no-recurse-limit]     Disable a limit on recursion whilst demangling\n\
11175fd0b74Schristos   [-t|--types]                Also attempt to demangle type encodings\n\
11275fd0b74Schristos   [-s|--format ");
11375fd0b74Schristos   print_demangler_list (stream);
11475fd0b74Schristos   fprintf (stream, "]\n");
11575fd0b74Schristos 
11675fd0b74Schristos   fprintf (stream, "\
11775fd0b74Schristos   [@<file>]                   Read extra options from <file>\n\
11875fd0b74Schristos   [-h|--help]                 Display this information\n\
11975fd0b74Schristos   [-v|--version]              Show the version information\n\
12075fd0b74Schristos Demangled names are displayed to stdout.\n\
12175fd0b74Schristos If a name cannot be demangled it is just echoed to stdout.\n\
12275fd0b74Schristos If no names are provided on the command line, stdin is read.\n");
12375fd0b74Schristos   if (REPORT_BUGS_TO[0] && status == 0)
12475fd0b74Schristos     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
12575fd0b74Schristos   exit (status);
12675fd0b74Schristos }
12775fd0b74Schristos 
12875fd0b74Schristos /* Return the string of non-alnum characters that may occur
12975fd0b74Schristos    as a valid symbol component, in the standard assembler symbol
13075fd0b74Schristos    syntax.  */
13175fd0b74Schristos 
13275fd0b74Schristos static const char *
standard_symbol_characters(void)13375fd0b74Schristos standard_symbol_characters (void)
13475fd0b74Schristos {
13575fd0b74Schristos   return "_$.";
13675fd0b74Schristos }
13775fd0b74Schristos 
13875fd0b74Schristos extern int main (int, char **);
13975fd0b74Schristos 
14075fd0b74Schristos int
main(int argc,char ** argv)14175fd0b74Schristos main (int argc, char **argv)
14275fd0b74Schristos {
14375fd0b74Schristos   int c;
14475fd0b74Schristos   const char *valid_symbols;
14575fd0b74Schristos   enum demangling_styles style = auto_demangling;
14675fd0b74Schristos 
14775fd0b74Schristos   program_name = argv[0];
14875fd0b74Schristos   xmalloc_set_program_name (program_name);
14975fd0b74Schristos   bfd_set_error_program_name (program_name);
15075fd0b74Schristos 
15175fd0b74Schristos   expandargv (&argc, &argv);
15275fd0b74Schristos 
153012573ebSchristos   while ((c = getopt_long (argc, argv, "_hinprRs:tv", long_options, (int *) 0)) != EOF)
15475fd0b74Schristos     {
15575fd0b74Schristos       switch (c)
15675fd0b74Schristos 	{
15775fd0b74Schristos 	case '?':
15875fd0b74Schristos 	  usage (stderr, 1);
15975fd0b74Schristos 	  break;
16075fd0b74Schristos 	case 'h':
16175fd0b74Schristos 	  usage (stdout, 0);
16275fd0b74Schristos 	case 'n':
16375fd0b74Schristos 	  strip_underscore = 0;
16475fd0b74Schristos 	  break;
16575fd0b74Schristos 	case 'p':
16675fd0b74Schristos 	  flags &= ~ DMGL_PARAMS;
16775fd0b74Schristos 	  break;
168012573ebSchristos 	case 'r':
169012573ebSchristos 	  flags |= DMGL_NO_RECURSE_LIMIT;
170012573ebSchristos 	  break;
171012573ebSchristos 	case 'R':
172012573ebSchristos 	  flags &= ~ DMGL_NO_RECURSE_LIMIT;
173012573ebSchristos 	  break;
17475fd0b74Schristos 	case 't':
17575fd0b74Schristos 	  flags |= DMGL_TYPES;
17675fd0b74Schristos 	  break;
17775fd0b74Schristos 	case 'i':
17875fd0b74Schristos 	  flags &= ~ DMGL_VERBOSE;
17975fd0b74Schristos 	  break;
18075fd0b74Schristos 	case 'v':
18175fd0b74Schristos 	  print_version ("c++filt");
18275fd0b74Schristos 	  return 0;
18375fd0b74Schristos 	case '_':
18475fd0b74Schristos 	  strip_underscore = 1;
18575fd0b74Schristos 	  break;
18675fd0b74Schristos 	case 's':
18775fd0b74Schristos 	  style = cplus_demangle_name_to_style (optarg);
18875fd0b74Schristos 	  if (style == unknown_demangling)
18975fd0b74Schristos 	    {
19075fd0b74Schristos 	      fprintf (stderr, "%s: unknown demangling style `%s'\n",
19175fd0b74Schristos 		       program_name, optarg);
19275fd0b74Schristos 	      return 1;
19375fd0b74Schristos 	    }
19475fd0b74Schristos 	  cplus_demangle_set_style (style);
19575fd0b74Schristos 	  break;
19675fd0b74Schristos 	}
19775fd0b74Schristos     }
19875fd0b74Schristos 
19975fd0b74Schristos   if (optind < argc)
20075fd0b74Schristos     {
20175fd0b74Schristos       for ( ; optind < argc; optind++)
20275fd0b74Schristos 	{
20375fd0b74Schristos 	  demangle_it (argv[optind]);
20475fd0b74Schristos 	  putchar ('\n');
20575fd0b74Schristos 	}
20675fd0b74Schristos 
20775fd0b74Schristos       return 0;
20875fd0b74Schristos     }
20975fd0b74Schristos 
21075fd0b74Schristos   switch (current_demangling_style)
21175fd0b74Schristos     {
212012573ebSchristos     case auto_demangling:
21375fd0b74Schristos     case gnu_v3_demangling:
214012573ebSchristos     case java_demangling:
215012573ebSchristos     case gnat_demangling:
21675fd0b74Schristos     case dlang_demangling:
217ede78133Schristos     case rust_demangling:
21875fd0b74Schristos        valid_symbols = standard_symbol_characters ();
21975fd0b74Schristos       break;
22075fd0b74Schristos     default:
22175fd0b74Schristos       /* Folks should explicitly indicate the appropriate alphabet for
22275fd0b74Schristos 	 each demangling.  Providing a default would allow the
22375fd0b74Schristos 	 question to go unconsidered.  */
22475fd0b74Schristos       fatal ("Internal error: no symbol alphabet for current style");
22575fd0b74Schristos     }
22675fd0b74Schristos 
22775fd0b74Schristos   for (;;)
22875fd0b74Schristos     {
22975fd0b74Schristos       static char mbuffer[32767];
23075fd0b74Schristos       unsigned i = 0;
23175fd0b74Schristos 
23275fd0b74Schristos       c = getchar ();
23375fd0b74Schristos       /* Try to read a mangled name.  */
23475fd0b74Schristos       while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
23575fd0b74Schristos 	{
23675fd0b74Schristos 	  if (i >= sizeof (mbuffer) - 1)
23775fd0b74Schristos 	    break;
23875fd0b74Schristos 	  mbuffer[i++] = c;
23975fd0b74Schristos 	  c = getchar ();
24075fd0b74Schristos 	}
24175fd0b74Schristos 
24275fd0b74Schristos       if (i > 0)
24375fd0b74Schristos 	{
24475fd0b74Schristos 	  mbuffer[i] = 0;
24575fd0b74Schristos 	  demangle_it (mbuffer);
24675fd0b74Schristos 	}
24775fd0b74Schristos 
24875fd0b74Schristos       if (c == EOF)
24975fd0b74Schristos 	break;
25075fd0b74Schristos 
25175fd0b74Schristos       /* Echo the whitespace characters so that the output looks
25275fd0b74Schristos 	 like the input, only with the mangled names demangled.  */
25375fd0b74Schristos       putchar (c);
25475fd0b74Schristos       if (c == '\n')
25575fd0b74Schristos 	fflush (stdout);
25675fd0b74Schristos     }
25775fd0b74Schristos 
25875fd0b74Schristos   fflush (stdout);
25975fd0b74Schristos   return 0;
26075fd0b74Schristos }
261