Daily bump.
[official-gcc.git] / libiberty / d-demangle.c
blob12457f003b11b66e466597f3ad55368c431d20c9
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 #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 #endif
49 #include <demangle.h>
50 #include "libiberty.h"
52 /* A mini string-handling package */
54 typedef struct string /* Beware: these aren't required to be */
55 { /* '\0' terminated. */
56 char *b; /* pointer to start of string */
57 char *p; /* pointer after last character */
58 char *e; /* pointer after end of allocated space */
59 } string;
61 static void
62 string_need (string *s, int n)
64 int tem;
66 if (s->b == NULL)
68 if (n < 32)
70 n = 32;
72 s->p = s->b = XNEWVEC (char, n);
73 s->e = s->b + n;
75 else if (s->e - s->p < n)
77 tem = s->p - s->b;
78 n += tem;
79 n *= 2;
80 s->b = XRESIZEVEC (char, s->b, n);
81 s->p = s->b + tem;
82 s->e = s->b + n;
86 static void
87 string_delete (string *s)
89 if (s->b != NULL)
91 XDELETEVEC (s->b);
92 s->b = s->e = s->p = NULL;
96 static void
97 string_init (string *s)
99 s->b = s->p = s->e = NULL;
102 static int
103 string_length (string *s)
105 if (s->p == s->b)
107 return 0;
109 return s->p - s->b;
112 static void
113 string_setlength (string *s, int n)
115 if (n - string_length (s) < 0)
117 s->p = s->b + n;
121 static void
122 string_append (string *p, const char *s)
124 int n = strlen (s);
125 string_need (p, n);
126 memcpy (p->p, s, n);
127 p->p += n;
130 static void
131 string_appendn (string *p, const char *s, int n)
133 if (n != 0)
135 string_need (p, n);
136 memcpy (p->p, s, n);
137 p->p += n;
141 static void
142 string_prependn (string *p, const char *s, int n)
144 char *q;
146 if (n != 0)
148 string_need (p, n);
149 for (q = p->p - 1; q >= p->b; q--)
151 q[n] = q[0];
153 memcpy (p->b, s, n);
154 p->p += n;
158 static void
159 string_prepend (string *p, const char *s)
161 if (s != NULL && *s != '\0')
163 string_prependn (p, s, strlen (s));
167 /* What kinds of symbol we could be parsing. */
168 enum dlang_symbol_kinds
170 /* Top-level symbol, needs it's type checked. */
171 dlang_top_level,
172 /* Function symbol, needs it's type checked. */
173 dlang_function,
174 /* Strongly typed name, such as for classes, structs and enums. */
175 dlang_type_name,
176 /* Template identifier. */
177 dlang_template_ident,
178 /* Template symbol parameter. */
179 dlang_template_param
182 /* Prototypes for forward referenced functions */
183 static const char *dlang_function_args (string *, const char *);
185 static const char *dlang_type (string *, const char *);
187 static const char *dlang_value (string *, const char *, const char *, char);
189 static const char *dlang_parse_symbol (string *, const char *,
190 enum dlang_symbol_kinds);
192 static const char *dlang_parse_tuple (string *, const char *);
194 static const char *dlang_parse_template (string *, const char *, long);
197 /* Demangle the calling convention from MANGLED and append it to DECL.
198 Return the remaining string on success or NULL on failure. */
199 static const char *
200 dlang_call_convention (string *decl, const char *mangled)
202 if (mangled == NULL || *mangled == '\0')
203 return NULL;
205 switch (*mangled)
207 case 'F': /* (D) */
208 mangled++;
209 break;
210 case 'U': /* (C) */
211 mangled++;
212 string_append (decl, "extern(C) ");
213 break;
214 case 'W': /* (Windows) */
215 mangled++;
216 string_append (decl, "extern(Windows) ");
217 break;
218 case 'V': /* (Pascal) */
219 mangled++;
220 string_append (decl, "extern(Pascal) ");
221 break;
222 case 'R': /* (C++) */
223 mangled++;
224 string_append (decl, "extern(C++) ");
225 break;
226 case 'Y': /* (Objective-C) */
227 mangled++;
228 string_append (decl, "extern(Objective-C) ");
229 break;
230 default:
231 return NULL;
234 return mangled;
237 /* Extract the type modifiers from MANGLED and append them to DECL.
238 Returns the remaining signature on success or NULL on failure. */
239 static const char *
240 dlang_type_modifiers (string *decl, const char *mangled)
242 if (mangled == NULL || *mangled == '\0')
243 return NULL;
245 switch (*mangled)
247 case 'x': /* const */
248 mangled++;
249 string_append (decl, " const");
250 return mangled;
251 case 'y': /* immutable */
252 mangled++;
253 string_append (decl, " immutable");
254 return mangled;
255 case 'O': /* shared */
256 mangled++;
257 string_append (decl, " shared");
258 return dlang_type_modifiers (decl, mangled);
259 case 'N':
260 mangled++;
261 if (*mangled == 'g') /* wild */
263 mangled++;
264 string_append (decl, " inout");
265 return dlang_type_modifiers (decl, mangled);
267 else
268 return NULL;
270 default:
271 return mangled;
275 /* Demangle the D function attributes from MANGLED and append it to DECL.
276 Return the remaining string on success or NULL on failure. */
277 static const char *
278 dlang_attributes (string *decl, const char *mangled)
280 if (mangled == NULL || *mangled == '\0')
281 return NULL;
283 while (*mangled == 'N')
285 mangled++;
286 switch (*mangled)
288 case 'a': /* pure */
289 mangled++;
290 string_append (decl, "pure ");
291 continue;
292 case 'b': /* nothrow */
293 mangled++;
294 string_append (decl, "nothrow ");
295 continue;
296 case 'c': /* ref */
297 mangled++;
298 string_append (decl, "ref ");
299 continue;
300 case 'd': /* @property */
301 mangled++;
302 string_append (decl, "@property ");
303 continue;
304 case 'e': /* @trusted */
305 mangled++;
306 string_append (decl, "@trusted ");
307 continue;
308 case 'f': /* @safe */
309 mangled++;
310 string_append (decl, "@safe ");
311 continue;
312 case 'g':
313 case 'h':
314 case 'k':
315 /* inout parameter is represented as 'Ng'.
316 vector parameter is represented as 'Nh'.
317 return paramenter is represented as 'Nk'.
318 If we see this, then we know we're really in the
319 parameter list. Rewind and break. */
320 mangled--;
321 break;
322 case 'i': /* @nogc */
323 mangled++;
324 string_append (decl, "@nogc ");
325 continue;
326 case 'j': /* return */
327 mangled++;
328 string_append (decl, "return ");
329 continue;
331 default: /* unknown attribute */
332 return NULL;
334 break;
337 return mangled;
340 /* Demangle the function type from MANGLED and append it to DECL.
341 Return the remaining string on success or NULL on failure. */
342 static const char *
343 dlang_function_type (string *decl, const char *mangled)
345 string attr, args, type;
346 size_t szattr, szargs, sztype;
348 if (mangled == NULL || *mangled == '\0')
349 return NULL;
351 /* The order of the mangled string is:
352 CallConvention FuncAttrs Arguments ArgClose Type
354 The demangled string is re-ordered as:
355 CallConvention Type Arguments FuncAttrs
357 string_init (&attr);
358 string_init (&args);
359 string_init (&type);
361 /* Function call convention. */
362 mangled = dlang_call_convention (decl, mangled);
364 /* Function attributes. */
365 mangled = dlang_attributes (&attr, mangled);
366 szattr = string_length (&attr);
368 /* Function arguments. */
369 mangled = dlang_function_args (&args, mangled);
370 szargs = string_length (&args);
372 /* Function return type. */
373 mangled = dlang_type (&type, mangled);
374 sztype = string_length (&type);
376 /* Append to decl in order. */
377 string_appendn (decl, type.b, sztype);
378 string_append (decl, "(");
379 string_appendn (decl, args.b, szargs);
380 string_append (decl, ") ");
381 string_appendn (decl, attr.b, szattr);
383 string_delete (&attr);
384 string_delete (&args);
385 string_delete (&type);
386 return mangled;
389 /* Demangle the argument list from MANGLED and append it to DECL.
390 Return the remaining string on success or NULL on failure. */
391 static const char *
392 dlang_function_args (string *decl, const char *mangled)
394 size_t n = 0;
396 while (mangled && *mangled != '\0')
398 switch (*mangled)
400 case 'X': /* (variadic T t...) style. */
401 mangled++;
402 string_append (decl, "...");
403 return mangled;
404 case 'Y': /* (variadic T t, ...) style. */
405 mangled++;
406 if (n != 0)
407 string_append (decl, ", ");
408 string_append (decl, "...");
409 return mangled;
410 case 'Z': /* Normal function. */
411 mangled++;
412 return mangled;
415 if (n++)
416 string_append (decl, ", ");
418 if (*mangled == 'M') /* scope(T) */
420 mangled++;
421 string_append (decl, "scope ");
424 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
426 mangled += 2;
427 string_append (decl, "return ");
430 switch (*mangled)
432 case 'J': /* out(T) */
433 mangled++;
434 string_append (decl, "out ");
435 break;
436 case 'K': /* ref(T) */
437 mangled++;
438 string_append (decl, "ref ");
439 break;
440 case 'L': /* lazy(T) */
441 mangled++;
442 string_append (decl, "lazy ");
443 break;
445 mangled = dlang_type (decl, mangled);
448 return mangled;
451 /* Demangle the type from MANGLED and append it to DECL.
452 Return the remaining string on success or NULL on failure. */
453 static const char *
454 dlang_type (string *decl, const char *mangled)
456 if (mangled == NULL || *mangled == '\0')
457 return NULL;
459 switch (*mangled)
461 case 'O': /* shared(T) */
462 mangled++;
463 string_append (decl, "shared(");
464 mangled = dlang_type (decl, mangled);
465 string_append (decl, ")");
466 return mangled;
467 case 'x': /* const(T) */
468 mangled++;
469 string_append (decl, "const(");
470 mangled = dlang_type (decl, mangled);
471 string_append (decl, ")");
472 return mangled;
473 case 'y': /* immutable(T) */
474 mangled++;
475 string_append (decl, "immutable(");
476 mangled = dlang_type (decl, mangled);
477 string_append (decl, ")");
478 return mangled;
479 case 'N':
480 mangled++;
481 if (*mangled == 'g') /* wild(T) */
483 mangled++;
484 string_append (decl, "inout(");
485 mangled = dlang_type (decl, mangled);
486 string_append (decl, ")");
487 return mangled;
489 else if (*mangled == 'h') /* vector(T) */
491 mangled++;
492 string_append (decl, "__vector(");
493 mangled = dlang_type (decl, mangled);
494 string_append (decl, ")");
495 return mangled;
497 else
498 return NULL;
499 case 'A': /* dynamic array (T[]) */
500 mangled++;
501 mangled = dlang_type (decl, mangled);
502 string_append (decl, "[]");
503 return mangled;
504 case 'G': /* static array (T[N]) */
506 const char *numptr;
507 size_t num = 0;
508 mangled++;
510 numptr = mangled;
511 while (ISDIGIT (*mangled))
513 num++;
514 mangled++;
516 mangled = dlang_type (decl, mangled);
517 string_append (decl, "[");
518 string_appendn (decl, numptr, num);
519 string_append (decl, "]");
520 return mangled;
522 case 'H': /* associative array (T[T]) */
524 string type;
525 size_t sztype;
526 mangled++;
528 string_init (&type);
529 mangled = dlang_type (&type, mangled);
530 sztype = string_length (&type);
532 mangled = dlang_type (decl, mangled);
533 string_append (decl, "[");
534 string_appendn (decl, type.b, sztype);
535 string_append (decl, "]");
537 string_delete (&type);
538 return mangled;
540 case 'P': /* pointer (T*) */
541 mangled++;
542 /* Function pointer types don't include the trailing asterisk. */
543 switch (*mangled)
545 case 'F': case 'U': case 'W':
546 case 'V': case 'R': case 'Y':
547 mangled = dlang_function_type (decl, mangled);
548 string_append (decl, "function");
549 return mangled;
551 mangled = dlang_type (decl, mangled);
552 string_append (decl, "*");
553 return mangled;
554 case 'I': /* ident T */
555 case 'C': /* class T */
556 case 'S': /* struct T */
557 case 'E': /* enum T */
558 case 'T': /* typedef T */
559 mangled++;
560 return dlang_parse_symbol (decl, mangled, dlang_type_name);
561 case 'D': /* delegate T */
563 string mods;
564 size_t szmods;
565 mangled++;
567 string_init (&mods);
568 mangled = dlang_type_modifiers (&mods, mangled);
569 szmods = string_length (&mods);
571 mangled = dlang_function_type (decl, mangled);
572 string_append (decl, "delegate");
573 string_appendn (decl, mods.b, szmods);
575 string_delete (&mods);
576 return mangled;
578 case 'B': /* tuple T */
579 mangled++;
580 return dlang_parse_tuple (decl, mangled);
582 /* Basic types */
583 case 'n':
584 mangled++;
585 string_append (decl, "none");
586 return mangled;
587 case 'v':
588 mangled++;
589 string_append (decl, "void");
590 return mangled;
591 case 'g':
592 mangled++;
593 string_append (decl, "byte");
594 return mangled;
595 case 'h':
596 mangled++;
597 string_append (decl, "ubyte");
598 return mangled;
599 case 's':
600 mangled++;
601 string_append (decl, "short");
602 return mangled;
603 case 't':
604 mangled++;
605 string_append (decl, "ushort");
606 return mangled;
607 case 'i':
608 mangled++;
609 string_append (decl, "int");
610 return mangled;
611 case 'k':
612 mangled++;
613 string_append (decl, "uint");
614 return mangled;
615 case 'l':
616 mangled++;
617 string_append (decl, "long");
618 return mangled;
619 case 'm':
620 mangled++;
621 string_append (decl, "ulong");
622 return mangled;
623 case 'f':
624 mangled++;
625 string_append (decl, "float");
626 return mangled;
627 case 'd':
628 mangled++;
629 string_append (decl, "double");
630 return mangled;
631 case 'e':
632 mangled++;
633 string_append (decl, "real");
634 return mangled;
636 /* Imaginary and Complex types */
637 case 'o':
638 mangled++;
639 string_append (decl, "ifloat");
640 return mangled;
641 case 'p':
642 mangled++;
643 string_append (decl, "idouble");
644 return mangled;
645 case 'j':
646 mangled++;
647 string_append (decl, "ireal");
648 return mangled;
649 case 'q':
650 mangled++;
651 string_append (decl, "cfloat");
652 return mangled;
653 case 'r':
654 mangled++;
655 string_append (decl, "cdouble");
656 return mangled;
657 case 'c':
658 mangled++;
659 string_append (decl, "creal");
660 return mangled;
662 /* Other types */
663 case 'b':
664 mangled++;
665 string_append (decl, "bool");
666 return mangled;
667 case 'a':
668 mangled++;
669 string_append (decl, "char");
670 return mangled;
671 case 'u':
672 mangled++;
673 string_append (decl, "wchar");
674 return mangled;
675 case 'w':
676 mangled++;
677 string_append (decl, "dchar");
678 return mangled;
679 case 'z':
680 mangled++;
681 switch (*mangled)
683 case 'i':
684 mangled++;
685 string_append (decl, "cent");
686 return mangled;
687 case 'k':
688 mangled++;
689 string_append (decl, "ucent");
690 return mangled;
692 return NULL;
694 default: /* unhandled */
695 return NULL;
699 /* Extract the identifier from MANGLED and append it to DECL.
700 Return the remaining string on success or NULL on failure. */
701 static const char *
702 dlang_identifier (string *decl, const char *mangled,
703 enum dlang_symbol_kinds kind)
705 char *endptr;
706 long len;
708 if (mangled == NULL || *mangled == '\0')
709 return NULL;
711 len = strtol (mangled, &endptr, 10);
713 if (endptr == NULL || len <= 0)
714 return NULL;
716 /* In template parameter symbols, the first character of the mangled
717 name can be a digit. This causes ambiguity issues because the
718 digits of the two numbers are adjacent. */
719 if (kind == dlang_template_param)
721 long psize = len;
722 char *pend;
723 int saved = string_length (decl);
725 /* Work backwards until a match is found. */
726 for (pend = endptr; endptr != NULL; pend--)
728 mangled = pend;
730 /* Reached the beginning of the pointer to the name length,
731 try parsing the entire symbol. */
732 if (psize == 0)
734 psize = len;
735 pend = endptr;
736 endptr = NULL;
739 /* Check whether template parameter is a function with a valid
740 return type or an untyped identifier. */
741 if (ISDIGIT (*mangled))
742 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
743 else if (strncmp (mangled, "_D", 2) == 0)
745 mangled += 2;
746 mangled = dlang_parse_symbol (decl, mangled, dlang_function);
749 /* Check for name length mismatch. */
750 if (mangled && (mangled - pend) == psize)
751 return mangled;
753 psize /= 10;
754 string_setlength (decl, saved);
757 /* No match on any combinations. */
758 return NULL;
760 else
762 if (strlen (endptr) < (size_t) len)
763 return NULL;
765 mangled = endptr;
767 /* May be a template instance. */
768 if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
770 /* Template symbol. */
771 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
772 return dlang_parse_template (decl, mangled, len);
774 return NULL;
777 switch (len)
779 case 6:
780 if (strncmp (mangled, "__ctor", len) == 0)
782 /* Constructor symbol for a class/struct. */
783 string_append (decl, "this");
784 mangled += len;
785 return mangled;
787 else if (strncmp (mangled, "__dtor", len) == 0)
789 /* Destructor symbol for a class/struct. */
790 string_append (decl, "~this");
791 mangled += len;
792 return mangled;
794 else if (strncmp (mangled, "__initZ", len+1) == 0)
796 /* The static initialiser for a given symbol. */
797 string_append (decl, "init$");
798 mangled += len;
799 return mangled;
801 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
803 /* The vtable symbol for a given class. */
804 string_prepend (decl, "vtable for ");
805 string_setlength (decl, string_length (decl) - 1);
806 mangled += len;
807 return mangled;
809 break;
811 case 7:
812 if (strncmp (mangled, "__ClassZ", len+1) == 0)
814 /* The classinfo symbol for a given class. */
815 string_prepend (decl, "ClassInfo for ");
816 string_setlength (decl, string_length (decl) - 1);
817 mangled += len;
818 return mangled;
820 break;
822 case 10:
823 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
825 /* Postblit symbol for a struct. */
826 string_append (decl, "this(this)");
827 mangled += len + 3;
828 return mangled;
830 break;
832 case 11:
833 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
835 /* The interface symbol for a given class. */
836 string_prepend (decl, "Interface for ");
837 string_setlength (decl, string_length (decl) - 1);
838 mangled += len;
839 return mangled;
841 break;
843 case 12:
844 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
846 /* The ModuleInfo symbol for a given module. */
847 string_prepend (decl, "ModuleInfo for ");
848 string_setlength (decl, string_length (decl) - 1);
849 mangled += len;
850 return mangled;
852 break;
855 string_appendn (decl, mangled, len);
856 mangled += len;
859 return mangled;
862 /* Extract the integer value from MANGLED and append it to DECL,
863 where TYPE is the type it should be represented as.
864 Return the remaining string on success or NULL on failure. */
865 static const char *
866 dlang_parse_integer (string *decl, const char *mangled, char type)
868 if (type == 'a' || type == 'u' || type == 'w')
870 /* Parse character value. */
871 char value[10];
872 int pos = 10;
873 int width = 0;
874 char *endptr;
875 long val = strtol (mangled, &endptr, 10);
877 if (endptr == NULL || val < 0)
878 return NULL;
880 string_append (decl, "'");
882 if (type == 'a' && val >= 0x20 && val < 0x7F)
884 /* Represent as a character literal. */
885 char c = (char) val;
886 string_appendn (decl, &c, 1);
888 else
890 /* Represent as a hexadecimal value. */
891 switch (type)
893 case 'a': /* char */
894 string_append (decl, "\\x");
895 width = 2;
896 break;
897 case 'u': /* wchar */
898 string_append (decl, "\\u");
899 width = 4;
900 break;
901 case 'w': /* dchar */
902 string_append (decl, "\\U");
903 width = 8;
904 break;
907 while (val > 0)
909 int digit = val % 16;
911 if (digit < 10)
912 value[--pos] = (char)(digit + '0');
913 else
914 value[--pos] = (char)((digit - 10) + 'a');
916 val /= 16;
917 width--;
920 for (; width > 0; width--)
921 value[--pos] = '0';
923 string_appendn (decl, &(value[pos]), 10 - pos);
925 string_append (decl, "'");
926 mangled = endptr;
928 else if (type == 'b')
930 /* Parse boolean value. */
931 char *endptr;
932 long val = strtol (mangled, &endptr, 10);
934 if (endptr == NULL || val < 0)
935 return NULL;
937 string_append (decl, val ? "true" : "false");
938 mangled = endptr;
940 else
942 /* Parse integer value. */
943 const char *numptr = mangled;
944 size_t num = 0;
946 while (ISDIGIT (*mangled))
948 num++;
949 mangled++;
951 string_appendn (decl, numptr, num);
953 /* Append suffix. */
954 switch (type)
956 case 'h': /* ubyte */
957 case 't': /* ushort */
958 case 'k': /* uint */
959 string_append (decl, "u");
960 break;
961 case 'l': /* long */
962 string_append (decl, "L");
963 break;
964 case 'm': /* ulong */
965 string_append (decl, "uL");
966 break;
970 return mangled;
973 /* Extract the floating-point value from MANGLED and append it to DECL.
974 Return the remaining string on success or NULL on failure. */
975 static const char *
976 dlang_parse_real (string *decl, const char *mangled)
978 char buffer[64];
979 int len = 0;
981 /* Handle NAN and +-INF. */
982 if (strncmp (mangled, "NAN", 3) == 0)
984 string_append (decl, "NaN");
985 mangled += 3;
986 return mangled;
988 else if (strncmp (mangled, "INF", 3) == 0)
990 string_append (decl, "Inf");
991 mangled += 3;
992 return mangled;
994 else if (strncmp (mangled, "NINF", 4) == 0)
996 string_append (decl, "-Inf");
997 mangled += 4;
998 return mangled;
1001 /* Hexadecimal prefix and leading bit. */
1002 if (*mangled == 'N')
1004 buffer[len++] = '-';
1005 mangled++;
1008 if (!ISXDIGIT (*mangled))
1009 return NULL;
1011 buffer[len++] = '0';
1012 buffer[len++] = 'x';
1013 buffer[len++] = *mangled;
1014 buffer[len++] = '.';
1015 mangled++;
1017 /* Significand. */
1018 while (ISXDIGIT (*mangled))
1020 buffer[len++] = *mangled;
1021 mangled++;
1024 /* Exponent. */
1025 if (*mangled != 'P')
1026 return NULL;
1028 buffer[len++] = 'p';
1029 mangled++;
1031 if (*mangled == 'N')
1033 buffer[len++] = '-';
1034 mangled++;
1037 while (ISDIGIT (*mangled))
1039 buffer[len++] = *mangled;
1040 mangled++;
1043 /* Write out the demangled hexadecimal, rather than trying to
1044 convert the buffer into a floating-point value. */
1045 buffer[len] = '\0';
1046 len = strlen (buffer);
1047 string_appendn (decl, buffer, len);
1048 return mangled;
1051 /* Convert VAL from an ascii hexdigit to value. */
1052 static char
1053 ascii2hex (char val)
1055 if (val >= 'a' && val <= 'f')
1056 return (val - 'a' + 10);
1058 if (val >= 'A' && val <= 'F')
1059 return (val - 'A' + 10);
1061 if (val >= '0' && val <= '9')
1062 return (val - '0');
1064 return 0;
1067 /* Extract the string value from MANGLED and append it to DECL.
1068 Return the remaining string on success or NULL on failure. */
1069 static const char *
1070 dlang_parse_string (string *decl, const char *mangled)
1072 char type = *mangled;
1073 char *endptr;
1074 long len;
1076 mangled++;
1077 len = strtol (mangled, &endptr, 10);
1079 if (endptr == NULL || len < 0)
1080 return NULL;
1082 mangled = endptr;
1083 if (*mangled != '_')
1084 return NULL;
1086 mangled++;
1087 string_append (decl, "\"");
1088 while (len--)
1090 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1092 char a = ascii2hex (mangled[0]);
1093 char b = ascii2hex (mangled[1]);
1094 char val = (a << 4) | b;
1096 /* Sanitize white and non-printable characters. */
1097 switch (val)
1099 case ' ':
1100 string_append (decl, " ");
1101 break;
1102 case '\t':
1103 string_append (decl, "\\t");
1104 break;
1105 case '\n':
1106 string_append (decl, "\\n");
1107 break;
1108 case '\r':
1109 string_append (decl, "\\r");
1110 break;
1111 case '\f':
1112 string_append (decl, "\\f");
1113 break;
1114 case '\v':
1115 string_append (decl, "\\v");
1116 break;
1118 default:
1119 if (ISPRINT (val))
1120 string_appendn (decl, &val, 1);
1121 else
1123 string_append (decl, "\\x");
1124 string_appendn (decl, mangled, 2);
1128 else
1129 return NULL;
1131 mangled += 2;
1133 string_append (decl, "\"");
1135 if (type != 'a')
1136 string_appendn (decl, &type, 1);
1138 return mangled;
1141 /* Extract the static array value from MANGLED and append it to DECL.
1142 Return the remaining string on success or NULL on failure. */
1143 static const char *
1144 dlang_parse_arrayliteral (string *decl, const char *mangled)
1146 char *endptr;
1147 long elements = strtol (mangled, &endptr, 10);
1149 if (endptr == NULL || elements < 0)
1150 return NULL;
1152 mangled = endptr;
1153 string_append (decl, "[");
1154 while (elements--)
1156 mangled = dlang_value (decl, mangled, NULL, '\0');
1157 if (elements != 0)
1158 string_append (decl, ", ");
1161 string_append (decl, "]");
1162 return mangled;
1165 /* Extract the associative array value from MANGLED and append it to DECL.
1166 Return the remaining string on success or NULL on failure. */
1167 static const char *
1168 dlang_parse_assocarray (string *decl, const char *mangled)
1170 char *endptr;
1171 long elements = strtol (mangled, &endptr, 10);
1173 if (endptr == NULL || elements < 0)
1174 return NULL;
1176 mangled = endptr;
1177 string_append (decl, "[");
1178 while (elements--)
1180 mangled = dlang_value (decl, mangled, NULL, '\0');
1181 string_append (decl, ":");
1182 mangled = dlang_value (decl, mangled, NULL, '\0');
1184 if (elements != 0)
1185 string_append (decl, ", ");
1188 string_append (decl, "]");
1189 return mangled;
1192 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1193 Return the remaining string on success or NULL on failure. */
1194 static const char *
1195 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1197 char *endptr;
1198 long args = strtol (mangled, &endptr, 10);
1200 if (endptr == NULL || args < 0)
1201 return NULL;
1203 mangled = endptr;
1204 if (name != NULL)
1205 string_append (decl, name);
1207 string_append (decl, "(");
1208 while (args--)
1210 mangled = dlang_value (decl, mangled, NULL, '\0');
1211 if (args != 0)
1212 string_append (decl, ", ");
1215 string_append (decl, ")");
1216 return mangled;
1219 /* Extract the value from MANGLED and append it to DECL.
1220 Return the remaining string on success or NULL on failure. */
1221 static const char *
1222 dlang_value (string *decl, const char *mangled, const char *name, char type)
1224 if (mangled == NULL || *mangled == '\0')
1225 return NULL;
1227 switch (*mangled)
1229 /* Null value. */
1230 case 'n':
1231 mangled++;
1232 string_append (decl, "null");
1233 break;
1235 /* Integral values. */
1236 case 'N':
1237 mangled++;
1238 string_append (decl, "-");
1239 mangled = dlang_parse_integer (decl, mangled, type);
1240 break;
1242 case 'i':
1243 mangled++;
1244 if (*mangled < '0' || *mangled > '9')
1245 return NULL;
1246 /* Fall through */
1247 case '0': case '1': case '2': case '3': case '4':
1248 case '5': case '6': case '7': case '8': case '9':
1249 mangled = dlang_parse_integer (decl, mangled, type);
1250 break;
1252 /* Real value. */
1253 case 'e':
1254 mangled++;
1255 mangled = dlang_parse_real (decl, mangled);
1256 break;
1258 /* Complex value. */
1259 case 'c':
1260 mangled++;
1261 mangled = dlang_parse_real (decl, mangled);
1262 string_append (decl, "+");
1263 if (mangled == NULL || *mangled != 'c')
1264 return NULL;
1265 mangled++;
1266 mangled = dlang_parse_real (decl, mangled);
1267 string_append (decl, "i");
1268 break;
1270 /* String values. */
1271 case 'a': /* UTF8 */
1272 case 'w': /* UTF16 */
1273 case 'd': /* UTF32 */
1274 mangled = dlang_parse_string (decl, mangled);
1275 break;
1277 /* Array values. */
1278 case 'A':
1279 mangled++;
1280 if (type == 'H')
1281 mangled = dlang_parse_assocarray (decl, mangled);
1282 else
1283 mangled = dlang_parse_arrayliteral (decl, mangled);
1284 break;
1286 /* Struct values. */
1287 case 'S':
1288 mangled++;
1289 mangled = dlang_parse_structlit (decl, mangled, name);
1290 break;
1292 default:
1293 return NULL;
1296 return mangled;
1299 /* Extract the type modifiers from MANGLED and return the string
1300 length that it consumes in MANGLED on success or 0 on failure. */
1301 static int
1302 dlang_type_modifier_p (const char *mangled)
1304 int i;
1306 switch (*mangled)
1308 case 'x': case 'y':
1309 return 1;
1311 case 'O':
1312 mangled++;
1313 i = dlang_type_modifier_p (mangled);
1314 return i + 1;
1316 case 'N':
1317 mangled++;
1318 if (*mangled == 'g')
1320 mangled++;
1321 i = dlang_type_modifier_p (mangled);
1322 return i + 2;
1326 return 0;
1329 /* Extract the function calling convention from MANGLED and
1330 return 1 on success or 0 on failure. */
1331 static int
1332 dlang_call_convention_p (const char *mangled)
1334 /* Prefix for functions needing 'this' */
1335 if (*mangled == 'M')
1337 mangled++;
1338 /* Also skip over any type modifiers. */
1339 mangled += dlang_type_modifier_p (mangled);
1342 switch (*mangled)
1344 case 'F': case 'U': case 'V':
1345 case 'W': case 'R': case 'Y':
1346 return 1;
1348 default:
1349 return 0;
1353 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1354 Returns the remaining signature on success or NULL on failure. */
1355 static const char *
1356 dlang_parse_symbol (string *decl, const char *mangled,
1357 enum dlang_symbol_kinds kind)
1359 int saved;
1360 size_t n = 0;
1363 if (n++)
1364 string_append (decl, ".");
1366 mangled = dlang_identifier (decl, mangled, kind);
1368 if (mangled && dlang_call_convention_p (mangled))
1370 string mods;
1371 const char *start = NULL;
1372 int checkpoint = 0;
1374 /* Skip over 'this' parameter. */
1375 if (*mangled == 'M')
1376 mangled++;
1378 /* We have reached here because we expect an extern(Pascal) function.
1379 However this is so rare, that it is more likely a template value
1380 parameter. Since this can't be assumed, first attempt parsing
1381 the symbol as a function, and then back out on failure. */
1382 if (*mangled == 'V')
1384 start = mangled;
1385 checkpoint = string_length (decl);
1388 /* Save the type modifiers for appending at the end. */
1389 string_init (&mods);
1390 mangled = dlang_type_modifiers (&mods, mangled);
1392 /* Skip over calling convention and attributes in qualified name. */
1393 saved = string_length (decl);
1394 mangled = dlang_call_convention (decl, mangled);
1395 mangled = dlang_attributes (decl, mangled);
1396 string_setlength (decl, saved);
1398 string_append (decl, "(");
1399 mangled = dlang_function_args (decl, mangled);
1400 string_append (decl, ")");
1402 /* Add any const/immutable/shared modifier. */
1403 string_appendn (decl, mods.b, string_length (&mods));
1404 string_delete (&mods);
1406 if (mangled == NULL && checkpoint != 0)
1408 mangled = start;
1409 string_setlength (decl, checkpoint);
1413 while (mangled && ISDIGIT (*mangled));
1415 /* Only top-level symbols or function template parameters have
1416 a type that needs checking. */
1417 if (kind == dlang_top_level || kind == dlang_function)
1419 /* Artificial symbols end with 'Z' and have no type. */
1420 if (mangled && *mangled == 'Z')
1421 mangled++;
1422 else
1424 saved = string_length (decl);
1425 mangled = dlang_type (decl, mangled);
1426 string_setlength (decl, saved);
1429 /* Check that the entire symbol was successfully demangled. */
1430 if (kind == dlang_top_level)
1432 if (mangled == NULL || *mangled != '\0')
1433 return NULL;
1437 return mangled;
1440 /* Demangle the tuple from MANGLED and append it to DECL.
1441 Return the remaining string on success or NULL on failure. */
1442 static const char *
1443 dlang_parse_tuple (string *decl, const char *mangled)
1445 char *endptr;
1446 long elements = strtol (mangled, &endptr, 10);
1448 if (endptr == NULL || elements < 0)
1449 return NULL;
1451 mangled = endptr;
1452 string_append (decl, "Tuple!(");
1454 while (elements--)
1456 mangled = dlang_type (decl, mangled);
1457 if (elements != 0)
1458 string_append (decl, ", ");
1461 string_append (decl, ")");
1462 return mangled;
1465 /* Demangle the argument list from MANGLED and append it to DECL.
1466 Return the remaining string on success or NULL on failure. */
1467 static const char *
1468 dlang_template_args (string *decl, const char *mangled)
1470 size_t n = 0;
1472 while (mangled && *mangled != '\0')
1474 switch (*mangled)
1476 case 'Z': /* End of parameter list. */
1477 mangled++;
1478 return mangled;
1481 if (n++)
1482 string_append (decl, ", ");
1484 /* Skip over specialised template prefix. */
1485 if (*mangled == 'H')
1486 mangled++;
1488 switch (*mangled)
1490 case 'S': /* Symbol parameter. */
1491 mangled++;
1492 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
1493 break;
1494 case 'T': /* Type parameter. */
1495 mangled++;
1496 mangled = dlang_type (decl, mangled);
1497 break;
1498 case 'V': /* Value parameter. */
1500 string name;
1501 char type;
1503 /* Peek at the type. */
1504 mangled++;
1505 type = *mangled;
1507 /* In the few instances where the type is actually desired in
1508 the output, it should precede the value from dlang_value. */
1509 string_init (&name);
1510 mangled = dlang_type (&name, mangled);
1511 string_need (&name, 1);
1512 *(name.p) = '\0';
1514 mangled = dlang_value (decl, mangled, name.b, type);
1515 string_delete (&name);
1516 break;
1519 default:
1520 return NULL;
1524 return mangled;
1527 /* Extract and demangle the template symbol in MANGLED, expected to
1528 be made up of LEN characters, and append it to DECL.
1529 Returns the remaining signature on success or NULL on failure. */
1530 static const char *
1531 dlang_parse_template (string *decl, const char *mangled, long len)
1533 const char *start = mangled;
1535 /* Template instance names have the types and values of its parameters
1536 encoded into it.
1538 TemplateInstanceName:
1539 Number __T LName TemplateArgs Z
1541 The start pointer should be at the above location, and LEN should be
1542 the value of the decoded number.
1544 if (strncmp (mangled, "__T", 3) != 0)
1545 return NULL;
1547 mangled += 3;
1549 /* Template identifier. */
1550 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1552 /* Template arguments. */
1553 string_append (decl, "!(");
1554 mangled = dlang_template_args (decl, mangled);
1555 string_append (decl, ")");
1557 /* Check for template name length mismatch. */
1558 if (mangled && (mangled - start) != len)
1559 return NULL;
1561 return mangled;
1564 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1565 signature on success or NULL on failure. */
1567 char *
1568 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1570 string decl;
1571 char *demangled = NULL;
1573 if (mangled == NULL || *mangled == '\0')
1574 return NULL;
1576 if (strncmp (mangled, "_D", 2) != 0)
1577 return NULL;
1579 string_init (&decl);
1581 if (strcmp (mangled, "_Dmain") == 0)
1583 string_append (&decl, "D main");
1585 else
1587 mangled += 2;
1589 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
1590 string_delete (&decl);
1593 if (string_length (&decl) > 0)
1595 string_need (&decl, 1);
1596 *(decl.p) = '\0';
1597 demangled = decl.b;
1600 return demangled;