]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libiberty/d-demangle.c
1 /* Demangler for the D programming language
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 In addition to the permissions in the GNU Library General Public
12 License, the Free Software Foundation gives you unlimited permission
13 to link the compiled version of this file into combinations with other
14 programs, and to distribute those combinations without any restriction
15 coming from the use of this file. (The Library Public License
16 restrictions do apply in other respects; for example, they cover
17 modification of the file, and distribution when not linked into a
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Library General Public License for more details.
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>. */
29 /* This file exports one function; dlang_demangle. */
35 #include "safe-ctype.h"
37 #include <sys/types.h>
46 #include "libiberty.h"
48 /* A mini string-handling package */
50 typedef struct string
/* Beware: these aren't required to be */
51 { /* '\0' terminated. */
52 char *b
; /* pointer to start of string */
53 char *p
; /* pointer after last character */
54 char *e
; /* pointer after end of allocated space */
58 string_need (string
*s
, int n
)
68 s
->p
= s
->b
= XNEWVEC (char, n
);
71 else if (s
->e
- s
->p
< n
)
76 s
->b
= XRESIZEVEC (char, s
->b
, n
);
83 string_delete (string
*s
)
88 s
->b
= s
->e
= s
->p
= NULL
;
93 string_init (string
*s
)
95 s
->b
= s
->p
= s
->e
= NULL
;
99 string_length (string
*s
)
109 string_setlength (string
*s
, int n
)
111 if (n
- string_length (s
) < 0)
118 string_append (string
*p
, const char *s
)
127 string_appendn (string
*p
, const char *s
, int n
)
138 string_prependn (string
*p
, const char *s
, int n
)
145 for (q
= p
->p
- 1; q
>= p
->b
; q
--)
155 string_prepend (string
*p
, const char *s
)
157 if (s
!= NULL
&& *s
!= '\0')
159 string_prependn (p
, s
, strlen (s
));
163 /* Demangle information structure we pass around. */
166 /* The string we are demangling. */
168 /* The index of the last back reference. */
172 /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
173 enum { TEMPLATE_LENGTH_UNKNOWN
= -1 };
175 /* Prototypes for forward referenced functions */
176 static const char *dlang_function_type (string
*, const char *,
177 struct dlang_info
*);
179 static const char *dlang_function_args (string
*, const char *,
180 struct dlang_info
*);
182 static const char *dlang_type (string
*, const char *, struct dlang_info
*);
184 static const char *dlang_value (string
*, const char *, const char *, char);
186 static const char *dlang_parse_qualified (string
*, const char *,
187 struct dlang_info
*, int);
189 static const char *dlang_parse_mangle (string
*, const char *,
190 struct dlang_info
*);
192 static const char *dlang_parse_tuple (string
*, const char *,
193 struct dlang_info
*);
195 static const char *dlang_parse_template (string
*, const char *,
196 struct dlang_info
*, long);
198 static const char *dlang_lname (string
*, const char *, long);
201 /* Extract the number from MANGLED, and assign the result to RET.
202 Return the remaining string on success or NULL on failure. */
204 dlang_number (const char *mangled
, long *ret
)
206 /* Return NULL if trying to extract something that isn't a digit. */
207 if (mangled
== NULL
|| !ISDIGIT (*mangled
))
212 while (ISDIGIT (*mangled
))
216 /* If an overflow occured when multiplying by ten, the result
217 will not be a multiple of ten. */
218 if ((*ret
% 10) != 0)
221 (*ret
) += mangled
[0] - '0';
225 if (*mangled
== '\0' || *ret
< 0)
231 /* Extract the hex-digit from MANGLED, and assign the result to RET.
232 Return the remaining string on success or NULL on failure. */
234 dlang_hexdigit (const char *mangled
, char *ret
)
238 /* Return NULL if trying to extract something that isn't a hexdigit. */
239 if (mangled
== NULL
|| !ISXDIGIT (mangled
[0]) || !ISXDIGIT (mangled
[1]))
244 (*ret
) = (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
250 (*ret
) = (*ret
<< 4) | (c
- (ISUPPER (c
) ? 'A' : 'a') + 10);
252 (*ret
) = (*ret
<< 4) | (c
- '0');
259 /* Extract the function calling convention from MANGLED and
260 return 1 on success or 0 on failure. */
262 dlang_call_convention_p (const char *mangled
)
266 case 'F': case 'U': case 'V':
267 case 'W': case 'R': case 'Y':
275 /* Extract the back reference position from MANGLED, and assign the result
276 to RET. Return the remaining string on success or NULL on failure. */
278 dlang_decode_backref (const char *mangled
, long *ret
)
280 /* Return NULL if trying to extract something that isn't a digit. */
281 if (mangled
== NULL
|| !ISALPHA (*mangled
))
284 /* Any identifier or non-basic type that has been emitted to the mangled
285 symbol before will not be emitted again, but is referenced by a special
286 sequence encoding the relative position of the original occurrence in the
289 Numbers in back references are encoded with base 26 by upper case letters
290 A-Z for higher digits but lower case letters a-z for the last digit.
299 while (ISALPHA (*mangled
))
303 /* If an overflow occured when multiplying by 26, the result
304 will not be a multiple of 26. */
305 if ((*ret
% 26) != 0)
308 if (mangled
[0] >= 'a' && mangled
[0] <= 'z')
310 (*ret
) += mangled
[0] - 'a';
314 (*ret
) += mangled
[0] - 'A';
321 /* Extract the symbol pointed at by the back reference and assign the result
322 to RET. Return the remaining string on success or NULL on failure. */
324 dlang_backref (const char *mangled
, const char **ret
, struct dlang_info
*info
)
328 if (mangled
== NULL
|| *mangled
!= 'Q')
331 /* Position of 'Q'. */
332 const char *qpos
= mangled
;
336 mangled
= dlang_decode_backref (mangled
, &refpos
);
340 if (refpos
<= 0 || refpos
> qpos
- info
->s
)
343 /* Set the position of the back reference. */
344 (*ret
) = qpos
- refpos
;
349 /* Demangle a back referenced symbol from MANGLED and append it to DECL.
350 Return the remaining string on success or NULL on failure. */
352 dlang_symbol_backref (string
*decl
, const char *mangled
,
353 struct dlang_info
*info
)
355 /* An identifier back reference always points to a digit 0 to 9.
364 /* Get position of the back reference. */
365 mangled
= dlang_backref (mangled
, &backref
, info
);
367 /* Must point to a simple identifier. */
368 backref
= dlang_number (backref
, &len
);
372 backref
= dlang_lname (decl
, backref
, len
);
379 /* Demangle a back referenced type from MANGLED and append it to DECL.
380 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
381 Return the remaining string on success or NULL on failure. */
383 dlang_type_backref (string
*decl
, const char *mangled
, struct dlang_info
*info
,
386 /* A type back reference always points to a letter.
394 /* If we appear to be moving backwards through the mangle string, then
395 bail as this may be a recursive back reference. */
396 if (mangled
- info
->s
>= info
->last_backref
)
399 int save_refpos
= info
->last_backref
;
400 info
->last_backref
= mangled
- info
->s
;
402 /* Get position of the back reference. */
403 mangled
= dlang_backref (mangled
, &backref
, info
);
405 /* Must point to a type. */
407 backref
= dlang_function_type (decl
, backref
, info
);
409 backref
= dlang_type (decl
, backref
, info
);
411 info
->last_backref
= save_refpos
;
419 /* Extract the beginning of a symbol name from MANGLED and
420 return 1 on success or 0 on failure. */
422 dlang_symbol_name_p (const char *mangled
, struct dlang_info
*info
)
425 const char *qref
= mangled
;
427 if (ISDIGIT (*mangled
))
430 if (mangled
[0] == '_' && mangled
[1] == '_'
431 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
437 mangled
= dlang_decode_backref (mangled
+ 1, &ret
);
438 if (mangled
== NULL
|| ret
<= 0 || ret
> qref
- info
->s
)
441 return ISDIGIT (qref
[-ret
]);
444 /* Demangle the calling convention from MANGLED and append it to DECL.
445 Return the remaining string on success or NULL on failure. */
447 dlang_call_convention (string
*decl
, const char *mangled
)
449 if (mangled
== NULL
|| *mangled
== '\0')
459 string_append (decl
, "extern(C) ");
461 case 'W': /* (Windows) */
463 string_append (decl
, "extern(Windows) ");
465 case 'V': /* (Pascal) */
467 string_append (decl
, "extern(Pascal) ");
469 case 'R': /* (C++) */
471 string_append (decl
, "extern(C++) ");
473 case 'Y': /* (Objective-C) */
475 string_append (decl
, "extern(Objective-C) ");
484 /* Extract the type modifiers from MANGLED and append them to DECL.
485 Returns the remaining signature on success or NULL on failure. */
487 dlang_type_modifiers (string
*decl
, const char *mangled
)
489 if (mangled
== NULL
|| *mangled
== '\0')
494 case 'x': /* const */
496 string_append (decl
, " const");
498 case 'y': /* immutable */
500 string_append (decl
, " immutable");
502 case 'O': /* shared */
504 string_append (decl
, " shared");
505 return dlang_type_modifiers (decl
, mangled
);
508 if (*mangled
== 'g') /* wild */
511 string_append (decl
, " inout");
512 return dlang_type_modifiers (decl
, mangled
);
522 /* Demangle the D function attributes from MANGLED and append it to DECL.
523 Return the remaining string on success or NULL on failure. */
525 dlang_attributes (string
*decl
, const char *mangled
)
527 if (mangled
== NULL
|| *mangled
== '\0')
530 while (*mangled
== 'N')
537 string_append (decl
, "pure ");
539 case 'b': /* nothrow */
541 string_append (decl
, "nothrow ");
545 string_append (decl
, "ref ");
547 case 'd': /* @property */
549 string_append (decl
, "@property ");
551 case 'e': /* @trusted */
553 string_append (decl
, "@trusted ");
555 case 'f': /* @safe */
557 string_append (decl
, "@safe ");
562 /* inout parameter is represented as 'Ng'.
563 vector parameter is represented as 'Nh'.
564 return paramenter is represented as 'Nk'.
565 If we see this, then we know we're really in the
566 parameter list. Rewind and break. */
569 case 'i': /* @nogc */
571 string_append (decl
, "@nogc ");
573 case 'j': /* return */
575 string_append (decl
, "return ");
577 case 'l': /* scope */
579 string_append (decl
, "scope ");
581 case 'm': /* @live */
583 string_append (decl
, "@live ");
586 default: /* unknown attribute */
595 /* Demangle the function type from MANGLED without the return type.
596 The arguments are appended to ARGS, the calling convention is appended
597 to CALL and attributes are appended to ATTR. Any of these can be NULL
598 to throw the information away. Return the remaining string on success
599 or NULL on failure. */
601 dlang_function_type_noreturn (string
*args
, string
*call
, string
*attr
,
602 const char *mangled
, struct dlang_info
*info
)
607 /* Skip over calling convention and attributes. */
608 mangled
= dlang_call_convention (call
? call
: &dump
, mangled
);
609 mangled
= dlang_attributes (attr
? attr
: &dump
, mangled
);
612 string_append (args
, "(");
614 mangled
= dlang_function_args (args
? args
: &dump
, mangled
, info
);
616 string_append (args
, ")");
618 string_delete (&dump
);
622 /* Demangle the function type from MANGLED and append it to DECL.
623 Return the remaining string on success or NULL on failure. */
625 dlang_function_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
627 string attr
, args
, type
;
629 if (mangled
== NULL
|| *mangled
== '\0')
632 /* The order of the mangled string is:
633 CallConvention FuncAttrs Arguments ArgClose Type
635 The demangled string is re-ordered as:
636 CallConvention Type Arguments FuncAttrs
642 mangled
= dlang_function_type_noreturn (&args
, decl
, &attr
, mangled
, info
);
644 /* Function return type. */
645 mangled
= dlang_type (&type
, mangled
, info
);
647 /* Append to decl in order. */
648 string_appendn (decl
, type
.b
, string_length (&type
));
649 string_appendn (decl
, args
.b
, string_length (&args
));
650 string_append (decl
, " ");
651 string_appendn (decl
, attr
.b
, string_length (&attr
));
653 string_delete (&attr
);
654 string_delete (&args
);
655 string_delete (&type
);
659 /* Demangle the argument list from MANGLED and append it to DECL.
660 Return the remaining string on success or NULL on failure. */
662 dlang_function_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
666 while (mangled
&& *mangled
!= '\0')
670 case 'X': /* (variadic T t...) style. */
672 string_append (decl
, "...");
674 case 'Y': /* (variadic T t, ...) style. */
677 string_append (decl
, ", ");
678 string_append (decl
, "...");
680 case 'Z': /* Normal function. */
686 string_append (decl
, ", ");
688 if (*mangled
== 'M') /* scope(T) */
691 string_append (decl
, "scope ");
694 if (mangled
[0] == 'N' && mangled
[1] == 'k') /* return(T) */
697 string_append (decl
, "return ");
702 case 'I': /* in(T) */
704 string_append (decl
, "in ");
705 if (*mangled
== 'K') /* in ref(T) */
708 string_append (decl
, "ref ");
711 case 'J': /* out(T) */
713 string_append (decl
, "out ");
715 case 'K': /* ref(T) */
717 string_append (decl
, "ref ");
719 case 'L': /* lazy(T) */
721 string_append (decl
, "lazy ");
724 mangled
= dlang_type (decl
, mangled
, info
);
730 /* Demangle the type from MANGLED and append it to DECL.
731 Return the remaining string on success or NULL on failure. */
733 dlang_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
735 if (mangled
== NULL
|| *mangled
== '\0')
740 case 'O': /* shared(T) */
742 string_append (decl
, "shared(");
743 mangled
= dlang_type (decl
, mangled
, info
);
744 string_append (decl
, ")");
746 case 'x': /* const(T) */
748 string_append (decl
, "const(");
749 mangled
= dlang_type (decl
, mangled
, info
);
750 string_append (decl
, ")");
752 case 'y': /* immutable(T) */
754 string_append (decl
, "immutable(");
755 mangled
= dlang_type (decl
, mangled
, info
);
756 string_append (decl
, ")");
760 if (*mangled
== 'g') /* wild(T) */
763 string_append (decl
, "inout(");
764 mangled
= dlang_type (decl
, mangled
, info
);
765 string_append (decl
, ")");
768 else if (*mangled
== 'h') /* vector(T) */
771 string_append (decl
, "__vector(");
772 mangled
= dlang_type (decl
, mangled
, info
);
773 string_append (decl
, ")");
778 case 'A': /* dynamic array (T[]) */
780 mangled
= dlang_type (decl
, mangled
, info
);
781 string_append (decl
, "[]");
783 case 'G': /* static array (T[N]) */
790 while (ISDIGIT (*mangled
))
795 mangled
= dlang_type (decl
, mangled
, info
);
796 string_append (decl
, "[");
797 string_appendn (decl
, numptr
, num
);
798 string_append (decl
, "]");
801 case 'H': /* associative array (T[T]) */
808 mangled
= dlang_type (&type
, mangled
, info
);
809 sztype
= string_length (&type
);
811 mangled
= dlang_type (decl
, mangled
, info
);
812 string_append (decl
, "[");
813 string_appendn (decl
, type
.b
, sztype
);
814 string_append (decl
, "]");
816 string_delete (&type
);
819 case 'P': /* pointer (T*) */
821 if (!dlang_call_convention_p (mangled
))
823 mangled
= dlang_type (decl
, mangled
, info
);
824 string_append (decl
, "*");
828 case 'F': /* function T (D) */
829 case 'U': /* function T (C) */
830 case 'W': /* function T (Windows) */
831 case 'V': /* function T (Pascal) */
832 case 'R': /* function T (C++) */
833 case 'Y': /* function T (Objective-C) */
834 /* Function pointer types don't include the trailing asterisk. */
835 mangled
= dlang_function_type (decl
, mangled
, info
);
836 string_append (decl
, "function");
838 case 'C': /* class T */
839 case 'S': /* struct T */
840 case 'E': /* enum T */
841 case 'T': /* typedef T */
843 return dlang_parse_qualified (decl
, mangled
, info
, 0);
844 case 'D': /* delegate T */
851 mangled
= dlang_type_modifiers (&mods
, mangled
);
852 szmods
= string_length (&mods
);
854 /* Back referenced function type. */
856 mangled
= dlang_type_backref (decl
, mangled
, info
, 1);
858 mangled
= dlang_function_type (decl
, mangled
, info
);
860 string_append (decl
, "delegate");
861 string_appendn (decl
, mods
.b
, szmods
);
863 string_delete (&mods
);
866 case 'B': /* tuple T */
868 return dlang_parse_tuple (decl
, mangled
, info
);
873 string_append (decl
, "none");
877 string_append (decl
, "void");
881 string_append (decl
, "byte");
885 string_append (decl
, "ubyte");
889 string_append (decl
, "short");
893 string_append (decl
, "ushort");
897 string_append (decl
, "int");
901 string_append (decl
, "uint");
905 string_append (decl
, "long");
909 string_append (decl
, "ulong");
913 string_append (decl
, "float");
917 string_append (decl
, "double");
921 string_append (decl
, "real");
924 /* Imaginary and Complex types */
927 string_append (decl
, "ifloat");
931 string_append (decl
, "idouble");
935 string_append (decl
, "ireal");
939 string_append (decl
, "cfloat");
943 string_append (decl
, "cdouble");
947 string_append (decl
, "creal");
953 string_append (decl
, "bool");
957 string_append (decl
, "char");
961 string_append (decl
, "wchar");
965 string_append (decl
, "dchar");
973 string_append (decl
, "cent");
977 string_append (decl
, "ucent");
982 /* Back referenced type. */
984 return dlang_type_backref (decl
, mangled
, info
, 0);
986 default: /* unhandled */
991 /* Extract the identifier from MANGLED and append it to DECL.
992 Return the remaining string on success or NULL on failure. */
994 dlang_identifier (string
*decl
, const char *mangled
, struct dlang_info
*info
)
998 if (mangled
== NULL
|| *mangled
== '\0')
1001 if (*mangled
== 'Q')
1002 return dlang_symbol_backref (decl
, mangled
, info
);
1004 /* May be a template instance without a length prefix. */
1005 if (mangled
[0] == '_' && mangled
[1] == '_'
1006 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1007 return dlang_parse_template (decl
, mangled
, info
, TEMPLATE_LENGTH_UNKNOWN
);
1009 const char *endptr
= dlang_number (mangled
, &len
);
1011 if (endptr
== NULL
|| len
== 0)
1014 if (strlen (endptr
) < (size_t) len
)
1019 /* May be a template instance with a length prefix. */
1020 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
1021 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1022 return dlang_parse_template (decl
, mangled
, info
, len
);
1024 return dlang_lname (decl
, mangled
, len
);
1027 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1028 with special treatment for some magic compiler generted symbols.
1029 Return the remaining string on success or NULL on failure. */
1031 dlang_lname (string
*decl
, const char *mangled
, long len
)
1036 if (strncmp (mangled
, "__ctor", len
) == 0)
1038 /* Constructor symbol for a class/struct. */
1039 string_append (decl
, "this");
1043 else if (strncmp (mangled
, "__dtor", len
) == 0)
1045 /* Destructor symbol for a class/struct. */
1046 string_append (decl
, "~this");
1050 else if (strncmp (mangled
, "__initZ", len
+ 1) == 0)
1052 /* The static initialiser for a given symbol. */
1053 string_prepend (decl
, "initializer for ");
1054 string_setlength (decl
, string_length (decl
) - 1);
1058 else if (strncmp (mangled
, "__vtblZ", len
+ 1) == 0)
1060 /* The vtable symbol for a given class. */
1061 string_prepend (decl
, "vtable for ");
1062 string_setlength (decl
, string_length (decl
) - 1);
1069 if (strncmp (mangled
, "__ClassZ", len
+ 1) == 0)
1071 /* The classinfo symbol for a given class. */
1072 string_prepend (decl
, "ClassInfo for ");
1073 string_setlength (decl
, string_length (decl
) - 1);
1080 if (strncmp (mangled
, "__postblitMFZ", len
+ 3) == 0)
1082 /* Postblit symbol for a struct. */
1083 string_append (decl
, "this(this)");
1090 if (strncmp (mangled
, "__InterfaceZ", len
+ 1) == 0)
1092 /* The interface symbol for a given class. */
1093 string_prepend (decl
, "Interface for ");
1094 string_setlength (decl
, string_length (decl
) - 1);
1101 if (strncmp (mangled
, "__ModuleInfoZ", len
+ 1) == 0)
1103 /* The ModuleInfo symbol for a given module. */
1104 string_prepend (decl
, "ModuleInfo for ");
1105 string_setlength (decl
, string_length (decl
) - 1);
1112 string_appendn (decl
, mangled
, len
);
1118 /* Extract the integer value from MANGLED and append it to DECL,
1119 where TYPE is the type it should be represented as.
1120 Return the remaining string on success or NULL on failure. */
1122 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
1124 if (type
== 'a' || type
== 'u' || type
== 'w')
1126 /* Parse character value. */
1128 int pos
= sizeof(value
);
1132 mangled
= dlang_number (mangled
, &val
);
1133 if (mangled
== NULL
)
1136 string_append (decl
, "'");
1138 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
1140 /* Represent as a character literal. */
1141 char c
= (char) val
;
1142 string_appendn (decl
, &c
, 1);
1146 /* Represent as a hexadecimal value. */
1149 case 'a': /* char */
1150 string_append (decl
, "\\x");
1153 case 'u': /* wchar */
1154 string_append (decl
, "\\u");
1157 case 'w': /* dchar */
1158 string_append (decl
, "\\U");
1165 int digit
= val
% 16;
1168 value
[--pos
] = (char)(digit
+ '0');
1170 value
[--pos
] = (char)((digit
- 10) + 'a');
1176 for (; width
> 0; width
--)
1179 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
1181 string_append (decl
, "'");
1183 else if (type
== 'b')
1185 /* Parse boolean value. */
1188 mangled
= dlang_number (mangled
, &val
);
1189 if (mangled
== NULL
)
1192 string_append (decl
, val
? "true" : "false");
1196 /* Parse integer value. */
1197 const char *numptr
= mangled
;
1200 if (! ISDIGIT (*mangled
))
1203 while (ISDIGIT (*mangled
))
1208 string_appendn (decl
, numptr
, num
);
1210 /* Append suffix. */
1213 case 'h': /* ubyte */
1214 case 't': /* ushort */
1215 case 'k': /* uint */
1216 string_append (decl
, "u");
1218 case 'l': /* long */
1219 string_append (decl
, "L");
1221 case 'm': /* ulong */
1222 string_append (decl
, "uL");
1230 /* Extract the floating-point value from MANGLED and append it to DECL.
1231 Return the remaining string on success or NULL on failure. */
1233 dlang_parse_real (string
*decl
, const char *mangled
)
1235 /* Handle NAN and +-INF. */
1236 if (strncmp (mangled
, "NAN", 3) == 0)
1238 string_append (decl
, "NaN");
1242 else if (strncmp (mangled
, "INF", 3) == 0)
1244 string_append (decl
, "Inf");
1248 else if (strncmp (mangled
, "NINF", 4) == 0)
1250 string_append (decl
, "-Inf");
1255 /* Hexadecimal prefix and leading bit. */
1256 if (*mangled
== 'N')
1258 string_append (decl
, "-");
1262 if (!ISXDIGIT (*mangled
))
1265 string_append (decl
, "0x");
1266 string_appendn (decl
, mangled
, 1);
1267 string_append (decl
, ".");
1271 while (ISXDIGIT (*mangled
))
1273 string_appendn (decl
, mangled
, 1);
1278 if (*mangled
!= 'P')
1281 string_append (decl
, "p");
1284 if (*mangled
== 'N')
1286 string_append (decl
, "-");
1290 while (ISDIGIT (*mangled
))
1292 string_appendn (decl
, mangled
, 1);
1299 /* Extract the string value from MANGLED and append it to DECL.
1300 Return the remaining string on success or NULL on failure. */
1302 dlang_parse_string (string
*decl
, const char *mangled
)
1304 char type
= *mangled
;
1308 mangled
= dlang_number (mangled
, &len
);
1309 if (mangled
== NULL
|| *mangled
!= '_')
1313 string_append (decl
, "\"");
1317 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1322 /* Sanitize white and non-printable characters. */
1326 string_append (decl
, " ");
1329 string_append (decl
, "\\t");
1332 string_append (decl
, "\\n");
1335 string_append (decl
, "\\r");
1338 string_append (decl
, "\\f");
1341 string_append (decl
, "\\v");
1346 string_appendn (decl
, &val
, 1);
1349 string_append (decl
, "\\x");
1350 string_appendn (decl
, mangled
, 2);
1356 string_append (decl
, "\"");
1359 string_appendn (decl
, &type
, 1);
1364 /* Extract the static array value from MANGLED and append it to DECL.
1365 Return the remaining string on success or NULL on failure. */
1367 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1371 mangled
= dlang_number (mangled
, &elements
);
1372 if (mangled
== NULL
)
1375 string_append (decl
, "[");
1378 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1379 if (mangled
== NULL
)
1383 string_append (decl
, ", ");
1386 string_append (decl
, "]");
1390 /* Extract the associative array value from MANGLED and append it to DECL.
1391 Return the remaining string on success or NULL on failure. */
1393 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1397 mangled
= dlang_number (mangled
, &elements
);
1398 if (mangled
== NULL
)
1401 string_append (decl
, "[");
1404 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1405 if (mangled
== NULL
)
1408 string_append (decl
, ":");
1409 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1410 if (mangled
== NULL
)
1414 string_append (decl
, ", ");
1417 string_append (decl
, "]");
1421 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1422 Return the remaining string on success or NULL on failure. */
1424 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1428 mangled
= dlang_number (mangled
, &args
);
1429 if (mangled
== NULL
)
1433 string_append (decl
, name
);
1435 string_append (decl
, "(");
1438 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1439 if (mangled
== NULL
)
1443 string_append (decl
, ", ");
1446 string_append (decl
, ")");
1450 /* Extract the value from MANGLED and append it to DECL.
1451 Return the remaining string on success or NULL on failure. */
1453 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1455 if (mangled
== NULL
|| *mangled
== '\0')
1463 string_append (decl
, "null");
1466 /* Integral values. */
1469 string_append (decl
, "-");
1470 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1477 /* There really should always be an `i' before encoded numbers, but there
1478 wasn't in early versions of D2, so this case range must remain for
1479 backwards compatibility. */
1480 case '0': case '1': case '2': case '3': case '4':
1481 case '5': case '6': case '7': case '8': case '9':
1482 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1488 mangled
= dlang_parse_real (decl
, mangled
);
1491 /* Complex value. */
1494 mangled
= dlang_parse_real (decl
, mangled
);
1495 string_append (decl
, "+");
1496 if (mangled
== NULL
|| *mangled
!= 'c')
1499 mangled
= dlang_parse_real (decl
, mangled
);
1500 string_append (decl
, "i");
1503 /* String values. */
1504 case 'a': /* UTF8 */
1505 case 'w': /* UTF16 */
1506 case 'd': /* UTF32 */
1507 mangled
= dlang_parse_string (decl
, mangled
);
1514 mangled
= dlang_parse_assocarray (decl
, mangled
);
1516 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1519 /* Struct values. */
1522 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1532 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1533 Returns the remaining signature on success or NULL on failure. */
1535 dlang_parse_mangle (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1537 /* A D mangled symbol is comprised of both scope and type information.
1540 _D QualifiedName Type
1543 The caller should have guaranteed that the start pointer is at the
1545 Note that type is never a function type, but only the return type of
1546 a function or the type of a variable.
1550 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 1);
1552 if (mangled
!= NULL
)
1554 /* Artificial symbols end with 'Z' and have no type. */
1555 if (*mangled
== 'Z')
1559 /* Discard the declaration or return type. */
1562 string_init (&type
);
1563 mangled
= dlang_type (&type
, mangled
, info
);
1564 string_delete (&type
);
1571 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1572 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1573 Returns the remaining signature on success or NULL on failure. */
1575 dlang_parse_qualified (string
*decl
, const char *mangled
,
1576 struct dlang_info
*info
, int suffix_modifiers
)
1578 /* Qualified names are identifiers separated by their encoded length.
1579 Nested functions also encode their argument types without specifying
1584 SymbolFunctionName QualifiedName
1589 SymbolName TypeFunctionNoReturn
1590 SymbolName M TypeFunctionNoReturn
1591 SymbolName M TypeModifiers TypeFunctionNoReturn
1593 The start pointer should be at the above location.
1599 string_append (decl
, ".");
1601 /* Skip over anonymous symbols. */
1602 while (*mangled
== '0')
1605 mangled
= dlang_identifier (decl
, mangled
, info
);
1607 /* Consume the encoded arguments. However if this is not followed by the
1608 next encoded length or mangle type, then this is not a continuation of
1609 a qualified name, in which case we backtrack and return the current
1610 unconsumed position of the mangled decl. */
1611 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1614 const char *start
= mangled
;
1615 int saved
= string_length (decl
);
1617 /* Save the type modifiers for appending at the end if needed. */
1618 string_init (&mods
);
1620 /* Skip over 'this' parameter and type modifiers. */
1621 if (*mangled
== 'M')
1624 mangled
= dlang_type_modifiers (&mods
, mangled
);
1625 string_setlength (decl
, saved
);
1628 mangled
= dlang_function_type_noreturn (decl
, NULL
, NULL
,
1630 if (suffix_modifiers
)
1631 string_appendn (decl
, mods
.b
, string_length (&mods
));
1633 if (mangled
== NULL
|| *mangled
== '\0')
1635 /* Did not match the rule we were looking for. */
1637 string_setlength (decl
, saved
);
1640 string_delete (&mods
);
1643 while (mangled
&& dlang_symbol_name_p (mangled
, info
));
1648 /* Demangle the tuple from MANGLED and append it to DECL.
1649 Return the remaining string on success or NULL on failure. */
1651 dlang_parse_tuple (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1655 mangled
= dlang_number (mangled
, &elements
);
1656 if (mangled
== NULL
)
1659 string_append (decl
, "Tuple!(");
1663 mangled
= dlang_type (decl
, mangled
, info
);
1664 if (mangled
== NULL
)
1668 string_append (decl
, ", ");
1671 string_append (decl
, ")");
1675 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1676 Return the remaining string on success or NULL on failure. */
1678 dlang_template_symbol_param (string
*decl
, const char *mangled
,
1679 struct dlang_info
*info
)
1681 if (strncmp (mangled
, "_D", 2) == 0
1682 && dlang_symbol_name_p (mangled
+ 2, info
))
1683 return dlang_parse_mangle (decl
, mangled
, info
);
1685 if (*mangled
== 'Q')
1686 return dlang_parse_qualified (decl
, mangled
, info
, 0);
1689 const char *endptr
= dlang_number (mangled
, &len
);
1691 if (endptr
== NULL
|| len
== 0)
1694 /* In template parameter symbols generated by the frontend up to 2.076,
1695 the symbol length is encoded and the first character of the mangled
1696 name can be a digit. This causes ambiguity issues because the digits
1697 of the two numbers are adjacent. */
1700 int saved
= string_length (decl
);
1702 /* Work backwards until a match is found. */
1703 for (pend
= endptr
; endptr
!= NULL
; pend
--)
1707 /* Reached the beginning of the pointer to the name length,
1708 try parsing the entire symbol. */
1716 /* Check whether template parameter is a function with a valid
1717 return type or an untyped identifier. */
1718 if (dlang_symbol_name_p (mangled
, info
))
1719 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 0);
1720 else if (strncmp (mangled
, "_D", 2) == 0
1721 && dlang_symbol_name_p (mangled
+ 2, info
))
1722 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1724 /* Check for name length mismatch. */
1725 if (mangled
&& (endptr
== NULL
|| (mangled
- pend
) == psize
))
1729 string_setlength (decl
, saved
);
1732 /* No match on any combinations. */
1736 /* Demangle the argument list from MANGLED and append it to DECL.
1737 Return the remaining string on success or NULL on failure. */
1739 dlang_template_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1743 while (mangled
&& *mangled
!= '\0')
1747 case 'Z': /* End of parameter list. */
1753 string_append (decl
, ", ");
1755 /* Skip over specialised template prefix. */
1756 if (*mangled
== 'H')
1761 case 'S': /* Symbol parameter. */
1763 mangled
= dlang_template_symbol_param (decl
, mangled
, info
);
1765 case 'T': /* Type parameter. */
1767 mangled
= dlang_type (decl
, mangled
, info
);
1769 case 'V': /* Value parameter. */
1774 /* Peek at the type. */
1780 /* Value type is a back reference, peek at the real type. */
1781 const char *backref
;
1782 if (dlang_backref (mangled
, &backref
, info
) == NULL
)
1788 /* In the few instances where the type is actually desired in
1789 the output, it should precede the value from dlang_value. */
1790 string_init (&name
);
1791 mangled
= dlang_type (&name
, mangled
, info
);
1792 string_need (&name
, 1);
1795 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1796 string_delete (&name
);
1799 case 'X': /* Externally mangled parameter. */
1805 endptr
= dlang_number (mangled
, &len
);
1806 if (endptr
== NULL
|| strlen (endptr
) < (size_t) len
)
1809 string_appendn (decl
, endptr
, len
);
1810 mangled
= endptr
+ len
;
1821 /* Extract and demangle the template symbol in MANGLED, expected to
1822 be made up of LEN characters (-1 if unknown), and append it to DECL.
1823 Returns the remaining signature on success or NULL on failure. */
1825 dlang_parse_template (string
*decl
, const char *mangled
,
1826 struct dlang_info
*info
, long len
)
1828 const char *start
= mangled
;
1831 /* Template instance names have the types and values of its parameters
1834 TemplateInstanceName:
1835 Number __T LName TemplateArgs Z
1836 Number __U LName TemplateArgs Z
1838 The start pointer should be at the above location, and LEN should be
1839 the value of the decoded number.
1842 /* Template symbol. */
1843 if (!dlang_symbol_name_p (mangled
+ 3, info
) || mangled
[3] == '0')
1848 /* Template identifier. */
1849 mangled
= dlang_identifier (decl
, mangled
, info
);
1851 /* Template arguments. */
1852 string_init (&args
);
1853 mangled
= dlang_template_args (&args
, mangled
, info
);
1855 string_append (decl
, "!(");
1856 string_appendn (decl
, args
.b
, string_length (&args
));
1857 string_append (decl
, ")");
1859 string_delete (&args
);
1861 /* Check for template name length mismatch. */
1862 if (len
!= TEMPLATE_LENGTH_UNKNOWN
&& mangled
&& (mangled
- start
) != len
)
1868 /* Initialize the information structure we use to pass around information. */
1870 dlang_demangle_init_info (const char *mangled
, int last_backref
,
1871 struct dlang_info
*info
)
1874 info
->last_backref
= last_backref
;
1877 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1878 signature on success or NULL on failure. */
1881 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1884 char *demangled
= NULL
;
1886 if (mangled
== NULL
|| *mangled
== '\0')
1889 if (strncmp (mangled
, "_D", 2) != 0)
1892 string_init (&decl
);
1894 if (strcmp (mangled
, "_Dmain") == 0)
1896 string_append (&decl
, "D main");
1900 struct dlang_info info
;
1902 dlang_demangle_init_info (mangled
, strlen (mangled
), &info
);
1903 mangled
= dlang_parse_mangle (&decl
, mangled
, &info
);
1905 /* Check that the entire symbol was successfully demangled. */
1906 if (mangled
== NULL
|| *mangled
!= '\0')
1907 string_delete (&decl
);
1910 if (string_length (&decl
) > 0)
1912 string_need (&decl
, 1);