]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libiberty/d-demangle.c
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. */
35 #include "safe-ctype.h"
37 #include <sys/types.h>
46 #include "libiberty.h"
48 /* A mini string-handling package */
50 typedef struct string
/* Beware: these aren't required to be */
51 { /* '\0' terminated. */
52 char *b
; /* pointer to start of string */
53 char *p
; /* pointer after last character */
54 char *e
; /* pointer after end of allocated space */
58 string_need (string
*s
, int n
)
68 s
->p
= s
->b
= XNEWVEC (char, n
);
71 else if (s
->e
- s
->p
< n
)
76 s
->b
= XRESIZEVEC (char, s
->b
, n
);
83 string_delete (string
*s
)
88 s
->b
= s
->e
= s
->p
= NULL
;
93 string_init (string
*s
)
95 s
->b
= s
->p
= s
->e
= NULL
;
99 string_length (string
*s
)
109 string_setlength (string
*s
, int n
)
111 if (n
- string_length (s
) < 0)
118 string_append (string
*p
, const char *s
)
127 string_appendn (string
*p
, const char *s
, int n
)
138 string_prependn (string
*p
, const char *s
, int n
)
145 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
155 string_prepend (string
*p
, const char *s
)
157 if (s
!= NULL
&& *s
!= '\0')
159 string_prependn (p
, s
, strlen (s
));
163 /* What kinds of symbol we could be parsing. */
164 enum dlang_symbol_kinds
166 /* Top-level symbol, needs it's type checked. */
168 /* Function symbol, needs it's type checked. */
170 /* Strongly typed name, such as for classes, structs and enums. */
172 /* Template identifier. */
173 dlang_template_ident
,
174 /* Template symbol parameter. */
178 /* Prototypes for forward referenced functions */
179 static const char *dlang_function_args (string
*, const char *);
181 static const char *dlang_type (string
*, const char *);
183 static const char *dlang_value (string
*, const char *, const char *, char);
185 static const char *dlang_parse_qualified (string
*, const char *,
186 enum dlang_symbol_kinds
);
188 static const char *dlang_parse_mangle (string
*, const char *,
189 enum dlang_symbol_kinds
);
191 static const char *dlang_parse_tuple (string
*, const char *);
193 static const char *dlang_parse_template (string
*, const char *, long);
196 /* Extract the number from MANGLED, and assign the result to RET.
197 Return the remaining string on success or NULL on failure. */
199 dlang_number (const char *mangled
, long *ret
)
201 /* Return NULL if trying to extract something that isn't a digit. */
202 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
207 while (ISDIGIT (*mangled
))
211 /* If an overflow occured when multiplying by ten, the result
212 will not be a multiple of ten. */
213 if ((*ret
% 10) != 0)
216 (*ret
) += mangled
[0] - '0';
220 if (*mangled
== '\0' || *ret
< 0)
226 /* Extract the hex-digit from MANGLED, and assign the result to RET.
227 Return the remaining string on success or NULL on failure. */
229 dlang_hexdigit (const char *mangled
, char *ret
)
233 /* Return NULL if trying to extract something that isn't a hexdigit. */
234 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
239 (*ret
) = (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
245 (*ret
) = (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
247 (*ret
) = (*ret
<< 4) | (c
- '0');
254 /* Demangle the calling convention from MANGLED and append it to DECL.
255 Return the remaining string on success or NULL on failure. */
257 dlang_call_convention (string
*decl
, const char *mangled
)
259 if (mangled
== NULL
|| *mangled
== '\0')
269 string_append (decl
, "extern(C) ");
271 case 'W': /* (Windows) */
273 string_append (decl
, "extern(Windows) ");
275 case 'V': /* (Pascal) */
277 string_append (decl
, "extern(Pascal) ");
279 case 'R': /* (C++) */
281 string_append (decl
, "extern(C++) ");
283 case 'Y': /* (Objective-C) */
285 string_append (decl
, "extern(Objective-C) ");
294 /* Extract the type modifiers from MANGLED and append them to DECL.
295 Returns the remaining signature on success or NULL on failure. */
297 dlang_type_modifiers (string
*decl
, const char *mangled
)
299 if (mangled
== NULL
|| *mangled
== '\0')
304 case 'x': /* const */
306 string_append (decl
, " const");
308 case 'y': /* immutable */
310 string_append (decl
, " immutable");
312 case 'O': /* shared */
314 string_append (decl
, " shared");
315 return dlang_type_modifiers (decl
, mangled
);
318 if (*mangled
== 'g') /* wild */
321 string_append (decl
, " inout");
322 return dlang_type_modifiers (decl
, mangled
);
332 /* Demangle the D function attributes from MANGLED and append it to DECL.
333 Return the remaining string on success or NULL on failure. */
335 dlang_attributes (string
*decl
, const char *mangled
)
337 if (mangled
== NULL
|| *mangled
== '\0')
340 while (*mangled
== 'N')
347 string_append (decl
, "pure ");
349 case 'b': /* nothrow */
351 string_append (decl
, "nothrow ");
355 string_append (decl
, "ref ");
357 case 'd': /* @property */
359 string_append (decl
, "@property ");
361 case 'e': /* @trusted */
363 string_append (decl
, "@trusted ");
365 case 'f': /* @safe */
367 string_append (decl
, "@safe ");
372 /* inout parameter is represented as 'Ng'.
373 vector parameter is represented as 'Nh'.
374 return paramenter is represented as 'Nk'.
375 If we see this, then we know we're really in the
376 parameter list. Rewind and break. */
379 case 'i': /* @nogc */
381 string_append (decl
, "@nogc ");
383 case 'j': /* return */
385 string_append (decl
, "return ");
387 case 'l': /* scope */
389 string_append (decl
, "scope ");
392 default: /* unknown attribute */
401 /* Demangle the function type from MANGLED and append it to DECL.
402 Return the remaining string on success or NULL on failure. */
404 dlang_function_type (string
*decl
, const char *mangled
)
406 string attr
, args
, type
;
407 size_t szattr
, szargs
, sztype
;
409 if (mangled
== NULL
|| *mangled
== '\0')
412 /* The order of the mangled string is:
413 CallConvention FuncAttrs Arguments ArgClose Type
415 The demangled string is re-ordered as:
416 CallConvention Type Arguments FuncAttrs
422 /* Function call convention. */
423 mangled
= dlang_call_convention (decl
, mangled
);
425 /* Function attributes. */
426 mangled
= dlang_attributes (&attr
, mangled
);
427 szattr
= string_length (&attr
);
429 /* Function arguments. */
430 mangled
= dlang_function_args (&args
, mangled
);
431 szargs
= string_length (&args
);
433 /* Function return type. */
434 mangled
= dlang_type (&type
, mangled
);
435 sztype
= string_length (&type
);
437 /* Append to decl in order. */
438 string_appendn (decl
, type
.b
, sztype
);
439 string_append (decl
, "(");
440 string_appendn (decl
, args
.b
, szargs
);
441 string_append (decl
, ") ");
442 string_appendn (decl
, attr
.b
, szattr
);
444 string_delete (&attr
);
445 string_delete (&args
);
446 string_delete (&type
);
450 /* Demangle the argument list from MANGLED and append it to DECL.
451 Return the remaining string on success or NULL on failure. */
453 dlang_function_args (string
*decl
, const char *mangled
)
457 while (mangled
&& *mangled
!= '\0')
461 case 'X': /* (variadic T t...) style. */
463 string_append (decl
, "...");
465 case 'Y': /* (variadic T t, ...) style. */
468 string_append (decl
, ", ");
469 string_append (decl
, "...");
471 case 'Z': /* Normal function. */
477 string_append (decl
, ", ");
479 if (*mangled
== 'M') /* scope(T) */
482 string_append (decl
, "scope ");
485 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
488 string_append (decl
, "return ");
493 case 'J': /* out(T) */
495 string_append (decl
, "out ");
497 case 'K': /* ref(T) */
499 string_append (decl
, "ref ");
501 case 'L': /* lazy(T) */
503 string_append (decl
, "lazy ");
506 mangled
= dlang_type (decl
, mangled
);
512 /* Demangle the type from MANGLED and append it to DECL.
513 Return the remaining string on success or NULL on failure. */
515 dlang_type (string
*decl
, const char *mangled
)
517 if (mangled
== NULL
|| *mangled
== '\0')
522 case 'O': /* shared(T) */
524 string_append (decl
, "shared(");
525 mangled
= dlang_type (decl
, mangled
);
526 string_append (decl
, ")");
528 case 'x': /* const(T) */
530 string_append (decl
, "const(");
531 mangled
= dlang_type (decl
, mangled
);
532 string_append (decl
, ")");
534 case 'y': /* immutable(T) */
536 string_append (decl
, "immutable(");
537 mangled
= dlang_type (decl
, mangled
);
538 string_append (decl
, ")");
542 if (*mangled
== 'g') /* wild(T) */
545 string_append (decl
, "inout(");
546 mangled
= dlang_type (decl
, mangled
);
547 string_append (decl
, ")");
550 else if (*mangled
== 'h') /* vector(T) */
553 string_append (decl
, "__vector(");
554 mangled
= dlang_type (decl
, mangled
);
555 string_append (decl
, ")");
560 case 'A': /* dynamic array (T[]) */
562 mangled
= dlang_type (decl
, mangled
);
563 string_append (decl
, "[]");
565 case 'G': /* static array (T[N]) */
572 while (ISDIGIT (*mangled
))
577 mangled
= dlang_type (decl
, mangled
);
578 string_append (decl
, "[");
579 string_appendn (decl
, numptr
, num
);
580 string_append (decl
, "]");
583 case 'H': /* associative array (T[T]) */
590 mangled
= dlang_type (&type
, mangled
);
591 sztype
= string_length (&type
);
593 mangled
= dlang_type (decl
, mangled
);
594 string_append (decl
, "[");
595 string_appendn (decl
, type
.b
, sztype
);
596 string_append (decl
, "]");
598 string_delete (&type
);
601 case 'P': /* pointer (T*) */
603 /* Function pointer types don't include the trailing asterisk. */
606 case 'F': case 'U': case 'W':
607 case 'V': case 'R': case 'Y':
608 mangled
= dlang_function_type (decl
, mangled
);
609 string_append (decl
, "function");
612 mangled
= dlang_type (decl
, mangled
);
613 string_append (decl
, "*");
615 case 'I': /* ident T */
616 case 'C': /* class T */
617 case 'S': /* struct T */
618 case 'E': /* enum T */
619 case 'T': /* typedef T */
621 return dlang_parse_qualified (decl
, mangled
, dlang_type_name
);
622 case 'D': /* delegate T */
629 mangled
= dlang_type_modifiers (&mods
, mangled
);
630 szmods
= string_length (&mods
);
632 mangled
= dlang_function_type (decl
, mangled
);
633 string_append (decl
, "delegate");
634 string_appendn (decl
, mods
.b
, szmods
);
636 string_delete (&mods
);
639 case 'B': /* tuple T */
641 return dlang_parse_tuple (decl
, mangled
);
646 string_append (decl
, "none");
650 string_append (decl
, "void");
654 string_append (decl
, "byte");
658 string_append (decl
, "ubyte");
662 string_append (decl
, "short");
666 string_append (decl
, "ushort");
670 string_append (decl
, "int");
674 string_append (decl
, "uint");
678 string_append (decl
, "long");
682 string_append (decl
, "ulong");
686 string_append (decl
, "float");
690 string_append (decl
, "double");
694 string_append (decl
, "real");
697 /* Imaginary and Complex types */
700 string_append (decl
, "ifloat");
704 string_append (decl
, "idouble");
708 string_append (decl
, "ireal");
712 string_append (decl
, "cfloat");
716 string_append (decl
, "cdouble");
720 string_append (decl
, "creal");
726 string_append (decl
, "bool");
730 string_append (decl
, "char");
734 string_append (decl
, "wchar");
738 string_append (decl
, "dchar");
746 string_append (decl
, "cent");
750 string_append (decl
, "ucent");
755 default: /* unhandled */
760 /* Extract the identifier from MANGLED and append it to DECL.
761 Return the remaining string on success or NULL on failure. */
763 dlang_identifier (string
*decl
, const char *mangled
,
764 enum dlang_symbol_kinds kind
)
767 const char *endptr
= dlang_number (mangled
, &len
);
769 if (endptr
== NULL
|| len
== 0)
772 /* In template parameter symbols, the first character of the mangled
773 name can be a digit. This causes ambiguity issues because the
774 digits of the two numbers are adjacent. */
775 if (kind
== dlang_template_param
)
779 int saved
= string_length (decl
);
781 /* Work backwards until a match is found. */
782 for (pend
= endptr
; endptr
!= NULL
; pend
--)
786 /* Reached the beginning of the pointer to the name length,
787 try parsing the entire symbol. */
795 /* Check whether template parameter is a function with a valid
796 return type or an untyped identifier. */
797 if (ISDIGIT (*mangled
))
798 mangled
= dlang_parse_qualified (decl
, mangled
,
799 dlang_template_ident
);
800 else if (strncmp (mangled
, "_D", 2) == 0)
801 mangled
= dlang_parse_mangle (decl
, mangled
, dlang_function
);
803 /* Check for name length mismatch. */
804 if (mangled
&& (mangled
- pend
) == psize
)
808 string_setlength (decl
, saved
);
811 /* No match on any combinations. */
816 if (strlen (endptr
) < (size_t) len
)
821 /* May be a template instance. */
822 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
823 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
824 return dlang_parse_template (decl
, mangled
, len
);
829 if (strncmp (mangled
, "__ctor", len
) == 0)
831 /* Constructor symbol for a class/struct. */
832 string_append (decl
, "this");
836 else if (strncmp (mangled
, "__dtor", len
) == 0)
838 /* Destructor symbol for a class/struct. */
839 string_append (decl
, "~this");
843 else if (strncmp (mangled
, "__initZ", len
+1) == 0)
845 /* The static initialiser for a given symbol. */
846 string_append (decl
, "init$");
850 else if (strncmp (mangled
, "__vtblZ", len
+1) == 0)
852 /* The vtable symbol for a given class. */
853 string_prepend (decl
, "vtable for ");
854 string_setlength (decl
, string_length (decl
) - 1);
861 if (strncmp (mangled
, "__ClassZ", len
+1) == 0)
863 /* The classinfo symbol for a given class. */
864 string_prepend (decl
, "ClassInfo for ");
865 string_setlength (decl
, string_length (decl
) - 1);
872 if (strncmp (mangled
, "__postblitMFZ", len
+3) == 0)
874 /* Postblit symbol for a struct. */
875 string_append (decl
, "this(this)");
882 if (strncmp (mangled
, "__InterfaceZ", len
+1) == 0)
884 /* The interface symbol for a given class. */
885 string_prepend (decl
, "Interface for ");
886 string_setlength (decl
, string_length (decl
) - 1);
893 if (strncmp (mangled
, "__ModuleInfoZ", len
+1) == 0)
895 /* The ModuleInfo symbol for a given module. */
896 string_prepend (decl
, "ModuleInfo for ");
897 string_setlength (decl
, string_length (decl
) - 1);
904 string_appendn (decl
, mangled
, len
);
911 /* Extract the integer value from MANGLED and append it to DECL,
912 where TYPE is the type it should be represented as.
913 Return the remaining string on success or NULL on failure. */
915 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
917 if (type
== 'a' || type
== 'u' || type
== 'w')
919 /* Parse character value. */
925 mangled
= dlang_number (mangled
, &val
);
929 string_append (decl
, "'");
931 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
933 /* Represent as a character literal. */
935 string_appendn (decl
, &c
, 1);
939 /* Represent as a hexadecimal value. */
943 string_append (decl
, "\\x");
946 case 'u': /* wchar */
947 string_append (decl
, "\\u");
950 case 'w': /* dchar */
951 string_append (decl
, "\\U");
958 int digit
= val
% 16;
961 value
[--pos
] = (char)(digit
+ '0');
963 value
[--pos
] = (char)((digit
- 10) + 'a');
969 for (; width
> 0; width
--)
972 string_appendn (decl
, &(value
[pos
]), 10 - pos
);
974 string_append (decl
, "'");
976 else if (type
== 'b')
978 /* Parse boolean value. */
981 mangled
= dlang_number (mangled
, &val
);
985 string_append (decl
, val
? "true" : "false");
989 /* Parse integer value. */
990 const char *numptr
= mangled
;
993 if (! ISDIGIT (*mangled
))
996 while (ISDIGIT (*mangled
))
1001 string_appendn (decl
, numptr
, num
);
1003 /* Append suffix. */
1006 case 'h': /* ubyte */
1007 case 't': /* ushort */
1008 case 'k': /* uint */
1009 string_append (decl
, "u");
1011 case 'l': /* long */
1012 string_append (decl
, "L");
1014 case 'm': /* ulong */
1015 string_append (decl
, "uL");
1023 /* Extract the floating-point value from MANGLED and append it to DECL.
1024 Return the remaining string on success or NULL on failure. */
1026 dlang_parse_real (string
*decl
, const char *mangled
)
1031 /* Handle NAN and +-INF. */
1032 if (strncmp (mangled
, "NAN", 3) == 0)
1034 string_append (decl
, "NaN");
1038 else if (strncmp (mangled
, "INF", 3) == 0)
1040 string_append (decl
, "Inf");
1044 else if (strncmp (mangled
, "NINF", 4) == 0)
1046 string_append (decl
, "-Inf");
1051 /* Hexadecimal prefix and leading bit. */
1052 if (*mangled
== 'N')
1054 buffer
[len
++] = '-';
1058 if (!ISXDIGIT (*mangled
))
1061 buffer
[len
++] = '0';
1062 buffer
[len
++] = 'x';
1063 buffer
[len
++] = *mangled
;
1064 buffer
[len
++] = '.';
1068 while (ISXDIGIT (*mangled
))
1070 buffer
[len
++] = *mangled
;
1075 if (*mangled
!= 'P')
1078 buffer
[len
++] = 'p';
1081 if (*mangled
== 'N')
1083 buffer
[len
++] = '-';
1087 while (ISDIGIT (*mangled
))
1089 buffer
[len
++] = *mangled
;
1093 /* Write out the demangled hexadecimal, rather than trying to
1094 convert the buffer into a floating-point value. */
1096 len
= strlen (buffer
);
1097 string_appendn (decl
, buffer
, len
);
1101 /* Extract the string value from MANGLED and append it to DECL.
1102 Return the remaining string on success or NULL on failure. */
1104 dlang_parse_string (string
*decl
, const char *mangled
)
1106 char type
= *mangled
;
1110 mangled
= dlang_number (mangled
, &len
);
1111 if (mangled
== NULL
|| *mangled
!= '_')
1115 string_append (decl
, "\"");
1119 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1124 /* Sanitize white and non-printable characters. */
1128 string_append (decl
, " ");
1131 string_append (decl
, "\\t");
1134 string_append (decl
, "\\n");
1137 string_append (decl
, "\\r");
1140 string_append (decl
, "\\f");
1143 string_append (decl
, "\\v");
1148 string_appendn (decl
, &val
, 1);
1151 string_append (decl
, "\\x");
1152 string_appendn (decl
, mangled
, 2);
1158 string_append (decl
, "\"");
1161 string_appendn (decl
, &type
, 1);
1166 /* Extract the static array value from MANGLED and append it to DECL.
1167 Return the remaining string on success or NULL on failure. */
1169 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1173 mangled
= dlang_number (mangled
, &elements
);
1174 if (mangled
== NULL
)
1177 string_append (decl
, "[");
1180 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1182 string_append (decl
, ", ");
1185 string_append (decl
, "]");
1189 /* Extract the associative array value from MANGLED and append it to DECL.
1190 Return the remaining string on success or NULL on failure. */
1192 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1196 mangled
= dlang_number (mangled
, &elements
);
1197 if (mangled
== NULL
)
1200 string_append (decl
, "[");
1203 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1204 string_append (decl
, ":");
1205 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1208 string_append (decl
, ", ");
1211 string_append (decl
, "]");
1215 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1216 Return the remaining string on success or NULL on failure. */
1218 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1222 mangled
= dlang_number (mangled
, &args
);
1223 if (mangled
== NULL
)
1227 string_append (decl
, name
);
1229 string_append (decl
, "(");
1232 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1234 string_append (decl
, ", ");
1237 string_append (decl
, ")");
1241 /* Extract the value from MANGLED and append it to DECL.
1242 Return the remaining string on success or NULL on failure. */
1244 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1246 if (mangled
== NULL
|| *mangled
== '\0')
1254 string_append (decl
, "null");
1257 /* Integral values. */
1260 string_append (decl
, "-");
1261 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1268 /* There really should always be an `i' before encoded numbers, but there
1269 wasn't in early versions of D2, so this case range must remain for
1270 backwards compatibility. */
1271 case '0': case '1': case '2': case '3': case '4':
1272 case '5': case '6': case '7': case '8': case '9':
1273 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1279 mangled
= dlang_parse_real (decl
, mangled
);
1282 /* Complex value. */
1285 mangled
= dlang_parse_real (decl
, mangled
);
1286 string_append (decl
, "+");
1287 if (mangled
== NULL
|| *mangled
!= 'c')
1290 mangled
= dlang_parse_real (decl
, mangled
);
1291 string_append (decl
, "i");
1294 /* String values. */
1295 case 'a': /* UTF8 */
1296 case 'w': /* UTF16 */
1297 case 'd': /* UTF32 */
1298 mangled
= dlang_parse_string (decl
, mangled
);
1305 mangled
= dlang_parse_assocarray (decl
, mangled
);
1307 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1310 /* Struct values. */
1313 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1323 /* Extract the function calling convention from MANGLED and
1324 return 1 on success or 0 on failure. */
1326 dlang_call_convention_p (const char *mangled
)
1330 case 'F': case 'U': case 'V':
1331 case 'W': case 'R': case 'Y':
1339 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1340 Returns the remaining signature on success or NULL on failure. */
1342 dlang_parse_mangle (string
*decl
, const char *mangled
,
1343 enum dlang_symbol_kinds kind
)
1345 /* A D mangled symbol is comprised of both scope and type information.
1348 _D QualifiedName Type
1349 _D QualifiedName M Type
1352 The caller should have guaranteed that the start pointer is at the
1357 mangled
= dlang_parse_qualified (decl
, mangled
, dlang_top_level
);
1359 if (mangled
!= NULL
)
1361 /* Artificial symbols end with 'Z' and have no type. */
1362 if (*mangled
== 'Z')
1369 /* Skip over 'this' parameter. */
1370 if (*mangled
== 'M')
1373 /* Save the type modifiers for appending at the end if needed. */
1374 string_init (&mods
);
1375 mangled
= dlang_type_modifiers (&mods
, mangled
);
1377 if (mangled
&& dlang_call_convention_p (mangled
))
1379 /* Skip over calling convention and attributes. */
1380 saved
= string_length (decl
);
1381 mangled
= dlang_call_convention (decl
, mangled
);
1382 mangled
= dlang_attributes (decl
, mangled
);
1383 string_setlength (decl
, saved
);
1385 string_append (decl
, "(");
1386 mangled
= dlang_function_args (decl
, mangled
);
1387 string_append (decl
, ")");
1389 /* Add any const/immutable/shared modifier. */
1390 string_appendn (decl
, mods
.b
, string_length (&mods
));
1393 /* Consume the decl type of symbol. */
1394 saved
= string_length (decl
);
1395 mangled
= dlang_type (decl
, mangled
);
1396 string_setlength (decl
, saved
);
1398 string_delete (&mods
);
1402 /* Check that the entire symbol was successfully demangled. */
1403 if (kind
== dlang_top_level
)
1405 if (mangled
== NULL
|| *mangled
!= '\0')
1412 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1413 Returns the remaining signature on success or NULL on failure. */
1415 dlang_parse_qualified (string
*decl
, const char *mangled
,
1416 enum dlang_symbol_kinds kind
)
1418 /* Qualified names are identifiers separated by their encoded length.
1419 Nested functions also encode their argument types without specifying
1424 SymbolName QualifiedName
1425 SymbolName TypeFunctionNoReturn QualifiedName
1426 SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
1428 The start pointer should be at the above location.
1434 string_append (decl
, ".");
1436 /* Skip over anonymous symbols. */
1437 while (*mangled
== '0')
1440 mangled
= dlang_identifier (decl
, mangled
, kind
);
1442 /* Consume the encoded arguments. However if this is not followed by the
1443 next encoded length, then this is not a continuation of a qualified
1444 name, in which case we backtrack and return the current unconsumed
1445 position of the mangled decl. */
1446 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1448 const char *start
= mangled
;
1449 int saved
= string_length (decl
);
1451 /* Skip over 'this' parameter and type modifiers. */
1452 if (*mangled
== 'M')
1455 mangled
= dlang_type_modifiers (decl
, mangled
);
1456 string_setlength (decl
, saved
);
1459 /* The rule we expect to match in the mangled string is:
1461 TypeFunctionNoReturn:
1462 CallConvention FuncAttrs Arguments ArgClose
1464 The calling convention and function attributes are not included
1465 in the demangled string. */
1466 mangled
= dlang_call_convention (decl
, mangled
);
1467 mangled
= dlang_attributes (decl
, mangled
);
1468 string_setlength (decl
, saved
);
1470 string_append (decl
, "(");
1471 mangled
= dlang_function_args (decl
, mangled
);
1472 string_append (decl
, ")");
1474 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
1476 /* Did not match the rule we were looking for. */
1478 string_setlength (decl
, saved
);
1482 while (mangled
&& ISDIGIT (*mangled
));
1487 /* Demangle the tuple from MANGLED and append it to DECL.
1488 Return the remaining string on success or NULL on failure. */
1490 dlang_parse_tuple (string
*decl
, const char *mangled
)
1494 mangled
= dlang_number (mangled
, &elements
);
1495 if (mangled
== NULL
)
1498 string_append (decl
, "Tuple!(");
1502 mangled
= dlang_type (decl
, mangled
);
1504 string_append (decl
, ", ");
1507 string_append (decl
, ")");
1511 /* Demangle the argument list from MANGLED and append it to DECL.
1512 Return the remaining string on success or NULL on failure. */
1514 dlang_template_args (string
*decl
, const char *mangled
)
1518 while (mangled
&& *mangled
!= '\0')
1522 case 'Z': /* End of parameter list. */
1528 string_append (decl
, ", ");
1530 /* Skip over specialised template prefix. */
1531 if (*mangled
== 'H')
1536 case 'S': /* Symbol parameter. */
1538 mangled
= dlang_identifier (decl
, mangled
, dlang_template_param
);
1540 case 'T': /* Type parameter. */
1542 mangled
= dlang_type (decl
, mangled
);
1544 case 'V': /* Value parameter. */
1549 /* Peek at the type. */
1553 /* In the few instances where the type is actually desired in
1554 the output, it should precede the value from dlang_value. */
1555 string_init (&name
);
1556 mangled
= dlang_type (&name
, mangled
);
1557 string_need (&name
, 1);
1560 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1561 string_delete (&name
);
1573 /* Extract and demangle the template symbol in MANGLED, expected to
1574 be made up of LEN characters, and append it to DECL.
1575 Returns the remaining signature on success or NULL on failure. */
1577 dlang_parse_template (string
*decl
, const char *mangled
, long len
)
1579 const char *start
= mangled
;
1581 /* Template instance names have the types and values of its parameters
1584 TemplateInstanceName:
1585 Number __T LName TemplateArgs Z
1586 Number __U LName TemplateArgs Z
1588 The start pointer should be at the above location, and LEN should be
1589 the value of the decoded number.
1592 /* Template symbol. */
1593 if (!ISDIGIT (mangled
[3]) || mangled
[3] == '0')
1598 /* Template identifier. */
1599 mangled
= dlang_identifier (decl
, mangled
, dlang_template_ident
);
1601 /* Template arguments. */
1602 string_append (decl
, "!(");
1603 mangled
= dlang_template_args (decl
, mangled
);
1604 string_append (decl
, ")");
1606 /* Check for template name length mismatch. */
1607 if (mangled
&& (mangled
- start
) != len
)
1613 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1614 signature on success or NULL on failure. */
1617 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1620 char *demangled
= NULL
;
1622 if (mangled
== NULL
|| *mangled
== '\0')
1625 if (strncmp (mangled
, "_D", 2) != 0)
1628 string_init (&decl
);
1630 if (strcmp (mangled
, "_Dmain") == 0)
1632 string_append (&decl
, "D main");
1636 if (dlang_parse_mangle (&decl
, mangled
, dlang_top_level
) == NULL
)
1637 string_delete (&decl
);
1640 if (string_length (&decl
) > 0)
1642 string_need (&decl
, 1);