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. */
33 #if 0 /* in valgrind */
37 #endif /* ! in valgrind */
39 #if 0 /* in valgrind */
40 #include "safe-ctype.h"
41 #endif /* ! in valgrind */
43 #if 0 /* in valgrind */
44 #include <sys/types.h>
47 #endif /* ! in valgrind */
49 #if 0 /* in valgrind */
53 extern long strtol (const char *nptr
, char **endptr
, int base
);
55 #endif /* ! in valgrind */
57 #if 0 /* in valgrind */
59 #include "libiberty.h"
60 #endif /* ! in valgrind */
62 #include "vg_libciface.h"
66 #include "safe-ctype.h"
68 /* A mini string-handling package */
70 typedef struct string
/* Beware: these aren't required to be */
71 { /* '\0' terminated. */
72 char *b
; /* pointer to start of string */
73 char *p
; /* pointer after last character */
74 char *e
; /* pointer after end of allocated space */
78 string_need (string
*s
, int n
)
88 s
->p
= s
->b
= XNEWVEC (char, n
);
91 else if (s
->e
- s
->p
< n
)
96 s
->b
= XRESIZEVEC (char, s
->b
, n
);
103 string_delete (string
*s
)
108 s
->b
= s
->e
= s
->p
= NULL
;
113 string_init (string
*s
)
115 s
->b
= s
->p
= s
->e
= NULL
;
119 string_length (string
*s
)
129 string_setlength (string
*s
, int n
)
131 if (n
- string_length (s
) < 0)
138 string_append (string
*p
, const char *s
)
147 string_appendn (string
*p
, const char *s
, int n
)
158 string_prependn (string
*p
, const char *s
, int n
)
165 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
175 string_prepend (string
*p
, const char *s
)
177 if (s
!= NULL
&& *s
!= '\0')
179 string_prependn (p
, s
, strlen (s
));
183 /* What kinds of symbol we could be parsing. */
184 enum dlang_symbol_kinds
186 /* Top-level symbol, needs it's type checked. */
188 /* Function symbol, needs it's type checked. */
190 /* Strongly typed name, such as for classes, structs and enums. */
192 /* Template identifier. */
193 dlang_template_ident
,
194 /* Template symbol parameter. */
198 /* Prototypes for forward referenced functions */
199 static const char *dlang_function_args (string
*, const char *);
201 static const char *dlang_type (string
*, const char *);
203 static const char *dlang_value (string
*, const char *, const char *, char);
205 static const char *dlang_parse_symbol (string
*, const char *,
206 enum dlang_symbol_kinds
);
208 static const char *dlang_parse_tuple (string
*, const char *);
210 static const char *dlang_parse_template (string
*, const char *, long);
213 /* Demangle the calling convention from MANGLED and append it to DECL.
214 Return the remaining string on success or NULL on failure. */
216 dlang_call_convention (string
*decl
, const char *mangled
)
218 if (mangled
== NULL
|| *mangled
== '\0')
228 string_append (decl
, "extern(C) ");
230 case 'W': /* (Windows) */
232 string_append (decl
, "extern(Windows) ");
234 case 'V': /* (Pascal) */
236 string_append (decl
, "extern(Pascal) ");
238 case 'R': /* (C++) */
240 string_append (decl
, "extern(C++) ");
242 case 'Y': /* (Objective-C) */
244 string_append (decl
, "extern(Objective-C) ");
253 /* Extract the type modifiers from MANGLED and append them to DECL.
254 Returns the remaining signature on success or NULL on failure. */
256 dlang_type_modifiers (string
*decl
, const char *mangled
)
258 if (mangled
== NULL
|| *mangled
== '\0')
263 case 'x': /* const */
265 string_append (decl
, " const");
267 case 'y': /* immutable */
269 string_append (decl
, " immutable");
271 case 'O': /* shared */
273 string_append (decl
, " shared");
274 return dlang_type_modifiers (decl
, mangled
);
277 if (*mangled
== 'g') /* wild */
280 string_append (decl
, " inout");
281 return dlang_type_modifiers (decl
, mangled
);
291 /* Demangle the D function attributes from MANGLED and append it to DECL.
292 Return the remaining string on success or NULL on failure. */
294 dlang_attributes (string
*decl
, const char *mangled
)
296 if (mangled
== NULL
|| *mangled
== '\0')
299 while (*mangled
== 'N')
306 string_append (decl
, "pure ");
308 case 'b': /* nothrow */
310 string_append (decl
, "nothrow ");
314 string_append (decl
, "ref ");
316 case 'd': /* @property */
318 string_append (decl
, "@property ");
320 case 'e': /* @trusted */
322 string_append (decl
, "@trusted ");
324 case 'f': /* @safe */
326 string_append (decl
, "@safe ");
331 /* inout parameter is represented as 'Ng'.
332 vector parameter is represented as 'Nh'.
333 return paramenter is represented as 'Nk'.
334 If we see this, then we know we're really in the
335 parameter list. Rewind and break. */
338 case 'i': /* @nogc */
340 string_append (decl
, "@nogc ");
342 case 'j': /* return */
344 string_append (decl
, "return ");
347 default: /* unknown attribute */
356 /* Demangle the function type from MANGLED and append it to DECL.
357 Return the remaining string on success or NULL on failure. */
359 dlang_function_type (string
*decl
, const char *mangled
)
361 string attr
, args
, type
;
362 size_t szattr
, szargs
, sztype
;
364 if (mangled
== NULL
|| *mangled
== '\0')
367 /* The order of the mangled string is:
368 CallConvention FuncAttrs Arguments ArgClose Type
370 The demangled string is re-ordered as:
371 CallConvention Type Arguments FuncAttrs
377 /* Function call convention. */
378 mangled
= dlang_call_convention (decl
, mangled
);
380 /* Function attributes. */
381 mangled
= dlang_attributes (&attr
, mangled
);
382 szattr
= string_length (&attr
);
384 /* Function arguments. */
385 mangled
= dlang_function_args (&args
, mangled
);
386 szargs
= string_length (&args
);
388 /* Function return type. */
389 mangled
= dlang_type (&type
, mangled
);
390 sztype
= string_length (&type
);
392 /* Append to decl in order. */
393 string_appendn (decl
, type
.b
, sztype
);
394 string_append (decl
, "(");
395 string_appendn (decl
, args
.b
, szargs
);
396 string_append (decl
, ") ");
397 string_appendn (decl
, attr
.b
, szattr
);
399 string_delete (&attr
);
400 string_delete (&args
);
401 string_delete (&type
);
405 /* Demangle the argument list from MANGLED and append it to DECL.
406 Return the remaining string on success or NULL on failure. */
408 dlang_function_args (string
*decl
, const char *mangled
)
412 while (mangled
&& *mangled
!= '\0')
416 case 'X': /* (variadic T t...) style. */
418 string_append (decl
, "...");
420 case 'Y': /* (variadic T t, ...) style. */
423 string_append (decl
, ", ");
424 string_append (decl
, "...");
426 case 'Z': /* Normal function. */
432 string_append (decl
, ", ");
434 if (*mangled
== 'M') /* scope(T) */
437 string_append (decl
, "scope ");
440 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
443 string_append (decl
, "return ");
448 case 'J': /* out(T) */
450 string_append (decl
, "out ");
452 case 'K': /* ref(T) */
454 string_append (decl
, "ref ");
456 case 'L': /* lazy(T) */
458 string_append (decl
, "lazy ");
461 mangled
= dlang_type (decl
, mangled
);
467 /* Demangle the type from MANGLED and append it to DECL.
468 Return the remaining string on success or NULL on failure. */
470 dlang_type (string
*decl
, const char *mangled
)
472 if (mangled
== NULL
|| *mangled
== '\0')
477 case 'O': /* shared(T) */
479 string_append (decl
, "shared(");
480 mangled
= dlang_type (decl
, mangled
);
481 string_append (decl
, ")");
483 case 'x': /* const(T) */
485 string_append (decl
, "const(");
486 mangled
= dlang_type (decl
, mangled
);
487 string_append (decl
, ")");
489 case 'y': /* immutable(T) */
491 string_append (decl
, "immutable(");
492 mangled
= dlang_type (decl
, mangled
);
493 string_append (decl
, ")");
497 if (*mangled
== 'g') /* wild(T) */
500 string_append (decl
, "inout(");
501 mangled
= dlang_type (decl
, mangled
);
502 string_append (decl
, ")");
505 else if (*mangled
== 'h') /* vector(T) */
508 string_append (decl
, "__vector(");
509 mangled
= dlang_type (decl
, mangled
);
510 string_append (decl
, ")");
515 case 'A': /* dynamic array (T[]) */
517 mangled
= dlang_type (decl
, mangled
);
518 string_append (decl
, "[]");
520 case 'G': /* static array (T[N]) */
527 while (ISDIGIT (*mangled
))
532 mangled
= dlang_type (decl
, mangled
);
533 string_append (decl
, "[");
534 string_appendn (decl
, numptr
, num
);
535 string_append (decl
, "]");
538 case 'H': /* associative array (T[T]) */
545 mangled
= dlang_type (&type
, mangled
);
546 sztype
= string_length (&type
);
548 mangled
= dlang_type (decl
, mangled
);
549 string_append (decl
, "[");
550 string_appendn (decl
, type
.b
, sztype
);
551 string_append (decl
, "]");
553 string_delete (&type
);
556 case 'P': /* pointer (T*) */
558 /* Function pointer types don't include the trailing asterisk. */
561 case 'F': case 'U': case 'W':
562 case 'V': case 'R': case 'Y':
563 mangled
= dlang_function_type (decl
, mangled
);
564 string_append (decl
, "function");
567 mangled
= dlang_type (decl
, mangled
);
568 string_append (decl
, "*");
570 case 'I': /* ident T */
571 case 'C': /* class T */
572 case 'S': /* struct T */
573 case 'E': /* enum T */
574 case 'T': /* typedef T */
576 return dlang_parse_symbol (decl
, mangled
, dlang_type_name
);
577 case 'D': /* delegate T */
584 mangled
= dlang_type_modifiers (&mods
, mangled
);
585 szmods
= string_length (&mods
);
587 mangled
= dlang_function_type (decl
, mangled
);
588 string_append (decl
, "delegate");
589 string_appendn (decl
, mods
.b
, szmods
);
591 string_delete (&mods
);
594 case 'B': /* tuple T */
596 return dlang_parse_tuple (decl
, mangled
);
601 string_append (decl
, "none");
605 string_append (decl
, "void");
609 string_append (decl
, "byte");
613 string_append (decl
, "ubyte");
617 string_append (decl
, "short");
621 string_append (decl
, "ushort");
625 string_append (decl
, "int");
629 string_append (decl
, "uint");
633 string_append (decl
, "long");
637 string_append (decl
, "ulong");
641 string_append (decl
, "float");
645 string_append (decl
, "double");
649 string_append (decl
, "real");
652 /* Imaginary and Complex types */
655 string_append (decl
, "ifloat");
659 string_append (decl
, "idouble");
663 string_append (decl
, "ireal");
667 string_append (decl
, "cfloat");
671 string_append (decl
, "cdouble");
675 string_append (decl
, "creal");
681 string_append (decl
, "bool");
685 string_append (decl
, "char");
689 string_append (decl
, "wchar");
693 string_append (decl
, "dchar");
701 string_append (decl
, "cent");
705 string_append (decl
, "ucent");
710 default: /* unhandled */
715 /* Extract the identifier from MANGLED and append it to DECL.
716 Return the remaining string on success or NULL on failure. */
718 dlang_identifier (string
*decl
, const char *mangled
,
719 enum dlang_symbol_kinds kind
)
724 if (mangled
== NULL
|| *mangled
== '\0')
727 len
= strtol (mangled
, &endptr
, 10);
729 if (endptr
== NULL
|| len
<= 0)
732 /* In template parameter symbols, the first character of the mangled
733 name can be a digit. This causes ambiguity issues because the
734 digits of the two numbers are adjacent. */
735 if (kind
== dlang_template_param
)
739 int saved
= string_length (decl
);
741 /* Work backwards until a match is found. */
742 for (pend
= endptr
; endptr
!= NULL
; pend
--)
746 /* Reached the beginning of the pointer to the name length,
747 try parsing the entire symbol. */
755 /* Check whether template parameter is a function with a valid
756 return type or an untyped identifier. */
757 if (ISDIGIT (*mangled
))
758 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_ident
);
759 else if (strncmp (mangled
, "_D", 2) == 0)
762 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_function
);
765 /* Check for name length mismatch. */
766 if (mangled
&& (mangled
- pend
) == psize
)
770 string_setlength (decl
, saved
);
773 /* No match on any combinations. */
778 if (strlen (endptr
) < (size_t) len
)
783 /* May be a template instance. */
784 if (len
>= 5 && strncmp (mangled
, "__T", 3) == 0)
786 /* Template symbol. */
787 if (ISDIGIT (mangled
[3]) && mangled
[3] != '0')
788 return dlang_parse_template (decl
, mangled
, len
);
796 if (strncmp (mangled
, "__ctor", len
) == 0)
798 /* Constructor symbol for a class/struct. */
799 string_append (decl
, "this");
803 else if (strncmp (mangled
, "__dtor", len
) == 0)
805 /* Destructor symbol for a class/struct. */
806 string_append (decl
, "~this");
810 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
812 /* The static initialiser for a given symbol. */
813 string_append (decl
, "init$");
817 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
819 /* The vtable symbol for a given class. */
820 string_prepend (decl
, "vtable for ");
821 string_setlength (decl
, string_length (decl
) - 1);
828 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
830 /* The classinfo symbol for a given class. */
831 string_prepend (decl
, "ClassInfo for ");
832 string_setlength (decl
, string_length (decl
) - 1);
839 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
841 /* Postblit symbol for a struct. */
842 string_append (decl
, "this(this)");
849 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
851 /* The interface symbol for a given class. */
852 string_prepend (decl
, "Interface for ");
853 string_setlength (decl
, string_length (decl
) - 1);
860 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
862 /* The ModuleInfo symbol for a given module. */
863 string_prepend (decl
, "ModuleInfo for ");
864 string_setlength (decl
, string_length (decl
) - 1);
871 string_appendn (decl
, mangled
, len
);
878 /* Extract the integer value from MANGLED and append it to DECL,
879 where TYPE is the type it should be represented as.
880 Return the remaining string on success or NULL on failure. */
882 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
884 if (type
== 'a' || type
== 'u' || type
== 'w')
886 /* Parse character value. */
891 long val
= strtol (mangled
, &endptr
, 10);
893 if (endptr
== NULL
|| val
< 0)
896 string_append (decl
, "'");
898 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
900 /* Represent as a character literal. */
902 string_appendn (decl
, &c
, 1);
906 /* Represent as a hexadecimal value. */
910 string_append (decl
, "\\x");
913 case 'u': /* wchar */
914 string_append (decl
, "\\u");
917 case 'w': /* dchar */
918 string_append (decl
, "\\U");
925 int digit
= val
% 16;
928 value
[--pos
] = (char)(digit
+ '0');
930 value
[--pos
] = (char)((digit
- 10) + 'a');
936 for (; width
> 0; width
--)
939 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
941 string_append (decl
, "'");
944 else if (type
== 'b')
946 /* Parse boolean value. */
948 long val
= strtol (mangled
, &endptr
, 10);
950 if (endptr
== NULL
|| val
< 0)
953 string_append (decl
, val
? "true" : "false");
958 /* Parse integer value. */
959 const char *numptr
= mangled
;
962 while (ISDIGIT (*mangled
))
967 string_appendn (decl
, numptr
, num
);
972 case 'h': /* ubyte */
973 case 't': /* ushort */
975 string_append (decl
, "u");
978 string_append (decl
, "L");
980 case 'm': /* ulong */
981 string_append (decl
, "uL");
989 /* Extract the floating-point value from MANGLED and append it to DECL.
990 Return the remaining string on success or NULL on failure. */
992 dlang_parse_real (string
*decl
, const char *mangled
)
997 /* Handle NAN and +-INF. */
998 if (strncmp (mangled
, "NAN", 3) == 0)
1000 string_append (decl
, "NaN");
1004 else if (strncmp (mangled
, "INF", 3) == 0)
1006 string_append (decl
, "Inf");
1010 else if (strncmp (mangled
, "NINF", 4) == 0)
1012 string_append (decl
, "-Inf");
1017 /* Hexadecimal prefix and leading bit. */
1018 if (*mangled
== 'N')
1020 buffer
[len
++] = '-';
1024 if (!ISXDIGIT (*mangled
))
1027 buffer
[len
++] = '0';
1028 buffer
[len
++] = 'x';
1029 buffer
[len
++] = *mangled
;
1030 buffer
[len
++] = '.';
1034 while (ISXDIGIT (*mangled
))
1036 buffer
[len
++] = *mangled
;
1041 if (*mangled
!= 'P')
1044 buffer
[len
++] = 'p';
1047 if (*mangled
== 'N')
1049 buffer
[len
++] = '-';
1053 while (ISDIGIT (*mangled
))
1055 buffer
[len
++] = *mangled
;
1059 /* Write out the demangled hexadecimal, rather than trying to
1060 convert the buffer into a floating-point value. */
1062 len
= strlen (buffer
);
1063 string_appendn (decl
, buffer
, len
);
1067 /* Convert VAL from an ascii hexdigit to value. */
1069 ascii2hex (char val
)
1071 if (val
>= 'a' && val
<= 'f')
1072 return (val
- 'a' + 10);
1074 if (val
>= 'A' && val
<= 'F')
1075 return (val
- 'A' + 10);
1077 if (val
>= '0' && val
<= '9')
1083 /* Extract the string value from MANGLED and append it to DECL.
1084 Return the remaining string on success or NULL on failure. */
1086 dlang_parse_string (string
*decl
, const char *mangled
)
1088 char type
= *mangled
;
1093 len
= strtol (mangled
, &endptr
, 10);
1095 if (endptr
== NULL
|| len
< 0)
1099 if (*mangled
!= '_')
1103 string_append (decl
, "\"");
1106 if (ISXDIGIT (mangled
[0]) && ISXDIGIT (mangled
[1]))
1108 char a
= ascii2hex (mangled
[0]);
1109 char b
= ascii2hex (mangled
[1]);
1110 char val
= (a
<< 4) | b
;
1112 /* Sanitize white and non-printable characters. */
1116 string_append (decl
, " ");
1119 string_append (decl
, "\\t");
1122 string_append (decl
, "\\n");
1125 string_append (decl
, "\\r");
1128 string_append (decl
, "\\f");
1131 string_append (decl
, "\\v");
1136 string_appendn (decl
, &val
, 1);
1139 string_append (decl
, "\\x");
1140 string_appendn (decl
, mangled
, 2);
1149 string_append (decl
, "\"");
1152 string_appendn (decl
, &type
, 1);
1157 /* Extract the static array value from MANGLED and append it to DECL.
1158 Return the remaining string on success or NULL on failure. */
1160 dlang_parse_arrayliteral (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');
1174 string_append (decl
, ", ");
1177 string_append (decl
, "]");
1181 /* Extract the associative array value from MANGLED and append it to DECL.
1182 Return the remaining string on success or NULL on failure. */
1184 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1187 long elements
= strtol (mangled
, &endptr
, 10);
1189 if (endptr
== NULL
|| elements
< 0)
1193 string_append (decl
, "[");
1196 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1197 string_append (decl
, ":");
1198 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1201 string_append (decl
, ", ");
1204 string_append (decl
, "]");
1208 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1209 Return the remaining string on success or NULL on failure. */
1211 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1214 long args
= strtol (mangled
, &endptr
, 10);
1216 if (endptr
== NULL
|| args
< 0)
1221 string_append (decl
, name
);
1223 string_append (decl
, "(");
1226 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1228 string_append (decl
, ", ");
1231 string_append (decl
, ")");
1235 /* Extract the value from MANGLED and append it to DECL.
1236 Return the remaining string on success or NULL on failure. */
1238 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1240 if (mangled
== NULL
|| *mangled
== '\0')
1248 string_append (decl
, "null");
1251 /* Integral values. */
1254 string_append (decl
, "-");
1255 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1260 if (*mangled
< '0' || *mangled
> '9')
1263 case '0': case '1': case '2': case '3': case '4':
1264 case '5': case '6': case '7': case '8': case '9':
1265 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1271 mangled
= dlang_parse_real (decl
, mangled
);
1274 /* Complex value. */
1277 mangled
= dlang_parse_real (decl
, mangled
);
1278 string_append (decl
, "+");
1279 if (mangled
== NULL
|| *mangled
!= 'c')
1282 mangled
= dlang_parse_real (decl
, mangled
);
1283 string_append (decl
, "i");
1286 /* String values. */
1287 case 'a': /* UTF8 */
1288 case 'w': /* UTF16 */
1289 case 'd': /* UTF32 */
1290 mangled
= dlang_parse_string (decl
, mangled
);
1297 mangled
= dlang_parse_assocarray (decl
, mangled
);
1299 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1302 /* Struct values. */
1305 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1315 /* Extract the type modifiers from MANGLED and return the string
1316 length that it consumes in MANGLED on success or 0 on failure. */
1318 dlang_type_modifier_p (const char *mangled
)
1329 i
= dlang_type_modifier_p (mangled
);
1334 if (*mangled
== 'g')
1337 i
= dlang_type_modifier_p (mangled
);
1345 /* Extract the function calling convention from MANGLED and
1346 return 1 on success or 0 on failure. */
1348 dlang_call_convention_p (const char *mangled
)
1350 /* Prefix for functions needing 'this' */
1351 if (*mangled
== 'M')
1354 /* Also skip over any type modifiers. */
1355 mangled
+= dlang_type_modifier_p (mangled
);
1360 case 'F': case 'U': case 'V':
1361 case 'W': case 'R': case 'Y':
1369 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1370 Returns the remaining signature on success or NULL on failure. */
1372 dlang_parse_symbol (string
*decl
, const char *mangled
,
1373 enum dlang_symbol_kinds kind
)
1380 string_append (decl
, ".");
1382 mangled
= dlang_identifier (decl
, mangled
, kind
);
1384 if (mangled
&& dlang_call_convention_p (mangled
))
1387 const char *start
= NULL
;
1390 /* Skip over 'this' parameter. */
1391 if (*mangled
== 'M')
1394 /* We have reached here because we expect an extern(Pascal) function.
1395 However this is so rare, that it is more likely a template value
1396 parameter. Since this can't be assumed, first attempt parsing
1397 the symbol as a function, and then back out on failure. */
1398 if (*mangled
== 'V')
1401 checkpoint
= string_length (decl
);
1404 /* Save the type modifiers for appending at the end. */
1405 string_init (&mods
);
1406 mangled
= dlang_type_modifiers (&mods
, mangled
);
1408 /* Skip over calling convention and attributes in qualified name. */
1409 saved
= string_length (decl
);
1410 mangled
= dlang_call_convention (decl
, mangled
);
1411 mangled
= dlang_attributes (decl
, mangled
);
1412 string_setlength (decl
, saved
);
1414 string_append (decl
, "(");
1415 mangled
= dlang_function_args (decl
, mangled
);
1416 string_append (decl
, ")");
1418 /* Add any const/immutable/shared modifier. */
1419 string_appendn (decl
, mods
.b
, string_length (&mods
));
1420 string_delete (&mods
);
1422 if (mangled
== NULL
&& checkpoint
!= 0)
1425 string_setlength (decl
, checkpoint
);
1429 while (mangled
&& ISDIGIT (*mangled
));
1431 /* Only top-level symbols or function template parameters have
1432 a type that needs checking. */
1433 if (kind
== dlang_top_level
|| kind
== dlang_function
)
1435 /* Artificial symbols end with 'Z' and have no type. */
1436 if (mangled
&& *mangled
== 'Z')
1440 saved
= string_length (decl
);
1441 mangled
= dlang_type (decl
, mangled
);
1442 string_setlength (decl
, saved
);
1445 /* Check that the entire symbol was successfully demangled. */
1446 if (kind
== dlang_top_level
)
1448 if (mangled
== NULL
|| *mangled
!= '\0')
1456 /* Demangle the tuple from MANGLED and append it to DECL.
1457 Return the remaining string on success or NULL on failure. */
1459 dlang_parse_tuple (string
*decl
, const char *mangled
)
1462 long elements
= strtol (mangled
, &endptr
, 10);
1464 if (endptr
== NULL
|| elements
< 0)
1468 string_append (decl
, "Tuple!(");
1472 mangled
= dlang_type (decl
, mangled
);
1474 string_append (decl
, ", ");
1477 string_append (decl
, ")");
1481 /* Demangle the argument list from MANGLED and append it to DECL.
1482 Return the remaining string on success or NULL on failure. */
1484 dlang_template_args (string
*decl
, const char *mangled
)
1488 while (mangled
&& *mangled
!= '\0')
1492 case 'Z': /* End of parameter list. */
1498 string_append (decl
, ", ");
1500 /* Skip over specialised template prefix. */
1501 if (*mangled
== 'H')
1506 case 'S': /* Symbol parameter. */
1508 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_param
);
1510 case 'T': /* Type parameter. */
1512 mangled
= dlang_type (decl
, mangled
);
1514 case 'V': /* Value parameter. */
1519 /* Peek at the type. */
1523 /* In the few instances where the type is actually desired in
1524 the output, it should precede the value from dlang_value. */
1525 string_init (&name
);
1526 mangled
= dlang_type (&name
, mangled
);
1527 string_need (&name
, 1);
1530 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1531 string_delete (&name
);
1543 /* Extract and demangle the template symbol in MANGLED, expected to
1544 be made up of LEN characters, and append it to DECL.
1545 Returns the remaining signature on success or NULL on failure. */
1547 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1549 const char *start
= mangled
;
1551 /* Template instance names have the types and values of its parameters
1554 TemplateInstanceName:
1555 Number __T LName TemplateArgs Z
1557 The start pointer should be at the above location, and LEN should be
1558 the value of the decoded number.
1560 if (strncmp (mangled
, "__T", 3) != 0)
1565 /* Template identifier. */
1566 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1568 /* Template arguments. */
1569 string_append (decl
, "!(");
1570 mangled
= dlang_template_args (decl
, mangled
);
1571 string_append (decl
, ")");
1573 /* Check for template name length mismatch. */
1574 if (mangled
&& (mangled
- start
) != len
)
1580 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1581 signature on success or NULL on failure. */
1584 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1587 char *demangled
= NULL
;
1589 if (mangled
== NULL
|| *mangled
== '\0')
1592 if (strncmp (mangled
, "_D", 2) != 0)
1595 string_init (&decl
);
1597 if (strcmp (mangled
, "_Dmain") == 0)
1599 string_append (&decl
, "D main");
1605 if (dlang_parse_symbol (&decl
, mangled
, dlang_top_level
) == NULL
)
1606 string_delete (&decl
);
1609 if (string_length (&decl
) > 0)
1611 string_need (&decl
, 1);