1 /* Demangler for the D programming language
2 Copyright (C) 2014-2019 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
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. */
35 #include "safe-ctype.h"
37 #include <sys/types.h>
46 #include "libiberty.h"
48 /* A mini string-handling package */
50 typedef struct string
/* Beware: these aren't required to be */
51 { /* '\0' terminated. */
52 char *b
; /* pointer to start of string */
53 char *p
; /* pointer after last character */
54 char *e
; /* pointer after end of allocated space */
58 string_need (string
*s
, int n
)
68 s
->p
= s
->b
= XNEWVEC (char, n
);
71 else if (s
->e
- s
->p
< n
)
76 s
->b
= XRESIZEVEC (char, s
->b
, n
);
83 string_delete (string
*s
)
88 s
->b
= s
->e
= s
->p
= NULL
;
93 string_init (string
*s
)
95 s
->b
= s
->p
= s
->e
= NULL
;
99 string_length (string
*s
)
109 string_setlength (string
*s
, int n
)
111 if (n
- string_length (s
) < 0)
118 string_append (string
*p
, const char *s
)
127 string_appendn (string
*p
, const char *s
, int n
)
138 string_prependn (string
*p
, const char *s
, int n
)
145 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
155 string_prepend (string
*p
, const char *s
)
157 if (s
!= NULL
&& *s
!= '\0')
159 string_prependn (p
, s
, strlen (s
));
163 /* What kinds of symbol we could be parsing. */
164 enum dlang_symbol_kinds
166 /* Top-level symbol, needs it's type checked. */
168 /* Function symbol, needs it's type checked. */
170 /* Strongly typed name, such as for classes, structs and enums. */
172 /* Template identifier. */
173 dlang_template_ident
,
174 /* Template symbol parameter. */
178 /* Prototypes for forward referenced functions */
179 static const char *dlang_function_args (string
*, const char *);
181 static const char *dlang_type (string
*, const char *);
183 static const char *dlang_value (string
*, const char *, const char *, char);
185 static const char *dlang_parse_qualified (string
*, const char *,
186 enum dlang_symbol_kinds
);
188 static const char *dlang_parse_mangle (string
*, const char *,
189 enum dlang_symbol_kinds
);
191 static const char *dlang_parse_tuple (string
*, const char *);
193 static const char *dlang_parse_template (string
*, const char *, long);
196 /* Extract the number from MANGLED, and assign the result to RET.
197 Return the remaining string on success or NULL on failure. */
199 dlang_number (const char *mangled
, long *ret
)
201 /* Return NULL if trying to extract something that isn't a digit. */
202 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
207 while (ISDIGIT (*mangled
))
211 /* If an overflow occured when multiplying by ten, the result
212 will not be a multiple of ten. */
213 if ((*ret
% 10) != 0)
216 (*ret
) += mangled
[0] - '0';
220 if (*mangled
== '\0' || *ret
< 0)
226 /* Extract the hex-digit from MANGLED, and assign the result to RET.
227 Return the remaining string on success or NULL on failure. */
229 dlang_hexdigit (const char *mangled
, char *ret
)
233 /* Return NULL if trying to extract something that isn't a hexdigit. */
234 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
239 (*ret
) = (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
245 (*ret
) = (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
247 (*ret
) = (*ret
<< 4) | (c
- '0');
254 /* Extract the function calling convention from MANGLED and
255 return 1 on success or 0 on failure. */
257 dlang_call_convention_p (const char *mangled
)
261 case 'F': case 'U': case 'V':
262 case 'W': case 'R': case 'Y':
270 /* Demangle the calling convention from MANGLED and append it to DECL.
271 Return the remaining string on success or NULL on failure. */
273 dlang_call_convention (string
*decl
, const char *mangled
)
275 if (mangled
== NULL
|| *mangled
== '\0')
285 string_append (decl
, "extern(C) ");
287 case 'W': /* (Windows) */
289 string_append (decl
, "extern(Windows) ");
291 case 'V': /* (Pascal) */
293 string_append (decl
, "extern(Pascal) ");
295 case 'R': /* (C++) */
297 string_append (decl
, "extern(C++) ");
299 case 'Y': /* (Objective-C) */
301 string_append (decl
, "extern(Objective-C) ");
310 /* Extract the type modifiers from MANGLED and append them to DECL.
311 Returns the remaining signature on success or NULL on failure. */
313 dlang_type_modifiers (string
*decl
, const char *mangled
)
315 if (mangled
== NULL
|| *mangled
== '\0')
320 case 'x': /* const */
322 string_append (decl
, " const");
324 case 'y': /* immutable */
326 string_append (decl
, " immutable");
328 case 'O': /* shared */
330 string_append (decl
, " shared");
331 return dlang_type_modifiers (decl
, mangled
);
334 if (*mangled
== 'g') /* wild */
337 string_append (decl
, " inout");
338 return dlang_type_modifiers (decl
, mangled
);
348 /* Demangle the D function attributes from MANGLED and append it to DECL.
349 Return the remaining string on success or NULL on failure. */
351 dlang_attributes (string
*decl
, const char *mangled
)
353 if (mangled
== NULL
|| *mangled
== '\0')
356 while (*mangled
== 'N')
363 string_append (decl
, "pure ");
365 case 'b': /* nothrow */
367 string_append (decl
, "nothrow ");
371 string_append (decl
, "ref ");
373 case 'd': /* @property */
375 string_append (decl
, "@property ");
377 case 'e': /* @trusted */
379 string_append (decl
, "@trusted ");
381 case 'f': /* @safe */
383 string_append (decl
, "@safe ");
388 /* inout parameter is represented as 'Ng'.
389 vector parameter is represented as 'Nh'.
390 return paramenter is represented as 'Nk'.
391 If we see this, then we know we're really in the
392 parameter list. Rewind and break. */
395 case 'i': /* @nogc */
397 string_append (decl
, "@nogc ");
399 case 'j': /* return */
401 string_append (decl
, "return ");
403 case 'l': /* scope */
405 string_append (decl
, "scope ");
408 default: /* unknown attribute */
417 /* Demangle the function type from MANGLED and append it to DECL.
418 Return the remaining string on success or NULL on failure. */
420 dlang_function_type (string
*decl
, const char *mangled
)
422 string attr
, args
, type
;
423 size_t szattr
, szargs
, sztype
;
425 if (mangled
== NULL
|| *mangled
== '\0')
428 /* The order of the mangled string is:
429 CallConvention FuncAttrs Arguments ArgClose Type
431 The demangled string is re-ordered as:
432 CallConvention Type Arguments FuncAttrs
438 /* Function call convention. */
439 mangled
= dlang_call_convention (decl
, mangled
);
441 /* Function attributes. */
442 mangled
= dlang_attributes (&attr
, mangled
);
443 szattr
= string_length (&attr
);
445 /* Function arguments. */
446 mangled
= dlang_function_args (&args
, mangled
);
447 szargs
= string_length (&args
);
449 /* Function return type. */
450 mangled
= dlang_type (&type
, mangled
);
451 sztype
= string_length (&type
);
453 /* Append to decl in order. */
454 string_appendn (decl
, type
.b
, sztype
);
455 string_append (decl
, "(");
456 string_appendn (decl
, args
.b
, szargs
);
457 string_append (decl
, ") ");
458 string_appendn (decl
, attr
.b
, szattr
);
460 string_delete (&attr
);
461 string_delete (&args
);
462 string_delete (&type
);
466 /* Demangle the argument list from MANGLED and append it to DECL.
467 Return the remaining string on success or NULL on failure. */
469 dlang_function_args (string
*decl
, const char *mangled
)
473 while (mangled
&& *mangled
!= '\0')
477 case 'X': /* (variadic T t...) style. */
479 string_append (decl
, "...");
481 case 'Y': /* (variadic T t, ...) style. */
484 string_append (decl
, ", ");
485 string_append (decl
, "...");
487 case 'Z': /* Normal function. */
493 string_append (decl
, ", ");
495 if (*mangled
== 'M') /* scope(T) */
498 string_append (decl
, "scope ");
501 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
504 string_append (decl
, "return ");
509 case 'J': /* out(T) */
511 string_append (decl
, "out ");
513 case 'K': /* ref(T) */
515 string_append (decl
, "ref ");
517 case 'L': /* lazy(T) */
519 string_append (decl
, "lazy ");
522 mangled
= dlang_type (decl
, mangled
);
528 /* Demangle the type from MANGLED and append it to DECL.
529 Return the remaining string on success or NULL on failure. */
531 dlang_type (string
*decl
, const char *mangled
)
533 if (mangled
== NULL
|| *mangled
== '\0')
538 case 'O': /* shared(T) */
540 string_append (decl
, "shared(");
541 mangled
= dlang_type (decl
, mangled
);
542 string_append (decl
, ")");
544 case 'x': /* const(T) */
546 string_append (decl
, "const(");
547 mangled
= dlang_type (decl
, mangled
);
548 string_append (decl
, ")");
550 case 'y': /* immutable(T) */
552 string_append (decl
, "immutable(");
553 mangled
= dlang_type (decl
, mangled
);
554 string_append (decl
, ")");
558 if (*mangled
== 'g') /* wild(T) */
561 string_append (decl
, "inout(");
562 mangled
= dlang_type (decl
, mangled
);
563 string_append (decl
, ")");
566 else if (*mangled
== 'h') /* vector(T) */
569 string_append (decl
, "__vector(");
570 mangled
= dlang_type (decl
, mangled
);
571 string_append (decl
, ")");
576 case 'A': /* dynamic array (T[]) */
578 mangled
= dlang_type (decl
, mangled
);
579 string_append (decl
, "[]");
581 case 'G': /* static array (T[N]) */
588 while (ISDIGIT (*mangled
))
593 mangled
= dlang_type (decl
, mangled
);
594 string_append (decl
, "[");
595 string_appendn (decl
, numptr
, num
);
596 string_append (decl
, "]");
599 case 'H': /* associative array (T[T]) */
606 mangled
= dlang_type (&type
, mangled
);
607 sztype
= string_length (&type
);
609 mangled
= dlang_type (decl
, mangled
);
610 string_append (decl
, "[");
611 string_appendn (decl
, type
.b
, sztype
);
612 string_append (decl
, "]");
614 string_delete (&type
);
617 case 'P': /* pointer (T*) */
619 if (!dlang_call_convention_p (mangled
))
621 mangled
= dlang_type (decl
, mangled
);
622 string_append (decl
, "*");
626 case 'F': /* function T (D) */
627 case 'U': /* function T (C) */
628 case 'W': /* function T (Windows) */
629 case 'V': /* function T (Pascal) */
630 case 'R': /* function T (C++) */
631 case 'Y': /* function T (Objective-C) */
632 /* Function pointer types don't include the trailing asterisk. */
633 mangled
= dlang_function_type (decl
, mangled
);
634 string_append (decl
, "function");
636 case 'I': /* ident T */
637 case 'C': /* class T */
638 case 'S': /* struct T */
639 case 'E': /* enum T */
640 case 'T': /* typedef T */
642 return dlang_parse_qualified (decl
, mangled
, dlang_type_name
);
643 case 'D': /* delegate T */
650 mangled
= dlang_type_modifiers (&mods
, mangled
);
651 szmods
= string_length (&mods
);
653 mangled
= dlang_function_type (decl
, mangled
);
654 string_append (decl
, "delegate");
655 string_appendn (decl
, mods
.b
, szmods
);
657 string_delete (&mods
);
660 case 'B': /* tuple T */
662 return dlang_parse_tuple (decl
, mangled
);
667 string_append (decl
, "none");
671 string_append (decl
, "void");
675 string_append (decl
, "byte");
679 string_append (decl
, "ubyte");
683 string_append (decl
, "short");
687 string_append (decl
, "ushort");
691 string_append (decl
, "int");
695 string_append (decl
, "uint");
699 string_append (decl
, "long");
703 string_append (decl
, "ulong");
707 string_append (decl
, "float");
711 string_append (decl
, "double");
715 string_append (decl
, "real");
718 /* Imaginary and Complex types */
721 string_append (decl
, "ifloat");
725 string_append (decl
, "idouble");
729 string_append (decl
, "ireal");
733 string_append (decl
, "cfloat");
737 string_append (decl
, "cdouble");
741 string_append (decl
, "creal");
747 string_append (decl
, "bool");
751 string_append (decl
, "char");
755 string_append (decl
, "wchar");
759 string_append (decl
, "dchar");
767 string_append (decl
, "cent");
771 string_append (decl
, "ucent");
776 default: /* unhandled */
781 /* Extract the identifier from MANGLED and append it to DECL.
782 Return the remaining string on success or NULL on failure. */
784 dlang_identifier (string
*decl
, const char *mangled
,
785 enum dlang_symbol_kinds kind
)
788 const char *endptr
= dlang_number (mangled
, &len
);
790 if (endptr
== NULL
|| len
== 0)
793 /* In template parameter symbols, the first character of the mangled
794 name can be a digit. This causes ambiguity issues because the
795 digits of the two numbers are adjacent. */
796 if (kind
== dlang_template_param
)
800 int saved
= string_length (decl
);
802 /* Work backwards until a match is found. */
803 for (pend
= endptr
; endptr
!= NULL
; pend
--)
807 /* Reached the beginning of the pointer to the name length,
808 try parsing the entire symbol. */
816 /* Check whether template parameter is a function with a valid
817 return type or an untyped identifier. */
818 if (ISDIGIT (*mangled
))
819 mangled
= dlang_parse_qualified (decl
, mangled
,
820 dlang_template_ident
);
821 else if (strncmp (mangled
, "_D", 2) == 0)
822 mangled
= dlang_parse_mangle (decl
, mangled
, dlang_function
);
824 /* Check for name length mismatch. */
825 if (mangled
&& (mangled
- pend
) == psize
)
829 string_setlength (decl
, saved
);
832 /* No match on any combinations. */
837 if (strlen (endptr
) < (size_t) len
)
842 /* May be a template instance. */
843 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
844 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
845 return dlang_parse_template (decl
, mangled
, len
);
850 if (strncmp (mangled
, "__ctor", len
) == 0)
852 /* Constructor symbol for a class/struct. */
853 string_append (decl
, "this");
857 else if (strncmp (mangled
, "__dtor", len
) == 0)
859 /* Destructor symbol for a class/struct. */
860 string_append (decl
, "~this");
864 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
866 /* The static initialiser for a given symbol. */
867 string_prepend (decl
, "initializer for ");
868 string_setlength (decl
, string_length (decl
) - 1);
872 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
874 /* The vtable symbol for a given class. */
875 string_prepend (decl
, "vtable for ");
876 string_setlength (decl
, string_length (decl
) - 1);
883 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
885 /* The classinfo symbol for a given class. */
886 string_prepend (decl
, "ClassInfo for ");
887 string_setlength (decl
, string_length (decl
) - 1);
894 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
896 /* Postblit symbol for a struct. */
897 string_append (decl
, "this(this)");
904 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
906 /* The interface symbol for a given class. */
907 string_prepend (decl
, "Interface for ");
908 string_setlength (decl
, string_length (decl
) - 1);
915 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
917 /* The ModuleInfo symbol for a given module. */
918 string_prepend (decl
, "ModuleInfo for ");
919 string_setlength (decl
, string_length (decl
) - 1);
926 string_appendn (decl
, mangled
, len
);
933 /* Extract the integer value from MANGLED and append it to DECL,
934 where TYPE is the type it should be represented as.
935 Return the remaining string on success or NULL on failure. */
937 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
939 if (type
== 'a' || type
== 'u' || type
== 'w')
941 /* Parse character value. */
943 int pos
= sizeof(value
);
947 mangled
= dlang_number (mangled
, &val
);
951 string_append (decl
, "'");
953 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
955 /* Represent as a character literal. */
957 string_appendn (decl
, &c
, 1);
961 /* Represent as a hexadecimal value. */
965 string_append (decl
, "\\x");
968 case 'u': /* wchar */
969 string_append (decl
, "\\u");
972 case 'w': /* dchar */
973 string_append (decl
, "\\U");
980 int digit
= val
% 16;
983 value
[--pos
] = (char)(digit
+ '0');
985 value
[--pos
] = (char)((digit
- 10) + 'a');
991 for (; width
> 0; width
--)
994 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
996 string_append (decl
, "'");
998 else if (type
== 'b')
1000 /* Parse boolean value. */
1003 mangled
= dlang_number (mangled
, &val
);
1004 if (mangled
== NULL
)
1007 string_append (decl
, val
? "true" : "false");
1011 /* Parse integer value. */
1012 const char *numptr
= mangled
;
1015 if (! ISDIGIT (*mangled
))
1018 while (ISDIGIT (*mangled
))
1023 string_appendn (decl
, numptr
, num
);
1025 /* Append suffix. */
1028 case 'h': /* ubyte */
1029 case 't': /* ushort */
1030 case 'k': /* uint */
1031 string_append (decl
, "u");
1033 case 'l': /* long */
1034 string_append (decl
, "L");
1036 case 'm': /* ulong */
1037 string_append (decl
, "uL");
1045 /* Extract the floating-point value from MANGLED and append it to DECL.
1046 Return the remaining string on success or NULL on failure. */
1048 dlang_parse_real (string
*decl
, const char *mangled
)
1050 /* Handle NAN and +-INF. */
1051 if (strncmp (mangled
, "NAN", 3) == 0)
1053 string_append (decl
, "NaN");
1057 else if (strncmp (mangled
, "INF", 3) == 0)
1059 string_append (decl
, "Inf");
1063 else if (strncmp (mangled
, "NINF", 4) == 0)
1065 string_append (decl
, "-Inf");
1070 /* Hexadecimal prefix and leading bit. */
1071 if (*mangled
== 'N')
1073 string_append (decl
, "-");
1077 if (!ISXDIGIT (*mangled
))
1080 string_append (decl
, "0x");
1081 string_appendn (decl
, mangled
, 1);
1082 string_append (decl
, ".");
1086 while (ISXDIGIT (*mangled
))
1088 string_appendn (decl
, mangled
, 1);
1093 if (*mangled
!= 'P')
1096 string_append (decl
, "p");
1099 if (*mangled
== 'N')
1101 string_append (decl
, "-");
1105 while (ISDIGIT (*mangled
))
1107 string_appendn (decl
, mangled
, 1);
1114 /* Extract the string value from MANGLED and append it to DECL.
1115 Return the remaining string on success or NULL on failure. */
1117 dlang_parse_string (string
*decl
, const char *mangled
)
1119 char type
= *mangled
;
1123 mangled
= dlang_number (mangled
, &len
);
1124 if (mangled
== NULL
|| *mangled
!= '_')
1128 string_append (decl
, "\"");
1132 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1137 /* Sanitize white and non-printable characters. */
1141 string_append (decl
, " ");
1144 string_append (decl
, "\\t");
1147 string_append (decl
, "\\n");
1150 string_append (decl
, "\\r");
1153 string_append (decl
, "\\f");
1156 string_append (decl
, "\\v");
1161 string_appendn (decl
, &val
, 1);
1164 string_append (decl
, "\\x");
1165 string_appendn (decl
, mangled
, 2);
1171 string_append (decl
, "\"");
1174 string_appendn (decl
, &type
, 1);
1179 /* Extract the static array value from MANGLED and append it to DECL.
1180 Return the remaining string on success or NULL on failure. */
1182 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1186 mangled
= dlang_number (mangled
, &elements
);
1187 if (mangled
== NULL
)
1190 string_append (decl
, "[");
1193 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1194 if (mangled
== NULL
)
1198 string_append (decl
, ", ");
1201 string_append (decl
, "]");
1205 /* Extract the associative array value from MANGLED and append it to DECL.
1206 Return the remaining string on success or NULL on failure. */
1208 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1212 mangled
= dlang_number (mangled
, &elements
);
1213 if (mangled
== NULL
)
1216 string_append (decl
, "[");
1219 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1220 if (mangled
== NULL
)
1223 string_append (decl
, ":");
1224 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1225 if (mangled
== NULL
)
1229 string_append (decl
, ", ");
1232 string_append (decl
, "]");
1236 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1237 Return the remaining string on success or NULL on failure. */
1239 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1243 mangled
= dlang_number (mangled
, &args
);
1244 if (mangled
== NULL
)
1248 string_append (decl
, name
);
1250 string_append (decl
, "(");
1253 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1254 if (mangled
== NULL
)
1258 string_append (decl
, ", ");
1261 string_append (decl
, ")");
1265 /* Extract the value from MANGLED and append it to DECL.
1266 Return the remaining string on success or NULL on failure. */
1268 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1270 if (mangled
== NULL
|| *mangled
== '\0')
1278 string_append (decl
, "null");
1281 /* Integral values. */
1284 string_append (decl
, "-");
1285 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1292 /* There really should always be an `i' before encoded numbers, but there
1293 wasn't in early versions of D2, so this case range must remain for
1294 backwards compatibility. */
1295 case '0': case '1': case '2': case '3': case '4':
1296 case '5': case '6': case '7': case '8': case '9':
1297 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1303 mangled
= dlang_parse_real (decl
, mangled
);
1306 /* Complex value. */
1309 mangled
= dlang_parse_real (decl
, mangled
);
1310 string_append (decl
, "+");
1311 if (mangled
== NULL
|| *mangled
!= 'c')
1314 mangled
= dlang_parse_real (decl
, mangled
);
1315 string_append (decl
, "i");
1318 /* String values. */
1319 case 'a': /* UTF8 */
1320 case 'w': /* UTF16 */
1321 case 'd': /* UTF32 */
1322 mangled
= dlang_parse_string (decl
, mangled
);
1329 mangled
= dlang_parse_assocarray (decl
, mangled
);
1331 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1334 /* Struct values. */
1337 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1347 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1348 Returns the remaining signature on success or NULL on failure. */
1350 dlang_parse_mangle (string
*decl
, const char *mangled
,
1351 enum dlang_symbol_kinds kind
)
1353 /* A D mangled symbol is comprised of both scope and type information.
1356 _D QualifiedName Type
1357 _D QualifiedName M Type
1360 The caller should have guaranteed that the start pointer is at the
1365 mangled
= dlang_parse_qualified (decl
, mangled
, dlang_top_level
);
1367 if (mangled
!= NULL
)
1369 /* Artificial symbols end with 'Z' and have no type. */
1370 if (*mangled
== 'Z')
1377 /* Skip over 'this' parameter. */
1378 if (*mangled
== 'M')
1381 /* Save the type modifiers for appending at the end if needed. */
1382 string_init (&mods
);
1383 mangled
= dlang_type_modifiers (&mods
, mangled
);
1385 if (mangled
&& dlang_call_convention_p (mangled
))
1387 /* Skip over calling convention and attributes. */
1388 saved
= string_length (decl
);
1389 mangled
= dlang_call_convention (decl
, mangled
);
1390 mangled
= dlang_attributes (decl
, mangled
);
1391 string_setlength (decl
, saved
);
1393 string_append (decl
, "(");
1394 mangled
= dlang_function_args (decl
, mangled
);
1395 string_append (decl
, ")");
1397 /* Add any const/immutable/shared modifier. */
1398 string_appendn (decl
, mods
.b
, string_length (&mods
));
1401 /* Consume the decl type of symbol. */
1402 saved
= string_length (decl
);
1403 mangled
= dlang_type (decl
, mangled
);
1404 string_setlength (decl
, saved
);
1406 string_delete (&mods
);
1410 /* Check that the entire symbol was successfully demangled. */
1411 if (kind
== dlang_top_level
)
1413 if (mangled
== NULL
|| *mangled
!= '\0')
1420 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1421 Returns the remaining signature on success or NULL on failure. */
1423 dlang_parse_qualified (string
*decl
, const char *mangled
,
1424 enum dlang_symbol_kinds kind
)
1426 /* Qualified names are identifiers separated by their encoded length.
1427 Nested functions also encode their argument types without specifying
1432 SymbolName QualifiedName
1433 SymbolName TypeFunctionNoReturn QualifiedName
1434 SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
1436 The start pointer should be at the above location.
1442 string_append (decl
, ".");
1444 /* Skip over anonymous symbols. */
1445 while (*mangled
== '0')
1448 mangled
= dlang_identifier (decl
, mangled
, kind
);
1450 /* Consume the encoded arguments. However if this is not followed by the
1451 next encoded length, then this is not a continuation of a qualified
1452 name, in which case we backtrack and return the current unconsumed
1453 position of the mangled decl. */
1454 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1456 const char *start
= mangled
;
1457 int saved
= string_length (decl
);
1459 /* Skip over 'this' parameter and type modifiers. */
1460 if (*mangled
== 'M')
1463 mangled
= dlang_type_modifiers (decl
, mangled
);
1464 string_setlength (decl
, saved
);
1467 /* The rule we expect to match in the mangled string is:
1469 TypeFunctionNoReturn:
1470 CallConvention FuncAttrs Arguments ArgClose
1472 The calling convention and function attributes are not included
1473 in the demangled string. */
1474 mangled
= dlang_call_convention (decl
, mangled
);
1475 mangled
= dlang_attributes (decl
, mangled
);
1476 string_setlength (decl
, saved
);
1478 string_append (decl
, "(");
1479 mangled
= dlang_function_args (decl
, mangled
);
1480 string_append (decl
, ")");
1482 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
1484 /* Did not match the rule we were looking for. */
1486 string_setlength (decl
, saved
);
1490 while (mangled
&& ISDIGIT (*mangled
));
1495 /* Demangle the tuple from MANGLED and append it to DECL.
1496 Return the remaining string on success or NULL on failure. */
1498 dlang_parse_tuple (string
*decl
, const char *mangled
)
1502 mangled
= dlang_number (mangled
, &elements
);
1503 if (mangled
== NULL
)
1506 string_append (decl
, "Tuple!(");
1510 mangled
= dlang_type (decl
, mangled
);
1511 if (mangled
== NULL
)
1515 string_append (decl
, ", ");
1518 string_append (decl
, ")");
1522 /* Demangle the argument list from MANGLED and append it to DECL.
1523 Return the remaining string on success or NULL on failure. */
1525 dlang_template_args (string
*decl
, const char *mangled
)
1529 while (mangled
&& *mangled
!= '\0')
1533 case 'Z': /* End of parameter list. */
1539 string_append (decl
, ", ");
1541 /* Skip over specialised template prefix. */
1542 if (*mangled
== 'H')
1547 case 'S': /* Symbol parameter. */
1549 mangled
= dlang_identifier (decl
, mangled
, dlang_template_param
);
1551 case 'T': /* Type parameter. */
1553 mangled
= dlang_type (decl
, mangled
);
1555 case 'V': /* Value parameter. */
1560 /* Peek at the type. */
1564 /* In the few instances where the type is actually desired in
1565 the output, it should precede the value from dlang_value. */
1566 string_init (&name
);
1567 mangled
= dlang_type (&name
, mangled
);
1568 string_need (&name
, 1);
1571 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1572 string_delete (&name
);
1584 /* Extract and demangle the template symbol in MANGLED, expected to
1585 be made up of LEN characters, and append it to DECL.
1586 Returns the remaining signature on success or NULL on failure. */
1588 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1590 const char *start
= mangled
;
1592 /* Template instance names have the types and values of its parameters
1595 TemplateInstanceName:
1596 Number __T LName TemplateArgs Z
1597 Number __U LName TemplateArgs Z
1599 The start pointer should be at the above location, and LEN should be
1600 the value of the decoded number.
1603 /* Template symbol. */
1604 if (!ISDIGIT (mangled
[3]) || mangled
[3] == '0')
1609 /* Template identifier. */
1610 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1612 /* Template arguments. */
1613 string_append (decl
, "!(");
1614 mangled
= dlang_template_args (decl
, mangled
);
1615 string_append (decl
, ")");
1617 /* Check for template name length mismatch. */
1618 if (mangled
&& (mangled
- start
) != len
)
1624 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1625 signature on success or NULL on failure. */
1628 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1631 char *demangled
= NULL
;
1633 if (mangled
== NULL
|| *mangled
== '\0')
1636 if (strncmp (mangled
, "_D", 2) != 0)
1639 string_init (&decl
);
1641 if (strcmp (mangled
, "_Dmain") == 0)
1643 string_append (&decl
, "D main");
1647 if (dlang_parse_mangle (&decl
, mangled
, dlang_top_level
) == NULL
)
1648 string_delete (&decl
);
1651 if (string_length (&decl
) > 0)
1653 string_need (&decl
, 1);