1 /* Demangler for the D programming language
2 Copyright (C) 2014-2024 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. */
38 #include "safe-ctype.h"
40 #include <sys/types.h>
49 #include "libiberty.h"
52 #define ULONG_MAX (~0UL)
55 #define UINT_MAX (~0U)
58 /* A mini string-handling package */
60 typedef struct string
/* Beware: these aren't required to be */
61 { /* '\0' terminated. */
62 char *b
; /* pointer to start of string */
63 char *p
; /* pointer after last character */
64 char *e
; /* pointer after end of allocated space */
68 string_need (string
*s
, size_t n
)
78 s
->p
= s
->b
= XNEWVEC (char, n
);
81 else if ((size_t) (s
->e
- s
->p
) < n
)
86 s
->b
= XRESIZEVEC (char, s
->b
, n
);
93 string_delete (string
*s
)
98 s
->b
= s
->e
= s
->p
= NULL
;
103 string_init (string
*s
)
105 s
->b
= s
->p
= s
->e
= NULL
;
109 string_length (string
*s
)
119 string_setlength (string
*s
, int n
)
121 if (n
- string_length (s
) < 0)
128 string_append (string
*p
, const char *s
)
130 size_t n
= strlen (s
);
137 string_appendn (string
*p
, const char *s
, size_t n
)
148 string_prependn (string
*p
, const char *s
, size_t n
)
155 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
165 string_prepend (string
*p
, const char *s
)
167 if (s
!= NULL
&& *s
!= '\0')
169 string_prependn (p
, s
, strlen (s
));
173 /* Demangle information structure we pass around. */
176 /* The string we are demangling. */
178 /* The index of the last back reference. */
182 /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
183 #define TEMPLATE_LENGTH_UNKNOWN (-1UL)
185 /* Prototypes for forward referenced functions */
186 static const char *dlang_function_type (string
*, const char *,
187 struct dlang_info
*);
189 static const char *dlang_function_args (string
*, const char *,
190 struct dlang_info
*);
192 static const char *dlang_type (string
*, const char *, struct dlang_info
*);
194 static const char *dlang_value (string
*, const char *, const char *, char,
195 struct dlang_info
*);
197 static const char *dlang_parse_qualified (string
*, const char *,
198 struct dlang_info
*, int);
200 static const char *dlang_parse_mangle (string
*, const char *,
201 struct dlang_info
*);
203 static const char *dlang_parse_tuple (string
*, const char *,
204 struct dlang_info
*);
206 static const char *dlang_parse_template (string
*, const char *,
207 struct dlang_info
*, unsigned long);
209 static const char *dlang_lname (string
*, const char *, unsigned long);
212 /* Extract the number from MANGLED, and assign the result to RET.
213 Return the remaining string on success or NULL on failure.
214 A result larger than UINT_MAX is considered a failure. */
216 dlang_number (const char *mangled
, unsigned long *ret
)
218 /* Return NULL if trying to extract something that isn't a digit. */
219 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
222 unsigned long val
= 0;
224 while (ISDIGIT (*mangled
))
226 unsigned long digit
= mangled
[0] - '0';
228 /* Check for overflow. */
229 if (val
> (UINT_MAX
- digit
) / 10)
232 val
= val
* 10 + digit
;
236 if (*mangled
== '\0')
243 /* Extract the hex-digit from MANGLED, and assign the result to RET.
244 Return the remaining string on success or NULL on failure. */
246 dlang_hexdigit (const char *mangled
, char *ret
)
250 /* Return NULL if trying to extract something that isn't a hexdigit. */
251 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
256 *ret
= c
- (ISUPPER (c
) ? 'A' : 'a') + 10;
262 *ret
= (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
264 *ret
= (*ret
<< 4) | (c
- '0');
271 /* Extract the function calling convention from MANGLED and
272 return 1 on success or 0 on failure. */
274 dlang_call_convention_p (const char *mangled
)
278 case 'F': case 'U': case 'V':
279 case 'W': case 'R': case 'Y':
287 /* Extract the back reference position from MANGLED, and assign the result
288 to RET. Return the remaining string on success or NULL on failure.
289 A result <= 0 is a failure. */
291 dlang_decode_backref (const char *mangled
, long *ret
)
293 /* Return NULL if trying to extract something that isn't a digit. */
294 if (mangled
== NULL
|| !ISALPHA (*mangled
))
297 /* Any identifier or non-basic type that has been emitted to the mangled
298 symbol before will not be emitted again, but is referenced by a special
299 sequence encoding the relative position of the original occurrence in the
302 Numbers in back references are encoded with base 26 by upper case letters
303 A-Z for higher digits but lower case letters a-z for the last digit.
310 unsigned long val
= 0;
312 while (ISALPHA (*mangled
))
314 /* Check for overflow. */
315 if (val
> (ULONG_MAX
- 25) / 26)
320 if (mangled
[0] >= 'a' && mangled
[0] <= 'z')
322 val
+= mangled
[0] - 'a';
329 val
+= mangled
[0] - 'A';
336 /* Extract the symbol pointed at by the back reference and assign the result
337 to RET. Return the remaining string on success or NULL on failure. */
339 dlang_backref (const char *mangled
, const char **ret
, struct dlang_info
*info
)
343 if (mangled
== NULL
|| *mangled
!= 'Q')
346 /* Position of 'Q'. */
347 const char *qpos
= mangled
;
351 mangled
= dlang_decode_backref (mangled
, &refpos
);
355 if (refpos
> qpos
- info
->s
)
358 /* Set the position of the back reference. */
359 *ret
= qpos
- refpos
;
364 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
365 Return the remaining string on success or NULL on failure. */
367 dlang_symbol_backref (string
*decl
, const char *mangled
,
368 struct dlang_info
*info
)
370 /* An identifier back reference always points to a digit 0 to 9.
379 /* Get position of the back reference. */
380 mangled
= dlang_backref (mangled
, &backref
, info
);
382 /* Must point to a simple identifier. */
383 backref
= dlang_number (backref
, &len
);
384 if (backref
== NULL
|| strlen(backref
) < len
)
387 backref
= dlang_lname (decl
, backref
, len
);
394 /* Demangle a back referenced type from MANGLED and append it to DECL.
395 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
396 Return the remaining string on success or NULL on failure. */
398 dlang_type_backref (string
*decl
, const char *mangled
, struct dlang_info
*info
,
401 /* A type back reference always points to a letter.
409 /* If we appear to be moving backwards through the mangle string, then
410 bail as this may be a recursive back reference. */
411 if (mangled
- info
->s
>= info
->last_backref
)
414 int save_refpos
= info
->last_backref
;
415 info
->last_backref
= mangled
- info
->s
;
417 /* Get position of the back reference. */
418 mangled
= dlang_backref (mangled
, &backref
, info
);
420 /* Must point to a type. */
422 backref
= dlang_function_type (decl
, backref
, info
);
424 backref
= dlang_type (decl
, backref
, info
);
426 info
->last_backref
= save_refpos
;
434 /* Extract the beginning of a symbol name from MANGLED and
435 return 1 on success or 0 on failure. */
437 dlang_symbol_name_p (const char *mangled
, struct dlang_info
*info
)
440 const char *qref
= mangled
;
442 if (ISDIGIT (*mangled
))
445 if (mangled
[0] == '_' && mangled
[1] == '_'
446 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
452 mangled
= dlang_decode_backref (mangled
+ 1, &ret
);
453 if (mangled
== NULL
|| ret
> qref
- info
->s
)
456 return ISDIGIT (qref
[-ret
]);
459 /* Demangle the calling convention from MANGLED and append it to DECL.
460 Return the remaining string on success or NULL on failure. */
462 dlang_call_convention (string
*decl
, const char *mangled
)
464 if (mangled
== NULL
|| *mangled
== '\0')
474 string_append (decl
, "extern(C) ");
476 case 'W': /* (Windows) */
478 string_append (decl
, "extern(Windows) ");
480 case 'V': /* (Pascal) */
482 string_append (decl
, "extern(Pascal) ");
484 case 'R': /* (C++) */
486 string_append (decl
, "extern(C++) ");
488 case 'Y': /* (Objective-C) */
490 string_append (decl
, "extern(Objective-C) ");
499 /* Extract the type modifiers from MANGLED and append them to DECL.
500 Returns the remaining signature on success or NULL on failure. */
502 dlang_type_modifiers (string
*decl
, const char *mangled
)
504 if (mangled
== NULL
|| *mangled
== '\0')
509 case 'x': /* const */
511 string_append (decl
, " const");
513 case 'y': /* immutable */
515 string_append (decl
, " immutable");
517 case 'O': /* shared */
519 string_append (decl
, " shared");
520 return dlang_type_modifiers (decl
, mangled
);
523 if (*mangled
== 'g') /* wild */
526 string_append (decl
, " inout");
527 return dlang_type_modifiers (decl
, mangled
);
537 /* Demangle the D function attributes from MANGLED and append it to DECL.
538 Return the remaining string on success or NULL on failure. */
540 dlang_attributes (string
*decl
, const char *mangled
)
542 if (mangled
== NULL
|| *mangled
== '\0')
545 while (*mangled
== 'N')
552 string_append (decl
, "pure ");
554 case 'b': /* nothrow */
556 string_append (decl
, "nothrow ");
560 string_append (decl
, "ref ");
562 case 'd': /* @property */
564 string_append (decl
, "@property ");
566 case 'e': /* @trusted */
568 string_append (decl
, "@trusted ");
570 case 'f': /* @safe */
572 string_append (decl
, "@safe ");
578 /* inout parameter is represented as 'Ng'.
579 vector parameter is represented as 'Nh'.
580 return parameter is represented as 'Nk'.
581 typeof(*null) parameter is represented as 'Nn'.
582 If we see this, then we know we're really in the
583 parameter list. Rewind and break. */
586 case 'i': /* @nogc */
588 string_append (decl
, "@nogc ");
590 case 'j': /* return */
592 string_append (decl
, "return ");
594 case 'l': /* scope */
596 string_append (decl
, "scope ");
598 case 'm': /* @live */
600 string_append (decl
, "@live ");
603 default: /* unknown attribute */
612 /* Demangle the function type from MANGLED without the return type.
613 The arguments are appended to ARGS, the calling convention is appended
614 to CALL and attributes are appended to ATTR. Any of these can be NULL
615 to throw the information away. Return the remaining string on success
616 or NULL on failure. */
618 dlang_function_type_noreturn (string
*args
, string
*call
, string
*attr
,
619 const char *mangled
, struct dlang_info
*info
)
624 /* Skip over calling convention and attributes. */
625 mangled
= dlang_call_convention (call
? call
: &dump
, mangled
);
626 mangled
= dlang_attributes (attr
? attr
: &dump
, mangled
);
629 string_append (args
, "(");
631 mangled
= dlang_function_args (args
? args
: &dump
, mangled
, info
);
633 string_append (args
, ")");
635 string_delete (&dump
);
639 /* Demangle the function type from MANGLED and append it to DECL.
640 Return the remaining string on success or NULL on failure. */
642 dlang_function_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
644 string attr
, args
, type
;
646 if (mangled
== NULL
|| *mangled
== '\0')
649 /* The order of the mangled string is:
650 CallConvention FuncAttrs Arguments ArgClose Type
652 The demangled string is re-ordered as:
653 CallConvention Type Arguments FuncAttrs
659 mangled
= dlang_function_type_noreturn (&args
, decl
, &attr
, mangled
, info
);
661 /* Function return type. */
662 mangled
= dlang_type (&type
, mangled
, info
);
664 /* Append to decl in order. */
665 string_appendn (decl
, type
.b
, string_length (&type
));
666 string_appendn (decl
, args
.b
, string_length (&args
));
667 string_append (decl
, " ");
668 string_appendn (decl
, attr
.b
, string_length (&attr
));
670 string_delete (&attr
);
671 string_delete (&args
);
672 string_delete (&type
);
676 /* Demangle the argument list from MANGLED and append it to DECL.
677 Return the remaining string on success or NULL on failure. */
679 dlang_function_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
683 while (mangled
&& *mangled
!= '\0')
687 case 'X': /* (variadic T t...) style. */
689 string_append (decl
, "...");
691 case 'Y': /* (variadic T t, ...) style. */
694 string_append (decl
, ", ");
695 string_append (decl
, "...");
697 case 'Z': /* Normal function. */
703 string_append (decl
, ", ");
705 if (*mangled
== 'M') /* scope(T) */
708 string_append (decl
, "scope ");
711 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
714 string_append (decl
, "return ");
719 case 'I': /* in(T) */
721 string_append (decl
, "in ");
722 if (*mangled
== 'K') /* in ref(T) */
725 string_append (decl
, "ref ");
728 case 'J': /* out(T) */
730 string_append (decl
, "out ");
732 case 'K': /* ref(T) */
734 string_append (decl
, "ref ");
736 case 'L': /* lazy(T) */
738 string_append (decl
, "lazy ");
741 mangled
= dlang_type (decl
, mangled
, info
);
747 /* Demangle the type from MANGLED and append it to DECL.
748 Return the remaining string on success or NULL on failure. */
750 dlang_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
752 if (mangled
== NULL
|| *mangled
== '\0')
757 case 'O': /* shared(T) */
759 string_append (decl
, "shared(");
760 mangled
= dlang_type (decl
, mangled
, info
);
761 string_append (decl
, ")");
763 case 'x': /* const(T) */
765 string_append (decl
, "const(");
766 mangled
= dlang_type (decl
, mangled
, info
);
767 string_append (decl
, ")");
769 case 'y': /* immutable(T) */
771 string_append (decl
, "immutable(");
772 mangled
= dlang_type (decl
, mangled
, info
);
773 string_append (decl
, ")");
777 if (*mangled
== 'g') /* wild(T) */
780 string_append (decl
, "inout(");
781 mangled
= dlang_type (decl
, mangled
, info
);
782 string_append (decl
, ")");
785 else if (*mangled
== 'h') /* vector(T) */
788 string_append (decl
, "__vector(");
789 mangled
= dlang_type (decl
, mangled
, info
);
790 string_append (decl
, ")");
793 else if (*mangled
== 'n') /* typeof(*null) */
796 string_append (decl
, "typeof(*null)");
801 case 'A': /* dynamic array (T[]) */
803 mangled
= dlang_type (decl
, mangled
, info
);
804 string_append (decl
, "[]");
806 case 'G': /* static array (T[N]) */
813 while (ISDIGIT (*mangled
))
818 mangled
= dlang_type (decl
, mangled
, info
);
819 string_append (decl
, "[");
820 string_appendn (decl
, numptr
, num
);
821 string_append (decl
, "]");
824 case 'H': /* associative array (T[T]) */
831 mangled
= dlang_type (&type
, mangled
, info
);
832 sztype
= string_length (&type
);
834 mangled
= dlang_type (decl
, mangled
, info
);
835 string_append (decl
, "[");
836 string_appendn (decl
, type
.b
, sztype
);
837 string_append (decl
, "]");
839 string_delete (&type
);
842 case 'P': /* pointer (T*) */
844 if (!dlang_call_convention_p (mangled
))
846 mangled
= dlang_type (decl
, mangled
, info
);
847 string_append (decl
, "*");
851 case 'F': /* function T (D) */
852 case 'U': /* function T (C) */
853 case 'W': /* function T (Windows) */
854 case 'V': /* function T (Pascal) */
855 case 'R': /* function T (C++) */
856 case 'Y': /* function T (Objective-C) */
857 /* Function pointer types don't include the trailing asterisk. */
858 mangled
= dlang_function_type (decl
, mangled
, info
);
859 string_append (decl
, "function");
861 case 'C': /* class T */
862 case 'S': /* struct T */
863 case 'E': /* enum T */
864 case 'T': /* typedef T */
866 return dlang_parse_qualified (decl
, mangled
, info
, 0);
867 case 'D': /* delegate T */
874 mangled
= dlang_type_modifiers (&mods
, mangled
);
875 szmods
= string_length (&mods
);
877 /* Back referenced function type. */
878 if (mangled
&& *mangled
== 'Q')
879 mangled
= dlang_type_backref (decl
, mangled
, info
, 1);
881 mangled
= dlang_function_type (decl
, mangled
, info
);
883 string_append (decl
, "delegate");
884 string_appendn (decl
, mods
.b
, szmods
);
886 string_delete (&mods
);
889 case 'B': /* tuple T */
891 return dlang_parse_tuple (decl
, mangled
, info
);
896 string_append (decl
, "typeof(null)");
900 string_append (decl
, "void");
904 string_append (decl
, "byte");
908 string_append (decl
, "ubyte");
912 string_append (decl
, "short");
916 string_append (decl
, "ushort");
920 string_append (decl
, "int");
924 string_append (decl
, "uint");
928 string_append (decl
, "long");
932 string_append (decl
, "ulong");
936 string_append (decl
, "float");
940 string_append (decl
, "double");
944 string_append (decl
, "real");
947 /* Imaginary and Complex types */
950 string_append (decl
, "ifloat");
954 string_append (decl
, "idouble");
958 string_append (decl
, "ireal");
962 string_append (decl
, "cfloat");
966 string_append (decl
, "cdouble");
970 string_append (decl
, "creal");
976 string_append (decl
, "bool");
980 string_append (decl
, "char");
984 string_append (decl
, "wchar");
988 string_append (decl
, "dchar");
996 string_append (decl
, "cent");
1000 string_append (decl
, "ucent");
1005 /* Back referenced type. */
1007 return dlang_type_backref (decl
, mangled
, info
, 0);
1009 default: /* unhandled */
1014 /* Extract the identifier from MANGLED and append it to DECL.
1015 Return the remaining string on success or NULL on failure. */
1017 dlang_identifier (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1021 if (mangled
== NULL
|| *mangled
== '\0')
1024 if (*mangled
== 'Q')
1025 return dlang_symbol_backref (decl
, mangled
, info
);
1027 /* May be a template instance without a length prefix. */
1028 if (mangled
[0] == '_' && mangled
[1] == '_'
1029 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1030 return dlang_parse_template (decl
, mangled
, info
, TEMPLATE_LENGTH_UNKNOWN
);
1032 const char *endptr
= dlang_number (mangled
, &len
);
1034 if (endptr
== NULL
|| len
== 0)
1037 if (strlen (endptr
) < len
)
1042 /* May be a template instance with a length prefix. */
1043 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
1044 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1045 return dlang_parse_template (decl
, mangled
, info
, len
);
1047 /* There can be multiple different declarations in the same function that have
1048 the same mangled name. To make the mangled names unique, a fake parent in
1049 the form `__Sddd' is added to the symbol. */
1050 if (len
>= 4 && mangled
[0] == '_' && mangled
[1] == '_' && mangled
[2] == 'S')
1052 const char *numptr
= mangled
+ 3;
1053 while (numptr
< (mangled
+ len
) && ISDIGIT (*numptr
))
1056 if (mangled
+ len
== numptr
)
1058 /* Skip over the fake parent. */
1060 return dlang_identifier (decl
, mangled
, info
);
1063 /* else demangle it as a plain identifier. */
1066 return dlang_lname (decl
, mangled
, len
);
1069 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1070 with special treatment for some magic compiler generted symbols.
1071 Return the remaining string on success or NULL on failure. */
1073 dlang_lname (string
*decl
, const char *mangled
, unsigned long len
)
1078 if (strncmp (mangled
, "__ctor", len
) == 0)
1080 /* Constructor symbol for a class/struct. */
1081 string_append (decl
, "this");
1085 else if (strncmp (mangled
, "__dtor", len
) == 0)
1087 /* Destructor symbol for a class/struct. */
1088 string_append (decl
, "~this");
1092 else if (strncmp (mangled
, "__initZ", len
+ 1) == 0)
1094 /* The static initialiser for a given symbol. */
1095 string_prepend (decl
, "initializer for ");
1096 string_setlength (decl
, string_length (decl
) - 1);
1100 else if (strncmp (mangled
, "__vtblZ", len
+ 1) == 0)
1102 /* The vtable symbol for a given class. */
1103 string_prepend (decl
, "vtable for ");
1104 string_setlength (decl
, string_length (decl
) - 1);
1111 if (strncmp (mangled
, "__ClassZ", len
+ 1) == 0)
1113 /* The classinfo symbol for a given class. */
1114 string_prepend (decl
, "ClassInfo for ");
1115 string_setlength (decl
, string_length (decl
) - 1);
1122 if (strncmp (mangled
, "__postblitMFZ", len
+ 3) == 0)
1124 /* Postblit symbol for a struct. */
1125 string_append (decl
, "this(this)");
1132 if (strncmp (mangled
, "__InterfaceZ", len
+ 1) == 0)
1134 /* The interface symbol for a given class. */
1135 string_prepend (decl
, "Interface for ");
1136 string_setlength (decl
, string_length (decl
) - 1);
1143 if (strncmp (mangled
, "__ModuleInfoZ", len
+ 1) == 0)
1145 /* The ModuleInfo symbol for a given module. */
1146 string_prepend (decl
, "ModuleInfo for ");
1147 string_setlength (decl
, string_length (decl
) - 1);
1154 string_appendn (decl
, mangled
, len
);
1160 /* Extract the integer value from MANGLED and append it to DECL,
1161 where TYPE is the type it should be represented as.
1162 Return the remaining string on success or NULL on failure. */
1164 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
1166 if (type
== 'a' || type
== 'u' || type
== 'w')
1168 /* Parse character value. */
1170 int pos
= sizeof(value
);
1174 mangled
= dlang_number (mangled
, &val
);
1175 if (mangled
== NULL
)
1178 string_append (decl
, "'");
1180 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
1182 /* Represent as a character literal. */
1183 char c
= (char) val
;
1184 string_appendn (decl
, &c
, 1);
1188 /* Represent as a hexadecimal value. */
1191 case 'a': /* char */
1192 string_append (decl
, "\\x");
1195 case 'u': /* wchar */
1196 string_append (decl
, "\\u");
1199 case 'w': /* dchar */
1200 string_append (decl
, "\\U");
1207 int digit
= val
% 16;
1210 value
[--pos
] = (char)(digit
+ '0');
1212 value
[--pos
] = (char)((digit
- 10) + 'a');
1218 for (; width
> 0; width
--)
1221 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
1223 string_append (decl
, "'");
1225 else if (type
== 'b')
1227 /* Parse boolean value. */
1230 mangled
= dlang_number (mangled
, &val
);
1231 if (mangled
== NULL
)
1234 string_append (decl
, val
? "true" : "false");
1238 /* Parse integer value. */
1239 const char *numptr
= mangled
;
1242 if (! ISDIGIT (*mangled
))
1245 while (ISDIGIT (*mangled
))
1250 string_appendn (decl
, numptr
, num
);
1252 /* Append suffix. */
1255 case 'h': /* ubyte */
1256 case 't': /* ushort */
1257 case 'k': /* uint */
1258 string_append (decl
, "u");
1260 case 'l': /* long */
1261 string_append (decl
, "L");
1263 case 'm': /* ulong */
1264 string_append (decl
, "uL");
1272 /* Extract the floating-point value from MANGLED and append it to DECL.
1273 Return the remaining string on success or NULL on failure. */
1275 dlang_parse_real (string
*decl
, const char *mangled
)
1277 /* Handle NAN and +-INF. */
1278 if (strncmp (mangled
, "NAN", 3) == 0)
1280 string_append (decl
, "NaN");
1284 else if (strncmp (mangled
, "INF", 3) == 0)
1286 string_append (decl
, "Inf");
1290 else if (strncmp (mangled
, "NINF", 4) == 0)
1292 string_append (decl
, "-Inf");
1297 /* Hexadecimal prefix and leading bit. */
1298 if (*mangled
== 'N')
1300 string_append (decl
, "-");
1304 if (!ISXDIGIT (*mangled
))
1307 string_append (decl
, "0x");
1308 string_appendn (decl
, mangled
, 1);
1309 string_append (decl
, ".");
1313 while (ISXDIGIT (*mangled
))
1315 string_appendn (decl
, mangled
, 1);
1320 if (*mangled
!= 'P')
1323 string_append (decl
, "p");
1326 if (*mangled
== 'N')
1328 string_append (decl
, "-");
1332 while (ISDIGIT (*mangled
))
1334 string_appendn (decl
, mangled
, 1);
1341 /* Extract the string value from MANGLED and append it to DECL.
1342 Return the remaining string on success or NULL on failure. */
1344 dlang_parse_string (string
*decl
, const char *mangled
)
1346 char type
= *mangled
;
1350 mangled
= dlang_number (mangled
, &len
);
1351 if (mangled
== NULL
|| *mangled
!= '_')
1355 string_append (decl
, "\"");
1359 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1364 /* Sanitize white and non-printable characters. */
1368 string_append (decl
, " ");
1371 string_append (decl
, "\\t");
1374 string_append (decl
, "\\n");
1377 string_append (decl
, "\\r");
1380 string_append (decl
, "\\f");
1383 string_append (decl
, "\\v");
1388 string_appendn (decl
, &val
, 1);
1391 string_append (decl
, "\\x");
1392 string_appendn (decl
, mangled
, 2);
1398 string_append (decl
, "\"");
1401 string_appendn (decl
, &type
, 1);
1406 /* Extract the static array value from MANGLED and append it to DECL.
1407 Return the remaining string on success or NULL on failure. */
1409 dlang_parse_arrayliteral (string
*decl
, const char *mangled
,
1410 struct dlang_info
*info
)
1412 unsigned long elements
;
1414 mangled
= dlang_number (mangled
, &elements
);
1415 if (mangled
== NULL
)
1418 string_append (decl
, "[");
1421 mangled
= dlang_value (decl
, mangled
, NULL
, '\0', info
);
1422 if (mangled
== NULL
)
1426 string_append (decl
, ", ");
1429 string_append (decl
, "]");
1433 /* Extract the associative array value from MANGLED and append it to DECL.
1434 Return the remaining string on success or NULL on failure. */
1436 dlang_parse_assocarray (string
*decl
, const char *mangled
,
1437 struct dlang_info
*info
)
1439 unsigned long elements
;
1441 mangled
= dlang_number (mangled
, &elements
);
1442 if (mangled
== NULL
)
1445 string_append (decl
, "[");
1448 mangled
= dlang_value (decl
, mangled
, NULL
, '\0', info
);
1449 if (mangled
== NULL
)
1452 string_append (decl
, ":");
1453 mangled
= dlang_value (decl
, mangled
, NULL
, '\0', info
);
1454 if (mangled
== NULL
)
1458 string_append (decl
, ", ");
1461 string_append (decl
, "]");
1465 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1466 Return the remaining string on success or NULL on failure. */
1468 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
,
1469 struct dlang_info
*info
)
1473 mangled
= dlang_number (mangled
, &args
);
1474 if (mangled
== NULL
)
1478 string_append (decl
, name
);
1480 string_append (decl
, "(");
1483 mangled
= dlang_value (decl
, mangled
, NULL
, '\0', info
);
1484 if (mangled
== NULL
)
1488 string_append (decl
, ", ");
1491 string_append (decl
, ")");
1495 /* Extract the value from MANGLED and append it to DECL.
1496 Return the remaining string on success or NULL on failure. */
1498 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
,
1499 struct dlang_info
*info
)
1501 if (mangled
== NULL
|| *mangled
== '\0')
1509 string_append (decl
, "null");
1512 /* Integral values. */
1515 string_append (decl
, "-");
1516 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1523 /* There really should always be an `i' before encoded numbers, but there
1524 wasn't in early versions of D2, so this case range must remain for
1525 backwards compatibility. */
1526 case '0': case '1': case '2': case '3': case '4':
1527 case '5': case '6': case '7': case '8': case '9':
1528 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1534 mangled
= dlang_parse_real (decl
, mangled
);
1537 /* Complex value. */
1540 mangled
= dlang_parse_real (decl
, mangled
);
1541 string_append (decl
, "+");
1542 if (mangled
== NULL
|| *mangled
!= 'c')
1545 mangled
= dlang_parse_real (decl
, mangled
);
1546 string_append (decl
, "i");
1549 /* String values. */
1550 case 'a': /* UTF8 */
1551 case 'w': /* UTF16 */
1552 case 'd': /* UTF32 */
1553 mangled
= dlang_parse_string (decl
, mangled
);
1560 mangled
= dlang_parse_assocarray (decl
, mangled
, info
);
1562 mangled
= dlang_parse_arrayliteral (decl
, mangled
, info
);
1565 /* Struct values. */
1568 mangled
= dlang_parse_structlit (decl
, mangled
, name
, info
);
1571 /* Function literal symbol. */
1574 if (strncmp (mangled
, "_D", 2) != 0
1575 || !dlang_symbol_name_p (mangled
+ 2, info
))
1577 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1587 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1588 Returns the remaining signature on success or NULL on failure. */
1590 dlang_parse_mangle (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1592 /* A D mangled symbol is comprised of both scope and type information.
1595 _D QualifiedName Type
1598 The caller should have guaranteed that the start pointer is at the
1600 Note that type is never a function type, but only the return type of
1601 a function or the type of a variable.
1605 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 1);
1607 if (mangled
!= NULL
)
1609 /* Artificial symbols end with 'Z' and have no type. */
1610 if (*mangled
== 'Z')
1614 /* Discard the declaration or return type. */
1617 string_init (&type
);
1618 mangled
= dlang_type (&type
, mangled
, info
);
1619 string_delete (&type
);
1626 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1627 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1628 Returns the remaining signature on success or NULL on failure. */
1630 dlang_parse_qualified (string
*decl
, const char *mangled
,
1631 struct dlang_info
*info
, int suffix_modifiers
)
1633 /* Qualified names are identifiers separated by their encoded length.
1634 Nested functions also encode their argument types without specifying
1639 SymbolFunctionName QualifiedName
1644 SymbolName TypeFunctionNoReturn
1645 SymbolName M TypeFunctionNoReturn
1646 SymbolName M TypeModifiers TypeFunctionNoReturn
1648 The start pointer should be at the above location.
1653 /* Skip over anonymous symbols. */
1654 if (*mangled
== '0')
1658 while (*mangled
== '0');
1664 string_append (decl
, ".");
1666 mangled
= dlang_identifier (decl
, mangled
, info
);
1668 /* Consume the encoded arguments. However if this is not followed by the
1669 next encoded length or mangle type, then this is not a continuation of
1670 a qualified name, in which case we backtrack and return the current
1671 unconsumed position of the mangled decl. */
1672 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1675 const char *start
= mangled
;
1676 int saved
= string_length (decl
);
1678 /* Save the type modifiers for appending at the end if needed. */
1679 string_init (&mods
);
1681 /* Skip over 'this' parameter and type modifiers. */
1682 if (*mangled
== 'M')
1685 mangled
= dlang_type_modifiers (&mods
, mangled
);
1686 string_setlength (decl
, saved
);
1689 mangled
= dlang_function_type_noreturn (decl
, NULL
, NULL
,
1691 if (suffix_modifiers
)
1692 string_appendn (decl
, mods
.b
, string_length (&mods
));
1694 if (mangled
== NULL
|| *mangled
== '\0')
1696 /* Did not match the rule we were looking for. */
1698 string_setlength (decl
, saved
);
1701 string_delete (&mods
);
1704 while (mangled
&& dlang_symbol_name_p (mangled
, info
));
1709 /* Demangle the tuple from MANGLED and append it to DECL.
1710 Return the remaining string on success or NULL on failure. */
1712 dlang_parse_tuple (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1714 unsigned long elements
;
1716 mangled
= dlang_number (mangled
, &elements
);
1717 if (mangled
== NULL
)
1720 string_append (decl
, "Tuple!(");
1724 mangled
= dlang_type (decl
, mangled
, info
);
1725 if (mangled
== NULL
)
1729 string_append (decl
, ", ");
1732 string_append (decl
, ")");
1736 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1737 Return the remaining string on success or NULL on failure. */
1739 dlang_template_symbol_param (string
*decl
, const char *mangled
,
1740 struct dlang_info
*info
)
1742 if (strncmp (mangled
, "_D", 2) == 0
1743 && dlang_symbol_name_p (mangled
+ 2, info
))
1744 return dlang_parse_mangle (decl
, mangled
, info
);
1746 if (*mangled
== 'Q')
1747 return dlang_parse_qualified (decl
, mangled
, info
, 0);
1750 const char *endptr
= dlang_number (mangled
, &len
);
1752 if (endptr
== NULL
|| len
== 0)
1755 /* In template parameter symbols generated by the frontend up to 2.076,
1756 the symbol length is encoded and the first character of the mangled
1757 name can be a digit. This causes ambiguity issues because the digits
1758 of the two numbers are adjacent. */
1761 int saved
= string_length (decl
);
1763 /* Work backwards until a match is found. */
1764 for (pend
= endptr
; endptr
!= NULL
; pend
--)
1768 /* Reached the beginning of the pointer to the name length,
1769 try parsing the entire symbol. */
1777 /* Check whether template parameter is a function with a valid
1778 return type or an untyped identifier. */
1779 if (dlang_symbol_name_p (mangled
, info
))
1780 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 0);
1781 else if (strncmp (mangled
, "_D", 2) == 0
1782 && dlang_symbol_name_p (mangled
+ 2, info
))
1783 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1785 /* Check for name length mismatch. */
1786 if (mangled
&& (endptr
== NULL
|| (mangled
- pend
) == psize
))
1790 string_setlength (decl
, saved
);
1793 /* No match on any combinations. */
1797 /* Demangle the argument list from MANGLED and append it to DECL.
1798 Return the remaining string on success or NULL on failure. */
1800 dlang_template_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1804 while (mangled
&& *mangled
!= '\0')
1808 case 'Z': /* End of parameter list. */
1814 string_append (decl
, ", ");
1816 /* Skip over specialised template prefix. */
1817 if (*mangled
== 'H')
1822 case 'S': /* Symbol parameter. */
1824 mangled
= dlang_template_symbol_param (decl
, mangled
, info
);
1826 case 'T': /* Type parameter. */
1828 mangled
= dlang_type (decl
, mangled
, info
);
1830 case 'V': /* Value parameter. */
1835 /* Peek at the type. */
1841 /* Value type is a back reference, peek at the real type. */
1842 const char *backref
;
1843 if (dlang_backref (mangled
, &backref
, info
) == NULL
)
1849 /* In the few instances where the type is actually desired in
1850 the output, it should precede the value from dlang_value. */
1851 string_init (&name
);
1852 mangled
= dlang_type (&name
, mangled
, info
);
1853 string_need (&name
, 1);
1856 mangled
= dlang_value (decl
, mangled
, name
.b
, type
, info
);
1857 string_delete (&name
);
1860 case 'X': /* Externally mangled parameter. */
1866 endptr
= dlang_number (mangled
, &len
);
1867 if (endptr
== NULL
|| strlen (endptr
) < len
)
1870 string_appendn (decl
, endptr
, len
);
1871 mangled
= endptr
+ len
;
1882 /* Extract and demangle the template symbol in MANGLED, expected to
1883 be made up of LEN characters (-1 if unknown), and append it to DECL.
1884 Returns the remaining signature on success or NULL on failure. */
1886 dlang_parse_template (string
*decl
, const char *mangled
,
1887 struct dlang_info
*info
, unsigned long len
)
1889 const char *start
= mangled
;
1892 /* Template instance names have the types and values of its parameters
1895 TemplateInstanceName:
1896 Number __T LName TemplateArgs Z
1897 Number __U LName TemplateArgs Z
1899 The start pointer should be at the above location, and LEN should be
1900 the value of the decoded number.
1903 /* Template symbol. */
1904 if (!dlang_symbol_name_p (mangled
+ 3, info
) || mangled
[3] == '0')
1909 /* Template identifier. */
1910 mangled
= dlang_identifier (decl
, mangled
, info
);
1912 /* Template arguments. */
1913 string_init (&args
);
1914 mangled
= dlang_template_args (&args
, mangled
, info
);
1916 string_append (decl
, "!(");
1917 string_appendn (decl
, args
.b
, string_length (&args
));
1918 string_append (decl
, ")");
1920 string_delete (&args
);
1922 /* Check for template name length mismatch. */
1923 if (len
!= TEMPLATE_LENGTH_UNKNOWN
1925 && (unsigned long) (mangled
- start
) != len
)
1931 /* Initialize the information structure we use to pass around information. */
1933 dlang_demangle_init_info (const char *mangled
, int last_backref
,
1934 struct dlang_info
*info
)
1937 info
->last_backref
= last_backref
;
1940 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1941 signature on success or NULL on failure. */
1944 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1947 char *demangled
= NULL
;
1949 if (mangled
== NULL
|| *mangled
== '\0')
1952 if (strncmp (mangled
, "_D", 2) != 0)
1955 string_init (&decl
);
1957 if (strcmp (mangled
, "_Dmain") == 0)
1959 string_append (&decl
, "D main");
1963 struct dlang_info info
;
1965 dlang_demangle_init_info (mangled
, strlen (mangled
), &info
);
1966 mangled
= dlang_parse_mangle (&decl
, mangled
, &info
);
1968 /* Check that the entire symbol was successfully demangled. */
1969 if (mangled
== NULL
|| *mangled
!= '\0')
1970 string_delete (&decl
);
1973 if (string_length (&decl
) > 0)
1975 string_need (&decl
, 1);