1 /* Demangler for the D programming language
2 Copyright (C) 2014-2017 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++) ");
226 case 'Y': /* (Objective-C) */
228 string_append (decl
, "extern(Objective-C) ");
237 /* Extract the type modifiers from MANGLED and append them to DECL.
238 Returns the remaining signature on success or NULL on failure. */
240 dlang_type_modifiers (string
*decl
, const char *mangled
)
242 if (mangled
== NULL
|| *mangled
== '\0')
247 case 'x': /* const */
249 string_append (decl
, " const");
251 case 'y': /* immutable */
253 string_append (decl
, " immutable");
255 case 'O': /* shared */
257 string_append (decl
, " shared");
258 return dlang_type_modifiers (decl
, mangled
);
261 if (*mangled
== 'g') /* wild */
264 string_append (decl
, " inout");
265 return dlang_type_modifiers (decl
, mangled
);
275 /* Demangle the D function attributes from MANGLED and append it to DECL.
276 Return the remaining string on success or NULL on failure. */
278 dlang_attributes (string
*decl
, const char *mangled
)
280 if (mangled
== NULL
|| *mangled
== '\0')
283 while (*mangled
== 'N')
290 string_append (decl
, "pure ");
292 case 'b': /* nothrow */
294 string_append (decl
, "nothrow ");
298 string_append (decl
, "ref ");
300 case 'd': /* @property */
302 string_append (decl
, "@property ");
304 case 'e': /* @trusted */
306 string_append (decl
, "@trusted ");
308 case 'f': /* @safe */
310 string_append (decl
, "@safe ");
315 /* inout parameter is represented as 'Ng'.
316 vector parameter is represented as 'Nh'.
317 return paramenter is represented as 'Nk'.
318 If we see this, then we know we're really in the
319 parameter list. Rewind and break. */
322 case 'i': /* @nogc */
324 string_append (decl
, "@nogc ");
326 case 'j': /* return */
328 string_append (decl
, "return ");
331 default: /* unknown attribute */
340 /* Demangle the function type from MANGLED and append it to DECL.
341 Return the remaining string on success or NULL on failure. */
343 dlang_function_type (string
*decl
, const char *mangled
)
345 string attr
, args
, type
;
346 size_t szattr
, szargs
, sztype
;
348 if (mangled
== NULL
|| *mangled
== '\0')
351 /* The order of the mangled string is:
352 CallConvention FuncAttrs Arguments ArgClose Type
354 The demangled string is re-ordered as:
355 CallConvention Type Arguments FuncAttrs
361 /* Function call convention. */
362 mangled
= dlang_call_convention (decl
, mangled
);
364 /* Function attributes. */
365 mangled
= dlang_attributes (&attr
, mangled
);
366 szattr
= string_length (&attr
);
368 /* Function arguments. */
369 mangled
= dlang_function_args (&args
, mangled
);
370 szargs
= string_length (&args
);
372 /* Function return type. */
373 mangled
= dlang_type (&type
, mangled
);
374 sztype
= string_length (&type
);
376 /* Append to decl in order. */
377 string_appendn (decl
, type
.b
, sztype
);
378 string_append (decl
, "(");
379 string_appendn (decl
, args
.b
, szargs
);
380 string_append (decl
, ") ");
381 string_appendn (decl
, attr
.b
, szattr
);
383 string_delete (&attr
);
384 string_delete (&args
);
385 string_delete (&type
);
389 /* Demangle the argument list from MANGLED and append it to DECL.
390 Return the remaining string on success or NULL on failure. */
392 dlang_function_args (string
*decl
, const char *mangled
)
396 while (mangled
&& *mangled
!= '\0')
400 case 'X': /* (variadic T t...) style. */
402 string_append (decl
, "...");
404 case 'Y': /* (variadic T t, ...) style. */
407 string_append (decl
, ", ");
408 string_append (decl
, "...");
410 case 'Z': /* Normal function. */
416 string_append (decl
, ", ");
418 if (*mangled
== 'M') /* scope(T) */
421 string_append (decl
, "scope ");
424 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
427 string_append (decl
, "return ");
432 case 'J': /* out(T) */
434 string_append (decl
, "out ");
436 case 'K': /* ref(T) */
438 string_append (decl
, "ref ");
440 case 'L': /* lazy(T) */
442 string_append (decl
, "lazy ");
445 mangled
= dlang_type (decl
, mangled
);
451 /* Demangle the type from MANGLED and append it to DECL.
452 Return the remaining string on success or NULL on failure. */
454 dlang_type (string
*decl
, const char *mangled
)
456 if (mangled
== NULL
|| *mangled
== '\0')
461 case 'O': /* shared(T) */
463 string_append (decl
, "shared(");
464 mangled
= dlang_type (decl
, mangled
);
465 string_append (decl
, ")");
467 case 'x': /* const(T) */
469 string_append (decl
, "const(");
470 mangled
= dlang_type (decl
, mangled
);
471 string_append (decl
, ")");
473 case 'y': /* immutable(T) */
475 string_append (decl
, "immutable(");
476 mangled
= dlang_type (decl
, mangled
);
477 string_append (decl
, ")");
481 if (*mangled
== 'g') /* wild(T) */
484 string_append (decl
, "inout(");
485 mangled
= dlang_type (decl
, mangled
);
486 string_append (decl
, ")");
489 else if (*mangled
== 'h') /* vector(T) */
492 string_append (decl
, "__vector(");
493 mangled
= dlang_type (decl
, mangled
);
494 string_append (decl
, ")");
499 case 'A': /* dynamic array (T[]) */
501 mangled
= dlang_type (decl
, mangled
);
502 string_append (decl
, "[]");
504 case 'G': /* static array (T[N]) */
511 while (ISDIGIT (*mangled
))
516 mangled
= dlang_type (decl
, mangled
);
517 string_append (decl
, "[");
518 string_appendn (decl
, numptr
, num
);
519 string_append (decl
, "]");
522 case 'H': /* associative array (T[T]) */
529 mangled
= dlang_type (&type
, mangled
);
530 sztype
= string_length (&type
);
532 mangled
= dlang_type (decl
, mangled
);
533 string_append (decl
, "[");
534 string_appendn (decl
, type
.b
, sztype
);
535 string_append (decl
, "]");
537 string_delete (&type
);
540 case 'P': /* pointer (T*) */
542 /* Function pointer types don't include the trailing asterisk. */
545 case 'F': case 'U': case 'W':
546 case 'V': case 'R': case 'Y':
547 mangled
= dlang_function_type (decl
, mangled
);
548 string_append (decl
, "function");
551 mangled
= dlang_type (decl
, mangled
);
552 string_append (decl
, "*");
554 case 'I': /* ident T */
555 case 'C': /* class T */
556 case 'S': /* struct T */
557 case 'E': /* enum T */
558 case 'T': /* typedef T */
560 return dlang_parse_symbol (decl
, mangled
, dlang_type_name
);
561 case 'D': /* delegate T */
568 mangled
= dlang_type_modifiers (&mods
, mangled
);
569 szmods
= string_length (&mods
);
571 mangled
= dlang_function_type (decl
, mangled
);
572 string_append (decl
, "delegate");
573 string_appendn (decl
, mods
.b
, szmods
);
575 string_delete (&mods
);
578 case 'B': /* tuple T */
580 return dlang_parse_tuple (decl
, mangled
);
585 string_append (decl
, "none");
589 string_append (decl
, "void");
593 string_append (decl
, "byte");
597 string_append (decl
, "ubyte");
601 string_append (decl
, "short");
605 string_append (decl
, "ushort");
609 string_append (decl
, "int");
613 string_append (decl
, "uint");
617 string_append (decl
, "long");
621 string_append (decl
, "ulong");
625 string_append (decl
, "float");
629 string_append (decl
, "double");
633 string_append (decl
, "real");
636 /* Imaginary and Complex types */
639 string_append (decl
, "ifloat");
643 string_append (decl
, "idouble");
647 string_append (decl
, "ireal");
651 string_append (decl
, "cfloat");
655 string_append (decl
, "cdouble");
659 string_append (decl
, "creal");
665 string_append (decl
, "bool");
669 string_append (decl
, "char");
673 string_append (decl
, "wchar");
677 string_append (decl
, "dchar");
685 string_append (decl
, "cent");
689 string_append (decl
, "ucent");
694 default: /* unhandled */
699 /* Extract the identifier from MANGLED and append it to DECL.
700 Return the remaining string on success or NULL on failure. */
702 dlang_identifier (string
*decl
, const char *mangled
,
703 enum dlang_symbol_kinds kind
)
708 if (mangled
== NULL
|| *mangled
== '\0')
711 len
= strtol (mangled
, &endptr
, 10);
713 if (endptr
== NULL
|| len
<= 0)
716 /* In template parameter symbols, the first character of the mangled
717 name can be a digit. This causes ambiguity issues because the
718 digits of the two numbers are adjacent. */
719 if (kind
== dlang_template_param
)
723 int saved
= string_length (decl
);
725 /* Work backwards until a match is found. */
726 for (pend
= endptr
; endptr
!= NULL
; pend
--)
730 /* Reached the beginning of the pointer to the name length,
731 try parsing the entire symbol. */
739 /* Check whether template parameter is a function with a valid
740 return type or an untyped identifier. */
741 if (ISDIGIT (*mangled
))
742 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_ident
);
743 else if (strncmp (mangled
, "_D", 2) == 0)
746 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_function
);
749 /* Check for name length mismatch. */
750 if (mangled
&& (mangled
- pend
) == psize
)
754 string_setlength (decl
, saved
);
757 /* No match on any combinations. */
762 if (strlen (endptr
) < (size_t) len
)
767 /* May be a template instance. */
768 if (len
>= 5 && strncmp (mangled
, "__T", 3) == 0)
770 /* Template symbol. */
771 if (ISDIGIT (mangled
[3]) && mangled
[3] != '0')
772 return dlang_parse_template (decl
, mangled
, len
);
780 if (strncmp (mangled
, "__ctor", len
) == 0)
782 /* Constructor symbol for a class/struct. */
783 string_append (decl
, "this");
787 else if (strncmp (mangled
, "__dtor", len
) == 0)
789 /* Destructor symbol for a class/struct. */
790 string_append (decl
, "~this");
794 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
796 /* The static initialiser for a given symbol. */
797 string_append (decl
, "init$");
801 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
803 /* The vtable symbol for a given class. */
804 string_prepend (decl
, "vtable for ");
805 string_setlength (decl
, string_length (decl
) - 1);
812 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
814 /* The classinfo symbol for a given class. */
815 string_prepend (decl
, "ClassInfo for ");
816 string_setlength (decl
, string_length (decl
) - 1);
823 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
825 /* Postblit symbol for a struct. */
826 string_append (decl
, "this(this)");
833 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
835 /* The interface symbol for a given class. */
836 string_prepend (decl
, "Interface for ");
837 string_setlength (decl
, string_length (decl
) - 1);
844 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
846 /* The ModuleInfo symbol for a given module. */
847 string_prepend (decl
, "ModuleInfo for ");
848 string_setlength (decl
, string_length (decl
) - 1);
855 string_appendn (decl
, mangled
, len
);
862 /* Extract the integer value from MANGLED and append it to DECL,
863 where TYPE is the type it should be represented as.
864 Return the remaining string on success or NULL on failure. */
866 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
868 if (type
== 'a' || type
== 'u' || type
== 'w')
870 /* Parse character value. */
875 long val
= strtol (mangled
, &endptr
, 10);
877 if (endptr
== NULL
|| val
< 0)
880 string_append (decl
, "'");
882 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
884 /* Represent as a character literal. */
886 string_appendn (decl
, &c
, 1);
890 /* Represent as a hexadecimal value. */
894 string_append (decl
, "\\x");
897 case 'u': /* wchar */
898 string_append (decl
, "\\u");
901 case 'w': /* dchar */
902 string_append (decl
, "\\U");
909 int digit
= val
% 16;
912 value
[--pos
] = (char)(digit
+ '0');
914 value
[--pos
] = (char)((digit
- 10) + 'a');
920 for (; width
> 0; width
--)
923 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
925 string_append (decl
, "'");
928 else if (type
== 'b')
930 /* Parse boolean value. */
932 long val
= strtol (mangled
, &endptr
, 10);
934 if (endptr
== NULL
|| val
< 0)
937 string_append (decl
, val
? "true" : "false");
942 /* Parse integer value. */
943 const char *numptr
= mangled
;
946 while (ISDIGIT (*mangled
))
951 string_appendn (decl
, numptr
, num
);
956 case 'h': /* ubyte */
957 case 't': /* ushort */
959 string_append (decl
, "u");
962 string_append (decl
, "L");
964 case 'm': /* ulong */
965 string_append (decl
, "uL");
973 /* Extract the floating-point value from MANGLED and append it to DECL.
974 Return the remaining string on success or NULL on failure. */
976 dlang_parse_real (string
*decl
, const char *mangled
)
981 /* Handle NAN and +-INF. */
982 if (strncmp (mangled
, "NAN", 3) == 0)
984 string_append (decl
, "NaN");
988 else if (strncmp (mangled
, "INF", 3) == 0)
990 string_append (decl
, "Inf");
994 else if (strncmp (mangled
, "NINF", 4) == 0)
996 string_append (decl
, "-Inf");
1001 /* Hexadecimal prefix and leading bit. */
1002 if (*mangled
== 'N')
1004 buffer
[len
++] = '-';
1008 if (!ISXDIGIT (*mangled
))
1011 buffer
[len
++] = '0';
1012 buffer
[len
++] = 'x';
1013 buffer
[len
++] = *mangled
;
1014 buffer
[len
++] = '.';
1018 while (ISXDIGIT (*mangled
))
1020 buffer
[len
++] = *mangled
;
1025 if (*mangled
!= 'P')
1028 buffer
[len
++] = 'p';
1031 if (*mangled
== 'N')
1033 buffer
[len
++] = '-';
1037 while (ISDIGIT (*mangled
))
1039 buffer
[len
++] = *mangled
;
1043 /* Write out the demangled hexadecimal, rather than trying to
1044 convert the buffer into a floating-point value. */
1046 len
= strlen (buffer
);
1047 string_appendn (decl
, buffer
, len
);
1051 /* Convert VAL from an ascii hexdigit to value. */
1053 ascii2hex (char val
)
1055 if (val
>= 'a' && val
<= 'f')
1056 return (val
- 'a' + 10);
1058 if (val
>= 'A' && val
<= 'F')
1059 return (val
- 'A' + 10);
1061 if (val
>= '0' && val
<= '9')
1067 /* Extract the string value from MANGLED and append it to DECL.
1068 Return the remaining string on success or NULL on failure. */
1070 dlang_parse_string (string
*decl
, const char *mangled
)
1072 char type
= *mangled
;
1077 len
= strtol (mangled
, &endptr
, 10);
1079 if (endptr
== NULL
|| len
< 0)
1083 if (*mangled
!= '_')
1087 string_append (decl
, "\"");
1090 if (ISXDIGIT (mangled
[0]) && ISXDIGIT (mangled
[1]))
1092 char a
= ascii2hex (mangled
[0]);
1093 char b
= ascii2hex (mangled
[1]);
1094 char val
= (a
<< 4) | b
;
1096 /* Sanitize white and non-printable characters. */
1100 string_append (decl
, " ");
1103 string_append (decl
, "\\t");
1106 string_append (decl
, "\\n");
1109 string_append (decl
, "\\r");
1112 string_append (decl
, "\\f");
1115 string_append (decl
, "\\v");
1120 string_appendn (decl
, &val
, 1);
1123 string_append (decl
, "\\x");
1124 string_appendn (decl
, mangled
, 2);
1133 string_append (decl
, "\"");
1136 string_appendn (decl
, &type
, 1);
1141 /* Extract the static array value from MANGLED and append it to DECL.
1142 Return the remaining string on success or NULL on failure. */
1144 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1147 long elements
= strtol (mangled
, &endptr
, 10);
1149 if (endptr
== NULL
|| elements
< 0)
1153 string_append (decl
, "[");
1156 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1158 string_append (decl
, ", ");
1161 string_append (decl
, "]");
1165 /* Extract the associative array value from MANGLED and append it to DECL.
1166 Return the remaining string on success or NULL on failure. */
1168 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1171 long elements
= strtol (mangled
, &endptr
, 10);
1173 if (endptr
== NULL
|| elements
< 0)
1177 string_append (decl
, "[");
1180 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1181 string_append (decl
, ":");
1182 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1185 string_append (decl
, ", ");
1188 string_append (decl
, "]");
1192 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1193 Return the remaining string on success or NULL on failure. */
1195 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1198 long args
= strtol (mangled
, &endptr
, 10);
1200 if (endptr
== NULL
|| args
< 0)
1205 string_append (decl
, name
);
1207 string_append (decl
, "(");
1210 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1212 string_append (decl
, ", ");
1215 string_append (decl
, ")");
1219 /* Extract the value from MANGLED and append it to DECL.
1220 Return the remaining string on success or NULL on failure. */
1222 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1224 if (mangled
== NULL
|| *mangled
== '\0')
1232 string_append (decl
, "null");
1235 /* Integral values. */
1238 string_append (decl
, "-");
1239 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1244 if (*mangled
< '0' || *mangled
> '9')
1247 case '0': case '1': case '2': case '3': case '4':
1248 case '5': case '6': case '7': case '8': case '9':
1249 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1255 mangled
= dlang_parse_real (decl
, mangled
);
1258 /* Complex value. */
1261 mangled
= dlang_parse_real (decl
, mangled
);
1262 string_append (decl
, "+");
1263 if (mangled
== NULL
|| *mangled
!= 'c')
1266 mangled
= dlang_parse_real (decl
, mangled
);
1267 string_append (decl
, "i");
1270 /* String values. */
1271 case 'a': /* UTF8 */
1272 case 'w': /* UTF16 */
1273 case 'd': /* UTF32 */
1274 mangled
= dlang_parse_string (decl
, mangled
);
1281 mangled
= dlang_parse_assocarray (decl
, mangled
);
1283 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1286 /* Struct values. */
1289 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1299 /* Extract the type modifiers from MANGLED and return the string
1300 length that it consumes in MANGLED on success or 0 on failure. */
1302 dlang_type_modifier_p (const char *mangled
)
1313 i
= dlang_type_modifier_p (mangled
);
1318 if (*mangled
== 'g')
1321 i
= dlang_type_modifier_p (mangled
);
1329 /* Extract the function calling convention from MANGLED and
1330 return 1 on success or 0 on failure. */
1332 dlang_call_convention_p (const char *mangled
)
1334 /* Prefix for functions needing 'this' */
1335 if (*mangled
== 'M')
1338 /* Also skip over any type modifiers. */
1339 mangled
+= dlang_type_modifier_p (mangled
);
1344 case 'F': case 'U': case 'V':
1345 case 'W': case 'R': case 'Y':
1353 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1354 Returns the remaining signature on success or NULL on failure. */
1356 dlang_parse_symbol (string
*decl
, const char *mangled
,
1357 enum dlang_symbol_kinds kind
)
1364 string_append (decl
, ".");
1366 mangled
= dlang_identifier (decl
, mangled
, kind
);
1368 if (mangled
&& dlang_call_convention_p (mangled
))
1371 const char *start
= NULL
;
1374 /* Skip over 'this' parameter. */
1375 if (*mangled
== 'M')
1378 /* We have reached here because we expect an extern(Pascal) function.
1379 However this is so rare, that it is more likely a template value
1380 parameter. Since this can't be assumed, first attempt parsing
1381 the symbol as a function, and then back out on failure. */
1382 if (*mangled
== 'V')
1385 checkpoint
= string_length (decl
);
1388 /* Save the type modifiers for appending at the end. */
1389 string_init (&mods
);
1390 mangled
= dlang_type_modifiers (&mods
, mangled
);
1392 /* Skip over calling convention and attributes in qualified name. */
1393 saved
= string_length (decl
);
1394 mangled
= dlang_call_convention (decl
, mangled
);
1395 mangled
= dlang_attributes (decl
, mangled
);
1396 string_setlength (decl
, saved
);
1398 string_append (decl
, "(");
1399 mangled
= dlang_function_args (decl
, mangled
);
1400 string_append (decl
, ")");
1402 /* Add any const/immutable/shared modifier. */
1403 string_appendn (decl
, mods
.b
, string_length (&mods
));
1404 string_delete (&mods
);
1406 if (mangled
== NULL
&& checkpoint
!= 0)
1409 string_setlength (decl
, checkpoint
);
1413 while (mangled
&& ISDIGIT (*mangled
));
1415 /* Only top-level symbols or function template parameters have
1416 a type that needs checking. */
1417 if (kind
== dlang_top_level
|| kind
== dlang_function
)
1419 /* Artificial symbols end with 'Z' and have no type. */
1420 if (mangled
&& *mangled
== 'Z')
1424 saved
= string_length (decl
);
1425 mangled
= dlang_type (decl
, mangled
);
1426 string_setlength (decl
, saved
);
1429 /* Check that the entire symbol was successfully demangled. */
1430 if (kind
== dlang_top_level
)
1432 if (mangled
== NULL
|| *mangled
!= '\0')
1440 /* Demangle the tuple from MANGLED and append it to DECL.
1441 Return the remaining string on success or NULL on failure. */
1443 dlang_parse_tuple (string
*decl
, const char *mangled
)
1446 long elements
= strtol (mangled
, &endptr
, 10);
1448 if (endptr
== NULL
|| elements
< 0)
1452 string_append (decl
, "Tuple!(");
1456 mangled
= dlang_type (decl
, mangled
);
1458 string_append (decl
, ", ");
1461 string_append (decl
, ")");
1465 /* Demangle the argument list from MANGLED and append it to DECL.
1466 Return the remaining string on success or NULL on failure. */
1468 dlang_template_args (string
*decl
, const char *mangled
)
1472 while (mangled
&& *mangled
!= '\0')
1476 case 'Z': /* End of parameter list. */
1482 string_append (decl
, ", ");
1484 /* Skip over specialised template prefix. */
1485 if (*mangled
== 'H')
1490 case 'S': /* Symbol parameter. */
1492 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_param
);
1494 case 'T': /* Type parameter. */
1496 mangled
= dlang_type (decl
, mangled
);
1498 case 'V': /* Value parameter. */
1503 /* Peek at the type. */
1507 /* In the few instances where the type is actually desired in
1508 the output, it should precede the value from dlang_value. */
1509 string_init (&name
);
1510 mangled
= dlang_type (&name
, mangled
);
1511 string_need (&name
, 1);
1514 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1515 string_delete (&name
);
1527 /* Extract and demangle the template symbol in MANGLED, expected to
1528 be made up of LEN characters, and append it to DECL.
1529 Returns the remaining signature on success or NULL on failure. */
1531 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1533 const char *start
= mangled
;
1535 /* Template instance names have the types and values of its parameters
1538 TemplateInstanceName:
1539 Number __T LName TemplateArgs Z
1541 The start pointer should be at the above location, and LEN should be
1542 the value of the decoded number.
1544 if (strncmp (mangled
, "__T", 3) != 0)
1549 /* Template identifier. */
1550 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1552 /* Template arguments. */
1553 string_append (decl
, "!(");
1554 mangled
= dlang_template_args (decl
, mangled
);
1555 string_append (decl
, ")");
1557 /* Check for template name length mismatch. */
1558 if (mangled
&& (mangled
- start
) != len
)
1564 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1565 signature on success or NULL on failure. */
1568 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1571 char *demangled
= NULL
;
1573 if (mangled
== NULL
|| *mangled
== '\0')
1576 if (strncmp (mangled
, "_D", 2) != 0)
1579 string_init (&decl
);
1581 if (strcmp (mangled
, "_Dmain") == 0)
1583 string_append (&decl
, "D main");
1589 if (dlang_parse_symbol (&decl
, mangled
, dlang_top_level
) == NULL
)
1590 string_delete (&decl
);
1593 if (string_length (&decl
) > 0)
1595 string_need (&decl
, 1);