2015-05-18 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / libiberty / d-demangle.c
bloba2a3b32af6a91a9be7eed56a511ca714314645ac
1 /* Demangler for the D programming language
2 Copyright 2014, 2015 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 and strtod for decoding mangled literals. */
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include "safe-ctype.h"
39 #include <sys/types.h>
40 #include <string.h>
41 #include <stdio.h>
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #else
46 extern long strtol (const char *nptr, char **endptr, int base);
47 extern double strtod (const char *nptr, char **endptr);
48 #endif
50 #include <demangle.h>
51 #include "libiberty.h"
53 /* A mini string-handling package */
55 typedef struct string /* Beware: these aren't required to be */
56 { /* '\0' terminated. */
57 char *b; /* pointer to start of string */
58 char *p; /* pointer after last character */
59 char *e; /* pointer after end of allocated space */
60 } string;
62 static void
63 string_need (string *s, int n)
65 int tem;
67 if (s->b == NULL)
69 if (n < 32)
71 n = 32;
73 s->p = s->b = XNEWVEC (char, n);
74 s->e = s->b + n;
76 else if (s->e - s->p < n)
78 tem = s->p - s->b;
79 n += tem;
80 n *= 2;
81 s->b = XRESIZEVEC (char, s->b, n);
82 s->p = s->b + tem;
83 s->e = s->b + n;
87 static void
88 string_delete (string *s)
90 if (s->b != NULL)
92 XDELETEVEC (s->b);
93 s->b = s->e = s->p = NULL;
97 static void
98 string_init (string *s)
100 s->b = s->p = s->e = NULL;
103 static int
104 string_length (string *s)
106 if (s->p == s->b)
108 return 0;
110 return s->p - s->b;
113 static void
114 string_setlength (string *s, int n)
116 if (n - string_length (s) < 0)
118 s->p = s->b + n;
122 static void
123 string_append (string *p, const char *s)
125 int n = strlen (s);
126 string_need (p, n);
127 memcpy (p->p, s, n);
128 p->p += n;
131 static void
132 string_appendn (string *p, const char *s, int n)
134 if (n != 0)
136 string_need (p, n);
137 memcpy (p->p, s, n);
138 p->p += n;
142 static void
143 string_prependn (string *p, const char *s, int n)
145 char *q;
147 if (n != 0)
149 string_need (p, n);
150 for (q = p->p - 1; q >= p->b; q--)
152 q[n] = q[0];
154 memcpy (p->b, s, n);
155 p->p += n;
159 static void
160 string_prepend (string *p, const char *s)
162 if (s != NULL && *s != '\0')
164 string_prependn (p, s, strlen (s));
168 /* What kinds of symbol we could be parsing. */
169 enum dlang_symbol_kinds
171 /* Top-level symbol, needs it's type checked. */
172 dlang_top_level,
173 /* Function symbol, needs it's type checked. */
174 dlang_function,
175 /* Strongly typed name, such as for classes, structs and enums. */
176 dlang_type_name,
177 /* Template identifier. */
178 dlang_template_ident,
179 /* Template symbol parameter. */
180 dlang_template_param
183 /* Prototypes for forward referenced functions */
184 static const char *dlang_function_args (string *, const char *);
186 static const char *dlang_type (string *, const char *);
188 static const char *dlang_value (string *, const char *, const char *, char);
190 static const char *dlang_parse_symbol (string *, const char *,
191 enum dlang_symbol_kinds);
193 static const char *dlang_parse_tuple (string *, const char *);
195 static const char *dlang_parse_template (string *, const char *, long);
198 /* Demangle the calling convention from MANGLED and append it to DECL.
199 Return the remaining string on success or NULL on failure. */
200 static const char *
201 dlang_call_convention (string *decl, const char *mangled)
203 if (mangled == NULL || *mangled == '\0')
204 return NULL;
206 switch (*mangled)
208 case 'F': /* (D) */
209 mangled++;
210 break;
211 case 'U': /* (C) */
212 mangled++;
213 string_append (decl, "extern(C) ");
214 break;
215 case 'W': /* (Windows) */
216 mangled++;
217 string_append (decl, "extern(Windows) ");
218 break;
219 case 'V': /* (Pascal) */
220 mangled++;
221 string_append (decl, "extern(Pascal) ");
222 break;
223 case 'R': /* (C++) */
224 mangled++;
225 string_append (decl, "extern(C++) ");
226 break;
227 default:
228 return NULL;
231 return mangled;
234 /* Extract the type modifiers from MANGLED and append them to DECL.
235 Returns the remaining signature on success or NULL on failure. */
236 static const char *
237 dlang_type_modifiers (string *decl, const char *mangled)
239 if (mangled == NULL || *mangled == '\0')
240 return NULL;
242 switch (*mangled)
244 case 'x': /* const */
245 mangled++;
246 string_append (decl, " const");
247 return mangled;
248 case 'y': /* immutable */
249 mangled++;
250 string_append (decl, " immutable");
251 return mangled;
252 case 'O': /* shared */
253 mangled++;
254 string_append (decl, " shared");
255 return dlang_type_modifiers (decl, mangled);
256 case 'N':
257 mangled++;
258 if (*mangled == 'g') /* wild */
260 mangled++;
261 string_append (decl, " inout");
262 return dlang_type_modifiers (decl, mangled);
264 else
265 return NULL;
267 default:
268 return mangled;
272 /* Demangle the D function attributes from MANGLED and append it to DECL.
273 Return the remaining string on success or NULL on failure. */
274 static const char *
275 dlang_attributes (string *decl, const char *mangled)
277 if (mangled == NULL || *mangled == '\0')
278 return NULL;
280 while (*mangled == 'N')
282 mangled++;
283 switch (*mangled)
285 case 'a': /* pure */
286 mangled++;
287 string_append (decl, "pure ");
288 continue;
289 case 'b': /* nothrow */
290 mangled++;
291 string_append (decl, "nothrow ");
292 continue;
293 case 'c': /* ref */
294 mangled++;
295 string_append (decl, "ref ");
296 continue;
297 case 'd': /* @property */
298 mangled++;
299 string_append (decl, "@property ");
300 continue;
301 case 'e': /* @trusted */
302 mangled++;
303 string_append (decl, "@trusted ");
304 continue;
305 case 'f': /* @safe */
306 mangled++;
307 string_append (decl, "@safe ");
308 continue;
309 case 'g':
310 case 'h':
311 case 'k':
312 /* inout parameter is represented as 'Ng'.
313 vector parameter is represented as 'Nh'.
314 return paramenter is represented as 'Nk'.
315 If we see this, then we know we're really in the
316 parameter list. Rewind and break. */
317 mangled--;
318 break;
319 case 'i': /* @nogc */
320 mangled++;
321 string_append (decl, "@nogc ");
322 continue;
323 case 'j': /* return */
324 mangled++;
325 string_append (decl, "return ");
326 continue;
328 default: /* unknown attribute */
329 return NULL;
331 break;
334 return mangled;
337 /* Demangle the function type from MANGLED and append it to DECL.
338 Return the remaining string on success or NULL on failure. */
339 static const char *
340 dlang_function_type (string *decl, const char *mangled)
342 string attr, args, type;
343 size_t szattr, szargs, sztype;
345 if (mangled == NULL || *mangled == '\0')
346 return NULL;
348 /* The order of the mangled string is:
349 CallConvention FuncAttrs Arguments ArgClose Type
351 The demangled string is re-ordered as:
352 CallConvention Type Arguments FuncAttrs
354 string_init (&attr);
355 string_init (&args);
356 string_init (&type);
358 /* Function call convention. */
359 mangled = dlang_call_convention (decl, mangled);
361 /* Function attributes. */
362 mangled = dlang_attributes (&attr, mangled);
363 szattr = string_length (&attr);
365 /* Function arguments. */
366 mangled = dlang_function_args (&args, mangled);
367 szargs = string_length (&args);
369 /* Function return type. */
370 mangled = dlang_type (&type, mangled);
371 sztype = string_length (&type);
373 /* Append to decl in order. */
374 string_appendn (decl, type.b, sztype);
375 string_append (decl, "(");
376 string_appendn (decl, args.b, szargs);
377 string_append (decl, ") ");
378 string_appendn (decl, attr.b, szattr);
380 string_delete (&attr);
381 string_delete (&args);
382 string_delete (&type);
383 return mangled;
386 /* Demangle the argument list from MANGLED and append it to DECL.
387 Return the remaining string on success or NULL on failure. */
388 static const char *
389 dlang_function_args (string *decl, const char *mangled)
391 size_t n = 0;
393 while (mangled && *mangled != '\0')
395 switch (*mangled)
397 case 'X': /* (variadic T t...) style. */
398 mangled++;
399 string_append (decl, "...");
400 return mangled;
401 case 'Y': /* (variadic T t, ...) style. */
402 mangled++;
403 string_append (decl, ", ...");
404 return mangled;
405 case 'Z': /* Normal function. */
406 mangled++;
407 return mangled;
410 if (n++)
411 string_append (decl, ", ");
413 if (*mangled == 'M') /* scope(T) */
415 mangled++;
416 string_append (decl, "scope ");
419 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
421 mangled += 2;
422 string_append (decl, "return ");
425 switch (*mangled)
427 case 'J': /* out(T) */
428 mangled++;
429 string_append (decl, "out ");
430 break;
431 case 'K': /* ref(T) */
432 mangled++;
433 string_append (decl, "ref ");
434 break;
435 case 'L': /* lazy(T) */
436 mangled++;
437 string_append (decl, "lazy ");
438 break;
440 mangled = dlang_type (decl, mangled);
443 return mangled;
446 /* Demangle the type from MANGLED and append it to DECL.
447 Return the remaining string on success or NULL on failure. */
448 static const char *
449 dlang_type (string *decl, const char *mangled)
451 if (mangled == NULL || *mangled == '\0')
452 return NULL;
454 switch (*mangled)
456 case 'O': /* shared(T) */
457 mangled++;
458 string_append (decl, "shared(");
459 mangled = dlang_type (decl, mangled);
460 string_append (decl, ")");
461 return mangled;
462 case 'x': /* const(T) */
463 mangled++;
464 string_append (decl, "const(");
465 mangled = dlang_type (decl, mangled);
466 string_append (decl, ")");
467 return mangled;
468 case 'y': /* immutable(T) */
469 mangled++;
470 string_append (decl, "immutable(");
471 mangled = dlang_type (decl, mangled);
472 string_append (decl, ")");
473 return mangled;
474 case 'N':
475 mangled++;
476 if (*mangled == 'g') /* wild(T) */
478 mangled++;
479 string_append (decl, "inout(");
480 mangled = dlang_type (decl, mangled);
481 string_append (decl, ")");
482 return mangled;
484 else if (*mangled == 'h') /* vector(T) */
486 mangled++;
487 string_append (decl, "__vector(");
488 mangled = dlang_type (decl, mangled);
489 string_append (decl, ")");
490 return mangled;
492 else
493 return NULL;
494 case 'A': /* dynamic array (T[]) */
495 mangled++;
496 mangled = dlang_type (decl, mangled);
497 string_append (decl, "[]");
498 return mangled;
499 case 'G': /* static array (T[N]) */
501 const char *numptr;
502 size_t num = 0;
503 mangled++;
505 numptr = mangled;
506 while (ISDIGIT (*mangled))
508 num++;
509 mangled++;
511 mangled = dlang_type (decl, mangled);
512 string_append (decl, "[");
513 string_appendn (decl, numptr, num);
514 string_append (decl, "]");
515 return mangled;
517 case 'H': /* associative array (T[T]) */
519 string type;
520 size_t sztype;
521 mangled++;
523 string_init (&type);
524 mangled = dlang_type (&type, mangled);
525 sztype = string_length (&type);
527 mangled = dlang_type (decl, mangled);
528 string_append (decl, "[");
529 string_appendn (decl, type.b, sztype);
530 string_append (decl, "]");
532 string_delete (&type);
533 return mangled;
535 case 'P': /* pointer (T*) */
536 mangled++;
537 mangled = dlang_type (decl, mangled);
538 string_append (decl, "*");
539 return mangled;
540 case 'I': /* ident T */
541 case 'C': /* class T */
542 case 'S': /* struct T */
543 case 'E': /* enum T */
544 case 'T': /* typedef T */
545 mangled++;
546 return dlang_parse_symbol (decl, mangled, dlang_type_name);
547 case 'D': /* delegate T */
549 string mods;
550 size_t szmods;
551 mangled++;
553 string_init (&mods);
554 mangled = dlang_type_modifiers (&mods, mangled);
555 szmods = string_length (&mods);
557 mangled = dlang_function_type (decl, mangled);
558 string_append (decl, "delegate");
559 string_appendn (decl, mods.b, szmods);
561 string_delete (&mods);
562 return mangled;
564 case 'B': /* tuple T */
565 mangled++;
566 return dlang_parse_tuple (decl, mangled);
568 /* Function types */
569 case 'F': case 'U': case 'W':
570 case 'V': case 'R':
571 mangled = dlang_function_type (decl, mangled);
572 string_append (decl, "function");
573 return mangled;
575 /* Basic types */
576 case 'n':
577 mangled++;
578 string_append (decl, "none");
579 return mangled;
580 case 'v':
581 mangled++;
582 string_append (decl, "void");
583 return mangled;
584 case 'g':
585 mangled++;
586 string_append (decl, "byte");
587 return mangled;
588 case 'h':
589 mangled++;
590 string_append (decl, "ubyte");
591 return mangled;
592 case 's':
593 mangled++;
594 string_append (decl, "short");
595 return mangled;
596 case 't':
597 mangled++;
598 string_append (decl, "ushort");
599 return mangled;
600 case 'i':
601 mangled++;
602 string_append (decl, "int");
603 return mangled;
604 case 'k':
605 mangled++;
606 string_append (decl, "uint");
607 return mangled;
608 case 'l':
609 mangled++;
610 string_append (decl, "long");
611 return mangled;
612 case 'm':
613 mangled++;
614 string_append (decl, "ulong");
615 return mangled;
616 case 'f':
617 mangled++;
618 string_append (decl, "float");
619 return mangled;
620 case 'd':
621 mangled++;
622 string_append (decl, "double");
623 return mangled;
624 case 'e':
625 mangled++;
626 string_append (decl, "real");
627 return mangled;
629 /* Imaginary and Complex types */
630 case 'o':
631 mangled++;
632 string_append (decl, "ifloat");
633 return mangled;
634 case 'p':
635 mangled++;
636 string_append (decl, "idouble");
637 return mangled;
638 case 'j':
639 mangled++;
640 string_append (decl, "ireal");
641 return mangled;
642 case 'q':
643 mangled++;
644 string_append (decl, "cfloat");
645 return mangled;
646 case 'r':
647 mangled++;
648 string_append (decl, "cdouble");
649 return mangled;
650 case 'c':
651 mangled++;
652 string_append (decl, "creal");
653 return mangled;
655 /* Other types */
656 case 'b':
657 mangled++;
658 string_append (decl, "bool");
659 return mangled;
660 case 'a':
661 mangled++;
662 string_append (decl, "char");
663 return mangled;
664 case 'u':
665 mangled++;
666 string_append (decl, "wchar");
667 return mangled;
668 case 'w':
669 mangled++;
670 string_append (decl, "dchar");
671 return mangled;
672 case 'z':
673 mangled++;
674 switch (*mangled)
676 case 'i':
677 mangled++;
678 string_append (decl, "cent");
679 return mangled;
680 case 'k':
681 mangled++;
682 string_append (decl, "ucent");
683 return mangled;
685 return NULL;
687 default: /* unhandled */
688 return NULL;
692 /* Extract the identifier from MANGLED and append it to DECL.
693 Return the remaining string on success or NULL on failure. */
694 static const char *
695 dlang_identifier (string *decl, const char *mangled,
696 enum dlang_symbol_kinds kind)
698 char *endptr;
699 long len;
701 if (mangled == NULL || *mangled == '\0')
702 return NULL;
704 len = strtol (mangled, &endptr, 10);
706 if (endptr == NULL || len <= 0)
707 return NULL;
709 /* In template parameter symbols, the first character of the mangled
710 name can be a digit. This causes ambiguity issues because the
711 digits of the two numbers are adjacent. */
712 if (kind == dlang_template_param)
714 long psize = len;
715 char *pend;
716 int saved = string_length (decl);
718 /* Work backwards until a match is found. */
719 for (pend = endptr; endptr != NULL; pend--)
721 mangled = pend;
723 /* Reached the beginning of the pointer to the name length,
724 try parsing the entire symbol. */
725 if (psize == 0)
727 psize = len;
728 pend = endptr;
729 endptr = NULL;
732 /* Check whether template parameter is a function with a valid
733 return type or an untyped identifier. */
734 if (ISDIGIT (*mangled))
735 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
736 else if (strncmp (mangled, "_D", 2) == 0)
738 mangled += 2;
739 mangled = dlang_parse_symbol (decl, mangled, dlang_function);
742 /* Check for name length mismatch. */
743 if (mangled && (mangled - pend) == psize)
744 return mangled;
746 psize /= 10;
747 string_setlength (decl, saved);
750 /* No match on any combinations. */
751 return NULL;
753 else
755 if (strlen (endptr) < (size_t) len)
756 return NULL;
758 mangled = endptr;
760 /* May be a template instance. */
761 if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
763 /* Template symbol. */
764 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
765 return dlang_parse_template (decl, mangled, len);
767 return NULL;
770 switch (len)
772 case 6:
773 if (strncmp (mangled, "__ctor", len) == 0)
775 /* Constructor symbol for a class/struct. */
776 string_append (decl, "this");
777 mangled += len;
778 return mangled;
780 else if (strncmp (mangled, "__dtor", len) == 0)
782 /* Destructor symbol for a class/struct. */
783 string_append (decl, "~this");
784 mangled += len;
785 return mangled;
787 else if (strncmp (mangled, "__initZ", len+1) == 0)
789 /* The static initialiser for a given symbol. */
790 string_append (decl, "init$");
791 mangled += len;
792 return mangled;
794 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
796 /* The vtable symbol for a given class. */
797 string_prepend (decl, "vtable for ");
798 string_setlength (decl, string_length (decl) - 1);
799 mangled += len;
800 return mangled;
802 break;
804 case 7:
805 if (strncmp (mangled, "__ClassZ", len+1) == 0)
807 /* The classinfo symbol for a given class. */
808 string_prepend (decl, "ClassInfo for ");
809 string_setlength (decl, string_length (decl) - 1);
810 mangled += len;
811 return mangled;
813 break;
815 case 10:
816 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
818 /* Postblit symbol for a struct. */
819 string_append (decl, "this(this)");
820 mangled += len + 3;
821 return mangled;
823 break;
825 case 11:
826 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
828 /* The interface symbol for a given class. */
829 string_prepend (decl, "Interface for ");
830 string_setlength (decl, string_length (decl) - 1);
831 mangled += len;
832 return mangled;
834 break;
836 case 12:
837 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
839 /* The ModuleInfo symbol for a given module. */
840 string_prepend (decl, "ModuleInfo for ");
841 string_setlength (decl, string_length (decl) - 1);
842 mangled += len;
843 return mangled;
845 break;
848 string_appendn (decl, mangled, len);
849 mangled += len;
852 return mangled;
855 /* Extract the integer value from MANGLED and append it to DECL,
856 where TYPE is the type it should be represented as.
857 Return the remaining string on success or NULL on failure. */
858 static const char *
859 dlang_parse_integer (string *decl, const char *mangled, char type)
861 if (type == 'a' || type == 'u' || type == 'w')
863 /* Parse character value. */
864 char value[10];
865 int pos = 10;
866 int width = 0;
867 char *endptr;
868 long val = strtol (mangled, &endptr, 10);
870 if (endptr == NULL || val < 0)
871 return NULL;
873 string_append (decl, "'");
875 if (type == 'a' && val >= 0x20 && val < 0x7F)
877 /* Represent as a character literal. */
878 char c = (char) val;
879 string_appendn (decl, &c, 1);
881 else
883 /* Represent as a hexadecimal value. */
884 switch (type)
886 case 'a': /* char */
887 string_append (decl, "\\x");
888 width = 2;
889 break;
890 case 'u': /* wchar */
891 string_append (decl, "\\u");
892 width = 4;
893 break;
894 case 'w': /* dchar */
895 string_append (decl, "\\U");
896 width = 8;
897 break;
900 while (val > 0)
902 int digit = val % 16;
904 if (digit < 10)
905 value[--pos] = (char)(digit + '0');
906 else
907 value[--pos] = (char)((digit - 10) + 'a');
909 val /= 16;
910 width--;
913 for (; width > 0; width--)
914 value[--pos] = '0';
916 string_appendn (decl, &(value[pos]), 10 - pos);
918 string_append (decl, "'");
919 mangled = endptr;
921 else if (type == 'b')
923 /* Parse boolean value. */
924 char *endptr;
925 long val = strtol (mangled, &endptr, 10);
927 if (endptr == NULL || val < 0)
928 return NULL;
930 string_append (decl, val ? "true" : "false");
931 mangled = endptr;
933 else
935 /* Parse integer value. */
936 const char *numptr = mangled;
937 size_t num = 0;
939 while (ISDIGIT (*mangled))
941 num++;
942 mangled++;
944 string_appendn (decl, numptr, num);
946 /* Append suffix. */
947 switch (type)
949 case 'h': /* ubyte */
950 case 't': /* ushort */
951 case 'k': /* uint */
952 string_append (decl, "u");
953 break;
954 case 'l': /* long */
955 string_append (decl, "L");
956 break;
957 case 'm': /* ulong */
958 string_append (decl, "uL");
959 break;
963 return mangled;
966 /* Extract the floating-point value from MANGLED and append it to DECL.
967 Return the remaining string on success or NULL on failure. */
968 static const char *
969 dlang_parse_real (string *decl, const char *mangled)
971 char buffer[64];
972 int len = 0;
973 double value;
974 char *endptr;
976 /* Handle NAN and +-INF. */
977 if (strncmp (mangled, "NAN", 3) == 0)
979 string_append (decl, "NaN");
980 mangled += 3;
981 return mangled;
983 else if (strncmp (mangled, "INF", 3) == 0)
985 string_append (decl, "Inf");
986 mangled += 3;
987 return mangled;
989 else if (strncmp (mangled, "NINF", 4) == 0)
991 string_append (decl, "-Inf");
992 mangled += 4;
993 return mangled;
996 /* Hexadecimal prefix and leading bit. */
997 if (*mangled == 'N')
999 buffer[len++] = '-';
1000 mangled++;
1003 if (!ISXDIGIT (*mangled))
1004 return NULL;
1006 buffer[len++] = '0';
1007 buffer[len++] = 'x';
1008 buffer[len++] = *mangled;
1009 buffer[len++] = '.';
1010 mangled++;
1012 /* Significand. */
1013 while (ISXDIGIT (*mangled))
1015 buffer[len++] = *mangled;
1016 mangled++;
1019 /* Exponent. */
1020 if (*mangled != 'P')
1021 return NULL;
1023 buffer[len++] = 'p';
1024 mangled++;
1026 if (*mangled == 'N')
1028 buffer[len++] = '-';
1029 mangled++;
1032 while (ISDIGIT (*mangled))
1034 buffer[len++] = *mangled;
1035 mangled++;
1038 /* Convert buffer from hexadecimal to floating-point. */
1039 buffer[len] = '\0';
1040 value = strtod (buffer, &endptr);
1042 if (endptr == NULL || endptr != (buffer + len))
1043 return NULL;
1045 len = snprintf (buffer, sizeof(buffer), "%#g", value);
1046 string_appendn (decl, buffer, len);
1047 return mangled;
1050 /* Convert VAL from an ascii hexdigit to value. */
1051 static char
1052 ascii2hex (char val)
1054 if (val >= 'a' && val <= 'f')
1055 return (val - 'a' + 10);
1057 if (val >= 'A' && val <= 'F')
1058 return (val - 'A' + 10);
1060 if (val >= '0' && val <= '9')
1061 return (val - '0');
1063 return 0;
1066 /* Extract the string value from MANGLED and append it to DECL.
1067 Return the remaining string on success or NULL on failure. */
1068 static const char *
1069 dlang_parse_string (string *decl, const char *mangled)
1071 char type = *mangled;
1072 char *endptr;
1073 long len;
1075 mangled++;
1076 len = strtol (mangled, &endptr, 10);
1078 if (endptr == NULL || len < 0)
1079 return NULL;
1081 mangled = endptr;
1082 if (*mangled != '_')
1083 return NULL;
1085 mangled++;
1086 string_append (decl, "\"");
1087 while (len--)
1089 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1091 char a = ascii2hex (mangled[0]);
1092 char b = ascii2hex (mangled[1]);
1093 char val = (a << 4) | b;
1095 /* Sanitize white and non-printable characters. */
1096 switch (val)
1098 case ' ':
1099 string_append (decl, " ");
1100 break;
1101 case '\t':
1102 string_append (decl, "\\t");
1103 break;
1104 case '\n':
1105 string_append (decl, "\\n");
1106 break;
1107 case '\r':
1108 string_append (decl, "\\r");
1109 break;
1110 case '\f':
1111 string_append (decl, "\\f");
1112 break;
1113 case '\v':
1114 string_append (decl, "\\v");
1115 break;
1117 default:
1118 if (ISPRINT (val))
1119 string_appendn (decl, &val, 1);
1120 else
1122 string_append (decl, "\\x");
1123 string_appendn (decl, mangled, 2);
1127 else
1128 return NULL;
1130 mangled += 2;
1132 string_append (decl, "\"");
1134 if (type != 'a')
1135 string_appendn (decl, &type, 1);
1137 return mangled;
1140 /* Extract the static array value from MANGLED and append it to DECL.
1141 Return the remaining string on success or NULL on failure. */
1142 static const char *
1143 dlang_parse_arrayliteral (string *decl, const char *mangled)
1145 char *endptr;
1146 long elements = strtol (mangled, &endptr, 10);
1148 if (endptr == NULL || elements < 0)
1149 return NULL;
1151 mangled = endptr;
1152 string_append (decl, "[");
1153 while (elements--)
1155 mangled = dlang_value (decl, mangled, NULL, '\0');
1156 if (elements != 0)
1157 string_append (decl, ", ");
1160 string_append (decl, "]");
1161 return mangled;
1164 /* Extract the associative array value from MANGLED and append it to DECL.
1165 Return the remaining string on success or NULL on failure. */
1166 static const char *
1167 dlang_parse_assocarray (string *decl, const char *mangled)
1169 char *endptr;
1170 long elements = strtol (mangled, &endptr, 10);
1172 if (endptr == NULL || elements < 0)
1173 return NULL;
1175 mangled = endptr;
1176 string_append (decl, "[");
1177 while (elements--)
1179 mangled = dlang_value (decl, mangled, NULL, '\0');
1180 string_append (decl, ":");
1181 mangled = dlang_value (decl, mangled, NULL, '\0');
1183 if (elements != 0)
1184 string_append (decl, ", ");
1187 string_append (decl, "]");
1188 return mangled;
1191 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1192 Return the remaining string on success or NULL on failure. */
1193 static const char *
1194 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1196 char *endptr;
1197 long args = strtol (mangled, &endptr, 10);
1199 if (endptr == NULL || args < 0)
1200 return NULL;
1202 mangled = endptr;
1203 if (name != NULL)
1204 string_append (decl, name);
1206 string_append (decl, "(");
1207 while (args--)
1209 mangled = dlang_value (decl, mangled, NULL, '\0');
1210 if (args != 0)
1211 string_append (decl, ", ");
1214 string_append (decl, ")");
1215 return mangled;
1218 /* Extract the value from MANGLED and append it to DECL.
1219 Return the remaining string on success or NULL on failure. */
1220 static const char *
1221 dlang_value (string *decl, const char *mangled, const char *name, char type)
1223 if (mangled == NULL || *mangled == '\0')
1224 return NULL;
1226 switch (*mangled)
1228 /* Null value. */
1229 case 'n':
1230 mangled++;
1231 string_append (decl, "null");
1232 break;
1234 /* Integral values. */
1235 case 'N':
1236 mangled++;
1237 string_append (decl, "-");
1238 mangled = dlang_parse_integer (decl, mangled, type);
1239 break;
1241 case 'i':
1242 mangled++;
1243 if (*mangled < '0' || *mangled > '9')
1244 return NULL;
1245 /* Fall through */
1246 case '0': case '1': case '2': case '3': case '4':
1247 case '5': case '6': case '7': case '8': case '9':
1248 mangled = dlang_parse_integer (decl, mangled, type);
1249 break;
1251 /* Real value. */
1252 case 'e':
1253 mangled++;
1254 mangled = dlang_parse_real (decl, mangled);
1255 break;
1257 /* Complex value. */
1258 case 'c':
1259 mangled++;
1260 mangled = dlang_parse_real (decl, mangled);
1261 string_append (decl, "+");
1262 if (mangled == NULL || *mangled != 'c')
1263 return NULL;
1264 mangled++;
1265 mangled = dlang_parse_real (decl, mangled);
1266 string_append (decl, "i");
1267 break;
1269 /* String values. */
1270 case 'a': /* UTF8 */
1271 case 'w': /* UTF16 */
1272 case 'd': /* UTF32 */
1273 mangled = dlang_parse_string (decl, mangled);
1274 break;
1276 /* Array values. */
1277 case 'A':
1278 mangled++;
1279 if (type == 'H')
1280 mangled = dlang_parse_assocarray (decl, mangled);
1281 else
1282 mangled = dlang_parse_arrayliteral (decl, mangled);
1283 break;
1285 /* Struct values. */
1286 case 'S':
1287 mangled++;
1288 mangled = dlang_parse_structlit (decl, mangled, name);
1289 break;
1291 default:
1292 return NULL;
1295 return mangled;
1298 /* Extract the type modifiers from MANGLED and return the string
1299 length that it consumes in MANGLED on success or 0 on failure. */
1300 static int
1301 dlang_type_modifier_p (const char *mangled)
1303 int i;
1305 switch (*mangled)
1307 case 'x': case 'y':
1308 return 1;
1310 case 'O':
1311 mangled++;
1312 i = dlang_type_modifier_p (mangled);
1313 return i + 1;
1315 case 'N':
1316 mangled++;
1317 if (*mangled == 'g')
1319 mangled++;
1320 i = dlang_type_modifier_p (mangled);
1321 return i + 2;
1325 return 0;
1328 /* Extract the function calling convention from MANGLED and
1329 return 1 on success or 0 on failure. */
1330 static int
1331 dlang_call_convention_p (const char *mangled)
1333 /* Prefix for functions needing 'this' */
1334 if (*mangled == 'M')
1336 mangled++;
1337 /* Also skip over any type modifiers. */
1338 mangled += dlang_type_modifier_p (mangled);
1341 switch (*mangled)
1343 case 'F': case 'U': case 'V':
1344 case 'W': case 'R':
1345 return 1;
1347 default:
1348 return 0;
1352 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1353 Returns the remaining signature on success or NULL on failure. */
1354 static const char *
1355 dlang_parse_symbol (string *decl, const char *mangled,
1356 enum dlang_symbol_kinds kind)
1358 int saved;
1359 size_t n = 0;
1362 if (n++)
1363 string_append (decl, ".");
1365 mangled = dlang_identifier (decl, mangled, kind);
1367 if (mangled && dlang_call_convention_p (mangled))
1369 string mods;
1370 const char *start = NULL;
1371 int checkpoint = 0;
1373 /* Skip over 'this' parameter. */
1374 if (*mangled == 'M')
1375 mangled++;
1377 /* We have reached here because we expect an extern(Pascal) function.
1378 However this is so rare, that it is more likely a template value
1379 parameter. Since this can't be assumed, first attempt parsing
1380 the symbol as a function, and then back out on failure. */
1381 if (*mangled == 'V')
1383 start = mangled;
1384 checkpoint = string_length (decl);
1387 /* Save the type modifiers for appending at the end. */
1388 string_init (&mods);
1389 mangled = dlang_type_modifiers (&mods, mangled);
1391 /* Skip over calling convention and attributes in qualified name. */
1392 saved = string_length (decl);
1393 mangled = dlang_call_convention (decl, mangled);
1394 mangled = dlang_attributes (decl, mangled);
1395 string_setlength (decl, saved);
1397 string_append (decl, "(");
1398 mangled = dlang_function_args (decl, mangled);
1399 string_append (decl, ")");
1401 /* Add any const/immutable/shared modifier. */
1402 string_appendn (decl, mods.b, string_length (&mods));
1403 string_delete (&mods);
1405 if (mangled == NULL && checkpoint != 0)
1407 mangled = start;
1408 string_setlength (decl, checkpoint);
1412 while (mangled && ISDIGIT (*mangled));
1414 /* Only top-level symbols or function template parameters have
1415 a type that needs checking. */
1416 if (kind == dlang_top_level || kind == dlang_function)
1418 /* Artificial symbols end with 'Z' and have no type. */
1419 if (mangled && *mangled == 'Z')
1420 mangled++;
1421 else
1423 saved = string_length (decl);
1424 mangled = dlang_type (decl, mangled);
1425 string_setlength (decl, saved);
1428 /* Check that the entire symbol was successfully demangled. */
1429 if (kind == dlang_top_level)
1431 if (mangled == NULL || *mangled != '\0')
1432 return NULL;
1436 return mangled;
1439 /* Demangle the tuple from MANGLED and append it to DECL.
1440 Return the remaining string on success or NULL on failure. */
1441 static const char *
1442 dlang_parse_tuple (string *decl, const char *mangled)
1444 char *endptr;
1445 long elements = strtol (mangled, &endptr, 10);
1447 if (endptr == NULL || elements < 0)
1448 return NULL;
1450 mangled = endptr;
1451 string_append (decl, "Tuple!(");
1453 while (elements--)
1455 mangled = dlang_type (decl, mangled);
1456 if (elements != 0)
1457 string_append (decl, ", ");
1460 string_append (decl, ")");
1461 return mangled;
1464 /* Demangle the argument list from MANGLED and append it to DECL.
1465 Return the remaining string on success or NULL on failure. */
1466 static const char *
1467 dlang_template_args (string *decl, const char *mangled)
1469 size_t n = 0;
1471 while (mangled && *mangled != '\0')
1473 switch (*mangled)
1475 case 'Z': /* End of parameter list. */
1476 mangled++;
1477 return mangled;
1480 if (n++)
1481 string_append (decl, ", ");
1483 /* Skip over specialised template prefix. */
1484 if (*mangled == 'H')
1485 mangled++;
1487 switch (*mangled)
1489 case 'S': /* Symbol parameter. */
1490 mangled++;
1491 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
1492 break;
1493 case 'T': /* Type parameter. */
1494 mangled++;
1495 mangled = dlang_type (decl, mangled);
1496 break;
1497 case 'V': /* Value parameter. */
1499 string name;
1500 char type;
1502 /* Peek at the type. */
1503 mangled++;
1504 type = *mangled;
1506 /* In the few instances where the type is actually desired in
1507 the output, it should precede the value from dlang_value. */
1508 string_init (&name);
1509 mangled = dlang_type (&name, mangled);
1510 string_need (&name, 1);
1511 *(name.p) = '\0';
1513 mangled = dlang_value (decl, mangled, name.b, type);
1514 string_delete (&name);
1515 break;
1518 default:
1519 return NULL;
1523 return mangled;
1526 /* Extract and demangle the template symbol in MANGLED, expected to
1527 be made up of LEN characters, and append it to DECL.
1528 Returns the remaining signature on success or NULL on failure. */
1529 static const char *
1530 dlang_parse_template (string *decl, const char *mangled, long len)
1532 const char *start = mangled;
1534 /* Template instance names have the types and values of its parameters
1535 encoded into it.
1537 TemplateInstanceName:
1538 Number __T LName TemplateArgs Z
1540 The start pointer should be at the above location, and LEN should be
1541 the value of the decoded number.
1543 if (strncmp (mangled, "__T", 3) != 0)
1544 return NULL;
1546 mangled += 3;
1548 /* Template identifier. */
1549 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1551 /* Template arguments. */
1552 string_append (decl, "!(");
1553 mangled = dlang_template_args (decl, mangled);
1554 string_append (decl, ")");
1556 /* Check for template name length mismatch. */
1557 if (mangled && (mangled - start) != len)
1558 return NULL;
1560 return mangled;
1563 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1564 signature on success or NULL on failure. */
1566 char *
1567 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1569 string decl;
1570 char *demangled = NULL;
1572 if (mangled == NULL || *mangled == '\0')
1573 return NULL;
1575 if (strncmp (mangled, "_D", 2) != 0)
1576 return NULL;
1578 string_init (&decl);
1580 if (strcmp (mangled, "_Dmain") == 0)
1582 string_append (&decl, "D main");
1584 else
1586 mangled += 2;
1588 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
1589 string_delete (&decl);
1592 if (string_length (&decl) > 0)
1594 string_need (&decl, 1);
1595 *(decl.p) = '\0';
1596 demangled = decl.b;
1599 return demangled;