xref: /dflybsd-src/contrib/binutils-2.34/libiberty/cplus-dem.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
1*fae548d3Szrj /* Demangler for GNU C++
2*fae548d3Szrj    Copyright (C) 1989-2020 Free Software Foundation, Inc.
3*fae548d3Szrj    Written by James Clark (jjc@jclark.uucp)
4*fae548d3Szrj    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5*fae548d3Szrj    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
6*fae548d3Szrj 
7*fae548d3Szrj This file is part of the libiberty library.
8*fae548d3Szrj Libiberty is free software; you can redistribute it and/or
9*fae548d3Szrj modify it under the terms of the GNU Library General Public
10*fae548d3Szrj License as published by the Free Software Foundation; either
11*fae548d3Szrj version 2 of the License, or (at your option) any later version.
12*fae548d3Szrj 
13*fae548d3Szrj In addition to the permissions in the GNU Library General Public
14*fae548d3Szrj License, the Free Software Foundation gives you unlimited permission
15*fae548d3Szrj to link the compiled version of this file into combinations with other
16*fae548d3Szrj programs, and to distribute those combinations without any restriction
17*fae548d3Szrj coming from the use of this file.  (The Library Public License
18*fae548d3Szrj restrictions do apply in other respects; for example, they cover
19*fae548d3Szrj modification of the file, and distribution when not linked into a
20*fae548d3Szrj combined executable.)
21*fae548d3Szrj 
22*fae548d3Szrj Libiberty is distributed in the hope that it will be useful,
23*fae548d3Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
24*fae548d3Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25*fae548d3Szrj Library General Public License for more details.
26*fae548d3Szrj 
27*fae548d3Szrj You should have received a copy of the GNU Library General Public
28*fae548d3Szrj License along with libiberty; see the file COPYING.LIB.  If
29*fae548d3Szrj not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
30*fae548d3Szrj Boston, MA 02110-1301, USA.  */
31*fae548d3Szrj 
32*fae548d3Szrj /* This file lives in both GCC and libiberty.  When making changes, please
33*fae548d3Szrj    try not to break either.  */
34*fae548d3Szrj 
35*fae548d3Szrj #ifdef HAVE_CONFIG_H
36*fae548d3Szrj #include "config.h"
37*fae548d3Szrj #endif
38*fae548d3Szrj 
39*fae548d3Szrj #include "safe-ctype.h"
40*fae548d3Szrj 
41*fae548d3Szrj #include <string.h>
42*fae548d3Szrj 
43*fae548d3Szrj #ifdef HAVE_STDLIB_H
44*fae548d3Szrj #include <stdlib.h>
45*fae548d3Szrj #else
46*fae548d3Szrj void * malloc ();
47*fae548d3Szrj void * realloc ();
48*fae548d3Szrj #endif
49*fae548d3Szrj 
50*fae548d3Szrj #include <demangle.h>
51*fae548d3Szrj #undef CURRENT_DEMANGLING_STYLE
52*fae548d3Szrj #define CURRENT_DEMANGLING_STYLE options
53*fae548d3Szrj 
54*fae548d3Szrj #include "libiberty.h"
55*fae548d3Szrj 
56*fae548d3Szrj enum demangling_styles current_demangling_style = auto_demangling;
57*fae548d3Szrj 
58*fae548d3Szrj const struct demangler_engine libiberty_demanglers[] =
59*fae548d3Szrj {
60*fae548d3Szrj   {
61*fae548d3Szrj     NO_DEMANGLING_STYLE_STRING,
62*fae548d3Szrj     no_demangling,
63*fae548d3Szrj     "Demangling disabled"
64*fae548d3Szrj   }
65*fae548d3Szrj   ,
66*fae548d3Szrj   {
67*fae548d3Szrj     AUTO_DEMANGLING_STYLE_STRING,
68*fae548d3Szrj       auto_demangling,
69*fae548d3Szrj       "Automatic selection based on executable"
70*fae548d3Szrj   }
71*fae548d3Szrj   ,
72*fae548d3Szrj   {
73*fae548d3Szrj     GNU_V3_DEMANGLING_STYLE_STRING,
74*fae548d3Szrj     gnu_v3_demangling,
75*fae548d3Szrj     "GNU (g++) V3 (Itanium C++ ABI) style demangling"
76*fae548d3Szrj   }
77*fae548d3Szrj   ,
78*fae548d3Szrj   {
79*fae548d3Szrj     JAVA_DEMANGLING_STYLE_STRING,
80*fae548d3Szrj     java_demangling,
81*fae548d3Szrj     "Java style demangling"
82*fae548d3Szrj   }
83*fae548d3Szrj   ,
84*fae548d3Szrj   {
85*fae548d3Szrj     GNAT_DEMANGLING_STYLE_STRING,
86*fae548d3Szrj     gnat_demangling,
87*fae548d3Szrj     "GNAT style demangling"
88*fae548d3Szrj   }
89*fae548d3Szrj   ,
90*fae548d3Szrj   {
91*fae548d3Szrj     DLANG_DEMANGLING_STYLE_STRING,
92*fae548d3Szrj     dlang_demangling,
93*fae548d3Szrj     "DLANG style demangling"
94*fae548d3Szrj   }
95*fae548d3Szrj   ,
96*fae548d3Szrj   {
97*fae548d3Szrj     RUST_DEMANGLING_STYLE_STRING,
98*fae548d3Szrj     rust_demangling,
99*fae548d3Szrj     "Rust style demangling"
100*fae548d3Szrj   }
101*fae548d3Szrj   ,
102*fae548d3Szrj   {
103*fae548d3Szrj     NULL, unknown_demangling, NULL
104*fae548d3Szrj   }
105*fae548d3Szrj };
106*fae548d3Szrj 
107*fae548d3Szrj /* Add a routine to set the demangling style to be sure it is valid and
108*fae548d3Szrj    allow for any demangler initialization that maybe necessary. */
109*fae548d3Szrj 
110*fae548d3Szrj enum demangling_styles
cplus_demangle_set_style(enum demangling_styles style)111*fae548d3Szrj cplus_demangle_set_style (enum demangling_styles style)
112*fae548d3Szrj {
113*fae548d3Szrj   const struct demangler_engine *demangler = libiberty_demanglers;
114*fae548d3Szrj 
115*fae548d3Szrj   for (; demangler->demangling_style != unknown_demangling; ++demangler)
116*fae548d3Szrj     if (style == demangler->demangling_style)
117*fae548d3Szrj       {
118*fae548d3Szrj 	current_demangling_style = style;
119*fae548d3Szrj 	return current_demangling_style;
120*fae548d3Szrj       }
121*fae548d3Szrj 
122*fae548d3Szrj   return unknown_demangling;
123*fae548d3Szrj }
124*fae548d3Szrj 
125*fae548d3Szrj /* Do string name to style translation */
126*fae548d3Szrj 
127*fae548d3Szrj enum demangling_styles
cplus_demangle_name_to_style(const char * name)128*fae548d3Szrj cplus_demangle_name_to_style (const char *name)
129*fae548d3Szrj {
130*fae548d3Szrj   const struct demangler_engine *demangler = libiberty_demanglers;
131*fae548d3Szrj 
132*fae548d3Szrj   for (; demangler->demangling_style != unknown_demangling; ++demangler)
133*fae548d3Szrj     if (strcmp (name, demangler->demangling_style_name) == 0)
134*fae548d3Szrj       return demangler->demangling_style;
135*fae548d3Szrj 
136*fae548d3Szrj   return unknown_demangling;
137*fae548d3Szrj }
138*fae548d3Szrj 
139*fae548d3Szrj /* char *cplus_demangle (const char *mangled, int options)
140*fae548d3Szrj 
141*fae548d3Szrj    If MANGLED is a mangled function name produced by GNU C++, then
142*fae548d3Szrj    a pointer to a @code{malloc}ed string giving a C++ representation
143*fae548d3Szrj    of the name will be returned; otherwise NULL will be returned.
144*fae548d3Szrj    It is the caller's responsibility to free the string which
145*fae548d3Szrj    is returned.
146*fae548d3Szrj 
147*fae548d3Szrj    Note that any leading underscores, or other such characters prepended by
148*fae548d3Szrj    the compilation system, are presumed to have already been stripped from
149*fae548d3Szrj    MANGLED.  */
150*fae548d3Szrj 
151*fae548d3Szrj char *
cplus_demangle(const char * mangled,int options)152*fae548d3Szrj cplus_demangle (const char *mangled, int options)
153*fae548d3Szrj {
154*fae548d3Szrj   char *ret;
155*fae548d3Szrj 
156*fae548d3Szrj   if (current_demangling_style == no_demangling)
157*fae548d3Szrj     return xstrdup (mangled);
158*fae548d3Szrj 
159*fae548d3Szrj   if ((options & DMGL_STYLE_MASK) == 0)
160*fae548d3Szrj     options |= (int) current_demangling_style & DMGL_STYLE_MASK;
161*fae548d3Szrj 
162*fae548d3Szrj   /* The Rust demangling is implemented elsewhere.
163*fae548d3Szrj      Legacy Rust symbols overlap with GNU_V3, so try Rust first.  */
164*fae548d3Szrj   if (RUST_DEMANGLING || AUTO_DEMANGLING)
165*fae548d3Szrj     {
166*fae548d3Szrj       ret = rust_demangle (mangled, options);
167*fae548d3Szrj       if (ret || RUST_DEMANGLING)
168*fae548d3Szrj         return ret;
169*fae548d3Szrj     }
170*fae548d3Szrj 
171*fae548d3Szrj   /* The V3 ABI demangling is implemented elsewhere.  */
172*fae548d3Szrj   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
173*fae548d3Szrj     {
174*fae548d3Szrj       ret = cplus_demangle_v3 (mangled, options);
175*fae548d3Szrj       if (ret || GNU_V3_DEMANGLING)
176*fae548d3Szrj 	return ret;
177*fae548d3Szrj     }
178*fae548d3Szrj 
179*fae548d3Szrj   if (JAVA_DEMANGLING)
180*fae548d3Szrj     {
181*fae548d3Szrj       ret = java_demangle_v3 (mangled);
182*fae548d3Szrj       if (ret)
183*fae548d3Szrj         return ret;
184*fae548d3Szrj     }
185*fae548d3Szrj 
186*fae548d3Szrj   if (GNAT_DEMANGLING)
187*fae548d3Szrj     return ada_demangle (mangled, options);
188*fae548d3Szrj 
189*fae548d3Szrj   if (DLANG_DEMANGLING)
190*fae548d3Szrj     {
191*fae548d3Szrj       ret = dlang_demangle (mangled, options);
192*fae548d3Szrj       if (ret)
193*fae548d3Szrj 	return ret;
194*fae548d3Szrj     }
195*fae548d3Szrj 
196*fae548d3Szrj   return (ret);
197*fae548d3Szrj }
198*fae548d3Szrj 
199*fae548d3Szrj /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
200*fae548d3Szrj 
201*fae548d3Szrj char *
ada_demangle(const char * mangled,int option ATTRIBUTE_UNUSED)202*fae548d3Szrj ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
203*fae548d3Szrj {
204*fae548d3Szrj   int len0;
205*fae548d3Szrj   const char* p;
206*fae548d3Szrj   char *d;
207*fae548d3Szrj   char *demangled = NULL;
208*fae548d3Szrj 
209*fae548d3Szrj   /* Discard leading _ada_, which is used for library level subprograms.  */
210*fae548d3Szrj   if (strncmp (mangled, "_ada_", 5) == 0)
211*fae548d3Szrj     mangled += 5;
212*fae548d3Szrj 
213*fae548d3Szrj   /* All ada unit names are lower-case.  */
214*fae548d3Szrj   if (!ISLOWER (mangled[0]))
215*fae548d3Szrj     goto unknown;
216*fae548d3Szrj 
217*fae548d3Szrj   /* Most of the demangling will trivially remove chars.  Operator names
218*fae548d3Szrj      may add one char but because they are always preceeded by '__' which is
219*fae548d3Szrj      replaced by '.', they eventually never expand the size.
220*fae548d3Szrj      A few special names such as '___elabs' add a few chars (at most 7), but
221*fae548d3Szrj      they occur only once.  */
222*fae548d3Szrj   len0 = strlen (mangled) + 7 + 1;
223*fae548d3Szrj   demangled = XNEWVEC (char, len0);
224*fae548d3Szrj 
225*fae548d3Szrj   d = demangled;
226*fae548d3Szrj   p = mangled;
227*fae548d3Szrj   while (1)
228*fae548d3Szrj     {
229*fae548d3Szrj       /* An entity names is expected.  */
230*fae548d3Szrj       if (ISLOWER (*p))
231*fae548d3Szrj         {
232*fae548d3Szrj           /* An identifier, which is always lower case.  */
233*fae548d3Szrj           do
234*fae548d3Szrj             *d++ = *p++;
235*fae548d3Szrj           while (ISLOWER(*p) || ISDIGIT (*p)
236*fae548d3Szrj                  || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
237*fae548d3Szrj         }
238*fae548d3Szrj       else if (p[0] == 'O')
239*fae548d3Szrj         {
240*fae548d3Szrj           /* An operator name.  */
241*fae548d3Szrj           static const char * const operators[][2] =
242*fae548d3Szrj             {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
243*fae548d3Szrj              {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
244*fae548d3Szrj              {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
245*fae548d3Szrj              {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
246*fae548d3Szrj              {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
247*fae548d3Szrj              {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
248*fae548d3Szrj              {"Oexpon", "**"}, {NULL, NULL}};
249*fae548d3Szrj           int k;
250*fae548d3Szrj 
251*fae548d3Szrj           for (k = 0; operators[k][0] != NULL; k++)
252*fae548d3Szrj             {
253*fae548d3Szrj               size_t slen = strlen (operators[k][0]);
254*fae548d3Szrj               if (strncmp (p, operators[k][0], slen) == 0)
255*fae548d3Szrj                 {
256*fae548d3Szrj                   p += slen;
257*fae548d3Szrj                   slen = strlen (operators[k][1]);
258*fae548d3Szrj                   *d++ = '"';
259*fae548d3Szrj                   memcpy (d, operators[k][1], slen);
260*fae548d3Szrj                   d += slen;
261*fae548d3Szrj                   *d++ = '"';
262*fae548d3Szrj                   break;
263*fae548d3Szrj                 }
264*fae548d3Szrj             }
265*fae548d3Szrj           /* Operator not found.  */
266*fae548d3Szrj           if (operators[k][0] == NULL)
267*fae548d3Szrj             goto unknown;
268*fae548d3Szrj         }
269*fae548d3Szrj       else
270*fae548d3Szrj         {
271*fae548d3Szrj           /* Not a GNAT encoding.  */
272*fae548d3Szrj           goto unknown;
273*fae548d3Szrj         }
274*fae548d3Szrj 
275*fae548d3Szrj       /* The name can be directly followed by some uppercase letters.  */
276*fae548d3Szrj       if (p[0] == 'T' && p[1] == 'K')
277*fae548d3Szrj         {
278*fae548d3Szrj           /* Task stuff.  */
279*fae548d3Szrj           if (p[2] == 'B' && p[3] == 0)
280*fae548d3Szrj             {
281*fae548d3Szrj               /* Subprogram for task body.  */
282*fae548d3Szrj               break;
283*fae548d3Szrj             }
284*fae548d3Szrj           else if (p[2] == '_' && p[3] == '_')
285*fae548d3Szrj             {
286*fae548d3Szrj               /* Inner declarations in a task.  */
287*fae548d3Szrj               p += 4;
288*fae548d3Szrj               *d++ = '.';
289*fae548d3Szrj               continue;
290*fae548d3Szrj             }
291*fae548d3Szrj           else
292*fae548d3Szrj             goto unknown;
293*fae548d3Szrj         }
294*fae548d3Szrj       if (p[0] == 'E' && p[1] == 0)
295*fae548d3Szrj         {
296*fae548d3Szrj           /* Exception name.  */
297*fae548d3Szrj           goto unknown;
298*fae548d3Szrj         }
299*fae548d3Szrj       if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
300*fae548d3Szrj         {
301*fae548d3Szrj           /* Protected type subprogram.  */
302*fae548d3Szrj           break;
303*fae548d3Szrj         }
304*fae548d3Szrj       if ((*p == 'N' || *p == 'S') && p[1] == 0)
305*fae548d3Szrj         {
306*fae548d3Szrj           /* Enumerated type name table.  */
307*fae548d3Szrj           goto unknown;
308*fae548d3Szrj         }
309*fae548d3Szrj       if (p[0] == 'X')
310*fae548d3Szrj         {
311*fae548d3Szrj           /* Body nested.  */
312*fae548d3Szrj           p++;
313*fae548d3Szrj           while (p[0] == 'n' || p[0] == 'b')
314*fae548d3Szrj             p++;
315*fae548d3Szrj         }
316*fae548d3Szrj       if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
317*fae548d3Szrj         {
318*fae548d3Szrj           /* Stream operations.  */
319*fae548d3Szrj           const char *name;
320*fae548d3Szrj           switch (p[1])
321*fae548d3Szrj             {
322*fae548d3Szrj             case 'R':
323*fae548d3Szrj               name = "'Read";
324*fae548d3Szrj               break;
325*fae548d3Szrj             case 'W':
326*fae548d3Szrj               name = "'Write";
327*fae548d3Szrj               break;
328*fae548d3Szrj             case 'I':
329*fae548d3Szrj               name = "'Input";
330*fae548d3Szrj               break;
331*fae548d3Szrj             case 'O':
332*fae548d3Szrj               name = "'Output";
333*fae548d3Szrj               break;
334*fae548d3Szrj             default:
335*fae548d3Szrj               goto unknown;
336*fae548d3Szrj             }
337*fae548d3Szrj           p += 2;
338*fae548d3Szrj           strcpy (d, name);
339*fae548d3Szrj           d += strlen (name);
340*fae548d3Szrj         }
341*fae548d3Szrj       else if (p[0] == 'D')
342*fae548d3Szrj         {
343*fae548d3Szrj           /* Controlled type operation.  */
344*fae548d3Szrj           const char *name;
345*fae548d3Szrj           switch (p[1])
346*fae548d3Szrj             {
347*fae548d3Szrj             case 'F':
348*fae548d3Szrj               name = ".Finalize";
349*fae548d3Szrj               break;
350*fae548d3Szrj             case 'A':
351*fae548d3Szrj               name = ".Adjust";
352*fae548d3Szrj               break;
353*fae548d3Szrj             default:
354*fae548d3Szrj               goto unknown;
355*fae548d3Szrj             }
356*fae548d3Szrj           strcpy (d, name);
357*fae548d3Szrj           d += strlen (name);
358*fae548d3Szrj           break;
359*fae548d3Szrj         }
360*fae548d3Szrj 
361*fae548d3Szrj       if (p[0] == '_')
362*fae548d3Szrj         {
363*fae548d3Szrj           /* Separator.  */
364*fae548d3Szrj           if (p[1] == '_')
365*fae548d3Szrj             {
366*fae548d3Szrj               /* Standard separator.  Handled first.  */
367*fae548d3Szrj               p += 2;
368*fae548d3Szrj 
369*fae548d3Szrj               if (ISDIGIT (*p))
370*fae548d3Szrj                 {
371*fae548d3Szrj                   /* Overloading number.  */
372*fae548d3Szrj                   do
373*fae548d3Szrj                     p++;
374*fae548d3Szrj                   while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
375*fae548d3Szrj                   if (*p == 'X')
376*fae548d3Szrj                     {
377*fae548d3Szrj                       p++;
378*fae548d3Szrj                       while (p[0] == 'n' || p[0] == 'b')
379*fae548d3Szrj                         p++;
380*fae548d3Szrj                     }
381*fae548d3Szrj                 }
382*fae548d3Szrj               else if (p[0] == '_' && p[1] != '_')
383*fae548d3Szrj                 {
384*fae548d3Szrj                   /* Special names.  */
385*fae548d3Szrj                   static const char * const special[][2] = {
386*fae548d3Szrj                     { "_elabb", "'Elab_Body" },
387*fae548d3Szrj                     { "_elabs", "'Elab_Spec" },
388*fae548d3Szrj                     { "_size", "'Size" },
389*fae548d3Szrj                     { "_alignment", "'Alignment" },
390*fae548d3Szrj                     { "_assign", ".\":=\"" },
391*fae548d3Szrj                     { NULL, NULL }
392*fae548d3Szrj                   };
393*fae548d3Szrj                   int k;
394*fae548d3Szrj 
395*fae548d3Szrj                   for (k = 0; special[k][0] != NULL; k++)
396*fae548d3Szrj                     {
397*fae548d3Szrj                       size_t slen = strlen (special[k][0]);
398*fae548d3Szrj                       if (strncmp (p, special[k][0], slen) == 0)
399*fae548d3Szrj                         {
400*fae548d3Szrj                           p += slen;
401*fae548d3Szrj                           slen = strlen (special[k][1]);
402*fae548d3Szrj                           memcpy (d, special[k][1], slen);
403*fae548d3Szrj                           d += slen;
404*fae548d3Szrj                           break;
405*fae548d3Szrj                         }
406*fae548d3Szrj                     }
407*fae548d3Szrj                   if (special[k][0] != NULL)
408*fae548d3Szrj                     break;
409*fae548d3Szrj                   else
410*fae548d3Szrj                     goto unknown;
411*fae548d3Szrj                 }
412*fae548d3Szrj               else
413*fae548d3Szrj                 {
414*fae548d3Szrj                   *d++ = '.';
415*fae548d3Szrj                   continue;
416*fae548d3Szrj                 }
417*fae548d3Szrj             }
418*fae548d3Szrj           else if (p[1] == 'B' || p[1] == 'E')
419*fae548d3Szrj             {
420*fae548d3Szrj               /* Entry Body or barrier Evaluation.  */
421*fae548d3Szrj               p += 2;
422*fae548d3Szrj               while (ISDIGIT (*p))
423*fae548d3Szrj                 p++;
424*fae548d3Szrj               if (p[0] == 's' && p[1] == 0)
425*fae548d3Szrj                 break;
426*fae548d3Szrj               else
427*fae548d3Szrj                 goto unknown;
428*fae548d3Szrj             }
429*fae548d3Szrj           else
430*fae548d3Szrj             goto unknown;
431*fae548d3Szrj         }
432*fae548d3Szrj 
433*fae548d3Szrj       if (p[0] == '.' && ISDIGIT (p[1]))
434*fae548d3Szrj         {
435*fae548d3Szrj           /* Nested subprogram.  */
436*fae548d3Szrj           p += 2;
437*fae548d3Szrj           while (ISDIGIT (*p))
438*fae548d3Szrj             p++;
439*fae548d3Szrj         }
440*fae548d3Szrj       if (*p == 0)
441*fae548d3Szrj         {
442*fae548d3Szrj           /* End of mangled name.  */
443*fae548d3Szrj           break;
444*fae548d3Szrj         }
445*fae548d3Szrj       else
446*fae548d3Szrj         goto unknown;
447*fae548d3Szrj     }
448*fae548d3Szrj   *d = 0;
449*fae548d3Szrj   return demangled;
450*fae548d3Szrj 
451*fae548d3Szrj  unknown:
452*fae548d3Szrj   XDELETEVEC (demangled);
453*fae548d3Szrj   len0 = strlen (mangled);
454*fae548d3Szrj   demangled = XNEWVEC (char, len0 + 3);
455*fae548d3Szrj 
456*fae548d3Szrj   if (mangled[0] == '<')
457*fae548d3Szrj      strcpy (demangled, mangled);
458*fae548d3Szrj   else
459*fae548d3Szrj     sprintf (demangled, "<%s>", mangled);
460*fae548d3Szrj 
461*fae548d3Szrj   return demangled;
462*fae548d3Szrj }
463