f41493b74edd45c4fdd3b0d0afb3cb10dafd1a1a
[platform/upstream/binutils.git] / 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 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 GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 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, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA.  */
24
25 #include "config.h"
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "demangle.h"
30 #include "getopt.h"
31 #include "safe-ctype.h"
32
33 static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
34
35 static void demangle_it (char *);
36 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
37 static void print_demangler_list (FILE *);
38
39 static void
40 demangle_it (char *mangled_name)
41 {
42   char *result;
43
44   /* For command line args, also try to demangle type encodings.  */
45   result = cplus_demangle (mangled_name, flags | DMGL_TYPES);
46   if (result == NULL)
47     {
48       printf ("%s\n", mangled_name);
49     }
50   else
51     {
52       printf ("%s\n", result);
53       free (result);
54     }
55 }
56
57 static void
58 print_demangler_list (FILE *stream)
59 {
60   const struct demangler_engine *demangler;
61
62   fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
63
64   for (demangler = libiberty_demanglers + 1;
65        demangler->demangling_style != unknown_demangling;
66        ++demangler)
67     fprintf (stream, ",%s", demangler->demangling_style_name);
68
69   fprintf (stream, "}");
70 }
71
72 static void
73 usage (FILE *stream, int status)
74 {
75   fprintf (stream, "\
76 Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n",
77            program_name);
78
79   fprintf (stream, "\
80        [-s ");
81   print_demangler_list (stream);
82   fprintf (stream, "]\n");
83
84   fprintf (stream, "\
85        [--format ");
86   print_demangler_list (stream);
87   fprintf (stream, "]\n");
88
89   fprintf (stream, "\
90        [--help] [--version] [arg...]\n");
91   exit (status);
92 }
93
94 #define MBUF_SIZE 32767
95 char mbuffer[MBUF_SIZE];
96
97 int strip_underscore = 0;
98
99 static const struct option long_options[] = {
100   {"strip-underscores", no_argument, 0, '_'},
101   {"format", required_argument, 0, 's'},
102   {"help", no_argument, 0, 'h'},
103   {"no-strip-underscores", no_argument, 0, 'n'},
104   {"version", no_argument, 0, 'v'},
105   {0, no_argument, 0, 0}
106 };
107
108 static const char *standard_symbol_characters (void);
109
110 static const char *hp_symbol_characters (void);
111
112 /* Return the string of non-alnum characters that may occur
113    as a valid symbol component, in the standard assembler symbol
114    syntax.  */
115
116 static const char *
117 standard_symbol_characters (void)
118 {
119   return "_$.";
120 }
121
122
123 /* Return the string of non-alnum characters that may occur
124    as a valid symbol name component in an HP object file.
125
126    Note that, since HP's compiler generates object code straight from
127    C++ source, without going through an assembler, its mangled
128    identifiers can use all sorts of characters that no assembler would
129    tolerate, so the alphabet this function creates is a little odd.
130    Here are some sample mangled identifiers offered by HP:
131
132         typeid*__XT24AddressIndExpClassMember_
133         [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
134         __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
135
136    This still seems really weird to me, since nowhere else in this
137    file is there anything to recognize curly brackets, parens, etc.
138    I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
139    this is right, but I still strongly suspect that there's a
140    misunderstanding here.
141
142    If we decide it's better for c++filt to use HP's assembler syntax
143    to scrape identifiers out of its input, here's the definition of
144    the symbol name syntax from the HP assembler manual:
145
146        Symbols are composed of uppercase and lowercase letters, decimal
147        digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
148        underscore (_). A symbol can begin with a letter, digit underscore or
149        dollar sign. If a symbol begins with a digit, it must contain a
150        non-digit character.
151
152    So have fun.  */
153 static const char *
154 hp_symbol_characters (void)
155 {
156   return "_$.<>#,*&[]:(){}";
157 }
158
159 extern int main (int, char **);
160
161 int
162 main (int argc, char **argv)
163 {
164   char *result;
165   int c;
166   const char *valid_symbols;
167   enum demangling_styles style = auto_demangling;
168
169   program_name = argv[0];
170   xmalloc_set_program_name (program_name);
171
172   strip_underscore = TARGET_PREPENDS_UNDERSCORE;
173
174   while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
175     {
176       switch (c)
177         {
178         case '?':
179           usage (stderr, 1);
180           break;
181         case 'h':
182           usage (stdout, 0);
183         case 'n':
184           strip_underscore = 0;
185           break;
186         case 'v':
187           print_version ("c++filt");
188           return (0);
189         case '_':
190           strip_underscore = 1;
191           break;
192         case 's':
193           {
194             style = cplus_demangle_name_to_style (optarg);
195             if (style == unknown_demangling)
196               {
197                 fprintf (stderr, "%s: unknown demangling style `%s'\n",
198                          program_name, optarg);
199                 return (1);
200               }
201             else
202               cplus_demangle_set_style (style);
203           }
204           break;
205         }
206     }
207
208   if (optind < argc)
209     {
210       for ( ; optind < argc; optind++)
211         {
212           demangle_it (argv[optind]);
213         }
214     }
215   else
216     {
217       switch (current_demangling_style)
218         {
219         case gnu_demangling:
220         case lucid_demangling:
221         case arm_demangling:
222         case java_demangling:
223         case edg_demangling:
224         case gnat_demangling:
225         case gnu_v3_demangling:
226         case auto_demangling:
227           valid_symbols = standard_symbol_characters ();
228           break;
229         case hp_demangling:
230           valid_symbols = hp_symbol_characters ();
231           break;
232         default:
233           /* Folks should explicitly indicate the appropriate alphabet for
234              each demangling.  Providing a default would allow the
235              question to go unconsidered.  */
236           fatal ("Internal error: no symbol alphabet for current style");
237         }
238
239       for (;;)
240         {
241           int i = 0;
242           c = getchar ();
243           /* Try to read a label.  */
244           while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
245             {
246               if (i >= MBUF_SIZE-1)
247                 break;
248               mbuffer[i++] = c;
249               c = getchar ();
250             }
251           if (i > 0)
252             {
253               int skip_first = 0;
254
255               mbuffer[i] = 0;
256               if (mbuffer[0] == '.' || mbuffer[0] == '$')
257                 ++skip_first;
258               if (strip_underscore && mbuffer[skip_first] == '_')
259                 ++skip_first;
260
261               if (skip_first > i)
262                 skip_first = i;
263
264               flags |= (int) style;
265               result = cplus_demangle (mbuffer + skip_first, flags);
266               if (result)
267                 {
268                   if (mbuffer[0] == '.')
269                     putc ('.', stdout);
270                   fputs (result, stdout);
271                   free (result);
272                 }
273               else
274                 fputs (mbuffer, stdout);
275
276               fflush (stdout);
277             }
278           if (c == EOF)
279             break;
280           putchar (c);
281           fflush (stdout);
282         }
283     }
284
285   return (0);
286 }