Update libiberty demangler to support Rust v0 name mangling
[valgrind.git] / coregrind / m_demangle / d-demangle.c
blob1f2fbbe43fc7eac303c00fdfccf06ffd3ae56f8c
1 /* Demangler for the D programming language
2 Copyright (C) 2014-2021 Free Software Foundation, Inc.
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 In addition to the permissions in the GNU Library General Public
12 License, the Free Software Foundation gives you unlimited permission
13 to link the compiled version of this file into combinations with other
14 programs, and to distribute those combinations without any restriction
15 coming from the use of this file. (The Library Public License
16 restrictions do apply in other respects; for example, they cover
17 modification of the file, and distribution when not linked into a
18 combined executable.)
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Library General Public License for more details.
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>. */
29 /* This file exports one function; dlang_demangle. */
31 #if 0 /* in valgrind */
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 #ifdef HAVE_LIMITS_H
36 #include <limits.h>
37 #endif
38 #endif /* ! in valgrind */
40 #if 0 /* in valgrind */
41 #include "safe-ctype.h"
42 #endif /* ! in valgrind */
44 #if 0 /* in valgrind */
45 #include <sys/types.h>
46 #include <string.h>
47 #include <stdio.h>
48 #endif /* ! in valgrind */
50 #if 0 /* in valgrind */
51 #ifdef HAVE_STDLIB_H
52 #include <stdlib.h>
53 #endif
54 #endif /* ! in valgrind */
56 #if 0 /* in valgrind */
57 #include <demangle.h>
58 #include "libiberty.h"
59 #endif /* ! in valgrind */
61 #include "vg_libciface.h"
63 #include "ansidecl.h"
64 #include "demangle.h"
65 #include "safe-ctype.h"
67 #ifndef ULONG_MAX
68 #define ULONG_MAX (~0UL)
69 #endif
70 #ifndef UINT_MAX
71 #define UINT_MAX (~0U)
72 #endif
74 /* A mini string-handling package */
76 typedef struct string /* Beware: these aren't required to be */
77 { /* '\0' terminated. */
78 char *b; /* pointer to start of string */
79 char *p; /* pointer after last character */
80 char *e; /* pointer after end of allocated space */
81 } string;
83 static void
84 string_need (string *s, size_t n)
86 size_t tem;
88 if (s->b == NULL)
90 if (n < 32)
92 n = 32;
94 s->p = s->b = XNEWVEC (char, n);
95 s->e = s->b + n;
97 else if ((size_t) (s->e - s->p) < n)
99 tem = s->p - s->b;
100 n += tem;
101 n *= 2;
102 s->b = XRESIZEVEC (char, s->b, n);
103 s->p = s->b + tem;
104 s->e = s->b + n;
108 static void
109 string_delete (string *s)
111 if (s->b != NULL)
113 XDELETEVEC (s->b);
114 s->b = s->e = s->p = NULL;
118 static void
119 string_init (string *s)
121 s->b = s->p = s->e = NULL;
124 static int
125 string_length (string *s)
127 if (s->p == s->b)
129 return 0;
131 return s->p - s->b;
134 static void
135 string_setlength (string *s, int n)
137 if (n - string_length (s) < 0)
139 s->p = s->b + n;
143 static void
144 string_append (string *p, const char *s)
146 size_t n = strlen (s);
147 string_need (p, n);
148 memcpy (p->p, s, n);
149 p->p += n;
152 static void
153 string_appendn (string *p, const char *s, size_t n)
155 if (n != 0)
157 string_need (p, n);
158 memcpy (p->p, s, n);
159 p->p += n;
163 static void
164 string_prependn (string *p, const char *s, size_t n)
166 char *q;
168 if (n != 0)
170 string_need (p, n);
171 for (q = p->p - 1; q >= p->b; q--)
173 q[n] = q[0];
175 memcpy (p->b, s, n);
176 p->p += n;
180 static void
181 string_prepend (string *p, const char *s)
183 if (s != NULL && *s != '\0')
185 string_prependn (p, s, strlen (s));
189 /* Demangle information structure we pass around. */
190 struct dlang_info
192 /* The string we are demangling. */
193 const char *s;
194 /* The index of the last back reference. */
195 int last_backref;
198 /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
199 #define TEMPLATE_LENGTH_UNKNOWN (-1UL)
201 /* Prototypes for forward referenced functions */
202 static const char *dlang_function_type (string *, const char *,
203 struct dlang_info *);
205 static const char *dlang_function_args (string *, const char *,
206 struct dlang_info *);
208 static const char *dlang_type (string *, const char *, struct dlang_info *);
210 static const char *dlang_value (string *, const char *, const char *, char);
212 static const char *dlang_parse_qualified (string *, const char *,
213 struct dlang_info *, int);
215 static const char *dlang_parse_mangle (string *, const char *,
216 struct dlang_info *);
218 static const char *dlang_parse_tuple (string *, const char *,
219 struct dlang_info *);
221 static const char *dlang_parse_template (string *, const char *,
222 struct dlang_info *, unsigned long);
224 static const char *dlang_lname (string *, const char *, unsigned long);
227 /* Extract the number from MANGLED, and assign the result to RET.
228 Return the remaining string on success or NULL on failure.
229 A result larger than UINT_MAX is considered a failure. */
230 static const char *
231 dlang_number (const char *mangled, unsigned long *ret)
233 /* Return NULL if trying to extract something that isn't a digit. */
234 if (mangled == NULL || !ISDIGIT (*mangled))
235 return NULL;
237 unsigned long val = 0;
239 while (ISDIGIT (*mangled))
241 unsigned long digit = mangled[0] - '0';
243 /* Check for overflow. */
244 if (val > (UINT_MAX - digit) / 10)
245 return NULL;
247 val = val * 10 + digit;
248 mangled++;
251 if (*mangled == '\0')
252 return NULL;
254 *ret = val;
255 return mangled;
258 /* Extract the hex-digit from MANGLED, and assign the result to RET.
259 Return the remaining string on success or NULL on failure. */
260 static const char *
261 dlang_hexdigit (const char *mangled, char *ret)
263 char c;
265 /* Return NULL if trying to extract something that isn't a hexdigit. */
266 if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
267 return NULL;
269 c = mangled[0];
270 if (!ISDIGIT (c))
271 (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10);
272 else
273 (*ret) = (c - '0');
275 c = mangled[1];
276 if (!ISDIGIT (c))
277 (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
278 else
279 (*ret) = (*ret << 4) | (c - '0');
281 mangled += 2;
283 return mangled;
286 /* Extract the function calling convention from MANGLED and
287 return 1 on success or 0 on failure. */
288 static int
289 dlang_call_convention_p (const char *mangled)
291 switch (*mangled)
293 case 'F': case 'U': case 'V':
294 case 'W': case 'R': case 'Y':
295 return 1;
297 default:
298 return 0;
302 /* Extract the back reference position from MANGLED, and assign the result
303 to RET. Return the remaining string on success or NULL on failure.
304 A result <= 0 is a failure. */
305 static const char *
306 dlang_decode_backref (const char *mangled, long *ret)
308 /* Return NULL if trying to extract something that isn't a digit. */
309 if (mangled == NULL || !ISALPHA (*mangled))
310 return NULL;
312 /* Any identifier or non-basic type that has been emitted to the mangled
313 symbol before will not be emitted again, but is referenced by a special
314 sequence encoding the relative position of the original occurrence in the
315 mangled symbol name.
317 Numbers in back references are encoded with base 26 by upper case letters
318 A-Z for higher digits but lower case letters a-z for the last digit.
320 NumberBackRef:
321 [a-z]
322 [A-Z] NumberBackRef
325 unsigned long val = 0;
327 while (ISALPHA (*mangled))
329 /* Check for overflow. */
330 if (val > (ULONG_MAX - 25) / 26)
331 break;
333 val *= 26;
335 if (mangled[0] >= 'a' && mangled[0] <= 'z')
337 val += mangled[0] - 'a';
338 if ((long) val <= 0)
339 break;
340 *ret = val;
341 return mangled + 1;
344 val += mangled[0] - 'A';
345 mangled++;
348 return NULL;
351 /* Extract the symbol pointed at by the back reference and assign the result
352 to RET. Return the remaining string on success or NULL on failure. */
353 static const char *
354 dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
356 (*ret) = NULL;
358 if (mangled == NULL || *mangled != 'Q')
359 return NULL;
361 /* Position of 'Q'. */
362 const char *qpos = mangled;
363 long refpos;
364 mangled++;
366 mangled = dlang_decode_backref (mangled, &refpos);
367 if (mangled == NULL)
368 return NULL;
370 if (refpos > qpos - info->s)
371 return NULL;
373 /* Set the position of the back reference. */
374 (*ret) = qpos - refpos;
376 return mangled;
379 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
380 Return the remaining string on success or NULL on failure. */
381 static const char *
382 dlang_symbol_backref (string *decl, const char *mangled,
383 struct dlang_info *info)
385 /* An identifier back reference always points to a digit 0 to 9.
387 IdentifierBackRef:
388 Q NumberBackRef
391 const char *backref;
392 unsigned long len;
394 /* Get position of the back reference. */
395 mangled = dlang_backref (mangled, &backref, info);
397 /* Must point to a simple identifier. */
398 backref = dlang_number (backref, &len);
399 if (backref == NULL)
400 return NULL;
402 backref = dlang_lname (decl, backref, len);
403 if (backref == NULL)
404 return NULL;
406 return mangled;
409 /* Demangle a back referenced type from MANGLED and append it to DECL.
410 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
411 Return the remaining string on success or NULL on failure. */
412 static const char *
413 dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
414 int is_function)
416 /* A type back reference always points to a letter.
418 TypeBackRef:
419 Q NumberBackRef
422 const char *backref;
424 /* If we appear to be moving backwards through the mangle string, then
425 bail as this may be a recursive back reference. */
426 if (mangled - info->s >= info->last_backref)
427 return NULL;
429 int save_refpos = info->last_backref;
430 info->last_backref = mangled - info->s;
432 /* Get position of the back reference. */
433 mangled = dlang_backref (mangled, &backref, info);
435 /* Must point to a type. */
436 if (is_function)
437 backref = dlang_function_type (decl, backref, info);
438 else
439 backref = dlang_type (decl, backref, info);
441 info->last_backref = save_refpos;
443 if (backref == NULL)
444 return NULL;
446 return mangled;
449 /* Extract the beginning of a symbol name from MANGLED and
450 return 1 on success or 0 on failure. */
451 static int
452 dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
454 long ret;
455 const char *qref = mangled;
457 if (ISDIGIT (*mangled))
458 return 1;
460 if (mangled[0] == '_' && mangled[1] == '_'
461 && (mangled[2] == 'T' || mangled[2] == 'U'))
462 return 1;
464 if (*mangled != 'Q')
465 return 0;
467 mangled = dlang_decode_backref (mangled + 1, &ret);
468 if (mangled == NULL || ret > qref - info->s)
469 return 0;
471 return ISDIGIT (qref[-ret]);
474 /* Demangle the calling convention from MANGLED and append it to DECL.
475 Return the remaining string on success or NULL on failure. */
476 static const char *
477 dlang_call_convention (string *decl, const char *mangled)
479 if (mangled == NULL || *mangled == '\0')
480 return NULL;
482 switch (*mangled)
484 case 'F': /* (D) */
485 mangled++;
486 break;
487 case 'U': /* (C) */
488 mangled++;
489 string_append (decl, "extern(C) ");
490 break;
491 case 'W': /* (Windows) */
492 mangled++;
493 string_append (decl, "extern(Windows) ");
494 break;
495 case 'V': /* (Pascal) */
496 mangled++;
497 string_append (decl, "extern(Pascal) ");
498 break;
499 case 'R': /* (C++) */
500 mangled++;
501 string_append (decl, "extern(C++) ");
502 break;
503 case 'Y': /* (Objective-C) */
504 mangled++;
505 string_append (decl, "extern(Objective-C) ");
506 break;
507 default:
508 return NULL;
511 return mangled;
514 /* Extract the type modifiers from MANGLED and append them to DECL.
515 Returns the remaining signature on success or NULL on failure. */
516 static const char *
517 dlang_type_modifiers (string *decl, const char *mangled)
519 if (mangled == NULL || *mangled == '\0')
520 return NULL;
522 switch (*mangled)
524 case 'x': /* const */
525 mangled++;
526 string_append (decl, " const");
527 return mangled;
528 case 'y': /* immutable */
529 mangled++;
530 string_append (decl, " immutable");
531 return mangled;
532 case 'O': /* shared */
533 mangled++;
534 string_append (decl, " shared");
535 return dlang_type_modifiers (decl, mangled);
536 case 'N':
537 mangled++;
538 if (*mangled == 'g') /* wild */
540 mangled++;
541 string_append (decl, " inout");
542 return dlang_type_modifiers (decl, mangled);
544 else
545 return NULL;
547 default:
548 return mangled;
552 /* Demangle the D function attributes from MANGLED and append it to DECL.
553 Return the remaining string on success or NULL on failure. */
554 static const char *
555 dlang_attributes (string *decl, const char *mangled)
557 if (mangled == NULL || *mangled == '\0')
558 return NULL;
560 while (*mangled == 'N')
562 mangled++;
563 switch (*mangled)
565 case 'a': /* pure */
566 mangled++;
567 string_append (decl, "pure ");
568 continue;
569 case 'b': /* nothrow */
570 mangled++;
571 string_append (decl, "nothrow ");
572 continue;
573 case 'c': /* ref */
574 mangled++;
575 string_append (decl, "ref ");
576 continue;
577 case 'd': /* @property */
578 mangled++;
579 string_append (decl, "@property ");
580 continue;
581 case 'e': /* @trusted */
582 mangled++;
583 string_append (decl, "@trusted ");
584 continue;
585 case 'f': /* @safe */
586 mangled++;
587 string_append (decl, "@safe ");
588 continue;
589 case 'g':
590 case 'h':
591 case 'k':
592 /* inout parameter is represented as 'Ng'.
593 vector parameter is represented as 'Nh'.
594 return paramenter is represented as 'Nk'.
595 If we see this, then we know we're really in the
596 parameter list. Rewind and break. */
597 mangled--;
598 break;
599 case 'i': /* @nogc */
600 mangled++;
601 string_append (decl, "@nogc ");
602 continue;
603 case 'j': /* return */
604 mangled++;
605 string_append (decl, "return ");
606 continue;
607 case 'l': /* scope */
608 mangled++;
609 string_append (decl, "scope ");
610 continue;
611 case 'm': /* @live */
612 mangled++;
613 string_append (decl, "@live ");
614 continue;
616 default: /* unknown attribute */
617 return NULL;
619 break;
622 return mangled;
625 /* Demangle the function type from MANGLED without the return type.
626 The arguments are appended to ARGS, the calling convention is appended
627 to CALL and attributes are appended to ATTR. Any of these can be NULL
628 to throw the information away. Return the remaining string on success
629 or NULL on failure. */
630 static const char *
631 dlang_function_type_noreturn (string *args, string *call, string *attr,
632 const char *mangled, struct dlang_info *info)
634 string dump;
635 string_init (&dump);
637 /* Skip over calling convention and attributes. */
638 mangled = dlang_call_convention (call ? call : &dump, mangled);
639 mangled = dlang_attributes (attr ? attr : &dump, mangled);
641 if (args)
642 string_append (args, "(");
644 mangled = dlang_function_args (args ? args : &dump, mangled, info);
645 if (args)
646 string_append (args, ")");
648 string_delete (&dump);
649 return mangled;
652 /* Demangle the function type from MANGLED and append it to DECL.
653 Return the remaining string on success or NULL on failure. */
654 static const char *
655 dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
657 string attr, args, type;
659 if (mangled == NULL || *mangled == '\0')
660 return NULL;
662 /* The order of the mangled string is:
663 CallConvention FuncAttrs Arguments ArgClose Type
665 The demangled string is re-ordered as:
666 CallConvention Type Arguments FuncAttrs
668 string_init (&attr);
669 string_init (&args);
670 string_init (&type);
672 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
674 /* Function return type. */
675 mangled = dlang_type (&type, mangled, info);
677 /* Append to decl in order. */
678 string_appendn (decl, type.b, string_length (&type));
679 string_appendn (decl, args.b, string_length (&args));
680 string_append (decl, " ");
681 string_appendn (decl, attr.b, string_length (&attr));
683 string_delete (&attr);
684 string_delete (&args);
685 string_delete (&type);
686 return mangled;
689 /* Demangle the argument list from MANGLED and append it to DECL.
690 Return the remaining string on success or NULL on failure. */
691 static const char *
692 dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
694 size_t n = 0;
696 while (mangled && *mangled != '\0')
698 switch (*mangled)
700 case 'X': /* (variadic T t...) style. */
701 mangled++;
702 string_append (decl, "...");
703 return mangled;
704 case 'Y': /* (variadic T t, ...) style. */
705 mangled++;
706 if (n != 0)
707 string_append (decl, ", ");
708 string_append (decl, "...");
709 return mangled;
710 case 'Z': /* Normal function. */
711 mangled++;
712 return mangled;
715 if (n++)
716 string_append (decl, ", ");
718 if (*mangled == 'M') /* scope(T) */
720 mangled++;
721 string_append (decl, "scope ");
724 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
726 mangled += 2;
727 string_append (decl, "return ");
730 switch (*mangled)
732 case 'I': /* in(T) */
733 mangled++;
734 string_append (decl, "in ");
735 if (*mangled == 'K') /* in ref(T) */
737 mangled++;
738 string_append (decl, "ref ");
740 break;
741 case 'J': /* out(T) */
742 mangled++;
743 string_append (decl, "out ");
744 break;
745 case 'K': /* ref(T) */
746 mangled++;
747 string_append (decl, "ref ");
748 break;
749 case 'L': /* lazy(T) */
750 mangled++;
751 string_append (decl, "lazy ");
752 break;
754 mangled = dlang_type (decl, mangled, info);
757 return mangled;
760 /* Demangle the type from MANGLED and append it to DECL.
761 Return the remaining string on success or NULL on failure. */
762 static const char *
763 dlang_type (string *decl, const char *mangled, struct dlang_info *info)
765 if (mangled == NULL || *mangled == '\0')
766 return NULL;
768 switch (*mangled)
770 case 'O': /* shared(T) */
771 mangled++;
772 string_append (decl, "shared(");
773 mangled = dlang_type (decl, mangled, info);
774 string_append (decl, ")");
775 return mangled;
776 case 'x': /* const(T) */
777 mangled++;
778 string_append (decl, "const(");
779 mangled = dlang_type (decl, mangled, info);
780 string_append (decl, ")");
781 return mangled;
782 case 'y': /* immutable(T) */
783 mangled++;
784 string_append (decl, "immutable(");
785 mangled = dlang_type (decl, mangled, info);
786 string_append (decl, ")");
787 return mangled;
788 case 'N':
789 mangled++;
790 if (*mangled == 'g') /* wild(T) */
792 mangled++;
793 string_append (decl, "inout(");
794 mangled = dlang_type (decl, mangled, info);
795 string_append (decl, ")");
796 return mangled;
798 else if (*mangled == 'h') /* vector(T) */
800 mangled++;
801 string_append (decl, "__vector(");
802 mangled = dlang_type (decl, mangled, info);
803 string_append (decl, ")");
804 return mangled;
806 else
807 return NULL;
808 case 'A': /* dynamic array (T[]) */
809 mangled++;
810 mangled = dlang_type (decl, mangled, info);
811 string_append (decl, "[]");
812 return mangled;
813 case 'G': /* static array (T[N]) */
815 const char *numptr;
816 size_t num = 0;
817 mangled++;
819 numptr = mangled;
820 while (ISDIGIT (*mangled))
822 num++;
823 mangled++;
825 mangled = dlang_type (decl, mangled, info);
826 string_append (decl, "[");
827 string_appendn (decl, numptr, num);
828 string_append (decl, "]");
829 return mangled;
831 case 'H': /* associative array (T[T]) */
833 string type;
834 size_t sztype;
835 mangled++;
837 string_init (&type);
838 mangled = dlang_type (&type, mangled, info);
839 sztype = string_length (&type);
841 mangled = dlang_type (decl, mangled, info);
842 string_append (decl, "[");
843 string_appendn (decl, type.b, sztype);
844 string_append (decl, "]");
846 string_delete (&type);
847 return mangled;
849 case 'P': /* pointer (T*) */
850 mangled++;
851 if (!dlang_call_convention_p (mangled))
853 mangled = dlang_type (decl, mangled, info);
854 string_append (decl, "*");
855 return mangled;
857 /* Fall through */
858 case 'F': /* function T (D) */
859 case 'U': /* function T (C) */
860 case 'W': /* function T (Windows) */
861 case 'V': /* function T (Pascal) */
862 case 'R': /* function T (C++) */
863 case 'Y': /* function T (Objective-C) */
864 /* Function pointer types don't include the trailing asterisk. */
865 mangled = dlang_function_type (decl, mangled, info);
866 string_append (decl, "function");
867 return mangled;
868 case 'C': /* class T */
869 case 'S': /* struct T */
870 case 'E': /* enum T */
871 case 'T': /* typedef T */
872 mangled++;
873 return dlang_parse_qualified (decl, mangled, info, 0);
874 case 'D': /* delegate T */
876 string mods;
877 size_t szmods;
878 mangled++;
880 string_init (&mods);
881 mangled = dlang_type_modifiers (&mods, mangled);
882 szmods = string_length (&mods);
884 /* Back referenced function type. */
885 if (*mangled == 'Q')
886 mangled = dlang_type_backref (decl, mangled, info, 1);
887 else
888 mangled = dlang_function_type (decl, mangled, info);
890 string_append (decl, "delegate");
891 string_appendn (decl, mods.b, szmods);
893 string_delete (&mods);
894 return mangled;
896 case 'B': /* tuple T */
897 mangled++;
898 return dlang_parse_tuple (decl, mangled, info);
900 /* Basic types */
901 case 'n':
902 mangled++;
903 string_append (decl, "none");
904 return mangled;
905 case 'v':
906 mangled++;
907 string_append (decl, "void");
908 return mangled;
909 case 'g':
910 mangled++;
911 string_append (decl, "byte");
912 return mangled;
913 case 'h':
914 mangled++;
915 string_append (decl, "ubyte");
916 return mangled;
917 case 's':
918 mangled++;
919 string_append (decl, "short");
920 return mangled;
921 case 't':
922 mangled++;
923 string_append (decl, "ushort");
924 return mangled;
925 case 'i':
926 mangled++;
927 string_append (decl, "int");
928 return mangled;
929 case 'k':
930 mangled++;
931 string_append (decl, "uint");
932 return mangled;
933 case 'l':
934 mangled++;
935 string_append (decl, "long");
936 return mangled;
937 case 'm':
938 mangled++;
939 string_append (decl, "ulong");
940 return mangled;
941 case 'f':
942 mangled++;
943 string_append (decl, "float");
944 return mangled;
945 case 'd':
946 mangled++;
947 string_append (decl, "double");
948 return mangled;
949 case 'e':
950 mangled++;
951 string_append (decl, "real");
952 return mangled;
954 /* Imaginary and Complex types */
955 case 'o':
956 mangled++;
957 string_append (decl, "ifloat");
958 return mangled;
959 case 'p':
960 mangled++;
961 string_append (decl, "idouble");
962 return mangled;
963 case 'j':
964 mangled++;
965 string_append (decl, "ireal");
966 return mangled;
967 case 'q':
968 mangled++;
969 string_append (decl, "cfloat");
970 return mangled;
971 case 'r':
972 mangled++;
973 string_append (decl, "cdouble");
974 return mangled;
975 case 'c':
976 mangled++;
977 string_append (decl, "creal");
978 return mangled;
980 /* Other types */
981 case 'b':
982 mangled++;
983 string_append (decl, "bool");
984 return mangled;
985 case 'a':
986 mangled++;
987 string_append (decl, "char");
988 return mangled;
989 case 'u':
990 mangled++;
991 string_append (decl, "wchar");
992 return mangled;
993 case 'w':
994 mangled++;
995 string_append (decl, "dchar");
996 return mangled;
997 case 'z':
998 mangled++;
999 switch (*mangled)
1001 case 'i':
1002 mangled++;
1003 string_append (decl, "cent");
1004 return mangled;
1005 case 'k':
1006 mangled++;
1007 string_append (decl, "ucent");
1008 return mangled;
1010 return NULL;
1012 /* Back referenced type. */
1013 case 'Q':
1014 return dlang_type_backref (decl, mangled, info, 0);
1016 default: /* unhandled */
1017 return NULL;
1021 /* Extract the identifier from MANGLED and append it to DECL.
1022 Return the remaining string on success or NULL on failure. */
1023 static const char *
1024 dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
1026 unsigned long len;
1028 if (mangled == NULL || *mangled == '\0')
1029 return NULL;
1031 if (*mangled == 'Q')
1032 return dlang_symbol_backref (decl, mangled, info);
1034 /* May be a template instance without a length prefix. */
1035 if (mangled[0] == '_' && mangled[1] == '_'
1036 && (mangled[2] == 'T' || mangled[2] == 'U'))
1037 return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
1039 const char *endptr = dlang_number (mangled, &len);
1041 if (endptr == NULL || len == 0)
1042 return NULL;
1044 if (strlen (endptr) < len)
1045 return NULL;
1047 mangled = endptr;
1049 /* May be a template instance with a length prefix. */
1050 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1051 && (mangled[2] == 'T' || mangled[2] == 'U'))
1052 return dlang_parse_template (decl, mangled, info, len);
1054 return dlang_lname (decl, mangled, len);
1057 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1058 with special treatment for some magic compiler generted symbols.
1059 Return the remaining string on success or NULL on failure. */
1060 static const char *
1061 dlang_lname (string *decl, const char *mangled, unsigned long len)
1063 switch (len)
1065 case 6:
1066 if (strncmp (mangled, "__ctor", len) == 0)
1068 /* Constructor symbol for a class/struct. */
1069 string_append (decl, "this");
1070 mangled += len;
1071 return mangled;
1073 else if (strncmp (mangled, "__dtor", len) == 0)
1075 /* Destructor symbol for a class/struct. */
1076 string_append (decl, "~this");
1077 mangled += len;
1078 return mangled;
1080 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1082 /* The static initialiser for a given symbol. */
1083 string_prepend (decl, "initializer for ");
1084 string_setlength (decl, string_length (decl) - 1);
1085 mangled += len;
1086 return mangled;
1088 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1090 /* The vtable symbol for a given class. */
1091 string_prepend (decl, "vtable for ");
1092 string_setlength (decl, string_length (decl) - 1);
1093 mangled += len;
1094 return mangled;
1096 break;
1098 case 7:
1099 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1101 /* The classinfo symbol for a given class. */
1102 string_prepend (decl, "ClassInfo for ");
1103 string_setlength (decl, string_length (decl) - 1);
1104 mangled += len;
1105 return mangled;
1107 break;
1109 case 10:
1110 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1112 /* Postblit symbol for a struct. */
1113 string_append (decl, "this(this)");
1114 mangled += len + 3;
1115 return mangled;
1117 break;
1119 case 11:
1120 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1122 /* The interface symbol for a given class. */
1123 string_prepend (decl, "Interface for ");
1124 string_setlength (decl, string_length (decl) - 1);
1125 mangled += len;
1126 return mangled;
1128 break;
1130 case 12:
1131 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1133 /* The ModuleInfo symbol for a given module. */
1134 string_prepend (decl, "ModuleInfo for ");
1135 string_setlength (decl, string_length (decl) - 1);
1136 mangled += len;
1137 return mangled;
1139 break;
1142 string_appendn (decl, mangled, len);
1143 mangled += len;
1145 return mangled;
1148 /* Extract the integer value from MANGLED and append it to DECL,
1149 where TYPE is the type it should be represented as.
1150 Return the remaining string on success or NULL on failure. */
1151 static const char *
1152 dlang_parse_integer (string *decl, const char *mangled, char type)
1154 if (type == 'a' || type == 'u' || type == 'w')
1156 /* Parse character value. */
1157 char value[20];
1158 int pos = sizeof(value);
1159 int width = 0;
1160 unsigned long val;
1162 mangled = dlang_number (mangled, &val);
1163 if (mangled == NULL)
1164 return NULL;
1166 string_append (decl, "'");
1168 if (type == 'a' && val >= 0x20 && val < 0x7F)
1170 /* Represent as a character literal. */
1171 char c = (char) val;
1172 string_appendn (decl, &c, 1);
1174 else
1176 /* Represent as a hexadecimal value. */
1177 switch (type)
1179 case 'a': /* char */
1180 string_append (decl, "\\x");
1181 width = 2;
1182 break;
1183 case 'u': /* wchar */
1184 string_append (decl, "\\u");
1185 width = 4;
1186 break;
1187 case 'w': /* dchar */
1188 string_append (decl, "\\U");
1189 width = 8;
1190 break;
1193 while (val > 0)
1195 int digit = val % 16;
1197 if (digit < 10)
1198 value[--pos] = (char)(digit + '0');
1199 else
1200 value[--pos] = (char)((digit - 10) + 'a');
1202 val /= 16;
1203 width--;
1206 for (; width > 0; width--)
1207 value[--pos] = '0';
1209 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
1211 string_append (decl, "'");
1213 else if (type == 'b')
1215 /* Parse boolean value. */
1216 unsigned long val;
1218 mangled = dlang_number (mangled, &val);
1219 if (mangled == NULL)
1220 return NULL;
1222 string_append (decl, val ? "true" : "false");
1224 else
1226 /* Parse integer value. */
1227 const char *numptr = mangled;
1228 size_t num = 0;
1230 if (! ISDIGIT (*mangled))
1231 return NULL;
1233 while (ISDIGIT (*mangled))
1235 num++;
1236 mangled++;
1238 string_appendn (decl, numptr, num);
1240 /* Append suffix. */
1241 switch (type)
1243 case 'h': /* ubyte */
1244 case 't': /* ushort */
1245 case 'k': /* uint */
1246 string_append (decl, "u");
1247 break;
1248 case 'l': /* long */
1249 string_append (decl, "L");
1250 break;
1251 case 'm': /* ulong */
1252 string_append (decl, "uL");
1253 break;
1257 return mangled;
1260 /* Extract the floating-point value from MANGLED and append it to DECL.
1261 Return the remaining string on success or NULL on failure. */
1262 static const char *
1263 dlang_parse_real (string *decl, const char *mangled)
1265 /* Handle NAN and +-INF. */
1266 if (strncmp (mangled, "NAN", 3) == 0)
1268 string_append (decl, "NaN");
1269 mangled += 3;
1270 return mangled;
1272 else if (strncmp (mangled, "INF", 3) == 0)
1274 string_append (decl, "Inf");
1275 mangled += 3;
1276 return mangled;
1278 else if (strncmp (mangled, "NINF", 4) == 0)
1280 string_append (decl, "-Inf");
1281 mangled += 4;
1282 return mangled;
1285 /* Hexadecimal prefix and leading bit. */
1286 if (*mangled == 'N')
1288 string_append (decl, "-");
1289 mangled++;
1292 if (!ISXDIGIT (*mangled))
1293 return NULL;
1295 string_append (decl, "0x");
1296 string_appendn (decl, mangled, 1);
1297 string_append (decl, ".");
1298 mangled++;
1300 /* Significand. */
1301 while (ISXDIGIT (*mangled))
1303 string_appendn (decl, mangled, 1);
1304 mangled++;
1307 /* Exponent. */
1308 if (*mangled != 'P')
1309 return NULL;
1311 string_append (decl, "p");
1312 mangled++;
1314 if (*mangled == 'N')
1316 string_append (decl, "-");
1317 mangled++;
1320 while (ISDIGIT (*mangled))
1322 string_appendn (decl, mangled, 1);
1323 mangled++;
1326 return mangled;
1329 /* Extract the string value from MANGLED and append it to DECL.
1330 Return the remaining string on success or NULL on failure. */
1331 static const char *
1332 dlang_parse_string (string *decl, const char *mangled)
1334 char type = *mangled;
1335 unsigned long len;
1337 mangled++;
1338 mangled = dlang_number (mangled, &len);
1339 if (mangled == NULL || *mangled != '_')
1340 return NULL;
1342 mangled++;
1343 string_append (decl, "\"");
1344 while (len--)
1346 char val;
1347 const char *endptr = dlang_hexdigit (mangled, &val);
1349 if (endptr == NULL)
1350 return NULL;
1352 /* Sanitize white and non-printable characters. */
1353 switch (val)
1355 case ' ':
1356 string_append (decl, " ");
1357 break;
1358 case '\t':
1359 string_append (decl, "\\t");
1360 break;
1361 case '\n':
1362 string_append (decl, "\\n");
1363 break;
1364 case '\r':
1365 string_append (decl, "\\r");
1366 break;
1367 case '\f':
1368 string_append (decl, "\\f");
1369 break;
1370 case '\v':
1371 string_append (decl, "\\v");
1372 break;
1374 default:
1375 if (ISPRINT (val))
1376 string_appendn (decl, &val, 1);
1377 else
1379 string_append (decl, "\\x");
1380 string_appendn (decl, mangled, 2);
1384 mangled = endptr;
1386 string_append (decl, "\"");
1388 if (type != 'a')
1389 string_appendn (decl, &type, 1);
1391 return mangled;
1394 /* Extract the static array value from MANGLED and append it to DECL.
1395 Return the remaining string on success or NULL on failure. */
1396 static const char *
1397 dlang_parse_arrayliteral (string *decl, const char *mangled)
1399 unsigned long elements;
1401 mangled = dlang_number (mangled, &elements);
1402 if (mangled == NULL)
1403 return NULL;
1405 string_append (decl, "[");
1406 while (elements--)
1408 mangled = dlang_value (decl, mangled, NULL, '\0');
1409 if (mangled == NULL)
1410 return NULL;
1412 if (elements != 0)
1413 string_append (decl, ", ");
1416 string_append (decl, "]");
1417 return mangled;
1420 /* Extract the associative array value from MANGLED and append it to DECL.
1421 Return the remaining string on success or NULL on failure. */
1422 static const char *
1423 dlang_parse_assocarray (string *decl, const char *mangled)
1425 unsigned long elements;
1427 mangled = dlang_number (mangled, &elements);
1428 if (mangled == NULL)
1429 return NULL;
1431 string_append (decl, "[");
1432 while (elements--)
1434 mangled = dlang_value (decl, mangled, NULL, '\0');
1435 if (mangled == NULL)
1436 return NULL;
1438 string_append (decl, ":");
1439 mangled = dlang_value (decl, mangled, NULL, '\0');
1440 if (mangled == NULL)
1441 return NULL;
1443 if (elements != 0)
1444 string_append (decl, ", ");
1447 string_append (decl, "]");
1448 return mangled;
1451 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1452 Return the remaining string on success or NULL on failure. */
1453 static const char *
1454 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1456 unsigned long args;
1458 mangled = dlang_number (mangled, &args);
1459 if (mangled == NULL)
1460 return NULL;
1462 if (name != NULL)
1463 string_append (decl, name);
1465 string_append (decl, "(");
1466 while (args--)
1468 mangled = dlang_value (decl, mangled, NULL, '\0');
1469 if (mangled == NULL)
1470 return NULL;
1472 if (args != 0)
1473 string_append (decl, ", ");
1476 string_append (decl, ")");
1477 return mangled;
1480 /* Extract the value from MANGLED and append it to DECL.
1481 Return the remaining string on success or NULL on failure. */
1482 static const char *
1483 dlang_value (string *decl, const char *mangled, const char *name, char type)
1485 if (mangled == NULL || *mangled == '\0')
1486 return NULL;
1488 switch (*mangled)
1490 /* Null value. */
1491 case 'n':
1492 mangled++;
1493 string_append (decl, "null");
1494 break;
1496 /* Integral values. */
1497 case 'N':
1498 mangled++;
1499 string_append (decl, "-");
1500 mangled = dlang_parse_integer (decl, mangled, type);
1501 break;
1503 case 'i':
1504 mangled++;
1505 /* Fall through */
1507 /* There really should always be an `i' before encoded numbers, but there
1508 wasn't in early versions of D2, so this case range must remain for
1509 backwards compatibility. */
1510 case '0': case '1': case '2': case '3': case '4':
1511 case '5': case '6': case '7': case '8': case '9':
1512 mangled = dlang_parse_integer (decl, mangled, type);
1513 break;
1515 /* Real value. */
1516 case 'e':
1517 mangled++;
1518 mangled = dlang_parse_real (decl, mangled);
1519 break;
1521 /* Complex value. */
1522 case 'c':
1523 mangled++;
1524 mangled = dlang_parse_real (decl, mangled);
1525 string_append (decl, "+");
1526 if (mangled == NULL || *mangled != 'c')
1527 return NULL;
1528 mangled++;
1529 mangled = dlang_parse_real (decl, mangled);
1530 string_append (decl, "i");
1531 break;
1533 /* String values. */
1534 case 'a': /* UTF8 */
1535 case 'w': /* UTF16 */
1536 case 'd': /* UTF32 */
1537 mangled = dlang_parse_string (decl, mangled);
1538 break;
1540 /* Array values. */
1541 case 'A':
1542 mangled++;
1543 if (type == 'H')
1544 mangled = dlang_parse_assocarray (decl, mangled);
1545 else
1546 mangled = dlang_parse_arrayliteral (decl, mangled);
1547 break;
1549 /* Struct values. */
1550 case 'S':
1551 mangled++;
1552 mangled = dlang_parse_structlit (decl, mangled, name);
1553 break;
1555 default:
1556 return NULL;
1559 return mangled;
1562 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1563 Returns the remaining signature on success or NULL on failure. */
1564 static const char *
1565 dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
1567 /* A D mangled symbol is comprised of both scope and type information.
1569 MangleName:
1570 _D QualifiedName Type
1571 _D QualifiedName Z
1573 The caller should have guaranteed that the start pointer is at the
1574 above location.
1575 Note that type is never a function type, but only the return type of
1576 a function or the type of a variable.
1578 mangled += 2;
1580 mangled = dlang_parse_qualified (decl, mangled, info, 1);
1582 if (mangled != NULL)
1584 /* Artificial symbols end with 'Z' and have no type. */
1585 if (*mangled == 'Z')
1586 mangled++;
1587 else
1589 /* Discard the declaration or return type. */
1590 string type;
1592 string_init (&type);
1593 mangled = dlang_type (&type, mangled, info);
1594 string_delete (&type);
1598 return mangled;
1601 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1602 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1603 Returns the remaining signature on success or NULL on failure. */
1604 static const char *
1605 dlang_parse_qualified (string *decl, const char *mangled,
1606 struct dlang_info *info, int suffix_modifiers)
1608 /* Qualified names are identifiers separated by their encoded length.
1609 Nested functions also encode their argument types without specifying
1610 what they return.
1612 QualifiedName:
1613 SymbolFunctionName
1614 SymbolFunctionName QualifiedName
1617 SymbolFunctionName:
1618 SymbolName
1619 SymbolName TypeFunctionNoReturn
1620 SymbolName M TypeFunctionNoReturn
1621 SymbolName M TypeModifiers TypeFunctionNoReturn
1623 The start pointer should be at the above location.
1625 size_t n = 0;
1628 if (n++)
1629 string_append (decl, ".");
1631 /* Skip over anonymous symbols. */
1632 while (*mangled == '0')
1633 mangled++;
1635 mangled = dlang_identifier (decl, mangled, info);
1637 /* Consume the encoded arguments. However if this is not followed by the
1638 next encoded length or mangle type, then this is not a continuation of
1639 a qualified name, in which case we backtrack and return the current
1640 unconsumed position of the mangled decl. */
1641 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
1643 string mods;
1644 const char *start = mangled;
1645 int saved = string_length (decl);
1647 /* Save the type modifiers for appending at the end if needed. */
1648 string_init (&mods);
1650 /* Skip over 'this' parameter and type modifiers. */
1651 if (*mangled == 'M')
1653 mangled++;
1654 mangled = dlang_type_modifiers (&mods, mangled);
1655 string_setlength (decl, saved);
1658 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1659 mangled, info);
1660 if (suffix_modifiers)
1661 string_appendn (decl, mods.b, string_length (&mods));
1663 if (mangled == NULL || *mangled == '\0')
1665 /* Did not match the rule we were looking for. */
1666 mangled = start;
1667 string_setlength (decl, saved);
1670 string_delete (&mods);
1673 while (mangled && dlang_symbol_name_p (mangled, info));
1675 return mangled;
1678 /* Demangle the tuple from MANGLED and append it to DECL.
1679 Return the remaining string on success or NULL on failure. */
1680 static const char *
1681 dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
1683 unsigned long elements;
1685 mangled = dlang_number (mangled, &elements);
1686 if (mangled == NULL)
1687 return NULL;
1689 string_append (decl, "Tuple!(");
1691 while (elements--)
1693 mangled = dlang_type (decl, mangled, info);
1694 if (mangled == NULL)
1695 return NULL;
1697 if (elements != 0)
1698 string_append (decl, ", ");
1701 string_append (decl, ")");
1702 return mangled;
1705 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1706 Return the remaining string on success or NULL on failure. */
1707 static const char *
1708 dlang_template_symbol_param (string *decl, const char *mangled,
1709 struct dlang_info *info)
1711 if (strncmp (mangled, "_D", 2) == 0
1712 && dlang_symbol_name_p (mangled + 2, info))
1713 return dlang_parse_mangle (decl, mangled, info);
1715 if (*mangled == 'Q')
1716 return dlang_parse_qualified (decl, mangled, info, 0);
1718 unsigned long len;
1719 const char *endptr = dlang_number (mangled, &len);
1721 if (endptr == NULL || len == 0)
1722 return NULL;
1724 /* In template parameter symbols generated by the frontend up to 2.076,
1725 the symbol length is encoded and the first character of the mangled
1726 name can be a digit. This causes ambiguity issues because the digits
1727 of the two numbers are adjacent. */
1728 long psize = len;
1729 const char *pend;
1730 int saved = string_length (decl);
1732 /* Work backwards until a match is found. */
1733 for (pend = endptr; endptr != NULL; pend--)
1735 mangled = pend;
1737 /* Reached the beginning of the pointer to the name length,
1738 try parsing the entire symbol. */
1739 if (psize == 0)
1741 psize = len;
1742 pend = endptr;
1743 endptr = NULL;
1746 /* Check whether template parameter is a function with a valid
1747 return type or an untyped identifier. */
1748 if (dlang_symbol_name_p (mangled, info))
1749 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1750 else if (strncmp (mangled, "_D", 2) == 0
1751 && dlang_symbol_name_p (mangled + 2, info))
1752 mangled = dlang_parse_mangle (decl, mangled, info);
1754 /* Check for name length mismatch. */
1755 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1756 return mangled;
1758 psize /= 10;
1759 string_setlength (decl, saved);
1762 /* No match on any combinations. */
1763 return NULL;
1766 /* Demangle the argument list from MANGLED and append it to DECL.
1767 Return the remaining string on success or NULL on failure. */
1768 static const char *
1769 dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
1771 size_t n = 0;
1773 while (mangled && *mangled != '\0')
1775 switch (*mangled)
1777 case 'Z': /* End of parameter list. */
1778 mangled++;
1779 return mangled;
1782 if (n++)
1783 string_append (decl, ", ");
1785 /* Skip over specialised template prefix. */
1786 if (*mangled == 'H')
1787 mangled++;
1789 switch (*mangled)
1791 case 'S': /* Symbol parameter. */
1792 mangled++;
1793 mangled = dlang_template_symbol_param (decl, mangled, info);
1794 break;
1795 case 'T': /* Type parameter. */
1796 mangled++;
1797 mangled = dlang_type (decl, mangled, info);
1798 break;
1799 case 'V': /* Value parameter. */
1801 string name;
1802 char type;
1804 /* Peek at the type. */
1805 mangled++;
1806 type = *mangled;
1808 if (type == 'Q')
1810 /* Value type is a back reference, peek at the real type. */
1811 const char *backref;
1812 if (dlang_backref (mangled, &backref, info) == NULL)
1813 return NULL;
1815 type = *backref;
1818 /* In the few instances where the type is actually desired in
1819 the output, it should precede the value from dlang_value. */
1820 string_init (&name);
1821 mangled = dlang_type (&name, mangled, info);
1822 string_need (&name, 1);
1823 *(name.p) = '\0';
1825 mangled = dlang_value (decl, mangled, name.b, type);
1826 string_delete (&name);
1827 break;
1829 case 'X': /* Externally mangled parameter. */
1831 unsigned long len;
1832 const char *endptr;
1834 mangled++;
1835 endptr = dlang_number (mangled, &len);
1836 if (endptr == NULL || strlen (endptr) < len)
1837 return NULL;
1839 string_appendn (decl, endptr, len);
1840 mangled = endptr + len;
1841 break;
1843 default:
1844 return NULL;
1848 return mangled;
1851 /* Extract and demangle the template symbol in MANGLED, expected to
1852 be made up of LEN characters (-1 if unknown), and append it to DECL.
1853 Returns the remaining signature on success or NULL on failure. */
1854 static const char *
1855 dlang_parse_template (string *decl, const char *mangled,
1856 struct dlang_info *info, unsigned long len)
1858 const char *start = mangled;
1859 string args;
1861 /* Template instance names have the types and values of its parameters
1862 encoded into it.
1864 TemplateInstanceName:
1865 Number __T LName TemplateArgs Z
1866 Number __U LName TemplateArgs Z
1868 The start pointer should be at the above location, and LEN should be
1869 the value of the decoded number.
1872 /* Template symbol. */
1873 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
1874 return NULL;
1876 mangled += 3;
1878 /* Template identifier. */
1879 mangled = dlang_identifier (decl, mangled, info);
1881 /* Template arguments. */
1882 string_init (&args);
1883 mangled = dlang_template_args (&args, mangled, info);
1885 string_append (decl, "!(");
1886 string_appendn (decl, args.b, string_length (&args));
1887 string_append (decl, ")");
1889 string_delete (&args);
1891 /* Check for template name length mismatch. */
1892 if (len != TEMPLATE_LENGTH_UNKNOWN
1893 && mangled
1894 && (unsigned long) (mangled - start) != len)
1895 return NULL;
1897 return mangled;
1900 /* Initialize the information structure we use to pass around information. */
1901 static void
1902 dlang_demangle_init_info (const char *mangled, int last_backref,
1903 struct dlang_info *info)
1905 info->s = mangled;
1906 info->last_backref = last_backref;
1909 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1910 signature on success or NULL on failure. */
1912 char *
1913 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1915 string decl;
1916 char *demangled = NULL;
1918 if (mangled == NULL || *mangled == '\0')
1919 return NULL;
1921 if (strncmp (mangled, "_D", 2) != 0)
1922 return NULL;
1924 string_init (&decl);
1926 if (strcmp (mangled, "_Dmain") == 0)
1928 string_append (&decl, "D main");
1930 else
1932 struct dlang_info info;
1934 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1935 mangled = dlang_parse_mangle (&decl, mangled, &info);
1937 /* Check that the entire symbol was successfully demangled. */
1938 if (mangled == NULL || *mangled != '\0')
1939 string_delete (&decl);
1942 if (string_length (&decl) > 0)
1944 string_need (&decl, 1);
1945 *(decl.p) = '\0';
1946 demangled = decl.b;
1949 return demangled;