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 ");
330 case 'l': /* scope */
332 string_append (decl
, "scope ");
335 default: /* unknown attribute */
344 /* Demangle the function type from MANGLED and append it to DECL.
345 Return the remaining string on success or NULL on failure. */
347 dlang_function_type (string
*decl
, const char *mangled
)
349 string attr
, args
, type
;
350 size_t szattr
, szargs
, sztype
;
352 if (mangled
== NULL
|| *mangled
== '\0')
355 /* The order of the mangled string is:
356 CallConvention FuncAttrs Arguments ArgClose Type
358 The demangled string is re-ordered as:
359 CallConvention Type Arguments FuncAttrs
365 /* Function call convention. */
366 mangled
= dlang_call_convention (decl
, mangled
);
368 /* Function attributes. */
369 mangled
= dlang_attributes (&attr
, mangled
);
370 szattr
= string_length (&attr
);
372 /* Function arguments. */
373 mangled
= dlang_function_args (&args
, mangled
);
374 szargs
= string_length (&args
);
376 /* Function return type. */
377 mangled
= dlang_type (&type
, mangled
);
378 sztype
= string_length (&type
);
380 /* Append to decl in order. */
381 string_appendn (decl
, type
.b
, sztype
);
382 string_append (decl
, "(");
383 string_appendn (decl
, args
.b
, szargs
);
384 string_append (decl
, ") ");
385 string_appendn (decl
, attr
.b
, szattr
);
387 string_delete (&attr
);
388 string_delete (&args
);
389 string_delete (&type
);
393 /* Demangle the argument list from MANGLED and append it to DECL.
394 Return the remaining string on success or NULL on failure. */
396 dlang_function_args (string
*decl
, const char *mangled
)
400 while (mangled
&& *mangled
!= '\0')
404 case 'X': /* (variadic T t...) style. */
406 string_append (decl
, "...");
408 case 'Y': /* (variadic T t, ...) style. */
411 string_append (decl
, ", ");
412 string_append (decl
, "...");
414 case 'Z': /* Normal function. */
420 string_append (decl
, ", ");
422 if (*mangled
== 'M') /* scope(T) */
425 string_append (decl
, "scope ");
428 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
431 string_append (decl
, "return ");
436 case 'J': /* out(T) */
438 string_append (decl
, "out ");
440 case 'K': /* ref(T) */
442 string_append (decl
, "ref ");
444 case 'L': /* lazy(T) */
446 string_append (decl
, "lazy ");
449 mangled
= dlang_type (decl
, mangled
);
455 /* Demangle the type from MANGLED and append it to DECL.
456 Return the remaining string on success or NULL on failure. */
458 dlang_type (string
*decl
, const char *mangled
)
460 if (mangled
== NULL
|| *mangled
== '\0')
465 case 'O': /* shared(T) */
467 string_append (decl
, "shared(");
468 mangled
= dlang_type (decl
, mangled
);
469 string_append (decl
, ")");
471 case 'x': /* const(T) */
473 string_append (decl
, "const(");
474 mangled
= dlang_type (decl
, mangled
);
475 string_append (decl
, ")");
477 case 'y': /* immutable(T) */
479 string_append (decl
, "immutable(");
480 mangled
= dlang_type (decl
, mangled
);
481 string_append (decl
, ")");
485 if (*mangled
== 'g') /* wild(T) */
488 string_append (decl
, "inout(");
489 mangled
= dlang_type (decl
, mangled
);
490 string_append (decl
, ")");
493 else if (*mangled
== 'h') /* vector(T) */
496 string_append (decl
, "__vector(");
497 mangled
= dlang_type (decl
, mangled
);
498 string_append (decl
, ")");
503 case 'A': /* dynamic array (T[]) */
505 mangled
= dlang_type (decl
, mangled
);
506 string_append (decl
, "[]");
508 case 'G': /* static array (T[N]) */
515 while (ISDIGIT (*mangled
))
520 mangled
= dlang_type (decl
, mangled
);
521 string_append (decl
, "[");
522 string_appendn (decl
, numptr
, num
);
523 string_append (decl
, "]");
526 case 'H': /* associative array (T[T]) */
533 mangled
= dlang_type (&type
, mangled
);
534 sztype
= string_length (&type
);
536 mangled
= dlang_type (decl
, mangled
);
537 string_append (decl
, "[");
538 string_appendn (decl
, type
.b
, sztype
);
539 string_append (decl
, "]");
541 string_delete (&type
);
544 case 'P': /* pointer (T*) */
546 /* Function pointer types don't include the trailing asterisk. */
549 case 'F': case 'U': case 'W':
550 case 'V': case 'R': case 'Y':
551 mangled
= dlang_function_type (decl
, mangled
);
552 string_append (decl
, "function");
555 mangled
= dlang_type (decl
, mangled
);
556 string_append (decl
, "*");
558 case 'I': /* ident T */
559 case 'C': /* class T */
560 case 'S': /* struct T */
561 case 'E': /* enum T */
562 case 'T': /* typedef T */
564 return dlang_parse_symbol (decl
, mangled
, dlang_type_name
);
565 case 'D': /* delegate T */
572 mangled
= dlang_type_modifiers (&mods
, mangled
);
573 szmods
= string_length (&mods
);
575 mangled
= dlang_function_type (decl
, mangled
);
576 string_append (decl
, "delegate");
577 string_appendn (decl
, mods
.b
, szmods
);
579 string_delete (&mods
);
582 case 'B': /* tuple T */
584 return dlang_parse_tuple (decl
, mangled
);
589 string_append (decl
, "none");
593 string_append (decl
, "void");
597 string_append (decl
, "byte");
601 string_append (decl
, "ubyte");
605 string_append (decl
, "short");
609 string_append (decl
, "ushort");
613 string_append (decl
, "int");
617 string_append (decl
, "uint");
621 string_append (decl
, "long");
625 string_append (decl
, "ulong");
629 string_append (decl
, "float");
633 string_append (decl
, "double");
637 string_append (decl
, "real");
640 /* Imaginary and Complex types */
643 string_append (decl
, "ifloat");
647 string_append (decl
, "idouble");
651 string_append (decl
, "ireal");
655 string_append (decl
, "cfloat");
659 string_append (decl
, "cdouble");
663 string_append (decl
, "creal");
669 string_append (decl
, "bool");
673 string_append (decl
, "char");
677 string_append (decl
, "wchar");
681 string_append (decl
, "dchar");
689 string_append (decl
, "cent");
693 string_append (decl
, "ucent");
698 default: /* unhandled */
703 /* Extract the identifier from MANGLED and append it to DECL.
704 Return the remaining string on success or NULL on failure. */
706 dlang_identifier (string
*decl
, const char *mangled
,
707 enum dlang_symbol_kinds kind
)
712 if (mangled
== NULL
|| *mangled
== '\0')
715 len
= strtol (mangled
, &endptr
, 10);
717 if (endptr
== NULL
|| len
<= 0)
720 /* In template parameter symbols, the first character of the mangled
721 name can be a digit. This causes ambiguity issues because the
722 digits of the two numbers are adjacent. */
723 if (kind
== dlang_template_param
)
727 int saved
= string_length (decl
);
729 /* Work backwards until a match is found. */
730 for (pend
= endptr
; endptr
!= NULL
; pend
--)
734 /* Reached the beginning of the pointer to the name length,
735 try parsing the entire symbol. */
743 /* Check whether template parameter is a function with a valid
744 return type or an untyped identifier. */
745 if (ISDIGIT (*mangled
))
746 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_ident
);
747 else if (strncmp (mangled
, "_D", 2) == 0)
750 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_function
);
753 /* Check for name length mismatch. */
754 if (mangled
&& (mangled
- pend
) == psize
)
758 string_setlength (decl
, saved
);
761 /* No match on any combinations. */
766 if (strlen (endptr
) < (size_t) len
)
771 /* May be a template instance. */
772 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
773 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
774 return dlang_parse_template (decl
, mangled
, len
);
779 if (strncmp (mangled
, "__ctor", len
) == 0)
781 /* Constructor symbol for a class/struct. */
782 string_append (decl
, "this");
786 else if (strncmp (mangled
, "__dtor", len
) == 0)
788 /* Destructor symbol for a class/struct. */
789 string_append (decl
, "~this");
793 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
795 /* The static initialiser for a given symbol. */
796 string_append (decl
, "init$");
800 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
802 /* The vtable symbol for a given class. */
803 string_prepend (decl
, "vtable for ");
804 string_setlength (decl
, string_length (decl
) - 1);
811 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
813 /* The classinfo symbol for a given class. */
814 string_prepend (decl
, "ClassInfo for ");
815 string_setlength (decl
, string_length (decl
) - 1);
822 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
824 /* Postblit symbol for a struct. */
825 string_append (decl
, "this(this)");
832 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
834 /* The interface symbol for a given class. */
835 string_prepend (decl
, "Interface for ");
836 string_setlength (decl
, string_length (decl
) - 1);
843 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
845 /* The ModuleInfo symbol for a given module. */
846 string_prepend (decl
, "ModuleInfo for ");
847 string_setlength (decl
, string_length (decl
) - 1);
854 string_appendn (decl
, mangled
, len
);
861 /* Extract the integer value from MANGLED and append it to DECL,
862 where TYPE is the type it should be represented as.
863 Return the remaining string on success or NULL on failure. */
865 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
867 if (type
== 'a' || type
== 'u' || type
== 'w')
869 /* Parse character value. */
874 long val
= strtol (mangled
, &endptr
, 10);
876 if (endptr
== NULL
|| val
< 0)
879 string_append (decl
, "'");
881 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
883 /* Represent as a character literal. */
885 string_appendn (decl
, &c
, 1);
889 /* Represent as a hexadecimal value. */
893 string_append (decl
, "\\x");
896 case 'u': /* wchar */
897 string_append (decl
, "\\u");
900 case 'w': /* dchar */
901 string_append (decl
, "\\U");
908 int digit
= val
% 16;
911 value
[--pos
] = (char)(digit
+ '0');
913 value
[--pos
] = (char)((digit
- 10) + 'a');
919 for (; width
> 0; width
--)
922 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
924 string_append (decl
, "'");
927 else if (type
== 'b')
929 /* Parse boolean value. */
931 long val
= strtol (mangled
, &endptr
, 10);
933 if (endptr
== NULL
|| val
< 0)
936 string_append (decl
, val
? "true" : "false");
941 /* Parse integer value. */
942 const char *numptr
= mangled
;
945 while (ISDIGIT (*mangled
))
950 string_appendn (decl
, numptr
, num
);
955 case 'h': /* ubyte */
956 case 't': /* ushort */
958 string_append (decl
, "u");
961 string_append (decl
, "L");
963 case 'm': /* ulong */
964 string_append (decl
, "uL");
972 /* Extract the floating-point value from MANGLED and append it to DECL.
973 Return the remaining string on success or NULL on failure. */
975 dlang_parse_real (string
*decl
, const char *mangled
)
980 /* Handle NAN and +-INF. */
981 if (strncmp (mangled
, "NAN", 3) == 0)
983 string_append (decl
, "NaN");
987 else if (strncmp (mangled
, "INF", 3) == 0)
989 string_append (decl
, "Inf");
993 else if (strncmp (mangled
, "NINF", 4) == 0)
995 string_append (decl
, "-Inf");
1000 /* Hexadecimal prefix and leading bit. */
1001 if (*mangled
== 'N')
1003 buffer
[len
++] = '-';
1007 if (!ISXDIGIT (*mangled
))
1010 buffer
[len
++] = '0';
1011 buffer
[len
++] = 'x';
1012 buffer
[len
++] = *mangled
;
1013 buffer
[len
++] = '.';
1017 while (ISXDIGIT (*mangled
))
1019 buffer
[len
++] = *mangled
;
1024 if (*mangled
!= 'P')
1027 buffer
[len
++] = 'p';
1030 if (*mangled
== 'N')
1032 buffer
[len
++] = '-';
1036 while (ISDIGIT (*mangled
))
1038 buffer
[len
++] = *mangled
;
1042 /* Write out the demangled hexadecimal, rather than trying to
1043 convert the buffer into a floating-point value. */
1045 len
= strlen (buffer
);
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':
1344 case 'W': case 'R': case 'Y':
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 /* Skip over anonymous symbols. */
1366 while (*mangled
== '0')
1369 mangled
= dlang_identifier (decl
, mangled
, kind
);
1371 if (mangled
&& dlang_call_convention_p (mangled
))
1374 const char *start
= NULL
;
1377 /* Skip over 'this' parameter. */
1378 if (*mangled
== 'M')
1381 /* We have reached here because we expect an extern(Pascal) function.
1382 However this is so rare, that it is more likely a template value
1383 parameter. Since this can't be assumed, first attempt parsing
1384 the symbol as a function, and then back out on failure. */
1385 if (*mangled
== 'V')
1388 checkpoint
= string_length (decl
);
1391 /* Save the type modifiers for appending at the end. */
1392 string_init (&mods
);
1393 mangled
= dlang_type_modifiers (&mods
, mangled
);
1395 /* Skip over calling convention and attributes in qualified name. */
1396 saved
= string_length (decl
);
1397 mangled
= dlang_call_convention (decl
, mangled
);
1398 mangled
= dlang_attributes (decl
, mangled
);
1399 string_setlength (decl
, saved
);
1401 string_append (decl
, "(");
1402 mangled
= dlang_function_args (decl
, mangled
);
1403 string_append (decl
, ")");
1405 /* Add any const/immutable/shared modifier. */
1406 string_appendn (decl
, mods
.b
, string_length (&mods
));
1407 string_delete (&mods
);
1409 if (mangled
== NULL
&& checkpoint
!= 0)
1412 string_setlength (decl
, checkpoint
);
1416 while (mangled
&& ISDIGIT (*mangled
));
1418 /* Only top-level symbols or function template parameters have
1419 a type that needs checking. */
1420 if (kind
== dlang_top_level
|| kind
== dlang_function
)
1422 /* Artificial symbols end with 'Z' and have no type. */
1423 if (mangled
&& *mangled
== 'Z')
1427 saved
= string_length (decl
);
1428 mangled
= dlang_type (decl
, mangled
);
1429 string_setlength (decl
, saved
);
1432 /* Check that the entire symbol was successfully demangled. */
1433 if (kind
== dlang_top_level
)
1435 if (mangled
== NULL
|| *mangled
!= '\0')
1443 /* Demangle the tuple from MANGLED and append it to DECL.
1444 Return the remaining string on success or NULL on failure. */
1446 dlang_parse_tuple (string
*decl
, const char *mangled
)
1449 long elements
= strtol (mangled
, &endptr
, 10);
1451 if (endptr
== NULL
|| elements
< 0)
1455 string_append (decl
, "Tuple!(");
1459 mangled
= dlang_type (decl
, mangled
);
1461 string_append (decl
, ", ");
1464 string_append (decl
, ")");
1468 /* Demangle the argument list from MANGLED and append it to DECL.
1469 Return the remaining string on success or NULL on failure. */
1471 dlang_template_args (string
*decl
, const char *mangled
)
1475 while (mangled
&& *mangled
!= '\0')
1479 case 'Z': /* End of parameter list. */
1485 string_append (decl
, ", ");
1487 /* Skip over specialised template prefix. */
1488 if (*mangled
== 'H')
1493 case 'S': /* Symbol parameter. */
1495 mangled
= dlang_parse_symbol (decl
, mangled
, dlang_template_param
);
1497 case 'T': /* Type parameter. */
1499 mangled
= dlang_type (decl
, mangled
);
1501 case 'V': /* Value parameter. */
1506 /* Peek at the type. */
1510 /* In the few instances where the type is actually desired in
1511 the output, it should precede the value from dlang_value. */
1512 string_init (&name
);
1513 mangled
= dlang_type (&name
, mangled
);
1514 string_need (&name
, 1);
1517 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1518 string_delete (&name
);
1530 /* Extract and demangle the template symbol in MANGLED, expected to
1531 be made up of LEN characters, and append it to DECL.
1532 Returns the remaining signature on success or NULL on failure. */
1534 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1536 const char *start
= mangled
;
1538 /* Template instance names have the types and values of its parameters
1541 TemplateInstanceName:
1542 Number __T LName TemplateArgs Z
1543 Number __U LName TemplateArgs Z
1545 The start pointer should be at the above location, and LEN should be
1546 the value of the decoded number.
1549 /* Template symbol. */
1550 if (!ISDIGIT (mangled
[3]) || mangled
[3] == '0')
1555 /* Template identifier. */
1556 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1558 /* Template arguments. */
1559 string_append (decl
, "!(");
1560 mangled
= dlang_template_args (decl
, mangled
);
1561 string_append (decl
, ")");
1563 /* Check for template name length mismatch. */
1564 if (mangled
&& (mangled
- start
) != len
)
1570 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1571 signature on success or NULL on failure. */
1574 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1577 char *demangled
= NULL
;
1579 if (mangled
== NULL
|| *mangled
== '\0')
1582 if (strncmp (mangled
, "_D", 2) != 0)
1585 string_init (&decl
);
1587 if (strcmp (mangled
, "_Dmain") == 0)
1589 string_append (&decl
, "D main");
1595 if (dlang_parse_symbol (&decl
, mangled
, dlang_top_level
) == NULL
)
1596 string_delete (&decl
);
1599 if (string_length (&decl
) > 0)
1601 string_need (&decl
, 1);