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 'J': /* out(T) */
704 string_append (decl
, "out ");
706 case 'K': /* ref(T) */
708 string_append (decl
, "ref ");
710 case 'L': /* lazy(T) */
712 string_append (decl
, "lazy ");
715 mangled
= dlang_type (decl
, mangled
, info
);
721 /* Demangle the type from MANGLED and append it to DECL.
722 Return the remaining string on success or NULL on failure. */
724 dlang_type (string
*decl
, const char *mangled
, struct dlang_info
*info
)
726 if (mangled
== NULL
|| *mangled
== '\0')
731 case 'O': /* shared(T) */
733 string_append (decl
, "shared(");
734 mangled
= dlang_type (decl
, mangled
, info
);
735 string_append (decl
, ")");
737 case 'x': /* const(T) */
739 string_append (decl
, "const(");
740 mangled
= dlang_type (decl
, mangled
, info
);
741 string_append (decl
, ")");
743 case 'y': /* immutable(T) */
745 string_append (decl
, "immutable(");
746 mangled
= dlang_type (decl
, mangled
, info
);
747 string_append (decl
, ")");
751 if (*mangled
== 'g') /* wild(T) */
754 string_append (decl
, "inout(");
755 mangled
= dlang_type (decl
, mangled
, info
);
756 string_append (decl
, ")");
759 else if (*mangled
== 'h') /* vector(T) */
762 string_append (decl
, "__vector(");
763 mangled
= dlang_type (decl
, mangled
, info
);
764 string_append (decl
, ")");
769 case 'A': /* dynamic array (T[]) */
771 mangled
= dlang_type (decl
, mangled
, info
);
772 string_append (decl
, "[]");
774 case 'G': /* static array (T[N]) */
781 while (ISDIGIT (*mangled
))
786 mangled
= dlang_type (decl
, mangled
, info
);
787 string_append (decl
, "[");
788 string_appendn (decl
, numptr
, num
);
789 string_append (decl
, "]");
792 case 'H': /* associative array (T[T]) */
799 mangled
= dlang_type (&type
, mangled
, info
);
800 sztype
= string_length (&type
);
802 mangled
= dlang_type (decl
, mangled
, info
);
803 string_append (decl
, "[");
804 string_appendn (decl
, type
.b
, sztype
);
805 string_append (decl
, "]");
807 string_delete (&type
);
810 case 'P': /* pointer (T*) */
812 if (!dlang_call_convention_p (mangled
))
814 mangled
= dlang_type (decl
, mangled
, info
);
815 string_append (decl
, "*");
819 case 'F': /* function T (D) */
820 case 'U': /* function T (C) */
821 case 'W': /* function T (Windows) */
822 case 'V': /* function T (Pascal) */
823 case 'R': /* function T (C++) */
824 case 'Y': /* function T (Objective-C) */
825 /* Function pointer types don't include the trailing asterisk. */
826 mangled
= dlang_function_type (decl
, mangled
, info
);
827 string_append (decl
, "function");
829 case 'I': /* ident T */
830 case 'C': /* class T */
831 case 'S': /* struct T */
832 case 'E': /* enum T */
833 case 'T': /* typedef T */
835 return dlang_parse_qualified (decl
, mangled
, info
, 0);
836 case 'D': /* delegate T */
843 mangled
= dlang_type_modifiers (&mods
, mangled
);
844 szmods
= string_length (&mods
);
846 /* Back referenced function type. */
848 mangled
= dlang_type_backref (decl
, mangled
, info
, 1);
850 mangled
= dlang_function_type (decl
, mangled
, info
);
852 string_append (decl
, "delegate");
853 string_appendn (decl
, mods
.b
, szmods
);
855 string_delete (&mods
);
858 case 'B': /* tuple T */
860 return dlang_parse_tuple (decl
, mangled
, info
);
865 string_append (decl
, "none");
869 string_append (decl
, "void");
873 string_append (decl
, "byte");
877 string_append (decl
, "ubyte");
881 string_append (decl
, "short");
885 string_append (decl
, "ushort");
889 string_append (decl
, "int");
893 string_append (decl
, "uint");
897 string_append (decl
, "long");
901 string_append (decl
, "ulong");
905 string_append (decl
, "float");
909 string_append (decl
, "double");
913 string_append (decl
, "real");
916 /* Imaginary and Complex types */
919 string_append (decl
, "ifloat");
923 string_append (decl
, "idouble");
927 string_append (decl
, "ireal");
931 string_append (decl
, "cfloat");
935 string_append (decl
, "cdouble");
939 string_append (decl
, "creal");
945 string_append (decl
, "bool");
949 string_append (decl
, "char");
953 string_append (decl
, "wchar");
957 string_append (decl
, "dchar");
965 string_append (decl
, "cent");
969 string_append (decl
, "ucent");
974 /* Back referenced type. */
976 return dlang_type_backref (decl
, mangled
, info
, 0);
978 default: /* unhandled */
983 /* Extract the identifier from MANGLED and append it to DECL.
984 Return the remaining string on success or NULL on failure. */
986 dlang_identifier (string
*decl
, const char *mangled
, struct dlang_info
*info
)
990 if (mangled
== NULL
|| *mangled
== '\0')
994 return dlang_symbol_backref (decl
, mangled
, info
);
996 /* May be a template instance without a length prefix. */
997 if (mangled
[0] == '_' && mangled
[1] == '_'
998 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
999 return dlang_parse_template (decl
, mangled
, info
, TEMPLATE_LENGTH_UNKNOWN
);
1001 const char *endptr
= dlang_number (mangled
, &len
);
1003 if (endptr
== NULL
|| len
== 0)
1006 if (strlen (endptr
) < (size_t) len
)
1011 /* May be a template instance with a length prefix. */
1012 if (len
>= 5 && mangled
[0] == '_' && mangled
[1] == '_'
1013 && (mangled
[2] == 'T' || mangled
[2] == 'U'))
1014 return dlang_parse_template (decl
, mangled
, info
, len
);
1016 return dlang_lname (decl
, mangled
, len
);
1019 /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1020 with special treatment for some magic compiler generted symbols.
1021 Return the remaining string on success or NULL on failure. */
1023 dlang_lname (string
*decl
, const char *mangled
, long len
)
1028 if (strncmp (mangled
, "__ctor", len
) == 0)
1030 /* Constructor symbol for a class/struct. */
1031 string_append (decl
, "this");
1035 else if (strncmp (mangled
, "__dtor", len
) == 0)
1037 /* Destructor symbol for a class/struct. */
1038 string_append (decl
, "~this");
1042 else if (strncmp (mangled
, "__initZ", len
+ 1) == 0)
1044 /* The static initialiser for a given symbol. */
1045 string_prepend (decl
, "initializer for ");
1046 string_setlength (decl
, string_length (decl
) - 1);
1050 else if (strncmp (mangled
, "__vtblZ", len
+ 1) == 0)
1052 /* The vtable symbol for a given class. */
1053 string_prepend (decl
, "vtable for ");
1054 string_setlength (decl
, string_length (decl
) - 1);
1061 if (strncmp (mangled
, "__ClassZ", len
+ 1) == 0)
1063 /* The classinfo symbol for a given class. */
1064 string_prepend (decl
, "ClassInfo for ");
1065 string_setlength (decl
, string_length (decl
) - 1);
1072 if (strncmp (mangled
, "__postblitMFZ", len
+ 3) == 0)
1074 /* Postblit symbol for a struct. */
1075 string_append (decl
, "this(this)");
1082 if (strncmp (mangled
, "__InterfaceZ", len
+ 1) == 0)
1084 /* The interface symbol for a given class. */
1085 string_prepend (decl
, "Interface for ");
1086 string_setlength (decl
, string_length (decl
) - 1);
1093 if (strncmp (mangled
, "__ModuleInfoZ", len
+ 1) == 0)
1095 /* The ModuleInfo symbol for a given module. */
1096 string_prepend (decl
, "ModuleInfo for ");
1097 string_setlength (decl
, string_length (decl
) - 1);
1104 string_appendn (decl
, mangled
, len
);
1110 /* Extract the integer value from MANGLED and append it to DECL,
1111 where TYPE is the type it should be represented as.
1112 Return the remaining string on success or NULL on failure. */
1114 dlang_parse_integer (string
*decl
, const char *mangled
, char type
)
1116 if (type
== 'a' || type
== 'u' || type
== 'w')
1118 /* Parse character value. */
1120 int pos
= sizeof(value
);
1124 mangled
= dlang_number (mangled
, &val
);
1125 if (mangled
== NULL
)
1128 string_append (decl
, "'");
1130 if (type
== 'a' && val
>= 0x20 && val
< 0x7F)
1132 /* Represent as a character literal. */
1133 char c
= (char) val
;
1134 string_appendn (decl
, &c
, 1);
1138 /* Represent as a hexadecimal value. */
1141 case 'a': /* char */
1142 string_append (decl
, "\\x");
1145 case 'u': /* wchar */
1146 string_append (decl
, "\\u");
1149 case 'w': /* dchar */
1150 string_append (decl
, "\\U");
1157 int digit
= val
% 16;
1160 value
[--pos
] = (char)(digit
+ '0');
1162 value
[--pos
] = (char)((digit
- 10) + 'a');
1168 for (; width
> 0; width
--)
1171 string_appendn (decl
, &(value
[pos
]), sizeof(value
) - pos
);
1173 string_append (decl
, "'");
1175 else if (type
== 'b')
1177 /* Parse boolean value. */
1180 mangled
= dlang_number (mangled
, &val
);
1181 if (mangled
== NULL
)
1184 string_append (decl
, val
? "true" : "false");
1188 /* Parse integer value. */
1189 const char *numptr
= mangled
;
1192 if (! ISDIGIT (*mangled
))
1195 while (ISDIGIT (*mangled
))
1200 string_appendn (decl
, numptr
, num
);
1202 /* Append suffix. */
1205 case 'h': /* ubyte */
1206 case 't': /* ushort */
1207 case 'k': /* uint */
1208 string_append (decl
, "u");
1210 case 'l': /* long */
1211 string_append (decl
, "L");
1213 case 'm': /* ulong */
1214 string_append (decl
, "uL");
1222 /* Extract the floating-point value from MANGLED and append it to DECL.
1223 Return the remaining string on success or NULL on failure. */
1225 dlang_parse_real (string
*decl
, const char *mangled
)
1227 /* Handle NAN and +-INF. */
1228 if (strncmp (mangled
, "NAN", 3) == 0)
1230 string_append (decl
, "NaN");
1234 else if (strncmp (mangled
, "INF", 3) == 0)
1236 string_append (decl
, "Inf");
1240 else if (strncmp (mangled
, "NINF", 4) == 0)
1242 string_append (decl
, "-Inf");
1247 /* Hexadecimal prefix and leading bit. */
1248 if (*mangled
== 'N')
1250 string_append (decl
, "-");
1254 if (!ISXDIGIT (*mangled
))
1257 string_append (decl
, "0x");
1258 string_appendn (decl
, mangled
, 1);
1259 string_append (decl
, ".");
1263 while (ISXDIGIT (*mangled
))
1265 string_appendn (decl
, mangled
, 1);
1270 if (*mangled
!= 'P')
1273 string_append (decl
, "p");
1276 if (*mangled
== 'N')
1278 string_append (decl
, "-");
1282 while (ISDIGIT (*mangled
))
1284 string_appendn (decl
, mangled
, 1);
1291 /* Extract the string value from MANGLED and append it to DECL.
1292 Return the remaining string on success or NULL on failure. */
1294 dlang_parse_string (string
*decl
, const char *mangled
)
1296 char type
= *mangled
;
1300 mangled
= dlang_number (mangled
, &len
);
1301 if (mangled
== NULL
|| *mangled
!= '_')
1305 string_append (decl
, "\"");
1309 const char *endptr
= dlang_hexdigit (mangled
, &val
);
1314 /* Sanitize white and non-printable characters. */
1318 string_append (decl
, " ");
1321 string_append (decl
, "\\t");
1324 string_append (decl
, "\\n");
1327 string_append (decl
, "\\r");
1330 string_append (decl
, "\\f");
1333 string_append (decl
, "\\v");
1338 string_appendn (decl
, &val
, 1);
1341 string_append (decl
, "\\x");
1342 string_appendn (decl
, mangled
, 2);
1348 string_append (decl
, "\"");
1351 string_appendn (decl
, &type
, 1);
1356 /* Extract the static array value from MANGLED and append it to DECL.
1357 Return the remaining string on success or NULL on failure. */
1359 dlang_parse_arrayliteral (string
*decl
, const char *mangled
)
1363 mangled
= dlang_number (mangled
, &elements
);
1364 if (mangled
== NULL
)
1367 string_append (decl
, "[");
1370 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1371 if (mangled
== NULL
)
1375 string_append (decl
, ", ");
1378 string_append (decl
, "]");
1382 /* Extract the associative array value from MANGLED and append it to DECL.
1383 Return the remaining string on success or NULL on failure. */
1385 dlang_parse_assocarray (string
*decl
, const char *mangled
)
1389 mangled
= dlang_number (mangled
, &elements
);
1390 if (mangled
== NULL
)
1393 string_append (decl
, "[");
1396 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1397 if (mangled
== NULL
)
1400 string_append (decl
, ":");
1401 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1402 if (mangled
== NULL
)
1406 string_append (decl
, ", ");
1409 string_append (decl
, "]");
1413 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1414 Return the remaining string on success or NULL on failure. */
1416 dlang_parse_structlit (string
*decl
, const char *mangled
, const char *name
)
1420 mangled
= dlang_number (mangled
, &args
);
1421 if (mangled
== NULL
)
1425 string_append (decl
, name
);
1427 string_append (decl
, "(");
1430 mangled
= dlang_value (decl
, mangled
, NULL
, '\0');
1431 if (mangled
== NULL
)
1435 string_append (decl
, ", ");
1438 string_append (decl
, ")");
1442 /* Extract the value from MANGLED and append it to DECL.
1443 Return the remaining string on success or NULL on failure. */
1445 dlang_value (string
*decl
, const char *mangled
, const char *name
, char type
)
1447 if (mangled
== NULL
|| *mangled
== '\0')
1455 string_append (decl
, "null");
1458 /* Integral values. */
1461 string_append (decl
, "-");
1462 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1469 /* There really should always be an `i' before encoded numbers, but there
1470 wasn't in early versions of D2, so this case range must remain for
1471 backwards compatibility. */
1472 case '0': case '1': case '2': case '3': case '4':
1473 case '5': case '6': case '7': case '8': case '9':
1474 mangled
= dlang_parse_integer (decl
, mangled
, type
);
1480 mangled
= dlang_parse_real (decl
, mangled
);
1483 /* Complex value. */
1486 mangled
= dlang_parse_real (decl
, mangled
);
1487 string_append (decl
, "+");
1488 if (mangled
== NULL
|| *mangled
!= 'c')
1491 mangled
= dlang_parse_real (decl
, mangled
);
1492 string_append (decl
, "i");
1495 /* String values. */
1496 case 'a': /* UTF8 */
1497 case 'w': /* UTF16 */
1498 case 'd': /* UTF32 */
1499 mangled
= dlang_parse_string (decl
, mangled
);
1506 mangled
= dlang_parse_assocarray (decl
, mangled
);
1508 mangled
= dlang_parse_arrayliteral (decl
, mangled
);
1511 /* Struct values. */
1514 mangled
= dlang_parse_structlit (decl
, mangled
, name
);
1524 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1525 Returns the remaining signature on success or NULL on failure. */
1527 dlang_parse_mangle (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1529 /* A D mangled symbol is comprised of both scope and type information.
1532 _D QualifiedName Type
1535 The caller should have guaranteed that the start pointer is at the
1537 Note that type is never a function type, but only the return type of
1538 a function or the type of a variable.
1542 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 1);
1544 if (mangled
!= NULL
)
1546 /* Artificial symbols end with 'Z' and have no type. */
1547 if (*mangled
== 'Z')
1551 /* Discard the declaration or return type. */
1554 string_init (&type
);
1555 mangled
= dlang_type (&type
, mangled
, info
);
1556 string_delete (&type
);
1563 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1564 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1565 Returns the remaining signature on success or NULL on failure. */
1567 dlang_parse_qualified (string
*decl
, const char *mangled
,
1568 struct dlang_info
*info
, int suffix_modifiers
)
1570 /* Qualified names are identifiers separated by their encoded length.
1571 Nested functions also encode their argument types without specifying
1576 SymbolFunctionName QualifiedName
1581 SymbolName TypeFunctionNoReturn
1582 SymbolName M TypeFunctionNoReturn
1583 SymbolName M TypeModifiers TypeFunctionNoReturn
1585 The start pointer should be at the above location.
1591 string_append (decl
, ".");
1593 /* Skip over anonymous symbols. */
1594 while (*mangled
== '0')
1597 mangled
= dlang_identifier (decl
, mangled
, info
);
1599 /* Consume the encoded arguments. However if this is not followed by the
1600 next encoded length or mangle type, then this is not a continuation of
1601 a qualified name, in which case we backtrack and return the current
1602 unconsumed position of the mangled decl. */
1603 if (mangled
&& (*mangled
== 'M' || dlang_call_convention_p (mangled
)))
1606 const char *start
= mangled
;
1607 int saved
= string_length (decl
);
1609 /* Save the type modifiers for appending at the end if needed. */
1610 string_init (&mods
);
1612 /* Skip over 'this' parameter and type modifiers. */
1613 if (*mangled
== 'M')
1616 mangled
= dlang_type_modifiers (&mods
, mangled
);
1617 string_setlength (decl
, saved
);
1620 mangled
= dlang_function_type_noreturn (decl
, NULL
, NULL
,
1622 if (suffix_modifiers
)
1623 string_appendn (decl
, mods
.b
, string_length (&mods
));
1625 if (mangled
== NULL
|| *mangled
== '\0')
1627 /* Did not match the rule we were looking for. */
1629 string_setlength (decl
, saved
);
1632 string_delete (&mods
);
1635 while (mangled
&& dlang_symbol_name_p (mangled
, info
));
1640 /* Demangle the tuple from MANGLED and append it to DECL.
1641 Return the remaining string on success or NULL on failure. */
1643 dlang_parse_tuple (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1647 mangled
= dlang_number (mangled
, &elements
);
1648 if (mangled
== NULL
)
1651 string_append (decl
, "Tuple!(");
1655 mangled
= dlang_type (decl
, mangled
, info
);
1656 if (mangled
== NULL
)
1660 string_append (decl
, ", ");
1663 string_append (decl
, ")");
1667 /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1668 Return the remaining string on success or NULL on failure. */
1670 dlang_template_symbol_param (string
*decl
, const char *mangled
,
1671 struct dlang_info
*info
)
1673 if (strncmp (mangled
, "_D", 2) == 0
1674 && dlang_symbol_name_p (mangled
+ 2, info
))
1675 return dlang_parse_mangle (decl
, mangled
, info
);
1677 if (*mangled
== 'Q')
1678 return dlang_parse_qualified (decl
, mangled
, info
, 0);
1681 const char *endptr
= dlang_number (mangled
, &len
);
1683 if (endptr
== NULL
|| len
== 0)
1686 /* In template parameter symbols generated by the frontend up to 2.076,
1687 the symbol length is encoded and the first character of the mangled
1688 name can be a digit. This causes ambiguity issues because the digits
1689 of the two numbers are adjacent. */
1692 int saved
= string_length (decl
);
1694 /* Work backwards until a match is found. */
1695 for (pend
= endptr
; endptr
!= NULL
; pend
--)
1699 /* Reached the beginning of the pointer to the name length,
1700 try parsing the entire symbol. */
1708 /* Check whether template parameter is a function with a valid
1709 return type or an untyped identifier. */
1710 if (dlang_symbol_name_p (mangled
, info
))
1711 mangled
= dlang_parse_qualified (decl
, mangled
, info
, 0);
1712 else if (strncmp (mangled
, "_D", 2) == 0
1713 && dlang_symbol_name_p (mangled
+ 2, info
))
1714 mangled
= dlang_parse_mangle (decl
, mangled
, info
);
1716 /* Check for name length mismatch. */
1717 if (mangled
&& (endptr
== NULL
|| (mangled
- pend
) == psize
))
1721 string_setlength (decl
, saved
);
1724 /* No match on any combinations. */
1728 /* Demangle the argument list from MANGLED and append it to DECL.
1729 Return the remaining string on success or NULL on failure. */
1731 dlang_template_args (string
*decl
, const char *mangled
, struct dlang_info
*info
)
1735 while (mangled
&& *mangled
!= '\0')
1739 case 'Z': /* End of parameter list. */
1745 string_append (decl
, ", ");
1747 /* Skip over specialised template prefix. */
1748 if (*mangled
== 'H')
1753 case 'S': /* Symbol parameter. */
1755 mangled
= dlang_template_symbol_param (decl
, mangled
, info
);
1757 case 'T': /* Type parameter. */
1759 mangled
= dlang_type (decl
, mangled
, info
);
1761 case 'V': /* Value parameter. */
1766 /* Peek at the type. */
1772 /* Value type is a back reference, peek at the real type. */
1773 const char *backref
;
1774 if (dlang_backref (mangled
, &backref
, info
) == NULL
)
1780 /* In the few instances where the type is actually desired in
1781 the output, it should precede the value from dlang_value. */
1782 string_init (&name
);
1783 mangled
= dlang_type (&name
, mangled
, info
);
1784 string_need (&name
, 1);
1787 mangled
= dlang_value (decl
, mangled
, name
.b
, type
);
1788 string_delete (&name
);
1791 case 'X': /* Externally mangled parameter. */
1797 endptr
= dlang_number (mangled
, &len
);
1798 if (endptr
== NULL
|| strlen (endptr
) < (size_t) len
)
1801 string_appendn (decl
, endptr
, len
);
1802 mangled
= endptr
+ len
;
1813 /* Extract and demangle the template symbol in MANGLED, expected to
1814 be made up of LEN characters (-1 if unknown), and append it to DECL.
1815 Returns the remaining signature on success or NULL on failure. */
1817 dlang_parse_template (string
*decl
, const char *mangled
,
1818 struct dlang_info
*info
, long len
)
1820 const char *start
= mangled
;
1823 /* Template instance names have the types and values of its parameters
1826 TemplateInstanceName:
1827 Number __T LName TemplateArgs Z
1828 Number __U LName TemplateArgs Z
1830 The start pointer should be at the above location, and LEN should be
1831 the value of the decoded number.
1834 /* Template symbol. */
1835 if (!dlang_symbol_name_p (mangled
+ 3, info
) || mangled
[3] == '0')
1840 /* Template identifier. */
1841 mangled
= dlang_identifier (decl
, mangled
, info
);
1843 /* Template arguments. */
1844 string_init (&args
);
1845 mangled
= dlang_template_args (&args
, mangled
, info
);
1847 string_append (decl
, "!(");
1848 string_appendn (decl
, args
.b
, string_length (&args
));
1849 string_append (decl
, ")");
1851 string_delete (&args
);
1853 /* Check for template name length mismatch. */
1854 if (len
!= TEMPLATE_LENGTH_UNKNOWN
&& mangled
&& (mangled
- start
) != len
)
1860 /* Initialize the information structure we use to pass around information. */
1862 dlang_demangle_init_info (const char *mangled
, int last_backref
,
1863 struct dlang_info
*info
)
1866 info
->last_backref
= last_backref
;
1869 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1870 signature on success or NULL on failure. */
1873 dlang_demangle (const char *mangled
, int option ATTRIBUTE_UNUSED
)
1876 char *demangled
= NULL
;
1878 if (mangled
== NULL
|| *mangled
== '\0')
1881 if (strncmp (mangled
, "_D", 2) != 0)
1884 string_init (&decl
);
1886 if (strcmp (mangled
, "_Dmain") == 0)
1888 string_append (&decl
, "D main");
1892 struct dlang_info info
;
1894 dlang_demangle_init_info (mangled
, strlen (mangled
), &info
);
1895 mangled
= dlang_parse_mangle (&decl
, mangled
, &info
);
1897 /* Check that the entire symbol was successfully demangled. */
1898 if (mangled
== NULL
|| *mangled
!= '\0')
1899 string_delete (&decl
);
1902 if (string_length (&decl
) > 0)
1904 string_need (&decl
, 1);
This page took 0.093068 seconds and 4 git commands to generate.