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