mc_translate.c: enable further uses of DLexpensive for scalar EQ/NE comparisons
[valgrind.git] / coregrind / m_demangle / d-demangle.c
blobf9a7f1df8d35d009e5b4a42f9f3e0024ff8d7824
1 /* Demangler for the D programming language
2 Copyright (C) 2014-2017 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
18 combined executable.)
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Library General Public License for more details.
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>. */
29 /* This file exports one function; dlang_demangle.
31 This file imports strtol for decoding mangled literals. */
33 #if 0 /* in valgrind */
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 #endif /* ! in valgrind */
39 #if 0 /* in valgrind */
40 #include "safe-ctype.h"
41 #endif /* ! in valgrind */
43 #if 0 /* in valgrind */
44 #include <sys/types.h>
45 #include <string.h>
46 #include <stdio.h>
47 #endif /* ! in valgrind */
49 #if 0 /* in valgrind */
50 #ifdef HAVE_STDLIB_H
51 #include <stdlib.h>
52 #else
53 extern long strtol (const char *nptr, char **endptr, int base);
54 #endif
55 #endif /* ! in valgrind */
57 #if 0 /* in valgrind */
58 #include <demangle.h>
59 #include "libiberty.h"
60 #endif /* ! in valgrind */
62 #include "vg_libciface.h"
64 #include "ansidecl.h"
65 #include "demangle.h"
66 #include "safe-ctype.h"
68 /* A mini string-handling package */
70 typedef struct string /* Beware: these aren't required to be */
71 { /* '\0' terminated. */
72 char *b; /* pointer to start of string */
73 char *p; /* pointer after last character */
74 char *e; /* pointer after end of allocated space */
75 } string;
77 static void
78 string_need (string *s, int n)
80 int tem;
82 if (s->b == NULL)
84 if (n < 32)
86 n = 32;
88 s->p = s->b = XNEWVEC (char, n);
89 s->e = s->b + n;
91 else if (s->e - s->p < n)
93 tem = s->p - s->b;
94 n += tem;
95 n *= 2;
96 s->b = XRESIZEVEC (char, s->b, n);
97 s->p = s->b + tem;
98 s->e = s->b + n;
102 static void
103 string_delete (string *s)
105 if (s->b != NULL)
107 XDELETEVEC (s->b);
108 s->b = s->e = s->p = NULL;
112 static void
113 string_init (string *s)
115 s->b = s->p = s->e = NULL;
118 static int
119 string_length (string *s)
121 if (s->p == s->b)
123 return 0;
125 return s->p - s->b;
128 static void
129 string_setlength (string *s, int n)
131 if (n - string_length (s) < 0)
133 s->p = s->b + n;
137 static void
138 string_append (string *p, const char *s)
140 int n = strlen (s);
141 string_need (p, n);
142 memcpy (p->p, s, n);
143 p->p += n;
146 static void
147 string_appendn (string *p, const char *s, int n)
149 if (n != 0)
151 string_need (p, n);
152 memcpy (p->p, s, n);
153 p->p += n;
157 static void
158 string_prependn (string *p, const char *s, int n)
160 char *q;
162 if (n != 0)
164 string_need (p, n);
165 for (q = p->p - 1; q >= p->b; q--)
167 q[n] = q[0];
169 memcpy (p->b, s, n);
170 p->p += n;
174 static void
175 string_prepend (string *p, const char *s)
177 if (s != NULL && *s != '\0')
179 string_prependn (p, s, strlen (s));
183 /* What kinds of symbol we could be parsing. */
184 enum dlang_symbol_kinds
186 /* Top-level symbol, needs it's type checked. */
187 dlang_top_level,
188 /* Function symbol, needs it's type checked. */
189 dlang_function,
190 /* Strongly typed name, such as for classes, structs and enums. */
191 dlang_type_name,
192 /* Template identifier. */
193 dlang_template_ident,
194 /* Template symbol parameter. */
195 dlang_template_param
198 /* Prototypes for forward referenced functions */
199 static const char *dlang_function_args (string *, const char *);
201 static const char *dlang_type (string *, const char *);
203 static const char *dlang_value (string *, const char *, const char *, char);
205 static const char *dlang_parse_symbol (string *, const char *,
206 enum dlang_symbol_kinds);
208 static const char *dlang_parse_tuple (string *, const char *);
210 static const char *dlang_parse_template (string *, const char *, long);
213 /* Demangle the calling convention from MANGLED and append it to DECL.
214 Return the remaining string on success or NULL on failure. */
215 static const char *
216 dlang_call_convention (string *decl, const char *mangled)
218 if (mangled == NULL || *mangled == '\0')
219 return NULL;
221 switch (*mangled)
223 case 'F': /* (D) */
224 mangled++;
225 break;
226 case 'U': /* (C) */
227 mangled++;
228 string_append (decl, "extern(C) ");
229 break;
230 case 'W': /* (Windows) */
231 mangled++;
232 string_append (decl, "extern(Windows) ");
233 break;
234 case 'V': /* (Pascal) */
235 mangled++;
236 string_append (decl, "extern(Pascal) ");
237 break;
238 case 'R': /* (C++) */
239 mangled++;
240 string_append (decl, "extern(C++) ");
241 break;
242 case 'Y': /* (Objective-C) */
243 mangled++;
244 string_append (decl, "extern(Objective-C) ");
245 break;
246 default:
247 return NULL;
250 return mangled;
253 /* Extract the type modifiers from MANGLED and append them to DECL.
254 Returns the remaining signature on success or NULL on failure. */
255 static const char *
256 dlang_type_modifiers (string *decl, const char *mangled)
258 if (mangled == NULL || *mangled == '\0')
259 return NULL;
261 switch (*mangled)
263 case 'x': /* const */
264 mangled++;
265 string_append (decl, " const");
266 return mangled;
267 case 'y': /* immutable */
268 mangled++;
269 string_append (decl, " immutable");
270 return mangled;
271 case 'O': /* shared */
272 mangled++;
273 string_append (decl, " shared");
274 return dlang_type_modifiers (decl, mangled);
275 case 'N':
276 mangled++;
277 if (*mangled == 'g') /* wild */
279 mangled++;
280 string_append (decl, " inout");
281 return dlang_type_modifiers (decl, mangled);
283 else
284 return NULL;
286 default:
287 return mangled;
291 /* Demangle the D function attributes from MANGLED and append it to DECL.
292 Return the remaining string on success or NULL on failure. */
293 static const char *
294 dlang_attributes (string *decl, const char *mangled)
296 if (mangled == NULL || *mangled == '\0')
297 return NULL;
299 while (*mangled == 'N')
301 mangled++;
302 switch (*mangled)
304 case 'a': /* pure */
305 mangled++;
306 string_append (decl, "pure ");
307 continue;
308 case 'b': /* nothrow */
309 mangled++;
310 string_append (decl, "nothrow ");
311 continue;
312 case 'c': /* ref */
313 mangled++;
314 string_append (decl, "ref ");
315 continue;
316 case 'd': /* @property */
317 mangled++;
318 string_append (decl, "@property ");
319 continue;
320 case 'e': /* @trusted */
321 mangled++;
322 string_append (decl, "@trusted ");
323 continue;
324 case 'f': /* @safe */
325 mangled++;
326 string_append (decl, "@safe ");
327 continue;
328 case 'g':
329 case 'h':
330 case 'k':
331 /* inout parameter is represented as 'Ng'.
332 vector parameter is represented as 'Nh'.
333 return paramenter is represented as 'Nk'.
334 If we see this, then we know we're really in the
335 parameter list. Rewind and break. */
336 mangled--;
337 break;
338 case 'i': /* @nogc */
339 mangled++;
340 string_append (decl, "@nogc ");
341 continue;
342 case 'j': /* return */
343 mangled++;
344 string_append (decl, "return ");
345 continue;
347 default: /* unknown attribute */
348 return NULL;
350 break;
353 return mangled;
356 /* Demangle the function type from MANGLED and append it to DECL.
357 Return the remaining string on success or NULL on failure. */
358 static const char *
359 dlang_function_type (string *decl, const char *mangled)
361 string attr, args, type;
362 size_t szattr, szargs, sztype;
364 if (mangled == NULL || *mangled == '\0')
365 return NULL;
367 /* The order of the mangled string is:
368 CallConvention FuncAttrs Arguments ArgClose Type
370 The demangled string is re-ordered as:
371 CallConvention Type Arguments FuncAttrs
373 string_init (&attr);
374 string_init (&args);
375 string_init (&type);
377 /* Function call convention. */
378 mangled = dlang_call_convention (decl, mangled);
380 /* Function attributes. */
381 mangled = dlang_attributes (&attr, mangled);
382 szattr = string_length (&attr);
384 /* Function arguments. */
385 mangled = dlang_function_args (&args, mangled);
386 szargs = string_length (&args);
388 /* Function return type. */
389 mangled = dlang_type (&type, mangled);
390 sztype = string_length (&type);
392 /* Append to decl in order. */
393 string_appendn (decl, type.b, sztype);
394 string_append (decl, "(");
395 string_appendn (decl, args.b, szargs);
396 string_append (decl, ") ");
397 string_appendn (decl, attr.b, szattr);
399 string_delete (&attr);
400 string_delete (&args);
401 string_delete (&type);
402 return mangled;
405 /* Demangle the argument list from MANGLED and append it to DECL.
406 Return the remaining string on success or NULL on failure. */
407 static const char *
408 dlang_function_args (string *decl, const char *mangled)
410 size_t n = 0;
412 while (mangled && *mangled != '\0')
414 switch (*mangled)
416 case 'X': /* (variadic T t...) style. */
417 mangled++;
418 string_append (decl, "...");
419 return mangled;
420 case 'Y': /* (variadic T t, ...) style. */
421 mangled++;
422 if (n != 0)
423 string_append (decl, ", ");
424 string_append (decl, "...");
425 return mangled;
426 case 'Z': /* Normal function. */
427 mangled++;
428 return mangled;
431 if (n++)
432 string_append (decl, ", ");
434 if (*mangled == 'M') /* scope(T) */
436 mangled++;
437 string_append (decl, "scope ");
440 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
442 mangled += 2;
443 string_append (decl, "return ");
446 switch (*mangled)
448 case 'J': /* out(T) */
449 mangled++;
450 string_append (decl, "out ");
451 break;
452 case 'K': /* ref(T) */
453 mangled++;
454 string_append (decl, "ref ");
455 break;
456 case 'L': /* lazy(T) */
457 mangled++;
458 string_append (decl, "lazy ");
459 break;
461 mangled = dlang_type (decl, mangled);
464 return mangled;
467 /* Demangle the type from MANGLED and append it to DECL.
468 Return the remaining string on success or NULL on failure. */
469 static const char *
470 dlang_type (string *decl, const char *mangled)
472 if (mangled == NULL || *mangled == '\0')
473 return NULL;
475 switch (*mangled)
477 case 'O': /* shared(T) */
478 mangled++;
479 string_append (decl, "shared(");
480 mangled = dlang_type (decl, mangled);
481 string_append (decl, ")");
482 return mangled;
483 case 'x': /* const(T) */
484 mangled++;
485 string_append (decl, "const(");
486 mangled = dlang_type (decl, mangled);
487 string_append (decl, ")");
488 return mangled;
489 case 'y': /* immutable(T) */
490 mangled++;
491 string_append (decl, "immutable(");
492 mangled = dlang_type (decl, mangled);
493 string_append (decl, ")");
494 return mangled;
495 case 'N':
496 mangled++;
497 if (*mangled == 'g') /* wild(T) */
499 mangled++;
500 string_append (decl, "inout(");
501 mangled = dlang_type (decl, mangled);
502 string_append (decl, ")");
503 return mangled;
505 else if (*mangled == 'h') /* vector(T) */
507 mangled++;
508 string_append (decl, "__vector(");
509 mangled = dlang_type (decl, mangled);
510 string_append (decl, ")");
511 return mangled;
513 else
514 return NULL;
515 case 'A': /* dynamic array (T[]) */
516 mangled++;
517 mangled = dlang_type (decl, mangled);
518 string_append (decl, "[]");
519 return mangled;
520 case 'G': /* static array (T[N]) */
522 const char *numptr;
523 size_t num = 0;
524 mangled++;
526 numptr = mangled;
527 while (ISDIGIT (*mangled))
529 num++;
530 mangled++;
532 mangled = dlang_type (decl, mangled);
533 string_append (decl, "[");
534 string_appendn (decl, numptr, num);
535 string_append (decl, "]");
536 return mangled;
538 case 'H': /* associative array (T[T]) */
540 string type;
541 size_t sztype;
542 mangled++;
544 string_init (&type);
545 mangled = dlang_type (&type, mangled);
546 sztype = string_length (&type);
548 mangled = dlang_type (decl, mangled);
549 string_append (decl, "[");
550 string_appendn (decl, type.b, sztype);
551 string_append (decl, "]");
553 string_delete (&type);
554 return mangled;
556 case 'P': /* pointer (T*) */
557 mangled++;
558 /* Function pointer types don't include the trailing asterisk. */
559 switch (*mangled)
561 case 'F': case 'U': case 'W':
562 case 'V': case 'R': case 'Y':
563 mangled = dlang_function_type (decl, mangled);
564 string_append (decl, "function");
565 return mangled;
567 mangled = dlang_type (decl, mangled);
568 string_append (decl, "*");
569 return mangled;
570 case 'I': /* ident T */
571 case 'C': /* class T */
572 case 'S': /* struct T */
573 case 'E': /* enum T */
574 case 'T': /* typedef T */
575 mangled++;
576 return dlang_parse_symbol (decl, mangled, dlang_type_name);
577 case 'D': /* delegate T */
579 string mods;
580 size_t szmods;
581 mangled++;
583 string_init (&mods);
584 mangled = dlang_type_modifiers (&mods, mangled);
585 szmods = string_length (&mods);
587 mangled = dlang_function_type (decl, mangled);
588 string_append (decl, "delegate");
589 string_appendn (decl, mods.b, szmods);
591 string_delete (&mods);
592 return mangled;
594 case 'B': /* tuple T */
595 mangled++;
596 return dlang_parse_tuple (decl, mangled);
598 /* Basic types */
599 case 'n':
600 mangled++;
601 string_append (decl, "none");
602 return mangled;
603 case 'v':
604 mangled++;
605 string_append (decl, "void");
606 return mangled;
607 case 'g':
608 mangled++;
609 string_append (decl, "byte");
610 return mangled;
611 case 'h':
612 mangled++;
613 string_append (decl, "ubyte");
614 return mangled;
615 case 's':
616 mangled++;
617 string_append (decl, "short");
618 return mangled;
619 case 't':
620 mangled++;
621 string_append (decl, "ushort");
622 return mangled;
623 case 'i':
624 mangled++;
625 string_append (decl, "int");
626 return mangled;
627 case 'k':
628 mangled++;
629 string_append (decl, "uint");
630 return mangled;
631 case 'l':
632 mangled++;
633 string_append (decl, "long");
634 return mangled;
635 case 'm':
636 mangled++;
637 string_append (decl, "ulong");
638 return mangled;
639 case 'f':
640 mangled++;
641 string_append (decl, "float");
642 return mangled;
643 case 'd':
644 mangled++;
645 string_append (decl, "double");
646 return mangled;
647 case 'e':
648 mangled++;
649 string_append (decl, "real");
650 return mangled;
652 /* Imaginary and Complex types */
653 case 'o':
654 mangled++;
655 string_append (decl, "ifloat");
656 return mangled;
657 case 'p':
658 mangled++;
659 string_append (decl, "idouble");
660 return mangled;
661 case 'j':
662 mangled++;
663 string_append (decl, "ireal");
664 return mangled;
665 case 'q':
666 mangled++;
667 string_append (decl, "cfloat");
668 return mangled;
669 case 'r':
670 mangled++;
671 string_append (decl, "cdouble");
672 return mangled;
673 case 'c':
674 mangled++;
675 string_append (decl, "creal");
676 return mangled;
678 /* Other types */
679 case 'b':
680 mangled++;
681 string_append (decl, "bool");
682 return mangled;
683 case 'a':
684 mangled++;
685 string_append (decl, "char");
686 return mangled;
687 case 'u':
688 mangled++;
689 string_append (decl, "wchar");
690 return mangled;
691 case 'w':
692 mangled++;
693 string_append (decl, "dchar");
694 return mangled;
695 case 'z':
696 mangled++;
697 switch (*mangled)
699 case 'i':
700 mangled++;
701 string_append (decl, "cent");
702 return mangled;
703 case 'k':
704 mangled++;
705 string_append (decl, "ucent");
706 return mangled;
708 return NULL;
710 default: /* unhandled */
711 return NULL;
715 /* Extract the identifier from MANGLED and append it to DECL.
716 Return the remaining string on success or NULL on failure. */
717 static const char *
718 dlang_identifier (string *decl, const char *mangled,
719 enum dlang_symbol_kinds kind)
721 char *endptr;
722 long len;
724 if (mangled == NULL || *mangled == '\0')
725 return NULL;
727 len = strtol (mangled, &endptr, 10);
729 if (endptr == NULL || len <= 0)
730 return NULL;
732 /* In template parameter symbols, the first character of the mangled
733 name can be a digit. This causes ambiguity issues because the
734 digits of the two numbers are adjacent. */
735 if (kind == dlang_template_param)
737 long psize = len;
738 char *pend;
739 int saved = string_length (decl);
741 /* Work backwards until a match is found. */
742 for (pend = endptr; endptr != NULL; pend--)
744 mangled = pend;
746 /* Reached the beginning of the pointer to the name length,
747 try parsing the entire symbol. */
748 if (psize == 0)
750 psize = len;
751 pend = endptr;
752 endptr = NULL;
755 /* Check whether template parameter is a function with a valid
756 return type or an untyped identifier. */
757 if (ISDIGIT (*mangled))
758 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
759 else if (strncmp (mangled, "_D", 2) == 0)
761 mangled += 2;
762 mangled = dlang_parse_symbol (decl, mangled, dlang_function);
765 /* Check for name length mismatch. */
766 if (mangled && (mangled - pend) == psize)
767 return mangled;
769 psize /= 10;
770 string_setlength (decl, saved);
773 /* No match on any combinations. */
774 return NULL;
776 else
778 if (strlen (endptr) < (size_t) len)
779 return NULL;
781 mangled = endptr;
783 /* May be a template instance. */
784 if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
786 /* Template symbol. */
787 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
788 return dlang_parse_template (decl, mangled, len);
790 return NULL;
793 switch (len)
795 case 6:
796 if (strncmp (mangled, "__ctor", len) == 0)
798 /* Constructor symbol for a class/struct. */
799 string_append (decl, "this");
800 mangled += len;
801 return mangled;
803 else if (strncmp (mangled, "__dtor", len) == 0)
805 /* Destructor symbol for a class/struct. */
806 string_append (decl, "~this");
807 mangled += len;
808 return mangled;
810 else if (strncmp (mangled, "__initZ", len+1) == 0)
812 /* The static initialiser for a given symbol. */
813 string_append (decl, "init$");
814 mangled += len;
815 return mangled;
817 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
819 /* The vtable symbol for a given class. */
820 string_prepend (decl, "vtable for ");
821 string_setlength (decl, string_length (decl) - 1);
822 mangled += len;
823 return mangled;
825 break;
827 case 7:
828 if (strncmp (mangled, "__ClassZ", len+1) == 0)
830 /* The classinfo symbol for a given class. */
831 string_prepend (decl, "ClassInfo for ");
832 string_setlength (decl, string_length (decl) - 1);
833 mangled += len;
834 return mangled;
836 break;
838 case 10:
839 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
841 /* Postblit symbol for a struct. */
842 string_append (decl, "this(this)");
843 mangled += len + 3;
844 return mangled;
846 break;
848 case 11:
849 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
851 /* The interface symbol for a given class. */
852 string_prepend (decl, "Interface for ");
853 string_setlength (decl, string_length (decl) - 1);
854 mangled += len;
855 return mangled;
857 break;
859 case 12:
860 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
862 /* The ModuleInfo symbol for a given module. */
863 string_prepend (decl, "ModuleInfo for ");
864 string_setlength (decl, string_length (decl) - 1);
865 mangled += len;
866 return mangled;
868 break;
871 string_appendn (decl, mangled, len);
872 mangled += len;
875 return mangled;
878 /* Extract the integer value from MANGLED and append it to DECL,
879 where TYPE is the type it should be represented as.
880 Return the remaining string on success or NULL on failure. */
881 static const char *
882 dlang_parse_integer (string *decl, const char *mangled, char type)
884 if (type == 'a' || type == 'u' || type == 'w')
886 /* Parse character value. */
887 char value[10];
888 int pos = 10;
889 int width = 0;
890 char *endptr;
891 long val = strtol (mangled, &endptr, 10);
893 if (endptr == NULL || val < 0)
894 return NULL;
896 string_append (decl, "'");
898 if (type == 'a' && val >= 0x20 && val < 0x7F)
900 /* Represent as a character literal. */
901 char c = (char) val;
902 string_appendn (decl, &c, 1);
904 else
906 /* Represent as a hexadecimal value. */
907 switch (type)
909 case 'a': /* char */
910 string_append (decl, "\\x");
911 width = 2;
912 break;
913 case 'u': /* wchar */
914 string_append (decl, "\\u");
915 width = 4;
916 break;
917 case 'w': /* dchar */
918 string_append (decl, "\\U");
919 width = 8;
920 break;
923 while (val > 0)
925 int digit = val % 16;
927 if (digit < 10)
928 value[--pos] = (char)(digit + '0');
929 else
930 value[--pos] = (char)((digit - 10) + 'a');
932 val /= 16;
933 width--;
936 for (; width > 0; width--)
937 value[--pos] = '0';
939 string_appendn (decl, &(value[pos]), 10 - pos);
941 string_append (decl, "'");
942 mangled = endptr;
944 else if (type == 'b')
946 /* Parse boolean value. */
947 char *endptr;
948 long val = strtol (mangled, &endptr, 10);
950 if (endptr == NULL || val < 0)
951 return NULL;
953 string_append (decl, val ? "true" : "false");
954 mangled = endptr;
956 else
958 /* Parse integer value. */
959 const char *numptr = mangled;
960 size_t num = 0;
962 while (ISDIGIT (*mangled))
964 num++;
965 mangled++;
967 string_appendn (decl, numptr, num);
969 /* Append suffix. */
970 switch (type)
972 case 'h': /* ubyte */
973 case 't': /* ushort */
974 case 'k': /* uint */
975 string_append (decl, "u");
976 break;
977 case 'l': /* long */
978 string_append (decl, "L");
979 break;
980 case 'm': /* ulong */
981 string_append (decl, "uL");
982 break;
986 return mangled;
989 /* Extract the floating-point value from MANGLED and append it to DECL.
990 Return the remaining string on success or NULL on failure. */
991 static const char *
992 dlang_parse_real (string *decl, const char *mangled)
994 char buffer[64];
995 int len = 0;
997 /* Handle NAN and +-INF. */
998 if (strncmp (mangled, "NAN", 3) == 0)
1000 string_append (decl, "NaN");
1001 mangled += 3;
1002 return mangled;
1004 else if (strncmp (mangled, "INF", 3) == 0)
1006 string_append (decl, "Inf");
1007 mangled += 3;
1008 return mangled;
1010 else if (strncmp (mangled, "NINF", 4) == 0)
1012 string_append (decl, "-Inf");
1013 mangled += 4;
1014 return mangled;
1017 /* Hexadecimal prefix and leading bit. */
1018 if (*mangled == 'N')
1020 buffer[len++] = '-';
1021 mangled++;
1024 if (!ISXDIGIT (*mangled))
1025 return NULL;
1027 buffer[len++] = '0';
1028 buffer[len++] = 'x';
1029 buffer[len++] = *mangled;
1030 buffer[len++] = '.';
1031 mangled++;
1033 /* Significand. */
1034 while (ISXDIGIT (*mangled))
1036 buffer[len++] = *mangled;
1037 mangled++;
1040 /* Exponent. */
1041 if (*mangled != 'P')
1042 return NULL;
1044 buffer[len++] = 'p';
1045 mangled++;
1047 if (*mangled == 'N')
1049 buffer[len++] = '-';
1050 mangled++;
1053 while (ISDIGIT (*mangled))
1055 buffer[len++] = *mangled;
1056 mangled++;
1059 /* Write out the demangled hexadecimal, rather than trying to
1060 convert the buffer into a floating-point value. */
1061 buffer[len] = '\0';
1062 len = strlen (buffer);
1063 string_appendn (decl, buffer, len);
1064 return mangled;
1067 /* Convert VAL from an ascii hexdigit to value. */
1068 static char
1069 ascii2hex (char val)
1071 if (val >= 'a' && val <= 'f')
1072 return (val - 'a' + 10);
1074 if (val >= 'A' && val <= 'F')
1075 return (val - 'A' + 10);
1077 if (val >= '0' && val <= '9')
1078 return (val - '0');
1080 return 0;
1083 /* Extract the string value from MANGLED and append it to DECL.
1084 Return the remaining string on success or NULL on failure. */
1085 static const char *
1086 dlang_parse_string (string *decl, const char *mangled)
1088 char type = *mangled;
1089 char *endptr;
1090 long len;
1092 mangled++;
1093 len = strtol (mangled, &endptr, 10);
1095 if (endptr == NULL || len < 0)
1096 return NULL;
1098 mangled = endptr;
1099 if (*mangled != '_')
1100 return NULL;
1102 mangled++;
1103 string_append (decl, "\"");
1104 while (len--)
1106 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1108 char a = ascii2hex (mangled[0]);
1109 char b = ascii2hex (mangled[1]);
1110 char val = (a << 4) | b;
1112 /* Sanitize white and non-printable characters. */
1113 switch (val)
1115 case ' ':
1116 string_append (decl, " ");
1117 break;
1118 case '\t':
1119 string_append (decl, "\\t");
1120 break;
1121 case '\n':
1122 string_append (decl, "\\n");
1123 break;
1124 case '\r':
1125 string_append (decl, "\\r");
1126 break;
1127 case '\f':
1128 string_append (decl, "\\f");
1129 break;
1130 case '\v':
1131 string_append (decl, "\\v");
1132 break;
1134 default:
1135 if (ISPRINT (val))
1136 string_appendn (decl, &val, 1);
1137 else
1139 string_append (decl, "\\x");
1140 string_appendn (decl, mangled, 2);
1144 else
1145 return NULL;
1147 mangled += 2;
1149 string_append (decl, "\"");
1151 if (type != 'a')
1152 string_appendn (decl, &type, 1);
1154 return mangled;
1157 /* Extract the static array value from MANGLED and append it to DECL.
1158 Return the remaining string on success or NULL on failure. */
1159 static const char *
1160 dlang_parse_arrayliteral (string *decl, const char *mangled)
1162 char *endptr;
1163 long elements = strtol (mangled, &endptr, 10);
1165 if (endptr == NULL || elements < 0)
1166 return NULL;
1168 mangled = endptr;
1169 string_append (decl, "[");
1170 while (elements--)
1172 mangled = dlang_value (decl, mangled, NULL, '\0');
1173 if (elements != 0)
1174 string_append (decl, ", ");
1177 string_append (decl, "]");
1178 return mangled;
1181 /* Extract the associative array value from MANGLED and append it to DECL.
1182 Return the remaining string on success or NULL on failure. */
1183 static const char *
1184 dlang_parse_assocarray (string *decl, const char *mangled)
1186 char *endptr;
1187 long elements = strtol (mangled, &endptr, 10);
1189 if (endptr == NULL || elements < 0)
1190 return NULL;
1192 mangled = endptr;
1193 string_append (decl, "[");
1194 while (elements--)
1196 mangled = dlang_value (decl, mangled, NULL, '\0');
1197 string_append (decl, ":");
1198 mangled = dlang_value (decl, mangled, NULL, '\0');
1200 if (elements != 0)
1201 string_append (decl, ", ");
1204 string_append (decl, "]");
1205 return mangled;
1208 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1209 Return the remaining string on success or NULL on failure. */
1210 static const char *
1211 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1213 char *endptr;
1214 long args = strtol (mangled, &endptr, 10);
1216 if (endptr == NULL || args < 0)
1217 return NULL;
1219 mangled = endptr;
1220 if (name != NULL)
1221 string_append (decl, name);
1223 string_append (decl, "(");
1224 while (args--)
1226 mangled = dlang_value (decl, mangled, NULL, '\0');
1227 if (args != 0)
1228 string_append (decl, ", ");
1231 string_append (decl, ")");
1232 return mangled;
1235 /* Extract the value from MANGLED and append it to DECL.
1236 Return the remaining string on success or NULL on failure. */
1237 static const char *
1238 dlang_value (string *decl, const char *mangled, const char *name, char type)
1240 if (mangled == NULL || *mangled == '\0')
1241 return NULL;
1243 switch (*mangled)
1245 /* Null value. */
1246 case 'n':
1247 mangled++;
1248 string_append (decl, "null");
1249 break;
1251 /* Integral values. */
1252 case 'N':
1253 mangled++;
1254 string_append (decl, "-");
1255 mangled = dlang_parse_integer (decl, mangled, type);
1256 break;
1258 case 'i':
1259 mangled++;
1260 if (*mangled < '0' || *mangled > '9')
1261 return NULL;
1262 /* Fall through */
1263 case '0': case '1': case '2': case '3': case '4':
1264 case '5': case '6': case '7': case '8': case '9':
1265 mangled = dlang_parse_integer (decl, mangled, type);
1266 break;
1268 /* Real value. */
1269 case 'e':
1270 mangled++;
1271 mangled = dlang_parse_real (decl, mangled);
1272 break;
1274 /* Complex value. */
1275 case 'c':
1276 mangled++;
1277 mangled = dlang_parse_real (decl, mangled);
1278 string_append (decl, "+");
1279 if (mangled == NULL || *mangled != 'c')
1280 return NULL;
1281 mangled++;
1282 mangled = dlang_parse_real (decl, mangled);
1283 string_append (decl, "i");
1284 break;
1286 /* String values. */
1287 case 'a': /* UTF8 */
1288 case 'w': /* UTF16 */
1289 case 'd': /* UTF32 */
1290 mangled = dlang_parse_string (decl, mangled);
1291 break;
1293 /* Array values. */
1294 case 'A':
1295 mangled++;
1296 if (type == 'H')
1297 mangled = dlang_parse_assocarray (decl, mangled);
1298 else
1299 mangled = dlang_parse_arrayliteral (decl, mangled);
1300 break;
1302 /* Struct values. */
1303 case 'S':
1304 mangled++;
1305 mangled = dlang_parse_structlit (decl, mangled, name);
1306 break;
1308 default:
1309 return NULL;
1312 return mangled;
1315 /* Extract the type modifiers from MANGLED and return the string
1316 length that it consumes in MANGLED on success or 0 on failure. */
1317 static int
1318 dlang_type_modifier_p (const char *mangled)
1320 int i;
1322 switch (*mangled)
1324 case 'x': case 'y':
1325 return 1;
1327 case 'O':
1328 mangled++;
1329 i = dlang_type_modifier_p (mangled);
1330 return i + 1;
1332 case 'N':
1333 mangled++;
1334 if (*mangled == 'g')
1336 mangled++;
1337 i = dlang_type_modifier_p (mangled);
1338 return i + 2;
1342 return 0;
1345 /* Extract the function calling convention from MANGLED and
1346 return 1 on success or 0 on failure. */
1347 static int
1348 dlang_call_convention_p (const char *mangled)
1350 /* Prefix for functions needing 'this' */
1351 if (*mangled == 'M')
1353 mangled++;
1354 /* Also skip over any type modifiers. */
1355 mangled += dlang_type_modifier_p (mangled);
1358 switch (*mangled)
1360 case 'F': case 'U': case 'V':
1361 case 'W': case 'R': case 'Y':
1362 return 1;
1364 default:
1365 return 0;
1369 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1370 Returns the remaining signature on success or NULL on failure. */
1371 static const char *
1372 dlang_parse_symbol (string *decl, const char *mangled,
1373 enum dlang_symbol_kinds kind)
1375 int saved;
1376 size_t n = 0;
1379 if (n++)
1380 string_append (decl, ".");
1382 mangled = dlang_identifier (decl, mangled, kind);
1384 if (mangled && dlang_call_convention_p (mangled))
1386 string mods;
1387 const char *start = NULL;
1388 int checkpoint = 0;
1390 /* Skip over 'this' parameter. */
1391 if (*mangled == 'M')
1392 mangled++;
1394 /* We have reached here because we expect an extern(Pascal) function.
1395 However this is so rare, that it is more likely a template value
1396 parameter. Since this can't be assumed, first attempt parsing
1397 the symbol as a function, and then back out on failure. */
1398 if (*mangled == 'V')
1400 start = mangled;
1401 checkpoint = string_length (decl);
1404 /* Save the type modifiers for appending at the end. */
1405 string_init (&mods);
1406 mangled = dlang_type_modifiers (&mods, mangled);
1408 /* Skip over calling convention and attributes in qualified name. */
1409 saved = string_length (decl);
1410 mangled = dlang_call_convention (decl, mangled);
1411 mangled = dlang_attributes (decl, mangled);
1412 string_setlength (decl, saved);
1414 string_append (decl, "(");
1415 mangled = dlang_function_args (decl, mangled);
1416 string_append (decl, ")");
1418 /* Add any const/immutable/shared modifier. */
1419 string_appendn (decl, mods.b, string_length (&mods));
1420 string_delete (&mods);
1422 if (mangled == NULL && checkpoint != 0)
1424 mangled = start;
1425 string_setlength (decl, checkpoint);
1429 while (mangled && ISDIGIT (*mangled));
1431 /* Only top-level symbols or function template parameters have
1432 a type that needs checking. */
1433 if (kind == dlang_top_level || kind == dlang_function)
1435 /* Artificial symbols end with 'Z' and have no type. */
1436 if (mangled && *mangled == 'Z')
1437 mangled++;
1438 else
1440 saved = string_length (decl);
1441 mangled = dlang_type (decl, mangled);
1442 string_setlength (decl, saved);
1445 /* Check that the entire symbol was successfully demangled. */
1446 if (kind == dlang_top_level)
1448 if (mangled == NULL || *mangled != '\0')
1449 return NULL;
1453 return mangled;
1456 /* Demangle the tuple from MANGLED and append it to DECL.
1457 Return the remaining string on success or NULL on failure. */
1458 static const char *
1459 dlang_parse_tuple (string *decl, const char *mangled)
1461 char *endptr;
1462 long elements = strtol (mangled, &endptr, 10);
1464 if (endptr == NULL || elements < 0)
1465 return NULL;
1467 mangled = endptr;
1468 string_append (decl, "Tuple!(");
1470 while (elements--)
1472 mangled = dlang_type (decl, mangled);
1473 if (elements != 0)
1474 string_append (decl, ", ");
1477 string_append (decl, ")");
1478 return mangled;
1481 /* Demangle the argument list from MANGLED and append it to DECL.
1482 Return the remaining string on success or NULL on failure. */
1483 static const char *
1484 dlang_template_args (string *decl, const char *mangled)
1486 size_t n = 0;
1488 while (mangled && *mangled != '\0')
1490 switch (*mangled)
1492 case 'Z': /* End of parameter list. */
1493 mangled++;
1494 return mangled;
1497 if (n++)
1498 string_append (decl, ", ");
1500 /* Skip over specialised template prefix. */
1501 if (*mangled == 'H')
1502 mangled++;
1504 switch (*mangled)
1506 case 'S': /* Symbol parameter. */
1507 mangled++;
1508 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
1509 break;
1510 case 'T': /* Type parameter. */
1511 mangled++;
1512 mangled = dlang_type (decl, mangled);
1513 break;
1514 case 'V': /* Value parameter. */
1516 string name;
1517 char type;
1519 /* Peek at the type. */
1520 mangled++;
1521 type = *mangled;
1523 /* In the few instances where the type is actually desired in
1524 the output, it should precede the value from dlang_value. */
1525 string_init (&name);
1526 mangled = dlang_type (&name, mangled);
1527 string_need (&name, 1);
1528 *(name.p) = '\0';
1530 mangled = dlang_value (decl, mangled, name.b, type);
1531 string_delete (&name);
1532 break;
1535 default:
1536 return NULL;
1540 return mangled;
1543 /* Extract and demangle the template symbol in MANGLED, expected to
1544 be made up of LEN characters, and append it to DECL.
1545 Returns the remaining signature on success or NULL on failure. */
1546 static const char *
1547 dlang_parse_template (string *decl, const char *mangled, long len)
1549 const char *start = mangled;
1551 /* Template instance names have the types and values of its parameters
1552 encoded into it.
1554 TemplateInstanceName:
1555 Number __T LName TemplateArgs Z
1557 The start pointer should be at the above location, and LEN should be
1558 the value of the decoded number.
1560 if (strncmp (mangled, "__T", 3) != 0)
1561 return NULL;
1563 mangled += 3;
1565 /* Template identifier. */
1566 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1568 /* Template arguments. */
1569 string_append (decl, "!(");
1570 mangled = dlang_template_args (decl, mangled);
1571 string_append (decl, ")");
1573 /* Check for template name length mismatch. */
1574 if (mangled && (mangled - start) != len)
1575 return NULL;
1577 return mangled;
1580 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1581 signature on success or NULL on failure. */
1583 char *
1584 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1586 string decl;
1587 char *demangled = NULL;
1589 if (mangled == NULL || *mangled == '\0')
1590 return NULL;
1592 if (strncmp (mangled, "_D", 2) != 0)
1593 return NULL;
1595 string_init (&decl);
1597 if (strcmp (mangled, "_Dmain") == 0)
1599 string_append (&decl, "D main");
1601 else
1603 mangled += 2;
1605 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
1606 string_delete (&decl);
1609 if (string_length (&decl) > 0)
1611 string_need (&decl, 1);
1612 *(decl.p) = '\0';
1613 demangled = decl.b;
1616 return demangled;