2015-01-07 Sandra Loosemore <sandra@codesourcery.com>
[official-gcc.git] / libiberty / d-demangle.c
blobbb481c0998e851b6c3fe6ad7610e00c92a0ea658
1 /* Demangler for the D programming language
2 Copyright 2014 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 /* Prototypes for forward referenced functions */
169 static const char *dlang_function_args (string *, const char *);
171 static const char *dlang_type (string *, const char *);
173 static const char *dlang_value (string *, const char *, const char *, char);
175 static const char *dlang_parse_symbol (string *, const char *);
177 static const char *dlang_parse_tuple (string *, const char *);
179 static const char *dlang_parse_template (string *, const char *, long);
182 /* Demangle the calling convention from MANGLED and append it to DECL.
183 Return the remaining string on success or NULL on failure. */
184 static const char *
185 dlang_call_convention (string *decl, const char *mangled)
187 if (mangled == NULL || *mangled == '\0')
188 return mangled;
190 switch (*mangled)
192 case 'F': /* (D) */
193 mangled++;
194 break;
195 case 'U': /* (C) */
196 mangled++;
197 string_append (decl, "extern(C) ");
198 break;
199 case 'W': /* (Windows) */
200 mangled++;
201 string_append (decl, "extern(Windows) ");
202 break;
203 case 'V': /* (Pascal) */
204 mangled++;
205 string_append (decl, "extern(Pascal) ");
206 break;
207 case 'R': /* (C++) */
208 mangled++;
209 string_append (decl, "extern(C++) ");
210 break;
211 default:
212 return NULL;
215 return mangled;
218 /* Demangle the D function attributes from MANGLED and append it to DECL.
219 Return the remaining string on success or NULL on failure. */
220 static const char *
221 dlang_attributes (string *decl, const char *mangled)
223 if (mangled == NULL || *mangled == '\0')
224 return mangled;
226 while (*mangled == 'N')
228 mangled++;
229 switch (*mangled)
231 case 'a': /* pure */
232 mangled++;
233 string_append (decl, "pure ");
234 continue;
235 case 'b': /* nothrow */
236 mangled++;
237 string_append (decl, "nothrow ");
238 continue;
239 case 'c': /* ref */
240 mangled++;
241 string_append (decl, "ref ");
242 continue;
243 case 'd': /* @property */
244 mangled++;
245 string_append (decl, "@property ");
246 continue;
247 case 'e': /* @trusted */
248 mangled++;
249 string_append (decl, "@trusted ");
250 continue;
251 case 'f': /* @safe */
252 mangled++;
253 string_append (decl, "@safe ");
254 continue;
255 case 'g':
256 case 'h':
257 /* inout parameter is represented as 'Ng'.
258 vector parameter is represented as 'Nh'.
259 If we see this, then we know we're really in the
260 parameter list. Rewind and break. */
261 mangled--;
262 break;
263 case 'i': /* @nogc */
264 mangled++;
265 string_append (decl, "@nogc ");
266 continue;
268 break;
271 return mangled;
274 /* Demangle the function type from MANGLED and append it to DECL.
275 Return the remaining string on success or NULL on failure. */
276 static const char *
277 dlang_function_type (string *decl, const char *mangled)
279 string attr, args, type;
280 size_t szattr, szargs, sztype;
282 if (mangled == NULL || *mangled == '\0')
283 return mangled;
285 /* The order of the mangled string is:
286 CallConvention FuncAttrs Arguments ArgClose Type
288 The demangled string is re-ordered as:
289 CallConvention Type Arguments FuncAttrs
291 string_init (&attr);
292 string_init (&args);
293 string_init (&type);
295 /* Function call convention. */
296 mangled = dlang_call_convention (decl, mangled);
298 /* Function attributes. */
299 mangled = dlang_attributes (&attr, mangled);
300 szattr = string_length (&attr);
302 /* Function arguments. */
303 mangled = dlang_function_args (&args, mangled);
304 szargs = string_length (&args);
306 /* Function return type. */
307 mangled = dlang_type (&type, mangled);
308 sztype = string_length (&type);
310 /* Append to decl in order. */
311 string_appendn (decl, type.b, sztype);
312 string_append (decl, "(");
313 string_appendn (decl, args.b, szargs);
314 string_append (decl, ") ");
315 string_appendn (decl, attr.b, szattr);
317 string_delete (&attr);
318 string_delete (&args);
319 string_delete (&type);
320 return mangled;
323 /* Demangle the argument list from MANGLED and append it to DECL.
324 Return the remaining string on success or NULL on failure. */
325 static const char *
326 dlang_function_args (string *decl, const char *mangled)
328 size_t n = 0;
330 while (mangled && *mangled != '\0')
332 switch (*mangled)
334 case 'X': /* (variadic T t...) style. */
335 mangled++;
336 string_append (decl, "...");
337 return mangled;
338 case 'Y': /* (variadic T t, ...) style. */
339 mangled++;
340 string_append (decl, ", ...");
341 return mangled;
342 case 'Z': /* Normal function. */
343 mangled++;
344 return mangled;
347 if (n++)
348 string_append (decl, ", ");
350 if (*mangled == 'M') /* scope(T) */
352 mangled++;
353 string_append (decl, "scope ");
356 switch (*mangled)
358 case 'J': /* out(T) */
359 mangled++;
360 string_append (decl, "out ");
361 break;
362 case 'K': /* ref(T) */
363 mangled++;
364 string_append (decl, "ref ");
365 break;
366 case 'L': /* lazy(T) */
367 mangled++;
368 string_append (decl, "lazy ");
369 break;
371 mangled = dlang_type (decl, mangled);
374 return mangled;
377 /* Demangle the type from MANGLED and append it to DECL.
378 Return the remaining string on success or NULL on failure. */
379 static const char *
380 dlang_type (string *decl, const char *mangled)
382 if (mangled == NULL || *mangled == '\0')
383 return mangled;
385 switch (*mangled)
387 case 'O': /* shared(T) */
388 mangled++;
389 string_append (decl, "shared(");
390 mangled = dlang_type (decl, mangled);
391 string_append (decl, ")");
392 return mangled;
393 case 'x': /* const(T) */
394 mangled++;
395 string_append (decl, "const(");
396 mangled = dlang_type (decl, mangled);
397 string_append (decl, ")");
398 return mangled;
399 case 'y': /* immutable(T) */
400 mangled++;
401 string_append (decl, "immutable(");
402 mangled = dlang_type (decl, mangled);
403 string_append (decl, ")");
404 return mangled;
405 case 'N':
406 mangled++;
407 if (*mangled == 'g') /* wild(T) */
409 mangled++;
410 string_append (decl, "inout(");
411 mangled = dlang_type (decl, mangled);
412 string_append (decl, ")");
413 return mangled;
415 else if (*mangled == 'h') /* vector(T) */
417 mangled++;
418 string_append (decl, "__vector(");
419 mangled = dlang_type (decl, mangled);
420 string_append (decl, ")");
421 return mangled;
423 else
424 return NULL;
425 case 'A': /* dynamic array (T[]) */
426 mangled++;
427 mangled = dlang_type (decl, mangled);
428 string_append (decl, "[]");
429 return mangled;
430 case 'G': /* static array (T[N]) */
432 const char *numptr;
433 size_t num = 0;
434 mangled++;
436 numptr = mangled;
437 while (ISDIGIT (*mangled))
439 num++;
440 mangled++;
442 mangled = dlang_type (decl, mangled);
443 string_append (decl, "[");
444 string_appendn (decl, numptr, num);
445 string_append (decl, "]");
446 return mangled;
448 case 'H': /* associative array (T[T]) */
450 string type;
451 size_t sztype;
452 mangled++;
454 string_init (&type);
455 mangled = dlang_type (&type, mangled);
456 sztype = string_length (&type);
458 mangled = dlang_type (decl, mangled);
459 string_append (decl, "[");
460 string_appendn (decl, type.b, sztype);
461 string_append (decl, "]");
463 string_delete (&type);
464 return mangled;
466 case 'P': /* pointer (T*) */
467 mangled++;
468 mangled = dlang_type (decl, mangled);
469 string_append (decl, "*");
470 return mangled;
471 case 'I': /* ident T */
472 case 'C': /* class T */
473 case 'S': /* struct T */
474 case 'E': /* enum T */
475 case 'T': /* typedef T */
476 mangled++;
477 return dlang_parse_symbol (decl, mangled);
478 case 'D': /* delegate T */
479 mangled++;
480 mangled = dlang_function_type (decl, mangled);
481 string_append (decl, "delegate");
482 return mangled;
483 case 'B': /* tuple T */
484 mangled++;
485 return dlang_parse_tuple (decl, mangled);
487 /* Function types */
488 case 'F': case 'U': case 'W':
489 case 'V': case 'R':
490 mangled = dlang_function_type (decl, mangled);
491 string_append (decl, "function");
492 return mangled;
494 /* Basic types */
495 case 'n':
496 mangled++;
497 string_append (decl, "none");
498 return mangled;
499 case 'v':
500 mangled++;
501 string_append (decl, "void");
502 return mangled;
503 case 'g':
504 mangled++;
505 string_append (decl, "byte");
506 return mangled;
507 case 'h':
508 mangled++;
509 string_append (decl, "ubyte");
510 return mangled;
511 case 's':
512 mangled++;
513 string_append (decl, "short");
514 return mangled;
515 case 't':
516 mangled++;
517 string_append (decl, "ushort");
518 return mangled;
519 case 'i':
520 mangled++;
521 string_append (decl, "int");
522 return mangled;
523 case 'k':
524 mangled++;
525 string_append (decl, "uint");
526 return mangled;
527 case 'l':
528 mangled++;
529 string_append (decl, "long");
530 return mangled;
531 case 'm':
532 mangled++;
533 string_append (decl, "ulong");
534 return mangled;
535 case 'f':
536 mangled++;
537 string_append (decl, "float");
538 return mangled;
539 case 'd':
540 mangled++;
541 string_append (decl, "double");
542 return mangled;
543 case 'e':
544 mangled++;
545 string_append (decl, "real");
546 return mangled;
548 /* Imaginary and Complex types */
549 case 'o':
550 mangled++;
551 string_append (decl, "ifloat");
552 return mangled;
553 case 'p':
554 mangled++;
555 string_append (decl, "idouble");
556 return mangled;
557 case 'j':
558 mangled++;
559 string_append (decl, "ireal");
560 return mangled;
561 case 'q':
562 mangled++;
563 string_append (decl, "cfloat");
564 return mangled;
565 case 'r':
566 mangled++;
567 string_append (decl, "cdouble");
568 return mangled;
569 case 'c':
570 mangled++;
571 string_append (decl, "creal");
572 return mangled;
574 /* Other types */
575 case 'b':
576 mangled++;
577 string_append (decl, "bool");
578 return mangled;
579 case 'a':
580 mangled++;
581 string_append (decl, "char");
582 return mangled;
583 case 'u':
584 mangled++;
585 string_append (decl, "wchar");
586 return mangled;
587 case 'w':
588 mangled++;
589 string_append (decl, "dchar");
590 return mangled;
592 default: /* unhandled */
593 return NULL;
597 /* Extract the identifier from MANGLED and append it to DECL.
598 Return the remaining string on success or NULL on failure. */
599 static const char *
600 dlang_identifier (string *decl, const char *mangled)
602 if (mangled == NULL || *mangled == '\0')
603 return mangled;
605 if (ISDIGIT (*mangled))
607 char *endptr;
608 long i = strtol (mangled, &endptr, 10);
610 if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
611 return NULL;
613 mangled = endptr;
615 /* May be a template instance. */
616 if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
618 /* Template symbol. */
619 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
620 return dlang_parse_template (decl, mangled, i);
622 return NULL;
625 if (strncmp (mangled, "__ctor", i) == 0)
627 /* Constructor symbol for a class/struct. */
628 string_append (decl, "this");
629 mangled += i;
630 return mangled;
632 else if (strncmp (mangled, "__dtor", i) == 0)
634 /* Destructor symbol for a class/struct. */
635 string_append (decl, "~this");
636 mangled += i;
637 return mangled;
639 else if (strncmp (mangled, "__postblit", i) == 0)
641 /* Postblit symbol for a struct. */
642 string_append (decl, "this(this)");
643 mangled += i;
644 return mangled;
646 else if (strncmp (mangled, "__initZ", i+1) == 0)
648 /* The static initialiser for a given symbol. */
649 string_append (decl, "init$");
650 mangled += i + 1;
651 return mangled;
653 else if (strncmp (mangled, "__ClassZ", i+1) == 0)
655 /* The classinfo symbol for a given class. */
656 string_prepend (decl, "ClassInfo for ");
657 string_setlength (decl, string_length (decl) - 1);
658 mangled += i + 1;
659 return mangled;
661 else if (strncmp (mangled, "__vtblZ", i+1) == 0)
663 /* The vtable symbol for a given class. */
664 string_prepend (decl, "vtable for ");
665 string_setlength (decl, string_length (decl) - 1);
666 mangled += i + 1;
667 return mangled;
669 else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
671 /* The interface symbol for a given class. */
672 string_prepend (decl, "Interface for ");
673 string_setlength (decl, string_length (decl) - 1);
674 mangled += i + 1;
675 return mangled;
677 else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
679 /* The ModuleInfo symbol for a given module. */
680 string_prepend (decl, "ModuleInfo for ");
681 string_setlength (decl, string_length (decl) - 1);
682 mangled += i + 1;
683 return mangled;
686 string_appendn (decl, mangled, i);
687 mangled += i;
689 else
690 return NULL;
692 return mangled;
695 /* Extract the integer value from MANGLED and append it to DECL,
696 where TYPE is the type it should be represented as.
697 Return the remaining string on success or NULL on failure. */
698 static const char *
699 dlang_parse_integer (string *decl, const char *mangled, char type)
701 if (type == 'a' || type == 'u' || type == 'w')
703 /* Parse character value. */
704 char value[10];
705 int pos = 10;
706 int width = 0;
707 char *endptr;
708 long val = strtol (mangled, &endptr, 10);
710 if (endptr == NULL || val < 0)
711 return NULL;
713 string_append (decl, "'");
715 if (type == 'a' && val >= 0x20 && val < 0x7F)
717 /* Represent as a character literal. */
718 char c = (char) val;
719 string_appendn (decl, &c, 1);
721 else
723 /* Represent as a hexadecimal value. */
724 switch (type)
726 case 'a': /* char */
727 string_append (decl, "\\x");
728 width = 2;
729 break;
730 case 'u': /* wchar */
731 string_append (decl, "\\u");
732 width = 4;
733 break;
734 case 'w': /* dchar */
735 string_append (decl, "\\U");
736 width = 8;
737 break;
740 while (val > 0)
742 int digit = val % 16;
744 if (digit < 10)
745 value[--pos] = (char)(digit + '0');
746 else
747 value[--pos] = (char)((digit - 10) + 'a');
749 val /= 16;
750 width--;
753 for (; width > 0; width--)
754 value[--pos] = '0';
756 string_appendn (decl, &(value[pos]), 10 - pos);
758 string_append (decl, "'");
759 mangled = endptr;
761 else if (type == 'b')
763 /* Parse boolean value. */
764 char *endptr;
765 long val = strtol (mangled, &endptr, 10);
767 if (endptr == NULL || val < 0)
768 return NULL;
770 string_append (decl, val ? "true" : "false");
771 mangled = endptr;
773 else
775 /* Parse integer value. */
776 const char *numptr = mangled;
777 size_t num = 0;
779 while (ISDIGIT (*mangled))
781 num++;
782 mangled++;
784 string_appendn (decl, numptr, num);
786 /* Append suffix. */
787 switch (type)
789 case 'h': /* ubyte */
790 case 't': /* ushort */
791 case 'k': /* uint */
792 string_append (decl, "u");
793 break;
794 case 'l': /* long */
795 string_append (decl, "L");
796 break;
797 case 'm': /* ulong */
798 string_append (decl, "uL");
799 break;
803 return mangled;
806 /* Extract the floating-point value from MANGLED and append it to DECL.
807 Return the remaining string on success or NULL on failure. */
808 static const char *
809 dlang_parse_real (string *decl, const char *mangled)
811 char buffer[64];
812 int len = 0;
813 double value;
814 char *endptr;
816 /* Handle NAN and +-INF. */
817 if (strncmp (mangled, "NAN", 3) == 0)
819 string_append (decl, "NaN");
820 mangled += 3;
821 return mangled;
823 else if (strncmp (mangled, "INF", 3) == 0)
825 string_append (decl, "Inf");
826 mangled += 3;
827 return mangled;
829 else if (strncmp (mangled, "NINF", 4) == 0)
831 string_append (decl, "-Inf");
832 mangled += 4;
833 return mangled;
836 /* Hexadecimal prefix and leading bit. */
837 if (*mangled == 'N')
839 buffer[len++] = '-';
840 mangled++;
843 if (!ISXDIGIT (*mangled))
844 return NULL;
846 buffer[len++] = '0';
847 buffer[len++] = 'x';
848 buffer[len++] = *mangled;
849 buffer[len++] = '.';
850 mangled++;
852 /* Significand. */
853 while (ISXDIGIT (*mangled))
855 buffer[len++] = *mangled;
856 mangled++;
859 /* Exponent. */
860 if (*mangled != 'P')
861 return NULL;
863 buffer[len++] = 'p';
864 mangled++;
866 if (*mangled == 'N')
868 buffer[len++] = '-';
869 mangled++;
872 while (ISDIGIT (*mangled))
874 buffer[len++] = *mangled;
875 mangled++;
878 /* Convert buffer from hexadecimal to floating-point. */
879 buffer[len] = '\0';
880 value = strtod (buffer, &endptr);
882 if (endptr == NULL || endptr != (buffer + len))
883 return NULL;
885 len = snprintf (buffer, sizeof(buffer), "%#g", value);
886 string_appendn (decl, buffer, len);
887 return mangled;
890 /* Convert VAL from an ascii hexdigit to value. */
891 static char
892 ascii2hex (char val)
894 if (val >= 'a' && val <= 'f')
895 return (val - 'a' + 10);
897 if (val >= 'A' && val <= 'F')
898 return (val - 'A' + 10);
900 if (val >= '0' && val <= '9')
901 return (val - '0');
903 return 0;
906 /* Extract the string value from MANGLED and append it to DECL.
907 Return the remaining string on success or NULL on failure. */
908 static const char *
909 dlang_parse_string (string *decl, const char *mangled)
911 char type = *mangled;
912 char *endptr;
913 long len;
915 mangled++;
916 len = strtol (mangled, &endptr, 10);
918 if (endptr == NULL || len < 0)
919 return NULL;
921 mangled = endptr;
922 if (*mangled != '_')
923 return NULL;
925 mangled++;
926 string_append (decl, "\"");
927 while (len--)
929 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
931 char a = ascii2hex (mangled[0]);
932 char b = ascii2hex (mangled[1]);
933 char val = (a << 4) | b;
934 string_appendn (decl, &val, 1);
936 else
937 return NULL;
939 mangled += 2;
941 string_append (decl, "\"");
943 if (type != 'a')
944 string_appendn (decl, &type, 1);
946 return mangled;
949 /* Extract the static array value from MANGLED and append it to DECL.
950 Return the remaining string on success or NULL on failure. */
951 static const char *
952 dlang_parse_arrayliteral (string *decl, const char *mangled)
954 char *endptr;
955 long elements = strtol (mangled, &endptr, 10);
957 if (endptr == NULL || elements < 0)
958 return NULL;
960 mangled = endptr;
961 string_append (decl, "[");
962 while (elements--)
964 mangled = dlang_value (decl, mangled, NULL, '\0');
965 if (elements != 0)
966 string_append (decl, ", ");
969 string_append (decl, "]");
970 return mangled;
973 /* Extract the associative array 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_assocarray (string *decl, const char *mangled)
978 char *endptr;
979 long elements = strtol (mangled, &endptr, 10);
981 if (endptr == NULL || elements < 0)
982 return NULL;
984 mangled = endptr;
985 string_append (decl, "[");
986 while (elements--)
988 mangled = dlang_value (decl, mangled, NULL, '\0');
989 string_append (decl, ":");
990 mangled = dlang_value (decl, mangled, NULL, '\0');
992 if (elements != 0)
993 string_append (decl, ", ");
996 string_append (decl, "]");
997 return mangled;
1000 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1001 Return the remaining string on success or NULL on failure. */
1002 static const char *
1003 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1005 char *endptr;
1006 long args = strtol (mangled, &endptr, 10);
1008 if (endptr == NULL || args < 0)
1009 return NULL;
1011 mangled = endptr;
1012 if (name != NULL)
1013 string_append (decl, name);
1015 string_append (decl, "(");
1016 while (args--)
1018 mangled = dlang_value (decl, mangled, NULL, '\0');
1019 if (args != 0)
1020 string_append (decl, ", ");
1023 string_append (decl, ")");
1024 return mangled;
1027 /* Extract the value from MANGLED and append it to DECL.
1028 Return the remaining string on success or NULL on failure. */
1029 static const char *
1030 dlang_value (string *decl, const char *mangled, const char *name, char type)
1032 if (mangled == NULL || *mangled == '\0')
1033 return mangled;
1035 switch (*mangled)
1037 /* Null value. */
1038 case 'n':
1039 mangled++;
1040 string_append (decl, "null");
1041 break;
1043 /* Integral values. */
1044 case 'N':
1045 mangled++;
1046 string_append (decl, "-");
1047 mangled = dlang_parse_integer (decl, mangled, type);
1048 break;
1050 case 'i':
1051 mangled++;
1052 if (*mangled < '0' || *mangled > '9')
1053 return NULL;
1054 /* Fall through */
1055 case '0': case '1': case '2': case '3': case '4':
1056 case '5': case '6': case '7': case '8': case '9':
1057 mangled = dlang_parse_integer (decl, mangled, type);
1058 break;
1060 /* Real value. */
1061 case 'e':
1062 mangled++;
1063 mangled = dlang_parse_real (decl, mangled);
1064 break;
1066 /* Complex value. */
1067 case 'c':
1068 mangled++;
1069 mangled = dlang_parse_real (decl, mangled);
1070 string_append (decl, "+");
1071 if (mangled == NULL || *mangled != 'c')
1072 return NULL;
1073 mangled++;
1074 mangled = dlang_parse_real (decl, mangled);
1075 string_append (decl, "i");
1076 break;
1078 /* String values. */
1079 case 'a': /* UTF8 */
1080 case 'w': /* UTF16 */
1081 case 'd': /* UTF32 */
1082 mangled = dlang_parse_string (decl, mangled);
1083 break;
1085 /* Array values. */
1086 case 'A':
1087 mangled++;
1088 if (type == 'H')
1089 mangled = dlang_parse_assocarray (decl, mangled);
1090 else
1091 mangled = dlang_parse_arrayliteral (decl, mangled);
1092 break;
1094 /* Struct values. */
1095 case 'S':
1096 mangled++;
1097 mangled = dlang_parse_structlit (decl, mangled, name);
1098 break;
1100 default:
1101 return NULL;
1104 return mangled;
1107 static int
1108 dlang_call_convention_p (const char *mangled)
1110 size_t i;
1112 switch (*mangled)
1114 case 'F': case 'U': case 'V':
1115 case 'W': case 'R':
1116 return 1;
1118 case 'M': /* Prefix for functions needing 'this' */
1119 i = 1;
1120 if (mangled[i] == 'x')
1121 i++;
1123 switch (mangled[i])
1125 case 'F': case 'U': case 'V':
1126 case 'W': case 'R':
1127 return 1;
1130 default:
1131 return 0;
1135 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1136 Returns the remaining signature on success or NULL on failure. */
1137 static const char *
1138 dlang_parse_symbol (string *decl, const char *mangled)
1140 size_t n = 0;
1143 if (n++)
1144 string_append (decl, ".");
1146 mangled = dlang_identifier (decl, mangled);
1148 if (mangled && dlang_call_convention_p (mangled))
1150 int saved;
1152 /* Skip over 'this' parameter. */
1153 if (*mangled == 'M')
1154 mangled += (mangled[1] == 'x') ? 2 : 1;
1156 /* Skip over calling convention and attributes in qualified name. */
1157 saved = string_length (decl);
1158 mangled = dlang_call_convention (decl, mangled);
1159 mangled = dlang_attributes (decl, mangled);
1160 string_setlength (decl, saved);
1162 string_append (decl, "(");
1163 mangled = dlang_function_args (decl, mangled);
1164 string_append (decl, ")");
1166 /* Demangle the function return type as a kind of sanity test. */
1167 if (mangled && !ISDIGIT (*mangled))
1169 saved = string_length (decl);
1170 mangled = dlang_type (decl, mangled);
1171 string_setlength (decl, saved);
1175 while (mangled && ISDIGIT (*mangled));
1177 return mangled;
1180 /* Demangle the tuple from MANGLED and append it to DECL.
1181 Return the remaining string on success or NULL on failure. */
1182 static const char *
1183 dlang_parse_tuple (string *decl, const char *mangled)
1185 char *endptr;
1186 long elements = strtol (mangled, &endptr, 10);
1188 if (endptr == NULL || elements < 0)
1189 return NULL;
1191 mangled = endptr;
1192 string_append (decl, "Tuple!(");
1194 while (elements--)
1196 mangled = dlang_type (decl, mangled);
1197 if (elements != 0)
1198 string_append (decl, ", ");
1201 string_append (decl, ")");
1202 return mangled;
1205 /* Demangle the argument list from MANGLED and append it to DECL.
1206 Return the remaining string on success or NULL on failure. */
1207 static const char *
1208 dlang_template_args (string *decl, const char *mangled)
1210 size_t n = 0;
1212 while (mangled && *mangled != '\0')
1214 switch (*mangled)
1216 case 'Z': /* End of parameter list. */
1217 mangled++;
1218 return mangled;
1221 if (n++)
1222 string_append (decl, ", ");
1224 switch (*mangled)
1226 case 'S': /* Symbol parameter. */
1227 mangled++;
1228 mangled = dlang_parse_symbol (decl, mangled);
1229 break;
1230 case 'T': /* Type parameter. */
1231 mangled++;
1232 mangled = dlang_type (decl, mangled);
1233 break;
1234 case 'V': /* Value parameter. */
1236 string name;
1237 char type;
1239 /* Peek at the type. */
1240 mangled++;
1241 type = *mangled;
1243 /* In the few instances where the type is actually desired in
1244 the output, it should precede the value from dlang_value. */
1245 string_init (&name);
1246 mangled = dlang_type (&name, mangled);
1247 string_need (&name, 1);
1248 *(name.p) = '\0';
1250 mangled = dlang_value (decl, mangled, name.b, type);
1251 string_delete (&name);
1252 break;
1255 default:
1256 return NULL;
1260 return mangled;
1263 /* Extract and demangle the template symbol in MANGLED, expected to
1264 be made up of LEN characters, and append it to DECL.
1265 Returns the remaining signature on success or NULL on failure. */
1266 static const char *
1267 dlang_parse_template (string *decl, const char *mangled, long len)
1269 const char *start = mangled;
1271 /* Template instance names have the types and values of its parameters
1272 encoded into it.
1274 TemplateInstanceName:
1275 Number __T LName TemplateArgs Z
1277 The start pointer should be at the above location, and LEN should be
1278 the value of the decoded number.
1280 if (strncmp (mangled, "__T", 3) != 0)
1281 return NULL;
1283 mangled += 3;
1285 /* Template identifier. */
1286 mangled = dlang_identifier (decl, mangled);
1288 /* Template arguments. */
1289 string_append (decl, "!(");
1290 mangled = dlang_template_args (decl, mangled);
1291 string_append (decl, ")");
1293 /* Check for template name length mismatch. */
1294 if (mangled && (mangled - start) != len)
1295 return NULL;
1297 return mangled;
1300 /* Extract and demangle the symbol in MANGLED. Returns the demangled
1301 signature on success or NULL on failure. */
1303 char *
1304 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1306 string decl;
1307 char *demangled = NULL;
1309 if (mangled == NULL || *mangled == '\0')
1310 return NULL;
1312 if (strncmp (mangled, "_D", 2) != 0)
1313 return NULL;
1315 string_init (&decl);
1317 if (strcmp (mangled, "_Dmain") == 0)
1319 string_append (&decl, "D main");
1321 else
1323 mangled += 2;
1325 if (dlang_parse_symbol (&decl, mangled) == NULL)
1326 string_delete (&decl);
1329 if (string_length (&decl) > 0)
1331 string_need (&decl, 1);
1332 *(decl.p) = '\0';
1333 demangled = decl.b;
1336 return demangled;