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. */
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);
196 static const char *dlang_parse_qualified (string
*, const char *,
197 struct dlang_info
*, int);
199 static const char *dlang_parse_mangle (string
*, const char *,
200 struct dlang_info
*);
202 static const char *dlang_parse_tuple (string
*, const char *,
203 struct dlang_info
*);
205 static const char *dlang_parse_template (string
*, const char *,
206 struct dlang_info
*, unsigned long);
208 static const char *dlang_lname (string
*, const char *, unsigned long);
211 /* Extract the number from MANGLED, and assign the result to RET.
212 Return the remaining string on success or NULL on failure.
213 A result larger than UINT_MAX is considered a failure. */
215 dlang_number (const char *mangled
, unsigned long *ret
)
217 /* Return NULL if trying to extract something that isn't a digit. */
218 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
221 unsigned long val
= 0;
223 while (ISDIGIT (*mangled
))
225 unsigned long digit
= mangled
[0] - '0';
227 /* Check for overflow. */
228 if (val
> (UINT_MAX
- digit
) / 10)
231 val
= val
* 10 + digit
;
235 if (*mangled
== '\0')
242 /* Extract the hex-digit from MANGLED, and assign the result to RET.
243 Return the remaining string on success or NULL on failure. */
245 dlang_hexdigit (const char *mangled
, char *ret
)
249 /* Return NULL if trying to extract something that isn't a hexdigit. */
250 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
255 (*ret
) = (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
261 (*ret
) = (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
263 (*ret
) = (*ret
<< 4) | (c
- '0');
270 /* Extract the function calling convention from MANGLED and
271 return 1 on success or 0 on failure. */
273 dlang_call_convention_p (const char *mangled
)
277 case 'F': case 'U': case 'V':
278 case 'W': case 'R': case 'Y':
286 /* Extract the back reference position from MANGLED, and assign the result
287 to RET. Return the remaining string on success or NULL on failure.
288 A result <= 0 is a failure. */
290 dlang_decode_backref (const char *mangled
, long *ret
)
292 /* Return NULL if trying to extract something that isn't a digit. */
293 if (mangled
== NULL
|| !ISALPHA (*mangled
))
296 /* Any identifier or non-basic type that has been emitted to the mangled
297 symbol before will not be emitted again, but is referenced by a special
298 sequence encoding the relative position of the original occurrence in the
301 Numbers in back references are encoded with base 26 by upper case letters
302 A-Z for higher digits but lower case letters a-z for the last digit.
309 unsigned long val
= 0;
311 while (ISALPHA (*mangled
))
313 /* Check for overflow. */
314 if (val
> (ULONG_MAX
- 25) / 26)
319 if (mangled
[0] >= 'a' && mangled
[0] <= 'z')
321 val
+= mangled
[0] - 'a';
328 val
+= mangled
[0] - 'A';
335 /* Extract the symbol pointed at by the back reference and assign the result
336 to RET. Return the remaining string on success or NULL on failure. */
338 dlang_backref (const char *mangled
, const char **ret
, struct dlang_info
*info
)
342 if (mangled
== NULL
|| *mangled
!= 'Q')
345 /* Position of 'Q'. */
346 const char *qpos
= mangled
;
350 mangled
= dlang_decode_backref (mangled
, &refpos
);
354 if (refpos
> qpos
- info
->s
)
357 /* Set the position of the back reference. */
358 (*ret
) = qpos
- refpos
;
363 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
364 Return the remaining string on success or NULL on failure. */
366 dlang_symbol_backref (string
*decl
, const char *mangled
,
367 struct dlang_info
*info
)
369 /* An identifier back reference always points to a digit 0 to 9.
378 /* Get position of the back reference. */
379 mangled
= dlang_backref (mangled
, &backref
, info
);
381 /* Must point to a simple identifier. */
382 backref
= dlang_number (backref
, &len
);
386 backref
= dlang_lname (decl
, backref
, len
);
393 /* Demangle a back referenced type from MANGLED and append it to DECL.
394 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
395 Return the remaining string on success or NULL on failure. */
397 dlang_type_backref (string
*decl
, const char *mangled
, struct dlang_info
*info
,
400 /* A type back reference always points to a letter.
408 /* If we appear to be moving backwards through the mangle string, then
409 bail as this may be a recursive back reference. */
410 if (mangled
- info
->s
>= info
->last_backref
)
413 int save_refpos
= info
->last_backref
;
414 info
->last_backref
= mangled
- info
->s
;
416 /* Get position of the back reference. */
417 mangled
= dlang_backref (mangled
, &backref
, info
);
419 /* Must point to a type. */
421 backref
= dlang_function_type (decl
, backref
, info
);
423 backref
= dlang_type (decl
, backref
, info
);
425 info
->last_backref
= save_refpos
;
433 /* Extract the beginning of a symbol name from MANGLED and
434 return 1 on success or 0 on failure. */
436 dlang_symbol_name_p (const char *mangled
, struct dlang_info
*info
)
439 const char *qref
= mangled
;
441 if (ISDIGIT (*mangled
))
444 if (mangled
[0] == '_' && mangled
[1] == '_'
445 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
451 mangled
= dlang_decode_backref (mangled
+ 1, &ret
);
452 if (mangled
== NULL
|| ret
> qref
- info
->s
)
455 return ISDIGIT (qref
[-ret
]);
458 /* Demangle the calling convention from MANGLED and append it to DECL.
459 Return the remaining string on success or NULL on failure. */
461 dlang_call_convention (string
*decl
, const char *mangled
)
463 if (mangled
== NULL
|| *mangled
== '\0')
473 string_append (decl
, "extern(C) ");
475 case 'W': /* (Windows) */
477 string_append (decl
, "extern(Windows) ");
479 case 'V': /* (Pascal) */
481 string_append (decl
, "extern(Pascal) ");
483 case 'R': /* (C++) */
485 string_append (decl
, "extern(C++) ");
487 case 'Y': /* (Objective-C) */
489 string_append (decl
, "extern(Objective-C) ");
498 /* Extract the type modifiers from MANGLED and append them to DECL.
499 Returns the remaining signature on success or NULL on failure. */
501 dlang_type_modifiers (string
*decl
, const char *mangled
)
503 if (mangled
== NULL
|| *mangled
== '\0')
508 case 'x': /* const */
510 string_append (decl
, " const");
512 case 'y': /* immutable */
514 string_append (decl
, " immutable");
516 case 'O': /* shared */
518 string_append (decl
, " shared");
519 return dlang_type_modifiers (decl
, mangled
);
522 if (*mangled
== 'g') /* wild */
525 string_append (decl
, " inout");
526 return dlang_type_modifiers (decl
, mangled
);
536 /* Demangle the D function attributes from MANGLED and append it to DECL.
537 Return the remaining string on success or NULL on failure. */
539 dlang_attributes (string
*decl
, const char *mangled
)
541 if (mangled
== NULL
|| *mangled
== '\0')
544 while (*mangled
== 'N')
551 string_append (decl
, "pure ");
553 case 'b': /* nothrow */
555 string_append (decl
, "nothrow ");
559 string_append (decl
, "ref ");
561 case 'd': /* @property */
563 string_append (decl
, "@property ");
565 case 'e': /* @trusted */
567 string_append (decl
, "@trusted ");
569 case 'f': /* @safe */
571 string_append (decl
, "@safe ");
576 /* inout parameter is represented as 'Ng'.
577 vector parameter is represented as 'Nh'.
578 return paramenter is represented as 'Nk'.
579 If we see this, then we know we're really in the
580 parameter list. Rewind and break. */
583 case 'i': /* @nogc */
585 string_append (decl
, "@nogc ");
587 case 'j': /* return */
589 string_append (decl
, "return ");
591 case 'l': /* scope */
593 string_append (decl
, "scope ");
595 case 'm': /* @live */
597 string_append (decl
, "@live ");
600 default: /* unknown attribute */
609 /* Demangle the function type from MANGLED without the return type.
610 The arguments are appended to ARGS, the calling convention is appended
611 to CALL and attributes are appended to ATTR. Any of these can be NULL
612 to throw the information away. Return the remaining string on success
613 or NULL on failure. */
615 dlang_function_type_noreturn (string
*args
, string
*call
, string
*attr
,
616 const char *mangled
, struct dlang_info
*info
)
621 /* Skip over calling convention and attributes. */
622 mangled
= dlang_call_convention (call
? call
: &dump
, mangled
);
623 mangled
= dlang_attributes (attr
? attr
: &dump
, mangled
);
626 string_append (args
, "(");
628 mangled
= dlang_function_args (args
? args
: &dump
, mangled
, info
);
630 string_append (args
, ")");
632 string_delete (&dump
);
636 /* Demangle the function type from MANGLED and append it to DECL.
637 Return the remaining string on success or NULL on failure. */
639 dlang_function_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
641 string attr
, args
, type
;
643 if (mangled
== NULL
|| *mangled
== '\0')
646 /* The order of the mangled string is:
647 CallConvention FuncAttrs Arguments ArgClose Type
649 The demangled string is re-ordered as:
650 CallConvention Type Arguments FuncAttrs
656 mangled
= dlang_function_type_noreturn (&args
, decl
, &attr
, mangled
, info
);
658 /* Function return type. */
659 mangled
= dlang_type (&type
, mangled
, info
);
661 /* Append to decl in order. */
662 string_appendn (decl
, type
.b
, string_length (&type
));
663 string_appendn (decl
, args
.b
, string_length (&args
));
664 string_append (decl
, " ");
665 string_appendn (decl
, attr
.b
, string_length (&attr
));
667 string_delete (&attr
);
668 string_delete (&args
);
669 string_delete (&type
);
673 /* Demangle the argument list from MANGLED and append it to DECL.
674 Return the remaining string on success or NULL on failure. */
676 dlang_function_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
680 while (mangled
&& *mangled
!= '\0')
684 case 'X': /* (variadic T t...) style. */
686 string_append (decl
, "...");
688 case 'Y': /* (variadic T t, ...) style. */
691 string_append (decl
, ", ");
692 string_append (decl
, "...");
694 case 'Z': /* Normal function. */
700 string_append (decl
, ", ");
702 if (*mangled
== 'M') /* scope(T) */
705 string_append (decl
, "scope ");
708 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
711 string_append (decl
, "return ");
716 case 'I': /* in(T) */
718 string_append (decl
, "in ");
719 if (*mangled
== 'K') /* in ref(T) */
722 string_append (decl
, "ref ");
725 case 'J': /* out(T) */
727 string_append (decl
, "out ");
729 case 'K': /* ref(T) */
731 string_append (decl
, "ref ");
733 case 'L': /* lazy(T) */
735 string_append (decl
, "lazy ");
738 mangled
= dlang_type (decl
, mangled
, info
);
744 /* Demangle the type from MANGLED and append it to DECL.
745 Return the remaining string on success or NULL on failure. */
747 dlang_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
749 if (mangled
== NULL
|| *mangled
== '\0')
754 case 'O': /* shared(T) */
756 string_append (decl
, "shared(");
757 mangled
= dlang_type (decl
, mangled
, info
);
758 string_append (decl
, ")");
760 case 'x': /* const(T) */
762 string_append (decl
, "const(");
763 mangled
= dlang_type (decl
, mangled
, info
);
764 string_append (decl
, ")");
766 case 'y': /* immutable(T) */
768 string_append (decl
, "immutable(");
769 mangled
= dlang_type (decl
, mangled
, info
);
770 string_append (decl
, ")");
774 if (*mangled
== 'g') /* wild(T) */
777 string_append (decl
, "inout(");
778 mangled
= dlang_type (decl
, mangled
, info
);
779 string_append (decl
, ")");
782 else if (*mangled
== 'h') /* vector(T) */
785 string_append (decl
, "__vector(");
786 mangled
= dlang_type (decl
, mangled
, info
);
787 string_append (decl
, ")");
792 case 'A': /* dynamic array (T[]) */
794 mangled
= dlang_type (decl
, mangled
, info
);
795 string_append (decl
, "[]");
797 case 'G': /* static array (T[N]) */
804 while (ISDIGIT (*mangled
))
809 mangled
= dlang_type (decl
, mangled
, info
);
810 string_append (decl
, "[");
811 string_appendn (decl
, numptr
, num
);
812 string_append (decl
, "]");
815 case 'H': /* associative array (T[T]) */
822 mangled
= dlang_type (&type
, mangled
, info
);
823 sztype
= string_length (&type
);
825 mangled
= dlang_type (decl
, mangled
, info
);
826 string_append (decl
, "[");
827 string_appendn (decl
, type
.b
, sztype
);
828 string_append (decl
, "]");
830 string_delete (&type
);
833 case 'P': /* pointer (T*) */
835 if (!dlang_call_convention_p (mangled
))
837 mangled
= dlang_type (decl
, mangled
, info
);
838 string_append (decl
, "*");
842 case 'F': /* function T (D) */
843 case 'U': /* function T (C) */
844 case 'W': /* function T (Windows) */
845 case 'V': /* function T (Pascal) */
846 case 'R': /* function T (C++) */
847 case 'Y': /* function T (Objective-C) */
848 /* Function pointer types don't include the trailing asterisk. */
849 mangled
= dlang_function_type (decl
, mangled
, info
);
850 string_append (decl
, "function");
852 case 'C': /* class T */
853 case 'S': /* struct T */
854 case 'E': /* enum T */
855 case 'T': /* typedef T */
857 return dlang_parse_qualified (decl
, mangled
, info
, 0);
858 case 'D': /* delegate T */
865 mangled
= dlang_type_modifiers (&mods
, mangled
);
866 szmods
= string_length (&mods
);
868 /* Back referenced function type. */
870 mangled
= dlang_type_backref (decl
, mangled
, info
, 1);
872 mangled
= dlang_function_type (decl
, mangled
, info
);
874 string_append (decl
, "delegate");
875 string_appendn (decl
, mods
.b
, szmods
);
877 string_delete (&mods
);
880 case 'B': /* tuple T */
882 return dlang_parse_tuple (decl
, mangled
, info
);
887 string_append (decl
, "none");
891 string_append (decl
, "void");
895 string_append (decl
, "byte");
899 string_append (decl
, "ubyte");
903 string_append (decl
, "short");
907 string_append (decl
, "ushort");
911 string_append (decl
, "int");
915 string_append (decl
, "uint");
919 string_append (decl
, "long");
923 string_append (decl
, "ulong");
927 string_append (decl
, "float");
931 string_append (decl
, "double");
935 string_append (decl
, "real");
938 /* Imaginary and Complex types */
941 string_append (decl
, "ifloat");
945 string_append (decl
, "idouble");
949 string_append (decl
, "ireal");
953 string_append (decl
, "cfloat");
957 string_append (decl
, "cdouble");
961 string_append (decl
, "creal");
967 string_append (decl
, "bool");
971 string_append (decl
, "char");
975 string_append (decl
, "wchar");
979 string_append (decl
, "dchar");
987 string_append (decl
, "cent");
991 string_append (decl
, "ucent");
996 /* Back referenced type. */
998 return dlang_type_backref (decl
, mangled
, info
, 0);
1000 default: /* unhandled */
1005 /* Extract the identifier from MANGLED and append it to DECL.
1006 Return the remaining string on success or NULL on failure. */
1008 dlang_identifier (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1012 if (mangled
== NULL
|| *mangled
== '\0')
1015 if (*mangled
== 'Q')
1016 return dlang_symbol_backref (decl
, mangled
, info
);
1018 /* May be a template instance without a length prefix. */
1019 if (mangled
[0] == '_' && mangled
[1] == '_'
1020 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1021 return dlang_parse_template (decl
, mangled
, info
, TEMPLATE_LENGTH_UNKNOWN
);
1023 const char *endptr
= dlang_number (mangled
, &len
);
1025 if (endptr
== NULL
|| len
== 0)
1028 if (strlen (endptr
) < len
)
1033 /* May be a template instance with a length prefix. */
1034 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
1035 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1036 return dlang_parse_template (decl
, mangled
, info
, len
);
1038 return dlang_lname (decl
, mangled
, len
);
1041 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1042 with special treatment for some magic compiler generted symbols.
1043 Return the remaining string on success or NULL on failure. */
1045 dlang_lname (string
*decl
, const char *mangled
, unsigned long len
)
1050 if (strncmp (mangled
, "__ctor", len
) == 0)
1052 /* Constructor symbol for a class/struct. */
1053 string_append (decl
, "this");
1057 else if (strncmp (mangled
, "__dtor", len
) == 0)
1059 /* Destructor symbol for a class/struct. */
1060 string_append (decl
, "~this");
1064 else if (strncmp (mangled
, "__initZ", len
+ 1) == 0)
1066 /* The static initialiser for a given symbol. */
1067 string_prepend (decl
, "initializer for ");
1068 string_setlength (decl
, string_length (decl
) - 1);
1072 else if (strncmp (mangled
, "__vtblZ", len
+ 1) == 0)
1074 /* The vtable symbol for a given class. */
1075 string_prepend (decl
, "vtable for ");
1076 string_setlength (decl
, string_length (decl
) - 1);
1083 if (strncmp (mangled
, "__ClassZ", len
+ 1) == 0)
1085 /* The classinfo symbol for a given class. */
1086 string_prepend (decl
, "ClassInfo for ");
1087 string_setlength (decl
, string_length (decl
) - 1);
1094 if (strncmp (mangled
, "__postblitMFZ", len
+ 3) == 0)
1096 /* Postblit symbol for a struct. */
1097 string_append (decl
, "this(this)");
1104 if (strncmp (mangled
, "__InterfaceZ", len
+ 1) == 0)
1106 /* The interface symbol for a given class. */
1107 string_prepend (decl
, "Interface for ");
1108 string_setlength (decl
, string_length (decl
) - 1);
1115 if (strncmp (mangled
, "__ModuleInfoZ", len
+ 1) == 0)
1117 /* The ModuleInfo symbol for a given module. */
1118 string_prepend (decl
, "ModuleInfo for ");
1119 string_setlength (decl
, string_length (decl
) - 1);
1126 string_appendn (decl
, mangled
, len
);
1132 /* Extract the integer value from MANGLED and append it to DECL,
1133 where TYPE is the type it should be represented as.
1134 Return the remaining string on success or NULL on failure. */
1136 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
1138 if (type
== 'a' || type
== 'u' || type
== 'w')
1140 /* Parse character value. */
1142 int pos
= sizeof(value
);
1146 mangled
= dlang_number (mangled
, &val
);
1147 if (mangled
== NULL
)
1150 string_append (decl
, "'");
1152 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
1154 /* Represent as a character literal. */
1155 char c
= (char) val
;
1156 string_appendn (decl
, &c
, 1);
1160 /* Represent as a hexadecimal value. */
1163 case 'a': /* char */
1164 string_append (decl
, "\\x");
1167 case 'u': /* wchar */
1168 string_append (decl
, "\\u");
1171 case 'w': /* dchar */
1172 string_append (decl
, "\\U");
1179 int digit
= val
% 16;
1182 value
[--pos
] = (char)(digit
+ '0');
1184 value
[--pos
] = (char)((digit
- 10) + 'a');
1190 for (; width
> 0; width
--)
1193 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
1195 string_append (decl
, "'");
1197 else if (type
== 'b')
1199 /* Parse boolean value. */
1202 mangled
= dlang_number (mangled
, &val
);
1203 if (mangled
== NULL
)
1206 string_append (decl
, val
? "true" : "false");
1210 /* Parse integer value. */
1211 const char *numptr
= mangled
;
1214 if (! ISDIGIT (*mangled
))
1217 while (ISDIGIT (*mangled
))
1222 string_appendn (decl
, numptr
, num
);
1224 /* Append suffix. */
1227 case 'h': /* ubyte */
1228 case 't': /* ushort */
1229 case 'k': /* uint */
1230 string_append (decl
, "u");
1232 case 'l': /* long */
1233 string_append (decl
, "L");
1235 case 'm': /* ulong */
1236 string_append (decl
, "uL");
1244 /* Extract the floating-point value from MANGLED and append it to DECL.
1245 Return the remaining string on success or NULL on failure. */
1247 dlang_parse_real (string
*decl
, const char *mangled
)
1249 /* Handle NAN and +-INF. */
1250 if (strncmp (mangled
, "NAN", 3) == 0)
1252 string_append (decl
, "NaN");
1256 else if (strncmp (mangled
, "INF", 3) == 0)
1258 string_append (decl
, "Inf");
1262 else if (strncmp (mangled
, "NINF", 4) == 0)
1264 string_append (decl
, "-Inf");
1269 /* Hexadecimal prefix and leading bit. */
1270 if (*mangled
== 'N')
1272 string_append (decl
, "-");
1276 if (!ISXDIGIT (*mangled
))
1279 string_append (decl
, "0x");
1280 string_appendn (decl
, mangled
, 1);
1281 string_append (decl
, ".");
1285 while (ISXDIGIT (*mangled
))
1287 string_appendn (decl
, mangled
, 1);
1292 if (*mangled
!= 'P')
1295 string_append (decl
, "p");
1298 if (*mangled
== 'N')
1300 string_append (decl
, "-");
1304 while (ISDIGIT (*mangled
))
1306 string_appendn (decl
, mangled
, 1);
1313 /* Extract the string value from MANGLED and append it to DECL.
1314 Return the remaining string on success or NULL on failure. */
1316 dlang_parse_string (string
*decl
, const char *mangled
)
1318 char type
= *mangled
;
1322 mangled
= dlang_number (mangled
, &len
);
1323 if (mangled
== NULL
|| *mangled
!= '_')
1327 string_append (decl
, "\"");
1331 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1336 /* Sanitize white and non-printable characters. */
1340 string_append (decl
, " ");
1343 string_append (decl
, "\\t");
1346 string_append (decl
, "\\n");
1349 string_append (decl
, "\\r");
1352 string_append (decl
, "\\f");
1355 string_append (decl
, "\\v");
1360 string_appendn (decl
, &val
, 1);
1363 string_append (decl
, "\\x");
1364 string_appendn (decl
, mangled
, 2);
1370 string_append (decl
, "\"");
1373 string_appendn (decl
, &type
, 1);
1378 /* Extract the static array value from MANGLED and append it to DECL.
1379 Return the remaining string on success or NULL on failure. */
1381 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1383 unsigned long elements
;
1385 mangled
= dlang_number (mangled
, &elements
);
1386 if (mangled
== NULL
)
1389 string_append (decl
, "[");
1392 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1393 if (mangled
== NULL
)
1397 string_append (decl
, ", ");
1400 string_append (decl
, "]");
1404 /* Extract the associative array value from MANGLED and append it to DECL.
1405 Return the remaining string on success or NULL on failure. */
1407 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1409 unsigned long elements
;
1411 mangled
= dlang_number (mangled
, &elements
);
1412 if (mangled
== NULL
)
1415 string_append (decl
, "[");
1418 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1419 if (mangled
== NULL
)
1422 string_append (decl
, ":");
1423 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1424 if (mangled
== NULL
)
1428 string_append (decl
, ", ");
1431 string_append (decl
, "]");
1435 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1436 Return the remaining string on success or NULL on failure. */
1438 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1442 mangled
= dlang_number (mangled
, &args
);
1443 if (mangled
== NULL
)
1447 string_append (decl
, name
);
1449 string_append (decl
, "(");
1452 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1453 if (mangled
== NULL
)
1457 string_append (decl
, ", ");
1460 string_append (decl
, ")");
1464 /* Extract the value from MANGLED and append it to DECL.
1465 Return the remaining string on success or NULL on failure. */
1467 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1469 if (mangled
== NULL
|| *mangled
== '\0')
1477 string_append (decl
, "null");
1480 /* Integral values. */
1483 string_append (decl
, "-");
1484 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1491 /* There really should always be an `i' before encoded numbers, but there
1492 wasn't in early versions of D2, so this case range must remain for
1493 backwards compatibility. */
1494 case '0': case '1': case '2': case '3': case '4':
1495 case '5': case '6': case '7': case '8': case '9':
1496 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1502 mangled
= dlang_parse_real (decl
, mangled
);
1505 /* Complex value. */
1508 mangled
= dlang_parse_real (decl
, mangled
);
1509 string_append (decl
, "+");
1510 if (mangled
== NULL
|| *mangled
!= 'c')
1513 mangled
= dlang_parse_real (decl
, mangled
);
1514 string_append (decl
, "i");
1517 /* String values. */
1518 case 'a': /* UTF8 */
1519 case 'w': /* UTF16 */
1520 case 'd': /* UTF32 */
1521 mangled
= dlang_parse_string (decl
, mangled
);
1528 mangled
= dlang_parse_assocarray (decl
, mangled
);
1530 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1533 /* Struct values. */
1536 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1546 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1547 Returns the remaining signature on success or NULL on failure. */
1549 dlang_parse_mangle (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1551 /* A D mangled symbol is comprised of both scope and type information.
1554 _D QualifiedName Type
1557 The caller should have guaranteed that the start pointer is at the
1559 Note that type is never a function type, but only the return type of
1560 a function or the type of a variable.
1564 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 1);
1566 if (mangled
!= NULL
)
1568 /* Artificial symbols end with 'Z' and have no type. */
1569 if (*mangled
== 'Z')
1573 /* Discard the declaration or return type. */
1576 string_init (&type
);
1577 mangled
= dlang_type (&type
, mangled
, info
);
1578 string_delete (&type
);
1585 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1586 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1587 Returns the remaining signature on success or NULL on failure. */
1589 dlang_parse_qualified (string
*decl
, const char *mangled
,
1590 struct dlang_info
*info
, int suffix_modifiers
)
1592 /* Qualified names are identifiers separated by their encoded length.
1593 Nested functions also encode their argument types without specifying
1598 SymbolFunctionName QualifiedName
1603 SymbolName TypeFunctionNoReturn
1604 SymbolName M TypeFunctionNoReturn
1605 SymbolName M TypeModifiers TypeFunctionNoReturn
1607 The start pointer should be at the above location.
1613 string_append (decl
, ".");
1615 /* Skip over anonymous symbols. */
1616 while (*mangled
== '0')
1619 mangled
= dlang_identifier (decl
, mangled
, info
);
1621 /* Consume the encoded arguments. However if this is not followed by the
1622 next encoded length or mangle type, then this is not a continuation of
1623 a qualified name, in which case we backtrack and return the current
1624 unconsumed position of the mangled decl. */
1625 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1628 const char *start
= mangled
;
1629 int saved
= string_length (decl
);
1631 /* Save the type modifiers for appending at the end if needed. */
1632 string_init (&mods
);
1634 /* Skip over 'this' parameter and type modifiers. */
1635 if (*mangled
== 'M')
1638 mangled
= dlang_type_modifiers (&mods
, mangled
);
1639 string_setlength (decl
, saved
);
1642 mangled
= dlang_function_type_noreturn (decl
, NULL
, NULL
,
1644 if (suffix_modifiers
)
1645 string_appendn (decl
, mods
.b
, string_length (&mods
));
1647 if (mangled
== NULL
|| *mangled
== '\0')
1649 /* Did not match the rule we were looking for. */
1651 string_setlength (decl
, saved
);
1654 string_delete (&mods
);
1657 while (mangled
&& dlang_symbol_name_p (mangled
, info
));
1662 /* Demangle the tuple from MANGLED and append it to DECL.
1663 Return the remaining string on success or NULL on failure. */
1665 dlang_parse_tuple (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1667 unsigned long elements
;
1669 mangled
= dlang_number (mangled
, &elements
);
1670 if (mangled
== NULL
)
1673 string_append (decl
, "Tuple!(");
1677 mangled
= dlang_type (decl
, mangled
, info
);
1678 if (mangled
== NULL
)
1682 string_append (decl
, ", ");
1685 string_append (decl
, ")");
1689 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1690 Return the remaining string on success or NULL on failure. */
1692 dlang_template_symbol_param (string
*decl
, const char *mangled
,
1693 struct dlang_info
*info
)
1695 if (strncmp (mangled
, "_D", 2) == 0
1696 && dlang_symbol_name_p (mangled
+ 2, info
))
1697 return dlang_parse_mangle (decl
, mangled
, info
);
1699 if (*mangled
== 'Q')
1700 return dlang_parse_qualified (decl
, mangled
, info
, 0);
1703 const char *endptr
= dlang_number (mangled
, &len
);
1705 if (endptr
== NULL
|| len
== 0)
1708 /* In template parameter symbols generated by the frontend up to 2.076,
1709 the symbol length is encoded and the first character of the mangled
1710 name can be a digit. This causes ambiguity issues because the digits
1711 of the two numbers are adjacent. */
1714 int saved
= string_length (decl
);
1716 /* Work backwards until a match is found. */
1717 for (pend
= endptr
; endptr
!= NULL
; pend
--)
1721 /* Reached the beginning of the pointer to the name length,
1722 try parsing the entire symbol. */
1730 /* Check whether template parameter is a function with a valid
1731 return type or an untyped identifier. */
1732 if (dlang_symbol_name_p (mangled
, info
))
1733 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 0);
1734 else if (strncmp (mangled
, "_D", 2) == 0
1735 && dlang_symbol_name_p (mangled
+ 2, info
))
1736 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1738 /* Check for name length mismatch. */
1739 if (mangled
&& (endptr
== NULL
|| (mangled
- pend
) == psize
))
1743 string_setlength (decl
, saved
);
1746 /* No match on any combinations. */
1750 /* Demangle the argument list from MANGLED and append it to DECL.
1751 Return the remaining string on success or NULL on failure. */
1753 dlang_template_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1757 while (mangled
&& *mangled
!= '\0')
1761 case 'Z': /* End of parameter list. */
1767 string_append (decl
, ", ");
1769 /* Skip over specialised template prefix. */
1770 if (*mangled
== 'H')
1775 case 'S': /* Symbol parameter. */
1777 mangled
= dlang_template_symbol_param (decl
, mangled
, info
);
1779 case 'T': /* Type parameter. */
1781 mangled
= dlang_type (decl
, mangled
, info
);
1783 case 'V': /* Value parameter. */
1788 /* Peek at the type. */
1794 /* Value type is a back reference, peek at the real type. */
1795 const char *backref
;
1796 if (dlang_backref (mangled
, &backref
, info
) == NULL
)
1802 /* In the few instances where the type is actually desired in
1803 the output, it should precede the value from dlang_value. */
1804 string_init (&name
);
1805 mangled
= dlang_type (&name
, mangled
, info
);
1806 string_need (&name
, 1);
1809 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1810 string_delete (&name
);
1813 case 'X': /* Externally mangled parameter. */
1819 endptr
= dlang_number (mangled
, &len
);
1820 if (endptr
== NULL
|| strlen (endptr
) < len
)
1823 string_appendn (decl
, endptr
, len
);
1824 mangled
= endptr
+ len
;
1835 /* Extract and demangle the template symbol in MANGLED, expected to
1836 be made up of LEN characters (-1 if unknown), and append it to DECL.
1837 Returns the remaining signature on success or NULL on failure. */
1839 dlang_parse_template (string
*decl
, const char *mangled
,
1840 struct dlang_info
*info
, unsigned long len
)
1842 const char *start
= mangled
;
1845 /* Template instance names have the types and values of its parameters
1848 TemplateInstanceName:
1849 Number __T LName TemplateArgs Z
1850 Number __U LName TemplateArgs Z
1852 The start pointer should be at the above location, and LEN should be
1853 the value of the decoded number.
1856 /* Template symbol. */
1857 if (!dlang_symbol_name_p (mangled
+ 3, info
) || mangled
[3] == '0')
1862 /* Template identifier. */
1863 mangled
= dlang_identifier (decl
, mangled
, info
);
1865 /* Template arguments. */
1866 string_init (&args
);
1867 mangled
= dlang_template_args (&args
, mangled
, info
);
1869 string_append (decl
, "!(");
1870 string_appendn (decl
, args
.b
, string_length (&args
));
1871 string_append (decl
, ")");
1873 string_delete (&args
);
1875 /* Check for template name length mismatch. */
1876 if (len
!= TEMPLATE_LENGTH_UNKNOWN
1878 && (unsigned long) (mangled
- start
) != len
)
1884 /* Initialize the information structure we use to pass around information. */
1886 dlang_demangle_init_info (const char *mangled
, int last_backref
,
1887 struct dlang_info
*info
)
1890 info
->last_backref
= last_backref
;
1893 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1894 signature on success or NULL on failure. */
1897 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1900 char *demangled
= NULL
;
1902 if (mangled
== NULL
|| *mangled
== '\0')
1905 if (strncmp (mangled
, "_D", 2) != 0)
1908 string_init (&decl
);
1910 if (strcmp (mangled
, "_Dmain") == 0)
1912 string_append (&decl
, "D main");
1916 struct dlang_info info
;
1918 dlang_demangle_init_info (mangled
, strlen (mangled
), &info
);
1919 mangled
= dlang_parse_mangle (&decl
, mangled
, &info
);
1921 /* Check that the entire symbol was successfully demangled. */
1922 if (mangled
== NULL
|| *mangled
!= '\0')
1923 string_delete (&decl
);
1926 if (string_length (&decl
) > 0)
1928 string_need (&decl
, 1);