1 /* Demangler for the D programming language
2 Copyright (C) 2014-2021 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 #if 0 /* in valgrind */
38 #endif /* ! in valgrind */
40 #if 0 /* in valgrind */
41 #include "safe-ctype.h"
42 #endif /* ! in valgrind */
44 #if 0 /* in valgrind */
45 #include <sys/types.h>
48 #endif /* ! in valgrind */
50 #if 0 /* in valgrind */
54 #endif /* ! in valgrind */
56 #if 0 /* in valgrind */
58 #include "libiberty.h"
59 #endif /* ! in valgrind */
61 #include "vg_libciface.h"
65 #include "safe-ctype.h"
68 #define ULONG_MAX (~0UL)
71 #define UINT_MAX (~0U)
74 /* A mini string-handling package */
76 typedef struct string
/* Beware: these aren't required to be */
77 { /* '\0' terminated. */
78 char *b
; /* pointer to start of string */
79 char *p
; /* pointer after last character */
80 char *e
; /* pointer after end of allocated space */
84 string_need (string
*s
, size_t n
)
94 s
->p
= s
->b
= XNEWVEC (char, n
);
97 else if ((size_t) (s
->e
- s
->p
) < n
)
102 s
->b
= XRESIZEVEC (char, s
->b
, n
);
109 string_delete (string
*s
)
114 s
->b
= s
->e
= s
->p
= NULL
;
119 string_init (string
*s
)
121 s
->b
= s
->p
= s
->e
= NULL
;
125 string_length (string
*s
)
135 string_setlength (string
*s
, int n
)
137 if (n
- string_length (s
) < 0)
144 string_append (string
*p
, const char *s
)
146 size_t n
= strlen (s
);
153 string_appendn (string
*p
, const char *s
, size_t n
)
164 string_prependn (string
*p
, const char *s
, size_t n
)
171 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
181 string_prepend (string
*p
, const char *s
)
183 if (s
!= NULL
&& *s
!= '\0')
185 string_prependn (p
, s
, strlen (s
));
189 /* Demangle information structure we pass around. */
192 /* The string we are demangling. */
194 /* The index of the last back reference. */
198 /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
199 #define TEMPLATE_LENGTH_UNKNOWN (-1UL)
201 /* Prototypes for forward referenced functions */
202 static const char *dlang_function_type (string
*, const char *,
203 struct dlang_info
*);
205 static const char *dlang_function_args (string
*, const char *,
206 struct dlang_info
*);
208 static const char *dlang_type (string
*, const char *, struct dlang_info
*);
210 static const char *dlang_value (string
*, const char *, const char *, char);
212 static const char *dlang_parse_qualified (string
*, const char *,
213 struct dlang_info
*, int);
215 static const char *dlang_parse_mangle (string
*, const char *,
216 struct dlang_info
*);
218 static const char *dlang_parse_tuple (string
*, const char *,
219 struct dlang_info
*);
221 static const char *dlang_parse_template (string
*, const char *,
222 struct dlang_info
*, unsigned long);
224 static const char *dlang_lname (string
*, const char *, unsigned long);
227 /* Extract the number from MANGLED, and assign the result to RET.
228 Return the remaining string on success or NULL on failure.
229 A result larger than UINT_MAX is considered a failure. */
231 dlang_number (const char *mangled
, unsigned long *ret
)
233 /* Return NULL if trying to extract something that isn't a digit. */
234 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
237 unsigned long val
= 0;
239 while (ISDIGIT (*mangled
))
241 unsigned long digit
= mangled
[0] - '0';
243 /* Check for overflow. */
244 if (val
> (UINT_MAX
- digit
) / 10)
247 val
= val
* 10 + digit
;
251 if (*mangled
== '\0')
258 /* Extract the hex-digit from MANGLED, and assign the result to RET.
259 Return the remaining string on success or NULL on failure. */
261 dlang_hexdigit (const char *mangled
, char *ret
)
265 /* Return NULL if trying to extract something that isn't a hexdigit. */
266 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
271 (*ret
) = (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
277 (*ret
) = (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
279 (*ret
) = (*ret
<< 4) | (c
- '0');
286 /* Extract the function calling convention from MANGLED and
287 return 1 on success or 0 on failure. */
289 dlang_call_convention_p (const char *mangled
)
293 case 'F': case 'U': case 'V':
294 case 'W': case 'R': case 'Y':
302 /* Extract the back reference position from MANGLED, and assign the result
303 to RET. Return the remaining string on success or NULL on failure.
304 A result <= 0 is a failure. */
306 dlang_decode_backref (const char *mangled
, long *ret
)
308 /* Return NULL if trying to extract something that isn't a digit. */
309 if (mangled
== NULL
|| !ISALPHA (*mangled
))
312 /* Any identifier or non-basic type that has been emitted to the mangled
313 symbol before will not be emitted again, but is referenced by a special
314 sequence encoding the relative position of the original occurrence in the
317 Numbers in back references are encoded with base 26 by upper case letters
318 A-Z for higher digits but lower case letters a-z for the last digit.
325 unsigned long val
= 0;
327 while (ISALPHA (*mangled
))
329 /* Check for overflow. */
330 if (val
> (ULONG_MAX
- 25) / 26)
335 if (mangled
[0] >= 'a' && mangled
[0] <= 'z')
337 val
+= mangled
[0] - 'a';
344 val
+= mangled
[0] - 'A';
351 /* Extract the symbol pointed at by the back reference and assign the result
352 to RET. Return the remaining string on success or NULL on failure. */
354 dlang_backref (const char *mangled
, const char **ret
, struct dlang_info
*info
)
358 if (mangled
== NULL
|| *mangled
!= 'Q')
361 /* Position of 'Q'. */
362 const char *qpos
= mangled
;
366 mangled
= dlang_decode_backref (mangled
, &refpos
);
370 if (refpos
> qpos
- info
->s
)
373 /* Set the position of the back reference. */
374 (*ret
) = qpos
- refpos
;
379 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
380 Return the remaining string on success or NULL on failure. */
382 dlang_symbol_backref (string
*decl
, const char *mangled
,
383 struct dlang_info
*info
)
385 /* An identifier back reference always points to a digit 0 to 9.
394 /* Get position of the back reference. */
395 mangled
= dlang_backref (mangled
, &backref
, info
);
397 /* Must point to a simple identifier. */
398 backref
= dlang_number (backref
, &len
);
402 backref
= dlang_lname (decl
, backref
, len
);
409 /* Demangle a back referenced type from MANGLED and append it to DECL.
410 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
411 Return the remaining string on success or NULL on failure. */
413 dlang_type_backref (string
*decl
, const char *mangled
, struct dlang_info
*info
,
416 /* A type back reference always points to a letter.
424 /* If we appear to be moving backwards through the mangle string, then
425 bail as this may be a recursive back reference. */
426 if (mangled
- info
->s
>= info
->last_backref
)
429 int save_refpos
= info
->last_backref
;
430 info
->last_backref
= mangled
- info
->s
;
432 /* Get position of the back reference. */
433 mangled
= dlang_backref (mangled
, &backref
, info
);
435 /* Must point to a type. */
437 backref
= dlang_function_type (decl
, backref
, info
);
439 backref
= dlang_type (decl
, backref
, info
);
441 info
->last_backref
= save_refpos
;
449 /* Extract the beginning of a symbol name from MANGLED and
450 return 1 on success or 0 on failure. */
452 dlang_symbol_name_p (const char *mangled
, struct dlang_info
*info
)
455 const char *qref
= mangled
;
457 if (ISDIGIT (*mangled
))
460 if (mangled
[0] == '_' && mangled
[1] == '_'
461 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
467 mangled
= dlang_decode_backref (mangled
+ 1, &ret
);
468 if (mangled
== NULL
|| ret
> qref
- info
->s
)
471 return ISDIGIT (qref
[-ret
]);
474 /* Demangle the calling convention from MANGLED and append it to DECL.
475 Return the remaining string on success or NULL on failure. */
477 dlang_call_convention (string
*decl
, const char *mangled
)
479 if (mangled
== NULL
|| *mangled
== '\0')
489 string_append (decl
, "extern(C) ");
491 case 'W': /* (Windows) */
493 string_append (decl
, "extern(Windows) ");
495 case 'V': /* (Pascal) */
497 string_append (decl
, "extern(Pascal) ");
499 case 'R': /* (C++) */
501 string_append (decl
, "extern(C++) ");
503 case 'Y': /* (Objective-C) */
505 string_append (decl
, "extern(Objective-C) ");
514 /* Extract the type modifiers from MANGLED and append them to DECL.
515 Returns the remaining signature on success or NULL on failure. */
517 dlang_type_modifiers (string
*decl
, const char *mangled
)
519 if (mangled
== NULL
|| *mangled
== '\0')
524 case 'x': /* const */
526 string_append (decl
, " const");
528 case 'y': /* immutable */
530 string_append (decl
, " immutable");
532 case 'O': /* shared */
534 string_append (decl
, " shared");
535 return dlang_type_modifiers (decl
, mangled
);
538 if (*mangled
== 'g') /* wild */
541 string_append (decl
, " inout");
542 return dlang_type_modifiers (decl
, mangled
);
552 /* Demangle the D function attributes from MANGLED and append it to DECL.
553 Return the remaining string on success or NULL on failure. */
555 dlang_attributes (string
*decl
, const char *mangled
)
557 if (mangled
== NULL
|| *mangled
== '\0')
560 while (*mangled
== 'N')
567 string_append (decl
, "pure ");
569 case 'b': /* nothrow */
571 string_append (decl
, "nothrow ");
575 string_append (decl
, "ref ");
577 case 'd': /* @property */
579 string_append (decl
, "@property ");
581 case 'e': /* @trusted */
583 string_append (decl
, "@trusted ");
585 case 'f': /* @safe */
587 string_append (decl
, "@safe ");
592 /* inout parameter is represented as 'Ng'.
593 vector parameter is represented as 'Nh'.
594 return paramenter is represented as 'Nk'.
595 If we see this, then we know we're really in the
596 parameter list. Rewind and break. */
599 case 'i': /* @nogc */
601 string_append (decl
, "@nogc ");
603 case 'j': /* return */
605 string_append (decl
, "return ");
607 case 'l': /* scope */
609 string_append (decl
, "scope ");
611 case 'm': /* @live */
613 string_append (decl
, "@live ");
616 default: /* unknown attribute */
625 /* Demangle the function type from MANGLED without the return type.
626 The arguments are appended to ARGS, the calling convention is appended
627 to CALL and attributes are appended to ATTR. Any of these can be NULL
628 to throw the information away. Return the remaining string on success
629 or NULL on failure. */
631 dlang_function_type_noreturn (string
*args
, string
*call
, string
*attr
,
632 const char *mangled
, struct dlang_info
*info
)
637 /* Skip over calling convention and attributes. */
638 mangled
= dlang_call_convention (call
? call
: &dump
, mangled
);
639 mangled
= dlang_attributes (attr
? attr
: &dump
, mangled
);
642 string_append (args
, "(");
644 mangled
= dlang_function_args (args
? args
: &dump
, mangled
, info
);
646 string_append (args
, ")");
648 string_delete (&dump
);
652 /* Demangle the function type from MANGLED and append it to DECL.
653 Return the remaining string on success or NULL on failure. */
655 dlang_function_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
657 string attr
, args
, type
;
659 if (mangled
== NULL
|| *mangled
== '\0')
662 /* The order of the mangled string is:
663 CallConvention FuncAttrs Arguments ArgClose Type
665 The demangled string is re-ordered as:
666 CallConvention Type Arguments FuncAttrs
672 mangled
= dlang_function_type_noreturn (&args
, decl
, &attr
, mangled
, info
);
674 /* Function return type. */
675 mangled
= dlang_type (&type
, mangled
, info
);
677 /* Append to decl in order. */
678 string_appendn (decl
, type
.b
, string_length (&type
));
679 string_appendn (decl
, args
.b
, string_length (&args
));
680 string_append (decl
, " ");
681 string_appendn (decl
, attr
.b
, string_length (&attr
));
683 string_delete (&attr
);
684 string_delete (&args
);
685 string_delete (&type
);
689 /* Demangle the argument list from MANGLED and append it to DECL.
690 Return the remaining string on success or NULL on failure. */
692 dlang_function_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
696 while (mangled
&& *mangled
!= '\0')
700 case 'X': /* (variadic T t...) style. */
702 string_append (decl
, "...");
704 case 'Y': /* (variadic T t, ...) style. */
707 string_append (decl
, ", ");
708 string_append (decl
, "...");
710 case 'Z': /* Normal function. */
716 string_append (decl
, ", ");
718 if (*mangled
== 'M') /* scope(T) */
721 string_append (decl
, "scope ");
724 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
727 string_append (decl
, "return ");
732 case 'I': /* in(T) */
734 string_append (decl
, "in ");
735 if (*mangled
== 'K') /* in ref(T) */
738 string_append (decl
, "ref ");
741 case 'J': /* out(T) */
743 string_append (decl
, "out ");
745 case 'K': /* ref(T) */
747 string_append (decl
, "ref ");
749 case 'L': /* lazy(T) */
751 string_append (decl
, "lazy ");
754 mangled
= dlang_type (decl
, mangled
, info
);
760 /* Demangle the type from MANGLED and append it to DECL.
761 Return the remaining string on success or NULL on failure. */
763 dlang_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
765 if (mangled
== NULL
|| *mangled
== '\0')
770 case 'O': /* shared(T) */
772 string_append (decl
, "shared(");
773 mangled
= dlang_type (decl
, mangled
, info
);
774 string_append (decl
, ")");
776 case 'x': /* const(T) */
778 string_append (decl
, "const(");
779 mangled
= dlang_type (decl
, mangled
, info
);
780 string_append (decl
, ")");
782 case 'y': /* immutable(T) */
784 string_append (decl
, "immutable(");
785 mangled
= dlang_type (decl
, mangled
, info
);
786 string_append (decl
, ")");
790 if (*mangled
== 'g') /* wild(T) */
793 string_append (decl
, "inout(");
794 mangled
= dlang_type (decl
, mangled
, info
);
795 string_append (decl
, ")");
798 else if (*mangled
== 'h') /* vector(T) */
801 string_append (decl
, "__vector(");
802 mangled
= dlang_type (decl
, mangled
, info
);
803 string_append (decl
, ")");
808 case 'A': /* dynamic array (T[]) */
810 mangled
= dlang_type (decl
, mangled
, info
);
811 string_append (decl
, "[]");
813 case 'G': /* static array (T[N]) */
820 while (ISDIGIT (*mangled
))
825 mangled
= dlang_type (decl
, mangled
, info
);
826 string_append (decl
, "[");
827 string_appendn (decl
, numptr
, num
);
828 string_append (decl
, "]");
831 case 'H': /* associative array (T[T]) */
838 mangled
= dlang_type (&type
, mangled
, info
);
839 sztype
= string_length (&type
);
841 mangled
= dlang_type (decl
, mangled
, info
);
842 string_append (decl
, "[");
843 string_appendn (decl
, type
.b
, sztype
);
844 string_append (decl
, "]");
846 string_delete (&type
);
849 case 'P': /* pointer (T*) */
851 if (!dlang_call_convention_p (mangled
))
853 mangled
= dlang_type (decl
, mangled
, info
);
854 string_append (decl
, "*");
858 case 'F': /* function T (D) */
859 case 'U': /* function T (C) */
860 case 'W': /* function T (Windows) */
861 case 'V': /* function T (Pascal) */
862 case 'R': /* function T (C++) */
863 case 'Y': /* function T (Objective-C) */
864 /* Function pointer types don't include the trailing asterisk. */
865 mangled
= dlang_function_type (decl
, mangled
, info
);
866 string_append (decl
, "function");
868 case 'C': /* class T */
869 case 'S': /* struct T */
870 case 'E': /* enum T */
871 case 'T': /* typedef T */
873 return dlang_parse_qualified (decl
, mangled
, info
, 0);
874 case 'D': /* delegate T */
881 mangled
= dlang_type_modifiers (&mods
, mangled
);
882 szmods
= string_length (&mods
);
884 /* Back referenced function type. */
886 mangled
= dlang_type_backref (decl
, mangled
, info
, 1);
888 mangled
= dlang_function_type (decl
, mangled
, info
);
890 string_append (decl
, "delegate");
891 string_appendn (decl
, mods
.b
, szmods
);
893 string_delete (&mods
);
896 case 'B': /* tuple T */
898 return dlang_parse_tuple (decl
, mangled
, info
);
903 string_append (decl
, "none");
907 string_append (decl
, "void");
911 string_append (decl
, "byte");
915 string_append (decl
, "ubyte");
919 string_append (decl
, "short");
923 string_append (decl
, "ushort");
927 string_append (decl
, "int");
931 string_append (decl
, "uint");
935 string_append (decl
, "long");
939 string_append (decl
, "ulong");
943 string_append (decl
, "float");
947 string_append (decl
, "double");
951 string_append (decl
, "real");
954 /* Imaginary and Complex types */
957 string_append (decl
, "ifloat");
961 string_append (decl
, "idouble");
965 string_append (decl
, "ireal");
969 string_append (decl
, "cfloat");
973 string_append (decl
, "cdouble");
977 string_append (decl
, "creal");
983 string_append (decl
, "bool");
987 string_append (decl
, "char");
991 string_append (decl
, "wchar");
995 string_append (decl
, "dchar");
1003 string_append (decl
, "cent");
1007 string_append (decl
, "ucent");
1012 /* Back referenced type. */
1014 return dlang_type_backref (decl
, mangled
, info
, 0);
1016 default: /* unhandled */
1021 /* Extract the identifier from MANGLED and append it to DECL.
1022 Return the remaining string on success or NULL on failure. */
1024 dlang_identifier (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1028 if (mangled
== NULL
|| *mangled
== '\0')
1031 if (*mangled
== 'Q')
1032 return dlang_symbol_backref (decl
, mangled
, info
);
1034 /* May be a template instance without a length prefix. */
1035 if (mangled
[0] == '_' && mangled
[1] == '_'
1036 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1037 return dlang_parse_template (decl
, mangled
, info
, TEMPLATE_LENGTH_UNKNOWN
);
1039 const char *endptr
= dlang_number (mangled
, &len
);
1041 if (endptr
== NULL
|| len
== 0)
1044 if (strlen (endptr
) < len
)
1049 /* May be a template instance with a length prefix. */
1050 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
1051 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1052 return dlang_parse_template (decl
, mangled
, info
, len
);
1054 return dlang_lname (decl
, mangled
, len
);
1057 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1058 with special treatment for some magic compiler generted symbols.
1059 Return the remaining string on success or NULL on failure. */
1061 dlang_lname (string
*decl
, const char *mangled
, unsigned long len
)
1066 if (strncmp (mangled
, "__ctor", len
) == 0)
1068 /* Constructor symbol for a class/struct. */
1069 string_append (decl
, "this");
1073 else if (strncmp (mangled
, "__dtor", len
) == 0)
1075 /* Destructor symbol for a class/struct. */
1076 string_append (decl
, "~this");
1080 else if (strncmp (mangled
, "__initZ", len
+ 1) == 0)
1082 /* The static initialiser for a given symbol. */
1083 string_prepend (decl
, "initializer for ");
1084 string_setlength (decl
, string_length (decl
) - 1);
1088 else if (strncmp (mangled
, "__vtblZ", len
+ 1) == 0)
1090 /* The vtable symbol for a given class. */
1091 string_prepend (decl
, "vtable for ");
1092 string_setlength (decl
, string_length (decl
) - 1);
1099 if (strncmp (mangled
, "__ClassZ", len
+ 1) == 0)
1101 /* The classinfo symbol for a given class. */
1102 string_prepend (decl
, "ClassInfo for ");
1103 string_setlength (decl
, string_length (decl
) - 1);
1110 if (strncmp (mangled
, "__postblitMFZ", len
+ 3) == 0)
1112 /* Postblit symbol for a struct. */
1113 string_append (decl
, "this(this)");
1120 if (strncmp (mangled
, "__InterfaceZ", len
+ 1) == 0)
1122 /* The interface symbol for a given class. */
1123 string_prepend (decl
, "Interface for ");
1124 string_setlength (decl
, string_length (decl
) - 1);
1131 if (strncmp (mangled
, "__ModuleInfoZ", len
+ 1) == 0)
1133 /* The ModuleInfo symbol for a given module. */
1134 string_prepend (decl
, "ModuleInfo for ");
1135 string_setlength (decl
, string_length (decl
) - 1);
1142 string_appendn (decl
, mangled
, len
);
1148 /* Extract the integer value from MANGLED and append it to DECL,
1149 where TYPE is the type it should be represented as.
1150 Return the remaining string on success or NULL on failure. */
1152 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
1154 if (type
== 'a' || type
== 'u' || type
== 'w')
1156 /* Parse character value. */
1158 int pos
= sizeof(value
);
1162 mangled
= dlang_number (mangled
, &val
);
1163 if (mangled
== NULL
)
1166 string_append (decl
, "'");
1168 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
1170 /* Represent as a character literal. */
1171 char c
= (char) val
;
1172 string_appendn (decl
, &c
, 1);
1176 /* Represent as a hexadecimal value. */
1179 case 'a': /* char */
1180 string_append (decl
, "\\x");
1183 case 'u': /* wchar */
1184 string_append (decl
, "\\u");
1187 case 'w': /* dchar */
1188 string_append (decl
, "\\U");
1195 int digit
= val
% 16;
1198 value
[--pos
] = (char)(digit
+ '0');
1200 value
[--pos
] = (char)((digit
- 10) + 'a');
1206 for (; width
> 0; width
--)
1209 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
1211 string_append (decl
, "'");
1213 else if (type
== 'b')
1215 /* Parse boolean value. */
1218 mangled
= dlang_number (mangled
, &val
);
1219 if (mangled
== NULL
)
1222 string_append (decl
, val
? "true" : "false");
1226 /* Parse integer value. */
1227 const char *numptr
= mangled
;
1230 if (! ISDIGIT (*mangled
))
1233 while (ISDIGIT (*mangled
))
1238 string_appendn (decl
, numptr
, num
);
1240 /* Append suffix. */
1243 case 'h': /* ubyte */
1244 case 't': /* ushort */
1245 case 'k': /* uint */
1246 string_append (decl
, "u");
1248 case 'l': /* long */
1249 string_append (decl
, "L");
1251 case 'm': /* ulong */
1252 string_append (decl
, "uL");
1260 /* Extract the floating-point value from MANGLED and append it to DECL.
1261 Return the remaining string on success or NULL on failure. */
1263 dlang_parse_real (string
*decl
, const char *mangled
)
1265 /* Handle NAN and +-INF. */
1266 if (strncmp (mangled
, "NAN", 3) == 0)
1268 string_append (decl
, "NaN");
1272 else if (strncmp (mangled
, "INF", 3) == 0)
1274 string_append (decl
, "Inf");
1278 else if (strncmp (mangled
, "NINF", 4) == 0)
1280 string_append (decl
, "-Inf");
1285 /* Hexadecimal prefix and leading bit. */
1286 if (*mangled
== 'N')
1288 string_append (decl
, "-");
1292 if (!ISXDIGIT (*mangled
))
1295 string_append (decl
, "0x");
1296 string_appendn (decl
, mangled
, 1);
1297 string_append (decl
, ".");
1301 while (ISXDIGIT (*mangled
))
1303 string_appendn (decl
, mangled
, 1);
1308 if (*mangled
!= 'P')
1311 string_append (decl
, "p");
1314 if (*mangled
== 'N')
1316 string_append (decl
, "-");
1320 while (ISDIGIT (*mangled
))
1322 string_appendn (decl
, mangled
, 1);
1329 /* Extract the string value from MANGLED and append it to DECL.
1330 Return the remaining string on success or NULL on failure. */
1332 dlang_parse_string (string
*decl
, const char *mangled
)
1334 char type
= *mangled
;
1338 mangled
= dlang_number (mangled
, &len
);
1339 if (mangled
== NULL
|| *mangled
!= '_')
1343 string_append (decl
, "\"");
1347 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1352 /* Sanitize white and non-printable characters. */
1356 string_append (decl
, " ");
1359 string_append (decl
, "\\t");
1362 string_append (decl
, "\\n");
1365 string_append (decl
, "\\r");
1368 string_append (decl
, "\\f");
1371 string_append (decl
, "\\v");
1376 string_appendn (decl
, &val
, 1);
1379 string_append (decl
, "\\x");
1380 string_appendn (decl
, mangled
, 2);
1386 string_append (decl
, "\"");
1389 string_appendn (decl
, &type
, 1);
1394 /* Extract the static array value from MANGLED and append it to DECL.
1395 Return the remaining string on success or NULL on failure. */
1397 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1399 unsigned long elements
;
1401 mangled
= dlang_number (mangled
, &elements
);
1402 if (mangled
== NULL
)
1405 string_append (decl
, "[");
1408 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1409 if (mangled
== NULL
)
1413 string_append (decl
, ", ");
1416 string_append (decl
, "]");
1420 /* Extract the associative array value from MANGLED and append it to DECL.
1421 Return the remaining string on success or NULL on failure. */
1423 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1425 unsigned long elements
;
1427 mangled
= dlang_number (mangled
, &elements
);
1428 if (mangled
== NULL
)
1431 string_append (decl
, "[");
1434 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1435 if (mangled
== NULL
)
1438 string_append (decl
, ":");
1439 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1440 if (mangled
== NULL
)
1444 string_append (decl
, ", ");
1447 string_append (decl
, "]");
1451 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1452 Return the remaining string on success or NULL on failure. */
1454 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1458 mangled
= dlang_number (mangled
, &args
);
1459 if (mangled
== NULL
)
1463 string_append (decl
, name
);
1465 string_append (decl
, "(");
1468 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1469 if (mangled
== NULL
)
1473 string_append (decl
, ", ");
1476 string_append (decl
, ")");
1480 /* Extract the value from MANGLED and append it to DECL.
1481 Return the remaining string on success or NULL on failure. */
1483 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1485 if (mangled
== NULL
|| *mangled
== '\0')
1493 string_append (decl
, "null");
1496 /* Integral values. */
1499 string_append (decl
, "-");
1500 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1507 /* There really should always be an `i' before encoded numbers, but there
1508 wasn't in early versions of D2, so this case range must remain for
1509 backwards compatibility. */
1510 case '0': case '1': case '2': case '3': case '4':
1511 case '5': case '6': case '7': case '8': case '9':
1512 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1518 mangled
= dlang_parse_real (decl
, mangled
);
1521 /* Complex value. */
1524 mangled
= dlang_parse_real (decl
, mangled
);
1525 string_append (decl
, "+");
1526 if (mangled
== NULL
|| *mangled
!= 'c')
1529 mangled
= dlang_parse_real (decl
, mangled
);
1530 string_append (decl
, "i");
1533 /* String values. */
1534 case 'a': /* UTF8 */
1535 case 'w': /* UTF16 */
1536 case 'd': /* UTF32 */
1537 mangled
= dlang_parse_string (decl
, mangled
);
1544 mangled
= dlang_parse_assocarray (decl
, mangled
);
1546 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1549 /* Struct values. */
1552 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1562 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1563 Returns the remaining signature on success or NULL on failure. */
1565 dlang_parse_mangle (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1567 /* A D mangled symbol is comprised of both scope and type information.
1570 _D QualifiedName Type
1573 The caller should have guaranteed that the start pointer is at the
1575 Note that type is never a function type, but only the return type of
1576 a function or the type of a variable.
1580 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 1);
1582 if (mangled
!= NULL
)
1584 /* Artificial symbols end with 'Z' and have no type. */
1585 if (*mangled
== 'Z')
1589 /* Discard the declaration or return type. */
1592 string_init (&type
);
1593 mangled
= dlang_type (&type
, mangled
, info
);
1594 string_delete (&type
);
1601 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1602 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1603 Returns the remaining signature on success or NULL on failure. */
1605 dlang_parse_qualified (string
*decl
, const char *mangled
,
1606 struct dlang_info
*info
, int suffix_modifiers
)
1608 /* Qualified names are identifiers separated by their encoded length.
1609 Nested functions also encode their argument types without specifying
1614 SymbolFunctionName QualifiedName
1619 SymbolName TypeFunctionNoReturn
1620 SymbolName M TypeFunctionNoReturn
1621 SymbolName M TypeModifiers TypeFunctionNoReturn
1623 The start pointer should be at the above location.
1629 string_append (decl
, ".");
1631 /* Skip over anonymous symbols. */
1632 while (*mangled
== '0')
1635 mangled
= dlang_identifier (decl
, mangled
, info
);
1637 /* Consume the encoded arguments. However if this is not followed by the
1638 next encoded length or mangle type, then this is not a continuation of
1639 a qualified name, in which case we backtrack and return the current
1640 unconsumed position of the mangled decl. */
1641 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1644 const char *start
= mangled
;
1645 int saved
= string_length (decl
);
1647 /* Save the type modifiers for appending at the end if needed. */
1648 string_init (&mods
);
1650 /* Skip over 'this' parameter and type modifiers. */
1651 if (*mangled
== 'M')
1654 mangled
= dlang_type_modifiers (&mods
, mangled
);
1655 string_setlength (decl
, saved
);
1658 mangled
= dlang_function_type_noreturn (decl
, NULL
, NULL
,
1660 if (suffix_modifiers
)
1661 string_appendn (decl
, mods
.b
, string_length (&mods
));
1663 if (mangled
== NULL
|| *mangled
== '\0')
1665 /* Did not match the rule we were looking for. */
1667 string_setlength (decl
, saved
);
1670 string_delete (&mods
);
1673 while (mangled
&& dlang_symbol_name_p (mangled
, info
));
1678 /* Demangle the tuple from MANGLED and append it to DECL.
1679 Return the remaining string on success or NULL on failure. */
1681 dlang_parse_tuple (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1683 unsigned long elements
;
1685 mangled
= dlang_number (mangled
, &elements
);
1686 if (mangled
== NULL
)
1689 string_append (decl
, "Tuple!(");
1693 mangled
= dlang_type (decl
, mangled
, info
);
1694 if (mangled
== NULL
)
1698 string_append (decl
, ", ");
1701 string_append (decl
, ")");
1705 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1706 Return the remaining string on success or NULL on failure. */
1708 dlang_template_symbol_param (string
*decl
, const char *mangled
,
1709 struct dlang_info
*info
)
1711 if (strncmp (mangled
, "_D", 2) == 0
1712 && dlang_symbol_name_p (mangled
+ 2, info
))
1713 return dlang_parse_mangle (decl
, mangled
, info
);
1715 if (*mangled
== 'Q')
1716 return dlang_parse_qualified (decl
, mangled
, info
, 0);
1719 const char *endptr
= dlang_number (mangled
, &len
);
1721 if (endptr
== NULL
|| len
== 0)
1724 /* In template parameter symbols generated by the frontend up to 2.076,
1725 the symbol length is encoded and the first character of the mangled
1726 name can be a digit. This causes ambiguity issues because the digits
1727 of the two numbers are adjacent. */
1730 int saved
= string_length (decl
);
1732 /* Work backwards until a match is found. */
1733 for (pend
= endptr
; endptr
!= NULL
; pend
--)
1737 /* Reached the beginning of the pointer to the name length,
1738 try parsing the entire symbol. */
1746 /* Check whether template parameter is a function with a valid
1747 return type or an untyped identifier. */
1748 if (dlang_symbol_name_p (mangled
, info
))
1749 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 0);
1750 else if (strncmp (mangled
, "_D", 2) == 0
1751 && dlang_symbol_name_p (mangled
+ 2, info
))
1752 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1754 /* Check for name length mismatch. */
1755 if (mangled
&& (endptr
== NULL
|| (mangled
- pend
) == psize
))
1759 string_setlength (decl
, saved
);
1762 /* No match on any combinations. */
1766 /* Demangle the argument list from MANGLED and append it to DECL.
1767 Return the remaining string on success or NULL on failure. */
1769 dlang_template_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1773 while (mangled
&& *mangled
!= '\0')
1777 case 'Z': /* End of parameter list. */
1783 string_append (decl
, ", ");
1785 /* Skip over specialised template prefix. */
1786 if (*mangled
== 'H')
1791 case 'S': /* Symbol parameter. */
1793 mangled
= dlang_template_symbol_param (decl
, mangled
, info
);
1795 case 'T': /* Type parameter. */
1797 mangled
= dlang_type (decl
, mangled
, info
);
1799 case 'V': /* Value parameter. */
1804 /* Peek at the type. */
1810 /* Value type is a back reference, peek at the real type. */
1811 const char *backref
;
1812 if (dlang_backref (mangled
, &backref
, info
) == NULL
)
1818 /* In the few instances where the type is actually desired in
1819 the output, it should precede the value from dlang_value. */
1820 string_init (&name
);
1821 mangled
= dlang_type (&name
, mangled
, info
);
1822 string_need (&name
, 1);
1825 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1826 string_delete (&name
);
1829 case 'X': /* Externally mangled parameter. */
1835 endptr
= dlang_number (mangled
, &len
);
1836 if (endptr
== NULL
|| strlen (endptr
) < len
)
1839 string_appendn (decl
, endptr
, len
);
1840 mangled
= endptr
+ len
;
1851 /* Extract and demangle the template symbol in MANGLED, expected to
1852 be made up of LEN characters (-1 if unknown), and append it to DECL.
1853 Returns the remaining signature on success or NULL on failure. */
1855 dlang_parse_template (string
*decl
, const char *mangled
,
1856 struct dlang_info
*info
, unsigned long len
)
1858 const char *start
= mangled
;
1861 /* Template instance names have the types and values of its parameters
1864 TemplateInstanceName:
1865 Number __T LName TemplateArgs Z
1866 Number __U LName TemplateArgs Z
1868 The start pointer should be at the above location, and LEN should be
1869 the value of the decoded number.
1872 /* Template symbol. */
1873 if (!dlang_symbol_name_p (mangled
+ 3, info
) || mangled
[3] == '0')
1878 /* Template identifier. */
1879 mangled
= dlang_identifier (decl
, mangled
, info
);
1881 /* Template arguments. */
1882 string_init (&args
);
1883 mangled
= dlang_template_args (&args
, mangled
, info
);
1885 string_append (decl
, "!(");
1886 string_appendn (decl
, args
.b
, string_length (&args
));
1887 string_append (decl
, ")");
1889 string_delete (&args
);
1891 /* Check for template name length mismatch. */
1892 if (len
!= TEMPLATE_LENGTH_UNKNOWN
1894 && (unsigned long) (mangled
- start
) != len
)
1900 /* Initialize the information structure we use to pass around information. */
1902 dlang_demangle_init_info (const char *mangled
, int last_backref
,
1903 struct dlang_info
*info
)
1906 info
->last_backref
= last_backref
;
1909 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1910 signature on success or NULL on failure. */
1913 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1916 char *demangled
= NULL
;
1918 if (mangled
== NULL
|| *mangled
== '\0')
1921 if (strncmp (mangled
, "_D", 2) != 0)
1924 string_init (&decl
);
1926 if (strcmp (mangled
, "_Dmain") == 0)
1928 string_append (&decl
, "D main");
1932 struct dlang_info info
;
1934 dlang_demangle_init_info (mangled
, strlen (mangled
), &info
);
1935 mangled
= dlang_parse_mangle (&decl
, mangled
, &info
);
1937 /* Check that the entire symbol was successfully demangled. */
1938 if (mangled
== NULL
|| *mangled
!= '\0')
1939 string_delete (&decl
);
1942 if (string_length (&decl
) > 0)
1944 string_need (&decl
, 1);