1 /* Demangler for the D programming language
2 Copyright 2014, 2015 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.
31 This file imports strtol and strtod for decoding mangled literals. */
37 #include "safe-ctype.h"
39 #include <sys/types.h>
46 extern long strtol (const char *nptr
, char **endptr
, int base
);
47 extern double strtod (const char *nptr
, char **endptr
);
51 #include "libiberty.h"
53 /* A mini string-handling package */
55 typedef struct string
/* Beware: these aren't required to be */
56 { /* '\0' terminated. */
57 char *b
; /* pointer to start of string */
58 char *p
; /* pointer after last character */
59 char *e
; /* pointer after end of allocated space */
63 string_need (string
*s
, int n
)
73 s
->p
= s
->b
= XNEWVEC (char, n
);
76 else if (s
->e
- s
->p
< n
)
81 s
->b
= XRESIZEVEC (char, s
->b
, n
);
88 string_delete (string
*s
)
93 s
->b
= s
->e
= s
->p
= NULL
;
98 string_init (string
*s
)
100 s
->b
= s
->p
= s
->e
= NULL
;
104 string_length (string
*s
)
114 string_setlength (string
*s
, int n
)
116 if (n
- string_length (s
) < 0)
123 string_append (string
*p
, const char *s
)
132 string_appendn (string
*p
, const char *s
, int n
)
143 string_prependn (string
*p
, const char *s
, int n
)
150 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
160 string_prepend (string
*p
, const char *s
)
162 if (s
!= NULL
&& *s
!= '\0')
164 string_prependn (p
, s
, strlen (s
));
168 /* What kinds of symbol we could be parsing. */
169 enum dlang_symbol_kinds
171 /* Top-level symbol, needs it's type checked. */
173 /* Function symbol, needs it's type checked. */
175 /* Strongly typed name, such as for classes, structs and enums. */
177 /* Template identifier. */
178 dlang_template_ident
,
179 /* Template symbol parameter. */
183 /* Prototypes for forward referenced functions */
184 static const char *dlang_function_args (string
*, const char *);
186 static const char *dlang_type (string
*, const char *);
188 static const char *dlang_value (string
*, const char *, const char *, char);
190 static const char *dlang_parse_symbol (string
*, const char *,
191 enum dlang_symbol_kinds
);
193 static const char *dlang_parse_tuple (string
*, const char *);
195 static const char *dlang_parse_template (string
*, const char *, long);
198 /* Demangle the calling convention from MANGLED and append it to DECL.
199 Return the remaining string on success or NULL on failure. */
201 dlang_call_convention (string
*decl
, const char *mangled
)
203 if (mangled
== NULL
|| *mangled
== '\0')
213 string_append (decl
, "extern(C) ");
215 case 'W': /* (Windows) */
217 string_append (decl
, "extern(Windows) ");
219 case 'V': /* (Pascal) */
221 string_append (decl
, "extern(Pascal) ");
223 case 'R': /* (C++) */
225 string_append (decl
, "extern(C++) ");
234 /* Extract the type modifiers from MANGLED and append them to DECL.
235 Returns the remaining signature on success or NULL on failure. */
237 dlang_type_modifiers (string
*decl
, const char *mangled
)
239 if (mangled
== NULL
|| *mangled
== '\0')
244 case 'x': /* const */
246 string_append (decl
, " const");
248 case 'y': /* immutable */
250 string_append (decl
, " immutable");
252 case 'O': /* shared */
254 string_append (decl
, " shared");
255 return dlang_type_modifiers (decl
, mangled
);
258 if (*mangled
== 'g') /* wild */
261 string_append (decl
, " inout");
262 return dlang_type_modifiers (decl
, mangled
);
272 /* Demangle the D function attributes from MANGLED and append it to DECL.
273 Return the remaining string on success or NULL on failure. */
275 dlang_attributes (string
*decl
, const char *mangled
)
277 if (mangled
== NULL
|| *mangled
== '\0')
280 while (*mangled
== 'N')
287 string_append (decl
, "pure ");
289 case 'b': /* nothrow */
291 string_append (decl
, "nothrow ");
295 string_append (decl
, "ref ");
297 case 'd': /* @property */
299 string_append (decl
, "@property ");
301 case 'e': /* @trusted */
303 string_append (decl
, "@trusted ");
305 case 'f': /* @safe */
307 string_append (decl
, "@safe ");
312 /* inout parameter is represented as 'Ng'.
313 vector parameter is represented as 'Nh'.
314 return paramenter is represented as 'Nk'.
315 If we see this, then we know we're really in the
316 parameter list. Rewind and break. */
319 case 'i': /* @nogc */
321 string_append (decl
, "@nogc ");
323 case 'j': /* return */
325 string_append (decl
, "return ");
328 default: /* unknown attribute */
337 /* Demangle the function type from MANGLED and append it to DECL.
338 Return the remaining string on success or NULL on failure. */
340 dlang_function_type (string
*decl
, const char *mangled
)
342 string attr
, args
, type
;
343 size_t szattr
, szargs
, sztype
;
345 if (mangled
== NULL
|| *mangled
== '\0')
348 /* The order of the mangled string is:
349 CallConvention FuncAttrs Arguments ArgClose Type
351 The demangled string is re-ordered as:
352 CallConvention Type Arguments FuncAttrs
358 /* Function call convention. */
359 mangled
= dlang_call_convention (decl
, mangled
);
361 /* Function attributes. */
362 mangled
= dlang_attributes (&attr
, mangled
);
363 szattr
= string_length (&attr
);
365 /* Function arguments. */
366 mangled
= dlang_function_args (&args
, mangled
);
367 szargs
= string_length (&args
);
369 /* Function return type. */
370 mangled
= dlang_type (&type
, mangled
);
371 sztype
= string_length (&type
);
373 /* Append to decl in order. */
374 string_appendn (decl
, type
.b
, sztype
);
375 string_append (decl
, "(");
376 string_appendn (decl
, args
.b
, szargs
);
377 string_append (decl
, ") ");
378 string_appendn (decl
, attr
.b
, szattr
);
380 string_delete (&attr
);
381 string_delete (&args
);
382 string_delete (&type
);
386 /* Demangle the argument list from MANGLED and append it to DECL.
387 Return the remaining string on success or NULL on failure. */
389 dlang_function_args (string
*decl
, const char *mangled
)
393 while (mangled
&& *mangled
!= '\0')
397 case 'X': /* (variadic T t...) style. */
399 string_append (decl
, "...");
401 case 'Y': /* (variadic T t, ...) style. */
403 string_append (decl
, ", ...");
405 case 'Z': /* Normal function. */
411 string_append (decl
, ", ");
413 if (*mangled
== 'M') /* scope(T) */
416 string_append (decl
, "scope ");
419 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
422 string_append (decl
, "return ");
427 case 'J': /* out(T) */
429 string_append (decl
, "out ");
431 case 'K': /* ref(T) */
433 string_append (decl
, "ref ");
435 case 'L': /* lazy(T) */
437 string_append (decl
, "lazy ");
440 mangled
= dlang_type (decl
, mangled
);
446 /* Demangle the type from MANGLED and append it to DECL.
447 Return the remaining string on success or NULL on failure. */
449 dlang_type (string
*decl
, const char *mangled
)
451 if (mangled
== NULL
|| *mangled
== '\0')
456 case 'O': /* shared(T) */
458 string_append (decl
, "shared(");
459 mangled
= dlang_type (decl
, mangled
);
460 string_append (decl
, ")");
462 case 'x': /* const(T) */
464 string_append (decl
, "const(");
465 mangled
= dlang_type (decl
, mangled
);
466 string_append (decl
, ")");
468 case 'y': /* immutable(T) */
470 string_append (decl
, "immutable(");
471 mangled
= dlang_type (decl
, mangled
);
472 string_append (decl
, ")");
476 if (*mangled
== 'g') /* wild(T) */
479 string_append (decl
, "inout(");
480 mangled
= dlang_type (decl
, mangled
);
481 string_append (decl
, ")");
484 else if (*mangled
== 'h') /* vector(T) */
487 string_append (decl
, "__vector(");
488 mangled
= dlang_type (decl
, mangled
);
489 string_append (decl
, ")");
494 case 'A': /* dynamic array (T[]) */
496 mangled
= dlang_type (decl
, mangled
);
497 string_append (decl
, "[]");
499 case 'G': /* static array (T[N]) */
506 while (ISDIGIT (*mangled
))
511 mangled
= dlang_type (decl
, mangled
);
512 string_append (decl
, "[");
513 string_appendn (decl
, numptr
, num
);
514 string_append (decl
, "]");
517 case 'H': /* associative array (T[T]) */
524 mangled
= dlang_type (&type
, mangled
);
525 sztype
= string_length (&type
);
527 mangled
= dlang_type (decl
, mangled
);
528 string_append (decl
, "[");
529 string_appendn (decl
, type
.b
, sztype
);
530 string_append (decl
, "]");
532 string_delete (&type
);
535 case 'P': /* pointer (T*) */
537 mangled
= dlang_type (decl
, mangled
);
538 string_append (decl
, "*");
540 case 'I': /* ident T */
541 case 'C': /* class T */
542 case 'S': /* struct T */
543 case 'E': /* enum T */
544 case 'T': /* typedef T */
546 return dlang_parse_symbol (decl
, mangled
, dlang_type_name
);
547 case 'D': /* delegate T */
554 mangled
= dlang_type_modifiers (&mods
, mangled
);
555 szmods
= string_length (&mods
);
557 mangled
= dlang_function_type (decl
, mangled
);
558 string_append (decl
, "delegate");
559 string_appendn (decl
, mods
.b
, szmods
);
561 string_delete (&mods
);
564 case 'B': /* tuple T */
566 return dlang_parse_tuple (decl
, mangled
);
569 case 'F': case 'U': case 'W':
571 mangled
= dlang_function_type (decl
, mangled
);
572 string_append (decl
, "function");
578 string_append (decl
, "none");
582 string_append (decl
, "void");
586 string_append (decl
, "byte");
590 string_append (decl
, "ubyte");
594 string_append (decl
, "short");
598 string_append (decl
, "ushort");
602 string_append (decl
, "int");
606 string_append (decl
, "uint");
610 string_append (decl
, "long");
614 string_append (decl
, "ulong");
618 string_append (decl
, "float");
622 string_append (decl
, "double");
626 string_append (decl
, "real");
629 /* Imaginary and Complex types */
632 string_append (decl
, "ifloat");
636 string_append (decl
, "idouble");
640 string_append (decl
, "ireal");
644 string_append (decl
, "cfloat");
648 string_append (decl
, "cdouble");
652 string_append (decl
, "creal");
658 string_append (decl
, "bool");
662 string_append (decl
, "char");
666 string_append (decl
, "wchar");
670 string_append (decl
, "dchar");
678 string_append (decl
, "cent");
682 string_append (decl
, "ucent");
687 default: /* unhandled */
692 /* Extract the identifier from MANGLED and append it to DECL.
693 Return the remaining string on success or NULL on failure. */
695 dlang_identifier (string
*decl
, const char *mangled
,
696 enum dlang_symbol_kinds kind
)
701 if (mangled
== NULL
|| *mangled
== '\0')
704 len
= strtol (mangled
, &endptr
, 10);
706 if (endptr
== NULL
|| len
<= 0)
709 /* In template parameter symbols, the first character of the mangled
710 name can be a digit. This causes ambiguity issues because the
711 digits of the two numbers are adjacent. */
712 if (kind
== dlang_template_param
)
716 int saved
= string_length (decl
);
718 /* Work backwards until a match is found. */
719 for (pend
= endptr
; endptr
!= NULL
; pend
--)
723 /* Reached the beginning of the pointer to the name length,
724 try parsing the entire symbol. */
732 /* Check whether template parameter is a function with a valid
733 return type or an untyped identifier. */
734 if (ISDIGIT (*mangled
))
735 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_ident
);
736 else if (strncmp (mangled
, "_D", 2) == 0)
739 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_function
);
742 /* Check for name length mismatch. */
743 if (mangled
&& (mangled
- pend
) == psize
)
747 string_setlength (decl
, saved
);
750 /* No match on any combinations. */
755 if (strlen (endptr
) < (size_t) len
)
760 /* May be a template instance. */
761 if (len
>= 5 && strncmp (mangled
, "__T", 3) == 0)
763 /* Template symbol. */
764 if (ISDIGIT (mangled
[3]) && mangled
[3] != '0')
765 return dlang_parse_template (decl
, mangled
, len
);
773 if (strncmp (mangled
, "__ctor", len
) == 0)
775 /* Constructor symbol for a class/struct. */
776 string_append (decl
, "this");
780 else if (strncmp (mangled
, "__dtor", len
) == 0)
782 /* Destructor symbol for a class/struct. */
783 string_append (decl
, "~this");
787 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
789 /* The static initialiser for a given symbol. */
790 string_append (decl
, "init$");
794 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
796 /* The vtable symbol for a given class. */
797 string_prepend (decl
, "vtable for ");
798 string_setlength (decl
, string_length (decl
) - 1);
805 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
807 /* The classinfo symbol for a given class. */
808 string_prepend (decl
, "ClassInfo for ");
809 string_setlength (decl
, string_length (decl
) - 1);
816 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
818 /* Postblit symbol for a struct. */
819 string_append (decl
, "this(this)");
826 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
828 /* The interface symbol for a given class. */
829 string_prepend (decl
, "Interface for ");
830 string_setlength (decl
, string_length (decl
) - 1);
837 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
839 /* The ModuleInfo symbol for a given module. */
840 string_prepend (decl
, "ModuleInfo for ");
841 string_setlength (decl
, string_length (decl
) - 1);
848 string_appendn (decl
, mangled
, len
);
855 /* Extract the integer value from MANGLED and append it to DECL,
856 where TYPE is the type it should be represented as.
857 Return the remaining string on success or NULL on failure. */
859 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
861 if (type
== 'a' || type
== 'u' || type
== 'w')
863 /* Parse character value. */
868 long val
= strtol (mangled
, &endptr
, 10);
870 if (endptr
== NULL
|| val
< 0)
873 string_append (decl
, "'");
875 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
877 /* Represent as a character literal. */
879 string_appendn (decl
, &c
, 1);
883 /* Represent as a hexadecimal value. */
887 string_append (decl
, "\\x");
890 case 'u': /* wchar */
891 string_append (decl
, "\\u");
894 case 'w': /* dchar */
895 string_append (decl
, "\\U");
902 int digit
= val
% 16;
905 value
[--pos
] = (char)(digit
+ '0');
907 value
[--pos
] = (char)((digit
- 10) + 'a');
913 for (; width
> 0; width
--)
916 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
918 string_append (decl
, "'");
921 else if (type
== 'b')
923 /* Parse boolean value. */
925 long val
= strtol (mangled
, &endptr
, 10);
927 if (endptr
== NULL
|| val
< 0)
930 string_append (decl
, val
? "true" : "false");
935 /* Parse integer value. */
936 const char *numptr
= mangled
;
939 while (ISDIGIT (*mangled
))
944 string_appendn (decl
, numptr
, num
);
949 case 'h': /* ubyte */
950 case 't': /* ushort */
952 string_append (decl
, "u");
955 string_append (decl
, "L");
957 case 'm': /* ulong */
958 string_append (decl
, "uL");
966 /* Extract the floating-point value from MANGLED and append it to DECL.
967 Return the remaining string on success or NULL on failure. */
969 dlang_parse_real (string
*decl
, const char *mangled
)
976 /* Handle NAN and +-INF. */
977 if (strncmp (mangled
, "NAN", 3) == 0)
979 string_append (decl
, "NaN");
983 else if (strncmp (mangled
, "INF", 3) == 0)
985 string_append (decl
, "Inf");
989 else if (strncmp (mangled
, "NINF", 4) == 0)
991 string_append (decl
, "-Inf");
996 /* Hexadecimal prefix and leading bit. */
1003 if (!ISXDIGIT (*mangled
))
1006 buffer
[len
++] = '0';
1007 buffer
[len
++] = 'x';
1008 buffer
[len
++] = *mangled
;
1009 buffer
[len
++] = '.';
1013 while (ISXDIGIT (*mangled
))
1015 buffer
[len
++] = *mangled
;
1020 if (*mangled
!= 'P')
1023 buffer
[len
++] = 'p';
1026 if (*mangled
== 'N')
1028 buffer
[len
++] = '-';
1032 while (ISDIGIT (*mangled
))
1034 buffer
[len
++] = *mangled
;
1038 /* Convert buffer from hexadecimal to floating-point. */
1040 value
= strtod (buffer
, &endptr
);
1042 if (endptr
== NULL
|| endptr
!= (buffer
+ len
))
1045 len
= snprintf (buffer
, sizeof(buffer
), "%#g", value
);
1046 string_appendn (decl
, buffer
, len
);
1050 /* Convert VAL from an ascii hexdigit to value. */
1052 ascii2hex (char val
)
1054 if (val
>= 'a' && val
<= 'f')
1055 return (val
- 'a' + 10);
1057 if (val
>= 'A' && val
<= 'F')
1058 return (val
- 'A' + 10);
1060 if (val
>= '0' && val
<= '9')
1066 /* Extract the string value from MANGLED and append it to DECL.
1067 Return the remaining string on success or NULL on failure. */
1069 dlang_parse_string (string
*decl
, const char *mangled
)
1071 char type
= *mangled
;
1076 len
= strtol (mangled
, &endptr
, 10);
1078 if (endptr
== NULL
|| len
< 0)
1082 if (*mangled
!= '_')
1086 string_append (decl
, "\"");
1089 if (ISXDIGIT (mangled
[0]) && ISXDIGIT (mangled
[1]))
1091 char a
= ascii2hex (mangled
[0]);
1092 char b
= ascii2hex (mangled
[1]);
1093 char val
= (a
<< 4) | b
;
1095 /* Sanitize white and non-printable characters. */
1099 string_append (decl
, " ");
1102 string_append (decl
, "\\t");
1105 string_append (decl
, "\\n");
1108 string_append (decl
, "\\r");
1111 string_append (decl
, "\\f");
1114 string_append (decl
, "\\v");
1119 string_appendn (decl
, &val
, 1);
1122 string_append (decl
, "\\x");
1123 string_appendn (decl
, mangled
, 2);
1132 string_append (decl
, "\"");
1135 string_appendn (decl
, &type
, 1);
1140 /* Extract the static array value from MANGLED and append it to DECL.
1141 Return the remaining string on success or NULL on failure. */
1143 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1146 long elements
= strtol (mangled
, &endptr
, 10);
1148 if (endptr
== NULL
|| elements
< 0)
1152 string_append (decl
, "[");
1155 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1157 string_append (decl
, ", ");
1160 string_append (decl
, "]");
1164 /* Extract the associative array value from MANGLED and append it to DECL.
1165 Return the remaining string on success or NULL on failure. */
1167 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1170 long elements
= strtol (mangled
, &endptr
, 10);
1172 if (endptr
== NULL
|| elements
< 0)
1176 string_append (decl
, "[");
1179 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1180 string_append (decl
, ":");
1181 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1184 string_append (decl
, ", ");
1187 string_append (decl
, "]");
1191 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1192 Return the remaining string on success or NULL on failure. */
1194 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1197 long args
= strtol (mangled
, &endptr
, 10);
1199 if (endptr
== NULL
|| args
< 0)
1204 string_append (decl
, name
);
1206 string_append (decl
, "(");
1209 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1211 string_append (decl
, ", ");
1214 string_append (decl
, ")");
1218 /* Extract the value from MANGLED and append it to DECL.
1219 Return the remaining string on success or NULL on failure. */
1221 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1223 if (mangled
== NULL
|| *mangled
== '\0')
1231 string_append (decl
, "null");
1234 /* Integral values. */
1237 string_append (decl
, "-");
1238 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1243 if (*mangled
< '0' || *mangled
> '9')
1246 case '0': case '1': case '2': case '3': case '4':
1247 case '5': case '6': case '7': case '8': case '9':
1248 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1254 mangled
= dlang_parse_real (decl
, mangled
);
1257 /* Complex value. */
1260 mangled
= dlang_parse_real (decl
, mangled
);
1261 string_append (decl
, "+");
1262 if (mangled
== NULL
|| *mangled
!= 'c')
1265 mangled
= dlang_parse_real (decl
, mangled
);
1266 string_append (decl
, "i");
1269 /* String values. */
1270 case 'a': /* UTF8 */
1271 case 'w': /* UTF16 */
1272 case 'd': /* UTF32 */
1273 mangled
= dlang_parse_string (decl
, mangled
);
1280 mangled
= dlang_parse_assocarray (decl
, mangled
);
1282 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1285 /* Struct values. */
1288 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1298 /* Extract the type modifiers from MANGLED and return the string
1299 length that it consumes in MANGLED on success or 0 on failure. */
1301 dlang_type_modifier_p (const char *mangled
)
1312 i
= dlang_type_modifier_p (mangled
);
1317 if (*mangled
== 'g')
1320 i
= dlang_type_modifier_p (mangled
);
1328 /* Extract the function calling convention from MANGLED and
1329 return 1 on success or 0 on failure. */
1331 dlang_call_convention_p (const char *mangled
)
1333 /* Prefix for functions needing 'this' */
1334 if (*mangled
== 'M')
1337 /* Also skip over any type modifiers. */
1338 mangled
+= dlang_type_modifier_p (mangled
);
1343 case 'F': case 'U': case 'V':
1352 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1353 Returns the remaining signature on success or NULL on failure. */
1355 dlang_parse_symbol (string
*decl
, const char *mangled
,
1356 enum dlang_symbol_kinds kind
)
1363 string_append (decl
, ".");
1365 mangled
= dlang_identifier (decl
, mangled
, kind
);
1367 if (mangled
&& dlang_call_convention_p (mangled
))
1370 const char *start
= NULL
;
1373 /* Skip over 'this' parameter. */
1374 if (*mangled
== 'M')
1377 /* We have reached here because we expect an extern(Pascal) function.
1378 However this is so rare, that it is more likely a template value
1379 parameter. Since this can't be assumed, first attempt parsing
1380 the symbol as a function, and then back out on failure. */
1381 if (*mangled
== 'V')
1384 checkpoint
= string_length (decl
);
1387 /* Save the type modifiers for appending at the end. */
1388 string_init (&mods
);
1389 mangled
= dlang_type_modifiers (&mods
, mangled
);
1391 /* Skip over calling convention and attributes in qualified name. */
1392 saved
= string_length (decl
);
1393 mangled
= dlang_call_convention (decl
, mangled
);
1394 mangled
= dlang_attributes (decl
, mangled
);
1395 string_setlength (decl
, saved
);
1397 string_append (decl
, "(");
1398 mangled
= dlang_function_args (decl
, mangled
);
1399 string_append (decl
, ")");
1401 /* Add any const/immutable/shared modifier. */
1402 string_appendn (decl
, mods
.b
, string_length (&mods
));
1403 string_delete (&mods
);
1405 if (mangled
== NULL
&& checkpoint
!= 0)
1408 string_setlength (decl
, checkpoint
);
1412 while (mangled
&& ISDIGIT (*mangled
));
1414 /* Only top-level symbols or function template parameters have
1415 a type that needs checking. */
1416 if (kind
== dlang_top_level
|| kind
== dlang_function
)
1418 /* Artificial symbols end with 'Z' and have no type. */
1419 if (mangled
&& *mangled
== 'Z')
1423 saved
= string_length (decl
);
1424 mangled
= dlang_type (decl
, mangled
);
1425 string_setlength (decl
, saved
);
1428 /* Check that the entire symbol was successfully demangled. */
1429 if (kind
== dlang_top_level
)
1431 if (mangled
== NULL
|| *mangled
!= '\0')
1439 /* Demangle the tuple from MANGLED and append it to DECL.
1440 Return the remaining string on success or NULL on failure. */
1442 dlang_parse_tuple (string
*decl
, const char *mangled
)
1445 long elements
= strtol (mangled
, &endptr
, 10);
1447 if (endptr
== NULL
|| elements
< 0)
1451 string_append (decl
, "Tuple!(");
1455 mangled
= dlang_type (decl
, mangled
);
1457 string_append (decl
, ", ");
1460 string_append (decl
, ")");
1464 /* Demangle the argument list from MANGLED and append it to DECL.
1465 Return the remaining string on success or NULL on failure. */
1467 dlang_template_args (string
*decl
, const char *mangled
)
1471 while (mangled
&& *mangled
!= '\0')
1475 case 'Z': /* End of parameter list. */
1481 string_append (decl
, ", ");
1483 /* Skip over specialised template prefix. */
1484 if (*mangled
== 'H')
1489 case 'S': /* Symbol parameter. */
1491 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_param
);
1493 case 'T': /* Type parameter. */
1495 mangled
= dlang_type (decl
, mangled
);
1497 case 'V': /* Value parameter. */
1502 /* Peek at the type. */
1506 /* In the few instances where the type is actually desired in
1507 the output, it should precede the value from dlang_value. */
1508 string_init (&name
);
1509 mangled
= dlang_type (&name
, mangled
);
1510 string_need (&name
, 1);
1513 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1514 string_delete (&name
);
1526 /* Extract and demangle the template symbol in MANGLED, expected to
1527 be made up of LEN characters, and append it to DECL.
1528 Returns the remaining signature on success or NULL on failure. */
1530 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1532 const char *start
= mangled
;
1534 /* Template instance names have the types and values of its parameters
1537 TemplateInstanceName:
1538 Number __T LName TemplateArgs Z
1540 The start pointer should be at the above location, and LEN should be
1541 the value of the decoded number.
1543 if (strncmp (mangled
, "__T", 3) != 0)
1548 /* Template identifier. */
1549 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1551 /* Template arguments. */
1552 string_append (decl
, "!(");
1553 mangled
= dlang_template_args (decl
, mangled
);
1554 string_append (decl
, ")");
1556 /* Check for template name length mismatch. */
1557 if (mangled
&& (mangled
- start
) != len
)
1563 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1564 signature on success or NULL on failure. */
1567 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1570 char *demangled
= NULL
;
1572 if (mangled
== NULL
|| *mangled
== '\0')
1575 if (strncmp (mangled
, "_D", 2) != 0)
1578 string_init (&decl
);
1580 if (strcmp (mangled
, "_Dmain") == 0)
1582 string_append (&decl
, "D main");
1588 if (dlang_parse_symbol (&decl
, mangled
, dlang_top_level
) == NULL
)
1589 string_delete (&decl
);
1592 if (string_length (&decl
) > 0)
1594 string_need (&decl
, 1);