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