Clean up some minor white space issues in trans-decl.c and trans-expr.c
[official-gcc.git] / libiberty / d-demangle.c
blob3d7ccf67985ca584982507b0bbddb98648f9ce7e
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 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 default:
227 return NULL;
230 return mangled;
233 /* Extract the type modifiers from MANGLED and append them to DECL.
234 Returns the remaining signature on success or NULL on failure. */
235 static const char *
236 dlang_type_modifiers (string *decl, const char *mangled)
238 if (mangled == NULL || *mangled == '\0')
239 return NULL;
241 switch (*mangled)
243 case 'x': /* const */
244 mangled++;
245 string_append (decl, " const");
246 return mangled;
247 case 'y': /* immutable */
248 mangled++;
249 string_append (decl, " immutable");
250 return mangled;
251 case 'O': /* shared */
252 mangled++;
253 string_append (decl, " shared");
254 return dlang_type_modifiers (decl, mangled);
255 case 'N':
256 mangled++;
257 if (*mangled == 'g') /* wild */
259 mangled++;
260 string_append (decl, " inout");
261 return dlang_type_modifiers (decl, mangled);
263 else
264 return NULL;
266 default:
267 return mangled;
271 /* Demangle the D function attributes from MANGLED and append it to DECL.
272 Return the remaining string on success or NULL on failure. */
273 static const char *
274 dlang_attributes (string *decl, const char *mangled)
276 if (mangled == NULL || *mangled == '\0')
277 return NULL;
279 while (*mangled == 'N')
281 mangled++;
282 switch (*mangled)
284 case 'a': /* pure */
285 mangled++;
286 string_append (decl, "pure ");
287 continue;
288 case 'b': /* nothrow */
289 mangled++;
290 string_append (decl, "nothrow ");
291 continue;
292 case 'c': /* ref */
293 mangled++;
294 string_append (decl, "ref ");
295 continue;
296 case 'd': /* @property */
297 mangled++;
298 string_append (decl, "@property ");
299 continue;
300 case 'e': /* @trusted */
301 mangled++;
302 string_append (decl, "@trusted ");
303 continue;
304 case 'f': /* @safe */
305 mangled++;
306 string_append (decl, "@safe ");
307 continue;
308 case 'g':
309 case 'h':
310 case 'k':
311 /* inout parameter is represented as 'Ng'.
312 vector parameter is represented as 'Nh'.
313 return paramenter is represented as 'Nk'.
314 If we see this, then we know we're really in the
315 parameter list. Rewind and break. */
316 mangled--;
317 break;
318 case 'i': /* @nogc */
319 mangled++;
320 string_append (decl, "@nogc ");
321 continue;
322 case 'j': /* return */
323 mangled++;
324 string_append (decl, "return ");
325 continue;
327 default: /* unknown attribute */
328 return NULL;
330 break;
333 return mangled;
336 /* Demangle the function type from MANGLED and append it to DECL.
337 Return the remaining string on success or NULL on failure. */
338 static const char *
339 dlang_function_type (string *decl, const char *mangled)
341 string attr, args, type;
342 size_t szattr, szargs, sztype;
344 if (mangled == NULL || *mangled == '\0')
345 return NULL;
347 /* The order of the mangled string is:
348 CallConvention FuncAttrs Arguments ArgClose Type
350 The demangled string is re-ordered as:
351 CallConvention Type Arguments FuncAttrs
353 string_init (&attr);
354 string_init (&args);
355 string_init (&type);
357 /* Function call convention. */
358 mangled = dlang_call_convention (decl, mangled);
360 /* Function attributes. */
361 mangled = dlang_attributes (&attr, mangled);
362 szattr = string_length (&attr);
364 /* Function arguments. */
365 mangled = dlang_function_args (&args, mangled);
366 szargs = string_length (&args);
368 /* Function return type. */
369 mangled = dlang_type (&type, mangled);
370 sztype = string_length (&type);
372 /* Append to decl in order. */
373 string_appendn (decl, type.b, sztype);
374 string_append (decl, "(");
375 string_appendn (decl, args.b, szargs);
376 string_append (decl, ") ");
377 string_appendn (decl, attr.b, szattr);
379 string_delete (&attr);
380 string_delete (&args);
381 string_delete (&type);
382 return mangled;
385 /* Demangle the argument list from MANGLED and append it to DECL.
386 Return the remaining string on success or NULL on failure. */
387 static const char *
388 dlang_function_args (string *decl, const char *mangled)
390 size_t n = 0;
392 while (mangled && *mangled != '\0')
394 switch (*mangled)
396 case 'X': /* (variadic T t...) style. */
397 mangled++;
398 string_append (decl, "...");
399 return mangled;
400 case 'Y': /* (variadic T t, ...) style. */
401 mangled++;
402 string_append (decl, ", ...");
403 return mangled;
404 case 'Z': /* Normal function. */
405 mangled++;
406 return mangled;
409 if (n++)
410 string_append (decl, ", ");
412 if (*mangled == 'M') /* scope(T) */
414 mangled++;
415 string_append (decl, "scope ");
418 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
420 mangled += 2;
421 string_append (decl, "return ");
424 switch (*mangled)
426 case 'J': /* out(T) */
427 mangled++;
428 string_append (decl, "out ");
429 break;
430 case 'K': /* ref(T) */
431 mangled++;
432 string_append (decl, "ref ");
433 break;
434 case 'L': /* lazy(T) */
435 mangled++;
436 string_append (decl, "lazy ");
437 break;
439 mangled = dlang_type (decl, mangled);
442 return mangled;
445 /* Demangle the type from MANGLED and append it to DECL.
446 Return the remaining string on success or NULL on failure. */
447 static const char *
448 dlang_type (string *decl, const char *mangled)
450 if (mangled == NULL || *mangled == '\0')
451 return NULL;
453 switch (*mangled)
455 case 'O': /* shared(T) */
456 mangled++;
457 string_append (decl, "shared(");
458 mangled = dlang_type (decl, mangled);
459 string_append (decl, ")");
460 return mangled;
461 case 'x': /* const(T) */
462 mangled++;
463 string_append (decl, "const(");
464 mangled = dlang_type (decl, mangled);
465 string_append (decl, ")");
466 return mangled;
467 case 'y': /* immutable(T) */
468 mangled++;
469 string_append (decl, "immutable(");
470 mangled = dlang_type (decl, mangled);
471 string_append (decl, ")");
472 return mangled;
473 case 'N':
474 mangled++;
475 if (*mangled == 'g') /* wild(T) */
477 mangled++;
478 string_append (decl, "inout(");
479 mangled = dlang_type (decl, mangled);
480 string_append (decl, ")");
481 return mangled;
483 else if (*mangled == 'h') /* vector(T) */
485 mangled++;
486 string_append (decl, "__vector(");
487 mangled = dlang_type (decl, mangled);
488 string_append (decl, ")");
489 return mangled;
491 else
492 return NULL;
493 case 'A': /* dynamic array (T[]) */
494 mangled++;
495 mangled = dlang_type (decl, mangled);
496 string_append (decl, "[]");
497 return mangled;
498 case 'G': /* static array (T[N]) */
500 const char *numptr;
501 size_t num = 0;
502 mangled++;
504 numptr = mangled;
505 while (ISDIGIT (*mangled))
507 num++;
508 mangled++;
510 mangled = dlang_type (decl, mangled);
511 string_append (decl, "[");
512 string_appendn (decl, numptr, num);
513 string_append (decl, "]");
514 return mangled;
516 case 'H': /* associative array (T[T]) */
518 string type;
519 size_t sztype;
520 mangled++;
522 string_init (&type);
523 mangled = dlang_type (&type, mangled);
524 sztype = string_length (&type);
526 mangled = dlang_type (decl, mangled);
527 string_append (decl, "[");
528 string_appendn (decl, type.b, sztype);
529 string_append (decl, "]");
531 string_delete (&type);
532 return mangled;
534 case 'P': /* pointer (T*) */
535 mangled++;
536 mangled = dlang_type (decl, mangled);
537 string_append (decl, "*");
538 return mangled;
539 case 'I': /* ident T */
540 case 'C': /* class T */
541 case 'S': /* struct T */
542 case 'E': /* enum T */
543 case 'T': /* typedef T */
544 mangled++;
545 return dlang_parse_symbol (decl, mangled, dlang_type_name);
546 case 'D': /* delegate T */
548 string mods;
549 size_t szmods;
550 mangled++;
552 string_init (&mods);
553 mangled = dlang_type_modifiers (&mods, mangled);
554 szmods = string_length (&mods);
556 mangled = dlang_function_type (decl, mangled);
557 string_append (decl, "delegate");
558 string_appendn (decl, mods.b, szmods);
560 string_delete (&mods);
561 return mangled;
563 case 'B': /* tuple T */
564 mangled++;
565 return dlang_parse_tuple (decl, mangled);
567 /* Function types */
568 case 'F': case 'U': case 'W':
569 case 'V': case 'R':
570 mangled = dlang_function_type (decl, mangled);
571 string_append (decl, "function");
572 return mangled;
574 /* Basic types */
575 case 'n':
576 mangled++;
577 string_append (decl, "none");
578 return mangled;
579 case 'v':
580 mangled++;
581 string_append (decl, "void");
582 return mangled;
583 case 'g':
584 mangled++;
585 string_append (decl, "byte");
586 return mangled;
587 case 'h':
588 mangled++;
589 string_append (decl, "ubyte");
590 return mangled;
591 case 's':
592 mangled++;
593 string_append (decl, "short");
594 return mangled;
595 case 't':
596 mangled++;
597 string_append (decl, "ushort");
598 return mangled;
599 case 'i':
600 mangled++;
601 string_append (decl, "int");
602 return mangled;
603 case 'k':
604 mangled++;
605 string_append (decl, "uint");
606 return mangled;
607 case 'l':
608 mangled++;
609 string_append (decl, "long");
610 return mangled;
611 case 'm':
612 mangled++;
613 string_append (decl, "ulong");
614 return mangled;
615 case 'f':
616 mangled++;
617 string_append (decl, "float");
618 return mangled;
619 case 'd':
620 mangled++;
621 string_append (decl, "double");
622 return mangled;
623 case 'e':
624 mangled++;
625 string_append (decl, "real");
626 return mangled;
628 /* Imaginary and Complex types */
629 case 'o':
630 mangled++;
631 string_append (decl, "ifloat");
632 return mangled;
633 case 'p':
634 mangled++;
635 string_append (decl, "idouble");
636 return mangled;
637 case 'j':
638 mangled++;
639 string_append (decl, "ireal");
640 return mangled;
641 case 'q':
642 mangled++;
643 string_append (decl, "cfloat");
644 return mangled;
645 case 'r':
646 mangled++;
647 string_append (decl, "cdouble");
648 return mangled;
649 case 'c':
650 mangled++;
651 string_append (decl, "creal");
652 return mangled;
654 /* Other types */
655 case 'b':
656 mangled++;
657 string_append (decl, "bool");
658 return mangled;
659 case 'a':
660 mangled++;
661 string_append (decl, "char");
662 return mangled;
663 case 'u':
664 mangled++;
665 string_append (decl, "wchar");
666 return mangled;
667 case 'w':
668 mangled++;
669 string_append (decl, "dchar");
670 return mangled;
671 case 'z':
672 mangled++;
673 switch (*mangled)
675 case 'i':
676 mangled++;
677 string_append (decl, "cent");
678 return mangled;
679 case 'k':
680 mangled++;
681 string_append (decl, "ucent");
682 return mangled;
684 return NULL;
686 default: /* unhandled */
687 return NULL;
691 /* Extract the identifier from MANGLED and append it to DECL.
692 Return the remaining string on success or NULL on failure. */
693 static const char *
694 dlang_identifier (string *decl, const char *mangled,
695 enum dlang_symbol_kinds kind)
697 char *endptr;
698 long len;
700 if (mangled == NULL || *mangled == '\0')
701 return NULL;
703 len = strtol (mangled, &endptr, 10);
705 if (endptr == NULL || len <= 0)
706 return NULL;
708 /* In template parameter symbols, the first character of the mangled
709 name can be a digit. This causes ambiguity issues because the
710 digits of the two numbers are adjacent. */
711 if (kind == dlang_template_param)
713 long psize = len;
714 char *pend;
715 int saved = string_length (decl);
717 /* Work backwards until a match is found. */
718 for (pend = endptr; endptr != NULL; pend--)
720 mangled = pend;
722 /* Reached the beginning of the pointer to the name length,
723 try parsing the entire symbol. */
724 if (psize == 0)
726 psize = len;
727 pend = endptr;
728 endptr = NULL;
731 /* Check whether template parameter is a function with a valid
732 return type or an untyped identifier. */
733 if (ISDIGIT (*mangled))
734 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident);
735 else if (strncmp (mangled, "_D", 2) == 0)
737 mangled += 2;
738 mangled = dlang_parse_symbol (decl, mangled, dlang_function);
741 /* Check for name length mismatch. */
742 if (mangled && (mangled - pend) == psize)
743 return mangled;
745 psize /= 10;
746 string_setlength (decl, saved);
749 /* No match on any combinations. */
750 return NULL;
752 else
754 if (strlen (endptr) < (size_t) len)
755 return NULL;
757 mangled = endptr;
759 /* May be a template instance. */
760 if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
762 /* Template symbol. */
763 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
764 return dlang_parse_template (decl, mangled, len);
766 return NULL;
769 switch (len)
771 case 6:
772 if (strncmp (mangled, "__ctor", len) == 0)
774 /* Constructor symbol for a class/struct. */
775 string_append (decl, "this");
776 mangled += len;
777 return mangled;
779 else if (strncmp (mangled, "__dtor", len) == 0)
781 /* Destructor symbol for a class/struct. */
782 string_append (decl, "~this");
783 mangled += len;
784 return mangled;
786 else if (strncmp (mangled, "__initZ", len+1) == 0)
788 /* The static initialiser for a given symbol. */
789 string_append (decl, "init$");
790 mangled += len;
791 return mangled;
793 else if (strncmp (mangled, "__vtblZ", len+1) == 0)
795 /* The vtable symbol for a given class. */
796 string_prepend (decl, "vtable for ");
797 string_setlength (decl, string_length (decl) - 1);
798 mangled += len;
799 return mangled;
801 break;
803 case 7:
804 if (strncmp (mangled, "__ClassZ", len+1) == 0)
806 /* The classinfo symbol for a given class. */
807 string_prepend (decl, "ClassInfo for ");
808 string_setlength (decl, string_length (decl) - 1);
809 mangled += len;
810 return mangled;
812 break;
814 case 10:
815 if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
817 /* Postblit symbol for a struct. */
818 string_append (decl, "this(this)");
819 mangled += len + 3;
820 return mangled;
822 break;
824 case 11:
825 if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
827 /* The interface symbol for a given class. */
828 string_prepend (decl, "Interface for ");
829 string_setlength (decl, string_length (decl) - 1);
830 mangled += len;
831 return mangled;
833 break;
835 case 12:
836 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
838 /* The ModuleInfo symbol for a given module. */
839 string_prepend (decl, "ModuleInfo for ");
840 string_setlength (decl, string_length (decl) - 1);
841 mangled += len;
842 return mangled;
844 break;
847 string_appendn (decl, mangled, len);
848 mangled += len;
851 return mangled;
854 /* Extract the integer value from MANGLED and append it to DECL,
855 where TYPE is the type it should be represented as.
856 Return the remaining string on success or NULL on failure. */
857 static const char *
858 dlang_parse_integer (string *decl, const char *mangled, char type)
860 if (type == 'a' || type == 'u' || type == 'w')
862 /* Parse character value. */
863 char value[10];
864 int pos = 10;
865 int width = 0;
866 char *endptr;
867 long val = strtol (mangled, &endptr, 10);
869 if (endptr == NULL || val < 0)
870 return NULL;
872 string_append (decl, "'");
874 if (type == 'a' && val >= 0x20 && val < 0x7F)
876 /* Represent as a character literal. */
877 char c = (char) val;
878 string_appendn (decl, &c, 1);
880 else
882 /* Represent as a hexadecimal value. */
883 switch (type)
885 case 'a': /* char */
886 string_append (decl, "\\x");
887 width = 2;
888 break;
889 case 'u': /* wchar */
890 string_append (decl, "\\u");
891 width = 4;
892 break;
893 case 'w': /* dchar */
894 string_append (decl, "\\U");
895 width = 8;
896 break;
899 while (val > 0)
901 int digit = val % 16;
903 if (digit < 10)
904 value[--pos] = (char)(digit + '0');
905 else
906 value[--pos] = (char)((digit - 10) + 'a');
908 val /= 16;
909 width--;
912 for (; width > 0; width--)
913 value[--pos] = '0';
915 string_appendn (decl, &(value[pos]), 10 - pos);
917 string_append (decl, "'");
918 mangled = endptr;
920 else if (type == 'b')
922 /* Parse boolean value. */
923 char *endptr;
924 long val = strtol (mangled, &endptr, 10);
926 if (endptr == NULL || val < 0)
927 return NULL;
929 string_append (decl, val ? "true" : "false");
930 mangled = endptr;
932 else
934 /* Parse integer value. */
935 const char *numptr = mangled;
936 size_t num = 0;
938 while (ISDIGIT (*mangled))
940 num++;
941 mangled++;
943 string_appendn (decl, numptr, num);
945 /* Append suffix. */
946 switch (type)
948 case 'h': /* ubyte */
949 case 't': /* ushort */
950 case 'k': /* uint */
951 string_append (decl, "u");
952 break;
953 case 'l': /* long */
954 string_append (decl, "L");
955 break;
956 case 'm': /* ulong */
957 string_append (decl, "uL");
958 break;
962 return mangled;
965 /* Extract the floating-point value from MANGLED and append it to DECL.
966 Return the remaining string on success or NULL on failure. */
967 static const char *
968 dlang_parse_real (string *decl, const char *mangled)
970 char buffer[64];
971 int len = 0;
973 /* Handle NAN and +-INF. */
974 if (strncmp (mangled, "NAN", 3) == 0)
976 string_append (decl, "NaN");
977 mangled += 3;
978 return mangled;
980 else if (strncmp (mangled, "INF", 3) == 0)
982 string_append (decl, "Inf");
983 mangled += 3;
984 return mangled;
986 else if (strncmp (mangled, "NINF", 4) == 0)
988 string_append (decl, "-Inf");
989 mangled += 4;
990 return mangled;
993 /* Hexadecimal prefix and leading bit. */
994 if (*mangled == 'N')
996 buffer[len++] = '-';
997 mangled++;
1000 if (!ISXDIGIT (*mangled))
1001 return NULL;
1003 buffer[len++] = '0';
1004 buffer[len++] = 'x';
1005 buffer[len++] = *mangled;
1006 buffer[len++] = '.';
1007 mangled++;
1009 /* Significand. */
1010 while (ISXDIGIT (*mangled))
1012 buffer[len++] = *mangled;
1013 mangled++;
1016 /* Exponent. */
1017 if (*mangled != 'P')
1018 return NULL;
1020 buffer[len++] = 'p';
1021 mangled++;
1023 if (*mangled == 'N')
1025 buffer[len++] = '-';
1026 mangled++;
1029 while (ISDIGIT (*mangled))
1031 buffer[len++] = *mangled;
1032 mangled++;
1035 /* Write out the demangled hexadecimal, rather than trying to
1036 convert the buffer into a floating-point value. */
1037 buffer[len] = '\0';
1038 len = strlen (buffer);
1039 string_appendn (decl, buffer, len);
1040 return mangled;
1043 /* Convert VAL from an ascii hexdigit to value. */
1044 static char
1045 ascii2hex (char val)
1047 if (val >= 'a' && val <= 'f')
1048 return (val - 'a' + 10);
1050 if (val >= 'A' && val <= 'F')
1051 return (val - 'A' + 10);
1053 if (val >= '0' && val <= '9')
1054 return (val - '0');
1056 return 0;
1059 /* Extract the string value from MANGLED and append it to DECL.
1060 Return the remaining string on success or NULL on failure. */
1061 static const char *
1062 dlang_parse_string (string *decl, const char *mangled)
1064 char type = *mangled;
1065 char *endptr;
1066 long len;
1068 mangled++;
1069 len = strtol (mangled, &endptr, 10);
1071 if (endptr == NULL || len < 0)
1072 return NULL;
1074 mangled = endptr;
1075 if (*mangled != '_')
1076 return NULL;
1078 mangled++;
1079 string_append (decl, "\"");
1080 while (len--)
1082 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1084 char a = ascii2hex (mangled[0]);
1085 char b = ascii2hex (mangled[1]);
1086 char val = (a << 4) | b;
1088 /* Sanitize white and non-printable characters. */
1089 switch (val)
1091 case ' ':
1092 string_append (decl, " ");
1093 break;
1094 case '\t':
1095 string_append (decl, "\\t");
1096 break;
1097 case '\n':
1098 string_append (decl, "\\n");
1099 break;
1100 case '\r':
1101 string_append (decl, "\\r");
1102 break;
1103 case '\f':
1104 string_append (decl, "\\f");
1105 break;
1106 case '\v':
1107 string_append (decl, "\\v");
1108 break;
1110 default:
1111 if (ISPRINT (val))
1112 string_appendn (decl, &val, 1);
1113 else
1115 string_append (decl, "\\x");
1116 string_appendn (decl, mangled, 2);
1120 else
1121 return NULL;
1123 mangled += 2;
1125 string_append (decl, "\"");
1127 if (type != 'a')
1128 string_appendn (decl, &type, 1);
1130 return mangled;
1133 /* Extract the static array value from MANGLED and append it to DECL.
1134 Return the remaining string on success or NULL on failure. */
1135 static const char *
1136 dlang_parse_arrayliteral (string *decl, const char *mangled)
1138 char *endptr;
1139 long elements = strtol (mangled, &endptr, 10);
1141 if (endptr == NULL || elements < 0)
1142 return NULL;
1144 mangled = endptr;
1145 string_append (decl, "[");
1146 while (elements--)
1148 mangled = dlang_value (decl, mangled, NULL, '\0');
1149 if (elements != 0)
1150 string_append (decl, ", ");
1153 string_append (decl, "]");
1154 return mangled;
1157 /* Extract the associative 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_assocarray (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 string_append (decl, ":");
1174 mangled = dlang_value (decl, mangled, NULL, '\0');
1176 if (elements != 0)
1177 string_append (decl, ", ");
1180 string_append (decl, "]");
1181 return mangled;
1184 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1185 Return the remaining string on success or NULL on failure. */
1186 static const char *
1187 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1189 char *endptr;
1190 long args = strtol (mangled, &endptr, 10);
1192 if (endptr == NULL || args < 0)
1193 return NULL;
1195 mangled = endptr;
1196 if (name != NULL)
1197 string_append (decl, name);
1199 string_append (decl, "(");
1200 while (args--)
1202 mangled = dlang_value (decl, mangled, NULL, '\0');
1203 if (args != 0)
1204 string_append (decl, ", ");
1207 string_append (decl, ")");
1208 return mangled;
1211 /* Extract the value from MANGLED and append it to DECL.
1212 Return the remaining string on success or NULL on failure. */
1213 static const char *
1214 dlang_value (string *decl, const char *mangled, const char *name, char type)
1216 if (mangled == NULL || *mangled == '\0')
1217 return NULL;
1219 switch (*mangled)
1221 /* Null value. */
1222 case 'n':
1223 mangled++;
1224 string_append (decl, "null");
1225 break;
1227 /* Integral values. */
1228 case 'N':
1229 mangled++;
1230 string_append (decl, "-");
1231 mangled = dlang_parse_integer (decl, mangled, type);
1232 break;
1234 case 'i':
1235 mangled++;
1236 if (*mangled < '0' || *mangled > '9')
1237 return NULL;
1238 /* Fall through */
1239 case '0': case '1': case '2': case '3': case '4':
1240 case '5': case '6': case '7': case '8': case '9':
1241 mangled = dlang_parse_integer (decl, mangled, type);
1242 break;
1244 /* Real value. */
1245 case 'e':
1246 mangled++;
1247 mangled = dlang_parse_real (decl, mangled);
1248 break;
1250 /* Complex value. */
1251 case 'c':
1252 mangled++;
1253 mangled = dlang_parse_real (decl, mangled);
1254 string_append (decl, "+");
1255 if (mangled == NULL || *mangled != 'c')
1256 return NULL;
1257 mangled++;
1258 mangled = dlang_parse_real (decl, mangled);
1259 string_append (decl, "i");
1260 break;
1262 /* String values. */
1263 case 'a': /* UTF8 */
1264 case 'w': /* UTF16 */
1265 case 'd': /* UTF32 */
1266 mangled = dlang_parse_string (decl, mangled);
1267 break;
1269 /* Array values. */
1270 case 'A':
1271 mangled++;
1272 if (type == 'H')
1273 mangled = dlang_parse_assocarray (decl, mangled);
1274 else
1275 mangled = dlang_parse_arrayliteral (decl, mangled);
1276 break;
1278 /* Struct values. */
1279 case 'S':
1280 mangled++;
1281 mangled = dlang_parse_structlit (decl, mangled, name);
1282 break;
1284 default:
1285 return NULL;
1288 return mangled;
1291 /* Extract the type modifiers from MANGLED and return the string
1292 length that it consumes in MANGLED on success or 0 on failure. */
1293 static int
1294 dlang_type_modifier_p (const char *mangled)
1296 int i;
1298 switch (*mangled)
1300 case 'x': case 'y':
1301 return 1;
1303 case 'O':
1304 mangled++;
1305 i = dlang_type_modifier_p (mangled);
1306 return i + 1;
1308 case 'N':
1309 mangled++;
1310 if (*mangled == 'g')
1312 mangled++;
1313 i = dlang_type_modifier_p (mangled);
1314 return i + 2;
1318 return 0;
1321 /* Extract the function calling convention from MANGLED and
1322 return 1 on success or 0 on failure. */
1323 static int
1324 dlang_call_convention_p (const char *mangled)
1326 /* Prefix for functions needing 'this' */
1327 if (*mangled == 'M')
1329 mangled++;
1330 /* Also skip over any type modifiers. */
1331 mangled += dlang_type_modifier_p (mangled);
1334 switch (*mangled)
1336 case 'F': case 'U': case 'V':
1337 case 'W': case 'R':
1338 return 1;
1340 default:
1341 return 0;
1345 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1346 Returns the remaining signature on success or NULL on failure. */
1347 static const char *
1348 dlang_parse_symbol (string *decl, const char *mangled,
1349 enum dlang_symbol_kinds kind)
1351 int saved;
1352 size_t n = 0;
1355 if (n++)
1356 string_append (decl, ".");
1358 mangled = dlang_identifier (decl, mangled, kind);
1360 if (mangled && dlang_call_convention_p (mangled))
1362 string mods;
1363 const char *start = NULL;
1364 int checkpoint = 0;
1366 /* Skip over 'this' parameter. */
1367 if (*mangled == 'M')
1368 mangled++;
1370 /* We have reached here because we expect an extern(Pascal) function.
1371 However this is so rare, that it is more likely a template value
1372 parameter. Since this can't be assumed, first attempt parsing
1373 the symbol as a function, and then back out on failure. */
1374 if (*mangled == 'V')
1376 start = mangled;
1377 checkpoint = string_length (decl);
1380 /* Save the type modifiers for appending at the end. */
1381 string_init (&mods);
1382 mangled = dlang_type_modifiers (&mods, mangled);
1384 /* Skip over calling convention and attributes in qualified name. */
1385 saved = string_length (decl);
1386 mangled = dlang_call_convention (decl, mangled);
1387 mangled = dlang_attributes (decl, mangled);
1388 string_setlength (decl, saved);
1390 string_append (decl, "(");
1391 mangled = dlang_function_args (decl, mangled);
1392 string_append (decl, ")");
1394 /* Add any const/immutable/shared modifier. */
1395 string_appendn (decl, mods.b, string_length (&mods));
1396 string_delete (&mods);
1398 if (mangled == NULL && checkpoint != 0)
1400 mangled = start;
1401 string_setlength (decl, checkpoint);
1405 while (mangled && ISDIGIT (*mangled));
1407 /* Only top-level symbols or function template parameters have
1408 a type that needs checking. */
1409 if (kind == dlang_top_level || kind == dlang_function)
1411 /* Artificial symbols end with 'Z' and have no type. */
1412 if (mangled && *mangled == 'Z')
1413 mangled++;
1414 else
1416 saved = string_length (decl);
1417 mangled = dlang_type (decl, mangled);
1418 string_setlength (decl, saved);
1421 /* Check that the entire symbol was successfully demangled. */
1422 if (kind == dlang_top_level)
1424 if (mangled == NULL || *mangled != '\0')
1425 return NULL;
1429 return mangled;
1432 /* Demangle the tuple from MANGLED and append it to DECL.
1433 Return the remaining string on success or NULL on failure. */
1434 static const char *
1435 dlang_parse_tuple (string *decl, const char *mangled)
1437 char *endptr;
1438 long elements = strtol (mangled, &endptr, 10);
1440 if (endptr == NULL || elements < 0)
1441 return NULL;
1443 mangled = endptr;
1444 string_append (decl, "Tuple!(");
1446 while (elements--)
1448 mangled = dlang_type (decl, mangled);
1449 if (elements != 0)
1450 string_append (decl, ", ");
1453 string_append (decl, ")");
1454 return mangled;
1457 /* Demangle the argument list from MANGLED and append it to DECL.
1458 Return the remaining string on success or NULL on failure. */
1459 static const char *
1460 dlang_template_args (string *decl, const char *mangled)
1462 size_t n = 0;
1464 while (mangled && *mangled != '\0')
1466 switch (*mangled)
1468 case 'Z': /* End of parameter list. */
1469 mangled++;
1470 return mangled;
1473 if (n++)
1474 string_append (decl, ", ");
1476 /* Skip over specialised template prefix. */
1477 if (*mangled == 'H')
1478 mangled++;
1480 switch (*mangled)
1482 case 'S': /* Symbol parameter. */
1483 mangled++;
1484 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
1485 break;
1486 case 'T': /* Type parameter. */
1487 mangled++;
1488 mangled = dlang_type (decl, mangled);
1489 break;
1490 case 'V': /* Value parameter. */
1492 string name;
1493 char type;
1495 /* Peek at the type. */
1496 mangled++;
1497 type = *mangled;
1499 /* In the few instances where the type is actually desired in
1500 the output, it should precede the value from dlang_value. */
1501 string_init (&name);
1502 mangled = dlang_type (&name, mangled);
1503 string_need (&name, 1);
1504 *(name.p) = '\0';
1506 mangled = dlang_value (decl, mangled, name.b, type);
1507 string_delete (&name);
1508 break;
1511 default:
1512 return NULL;
1516 return mangled;
1519 /* Extract and demangle the template symbol in MANGLED, expected to
1520 be made up of LEN characters, and append it to DECL.
1521 Returns the remaining signature on success or NULL on failure. */
1522 static const char *
1523 dlang_parse_template (string *decl, const char *mangled, long len)
1525 const char *start = mangled;
1527 /* Template instance names have the types and values of its parameters
1528 encoded into it.
1530 TemplateInstanceName:
1531 Number __T LName TemplateArgs Z
1533 The start pointer should be at the above location, and LEN should be
1534 the value of the decoded number.
1536 if (strncmp (mangled, "__T", 3) != 0)
1537 return NULL;
1539 mangled += 3;
1541 /* Template identifier. */
1542 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1544 /* Template arguments. */
1545 string_append (decl, "!(");
1546 mangled = dlang_template_args (decl, mangled);
1547 string_append (decl, ")");
1549 /* Check for template name length mismatch. */
1550 if (mangled && (mangled - start) != len)
1551 return NULL;
1553 return mangled;
1556 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1557 signature on success or NULL on failure. */
1559 char *
1560 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1562 string decl;
1563 char *demangled = NULL;
1565 if (mangled == NULL || *mangled == '\0')
1566 return NULL;
1568 if (strncmp (mangled, "_D", 2) != 0)
1569 return NULL;
1571 string_init (&decl);
1573 if (strcmp (mangled, "_Dmain") == 0)
1575 string_append (&decl, "D main");
1577 else
1579 mangled += 2;
1581 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
1582 string_delete (&decl);
1585 if (string_length (&decl) > 0)
1587 string_need (&decl, 1);
1588 *(decl.p) = '\0';
1589 demangled = decl.b;
1592 return demangled;