]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
d-demangle.c (dlang_parse_symbol): Skip over anonymous symbols.
[thirdparty/gcc.git] / libiberty / d-demangle.c
CommitLineData
43b1b9ed 1/* Demangler for the D programming language
2afd3180 2 Copyright (C) 2014-2017 Free Software Foundation, Inc.
43b1b9ed
IB
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11In addition to the permissions in the GNU Library General Public
12License, the Free Software Foundation gives you unlimited permission
13to link the compiled version of this file into combinations with other
14programs, and to distribute those combinations without any restriction
15coming from the use of this file. (The Library Public License
16restrictions do apply in other respects; for example, they cover
17modification of the file, and distribution when not linked into a
18combined executable.)
19
20Libiberty is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23Library General Public License for more details.
24
25You should have received a copy of the GNU Library General Public
26License along with libiberty; see the file COPYING.LIB.
27If not, see <http://www.gnu.org/licenses/>. */
28
29/* This file exports one function; dlang_demangle.
30
fd91ffb8 31 This file imports strtol for decoding mangled literals. */
43b1b9ed
IB
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include "safe-ctype.h"
38
39#include <sys/types.h>
40#include <string.h>
41#include <stdio.h>
42
43#ifdef HAVE_STDLIB_H
44#include <stdlib.h>
45#else
46extern long strtol (const char *nptr, char **endptr, int base);
43b1b9ed
IB
47#endif
48
49#include <demangle.h>
50#include "libiberty.h"
51
52/* A mini string-handling package */
53
54typedef struct string /* Beware: these aren't required to be */
55{ /* '\0' terminated. */
56 char *b; /* pointer to start of string */
57 char *p; /* pointer after last character */
58 char *e; /* pointer after end of allocated space */
59} string;
60
61static void
62string_need (string *s, int n)
63{
64 int tem;
65
66 if (s->b == NULL)
67 {
68 if (n < 32)
69 {
70 n = 32;
71 }
72 s->p = s->b = XNEWVEC (char, n);
73 s->e = s->b + n;
74 }
75 else if (s->e - s->p < n)
76 {
77 tem = s->p - s->b;
78 n += tem;
79 n *= 2;
80 s->b = XRESIZEVEC (char, s->b, n);
81 s->p = s->b + tem;
82 s->e = s->b + n;
83 }
84}
85
86static void
87string_delete (string *s)
88{
89 if (s->b != NULL)
90 {
91 XDELETEVEC (s->b);
92 s->b = s->e = s->p = NULL;
93 }
94}
95
96static void
97string_init (string *s)
98{
99 s->b = s->p = s->e = NULL;
100}
101
102static int
103string_length (string *s)
104{
105 if (s->p == s->b)
106 {
107 return 0;
108 }
109 return s->p - s->b;
110}
111
112static void
113string_setlength (string *s, int n)
114{
115 if (n - string_length (s) < 0)
116 {
117 s->p = s->b + n;
118 }
119}
120
121static void
122string_append (string *p, const char *s)
123{
124 int n = strlen (s);
125 string_need (p, n);
126 memcpy (p->p, s, n);
127 p->p += n;
128}
129
130static void
131string_appendn (string *p, const char *s, int n)
132{
133 if (n != 0)
134 {
135 string_need (p, n);
136 memcpy (p->p, s, n);
137 p->p += n;
138 }
139}
140
141static void
142string_prependn (string *p, const char *s, int n)
143{
144 char *q;
145
146 if (n != 0)
147 {
148 string_need (p, n);
149 for (q = p->p - 1; q >= p->b; q--)
150 {
151 q[n] = q[0];
152 }
153 memcpy (p->b, s, n);
154 p->p += n;
155 }
156}
157
158static void
159string_prepend (string *p, const char *s)
160{
161 if (s != NULL && *s != '\0')
162 {
163 string_prependn (p, s, strlen (s));
164 }
165}
166
7e865541
IB
167/* What kinds of symbol we could be parsing. */
168enum dlang_symbol_kinds
169{
170 /* Top-level symbol, needs it's type checked. */
171 dlang_top_level,
172 /* Function symbol, needs it's type checked. */
173 dlang_function,
174 /* Strongly typed name, such as for classes, structs and enums. */
175 dlang_type_name,
176 /* Template identifier. */
177 dlang_template_ident,
178 /* Template symbol parameter. */
179 dlang_template_param
180};
181
43b1b9ed
IB
182/* Prototypes for forward referenced functions */
183static const char *dlang_function_args (string *, const char *);
184
185static const char *dlang_type (string *, const char *);
186
187static const char *dlang_value (string *, const char *, const char *, char);
188
7e865541
IB
189static const char *dlang_parse_symbol (string *, const char *,
190 enum dlang_symbol_kinds);
43b1b9ed
IB
191
192static const char *dlang_parse_tuple (string *, const char *);
193
194static const char *dlang_parse_template (string *, const char *, long);
195
196
197/* Demangle the calling convention from MANGLED and append it to DECL.
198 Return the remaining string on success or NULL on failure. */
199static const char *
200dlang_call_convention (string *decl, const char *mangled)
201{
202 if (mangled == NULL || *mangled == '\0')
76b41cad 203 return NULL;
43b1b9ed
IB
204
205 switch (*mangled)
206 {
207 case 'F': /* (D) */
208 mangled++;
209 break;
210 case 'U': /* (C) */
211 mangled++;
212 string_append (decl, "extern(C) ");
213 break;
214 case 'W': /* (Windows) */
215 mangled++;
216 string_append (decl, "extern(Windows) ");
217 break;
218 case 'V': /* (Pascal) */
219 mangled++;
220 string_append (decl, "extern(Pascal) ");
221 break;
222 case 'R': /* (C++) */
223 mangled++;
224 string_append (decl, "extern(C++) ");
225 break;
13617162
IB
226 case 'Y': /* (Objective-C) */
227 mangled++;
228 string_append (decl, "extern(Objective-C) ");
229 break;
43b1b9ed
IB
230 default:
231 return NULL;
232 }
233
234 return mangled;
235}
236
fa66ced4
IB
237/* Extract the type modifiers from MANGLED and append them to DECL.
238 Returns the remaining signature on success or NULL on failure. */
239static const char *
240dlang_type_modifiers (string *decl, const char *mangled)
241{
242 if (mangled == NULL || *mangled == '\0')
243 return NULL;
244
245 switch (*mangled)
246 {
247 case 'x': /* const */
248 mangled++;
249 string_append (decl, " const");
250 return mangled;
251 case 'y': /* immutable */
252 mangled++;
253 string_append (decl, " immutable");
254 return mangled;
255 case 'O': /* shared */
256 mangled++;
257 string_append (decl, " shared");
258 return dlang_type_modifiers (decl, mangled);
259 case 'N':
260 mangled++;
261 if (*mangled == 'g') /* wild */
262 {
263 mangled++;
264 string_append (decl, " inout");
265 return dlang_type_modifiers (decl, mangled);
266 }
267 else
268 return NULL;
269
270 default:
271 return mangled;
272 }
273}
274
43b1b9ed
IB
275/* Demangle the D function attributes from MANGLED and append it to DECL.
276 Return the remaining string on success or NULL on failure. */
277static const char *
278dlang_attributes (string *decl, const char *mangled)
279{
280 if (mangled == NULL || *mangled == '\0')
76b41cad 281 return NULL;
43b1b9ed
IB
282
283 while (*mangled == 'N')
284 {
285 mangled++;
286 switch (*mangled)
287 {
288 case 'a': /* pure */
289 mangled++;
290 string_append (decl, "pure ");
291 continue;
292 case 'b': /* nothrow */
293 mangled++;
294 string_append (decl, "nothrow ");
295 continue;
296 case 'c': /* ref */
297 mangled++;
298 string_append (decl, "ref ");
299 continue;
300 case 'd': /* @property */
301 mangled++;
302 string_append (decl, "@property ");
303 continue;
304 case 'e': /* @trusted */
305 mangled++;
306 string_append (decl, "@trusted ");
307 continue;
308 case 'f': /* @safe */
309 mangled++;
310 string_append (decl, "@safe ");
311 continue;
312 case 'g':
313 case 'h':
7ce4461f 314 case 'k':
43b1b9ed
IB
315 /* inout parameter is represented as 'Ng'.
316 vector parameter is represented as 'Nh'.
7ce4461f 317 return paramenter is represented as 'Nk'.
43b1b9ed
IB
318 If we see this, then we know we're really in the
319 parameter list. Rewind and break. */
320 mangled--;
321 break;
322 case 'i': /* @nogc */
323 mangled++;
324 string_append (decl, "@nogc ");
325 continue;
7ce4461f
IB
326 case 'j': /* return */
327 mangled++;
328 string_append (decl, "return ");
329 continue;
ec89d258
IB
330 case 'l': /* scope */
331 mangled++;
332 string_append (decl, "scope ");
333 continue;
7ce4461f
IB
334
335 default: /* unknown attribute */
336 return NULL;
43b1b9ed
IB
337 }
338 break;
339 }
340
341 return mangled;
342}
343
344/* Demangle the function type from MANGLED and append it to DECL.
345 Return the remaining string on success or NULL on failure. */
346static const char *
347dlang_function_type (string *decl, const char *mangled)
348{
349 string attr, args, type;
350 size_t szattr, szargs, sztype;
351
352 if (mangled == NULL || *mangled == '\0')
76b41cad 353 return NULL;
43b1b9ed
IB
354
355 /* The order of the mangled string is:
356 CallConvention FuncAttrs Arguments ArgClose Type
357
358 The demangled string is re-ordered as:
359 CallConvention Type Arguments FuncAttrs
360 */
361 string_init (&attr);
362 string_init (&args);
363 string_init (&type);
364
365 /* Function call convention. */
366 mangled = dlang_call_convention (decl, mangled);
367
368 /* Function attributes. */
369 mangled = dlang_attributes (&attr, mangled);
370 szattr = string_length (&attr);
371
372 /* Function arguments. */
373 mangled = dlang_function_args (&args, mangled);
374 szargs = string_length (&args);
375
376 /* Function return type. */
377 mangled = dlang_type (&type, mangled);
378 sztype = string_length (&type);
379
380 /* Append to decl in order. */
381 string_appendn (decl, type.b, sztype);
382 string_append (decl, "(");
383 string_appendn (decl, args.b, szargs);
384 string_append (decl, ") ");
385 string_appendn (decl, attr.b, szattr);
386
387 string_delete (&attr);
388 string_delete (&args);
389 string_delete (&type);
390 return mangled;
391}
392
393/* Demangle the argument list from MANGLED and append it to DECL.
394 Return the remaining string on success or NULL on failure. */
395static const char *
396dlang_function_args (string *decl, const char *mangled)
397{
398 size_t n = 0;
399
400 while (mangled && *mangled != '\0')
401 {
402 switch (*mangled)
403 {
404 case 'X': /* (variadic T t...) style. */
405 mangled++;
406 string_append (decl, "...");
407 return mangled;
408 case 'Y': /* (variadic T t, ...) style. */
409 mangled++;
acf1f7da
IB
410 if (n != 0)
411 string_append (decl, ", ");
412 string_append (decl, "...");
43b1b9ed
IB
413 return mangled;
414 case 'Z': /* Normal function. */
415 mangled++;
416 return mangled;
417 }
418
419 if (n++)
420 string_append (decl, ", ");
421
422 if (*mangled == 'M') /* scope(T) */
423 {
424 mangled++;
425 string_append (decl, "scope ");
426 }
427
7ce4461f
IB
428 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
429 {
430 mangled += 2;
431 string_append (decl, "return ");
432 }
433
43b1b9ed
IB
434 switch (*mangled)
435 {
436 case 'J': /* out(T) */
437 mangled++;
438 string_append (decl, "out ");
439 break;
440 case 'K': /* ref(T) */
441 mangled++;
442 string_append (decl, "ref ");
443 break;
444 case 'L': /* lazy(T) */
445 mangled++;
446 string_append (decl, "lazy ");
447 break;
448 }
449 mangled = dlang_type (decl, mangled);
450 }
451
452 return mangled;
453}
454
455/* Demangle the type from MANGLED and append it to DECL.
456 Return the remaining string on success or NULL on failure. */
457static const char *
458dlang_type (string *decl, const char *mangled)
459{
460 if (mangled == NULL || *mangled == '\0')
76b41cad 461 return NULL;
43b1b9ed
IB
462
463 switch (*mangled)
464 {
465 case 'O': /* shared(T) */
466 mangled++;
467 string_append (decl, "shared(");
468 mangled = dlang_type (decl, mangled);
469 string_append (decl, ")");
470 return mangled;
471 case 'x': /* const(T) */
472 mangled++;
473 string_append (decl, "const(");
474 mangled = dlang_type (decl, mangled);
475 string_append (decl, ")");
476 return mangled;
477 case 'y': /* immutable(T) */
478 mangled++;
479 string_append (decl, "immutable(");
480 mangled = dlang_type (decl, mangled);
481 string_append (decl, ")");
482 return mangled;
483 case 'N':
484 mangled++;
485 if (*mangled == 'g') /* wild(T) */
486 {
487 mangled++;
488 string_append (decl, "inout(");
489 mangled = dlang_type (decl, mangled);
490 string_append (decl, ")");
491 return mangled;
492 }
493 else if (*mangled == 'h') /* vector(T) */
494 {
495 mangled++;
496 string_append (decl, "__vector(");
497 mangled = dlang_type (decl, mangled);
498 string_append (decl, ")");
499 return mangled;
500 }
501 else
502 return NULL;
503 case 'A': /* dynamic array (T[]) */
504 mangled++;
505 mangled = dlang_type (decl, mangled);
506 string_append (decl, "[]");
507 return mangled;
508 case 'G': /* static array (T[N]) */
509 {
510 const char *numptr;
511 size_t num = 0;
512 mangled++;
513
514 numptr = mangled;
515 while (ISDIGIT (*mangled))
516 {
517 num++;
518 mangled++;
519 }
520 mangled = dlang_type (decl, mangled);
521 string_append (decl, "[");
522 string_appendn (decl, numptr, num);
523 string_append (decl, "]");
524 return mangled;
525 }
526 case 'H': /* associative array (T[T]) */
527 {
528 string type;
529 size_t sztype;
530 mangled++;
531
532 string_init (&type);
533 mangled = dlang_type (&type, mangled);
534 sztype = string_length (&type);
535
536 mangled = dlang_type (decl, mangled);
537 string_append (decl, "[");
538 string_appendn (decl, type.b, sztype);
539 string_append (decl, "]");
540
541 string_delete (&type);
542 return mangled;
543 }
544 case 'P': /* pointer (T*) */
545 mangled++;
0f4b8b31
IB
546 /* Function pointer types don't include the trailing asterisk. */
547 switch (*mangled)
548 {
549 case 'F': case 'U': case 'W':
13617162 550 case 'V': case 'R': case 'Y':
0f4b8b31
IB
551 mangled = dlang_function_type (decl, mangled);
552 string_append (decl, "function");
553 return mangled;
554 }
43b1b9ed
IB
555 mangled = dlang_type (decl, mangled);
556 string_append (decl, "*");
557 return mangled;
558 case 'I': /* ident T */
559 case 'C': /* class T */
560 case 'S': /* struct T */
561 case 'E': /* enum T */
562 case 'T': /* typedef T */
563 mangled++;
7e865541 564 return dlang_parse_symbol (decl, mangled, dlang_type_name);
43b1b9ed 565 case 'D': /* delegate T */
fa66ced4
IB
566 {
567 string mods;
568 size_t szmods;
43b1b9ed 569 mangled++;
fa66ced4
IB
570
571 string_init (&mods);
572 mangled = dlang_type_modifiers (&mods, mangled);
573 szmods = string_length (&mods);
574
43b1b9ed
IB
575 mangled = dlang_function_type (decl, mangled);
576 string_append (decl, "delegate");
fa66ced4
IB
577 string_appendn (decl, mods.b, szmods);
578
579 string_delete (&mods);
43b1b9ed 580 return mangled;
fa66ced4 581 }
43b1b9ed
IB
582 case 'B': /* tuple T */
583 mangled++;
584 return dlang_parse_tuple (decl, mangled);
585
43b1b9ed
IB
586 /* Basic types */
587 case 'n':
588 mangled++;
589 string_append (decl, "none");
590 return mangled;
591 case 'v':
592 mangled++;
593 string_append (decl, "void");
594 return mangled;
595 case 'g':
596 mangled++;
597 string_append (decl, "byte");
598 return mangled;
599 case 'h':
600 mangled++;
601 string_append (decl, "ubyte");
602 return mangled;
603 case 's':
604 mangled++;
605 string_append (decl, "short");
606 return mangled;
607 case 't':
608 mangled++;
609 string_append (decl, "ushort");
610 return mangled;
611 case 'i':
612 mangled++;
613 string_append (decl, "int");
614 return mangled;
615 case 'k':
616 mangled++;
617 string_append (decl, "uint");
618 return mangled;
619 case 'l':
620 mangled++;
621 string_append (decl, "long");
622 return mangled;
623 case 'm':
624 mangled++;
625 string_append (decl, "ulong");
626 return mangled;
627 case 'f':
628 mangled++;
629 string_append (decl, "float");
630 return mangled;
631 case 'd':
632 mangled++;
633 string_append (decl, "double");
634 return mangled;
635 case 'e':
636 mangled++;
637 string_append (decl, "real");
638 return mangled;
639
640 /* Imaginary and Complex types */
641 case 'o':
642 mangled++;
643 string_append (decl, "ifloat");
644 return mangled;
645 case 'p':
646 mangled++;
647 string_append (decl, "idouble");
648 return mangled;
649 case 'j':
650 mangled++;
651 string_append (decl, "ireal");
652 return mangled;
653 case 'q':
654 mangled++;
655 string_append (decl, "cfloat");
656 return mangled;
657 case 'r':
658 mangled++;
659 string_append (decl, "cdouble");
660 return mangled;
661 case 'c':
662 mangled++;
663 string_append (decl, "creal");
664 return mangled;
665
666 /* Other types */
667 case 'b':
668 mangled++;
669 string_append (decl, "bool");
670 return mangled;
671 case 'a':
672 mangled++;
673 string_append (decl, "char");
674 return mangled;
675 case 'u':
676 mangled++;
677 string_append (decl, "wchar");
678 return mangled;
679 case 'w':
680 mangled++;
681 string_append (decl, "dchar");
682 return mangled;
59251a73
IB
683 case 'z':
684 mangled++;
685 switch (*mangled)
686 {
687 case 'i':
688 mangled++;
689 string_append (decl, "cent");
690 return mangled;
691 case 'k':
692 mangled++;
693 string_append (decl, "ucent");
694 return mangled;
695 }
696 return NULL;
43b1b9ed
IB
697
698 default: /* unhandled */
699 return NULL;
700 }
701}
702
703/* Extract the identifier from MANGLED and append it to DECL.
704 Return the remaining string on success or NULL on failure. */
705static const char *
7e865541
IB
706dlang_identifier (string *decl, const char *mangled,
707 enum dlang_symbol_kinds kind)
43b1b9ed 708{
7e865541
IB
709 char *endptr;
710 long len;
711
43b1b9ed 712 if (mangled == NULL || *mangled == '\0')
76b41cad 713 return NULL;
43b1b9ed 714
7e865541
IB
715 len = strtol (mangled, &endptr, 10);
716
717 if (endptr == NULL || len <= 0)
718 return NULL;
719
720 /* In template parameter symbols, the first character of the mangled
721 name can be a digit. This causes ambiguity issues because the
722 digits of the two numbers are adjacent. */
723 if (kind == dlang_template_param)
43b1b9ed 724 {
7e865541
IB
725 long psize = len;
726 char *pend;
727 int saved = string_length (decl);
728
729 /* Work backwards until a match is found. */
730 for (pend = endptr; endptr != NULL; pend--)
731 {
732 mangled = pend;
43b1b9ed 733
7e865541
IB
734 /* Reached the beginning of the pointer to the name length,
735 try parsing the entire symbol. */
736 if (psize == 0)
737 {
738 psize = len;
739 pend = endptr;
740 endptr = NULL;
741 }
742
743 /* Check whether template parameter is a function with a valid
744 return type or an untyped identifier. */
745 if (ISDIGIT (*mangled))
746 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
747 else if (strncmp (mangled, "_D", 2) == 0)
748 {
749 mangled += 2;
750 mangled = dlang_parse_symbol (decl, mangled, dlang_function);
751 }
752
753 /* Check for name length mismatch. */
754 if (mangled && (mangled - pend) == psize)
755 return mangled;
756
757 psize /= 10;
758 string_setlength (decl, saved);
759 }
760
761 /* No match on any combinations. */
762 return NULL;
763 }
764 else
765 {
766 if (strlen (endptr) < (size_t) len)
43b1b9ed
IB
767 return NULL;
768
769 mangled = endptr;
770
771 /* May be a template instance. */
c6f44bae
IB
772 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
773 && (mangled[2] == 'T' || mangled[2] == 'U'))
774 return dlang_parse_template (decl, mangled, len);
43b1b9ed 775
7e865541 776 switch (len)
43b1b9ed 777 {
5cc158e9 778 case 6:
7e865541 779 if (strncmp (mangled, "__ctor", len) == 0)
5cc158e9
IB
780 {
781 /* Constructor symbol for a class/struct. */
782 string_append (decl, "this");
7e865541 783 mangled += len;
5cc158e9
IB
784 return mangled;
785 }
7e865541 786 else if (strncmp (mangled, "__dtor", len) == 0)
5cc158e9
IB
787 {
788 /* Destructor symbol for a class/struct. */
789 string_append (decl, "~this");
7e865541 790 mangled += len;
5cc158e9
IB
791 return mangled;
792 }
7e865541 793 else if (strncmp (mangled, "__initZ", len+1) == 0)
5cc158e9
IB
794 {
795 /* The static initialiser for a given symbol. */
796 string_append (decl, "init$");
7e865541 797 mangled += len;
5cc158e9
IB
798 return mangled;
799 }
7e865541 800 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
5cc158e9
IB
801 {
802 /* The vtable symbol for a given class. */
803 string_prepend (decl, "vtable for ");
804 string_setlength (decl, string_length (decl) - 1);
7e865541 805 mangled += len;
5cc158e9
IB
806 return mangled;
807 }
808 break;
809
810 case 7:
7e865541 811 if (strncmp (mangled, "__ClassZ", len+1) == 0)
5cc158e9
IB
812 {
813 /* The classinfo symbol for a given class. */
814 string_prepend (decl, "ClassInfo for ");
815 string_setlength (decl, string_length (decl) - 1);
7e865541 816 mangled += len;
5cc158e9
IB
817 return mangled;
818 }
819 break;
820
821 case 10:
7e865541 822 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
5cc158e9
IB
823 {
824 /* Postblit symbol for a struct. */
825 string_append (decl, "this(this)");
7e865541 826 mangled += len + 3;
5cc158e9
IB
827 return mangled;
828 }
829 break;
830
831 case 11:
7e865541 832 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
5cc158e9
IB
833 {
834 /* The interface symbol for a given class. */
835 string_prepend (decl, "Interface for ");
836 string_setlength (decl, string_length (decl) - 1);
7e865541 837 mangled += len;
5cc158e9
IB
838 return mangled;
839 }
840 break;
841
842 case 12:
7e865541 843 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
5cc158e9
IB
844 {
845 /* The ModuleInfo symbol for a given module. */
846 string_prepend (decl, "ModuleInfo for ");
847 string_setlength (decl, string_length (decl) - 1);
7e865541 848 mangled += len;
5cc158e9
IB
849 return mangled;
850 }
851 break;
43b1b9ed
IB
852 }
853
7e865541
IB
854 string_appendn (decl, mangled, len);
855 mangled += len;
43b1b9ed 856 }
43b1b9ed
IB
857
858 return mangled;
859}
860
861/* Extract the integer value from MANGLED and append it to DECL,
862 where TYPE is the type it should be represented as.
863 Return the remaining string on success or NULL on failure. */
864static const char *
865dlang_parse_integer (string *decl, const char *mangled, char type)
866{
867 if (type == 'a' || type == 'u' || type == 'w')
868 {
869 /* Parse character value. */
870 char value[10];
871 int pos = 10;
872 int width = 0;
873 char *endptr;
874 long val = strtol (mangled, &endptr, 10);
875
876 if (endptr == NULL || val < 0)
877 return NULL;
878
879 string_append (decl, "'");
880
881 if (type == 'a' && val >= 0x20 && val < 0x7F)
882 {
883 /* Represent as a character literal. */
884 char c = (char) val;
885 string_appendn (decl, &c, 1);
886 }
887 else
888 {
889 /* Represent as a hexadecimal value. */
890 switch (type)
891 {
892 case 'a': /* char */
893 string_append (decl, "\\x");
894 width = 2;
895 break;
896 case 'u': /* wchar */
897 string_append (decl, "\\u");
898 width = 4;
899 break;
900 case 'w': /* dchar */
901 string_append (decl, "\\U");
902 width = 8;
903 break;
904 }
905
906 while (val > 0)
907 {
908 int digit = val % 16;
909
910 if (digit < 10)
911 value[--pos] = (char)(digit + '0');
912 else
913 value[--pos] = (char)((digit - 10) + 'a');
914
915 val /= 16;
916 width--;
917 }
918
919 for (; width > 0; width--)
920 value[--pos] = '0';
921
922 string_appendn (decl, &(value[pos]), 10 - pos);
923 }
924 string_append (decl, "'");
925 mangled = endptr;
926 }
927 else if (type == 'b')
928 {
929 /* Parse boolean value. */
930 char *endptr;
931 long val = strtol (mangled, &endptr, 10);
932
933 if (endptr == NULL || val < 0)
934 return NULL;
935
936 string_append (decl, val ? "true" : "false");
937 mangled = endptr;
938 }
939 else
940 {
941 /* Parse integer value. */
942 const char *numptr = mangled;
943 size_t num = 0;
944
945 while (ISDIGIT (*mangled))
946 {
947 num++;
948 mangled++;
949 }
950 string_appendn (decl, numptr, num);
951
952 /* Append suffix. */
953 switch (type)
954 {
955 case 'h': /* ubyte */
956 case 't': /* ushort */
957 case 'k': /* uint */
958 string_append (decl, "u");
959 break;
960 case 'l': /* long */
961 string_append (decl, "L");
962 break;
963 case 'm': /* ulong */
964 string_append (decl, "uL");
965 break;
966 }
967 }
968
969 return mangled;
970}
971
972/* Extract the floating-point value from MANGLED and append it to DECL.
973 Return the remaining string on success or NULL on failure. */
974static const char *
975dlang_parse_real (string *decl, const char *mangled)
976{
977 char buffer[64];
978 int len = 0;
43b1b9ed
IB
979
980 /* Handle NAN and +-INF. */
981 if (strncmp (mangled, "NAN", 3) == 0)
982 {
983 string_append (decl, "NaN");
984 mangled += 3;
985 return mangled;
986 }
987 else if (strncmp (mangled, "INF", 3) == 0)
988 {
989 string_append (decl, "Inf");
990 mangled += 3;
991 return mangled;
992 }
993 else if (strncmp (mangled, "NINF", 4) == 0)
994 {
995 string_append (decl, "-Inf");
996 mangled += 4;
997 return mangled;
998 }
999
1000 /* Hexadecimal prefix and leading bit. */
1001 if (*mangled == 'N')
1002 {
1003 buffer[len++] = '-';
1004 mangled++;
1005 }
1006
1007 if (!ISXDIGIT (*mangled))
1008 return NULL;
1009
1010 buffer[len++] = '0';
1011 buffer[len++] = 'x';
1012 buffer[len++] = *mangled;
1013 buffer[len++] = '.';
1014 mangled++;
1015
1016 /* Significand. */
1017 while (ISXDIGIT (*mangled))
1018 {
1019 buffer[len++] = *mangled;
1020 mangled++;
1021 }
1022
1023 /* Exponent. */
1024 if (*mangled != 'P')
1025 return NULL;
1026
1027 buffer[len++] = 'p';
1028 mangled++;
1029
1030 if (*mangled == 'N')
1031 {
1032 buffer[len++] = '-';
1033 mangled++;
1034 }
1035
1036 while (ISDIGIT (*mangled))
1037 {
1038 buffer[len++] = *mangled;
1039 mangled++;
1040 }
1041
fd91ffb8
IB
1042 /* Write out the demangled hexadecimal, rather than trying to
1043 convert the buffer into a floating-point value. */
43b1b9ed 1044 buffer[len] = '\0';
fd91ffb8 1045 len = strlen (buffer);
43b1b9ed
IB
1046 string_appendn (decl, buffer, len);
1047 return mangled;
1048}
1049
1050/* Convert VAL from an ascii hexdigit to value. */
1051static char
1052ascii2hex (char val)
1053{
1054 if (val >= 'a' && val <= 'f')
1055 return (val - 'a' + 10);
1056
1057 if (val >= 'A' && val <= 'F')
1058 return (val - 'A' + 10);
1059
1060 if (val >= '0' && val <= '9')
1061 return (val - '0');
1062
1063 return 0;
1064}
1065
1066/* Extract the string value from MANGLED and append it to DECL.
1067 Return the remaining string on success or NULL on failure. */
1068static const char *
1069dlang_parse_string (string *decl, const char *mangled)
1070{
1071 char type = *mangled;
1072 char *endptr;
1073 long len;
1074
1075 mangled++;
1076 len = strtol (mangled, &endptr, 10);
1077
1078 if (endptr == NULL || len < 0)
1079 return NULL;
1080
1081 mangled = endptr;
1082 if (*mangled != '_')
1083 return NULL;
1084
1085 mangled++;
1086 string_append (decl, "\"");
1087 while (len--)
1088 {
1089 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1090 {
1091 char a = ascii2hex (mangled[0]);
1092 char b = ascii2hex (mangled[1]);
1093 char val = (a << 4) | b;
eb058b7d
IB
1094
1095 /* Sanitize white and non-printable characters. */
1096 switch (val)
1097 {
1098 case ' ':
1099 string_append (decl, " ");
1100 break;
1101 case '\t':
1102 string_append (decl, "\\t");
1103 break;
1104 case '\n':
1105 string_append (decl, "\\n");
1106 break;
1107 case '\r':
1108 string_append (decl, "\\r");
1109 break;
1110 case '\f':
1111 string_append (decl, "\\f");
1112 break;
1113 case '\v':
1114 string_append (decl, "\\v");
1115 break;
1116
1117 default:
1118 if (ISPRINT (val))
1119 string_appendn (decl, &val, 1);
1120 else
1121 {
1122 string_append (decl, "\\x");
1123 string_appendn (decl, mangled, 2);
1124 }
1125 }
43b1b9ed
IB
1126 }
1127 else
1128 return NULL;
1129
1130 mangled += 2;
1131 }
1132 string_append (decl, "\"");
1133
1134 if (type != 'a')
1135 string_appendn (decl, &type, 1);
1136
1137 return mangled;
1138}
1139
1140/* Extract the static array value from MANGLED and append it to DECL.
1141 Return the remaining string on success or NULL on failure. */
1142static const char *
1143dlang_parse_arrayliteral (string *decl, const char *mangled)
1144{
1145 char *endptr;
1146 long elements = strtol (mangled, &endptr, 10);
1147
1148 if (endptr == NULL || elements < 0)
1149 return NULL;
1150
1151 mangled = endptr;
1152 string_append (decl, "[");
1153 while (elements--)
1154 {
1155 mangled = dlang_value (decl, mangled, NULL, '\0');
1156 if (elements != 0)
1157 string_append (decl, ", ");
1158 }
1159
1160 string_append (decl, "]");
1161 return mangled;
1162}
1163
1164/* Extract the associative array value from MANGLED and append it to DECL.
1165 Return the remaining string on success or NULL on failure. */
1166static const char *
1167dlang_parse_assocarray (string *decl, const char *mangled)
1168{
1169 char *endptr;
1170 long elements = strtol (mangled, &endptr, 10);
1171
1172 if (endptr == NULL || elements < 0)
1173 return NULL;
1174
1175 mangled = endptr;
1176 string_append (decl, "[");
1177 while (elements--)
1178 {
1179 mangled = dlang_value (decl, mangled, NULL, '\0');
1180 string_append (decl, ":");
1181 mangled = dlang_value (decl, mangled, NULL, '\0');
1182
1183 if (elements != 0)
1184 string_append (decl, ", ");
1185 }
1186
1187 string_append (decl, "]");
1188 return mangled;
1189}
1190
1191/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1192 Return the remaining string on success or NULL on failure. */
1193static const char *
1194dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1195{
1196 char *endptr;
1197 long args = strtol (mangled, &endptr, 10);
1198
1199 if (endptr == NULL || args < 0)
1200 return NULL;
1201
1202 mangled = endptr;
1203 if (name != NULL)
1204 string_append (decl, name);
1205
1206 string_append (decl, "(");
1207 while (args--)
1208 {
1209 mangled = dlang_value (decl, mangled, NULL, '\0');
1210 if (args != 0)
1211 string_append (decl, ", ");
1212 }
1213
1214 string_append (decl, ")");
1215 return mangled;
1216}
1217
1218/* Extract the value from MANGLED and append it to DECL.
1219 Return the remaining string on success or NULL on failure. */
1220static const char *
1221dlang_value (string *decl, const char *mangled, const char *name, char type)
1222{
1223 if (mangled == NULL || *mangled == '\0')
76b41cad 1224 return NULL;
43b1b9ed
IB
1225
1226 switch (*mangled)
1227 {
1228 /* Null value. */
1229 case 'n':
1230 mangled++;
1231 string_append (decl, "null");
1232 break;
1233
1234 /* Integral values. */
1235 case 'N':
1236 mangled++;
1237 string_append (decl, "-");
1238 mangled = dlang_parse_integer (decl, mangled, type);
1239 break;
1240
1241 case 'i':
1242 mangled++;
1243 if (*mangled < '0' || *mangled > '9')
1244 return NULL;
1245 /* Fall through */
1246 case '0': case '1': case '2': case '3': case '4':
1247 case '5': case '6': case '7': case '8': case '9':
1248 mangled = dlang_parse_integer (decl, mangled, type);
1249 break;
1250
1251 /* Real value. */
1252 case 'e':
1253 mangled++;
1254 mangled = dlang_parse_real (decl, mangled);
1255 break;
1256
1257 /* Complex value. */
1258 case 'c':
1259 mangled++;
1260 mangled = dlang_parse_real (decl, mangled);
1261 string_append (decl, "+");
1262 if (mangled == NULL || *mangled != 'c')
1263 return NULL;
1264 mangled++;
1265 mangled = dlang_parse_real (decl, mangled);
1266 string_append (decl, "i");
1267 break;
1268
1269 /* String values. */
1270 case 'a': /* UTF8 */
1271 case 'w': /* UTF16 */
1272 case 'd': /* UTF32 */
1273 mangled = dlang_parse_string (decl, mangled);
1274 break;
1275
1276 /* Array values. */
1277 case 'A':
1278 mangled++;
1279 if (type == 'H')
1280 mangled = dlang_parse_assocarray (decl, mangled);
1281 else
1282 mangled = dlang_parse_arrayliteral (decl, mangled);
1283 break;
1284
1285 /* Struct values. */
1286 case 'S':
1287 mangled++;
1288 mangled = dlang_parse_structlit (decl, mangled, name);
1289 break;
1290
1291 default:
1292 return NULL;
1293 }
1294
1295 return mangled;
1296}
1297
fa66ced4
IB
1298/* Extract the type modifiers from MANGLED and return the string
1299 length that it consumes in MANGLED on success or 0 on failure. */
43b1b9ed 1300static int
fa66ced4 1301dlang_type_modifier_p (const char *mangled)
43b1b9ed 1302{
fa66ced4 1303 int i;
43b1b9ed
IB
1304
1305 switch (*mangled)
1306 {
fa66ced4 1307 case 'x': case 'y':
43b1b9ed
IB
1308 return 1;
1309
fa66ced4
IB
1310 case 'O':
1311 mangled++;
1312 i = dlang_type_modifier_p (mangled);
1313 return i + 1;
43b1b9ed 1314
fa66ced4
IB
1315 case 'N':
1316 mangled++;
1317 if (*mangled == 'g')
43b1b9ed 1318 {
fa66ced4
IB
1319 mangled++;
1320 i = dlang_type_modifier_p (mangled);
1321 return i + 2;
43b1b9ed 1322 }
fa66ced4
IB
1323 }
1324
1325 return 0;
1326}
1327
1328/* Extract the function calling convention from MANGLED and
1329 return 1 on success or 0 on failure. */
1330static int
1331dlang_call_convention_p (const char *mangled)
1332{
1333 /* Prefix for functions needing 'this' */
1334 if (*mangled == 'M')
1335 {
1336 mangled++;
1337 /* Also skip over any type modifiers. */
1338 mangled += dlang_type_modifier_p (mangled);
1339 }
1340
1341 switch (*mangled)
1342 {
1343 case 'F': case 'U': case 'V':
13617162 1344 case 'W': case 'R': case 'Y':
fa66ced4 1345 return 1;
43b1b9ed
IB
1346
1347 default:
1348 return 0;
1349 }
1350}
1351
1352/* Extract and demangle the symbol in MANGLED and append it to DECL.
1353 Returns the remaining signature on success or NULL on failure. */
1354static const char *
7e865541
IB
1355dlang_parse_symbol (string *decl, const char *mangled,
1356 enum dlang_symbol_kinds kind)
43b1b9ed 1357{
7e865541 1358 int saved;
43b1b9ed
IB
1359 size_t n = 0;
1360 do
1361 {
1362 if (n++)
1363 string_append (decl, ".");
1364
98bb7ee2
IB
1365 /* Skip over anonymous symbols. */
1366 while (*mangled == '0')
1367 mangled++;
1368
7e865541 1369 mangled = dlang_identifier (decl, mangled, kind);
43b1b9ed
IB
1370
1371 if (mangled && dlang_call_convention_p (mangled))
1372 {
fa66ced4 1373 string mods;
7e865541
IB
1374 const char *start = NULL;
1375 int checkpoint = 0;
43b1b9ed
IB
1376
1377 /* Skip over 'this' parameter. */
1378 if (*mangled == 'M')
fa66ced4
IB
1379 mangled++;
1380
7e865541
IB
1381 /* We have reached here because we expect an extern(Pascal) function.
1382 However this is so rare, that it is more likely a template value
1383 parameter. Since this can't be assumed, first attempt parsing
1384 the symbol as a function, and then back out on failure. */
1385 if (*mangled == 'V')
1386 {
1387 start = mangled;
1388 checkpoint = string_length (decl);
1389 }
1390
fa66ced4
IB
1391 /* Save the type modifiers for appending at the end. */
1392 string_init (&mods);
1393 mangled = dlang_type_modifiers (&mods, mangled);
43b1b9ed
IB
1394
1395 /* Skip over calling convention and attributes in qualified name. */
1396 saved = string_length (decl);
1397 mangled = dlang_call_convention (decl, mangled);
1398 mangled = dlang_attributes (decl, mangled);
1399 string_setlength (decl, saved);
1400
1401 string_append (decl, "(");
1402 mangled = dlang_function_args (decl, mangled);
1403 string_append (decl, ")");
1404
fa66ced4
IB
1405 /* Add any const/immutable/shared modifier. */
1406 string_appendn (decl, mods.b, string_length (&mods));
1407 string_delete (&mods);
7e865541
IB
1408
1409 if (mangled == NULL && checkpoint != 0)
1410 {
1411 mangled = start;
1412 string_setlength (decl, checkpoint);
1413 }
43b1b9ed
IB
1414 }
1415 }
1416 while (mangled && ISDIGIT (*mangled));
1417
7e865541
IB
1418 /* Only top-level symbols or function template parameters have
1419 a type that needs checking. */
1420 if (kind == dlang_top_level || kind == dlang_function)
1421 {
1422 /* Artificial symbols end with 'Z' and have no type. */
1423 if (mangled && *mangled == 'Z')
1424 mangled++;
1425 else
1426 {
1427 saved = string_length (decl);
1428 mangled = dlang_type (decl, mangled);
1429 string_setlength (decl, saved);
1430 }
1431
1432 /* Check that the entire symbol was successfully demangled. */
1433 if (kind == dlang_top_level)
1434 {
1435 if (mangled == NULL || *mangled != '\0')
1436 return NULL;
1437 }
1438 }
1439
43b1b9ed
IB
1440 return mangled;
1441}
1442
1443/* Demangle the tuple from MANGLED and append it to DECL.
1444 Return the remaining string on success or NULL on failure. */
1445static const char *
1446dlang_parse_tuple (string *decl, const char *mangled)
1447{
1448 char *endptr;
1449 long elements = strtol (mangled, &endptr, 10);
1450
1451 if (endptr == NULL || elements < 0)
1452 return NULL;
1453
1454 mangled = endptr;
1455 string_append (decl, "Tuple!(");
1456
1457 while (elements--)
1458 {
1459 mangled = dlang_type (decl, mangled);
1460 if (elements != 0)
1461 string_append (decl, ", ");
1462 }
1463
1464 string_append (decl, ")");
1465 return mangled;
1466}
1467
1468/* Demangle the argument list from MANGLED and append it to DECL.
1469 Return the remaining string on success or NULL on failure. */
1470static const char *
1471dlang_template_args (string *decl, const char *mangled)
1472{
1473 size_t n = 0;
1474
1475 while (mangled && *mangled != '\0')
1476 {
1477 switch (*mangled)
1478 {
1479 case 'Z': /* End of parameter list. */
1480 mangled++;
1481 return mangled;
1482 }
1483
1484 if (n++)
1485 string_append (decl, ", ");
1486
ed4cdb85
IB
1487 /* Skip over specialised template prefix. */
1488 if (*mangled == 'H')
1489 mangled++;
1490
43b1b9ed
IB
1491 switch (*mangled)
1492 {
1493 case 'S': /* Symbol parameter. */
1494 mangled++;
7e865541 1495 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
43b1b9ed
IB
1496 break;
1497 case 'T': /* Type parameter. */
1498 mangled++;
1499 mangled = dlang_type (decl, mangled);
1500 break;
1501 case 'V': /* Value parameter. */
1502 {
1503 string name;
1504 char type;
1505
1506 /* Peek at the type. */
1507 mangled++;
1508 type = *mangled;
1509
1510 /* In the few instances where the type is actually desired in
1511 the output, it should precede the value from dlang_value. */
1512 string_init (&name);
1513 mangled = dlang_type (&name, mangled);
1514 string_need (&name, 1);
1515 *(name.p) = '\0';
1516
1517 mangled = dlang_value (decl, mangled, name.b, type);
1518 string_delete (&name);
1519 break;
1520 }
1521
1522 default:
1523 return NULL;
1524 }
1525 }
1526
1527 return mangled;
1528}
1529
1530/* Extract and demangle the template symbol in MANGLED, expected to
1531 be made up of LEN characters, and append it to DECL.
1532 Returns the remaining signature on success or NULL on failure. */
1533static const char *
1534dlang_parse_template (string *decl, const char *mangled, long len)
1535{
1536 const char *start = mangled;
1537
1538 /* Template instance names have the types and values of its parameters
1539 encoded into it.
1540
1541 TemplateInstanceName:
1542 Number __T LName TemplateArgs Z
c6f44bae 1543 Number __U LName TemplateArgs Z
43b1b9ed
IB
1544 ^
1545 The start pointer should be at the above location, and LEN should be
1546 the value of the decoded number.
1547 */
c6f44bae
IB
1548
1549 /* Template symbol. */
1550 if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
43b1b9ed
IB
1551 return NULL;
1552
1553 mangled += 3;
1554
1555 /* Template identifier. */
7e865541 1556 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
43b1b9ed
IB
1557
1558 /* Template arguments. */
1559 string_append (decl, "!(");
1560 mangled = dlang_template_args (decl, mangled);
1561 string_append (decl, ")");
1562
1563 /* Check for template name length mismatch. */
1564 if (mangled && (mangled - start) != len)
1565 return NULL;
1566
1567 return mangled;
1568}
1569
1570/* Extract and demangle the symbol in MANGLED. Returns the demangled
1571 signature on success or NULL on failure. */
1572
1573char *
1574dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1575{
1576 string decl;
1577 char *demangled = NULL;
1578
1579 if (mangled == NULL || *mangled == '\0')
1580 return NULL;
1581
1582 if (strncmp (mangled, "_D", 2) != 0)
1583 return NULL;
1584
1585 string_init (&decl);
1586
1587 if (strcmp (mangled, "_Dmain") == 0)
1588 {
1589 string_append (&decl, "D main");
1590 }
1591 else
1592 {
1593 mangled += 2;
1594
7e865541 1595 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
43b1b9ed
IB
1596 string_delete (&decl);
1597 }
1598
1599 if (string_length (&decl) > 0)
1600 {
1601 string_need (&decl, 1);
1602 *(decl.p) = '\0';
1603 demangled = decl.b;
1604 }
1605
1606 return demangled;
1607}
1608