Remove some explicit memory management from dwarf2read.c
[deliverable/binutils-gdb.git] / libiberty / d-demangle.c
CommitLineData
b55f9678 1/* Demangler for the D programming language
82704155 2 Copyright (C) 2014-2019 Free Software Foundation, Inc.
b55f9678
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
d7e2ebe7 29/* This file exports one function; dlang_demangle. */
b55f9678
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>
b55f9678
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
f91ca6bc
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
b55f9678
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
d7e2ebe7
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 *,
f91ca6bc 189 enum dlang_symbol_kinds);
b55f9678
IB
190
191static const char *dlang_parse_tuple (string *, const char *);
192
193static const char *dlang_parse_template (string *, const char *, long);
194
195
d7e2ebe7
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
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
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
b55f9678
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')
f91ca6bc 276 return NULL;
b55f9678
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;
9d98de83
IB
299 case 'Y': /* (Objective-C) */
300 mangled++;
301 string_append (decl, "extern(Objective-C) ");
302 break;
b55f9678
IB
303 default:
304 return NULL;
305 }
306
307 return mangled;
308}
309
f91ca6bc
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
b55f9678
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')
f91ca6bc 354 return NULL;
b55f9678
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':
f91ca6bc 387 case 'k':
b55f9678
IB
388 /* inout parameter is represented as 'Ng'.
389 vector parameter is represented as 'Nh'.
f91ca6bc 390 return paramenter is represented as 'Nk'.
b55f9678
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;
f91ca6bc
IB
399 case 'j': /* return */
400 mangled++;
401 string_append (decl, "return ");
402 continue;
d7e2ebe7
IB
403 case 'l': /* scope */
404 mangled++;
405 string_append (decl, "scope ");
406 continue;
f91ca6bc
IB
407
408 default: /* unknown attribute */
409 return NULL;
b55f9678
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')
f91ca6bc 426 return NULL;
b55f9678
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++;
9d98de83
IB
483 if (n != 0)
484 string_append (decl, ", ");
485 string_append (decl, "...");
b55f9678
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
f91ca6bc
IB
501 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
502 {
503 mangled += 2;
504 string_append (decl, "return ");
505 }
506
b55f9678
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')
f91ca6bc 534 return NULL;
b55f9678
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++;
d7e2ebe7 619 if (!dlang_call_convention_p (mangled))
9d98de83 620 {
d7e2ebe7
IB
621 mangled = dlang_type (decl, mangled);
622 string_append (decl, "*");
9d98de83
IB
623 return mangled;
624 }
d7e2ebe7
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");
b55f9678
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++;
d7e2ebe7 642 return dlang_parse_qualified (decl, mangled, dlang_type_name);
b55f9678 643 case 'D': /* delegate T */
f91ca6bc
IB
644 {
645 string mods;
646 size_t szmods;
b55f9678 647 mangled++;
f91ca6bc
IB
648
649 string_init (&mods);
650 mangled = dlang_type_modifiers (&mods, mangled);
651 szmods = string_length (&mods);
652
b55f9678
IB
653 mangled = dlang_function_type (decl, mangled);
654 string_append (decl, "delegate");
f91ca6bc
IB
655 string_appendn (decl, mods.b, szmods);
656
657 string_delete (&mods);
b55f9678 658 return mangled;
f91ca6bc 659 }
b55f9678
IB
660 case 'B': /* tuple T */
661 mangled++;
662 return dlang_parse_tuple (decl, mangled);
663
b55f9678
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;
f91ca6bc
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;
b55f9678
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 *
f91ca6bc
IB
784dlang_identifier (string *decl, const char *mangled,
785 enum dlang_symbol_kinds kind)
b55f9678 786{
f91ca6bc 787 long len;
d7e2ebe7 788 const char *endptr = dlang_number (mangled, &len);
f91ca6bc 789
d7e2ebe7 790 if (endptr == NULL || len == 0)
f91ca6bc
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)
b55f9678 797 {
f91ca6bc 798 long psize = len;
d7e2ebe7 799 const char *pend;
f91ca6bc 800 int saved = string_length (decl);
b55f9678 801
f91ca6bc
IB
802 /* Work backwards until a match is found. */
803 for (pend = endptr; endptr != NULL; pend--)
804 {
805 mangled = pend;
806
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))
d7e2ebe7
IB
819 mangled = dlang_parse_qualified (decl, mangled,
820 dlang_template_ident);
f91ca6bc 821 else if (strncmp (mangled, "_D", 2) == 0)
d7e2ebe7 822 mangled = dlang_parse_mangle (decl, mangled, dlang_function);
f91ca6bc
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)
b55f9678
IB
838 return NULL;
839
840 mangled = endptr;
841
842 /* May be a template instance. */
d7e2ebe7
IB
843 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
844 && (mangled[2] == 'T' || mangled[2] == 'U'))
845 return dlang_parse_template (decl, mangled, len);
b55f9678 846
f91ca6bc 847 switch (len)
b55f9678 848 {
f91ca6bc
IB
849 case 6:
850 if (strncmp (mangled, "__ctor", len) == 0)
851 {
852 /* Constructor symbol for a class/struct. */
853 string_append (decl, "this");
854 mangled += len;
855 return mangled;
856 }
857 else if (strncmp (mangled, "__dtor", len) == 0)
858 {
859 /* Destructor symbol for a class/struct. */
860 string_append (decl, "~this");
861 mangled += len;
862 return mangled;
863 }
864 else if (strncmp (mangled, "__initZ", len+1) == 0)
865 {
866 /* The static initialiser for a given symbol. */
d7e2ebe7
IB
867 string_prepend (decl, "initializer for ");
868 string_setlength (decl, string_length (decl) - 1);
f91ca6bc
IB
869 mangled += len;
870 return mangled;
871 }
872 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
873 {
874 /* The vtable symbol for a given class. */
875 string_prepend (decl, "vtable for ");
876 string_setlength (decl, string_length (decl) - 1);
877 mangled += len;
878 return mangled;
879 }
880 break;
881
882 case 7:
883 if (strncmp (mangled, "__ClassZ", len+1) == 0)
884 {
885 /* The classinfo symbol for a given class. */
886 string_prepend (decl, "ClassInfo for ");
887 string_setlength (decl, string_length (decl) - 1);
888 mangled += len;
889 return mangled;
890 }
891 break;
892
893 case 10:
894 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
895 {
896 /* Postblit symbol for a struct. */
897 string_append (decl, "this(this)");
898 mangled += len + 3;
899 return mangled;
900 }
901 break;
902
903 case 11:
904 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
905 {
906 /* The interface symbol for a given class. */
907 string_prepend (decl, "Interface for ");
908 string_setlength (decl, string_length (decl) - 1);
909 mangled += len;
910 return mangled;
911 }
912 break;
913
914 case 12:
915 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
916 {
917 /* The ModuleInfo symbol for a given module. */
918 string_prepend (decl, "ModuleInfo for ");
919 string_setlength (decl, string_length (decl) - 1);
920 mangled += len;
921 return mangled;
922 }
923 break;
b55f9678
IB
924 }
925
f91ca6bc
IB
926 string_appendn (decl, mangled, len);
927 mangled += len;
b55f9678 928 }
b55f9678
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. */
f211b8c0
NC
942 char value[20];
943 int pos = sizeof(value);
b55f9678 944 int width = 0;
d7e2ebe7 945 long val;
b55f9678 946
d7e2ebe7
IB
947 mangled = dlang_number (mangled, &val);
948 if (mangled == NULL)
b55f9678
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
f211b8c0 994 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
b55f9678
IB
995 }
996 string_append (decl, "'");
b55f9678
IB
997 }
998 else if (type == 'b')
999 {
1000 /* Parse boolean value. */
d7e2ebe7 1001 long val;
b55f9678 1002
d7e2ebe7
IB
1003 mangled = dlang_number (mangled, &val);
1004 if (mangled == NULL)
b55f9678
IB
1005 return NULL;
1006
1007 string_append (decl, val ? "true" : "false");
b55f9678
IB
1008 }
1009 else
1010 {
1011 /* Parse integer value. */
1012 const char *numptr = mangled;
1013 size_t num = 0;
1014
d7e2ebe7
IB
1015 if (! ISDIGIT (*mangled))
1016 return NULL;
1017
b55f9678
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{
b55f9678
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 {
d7e2ebe7 1073 string_append (decl, "-");
b55f9678
IB
1074 mangled++;
1075 }
1076
1077 if (!ISXDIGIT (*mangled))
1078 return NULL;
1079
d7e2ebe7
IB
1080 string_append (decl, "0x");
1081 string_appendn (decl, mangled, 1);
1082 string_append (decl, ".");
b55f9678
IB
1083 mangled++;
1084
1085 /* Significand. */
1086 while (ISXDIGIT (*mangled))
1087 {
d7e2ebe7 1088 string_appendn (decl, mangled, 1);
b55f9678
IB
1089 mangled++;
1090 }
1091
1092 /* Exponent. */
1093 if (*mangled != 'P')
1094 return NULL;
1095
d7e2ebe7 1096 string_append (decl, "p");
b55f9678
IB
1097 mangled++;
1098
1099 if (*mangled == 'N')
1100 {
d7e2ebe7 1101 string_append (decl, "-");
b55f9678
IB
1102 mangled++;
1103 }
1104
1105 while (ISDIGIT (*mangled))
1106 {
d7e2ebe7 1107 string_appendn (decl, mangled, 1);
b55f9678
IB
1108 mangled++;
1109 }
1110
b55f9678
IB
1111 return mangled;
1112}
1113
b55f9678
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;
b55f9678
IB
1120 long len;
1121
1122 mangled++;
d7e2ebe7
IB
1123 mangled = dlang_number (mangled, &len);
1124 if (mangled == NULL || *mangled != '_')
b55f9678
IB
1125 return NULL;
1126
1127 mangled++;
1128 string_append (decl, "\"");
1129 while (len--)
1130 {
d7e2ebe7
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)
b55f9678 1139 {
d7e2ebe7
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;
f91ca6bc 1158
d7e2ebe7
IB
1159 default:
1160 if (ISPRINT (val))
1161 string_appendn (decl, &val, 1);
1162 else
f91ca6bc 1163 {
d7e2ebe7
IB
1164 string_append (decl, "\\x");
1165 string_appendn (decl, mangled, 2);
f91ca6bc 1166 }
b55f9678 1167 }
b55f9678 1168
d7e2ebe7 1169 mangled = endptr;
b55f9678
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{
d7e2ebe7 1184 long elements;
b55f9678 1185
d7e2ebe7
IB
1186 mangled = dlang_number (mangled, &elements);
1187 if (mangled == NULL)
b55f9678
IB
1188 return NULL;
1189
b55f9678
IB
1190 string_append (decl, "[");
1191 while (elements--)
1192 {
1193 mangled = dlang_value (decl, mangled, NULL, '\0');
f211b8c0
NC
1194 if (mangled == NULL)
1195 return NULL;
1196
b55f9678
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{
d7e2ebe7 1210 long elements;
b55f9678 1211
d7e2ebe7
IB
1212 mangled = dlang_number (mangled, &elements);
1213 if (mangled == NULL)
b55f9678
IB
1214 return NULL;
1215
b55f9678
IB
1216 string_append (decl, "[");
1217 while (elements--)
1218 {
1219 mangled = dlang_value (decl, mangled, NULL, '\0');
f211b8c0
NC
1220 if (mangled == NULL)
1221 return NULL;
1222
b55f9678
IB
1223 string_append (decl, ":");
1224 mangled = dlang_value (decl, mangled, NULL, '\0');
f211b8c0
NC
1225 if (mangled == NULL)
1226 return NULL;
b55f9678
IB
1227
1228 if (elements != 0)
1229 string_append (decl, ", ");
1230 }
1231
1232 string_append (decl, "]");
1233 return mangled;
1234}
1235
1236/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1237 Return the remaining string on success or NULL on failure. */
1238static const char *
1239dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1240{
d7e2ebe7 1241 long args;
b55f9678 1242
d7e2ebe7
IB
1243 mangled = dlang_number (mangled, &args);
1244 if (mangled == NULL)
b55f9678
IB
1245 return NULL;
1246
b55f9678
IB
1247 if (name != NULL)
1248 string_append (decl, name);
1249
1250 string_append (decl, "(");
1251 while (args--)
1252 {
1253 mangled = dlang_value (decl, mangled, NULL, '\0');
f211b8c0
NC
1254 if (mangled == NULL)
1255 return NULL;
1256
b55f9678
IB
1257 if (args != 0)
1258 string_append (decl, ", ");
1259 }
1260
1261 string_append (decl, ")");
1262 return mangled;
1263}
1264
1265/* Extract the value from MANGLED and append it to DECL.
1266 Return the remaining string on success or NULL on failure. */
1267static const char *
1268dlang_value (string *decl, const char *mangled, const char *name, char type)
1269{
1270 if (mangled == NULL || *mangled == '\0')
f91ca6bc 1271 return NULL;
b55f9678
IB
1272
1273 switch (*mangled)
1274 {
1275 /* Null value. */
1276 case 'n':
1277 mangled++;
1278 string_append (decl, "null");
1279 break;
1280
1281 /* Integral values. */
1282 case 'N':
1283 mangled++;
1284 string_append (decl, "-");
1285 mangled = dlang_parse_integer (decl, mangled, type);
1286 break;
1287
1288 case 'i':
1289 mangled++;
b55f9678 1290 /* Fall through */
d7e2ebe7
IB
1291
1292 /* There really should always be an `i' before encoded numbers, but there
1293 wasn't in early versions of D2, so this case range must remain for
1294 backwards compatibility. */
b55f9678
IB
1295 case '0': case '1': case '2': case '3': case '4':
1296 case '5': case '6': case '7': case '8': case '9':
1297 mangled = dlang_parse_integer (decl, mangled, type);
1298 break;
1299
1300 /* Real value. */
1301 case 'e':
1302 mangled++;
1303 mangled = dlang_parse_real (decl, mangled);
1304 break;
1305
1306 /* Complex value. */
1307 case 'c':
1308 mangled++;
1309 mangled = dlang_parse_real (decl, mangled);
1310 string_append (decl, "+");
1311 if (mangled == NULL || *mangled != 'c')
1312 return NULL;
1313 mangled++;
1314 mangled = dlang_parse_real (decl, mangled);
1315 string_append (decl, "i");
1316 break;
1317
1318 /* String values. */
1319 case 'a': /* UTF8 */
1320 case 'w': /* UTF16 */
1321 case 'd': /* UTF32 */
1322 mangled = dlang_parse_string (decl, mangled);
1323 break;
1324
1325 /* Array values. */
1326 case 'A':
1327 mangled++;
1328 if (type == 'H')
1329 mangled = dlang_parse_assocarray (decl, mangled);
1330 else
1331 mangled = dlang_parse_arrayliteral (decl, mangled);
1332 break;
1333
1334 /* Struct values. */
1335 case 'S':
1336 mangled++;
1337 mangled = dlang_parse_structlit (decl, mangled, name);
1338 break;
1339
1340 default:
1341 return NULL;
1342 }
1343
1344 return mangled;
1345}
1346
d7e2ebe7
IB
1347/* Extract and demangle the symbol in MANGLED and append it to DECL.
1348 Returns the remaining signature on success or NULL on failure. */
1349static const char *
1350dlang_parse_mangle (string *decl, const char *mangled,
1351 enum dlang_symbol_kinds kind)
b55f9678 1352{
d7e2ebe7
IB
1353 /* A D mangled symbol is comprised of both scope and type information.
1354
1355 MangleName:
1356 _D QualifiedName Type
1357 _D QualifiedName M Type
1358 _D QualifiedName Z
1359 ^
1360 The caller should have guaranteed that the start pointer is at the
1361 above location.
1362 */
1363 mangled += 2;
b55f9678 1364
d7e2ebe7
IB
1365 mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
1366
1367 if (mangled != NULL)
b55f9678 1368 {
d7e2ebe7
IB
1369 /* Artificial symbols end with 'Z' and have no type. */
1370 if (*mangled == 'Z')
1371 mangled++;
1372 else
1373 {
1374 string mods;
1375 int saved;
b55f9678 1376
d7e2ebe7
IB
1377 /* Skip over 'this' parameter. */
1378 if (*mangled == 'M')
1379 mangled++;
b55f9678 1380
d7e2ebe7
IB
1381 /* Save the type modifiers for appending at the end if needed. */
1382 string_init (&mods);
1383 mangled = dlang_type_modifiers (&mods, mangled);
f91ca6bc 1384
d7e2ebe7
IB
1385 if (mangled && dlang_call_convention_p (mangled))
1386 {
1387 /* Skip over calling convention and attributes. */
1388 saved = string_length (decl);
1389 mangled = dlang_call_convention (decl, mangled);
1390 mangled = dlang_attributes (decl, mangled);
1391 string_setlength (decl, saved);
1392
1393 string_append (decl, "(");
1394 mangled = dlang_function_args (decl, mangled);
1395 string_append (decl, ")");
1396
1397 /* Add any const/immutable/shared modifier. */
1398 string_appendn (decl, mods.b, string_length (&mods));
1399 }
f91ca6bc 1400
d7e2ebe7
IB
1401 /* Consume the decl type of symbol. */
1402 saved = string_length (decl);
1403 mangled = dlang_type (decl, mangled);
1404 string_setlength (decl, saved);
1405
1406 string_delete (&mods);
1407 }
f91ca6bc
IB
1408 }
1409
d7e2ebe7
IB
1410 /* Check that the entire symbol was successfully demangled. */
1411 if (kind == dlang_top_level)
f91ca6bc 1412 {
d7e2ebe7
IB
1413 if (mangled == NULL || *mangled != '\0')
1414 return NULL;
b55f9678 1415 }
d7e2ebe7
IB
1416
1417 return mangled;
b55f9678
IB
1418}
1419
d7e2ebe7 1420/* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
b55f9678
IB
1421 Returns the remaining signature on success or NULL on failure. */
1422static const char *
d7e2ebe7
IB
1423dlang_parse_qualified (string *decl, const char *mangled,
1424 enum dlang_symbol_kinds kind)
b55f9678 1425{
d7e2ebe7
IB
1426 /* Qualified names are identifiers separated by their encoded length.
1427 Nested functions also encode their argument types without specifying
1428 what they return.
1429
1430 QualifiedName:
1431 SymbolName
1432 SymbolName QualifiedName
1433 SymbolName TypeFunctionNoReturn QualifiedName
1434 SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
1435 ^
1436 The start pointer should be at the above location.
1437 */
b55f9678
IB
1438 size_t n = 0;
1439 do
1440 {
1441 if (n++)
1442 string_append (decl, ".");
1443
d7e2ebe7
IB
1444 /* Skip over anonymous symbols. */
1445 while (*mangled == '0')
1446 mangled++;
1447
f91ca6bc 1448 mangled = dlang_identifier (decl, mangled, kind);
b55f9678 1449
d7e2ebe7
IB
1450 /* Consume the encoded arguments. However if this is not followed by the
1451 next encoded length, then this is not a continuation of a qualified
1452 name, in which case we backtrack and return the current unconsumed
1453 position of the mangled decl. */
1454 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
b55f9678 1455 {
d7e2ebe7
IB
1456 const char *start = mangled;
1457 int saved = string_length (decl);
b55f9678 1458
d7e2ebe7 1459 /* Skip over 'this' parameter and type modifiers. */
b55f9678 1460 if (*mangled == 'M')
f91ca6bc 1461 {
d7e2ebe7
IB
1462 mangled++;
1463 mangled = dlang_type_modifiers (decl, mangled);
1464 string_setlength (decl, saved);
f91ca6bc
IB
1465 }
1466
d7e2ebe7 1467 /* The rule we expect to match in the mangled string is:
b55f9678 1468
d7e2ebe7
IB
1469 TypeFunctionNoReturn:
1470 CallConvention FuncAttrs Arguments ArgClose
1471
1472 The calling convention and function attributes are not included
1473 in the demangled string. */
b55f9678
IB
1474 mangled = dlang_call_convention (decl, mangled);
1475 mangled = dlang_attributes (decl, mangled);
1476 string_setlength (decl, saved);
1477
1478 string_append (decl, "(");
1479 mangled = dlang_function_args (decl, mangled);
1480 string_append (decl, ")");
1481
d7e2ebe7 1482 if (mangled == NULL || !ISDIGIT (*mangled))
b55f9678 1483 {
d7e2ebe7 1484 /* Did not match the rule we were looking for. */
f91ca6bc 1485 mangled = start;
d7e2ebe7 1486 string_setlength (decl, saved);
b55f9678
IB
1487 }
1488 }
1489 }
1490 while (mangled && ISDIGIT (*mangled));
1491
1492 return mangled;
1493}
1494
1495/* Demangle the tuple from MANGLED and append it to DECL.
1496 Return the remaining string on success or NULL on failure. */
1497static const char *
1498dlang_parse_tuple (string *decl, const char *mangled)
1499{
d7e2ebe7 1500 long elements;
b55f9678 1501
d7e2ebe7
IB
1502 mangled = dlang_number (mangled, &elements);
1503 if (mangled == NULL)
b55f9678
IB
1504 return NULL;
1505
b55f9678
IB
1506 string_append (decl, "Tuple!(");
1507
1508 while (elements--)
1509 {
1510 mangled = dlang_type (decl, mangled);
f211b8c0
NC
1511 if (mangled == NULL)
1512 return NULL;
1513
b55f9678
IB
1514 if (elements != 0)
1515 string_append (decl, ", ");
1516 }
1517
1518 string_append (decl, ")");
1519 return mangled;
1520}
1521
1522/* Demangle the argument list from MANGLED and append it to DECL.
1523 Return the remaining string on success or NULL on failure. */
1524static const char *
1525dlang_template_args (string *decl, const char *mangled)
1526{
1527 size_t n = 0;
1528
1529 while (mangled && *mangled != '\0')
1530 {
1531 switch (*mangled)
1532 {
1533 case 'Z': /* End of parameter list. */
1534 mangled++;
1535 return mangled;
1536 }
1537
1538 if (n++)
1539 string_append (decl, ", ");
1540
f91ca6bc
IB
1541 /* Skip over specialised template prefix. */
1542 if (*mangled == 'H')
1543 mangled++;
1544
b55f9678
IB
1545 switch (*mangled)
1546 {
1547 case 'S': /* Symbol parameter. */
1548 mangled++;
d7e2ebe7 1549 mangled = dlang_identifier (decl, mangled, dlang_template_param);
b55f9678
IB
1550 break;
1551 case 'T': /* Type parameter. */
1552 mangled++;
1553 mangled = dlang_type (decl, mangled);
1554 break;
1555 case 'V': /* Value parameter. */
1556 {
1557 string name;
1558 char type;
1559
1560 /* Peek at the type. */
1561 mangled++;
1562 type = *mangled;
1563
1564 /* In the few instances where the type is actually desired in
1565 the output, it should precede the value from dlang_value. */
1566 string_init (&name);
1567 mangled = dlang_type (&name, mangled);
1568 string_need (&name, 1);
1569 *(name.p) = '\0';
1570
1571 mangled = dlang_value (decl, mangled, name.b, type);
1572 string_delete (&name);
1573 break;
1574 }
1575
1576 default:
1577 return NULL;
1578 }
1579 }
1580
1581 return mangled;
1582}
1583
1584/* Extract and demangle the template symbol in MANGLED, expected to
1585 be made up of LEN characters, and append it to DECL.
1586 Returns the remaining signature on success or NULL on failure. */
1587static const char *
1588dlang_parse_template (string *decl, const char *mangled, long len)
1589{
1590 const char *start = mangled;
1591
1592 /* Template instance names have the types and values of its parameters
1593 encoded into it.
1594
1595 TemplateInstanceName:
1596 Number __T LName TemplateArgs Z
d7e2ebe7 1597 Number __U LName TemplateArgs Z
b55f9678
IB
1598 ^
1599 The start pointer should be at the above location, and LEN should be
1600 the value of the decoded number.
1601 */
d7e2ebe7
IB
1602
1603 /* Template symbol. */
1604 if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
b55f9678
IB
1605 return NULL;
1606
1607 mangled += 3;
1608
1609 /* Template identifier. */
f91ca6bc 1610 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
b55f9678
IB
1611
1612 /* Template arguments. */
1613 string_append (decl, "!(");
1614 mangled = dlang_template_args (decl, mangled);
1615 string_append (decl, ")");
1616
1617 /* Check for template name length mismatch. */
1618 if (mangled && (mangled - start) != len)
1619 return NULL;
1620
1621 return mangled;
1622}
1623
1624/* Extract and demangle the symbol in MANGLED. Returns the demangled
1625 signature on success or NULL on failure. */
1626
1627char *
1628dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1629{
1630 string decl;
1631 char *demangled = NULL;
1632
1633 if (mangled == NULL || *mangled == '\0')
1634 return NULL;
1635
1636 if (strncmp (mangled, "_D", 2) != 0)
1637 return NULL;
1638
1639 string_init (&decl);
1640
1641 if (strcmp (mangled, "_Dmain") == 0)
1642 {
1643 string_append (&decl, "D main");
1644 }
1645 else
1646 {
d7e2ebe7 1647 if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
b55f9678
IB
1648 string_delete (&decl);
1649 }
1650
1651 if (string_length (&decl) > 0)
1652 {
1653 string_need (&decl, 1);
1654 *(decl.p) = '\0';
1655 demangled = decl.b;
1656 }
1657
1658 return demangled;
1659}
1660
This page took 0.309533 seconds and 4 git commands to generate.