vgdb: Handle EAGAIN in read_buf
[valgrind.git] / coregrind / m_demangle / d-demangle.c
blobc2c3e08c8d9ef61e7cca4c79df9fa1da1a5e2253
1 /* Demangler for the D programming language
2 Copyright (C) 2014-2022 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,
211 struct dlang_info *);
213 static const char *dlang_parse_qualified (string *, const char *,
214 struct dlang_info *, int);
216 static const char *dlang_parse_mangle (string *, const char *,
217 struct dlang_info *);
219 static const char *dlang_parse_tuple (string *, const char *,
220 struct dlang_info *);
222 static const char *dlang_parse_template (string *, const char *,
223 struct dlang_info *, unsigned long);
225 static const char *dlang_lname (string *, const char *, unsigned long);
228 /* Extract the number from MANGLED, and assign the result to RET.
229 Return the remaining string on success or NULL on failure.
230 A result larger than UINT_MAX is considered a failure. */
231 static const char *
232 dlang_number (const char *mangled, unsigned long *ret)
234 /* Return NULL if trying to extract something that isn't a digit. */
235 if (mangled == NULL || !ISDIGIT (*mangled))
236 return NULL;
238 unsigned long val = 0;
240 while (ISDIGIT (*mangled))
242 unsigned long digit = mangled[0] - '0';
244 /* Check for overflow. */
245 if (val > (UINT_MAX - digit) / 10)
246 return NULL;
248 val = val * 10 + digit;
249 mangled++;
252 if (*mangled == '\0')
253 return NULL;
255 *ret = val;
256 return mangled;
259 /* Extract the hex-digit from MANGLED, and assign the result to RET.
260 Return the remaining string on success or NULL on failure. */
261 static const char *
262 dlang_hexdigit (const char *mangled, char *ret)
264 char c;
266 /* Return NULL if trying to extract something that isn't a hexdigit. */
267 if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
268 return NULL;
270 c = mangled[0];
271 if (!ISDIGIT (c))
272 *ret = c - (ISUPPER (c) ? 'A' : 'a') + 10;
273 else
274 *ret = c - '0';
276 c = mangled[1];
277 if (!ISDIGIT (c))
278 *ret = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
279 else
280 *ret = (*ret << 4) | (c - '0');
282 mangled += 2;
284 return mangled;
287 /* Extract the function calling convention from MANGLED and
288 return 1 on success or 0 on failure. */
289 static int
290 dlang_call_convention_p (const char *mangled)
292 switch (*mangled)
294 case 'F': case 'U': case 'V':
295 case 'W': case 'R': case 'Y':
296 return 1;
298 default:
299 return 0;
303 /* Extract the back reference position from MANGLED, and assign the result
304 to RET. Return the remaining string on success or NULL on failure.
305 A result <= 0 is a failure. */
306 static const char *
307 dlang_decode_backref (const char *mangled, long *ret)
309 /* Return NULL if trying to extract something that isn't a digit. */
310 if (mangled == NULL || !ISALPHA (*mangled))
311 return NULL;
313 /* Any identifier or non-basic type that has been emitted to the mangled
314 symbol before will not be emitted again, but is referenced by a special
315 sequence encoding the relative position of the original occurrence in the
316 mangled symbol name.
318 Numbers in back references are encoded with base 26 by upper case letters
319 A-Z for higher digits but lower case letters a-z for the last digit.
321 NumberBackRef:
322 [a-z]
323 [A-Z] NumberBackRef
326 unsigned long val = 0;
328 while (ISALPHA (*mangled))
330 /* Check for overflow. */
331 if (val > (ULONG_MAX - 25) / 26)
332 break;
334 val *= 26;
336 if (mangled[0] >= 'a' && mangled[0] <= 'z')
338 val += mangled[0] - 'a';
339 if ((long) val <= 0)
340 break;
341 *ret = val;
342 return mangled + 1;
345 val += mangled[0] - 'A';
346 mangled++;
349 return NULL;
352 /* Extract the symbol pointed at by the back reference and assign the result
353 to RET. Return the remaining string on success or NULL on failure. */
354 static const char *
355 dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
357 *ret = NULL;
359 if (mangled == NULL || *mangled != 'Q')
360 return NULL;
362 /* Position of 'Q'. */
363 const char *qpos = mangled;
364 long refpos;
365 mangled++;
367 mangled = dlang_decode_backref (mangled, &refpos);
368 if (mangled == NULL)
369 return NULL;
371 if (refpos > qpos - info->s)
372 return NULL;
374 /* Set the position of the back reference. */
375 *ret = qpos - refpos;
377 return mangled;
380 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
381 Return the remaining string on success or NULL on failure. */
382 static const char *
383 dlang_symbol_backref (string *decl, const char *mangled,
384 struct dlang_info *info)
386 /* An identifier back reference always points to a digit 0 to 9.
388 IdentifierBackRef:
389 Q NumberBackRef
392 const char *backref;
393 unsigned long len;
395 /* Get position of the back reference. */
396 mangled = dlang_backref (mangled, &backref, info);
398 /* Must point to a simple identifier. */
399 backref = dlang_number (backref, &len);
400 if (backref == NULL || strlen(backref) < len)
401 return NULL;
403 backref = dlang_lname (decl, backref, len);
404 if (backref == NULL)
405 return NULL;
407 return mangled;
410 /* Demangle a back referenced type from MANGLED and append it to DECL.
411 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
412 Return the remaining string on success or NULL on failure. */
413 static const char *
414 dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
415 int is_function)
417 /* A type back reference always points to a letter.
419 TypeBackRef:
420 Q NumberBackRef
423 const char *backref;
425 /* If we appear to be moving backwards through the mangle string, then
426 bail as this may be a recursive back reference. */
427 if (mangled - info->s >= info->last_backref)
428 return NULL;
430 int save_refpos = info->last_backref;
431 info->last_backref = mangled - info->s;
433 /* Get position of the back reference. */
434 mangled = dlang_backref (mangled, &backref, info);
436 /* Must point to a type. */
437 if (is_function)
438 backref = dlang_function_type (decl, backref, info);
439 else
440 backref = dlang_type (decl, backref, info);
442 info->last_backref = save_refpos;
444 if (backref == NULL)
445 return NULL;
447 return mangled;
450 /* Extract the beginning of a symbol name from MANGLED and
451 return 1 on success or 0 on failure. */
452 static int
453 dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
455 long ret;
456 const char *qref = mangled;
458 if (ISDIGIT (*mangled))
459 return 1;
461 if (mangled[0] == '_' && mangled[1] == '_'
462 && (mangled[2] == 'T' || mangled[2] == 'U'))
463 return 1;
465 if (*mangled != 'Q')
466 return 0;
468 mangled = dlang_decode_backref (mangled + 1, &ret);
469 if (mangled == NULL || ret > qref - info->s)
470 return 0;
472 return ISDIGIT (qref[-ret]);
475 /* Demangle the calling convention from MANGLED and append it to DECL.
476 Return the remaining string on success or NULL on failure. */
477 static const char *
478 dlang_call_convention (string *decl, const char *mangled)
480 if (mangled == NULL || *mangled == '\0')
481 return NULL;
483 switch (*mangled)
485 case 'F': /* (D) */
486 mangled++;
487 break;
488 case 'U': /* (C) */
489 mangled++;
490 string_append (decl, "extern(C) ");
491 break;
492 case 'W': /* (Windows) */
493 mangled++;
494 string_append (decl, "extern(Windows) ");
495 break;
496 case 'V': /* (Pascal) */
497 mangled++;
498 string_append (decl, "extern(Pascal) ");
499 break;
500 case 'R': /* (C++) */
501 mangled++;
502 string_append (decl, "extern(C++) ");
503 break;
504 case 'Y': /* (Objective-C) */
505 mangled++;
506 string_append (decl, "extern(Objective-C) ");
507 break;
508 default:
509 return NULL;
512 return mangled;
515 /* Extract the type modifiers from MANGLED and append them to DECL.
516 Returns the remaining signature on success or NULL on failure. */
517 static const char *
518 dlang_type_modifiers (string *decl, const char *mangled)
520 if (mangled == NULL || *mangled == '\0')
521 return NULL;
523 switch (*mangled)
525 case 'x': /* const */
526 mangled++;
527 string_append (decl, " const");
528 return mangled;
529 case 'y': /* immutable */
530 mangled++;
531 string_append (decl, " immutable");
532 return mangled;
533 case 'O': /* shared */
534 mangled++;
535 string_append (decl, " shared");
536 return dlang_type_modifiers (decl, mangled);
537 case 'N':
538 mangled++;
539 if (*mangled == 'g') /* wild */
541 mangled++;
542 string_append (decl, " inout");
543 return dlang_type_modifiers (decl, mangled);
545 else
546 return NULL;
548 default:
549 return mangled;
553 /* Demangle the D function attributes from MANGLED and append it to DECL.
554 Return the remaining string on success or NULL on failure. */
555 static const char *
556 dlang_attributes (string *decl, const char *mangled)
558 if (mangled == NULL || *mangled == '\0')
559 return NULL;
561 while (*mangled == 'N')
563 mangled++;
564 switch (*mangled)
566 case 'a': /* pure */
567 mangled++;
568 string_append (decl, "pure ");
569 continue;
570 case 'b': /* nothrow */
571 mangled++;
572 string_append (decl, "nothrow ");
573 continue;
574 case 'c': /* ref */
575 mangled++;
576 string_append (decl, "ref ");
577 continue;
578 case 'd': /* @property */
579 mangled++;
580 string_append (decl, "@property ");
581 continue;
582 case 'e': /* @trusted */
583 mangled++;
584 string_append (decl, "@trusted ");
585 continue;
586 case 'f': /* @safe */
587 mangled++;
588 string_append (decl, "@safe ");
589 continue;
590 case 'g':
591 case 'h':
592 case 'k':
593 case 'n':
594 /* inout parameter is represented as 'Ng'.
595 vector parameter is represented as 'Nh'.
596 return parameter is represented as 'Nk'.
597 typeof(*null) parameter is represented as 'Nn'.
598 If we see this, then we know we're really in the
599 parameter list. Rewind and break. */
600 mangled--;
601 break;
602 case 'i': /* @nogc */
603 mangled++;
604 string_append (decl, "@nogc ");
605 continue;
606 case 'j': /* return */
607 mangled++;
608 string_append (decl, "return ");
609 continue;
610 case 'l': /* scope */
611 mangled++;
612 string_append (decl, "scope ");
613 continue;
614 case 'm': /* @live */
615 mangled++;
616 string_append (decl, "@live ");
617 continue;
619 default: /* unknown attribute */
620 return NULL;
622 break;
625 return mangled;
628 /* Demangle the function type from MANGLED without the return type.
629 The arguments are appended to ARGS, the calling convention is appended
630 to CALL and attributes are appended to ATTR. Any of these can be NULL
631 to throw the information away. Return the remaining string on success
632 or NULL on failure. */
633 static const char *
634 dlang_function_type_noreturn (string *args, string *call, string *attr,
635 const char *mangled, struct dlang_info *info)
637 string dump;
638 string_init (&dump);
640 /* Skip over calling convention and attributes. */
641 mangled = dlang_call_convention (call ? call : &dump, mangled);
642 mangled = dlang_attributes (attr ? attr : &dump, mangled);
644 if (args)
645 string_append (args, "(");
647 mangled = dlang_function_args (args ? args : &dump, mangled, info);
648 if (args)
649 string_append (args, ")");
651 string_delete (&dump);
652 return mangled;
655 /* Demangle the function type from MANGLED and append it to DECL.
656 Return the remaining string on success or NULL on failure. */
657 static const char *
658 dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
660 string attr, args, type;
662 if (mangled == NULL || *mangled == '\0')
663 return NULL;
665 /* The order of the mangled string is:
666 CallConvention FuncAttrs Arguments ArgClose Type
668 The demangled string is re-ordered as:
669 CallConvention Type Arguments FuncAttrs
671 string_init (&attr);
672 string_init (&args);
673 string_init (&type);
675 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
677 /* Function return type. */
678 mangled = dlang_type (&type, mangled, info);
680 /* Append to decl in order. */
681 string_appendn (decl, type.b, string_length (&type));
682 string_appendn (decl, args.b, string_length (&args));
683 string_append (decl, " ");
684 string_appendn (decl, attr.b, string_length (&attr));
686 string_delete (&attr);
687 string_delete (&args);
688 string_delete (&type);
689 return mangled;
692 /* Demangle the argument list from MANGLED and append it to DECL.
693 Return the remaining string on success or NULL on failure. */
694 static const char *
695 dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
697 size_t n = 0;
699 while (mangled && *mangled != '\0')
701 switch (*mangled)
703 case 'X': /* (variadic T t...) style. */
704 mangled++;
705 string_append (decl, "...");
706 return mangled;
707 case 'Y': /* (variadic T t, ...) style. */
708 mangled++;
709 if (n != 0)
710 string_append (decl, ", ");
711 string_append (decl, "...");
712 return mangled;
713 case 'Z': /* Normal function. */
714 mangled++;
715 return mangled;
718 if (n++)
719 string_append (decl, ", ");
721 if (*mangled == 'M') /* scope(T) */
723 mangled++;
724 string_append (decl, "scope ");
727 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
729 mangled += 2;
730 string_append (decl, "return ");
733 switch (*mangled)
735 case 'I': /* in(T) */
736 mangled++;
737 string_append (decl, "in ");
738 if (*mangled == 'K') /* in ref(T) */
740 mangled++;
741 string_append (decl, "ref ");
743 break;
744 case 'J': /* out(T) */
745 mangled++;
746 string_append (decl, "out ");
747 break;
748 case 'K': /* ref(T) */
749 mangled++;
750 string_append (decl, "ref ");
751 break;
752 case 'L': /* lazy(T) */
753 mangled++;
754 string_append (decl, "lazy ");
755 break;
757 mangled = dlang_type (decl, mangled, info);
760 return mangled;
763 /* Demangle the type from MANGLED and append it to DECL.
764 Return the remaining string on success or NULL on failure. */
765 static const char *
766 dlang_type (string *decl, const char *mangled, struct dlang_info *info)
768 if (mangled == NULL || *mangled == '\0')
769 return NULL;
771 switch (*mangled)
773 case 'O': /* shared(T) */
774 mangled++;
775 string_append (decl, "shared(");
776 mangled = dlang_type (decl, mangled, info);
777 string_append (decl, ")");
778 return mangled;
779 case 'x': /* const(T) */
780 mangled++;
781 string_append (decl, "const(");
782 mangled = dlang_type (decl, mangled, info);
783 string_append (decl, ")");
784 return mangled;
785 case 'y': /* immutable(T) */
786 mangled++;
787 string_append (decl, "immutable(");
788 mangled = dlang_type (decl, mangled, info);
789 string_append (decl, ")");
790 return mangled;
791 case 'N':
792 mangled++;
793 if (*mangled == 'g') /* wild(T) */
795 mangled++;
796 string_append (decl, "inout(");
797 mangled = dlang_type (decl, mangled, info);
798 string_append (decl, ")");
799 return mangled;
801 else if (*mangled == 'h') /* vector(T) */
803 mangled++;
804 string_append (decl, "__vector(");
805 mangled = dlang_type (decl, mangled, info);
806 string_append (decl, ")");
807 return mangled;
809 else if (*mangled == 'n') /* typeof(*null) */
811 mangled++;
812 string_append (decl, "typeof(*null)");
813 return mangled;
815 else
816 return NULL;
817 case 'A': /* dynamic array (T[]) */
818 mangled++;
819 mangled = dlang_type (decl, mangled, info);
820 string_append (decl, "[]");
821 return mangled;
822 case 'G': /* static array (T[N]) */
824 const char *numptr;
825 size_t num = 0;
826 mangled++;
828 numptr = mangled;
829 while (ISDIGIT (*mangled))
831 num++;
832 mangled++;
834 mangled = dlang_type (decl, mangled, info);
835 string_append (decl, "[");
836 string_appendn (decl, numptr, num);
837 string_append (decl, "]");
838 return mangled;
840 case 'H': /* associative array (T[T]) */
842 string type;
843 size_t sztype;
844 mangled++;
846 string_init (&type);
847 mangled = dlang_type (&type, mangled, info);
848 sztype = string_length (&type);
850 mangled = dlang_type (decl, mangled, info);
851 string_append (decl, "[");
852 string_appendn (decl, type.b, sztype);
853 string_append (decl, "]");
855 string_delete (&type);
856 return mangled;
858 case 'P': /* pointer (T*) */
859 mangled++;
860 if (!dlang_call_convention_p (mangled))
862 mangled = dlang_type (decl, mangled, info);
863 string_append (decl, "*");
864 return mangled;
866 /* Fall through */
867 case 'F': /* function T (D) */
868 case 'U': /* function T (C) */
869 case 'W': /* function T (Windows) */
870 case 'V': /* function T (Pascal) */
871 case 'R': /* function T (C++) */
872 case 'Y': /* function T (Objective-C) */
873 /* Function pointer types don't include the trailing asterisk. */
874 mangled = dlang_function_type (decl, mangled, info);
875 string_append (decl, "function");
876 return mangled;
877 case 'C': /* class T */
878 case 'S': /* struct T */
879 case 'E': /* enum T */
880 case 'T': /* typedef T */
881 mangled++;
882 return dlang_parse_qualified (decl, mangled, info, 0);
883 case 'D': /* delegate T */
885 string mods;
886 size_t szmods;
887 mangled++;
889 string_init (&mods);
890 mangled = dlang_type_modifiers (&mods, mangled);
891 szmods = string_length (&mods);
893 /* Back referenced function type. */
894 if (mangled && *mangled == 'Q')
895 mangled = dlang_type_backref (decl, mangled, info, 1);
896 else
897 mangled = dlang_function_type (decl, mangled, info);
899 string_append (decl, "delegate");
900 string_appendn (decl, mods.b, szmods);
902 string_delete (&mods);
903 return mangled;
905 case 'B': /* tuple T */
906 mangled++;
907 return dlang_parse_tuple (decl, mangled, info);
909 /* Basic types */
910 case 'n':
911 mangled++;
912 string_append (decl, "typeof(null)");
913 return mangled;
914 case 'v':
915 mangled++;
916 string_append (decl, "void");
917 return mangled;
918 case 'g':
919 mangled++;
920 string_append (decl, "byte");
921 return mangled;
922 case 'h':
923 mangled++;
924 string_append (decl, "ubyte");
925 return mangled;
926 case 's':
927 mangled++;
928 string_append (decl, "short");
929 return mangled;
930 case 't':
931 mangled++;
932 string_append (decl, "ushort");
933 return mangled;
934 case 'i':
935 mangled++;
936 string_append (decl, "int");
937 return mangled;
938 case 'k':
939 mangled++;
940 string_append (decl, "uint");
941 return mangled;
942 case 'l':
943 mangled++;
944 string_append (decl, "long");
945 return mangled;
946 case 'm':
947 mangled++;
948 string_append (decl, "ulong");
949 return mangled;
950 case 'f':
951 mangled++;
952 string_append (decl, "float");
953 return mangled;
954 case 'd':
955 mangled++;
956 string_append (decl, "double");
957 return mangled;
958 case 'e':
959 mangled++;
960 string_append (decl, "real");
961 return mangled;
963 /* Imaginary and Complex types */
964 case 'o':
965 mangled++;
966 string_append (decl, "ifloat");
967 return mangled;
968 case 'p':
969 mangled++;
970 string_append (decl, "idouble");
971 return mangled;
972 case 'j':
973 mangled++;
974 string_append (decl, "ireal");
975 return mangled;
976 case 'q':
977 mangled++;
978 string_append (decl, "cfloat");
979 return mangled;
980 case 'r':
981 mangled++;
982 string_append (decl, "cdouble");
983 return mangled;
984 case 'c':
985 mangled++;
986 string_append (decl, "creal");
987 return mangled;
989 /* Other types */
990 case 'b':
991 mangled++;
992 string_append (decl, "bool");
993 return mangled;
994 case 'a':
995 mangled++;
996 string_append (decl, "char");
997 return mangled;
998 case 'u':
999 mangled++;
1000 string_append (decl, "wchar");
1001 return mangled;
1002 case 'w':
1003 mangled++;
1004 string_append (decl, "dchar");
1005 return mangled;
1006 case 'z':
1007 mangled++;
1008 switch (*mangled)
1010 case 'i':
1011 mangled++;
1012 string_append (decl, "cent");
1013 return mangled;
1014 case 'k':
1015 mangled++;
1016 string_append (decl, "ucent");
1017 return mangled;
1019 return NULL;
1021 /* Back referenced type. */
1022 case 'Q':
1023 return dlang_type_backref (decl, mangled, info, 0);
1025 default: /* unhandled */
1026 return NULL;
1030 /* Extract the identifier from MANGLED and append it to DECL.
1031 Return the remaining string on success or NULL on failure. */
1032 static const char *
1033 dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
1035 unsigned long len;
1037 if (mangled == NULL || *mangled == '\0')
1038 return NULL;
1040 if (*mangled == 'Q')
1041 return dlang_symbol_backref (decl, mangled, info);
1043 /* May be a template instance without a length prefix. */
1044 if (mangled[0] == '_' && mangled[1] == '_'
1045 && (mangled[2] == 'T' || mangled[2] == 'U'))
1046 return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
1048 const char *endptr = dlang_number (mangled, &len);
1050 if (endptr == NULL || len == 0)
1051 return NULL;
1053 if (strlen (endptr) < len)
1054 return NULL;
1056 mangled = endptr;
1058 /* May be a template instance with a length prefix. */
1059 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1060 && (mangled[2] == 'T' || mangled[2] == 'U'))
1061 return dlang_parse_template (decl, mangled, info, len);
1063 /* There can be multiple different declarations in the same function that have
1064 the same mangled name. To make the mangled names unique, a fake parent in
1065 the form `__Sddd' is added to the symbol. */
1066 if (len >= 4 && mangled[0] == '_' && mangled[1] == '_' && mangled[2] == 'S')
1068 const char *numptr = mangled + 3;
1069 while (numptr < (mangled + len) && ISDIGIT (*numptr))
1070 numptr++;
1072 if (mangled + len == numptr)
1074 /* Skip over the fake parent. */
1075 mangled += len;
1076 return dlang_identifier (decl, mangled, info);
1079 /* else demangle it as a plain identifier. */
1082 return dlang_lname (decl, mangled, len);
1085 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1086 with special treatment for some magic compiler generted symbols.
1087 Return the remaining string on success or NULL on failure. */
1088 static const char *
1089 dlang_lname (string *decl, const char *mangled, unsigned long len)
1091 switch (len)
1093 case 6:
1094 if (strncmp (mangled, "__ctor", len) == 0)
1096 /* Constructor symbol for a class/struct. */
1097 string_append (decl, "this");
1098 mangled += len;
1099 return mangled;
1101 else if (strncmp (mangled, "__dtor", len) == 0)
1103 /* Destructor symbol for a class/struct. */
1104 string_append (decl, "~this");
1105 mangled += len;
1106 return mangled;
1108 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1110 /* The static initialiser for a given symbol. */
1111 string_prepend (decl, "initializer for ");
1112 string_setlength (decl, string_length (decl) - 1);
1113 mangled += len;
1114 return mangled;
1116 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1118 /* The vtable symbol for a given class. */
1119 string_prepend (decl, "vtable for ");
1120 string_setlength (decl, string_length (decl) - 1);
1121 mangled += len;
1122 return mangled;
1124 break;
1126 case 7:
1127 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1129 /* The classinfo symbol for a given class. */
1130 string_prepend (decl, "ClassInfo for ");
1131 string_setlength (decl, string_length (decl) - 1);
1132 mangled += len;
1133 return mangled;
1135 break;
1137 case 10:
1138 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1140 /* Postblit symbol for a struct. */
1141 string_append (decl, "this(this)");
1142 mangled += len + 3;
1143 return mangled;
1145 break;
1147 case 11:
1148 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1150 /* The interface symbol for a given class. */
1151 string_prepend (decl, "Interface for ");
1152 string_setlength (decl, string_length (decl) - 1);
1153 mangled += len;
1154 return mangled;
1156 break;
1158 case 12:
1159 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1161 /* The ModuleInfo symbol for a given module. */
1162 string_prepend (decl, "ModuleInfo for ");
1163 string_setlength (decl, string_length (decl) - 1);
1164 mangled += len;
1165 return mangled;
1167 break;
1170 string_appendn (decl, mangled, len);
1171 mangled += len;
1173 return mangled;
1176 /* Extract the integer value from MANGLED and append it to DECL,
1177 where TYPE is the type it should be represented as.
1178 Return the remaining string on success or NULL on failure. */
1179 static const char *
1180 dlang_parse_integer (string *decl, const char *mangled, char type)
1182 if (type == 'a' || type == 'u' || type == 'w')
1184 /* Parse character value. */
1185 char value[20];
1186 int pos = sizeof(value);
1187 int width = 0;
1188 unsigned long val;
1190 mangled = dlang_number (mangled, &val);
1191 if (mangled == NULL)
1192 return NULL;
1194 string_append (decl, "'");
1196 if (type == 'a' && val >= 0x20 && val < 0x7F)
1198 /* Represent as a character literal. */
1199 char c = (char) val;
1200 string_appendn (decl, &c, 1);
1202 else
1204 /* Represent as a hexadecimal value. */
1205 switch (type)
1207 case 'a': /* char */
1208 string_append (decl, "\\x");
1209 width = 2;
1210 break;
1211 case 'u': /* wchar */
1212 string_append (decl, "\\u");
1213 width = 4;
1214 break;
1215 case 'w': /* dchar */
1216 string_append (decl, "\\U");
1217 width = 8;
1218 break;
1221 while (val > 0)
1223 int digit = val % 16;
1225 if (digit < 10)
1226 value[--pos] = (char)(digit + '0');
1227 else
1228 value[--pos] = (char)((digit - 10) + 'a');
1230 val /= 16;
1231 width--;
1234 for (; width > 0; width--)
1235 value[--pos] = '0';
1237 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
1239 string_append (decl, "'");
1241 else if (type == 'b')
1243 /* Parse boolean value. */
1244 unsigned long val;
1246 mangled = dlang_number (mangled, &val);
1247 if (mangled == NULL)
1248 return NULL;
1250 string_append (decl, val ? "true" : "false");
1252 else
1254 /* Parse integer value. */
1255 const char *numptr = mangled;
1256 size_t num = 0;
1258 if (! ISDIGIT (*mangled))
1259 return NULL;
1261 while (ISDIGIT (*mangled))
1263 num++;
1264 mangled++;
1266 string_appendn (decl, numptr, num);
1268 /* Append suffix. */
1269 switch (type)
1271 case 'h': /* ubyte */
1272 case 't': /* ushort */
1273 case 'k': /* uint */
1274 string_append (decl, "u");
1275 break;
1276 case 'l': /* long */
1277 string_append (decl, "L");
1278 break;
1279 case 'm': /* ulong */
1280 string_append (decl, "uL");
1281 break;
1285 return mangled;
1288 /* Extract the floating-point value from MANGLED and append it to DECL.
1289 Return the remaining string on success or NULL on failure. */
1290 static const char *
1291 dlang_parse_real (string *decl, const char *mangled)
1293 /* Handle NAN and +-INF. */
1294 if (strncmp (mangled, "NAN", 3) == 0)
1296 string_append (decl, "NaN");
1297 mangled += 3;
1298 return mangled;
1300 else if (strncmp (mangled, "INF", 3) == 0)
1302 string_append (decl, "Inf");
1303 mangled += 3;
1304 return mangled;
1306 else if (strncmp (mangled, "NINF", 4) == 0)
1308 string_append (decl, "-Inf");
1309 mangled += 4;
1310 return mangled;
1313 /* Hexadecimal prefix and leading bit. */
1314 if (*mangled == 'N')
1316 string_append (decl, "-");
1317 mangled++;
1320 if (!ISXDIGIT (*mangled))
1321 return NULL;
1323 string_append (decl, "0x");
1324 string_appendn (decl, mangled, 1);
1325 string_append (decl, ".");
1326 mangled++;
1328 /* Significand. */
1329 while (ISXDIGIT (*mangled))
1331 string_appendn (decl, mangled, 1);
1332 mangled++;
1335 /* Exponent. */
1336 if (*mangled != 'P')
1337 return NULL;
1339 string_append (decl, "p");
1340 mangled++;
1342 if (*mangled == 'N')
1344 string_append (decl, "-");
1345 mangled++;
1348 while (ISDIGIT (*mangled))
1350 string_appendn (decl, mangled, 1);
1351 mangled++;
1354 return mangled;
1357 /* Extract the string value from MANGLED and append it to DECL.
1358 Return the remaining string on success or NULL on failure. */
1359 static const char *
1360 dlang_parse_string (string *decl, const char *mangled)
1362 char type = *mangled;
1363 unsigned long len;
1365 mangled++;
1366 mangled = dlang_number (mangled, &len);
1367 if (mangled == NULL || *mangled != '_')
1368 return NULL;
1370 mangled++;
1371 string_append (decl, "\"");
1372 while (len--)
1374 char val;
1375 const char *endptr = dlang_hexdigit (mangled, &val);
1377 if (endptr == NULL)
1378 return NULL;
1380 /* Sanitize white and non-printable characters. */
1381 switch (val)
1383 case ' ':
1384 string_append (decl, " ");
1385 break;
1386 case '\t':
1387 string_append (decl, "\\t");
1388 break;
1389 case '\n':
1390 string_append (decl, "\\n");
1391 break;
1392 case '\r':
1393 string_append (decl, "\\r");
1394 break;
1395 case '\f':
1396 string_append (decl, "\\f");
1397 break;
1398 case '\v':
1399 string_append (decl, "\\v");
1400 break;
1402 default:
1403 if (ISPRINT (val))
1404 string_appendn (decl, &val, 1);
1405 else
1407 string_append (decl, "\\x");
1408 string_appendn (decl, mangled, 2);
1412 mangled = endptr;
1414 string_append (decl, "\"");
1416 if (type != 'a')
1417 string_appendn (decl, &type, 1);
1419 return mangled;
1422 /* Extract the static array value from MANGLED and append it to DECL.
1423 Return the remaining string on success or NULL on failure. */
1424 static const char *
1425 dlang_parse_arrayliteral (string *decl, const char *mangled,
1426 struct dlang_info *info)
1428 unsigned long elements;
1430 mangled = dlang_number (mangled, &elements);
1431 if (mangled == NULL)
1432 return NULL;
1434 string_append (decl, "[");
1435 while (elements--)
1437 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1438 if (mangled == NULL)
1439 return NULL;
1441 if (elements != 0)
1442 string_append (decl, ", ");
1445 string_append (decl, "]");
1446 return mangled;
1449 /* Extract the associative array value from MANGLED and append it to DECL.
1450 Return the remaining string on success or NULL on failure. */
1451 static const char *
1452 dlang_parse_assocarray (string *decl, const char *mangled,
1453 struct dlang_info *info)
1455 unsigned long elements;
1457 mangled = dlang_number (mangled, &elements);
1458 if (mangled == NULL)
1459 return NULL;
1461 string_append (decl, "[");
1462 while (elements--)
1464 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1465 if (mangled == NULL)
1466 return NULL;
1468 string_append (decl, ":");
1469 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1470 if (mangled == NULL)
1471 return NULL;
1473 if (elements != 0)
1474 string_append (decl, ", ");
1477 string_append (decl, "]");
1478 return mangled;
1481 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1482 Return the remaining string on success or NULL on failure. */
1483 static const char *
1484 dlang_parse_structlit (string *decl, const char *mangled, const char *name,
1485 struct dlang_info *info)
1487 unsigned long args;
1489 mangled = dlang_number (mangled, &args);
1490 if (mangled == NULL)
1491 return NULL;
1493 if (name != NULL)
1494 string_append (decl, name);
1496 string_append (decl, "(");
1497 while (args--)
1499 mangled = dlang_value (decl, mangled, NULL, '\0', info);
1500 if (mangled == NULL)
1501 return NULL;
1503 if (args != 0)
1504 string_append (decl, ", ");
1507 string_append (decl, ")");
1508 return mangled;
1511 /* Extract the value from MANGLED and append it to DECL.
1512 Return the remaining string on success or NULL on failure. */
1513 static const char *
1514 dlang_value (string *decl, const char *mangled, const char *name, char type,
1515 struct dlang_info *info)
1517 if (mangled == NULL || *mangled == '\0')
1518 return NULL;
1520 switch (*mangled)
1522 /* Null value. */
1523 case 'n':
1524 mangled++;
1525 string_append (decl, "null");
1526 break;
1528 /* Integral values. */
1529 case 'N':
1530 mangled++;
1531 string_append (decl, "-");
1532 mangled = dlang_parse_integer (decl, mangled, type);
1533 break;
1535 case 'i':
1536 mangled++;
1537 /* Fall through */
1539 /* There really should always be an `i' before encoded numbers, but there
1540 wasn't in early versions of D2, so this case range must remain for
1541 backwards compatibility. */
1542 case '0': case '1': case '2': case '3': case '4':
1543 case '5': case '6': case '7': case '8': case '9':
1544 mangled = dlang_parse_integer (decl, mangled, type);
1545 break;
1547 /* Real value. */
1548 case 'e':
1549 mangled++;
1550 mangled = dlang_parse_real (decl, mangled);
1551 break;
1553 /* Complex value. */
1554 case 'c':
1555 mangled++;
1556 mangled = dlang_parse_real (decl, mangled);
1557 string_append (decl, "+");
1558 if (mangled == NULL || *mangled != 'c')
1559 return NULL;
1560 mangled++;
1561 mangled = dlang_parse_real (decl, mangled);
1562 string_append (decl, "i");
1563 break;
1565 /* String values. */
1566 case 'a': /* UTF8 */
1567 case 'w': /* UTF16 */
1568 case 'd': /* UTF32 */
1569 mangled = dlang_parse_string (decl, mangled);
1570 break;
1572 /* Array values. */
1573 case 'A':
1574 mangled++;
1575 if (type == 'H')
1576 mangled = dlang_parse_assocarray (decl, mangled, info);
1577 else
1578 mangled = dlang_parse_arrayliteral (decl, mangled, info);
1579 break;
1581 /* Struct values. */
1582 case 'S':
1583 mangled++;
1584 mangled = dlang_parse_structlit (decl, mangled, name, info);
1585 break;
1587 /* Function literal symbol. */
1588 case 'f':
1589 mangled++;
1590 if (strncmp (mangled, "_D", 2) != 0
1591 || !dlang_symbol_name_p (mangled + 2, info))
1592 return NULL;
1593 mangled = dlang_parse_mangle (decl, mangled, info);
1594 break;
1596 default:
1597 return NULL;
1600 return mangled;
1603 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1604 Returns the remaining signature on success or NULL on failure. */
1605 static const char *
1606 dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
1608 /* A D mangled symbol is comprised of both scope and type information.
1610 MangleName:
1611 _D QualifiedName Type
1612 _D QualifiedName Z
1614 The caller should have guaranteed that the start pointer is at the
1615 above location.
1616 Note that type is never a function type, but only the return type of
1617 a function or the type of a variable.
1619 mangled += 2;
1621 mangled = dlang_parse_qualified (decl, mangled, info, 1);
1623 if (mangled != NULL)
1625 /* Artificial symbols end with 'Z' and have no type. */
1626 if (*mangled == 'Z')
1627 mangled++;
1628 else
1630 /* Discard the declaration or return type. */
1631 string type;
1633 string_init (&type);
1634 mangled = dlang_type (&type, mangled, info);
1635 string_delete (&type);
1639 return mangled;
1642 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1643 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1644 Returns the remaining signature on success or NULL on failure. */
1645 static const char *
1646 dlang_parse_qualified (string *decl, const char *mangled,
1647 struct dlang_info *info, int suffix_modifiers)
1649 /* Qualified names are identifiers separated by their encoded length.
1650 Nested functions also encode their argument types without specifying
1651 what they return.
1653 QualifiedName:
1654 SymbolFunctionName
1655 SymbolFunctionName QualifiedName
1658 SymbolFunctionName:
1659 SymbolName
1660 SymbolName TypeFunctionNoReturn
1661 SymbolName M TypeFunctionNoReturn
1662 SymbolName M TypeModifiers TypeFunctionNoReturn
1664 The start pointer should be at the above location.
1666 size_t n = 0;
1669 /* Skip over anonymous symbols. */
1670 if (*mangled == '0')
1673 mangled++;
1674 while (*mangled == '0');
1676 continue;
1679 if (n++)
1680 string_append (decl, ".");
1682 mangled = dlang_identifier (decl, mangled, info);
1684 /* Consume the encoded arguments. However if this is not followed by the
1685 next encoded length or mangle type, then this is not a continuation of
1686 a qualified name, in which case we backtrack and return the current
1687 unconsumed position of the mangled decl. */
1688 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
1690 string mods;
1691 const char *start = mangled;
1692 int saved = string_length (decl);
1694 /* Save the type modifiers for appending at the end if needed. */
1695 string_init (&mods);
1697 /* Skip over 'this' parameter and type modifiers. */
1698 if (*mangled == 'M')
1700 mangled++;
1701 mangled = dlang_type_modifiers (&mods, mangled);
1702 string_setlength (decl, saved);
1705 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1706 mangled, info);
1707 if (suffix_modifiers)
1708 string_appendn (decl, mods.b, string_length (&mods));
1710 if (mangled == NULL || *mangled == '\0')
1712 /* Did not match the rule we were looking for. */
1713 mangled = start;
1714 string_setlength (decl, saved);
1717 string_delete (&mods);
1720 while (mangled && dlang_symbol_name_p (mangled, info));
1722 return mangled;
1725 /* Demangle the tuple from MANGLED and append it to DECL.
1726 Return the remaining string on success or NULL on failure. */
1727 static const char *
1728 dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
1730 unsigned long elements;
1732 mangled = dlang_number (mangled, &elements);
1733 if (mangled == NULL)
1734 return NULL;
1736 string_append (decl, "Tuple!(");
1738 while (elements--)
1740 mangled = dlang_type (decl, mangled, info);
1741 if (mangled == NULL)
1742 return NULL;
1744 if (elements != 0)
1745 string_append (decl, ", ");
1748 string_append (decl, ")");
1749 return mangled;
1752 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1753 Return the remaining string on success or NULL on failure. */
1754 static const char *
1755 dlang_template_symbol_param (string *decl, const char *mangled,
1756 struct dlang_info *info)
1758 if (strncmp (mangled, "_D", 2) == 0
1759 && dlang_symbol_name_p (mangled + 2, info))
1760 return dlang_parse_mangle (decl, mangled, info);
1762 if (*mangled == 'Q')
1763 return dlang_parse_qualified (decl, mangled, info, 0);
1765 unsigned long len;
1766 const char *endptr = dlang_number (mangled, &len);
1768 if (endptr == NULL || len == 0)
1769 return NULL;
1771 /* In template parameter symbols generated by the frontend up to 2.076,
1772 the symbol length is encoded and the first character of the mangled
1773 name can be a digit. This causes ambiguity issues because the digits
1774 of the two numbers are adjacent. */
1775 long psize = len;
1776 const char *pend;
1777 int saved = string_length (decl);
1779 /* Work backwards until a match is found. */
1780 for (pend = endptr; endptr != NULL; pend--)
1782 mangled = pend;
1784 /* Reached the beginning of the pointer to the name length,
1785 try parsing the entire symbol. */
1786 if (psize == 0)
1788 psize = len;
1789 pend = endptr;
1790 endptr = NULL;
1793 /* Check whether template parameter is a function with a valid
1794 return type or an untyped identifier. */
1795 if (dlang_symbol_name_p (mangled, info))
1796 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1797 else if (strncmp (mangled, "_D", 2) == 0
1798 && dlang_symbol_name_p (mangled + 2, info))
1799 mangled = dlang_parse_mangle (decl, mangled, info);
1801 /* Check for name length mismatch. */
1802 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1803 return mangled;
1805 psize /= 10;
1806 string_setlength (decl, saved);
1809 /* No match on any combinations. */
1810 return NULL;
1813 /* Demangle the argument list from MANGLED and append it to DECL.
1814 Return the remaining string on success or NULL on failure. */
1815 static const char *
1816 dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
1818 size_t n = 0;
1820 while (mangled && *mangled != '\0')
1822 switch (*mangled)
1824 case 'Z': /* End of parameter list. */
1825 mangled++;
1826 return mangled;
1829 if (n++)
1830 string_append (decl, ", ");
1832 /* Skip over specialised template prefix. */
1833 if (*mangled == 'H')
1834 mangled++;
1836 switch (*mangled)
1838 case 'S': /* Symbol parameter. */
1839 mangled++;
1840 mangled = dlang_template_symbol_param (decl, mangled, info);
1841 break;
1842 case 'T': /* Type parameter. */
1843 mangled++;
1844 mangled = dlang_type (decl, mangled, info);
1845 break;
1846 case 'V': /* Value parameter. */
1848 string name;
1849 char type;
1851 /* Peek at the type. */
1852 mangled++;
1853 type = *mangled;
1855 if (type == 'Q')
1857 /* Value type is a back reference, peek at the real type. */
1858 const char *backref;
1859 if (dlang_backref (mangled, &backref, info) == NULL)
1860 return NULL;
1862 type = *backref;
1865 /* In the few instances where the type is actually desired in
1866 the output, it should precede the value from dlang_value. */
1867 string_init (&name);
1868 mangled = dlang_type (&name, mangled, info);
1869 string_need (&name, 1);
1870 *(name.p) = '\0';
1872 mangled = dlang_value (decl, mangled, name.b, type, info);
1873 string_delete (&name);
1874 break;
1876 case 'X': /* Externally mangled parameter. */
1878 unsigned long len;
1879 const char *endptr;
1881 mangled++;
1882 endptr = dlang_number (mangled, &len);
1883 if (endptr == NULL || strlen (endptr) < len)
1884 return NULL;
1886 string_appendn (decl, endptr, len);
1887 mangled = endptr + len;
1888 break;
1890 default:
1891 return NULL;
1895 return mangled;
1898 /* Extract and demangle the template symbol in MANGLED, expected to
1899 be made up of LEN characters (-1 if unknown), and append it to DECL.
1900 Returns the remaining signature on success or NULL on failure. */
1901 static const char *
1902 dlang_parse_template (string *decl, const char *mangled,
1903 struct dlang_info *info, unsigned long len)
1905 const char *start = mangled;
1906 string args;
1908 /* Template instance names have the types and values of its parameters
1909 encoded into it.
1911 TemplateInstanceName:
1912 Number __T LName TemplateArgs Z
1913 Number __U LName TemplateArgs Z
1915 The start pointer should be at the above location, and LEN should be
1916 the value of the decoded number.
1919 /* Template symbol. */
1920 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
1921 return NULL;
1923 mangled += 3;
1925 /* Template identifier. */
1926 mangled = dlang_identifier (decl, mangled, info);
1928 /* Template arguments. */
1929 string_init (&args);
1930 mangled = dlang_template_args (&args, mangled, info);
1932 string_append (decl, "!(");
1933 string_appendn (decl, args.b, string_length (&args));
1934 string_append (decl, ")");
1936 string_delete (&args);
1938 /* Check for template name length mismatch. */
1939 if (len != TEMPLATE_LENGTH_UNKNOWN
1940 && mangled
1941 && (unsigned long) (mangled - start) != len)
1942 return NULL;
1944 return mangled;
1947 /* Initialize the information structure we use to pass around information. */
1948 static void
1949 dlang_demangle_init_info (const char *mangled, int last_backref,
1950 struct dlang_info *info)
1952 info->s = mangled;
1953 info->last_backref = last_backref;
1956 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1957 signature on success or NULL on failure. */
1959 char *
1960 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1962 string decl;
1963 char *demangled = NULL;
1965 if (mangled == NULL || *mangled == '\0')
1966 return NULL;
1968 if (strncmp (mangled, "_D", 2) != 0)
1969 return NULL;
1971 string_init (&decl);
1973 if (strcmp (mangled, "_Dmain") == 0)
1975 string_append (&decl, "D main");
1977 else
1979 struct dlang_info info;
1981 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1982 mangled = dlang_parse_mangle (&decl, mangled, &info);
1984 /* Check that the entire symbol was successfully demangled. */
1985 if (mangled == NULL || *mangled != '\0')
1986 string_delete (&decl);
1989 if (string_length (&decl) > 0)
1991 string_need (&decl, 1);
1992 *(decl.p) = '\0';
1993 demangled = decl.b;
1996 return demangled;