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 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
);
50 #include "libiberty.h"
52 /* A mini string-handling package */
54 typedef struct string
/* Beware: these aren't required to be */
55 { /* '\0' terminated. */
56 char *b
; /* pointer to start of string */
57 char *p
; /* pointer after last character */
58 char *e
; /* pointer after end of allocated space */
62 string_need (string
*s
, int n
)
72 s
->p
= s
->b
= XNEWVEC (char, n
);
75 else if (s
->e
- s
->p
< n
)
80 s
->b
= XRESIZEVEC (char, s
->b
, n
);
87 string_delete (string
*s
)
92 s
->b
= s
->e
= s
->p
= NULL
;
97 string_init (string
*s
)
99 s
->b
= s
->p
= s
->e
= NULL
;
103 string_length (string
*s
)
113 string_setlength (string
*s
, int n
)
115 if (n
- string_length (s
) < 0)
122 string_append (string
*p
, const char *s
)
131 string_appendn (string
*p
, const char *s
, int n
)
142 string_prependn (string
*p
, const char *s
, int n
)
149 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
159 string_prepend (string
*p
, const char *s
)
161 if (s
!= NULL
&& *s
!= '\0')
163 string_prependn (p
, s
, strlen (s
));
167 /* What kinds of symbol we could be parsing. */
168 enum dlang_symbol_kinds
170 /* Top-level symbol, needs it's type checked. */
172 /* Function symbol, needs it's type checked. */
174 /* Strongly typed name, such as for classes, structs and enums. */
176 /* Template identifier. */
177 dlang_template_ident
,
178 /* Template symbol parameter. */
182 /* Prototypes for forward referenced functions */
183 static const char *dlang_function_args (string
*, const char *);
185 static const char *dlang_type (string
*, const char *);
187 static const char *dlang_value (string
*, const char *, const char *, char);
189 static const char *dlang_parse_symbol (string
*, const char *,
190 enum dlang_symbol_kinds
);
192 static const char *dlang_parse_tuple (string
*, const char *);
194 static const char *dlang_parse_template (string
*, const char *, long);
197 /* Demangle the calling convention from MANGLED and append it to DECL.
198 Return the remaining string on success or NULL on failure. */
200 dlang_call_convention (string
*decl
, const char *mangled
)
202 if (mangled
== NULL
|| *mangled
== '\0')
212 string_append (decl
, "extern(C) ");
214 case 'W': /* (Windows) */
216 string_append (decl
, "extern(Windows) ");
218 case 'V': /* (Pascal) */
220 string_append (decl
, "extern(Pascal) ");
222 case 'R': /* (C++) */
224 string_append (decl
, "extern(C++) ");
233 /* Extract the type modifiers from MANGLED and append them to DECL.
234 Returns the remaining signature on success or NULL on failure. */
236 dlang_type_modifiers (string
*decl
, const char *mangled
)
238 if (mangled
== NULL
|| *mangled
== '\0')
243 case 'x': /* const */
245 string_append (decl
, " const");
247 case 'y': /* immutable */
249 string_append (decl
, " immutable");
251 case 'O': /* shared */
253 string_append (decl
, " shared");
254 return dlang_type_modifiers (decl
, mangled
);
257 if (*mangled
== 'g') /* wild */
260 string_append (decl
, " inout");
261 return dlang_type_modifiers (decl
, mangled
);
271 /* Demangle the D function attributes from MANGLED and append it to DECL.
272 Return the remaining string on success or NULL on failure. */
274 dlang_attributes (string
*decl
, const char *mangled
)
276 if (mangled
== NULL
|| *mangled
== '\0')
279 while (*mangled
== 'N')
286 string_append (decl
, "pure ");
288 case 'b': /* nothrow */
290 string_append (decl
, "nothrow ");
294 string_append (decl
, "ref ");
296 case 'd': /* @property */
298 string_append (decl
, "@property ");
300 case 'e': /* @trusted */
302 string_append (decl
, "@trusted ");
304 case 'f': /* @safe */
306 string_append (decl
, "@safe ");
311 /* inout parameter is represented as 'Ng'.
312 vector parameter is represented as 'Nh'.
313 return paramenter is represented as 'Nk'.
314 If we see this, then we know we're really in the
315 parameter list. Rewind and break. */
318 case 'i': /* @nogc */
320 string_append (decl
, "@nogc ");
322 case 'j': /* return */
324 string_append (decl
, "return ");
327 default: /* unknown attribute */
336 /* Demangle the function type from MANGLED and append it to DECL.
337 Return the remaining string on success or NULL on failure. */
339 dlang_function_type (string
*decl
, const char *mangled
)
341 string attr
, args
, type
;
342 size_t szattr
, szargs
, sztype
;
344 if (mangled
== NULL
|| *mangled
== '\0')
347 /* The order of the mangled string is:
348 CallConvention FuncAttrs Arguments ArgClose Type
350 The demangled string is re-ordered as:
351 CallConvention Type Arguments FuncAttrs
357 /* Function call convention. */
358 mangled
= dlang_call_convention (decl
, mangled
);
360 /* Function attributes. */
361 mangled
= dlang_attributes (&attr
, mangled
);
362 szattr
= string_length (&attr
);
364 /* Function arguments. */
365 mangled
= dlang_function_args (&args
, mangled
);
366 szargs
= string_length (&args
);
368 /* Function return type. */
369 mangled
= dlang_type (&type
, mangled
);
370 sztype
= string_length (&type
);
372 /* Append to decl in order. */
373 string_appendn (decl
, type
.b
, sztype
);
374 string_append (decl
, "(");
375 string_appendn (decl
, args
.b
, szargs
);
376 string_append (decl
, ") ");
377 string_appendn (decl
, attr
.b
, szattr
);
379 string_delete (&attr
);
380 string_delete (&args
);
381 string_delete (&type
);
385 /* Demangle the argument list from MANGLED and append it to DECL.
386 Return the remaining string on success or NULL on failure. */
388 dlang_function_args (string
*decl
, const char *mangled
)
392 while (mangled
&& *mangled
!= '\0')
396 case 'X': /* (variadic T t...) style. */
398 string_append (decl
, "...");
400 case 'Y': /* (variadic T t, ...) style. */
402 string_append (decl
, ", ...");
404 case 'Z': /* Normal function. */
410 string_append (decl
, ", ");
412 if (*mangled
== 'M') /* scope(T) */
415 string_append (decl
, "scope ");
418 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
421 string_append (decl
, "return ");
426 case 'J': /* out(T) */
428 string_append (decl
, "out ");
430 case 'K': /* ref(T) */
432 string_append (decl
, "ref ");
434 case 'L': /* lazy(T) */
436 string_append (decl
, "lazy ");
439 mangled
= dlang_type (decl
, mangled
);
445 /* Demangle the type from MANGLED and append it to DECL.
446 Return the remaining string on success or NULL on failure. */
448 dlang_type (string
*decl
, const char *mangled
)
450 if (mangled
== NULL
|| *mangled
== '\0')
455 case 'O': /* shared(T) */
457 string_append (decl
, "shared(");
458 mangled
= dlang_type (decl
, mangled
);
459 string_append (decl
, ")");
461 case 'x': /* const(T) */
463 string_append (decl
, "const(");
464 mangled
= dlang_type (decl
, mangled
);
465 string_append (decl
, ")");
467 case 'y': /* immutable(T) */
469 string_append (decl
, "immutable(");
470 mangled
= dlang_type (decl
, mangled
);
471 string_append (decl
, ")");
475 if (*mangled
== 'g') /* wild(T) */
478 string_append (decl
, "inout(");
479 mangled
= dlang_type (decl
, mangled
);
480 string_append (decl
, ")");
483 else if (*mangled
== 'h') /* vector(T) */
486 string_append (decl
, "__vector(");
487 mangled
= dlang_type (decl
, mangled
);
488 string_append (decl
, ")");
493 case 'A': /* dynamic array (T[]) */
495 mangled
= dlang_type (decl
, mangled
);
496 string_append (decl
, "[]");
498 case 'G': /* static array (T[N]) */
505 while (ISDIGIT (*mangled
))
510 mangled
= dlang_type (decl
, mangled
);
511 string_append (decl
, "[");
512 string_appendn (decl
, numptr
, num
);
513 string_append (decl
, "]");
516 case 'H': /* associative array (T[T]) */
523 mangled
= dlang_type (&type
, mangled
);
524 sztype
= string_length (&type
);
526 mangled
= dlang_type (decl
, mangled
);
527 string_append (decl
, "[");
528 string_appendn (decl
, type
.b
, sztype
);
529 string_append (decl
, "]");
531 string_delete (&type
);
534 case 'P': /* pointer (T*) */
536 mangled
= dlang_type (decl
, mangled
);
537 string_append (decl
, "*");
539 case 'I': /* ident T */
540 case 'C': /* class T */
541 case 'S': /* struct T */
542 case 'E': /* enum T */
543 case 'T': /* typedef T */
545 return dlang_parse_symbol (decl
, mangled
, dlang_type_name
);
546 case 'D': /* delegate T */
553 mangled
= dlang_type_modifiers (&mods
, mangled
);
554 szmods
= string_length (&mods
);
556 mangled
= dlang_function_type (decl
, mangled
);
557 string_append (decl
, "delegate");
558 string_appendn (decl
, mods
.b
, szmods
);
560 string_delete (&mods
);
563 case 'B': /* tuple T */
565 return dlang_parse_tuple (decl
, mangled
);
568 case 'F': case 'U': case 'W':
570 mangled
= dlang_function_type (decl
, mangled
);
571 string_append (decl
, "function");
577 string_append (decl
, "none");
581 string_append (decl
, "void");
585 string_append (decl
, "byte");
589 string_append (decl
, "ubyte");
593 string_append (decl
, "short");
597 string_append (decl
, "ushort");
601 string_append (decl
, "int");
605 string_append (decl
, "uint");
609 string_append (decl
, "long");
613 string_append (decl
, "ulong");
617 string_append (decl
, "float");
621 string_append (decl
, "double");
625 string_append (decl
, "real");
628 /* Imaginary and Complex types */
631 string_append (decl
, "ifloat");
635 string_append (decl
, "idouble");
639 string_append (decl
, "ireal");
643 string_append (decl
, "cfloat");
647 string_append (decl
, "cdouble");
651 string_append (decl
, "creal");
657 string_append (decl
, "bool");
661 string_append (decl
, "char");
665 string_append (decl
, "wchar");
669 string_append (decl
, "dchar");
677 string_append (decl
, "cent");
681 string_append (decl
, "ucent");
686 default: /* unhandled */
691 /* Extract the identifier from MANGLED and append it to DECL.
692 Return the remaining string on success or NULL on failure. */
694 dlang_identifier (string
*decl
, const char *mangled
,
695 enum dlang_symbol_kinds kind
)
700 if (mangled
== NULL
|| *mangled
== '\0')
703 len
= strtol (mangled
, &endptr
, 10);
705 if (endptr
== NULL
|| len
<= 0)
708 /* In template parameter symbols, the first character of the mangled
709 name can be a digit. This causes ambiguity issues because the
710 digits of the two numbers are adjacent. */
711 if (kind
== dlang_template_param
)
715 int saved
= string_length (decl
);
717 /* Work backwards until a match is found. */
718 for (pend
= endptr
; endptr
!= NULL
; pend
--)
722 /* Reached the beginning of the pointer to the name length,
723 try parsing the entire symbol. */
731 /* Check whether template parameter is a function with a valid
732 return type or an untyped identifier. */
733 if (ISDIGIT (*mangled
))
734 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_ident
);
735 else if (strncmp (mangled
, "_D", 2) == 0)
738 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_function
);
741 /* Check for name length mismatch. */
742 if (mangled
&& (mangled
- pend
) == psize
)
746 string_setlength (decl
, saved
);
749 /* No match on any combinations. */
754 if (strlen (endptr
) < (size_t) len
)
759 /* May be a template instance. */
760 if (len
>= 5 && strncmp (mangled
, "__T", 3) == 0)
762 /* Template symbol. */
763 if (ISDIGIT (mangled
[3]) && mangled
[3] != '0')
764 return dlang_parse_template (decl
, mangled
, len
);
772 if (strncmp (mangled
, "__ctor", len
) == 0)
774 /* Constructor symbol for a class/struct. */
775 string_append (decl
, "this");
779 else if (strncmp (mangled
, "__dtor", len
) == 0)
781 /* Destructor symbol for a class/struct. */
782 string_append (decl
, "~this");
786 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
788 /* The static initialiser for a given symbol. */
789 string_append (decl
, "init$");
793 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
795 /* The vtable symbol for a given class. */
796 string_prepend (decl
, "vtable for ");
797 string_setlength (decl
, string_length (decl
) - 1);
804 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
806 /* The classinfo symbol for a given class. */
807 string_prepend (decl
, "ClassInfo for ");
808 string_setlength (decl
, string_length (decl
) - 1);
815 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
817 /* Postblit symbol for a struct. */
818 string_append (decl
, "this(this)");
825 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
827 /* The interface symbol for a given class. */
828 string_prepend (decl
, "Interface for ");
829 string_setlength (decl
, string_length (decl
) - 1);
836 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
838 /* The ModuleInfo symbol for a given module. */
839 string_prepend (decl
, "ModuleInfo for ");
840 string_setlength (decl
, string_length (decl
) - 1);
847 string_appendn (decl
, mangled
, len
);
854 /* Extract the integer value from MANGLED and append it to DECL,
855 where TYPE is the type it should be represented as.
856 Return the remaining string on success or NULL on failure. */
858 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
860 if (type
== 'a' || type
== 'u' || type
== 'w')
862 /* Parse character value. */
867 long val
= strtol (mangled
, &endptr
, 10);
869 if (endptr
== NULL
|| val
< 0)
872 string_append (decl
, "'");
874 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
876 /* Represent as a character literal. */
878 string_appendn (decl
, &c
, 1);
882 /* Represent as a hexadecimal value. */
886 string_append (decl
, "\\x");
889 case 'u': /* wchar */
890 string_append (decl
, "\\u");
893 case 'w': /* dchar */
894 string_append (decl
, "\\U");
901 int digit
= val
% 16;
904 value
[--pos
] = (char)(digit
+ '0');
906 value
[--pos
] = (char)((digit
- 10) + 'a');
912 for (; width
> 0; width
--)
915 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
917 string_append (decl
, "'");
920 else if (type
== 'b')
922 /* Parse boolean value. */
924 long val
= strtol (mangled
, &endptr
, 10);
926 if (endptr
== NULL
|| val
< 0)
929 string_append (decl
, val
? "true" : "false");
934 /* Parse integer value. */
935 const char *numptr
= mangled
;
938 while (ISDIGIT (*mangled
))
943 string_appendn (decl
, numptr
, num
);
948 case 'h': /* ubyte */
949 case 't': /* ushort */
951 string_append (decl
, "u");
954 string_append (decl
, "L");
956 case 'm': /* ulong */
957 string_append (decl
, "uL");
965 /* Extract the floating-point value from MANGLED and append it to DECL.
966 Return the remaining string on success or NULL on failure. */
968 dlang_parse_real (string
*decl
, const char *mangled
)
973 /* Handle NAN and +-INF. */
974 if (strncmp (mangled
, "NAN", 3) == 0)
976 string_append (decl
, "NaN");
980 else if (strncmp (mangled
, "INF", 3) == 0)
982 string_append (decl
, "Inf");
986 else if (strncmp (mangled
, "NINF", 4) == 0)
988 string_append (decl
, "-Inf");
993 /* Hexadecimal prefix and leading bit. */
1000 if (!ISXDIGIT (*mangled
))
1003 buffer
[len
++] = '0';
1004 buffer
[len
++] = 'x';
1005 buffer
[len
++] = *mangled
;
1006 buffer
[len
++] = '.';
1010 while (ISXDIGIT (*mangled
))
1012 buffer
[len
++] = *mangled
;
1017 if (*mangled
!= 'P')
1020 buffer
[len
++] = 'p';
1023 if (*mangled
== 'N')
1025 buffer
[len
++] = '-';
1029 while (ISDIGIT (*mangled
))
1031 buffer
[len
++] = *mangled
;
1035 /* Write out the demangled hexadecimal, rather than trying to
1036 convert the buffer into a floating-point value. */
1038 len
= strlen (buffer
);
1039 string_appendn (decl
, buffer
, len
);
1043 /* Convert VAL from an ascii hexdigit to value. */
1045 ascii2hex (char val
)
1047 if (val
>= 'a' && val
<= 'f')
1048 return (val
- 'a' + 10);
1050 if (val
>= 'A' && val
<= 'F')
1051 return (val
- 'A' + 10);
1053 if (val
>= '0' && val
<= '9')
1059 /* Extract the string value from MANGLED and append it to DECL.
1060 Return the remaining string on success or NULL on failure. */
1062 dlang_parse_string (string
*decl
, const char *mangled
)
1064 char type
= *mangled
;
1069 len
= strtol (mangled
, &endptr
, 10);
1071 if (endptr
== NULL
|| len
< 0)
1075 if (*mangled
!= '_')
1079 string_append (decl
, "\"");
1082 if (ISXDIGIT (mangled
[0]) && ISXDIGIT (mangled
[1]))
1084 char a
= ascii2hex (mangled
[0]);
1085 char b
= ascii2hex (mangled
[1]);
1086 char val
= (a
<< 4) | b
;
1088 /* Sanitize white and non-printable characters. */
1092 string_append (decl
, " ");
1095 string_append (decl
, "\\t");
1098 string_append (decl
, "\\n");
1101 string_append (decl
, "\\r");
1104 string_append (decl
, "\\f");
1107 string_append (decl
, "\\v");
1112 string_appendn (decl
, &val
, 1);
1115 string_append (decl
, "\\x");
1116 string_appendn (decl
, mangled
, 2);
1125 string_append (decl
, "\"");
1128 string_appendn (decl
, &type
, 1);
1133 /* Extract the static array value from MANGLED and append it to DECL.
1134 Return the remaining string on success or NULL on failure. */
1136 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1139 long elements
= strtol (mangled
, &endptr
, 10);
1141 if (endptr
== NULL
|| elements
< 0)
1145 string_append (decl
, "[");
1148 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1150 string_append (decl
, ", ");
1153 string_append (decl
, "]");
1157 /* Extract the associative array value from MANGLED and append it to DECL.
1158 Return the remaining string on success or NULL on failure. */
1160 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1163 long elements
= strtol (mangled
, &endptr
, 10);
1165 if (endptr
== NULL
|| elements
< 0)
1169 string_append (decl
, "[");
1172 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1173 string_append (decl
, ":");
1174 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1177 string_append (decl
, ", ");
1180 string_append (decl
, "]");
1184 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1185 Return the remaining string on success or NULL on failure. */
1187 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1190 long args
= strtol (mangled
, &endptr
, 10);
1192 if (endptr
== NULL
|| args
< 0)
1197 string_append (decl
, name
);
1199 string_append (decl
, "(");
1202 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1204 string_append (decl
, ", ");
1207 string_append (decl
, ")");
1211 /* Extract the value from MANGLED and append it to DECL.
1212 Return the remaining string on success or NULL on failure. */
1214 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1216 if (mangled
== NULL
|| *mangled
== '\0')
1224 string_append (decl
, "null");
1227 /* Integral values. */
1230 string_append (decl
, "-");
1231 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1236 if (*mangled
< '0' || *mangled
> '9')
1239 case '0': case '1': case '2': case '3': case '4':
1240 case '5': case '6': case '7': case '8': case '9':
1241 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1247 mangled
= dlang_parse_real (decl
, mangled
);
1250 /* Complex value. */
1253 mangled
= dlang_parse_real (decl
, mangled
);
1254 string_append (decl
, "+");
1255 if (mangled
== NULL
|| *mangled
!= 'c')
1258 mangled
= dlang_parse_real (decl
, mangled
);
1259 string_append (decl
, "i");
1262 /* String values. */
1263 case 'a': /* UTF8 */
1264 case 'w': /* UTF16 */
1265 case 'd': /* UTF32 */
1266 mangled
= dlang_parse_string (decl
, mangled
);
1273 mangled
= dlang_parse_assocarray (decl
, mangled
);
1275 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1278 /* Struct values. */
1281 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1291 /* Extract the type modifiers from MANGLED and return the string
1292 length that it consumes in MANGLED on success or 0 on failure. */
1294 dlang_type_modifier_p (const char *mangled
)
1305 i
= dlang_type_modifier_p (mangled
);
1310 if (*mangled
== 'g')
1313 i
= dlang_type_modifier_p (mangled
);
1321 /* Extract the function calling convention from MANGLED and
1322 return 1 on success or 0 on failure. */
1324 dlang_call_convention_p (const char *mangled
)
1326 /* Prefix for functions needing 'this' */
1327 if (*mangled
== 'M')
1330 /* Also skip over any type modifiers. */
1331 mangled
+= dlang_type_modifier_p (mangled
);
1336 case 'F': case 'U': case 'V':
1345 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1346 Returns the remaining signature on success or NULL on failure. */
1348 dlang_parse_symbol (string
*decl
, const char *mangled
,
1349 enum dlang_symbol_kinds kind
)
1356 string_append (decl
, ".");
1358 mangled
= dlang_identifier (decl
, mangled
, kind
);
1360 if (mangled
&& dlang_call_convention_p (mangled
))
1363 const char *start
= NULL
;
1366 /* Skip over 'this' parameter. */
1367 if (*mangled
== 'M')
1370 /* We have reached here because we expect an extern(Pascal) function.
1371 However this is so rare, that it is more likely a template value
1372 parameter. Since this can't be assumed, first attempt parsing
1373 the symbol as a function, and then back out on failure. */
1374 if (*mangled
== 'V')
1377 checkpoint
= string_length (decl
);
1380 /* Save the type modifiers for appending at the end. */
1381 string_init (&mods
);
1382 mangled
= dlang_type_modifiers (&mods
, mangled
);
1384 /* Skip over calling convention and attributes in qualified name. */
1385 saved
= string_length (decl
);
1386 mangled
= dlang_call_convention (decl
, mangled
);
1387 mangled
= dlang_attributes (decl
, mangled
);
1388 string_setlength (decl
, saved
);
1390 string_append (decl
, "(");
1391 mangled
= dlang_function_args (decl
, mangled
);
1392 string_append (decl
, ")");
1394 /* Add any const/immutable/shared modifier. */
1395 string_appendn (decl
, mods
.b
, string_length (&mods
));
1396 string_delete (&mods
);
1398 if (mangled
== NULL
&& checkpoint
!= 0)
1401 string_setlength (decl
, checkpoint
);
1405 while (mangled
&& ISDIGIT (*mangled
));
1407 /* Only top-level symbols or function template parameters have
1408 a type that needs checking. */
1409 if (kind
== dlang_top_level
|| kind
== dlang_function
)
1411 /* Artificial symbols end with 'Z' and have no type. */
1412 if (mangled
&& *mangled
== 'Z')
1416 saved
= string_length (decl
);
1417 mangled
= dlang_type (decl
, mangled
);
1418 string_setlength (decl
, saved
);
1421 /* Check that the entire symbol was successfully demangled. */
1422 if (kind
== dlang_top_level
)
1424 if (mangled
== NULL
|| *mangled
!= '\0')
1432 /* Demangle the tuple from MANGLED and append it to DECL.
1433 Return the remaining string on success or NULL on failure. */
1435 dlang_parse_tuple (string
*decl
, const char *mangled
)
1438 long elements
= strtol (mangled
, &endptr
, 10);
1440 if (endptr
== NULL
|| elements
< 0)
1444 string_append (decl
, "Tuple!(");
1448 mangled
= dlang_type (decl
, mangled
);
1450 string_append (decl
, ", ");
1453 string_append (decl
, ")");
1457 /* Demangle the argument list from MANGLED and append it to DECL.
1458 Return the remaining string on success or NULL on failure. */
1460 dlang_template_args (string
*decl
, const char *mangled
)
1464 while (mangled
&& *mangled
!= '\0')
1468 case 'Z': /* End of parameter list. */
1474 string_append (decl
, ", ");
1476 /* Skip over specialised template prefix. */
1477 if (*mangled
== 'H')
1482 case 'S': /* Symbol parameter. */
1484 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_param
);
1486 case 'T': /* Type parameter. */
1488 mangled
= dlang_type (decl
, mangled
);
1490 case 'V': /* Value parameter. */
1495 /* Peek at the type. */
1499 /* In the few instances where the type is actually desired in
1500 the output, it should precede the value from dlang_value. */
1501 string_init (&name
);
1502 mangled
= dlang_type (&name
, mangled
);
1503 string_need (&name
, 1);
1506 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1507 string_delete (&name
);
1519 /* Extract and demangle the template symbol in MANGLED, expected to
1520 be made up of LEN characters, and append it to DECL.
1521 Returns the remaining signature on success or NULL on failure. */
1523 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1525 const char *start
= mangled
;
1527 /* Template instance names have the types and values of its parameters
1530 TemplateInstanceName:
1531 Number __T LName TemplateArgs Z
1533 The start pointer should be at the above location, and LEN should be
1534 the value of the decoded number.
1536 if (strncmp (mangled
, "__T", 3) != 0)
1541 /* Template identifier. */
1542 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1544 /* Template arguments. */
1545 string_append (decl
, "!(");
1546 mangled
= dlang_template_args (decl
, mangled
);
1547 string_append (decl
, ")");
1549 /* Check for template name length mismatch. */
1550 if (mangled
&& (mangled
- start
) != len
)
1556 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1557 signature on success or NULL on failure. */
1560 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1563 char *demangled
= NULL
;
1565 if (mangled
== NULL
|| *mangled
== '\0')
1568 if (strncmp (mangled
, "_D", 2) != 0)
1571 string_init (&decl
);
1573 if (strcmp (mangled
, "_Dmain") == 0)
1575 string_append (&decl
, "D main");
1581 if (dlang_parse_symbol (&decl
, mangled
, dlang_top_level
) == NULL
)
1582 string_delete (&decl
);
1585 if (string_length (&decl
) > 0)
1587 string_need (&decl
, 1);