]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
d-demangle.c (dlang_type): Handle cent and ucent types.
[thirdparty/gcc.git] / libiberty / d-demangle.c
CommitLineData
43b1b9ed 1/* Demangler for the D programming language
eb058b7d 2 Copyright 2014, 2015 Free Software Foundation, Inc.
43b1b9ed
IB
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11In addition to the permissions in the GNU Library General Public
12License, the Free Software Foundation gives you unlimited permission
13to link the compiled version of this file into combinations with other
14programs, and to distribute those combinations without any restriction
15coming from the use of this file. (The Library Public License
16restrictions do apply in other respects; for example, they cover
17modification of the file, and distribution when not linked into a
18combined executable.)
19
20Libiberty is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23Library General Public License for more details.
24
25You should have received a copy of the GNU Library General Public
26License along with libiberty; see the file COPYING.LIB.
27If not, see <http://www.gnu.org/licenses/>. */
28
29/* This file exports one function; dlang_demangle.
30
2a523cfe 31 This file imports strtol and strtod for decoding mangled literals. */
43b1b9ed
IB
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif
36
37#include "safe-ctype.h"
38
39#include <sys/types.h>
40#include <string.h>
41#include <stdio.h>
42
43#ifdef HAVE_STDLIB_H
44#include <stdlib.h>
45#else
46extern long strtol (const char *nptr, char **endptr, int base);
2a523cfe 47extern double strtod (const char *nptr, char **endptr);
43b1b9ed
IB
48#endif
49
50#include <demangle.h>
51#include "libiberty.h"
52
53/* A mini string-handling package */
54
55typedef 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;
61
62static void
63string_need (string *s, int n)
64{
65 int tem;
66
67 if (s->b == NULL)
68 {
69 if (n < 32)
70 {
71 n = 32;
72 }
73 s->p = s->b = XNEWVEC (char, n);
74 s->e = s->b + n;
75 }
76 else if (s->e - s->p < n)
77 {
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;
84 }
85}
86
87static void
88string_delete (string *s)
89{
90 if (s->b != NULL)
91 {
92 XDELETEVEC (s->b);
93 s->b = s->e = s->p = NULL;
94 }
95}
96
97static void
98string_init (string *s)
99{
100 s->b = s->p = s->e = NULL;
101}
102
103static int
104string_length (string *s)
105{
106 if (s->p == s->b)
107 {
108 return 0;
109 }
110 return s->p - s->b;
111}
112
113static void
114string_setlength (string *s, int n)
115{
116 if (n - string_length (s) < 0)
117 {
118 s->p = s->b + n;
119 }
120}
121
122static void
123string_append (string *p, const char *s)
124{
125 int n = strlen (s);
126 string_need (p, n);
127 memcpy (p->p, s, n);
128 p->p += n;
129}
130
131static void
132string_appendn (string *p, const char *s, int n)
133{
134 if (n != 0)
135 {
136 string_need (p, n);
137 memcpy (p->p, s, n);
138 p->p += n;
139 }
140}
141
142static void
143string_prependn (string *p, const char *s, int n)
144{
145 char *q;
146
147 if (n != 0)
148 {
149 string_need (p, n);
150 for (q = p->p - 1; q >= p->b; q--)
151 {
152 q[n] = q[0];
153 }
154 memcpy (p->b, s, n);
155 p->p += n;
156 }
157}
158
159static void
160string_prepend (string *p, const char *s)
161{
162 if (s != NULL && *s != '\0')
163 {
164 string_prependn (p, s, strlen (s));
165 }
166}
167
168/* Prototypes for forward referenced functions */
169static const char *dlang_function_args (string *, const char *);
170
171static const char *dlang_type (string *, const char *);
172
173static const char *dlang_value (string *, const char *, const char *, char);
174
175static const char *dlang_parse_symbol (string *, const char *);
176
177static const char *dlang_parse_tuple (string *, const char *);
178
179static const char *dlang_parse_template (string *, const char *, long);
180
181
182/* Demangle the calling convention from MANGLED and append it to DECL.
183 Return the remaining string on success or NULL on failure. */
184static const char *
185dlang_call_convention (string *decl, const char *mangled)
186{
187 if (mangled == NULL || *mangled == '\0')
76b41cad 188 return NULL;
43b1b9ed
IB
189
190 switch (*mangled)
191 {
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;
213 }
214
215 return mangled;
216}
217
fa66ced4
IB
218/* Extract the type modifiers from MANGLED and append them to DECL.
219 Returns the remaining signature on success or NULL on failure. */
220static const char *
221dlang_type_modifiers (string *decl, const char *mangled)
222{
223 if (mangled == NULL || *mangled == '\0')
224 return NULL;
225
226 switch (*mangled)
227 {
228 case 'x': /* const */
229 mangled++;
230 string_append (decl, " const");
231 return mangled;
232 case 'y': /* immutable */
233 mangled++;
234 string_append (decl, " immutable");
235 return mangled;
236 case 'O': /* shared */
237 mangled++;
238 string_append (decl, " shared");
239 return dlang_type_modifiers (decl, mangled);
240 case 'N':
241 mangled++;
242 if (*mangled == 'g') /* wild */
243 {
244 mangled++;
245 string_append (decl, " inout");
246 return dlang_type_modifiers (decl, mangled);
247 }
248 else
249 return NULL;
250
251 default:
252 return mangled;
253 }
254}
255
43b1b9ed
IB
256/* Demangle the D function attributes from MANGLED and append it to DECL.
257 Return the remaining string on success or NULL on failure. */
258static const char *
259dlang_attributes (string *decl, const char *mangled)
260{
261 if (mangled == NULL || *mangled == '\0')
76b41cad 262 return NULL;
43b1b9ed
IB
263
264 while (*mangled == 'N')
265 {
266 mangled++;
267 switch (*mangled)
268 {
269 case 'a': /* pure */
270 mangled++;
271 string_append (decl, "pure ");
272 continue;
273 case 'b': /* nothrow */
274 mangled++;
275 string_append (decl, "nothrow ");
276 continue;
277 case 'c': /* ref */
278 mangled++;
279 string_append (decl, "ref ");
280 continue;
281 case 'd': /* @property */
282 mangled++;
283 string_append (decl, "@property ");
284 continue;
285 case 'e': /* @trusted */
286 mangled++;
287 string_append (decl, "@trusted ");
288 continue;
289 case 'f': /* @safe */
290 mangled++;
291 string_append (decl, "@safe ");
292 continue;
293 case 'g':
294 case 'h':
7ce4461f 295 case 'k':
43b1b9ed
IB
296 /* inout parameter is represented as 'Ng'.
297 vector parameter is represented as 'Nh'.
7ce4461f 298 return paramenter is represented as 'Nk'.
43b1b9ed
IB
299 If we see this, then we know we're really in the
300 parameter list. Rewind and break. */
301 mangled--;
302 break;
303 case 'i': /* @nogc */
304 mangled++;
305 string_append (decl, "@nogc ");
306 continue;
7ce4461f
IB
307 case 'j': /* return */
308 mangled++;
309 string_append (decl, "return ");
310 continue;
311
312 default: /* unknown attribute */
313 return NULL;
43b1b9ed
IB
314 }
315 break;
316 }
317
318 return mangled;
319}
320
321/* Demangle the function type from MANGLED and append it to DECL.
322 Return the remaining string on success or NULL on failure. */
323static const char *
324dlang_function_type (string *decl, const char *mangled)
325{
326 string attr, args, type;
327 size_t szattr, szargs, sztype;
328
329 if (mangled == NULL || *mangled == '\0')
76b41cad 330 return NULL;
43b1b9ed
IB
331
332 /* The order of the mangled string is:
333 CallConvention FuncAttrs Arguments ArgClose Type
334
335 The demangled string is re-ordered as:
336 CallConvention Type Arguments FuncAttrs
337 */
338 string_init (&attr);
339 string_init (&args);
340 string_init (&type);
341
342 /* Function call convention. */
343 mangled = dlang_call_convention (decl, mangled);
344
345 /* Function attributes. */
346 mangled = dlang_attributes (&attr, mangled);
347 szattr = string_length (&attr);
348
349 /* Function arguments. */
350 mangled = dlang_function_args (&args, mangled);
351 szargs = string_length (&args);
352
353 /* Function return type. */
354 mangled = dlang_type (&type, mangled);
355 sztype = string_length (&type);
356
357 /* Append to decl in order. */
358 string_appendn (decl, type.b, sztype);
359 string_append (decl, "(");
360 string_appendn (decl, args.b, szargs);
361 string_append (decl, ") ");
362 string_appendn (decl, attr.b, szattr);
363
364 string_delete (&attr);
365 string_delete (&args);
366 string_delete (&type);
367 return mangled;
368}
369
370/* Demangle the argument list from MANGLED and append it to DECL.
371 Return the remaining string on success or NULL on failure. */
372static const char *
373dlang_function_args (string *decl, const char *mangled)
374{
375 size_t n = 0;
376
377 while (mangled && *mangled != '\0')
378 {
379 switch (*mangled)
380 {
381 case 'X': /* (variadic T t...) style. */
382 mangled++;
383 string_append (decl, "...");
384 return mangled;
385 case 'Y': /* (variadic T t, ...) style. */
386 mangled++;
387 string_append (decl, ", ...");
388 return mangled;
389 case 'Z': /* Normal function. */
390 mangled++;
391 return mangled;
392 }
393
394 if (n++)
395 string_append (decl, ", ");
396
397 if (*mangled == 'M') /* scope(T) */
398 {
399 mangled++;
400 string_append (decl, "scope ");
401 }
402
7ce4461f
IB
403 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
404 {
405 mangled += 2;
406 string_append (decl, "return ");
407 }
408
43b1b9ed
IB
409 switch (*mangled)
410 {
411 case 'J': /* out(T) */
412 mangled++;
413 string_append (decl, "out ");
414 break;
415 case 'K': /* ref(T) */
416 mangled++;
417 string_append (decl, "ref ");
418 break;
419 case 'L': /* lazy(T) */
420 mangled++;
421 string_append (decl, "lazy ");
422 break;
423 }
424 mangled = dlang_type (decl, mangled);
425 }
426
427 return mangled;
428}
429
430/* Demangle the type from MANGLED and append it to DECL.
431 Return the remaining string on success or NULL on failure. */
432static const char *
433dlang_type (string *decl, const char *mangled)
434{
435 if (mangled == NULL || *mangled == '\0')
76b41cad 436 return NULL;
43b1b9ed
IB
437
438 switch (*mangled)
439 {
440 case 'O': /* shared(T) */
441 mangled++;
442 string_append (decl, "shared(");
443 mangled = dlang_type (decl, mangled);
444 string_append (decl, ")");
445 return mangled;
446 case 'x': /* const(T) */
447 mangled++;
448 string_append (decl, "const(");
449 mangled = dlang_type (decl, mangled);
450 string_append (decl, ")");
451 return mangled;
452 case 'y': /* immutable(T) */
453 mangled++;
454 string_append (decl, "immutable(");
455 mangled = dlang_type (decl, mangled);
456 string_append (decl, ")");
457 return mangled;
458 case 'N':
459 mangled++;
460 if (*mangled == 'g') /* wild(T) */
461 {
462 mangled++;
463 string_append (decl, "inout(");
464 mangled = dlang_type (decl, mangled);
465 string_append (decl, ")");
466 return mangled;
467 }
468 else if (*mangled == 'h') /* vector(T) */
469 {
470 mangled++;
471 string_append (decl, "__vector(");
472 mangled = dlang_type (decl, mangled);
473 string_append (decl, ")");
474 return mangled;
475 }
476 else
477 return NULL;
478 case 'A': /* dynamic array (T[]) */
479 mangled++;
480 mangled = dlang_type (decl, mangled);
481 string_append (decl, "[]");
482 return mangled;
483 case 'G': /* static array (T[N]) */
484 {
485 const char *numptr;
486 size_t num = 0;
487 mangled++;
488
489 numptr = mangled;
490 while (ISDIGIT (*mangled))
491 {
492 num++;
493 mangled++;
494 }
495 mangled = dlang_type (decl, mangled);
496 string_append (decl, "[");
497 string_appendn (decl, numptr, num);
498 string_append (decl, "]");
499 return mangled;
500 }
501 case 'H': /* associative array (T[T]) */
502 {
503 string type;
504 size_t sztype;
505 mangled++;
506
507 string_init (&type);
508 mangled = dlang_type (&type, mangled);
509 sztype = string_length (&type);
510
511 mangled = dlang_type (decl, mangled);
512 string_append (decl, "[");
513 string_appendn (decl, type.b, sztype);
514 string_append (decl, "]");
515
516 string_delete (&type);
517 return mangled;
518 }
519 case 'P': /* pointer (T*) */
520 mangled++;
521 mangled = dlang_type (decl, mangled);
522 string_append (decl, "*");
523 return mangled;
524 case 'I': /* ident T */
525 case 'C': /* class T */
526 case 'S': /* struct T */
527 case 'E': /* enum T */
528 case 'T': /* typedef T */
529 mangled++;
530 return dlang_parse_symbol (decl, mangled);
531 case 'D': /* delegate T */
fa66ced4
IB
532 {
533 string mods;
534 size_t szmods;
43b1b9ed 535 mangled++;
fa66ced4
IB
536
537 string_init (&mods);
538 mangled = dlang_type_modifiers (&mods, mangled);
539 szmods = string_length (&mods);
540
43b1b9ed
IB
541 mangled = dlang_function_type (decl, mangled);
542 string_append (decl, "delegate");
fa66ced4
IB
543 string_appendn (decl, mods.b, szmods);
544
545 string_delete (&mods);
43b1b9ed 546 return mangled;
fa66ced4 547 }
43b1b9ed
IB
548 case 'B': /* tuple T */
549 mangled++;
550 return dlang_parse_tuple (decl, mangled);
551
552 /* Function types */
553 case 'F': case 'U': case 'W':
554 case 'V': case 'R':
555 mangled = dlang_function_type (decl, mangled);
556 string_append (decl, "function");
557 return mangled;
558
559 /* Basic types */
560 case 'n':
561 mangled++;
562 string_append (decl, "none");
563 return mangled;
564 case 'v':
565 mangled++;
566 string_append (decl, "void");
567 return mangled;
568 case 'g':
569 mangled++;
570 string_append (decl, "byte");
571 return mangled;
572 case 'h':
573 mangled++;
574 string_append (decl, "ubyte");
575 return mangled;
576 case 's':
577 mangled++;
578 string_append (decl, "short");
579 return mangled;
580 case 't':
581 mangled++;
582 string_append (decl, "ushort");
583 return mangled;
584 case 'i':
585 mangled++;
586 string_append (decl, "int");
587 return mangled;
588 case 'k':
589 mangled++;
590 string_append (decl, "uint");
591 return mangled;
592 case 'l':
593 mangled++;
594 string_append (decl, "long");
595 return mangled;
596 case 'm':
597 mangled++;
598 string_append (decl, "ulong");
599 return mangled;
600 case 'f':
601 mangled++;
602 string_append (decl, "float");
603 return mangled;
604 case 'd':
605 mangled++;
606 string_append (decl, "double");
607 return mangled;
608 case 'e':
609 mangled++;
610 string_append (decl, "real");
611 return mangled;
612
613 /* Imaginary and Complex types */
614 case 'o':
615 mangled++;
616 string_append (decl, "ifloat");
617 return mangled;
618 case 'p':
619 mangled++;
620 string_append (decl, "idouble");
621 return mangled;
622 case 'j':
623 mangled++;
624 string_append (decl, "ireal");
625 return mangled;
626 case 'q':
627 mangled++;
628 string_append (decl, "cfloat");
629 return mangled;
630 case 'r':
631 mangled++;
632 string_append (decl, "cdouble");
633 return mangled;
634 case 'c':
635 mangled++;
636 string_append (decl, "creal");
637 return mangled;
638
639 /* Other types */
640 case 'b':
641 mangled++;
642 string_append (decl, "bool");
643 return mangled;
644 case 'a':
645 mangled++;
646 string_append (decl, "char");
647 return mangled;
648 case 'u':
649 mangled++;
650 string_append (decl, "wchar");
651 return mangled;
652 case 'w':
653 mangled++;
654 string_append (decl, "dchar");
655 return mangled;
59251a73
IB
656 case 'z':
657 mangled++;
658 switch (*mangled)
659 {
660 case 'i':
661 mangled++;
662 string_append (decl, "cent");
663 return mangled;
664 case 'k':
665 mangled++;
666 string_append (decl, "ucent");
667 return mangled;
668 }
669 return NULL;
43b1b9ed
IB
670
671 default: /* unhandled */
672 return NULL;
673 }
674}
675
676/* Extract the identifier from MANGLED and append it to DECL.
677 Return the remaining string on success or NULL on failure. */
678static const char *
679dlang_identifier (string *decl, const char *mangled)
680{
681 if (mangled == NULL || *mangled == '\0')
76b41cad 682 return NULL;
43b1b9ed
IB
683
684 if (ISDIGIT (*mangled))
685 {
686 char *endptr;
687 long i = strtol (mangled, &endptr, 10);
688
689 if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
690 return NULL;
691
692 mangled = endptr;
693
694 /* May be a template instance. */
695 if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
696 {
697 /* Template symbol. */
698 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
699 return dlang_parse_template (decl, mangled, i);
700
701 return NULL;
702 }
703
5cc158e9 704 switch (i)
43b1b9ed 705 {
5cc158e9
IB
706 case 6:
707 if (strncmp (mangled, "__ctor", i) == 0)
708 {
709 /* Constructor symbol for a class/struct. */
710 string_append (decl, "this");
711 mangled += i;
712 return mangled;
713 }
714 else if (strncmp (mangled, "__dtor", i) == 0)
715 {
716 /* Destructor symbol for a class/struct. */
717 string_append (decl, "~this");
718 mangled += i;
719 return mangled;
720 }
721 else if (strncmp (mangled, "__initZ", i+1) == 0)
722 {
723 /* The static initialiser for a given symbol. */
724 string_append (decl, "init$");
725 mangled += i;
726 return mangled;
727 }
728 else if (strncmp (mangled, "__vtblZ", i+1) == 0)
729 {
730 /* The vtable symbol for a given class. */
731 string_prepend (decl, "vtable for ");
732 string_setlength (decl, string_length (decl) - 1);
733 mangled += i;
734 return mangled;
735 }
736 break;
737
738 case 7:
739 if (strncmp (mangled, "__ClassZ", i+1) == 0)
740 {
741 /* The classinfo symbol for a given class. */
742 string_prepend (decl, "ClassInfo for ");
743 string_setlength (decl, string_length (decl) - 1);
744 mangled += i;
745 return mangled;
746 }
747 break;
748
749 case 10:
750 if (strncmp (mangled, "__postblitMFZ", i+3) == 0)
751 {
752 /* Postblit symbol for a struct. */
753 string_append (decl, "this(this)");
754 mangled += i + 3;
755 return mangled;
756 }
757 break;
758
759 case 11:
760 if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
761 {
762 /* The interface symbol for a given class. */
763 string_prepend (decl, "Interface for ");
764 string_setlength (decl, string_length (decl) - 1);
765 mangled += i;
766 return mangled;
767 }
768 break;
769
770 case 12:
771 if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
772 {
773 /* The ModuleInfo symbol for a given module. */
774 string_prepend (decl, "ModuleInfo for ");
775 string_setlength (decl, string_length (decl) - 1);
776 mangled += i;
777 return mangled;
778 }
779 break;
43b1b9ed
IB
780 }
781
782 string_appendn (decl, mangled, i);
783 mangled += i;
784 }
785 else
786 return NULL;
787
788 return mangled;
789}
790
791/* Extract the integer value from MANGLED and append it to DECL,
792 where TYPE is the type it should be represented as.
793 Return the remaining string on success or NULL on failure. */
794static const char *
795dlang_parse_integer (string *decl, const char *mangled, char type)
796{
797 if (type == 'a' || type == 'u' || type == 'w')
798 {
799 /* Parse character value. */
800 char value[10];
801 int pos = 10;
802 int width = 0;
803 char *endptr;
804 long val = strtol (mangled, &endptr, 10);
805
806 if (endptr == NULL || val < 0)
807 return NULL;
808
809 string_append (decl, "'");
810
811 if (type == 'a' && val >= 0x20 && val < 0x7F)
812 {
813 /* Represent as a character literal. */
814 char c = (char) val;
815 string_appendn (decl, &c, 1);
816 }
817 else
818 {
819 /* Represent as a hexadecimal value. */
820 switch (type)
821 {
822 case 'a': /* char */
823 string_append (decl, "\\x");
824 width = 2;
825 break;
826 case 'u': /* wchar */
827 string_append (decl, "\\u");
828 width = 4;
829 break;
830 case 'w': /* dchar */
831 string_append (decl, "\\U");
832 width = 8;
833 break;
834 }
835
836 while (val > 0)
837 {
838 int digit = val % 16;
839
840 if (digit < 10)
841 value[--pos] = (char)(digit + '0');
842 else
843 value[--pos] = (char)((digit - 10) + 'a');
844
845 val /= 16;
846 width--;
847 }
848
849 for (; width > 0; width--)
850 value[--pos] = '0';
851
852 string_appendn (decl, &(value[pos]), 10 - pos);
853 }
854 string_append (decl, "'");
855 mangled = endptr;
856 }
857 else if (type == 'b')
858 {
859 /* Parse boolean value. */
860 char *endptr;
861 long val = strtol (mangled, &endptr, 10);
862
863 if (endptr == NULL || val < 0)
864 return NULL;
865
866 string_append (decl, val ? "true" : "false");
867 mangled = endptr;
868 }
869 else
870 {
871 /* Parse integer value. */
872 const char *numptr = mangled;
873 size_t num = 0;
874
875 while (ISDIGIT (*mangled))
876 {
877 num++;
878 mangled++;
879 }
880 string_appendn (decl, numptr, num);
881
882 /* Append suffix. */
883 switch (type)
884 {
885 case 'h': /* ubyte */
886 case 't': /* ushort */
887 case 'k': /* uint */
888 string_append (decl, "u");
889 break;
890 case 'l': /* long */
891 string_append (decl, "L");
892 break;
893 case 'm': /* ulong */
894 string_append (decl, "uL");
895 break;
896 }
897 }
898
899 return mangled;
900}
901
902/* Extract the floating-point value from MANGLED and append it to DECL.
903 Return the remaining string on success or NULL on failure. */
904static const char *
905dlang_parse_real (string *decl, const char *mangled)
906{
907 char buffer[64];
908 int len = 0;
2a523cfe 909 double value;
43b1b9ed
IB
910 char *endptr;
911
912 /* Handle NAN and +-INF. */
913 if (strncmp (mangled, "NAN", 3) == 0)
914 {
915 string_append (decl, "NaN");
916 mangled += 3;
917 return mangled;
918 }
919 else if (strncmp (mangled, "INF", 3) == 0)
920 {
921 string_append (decl, "Inf");
922 mangled += 3;
923 return mangled;
924 }
925 else if (strncmp (mangled, "NINF", 4) == 0)
926 {
927 string_append (decl, "-Inf");
928 mangled += 4;
929 return mangled;
930 }
931
932 /* Hexadecimal prefix and leading bit. */
933 if (*mangled == 'N')
934 {
935 buffer[len++] = '-';
936 mangled++;
937 }
938
939 if (!ISXDIGIT (*mangled))
940 return NULL;
941
942 buffer[len++] = '0';
943 buffer[len++] = 'x';
944 buffer[len++] = *mangled;
945 buffer[len++] = '.';
946 mangled++;
947
948 /* Significand. */
949 while (ISXDIGIT (*mangled))
950 {
951 buffer[len++] = *mangled;
952 mangled++;
953 }
954
955 /* Exponent. */
956 if (*mangled != 'P')
957 return NULL;
958
959 buffer[len++] = 'p';
960 mangled++;
961
962 if (*mangled == 'N')
963 {
964 buffer[len++] = '-';
965 mangled++;
966 }
967
968 while (ISDIGIT (*mangled))
969 {
970 buffer[len++] = *mangled;
971 mangled++;
972 }
973
974 /* Convert buffer from hexadecimal to floating-point. */
975 buffer[len] = '\0';
2a523cfe 976 value = strtod (buffer, &endptr);
43b1b9ed
IB
977
978 if (endptr == NULL || endptr != (buffer + len))
979 return NULL;
980
2a523cfe 981 len = snprintf (buffer, sizeof(buffer), "%#g", value);
43b1b9ed
IB
982 string_appendn (decl, buffer, len);
983 return mangled;
984}
985
986/* Convert VAL from an ascii hexdigit to value. */
987static char
988ascii2hex (char val)
989{
990 if (val >= 'a' && val <= 'f')
991 return (val - 'a' + 10);
992
993 if (val >= 'A' && val <= 'F')
994 return (val - 'A' + 10);
995
996 if (val >= '0' && val <= '9')
997 return (val - '0');
998
999 return 0;
1000}
1001
1002/* Extract the string value from MANGLED and append it to DECL.
1003 Return the remaining string on success or NULL on failure. */
1004static const char *
1005dlang_parse_string (string *decl, const char *mangled)
1006{
1007 char type = *mangled;
1008 char *endptr;
1009 long len;
1010
1011 mangled++;
1012 len = strtol (mangled, &endptr, 10);
1013
1014 if (endptr == NULL || len < 0)
1015 return NULL;
1016
1017 mangled = endptr;
1018 if (*mangled != '_')
1019 return NULL;
1020
1021 mangled++;
1022 string_append (decl, "\"");
1023 while (len--)
1024 {
1025 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
1026 {
1027 char a = ascii2hex (mangled[0]);
1028 char b = ascii2hex (mangled[1]);
1029 char val = (a << 4) | b;
eb058b7d
IB
1030
1031 /* Sanitize white and non-printable characters. */
1032 switch (val)
1033 {
1034 case ' ':
1035 string_append (decl, " ");
1036 break;
1037 case '\t':
1038 string_append (decl, "\\t");
1039 break;
1040 case '\n':
1041 string_append (decl, "\\n");
1042 break;
1043 case '\r':
1044 string_append (decl, "\\r");
1045 break;
1046 case '\f':
1047 string_append (decl, "\\f");
1048 break;
1049 case '\v':
1050 string_append (decl, "\\v");
1051 break;
1052
1053 default:
1054 if (ISPRINT (val))
1055 string_appendn (decl, &val, 1);
1056 else
1057 {
1058 string_append (decl, "\\x");
1059 string_appendn (decl, mangled, 2);
1060 }
1061 }
43b1b9ed
IB
1062 }
1063 else
1064 return NULL;
1065
1066 mangled += 2;
1067 }
1068 string_append (decl, "\"");
1069
1070 if (type != 'a')
1071 string_appendn (decl, &type, 1);
1072
1073 return mangled;
1074}
1075
1076/* Extract the static array value from MANGLED and append it to DECL.
1077 Return the remaining string on success or NULL on failure. */
1078static const char *
1079dlang_parse_arrayliteral (string *decl, const char *mangled)
1080{
1081 char *endptr;
1082 long elements = strtol (mangled, &endptr, 10);
1083
1084 if (endptr == NULL || elements < 0)
1085 return NULL;
1086
1087 mangled = endptr;
1088 string_append (decl, "[");
1089 while (elements--)
1090 {
1091 mangled = dlang_value (decl, mangled, NULL, '\0');
1092 if (elements != 0)
1093 string_append (decl, ", ");
1094 }
1095
1096 string_append (decl, "]");
1097 return mangled;
1098}
1099
1100/* Extract the associative array value from MANGLED and append it to DECL.
1101 Return the remaining string on success or NULL on failure. */
1102static const char *
1103dlang_parse_assocarray (string *decl, const char *mangled)
1104{
1105 char *endptr;
1106 long elements = strtol (mangled, &endptr, 10);
1107
1108 if (endptr == NULL || elements < 0)
1109 return NULL;
1110
1111 mangled = endptr;
1112 string_append (decl, "[");
1113 while (elements--)
1114 {
1115 mangled = dlang_value (decl, mangled, NULL, '\0');
1116 string_append (decl, ":");
1117 mangled = dlang_value (decl, mangled, NULL, '\0');
1118
1119 if (elements != 0)
1120 string_append (decl, ", ");
1121 }
1122
1123 string_append (decl, "]");
1124 return mangled;
1125}
1126
1127/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1128 Return the remaining string on success or NULL on failure. */
1129static const char *
1130dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1131{
1132 char *endptr;
1133 long args = strtol (mangled, &endptr, 10);
1134
1135 if (endptr == NULL || args < 0)
1136 return NULL;
1137
1138 mangled = endptr;
1139 if (name != NULL)
1140 string_append (decl, name);
1141
1142 string_append (decl, "(");
1143 while (args--)
1144 {
1145 mangled = dlang_value (decl, mangled, NULL, '\0');
1146 if (args != 0)
1147 string_append (decl, ", ");
1148 }
1149
1150 string_append (decl, ")");
1151 return mangled;
1152}
1153
1154/* Extract the value from MANGLED and append it to DECL.
1155 Return the remaining string on success or NULL on failure. */
1156static const char *
1157dlang_value (string *decl, const char *mangled, const char *name, char type)
1158{
1159 if (mangled == NULL || *mangled == '\0')
76b41cad 1160 return NULL;
43b1b9ed
IB
1161
1162 switch (*mangled)
1163 {
1164 /* Null value. */
1165 case 'n':
1166 mangled++;
1167 string_append (decl, "null");
1168 break;
1169
1170 /* Integral values. */
1171 case 'N':
1172 mangled++;
1173 string_append (decl, "-");
1174 mangled = dlang_parse_integer (decl, mangled, type);
1175 break;
1176
1177 case 'i':
1178 mangled++;
1179 if (*mangled < '0' || *mangled > '9')
1180 return NULL;
1181 /* Fall through */
1182 case '0': case '1': case '2': case '3': case '4':
1183 case '5': case '6': case '7': case '8': case '9':
1184 mangled = dlang_parse_integer (decl, mangled, type);
1185 break;
1186
1187 /* Real value. */
1188 case 'e':
1189 mangled++;
1190 mangled = dlang_parse_real (decl, mangled);
1191 break;
1192
1193 /* Complex value. */
1194 case 'c':
1195 mangled++;
1196 mangled = dlang_parse_real (decl, mangled);
1197 string_append (decl, "+");
1198 if (mangled == NULL || *mangled != 'c')
1199 return NULL;
1200 mangled++;
1201 mangled = dlang_parse_real (decl, mangled);
1202 string_append (decl, "i");
1203 break;
1204
1205 /* String values. */
1206 case 'a': /* UTF8 */
1207 case 'w': /* UTF16 */
1208 case 'd': /* UTF32 */
1209 mangled = dlang_parse_string (decl, mangled);
1210 break;
1211
1212 /* Array values. */
1213 case 'A':
1214 mangled++;
1215 if (type == 'H')
1216 mangled = dlang_parse_assocarray (decl, mangled);
1217 else
1218 mangled = dlang_parse_arrayliteral (decl, mangled);
1219 break;
1220
1221 /* Struct values. */
1222 case 'S':
1223 mangled++;
1224 mangled = dlang_parse_structlit (decl, mangled, name);
1225 break;
1226
1227 default:
1228 return NULL;
1229 }
1230
1231 return mangled;
1232}
1233
fa66ced4
IB
1234/* Extract the type modifiers from MANGLED and return the string
1235 length that it consumes in MANGLED on success or 0 on failure. */
43b1b9ed 1236static int
fa66ced4 1237dlang_type_modifier_p (const char *mangled)
43b1b9ed 1238{
fa66ced4 1239 int i;
43b1b9ed
IB
1240
1241 switch (*mangled)
1242 {
fa66ced4 1243 case 'x': case 'y':
43b1b9ed
IB
1244 return 1;
1245
fa66ced4
IB
1246 case 'O':
1247 mangled++;
1248 i = dlang_type_modifier_p (mangled);
1249 return i + 1;
43b1b9ed 1250
fa66ced4
IB
1251 case 'N':
1252 mangled++;
1253 if (*mangled == 'g')
43b1b9ed 1254 {
fa66ced4
IB
1255 mangled++;
1256 i = dlang_type_modifier_p (mangled);
1257 return i + 2;
43b1b9ed 1258 }
fa66ced4
IB
1259 }
1260
1261 return 0;
1262}
1263
1264/* Extract the function calling convention from MANGLED and
1265 return 1 on success or 0 on failure. */
1266static int
1267dlang_call_convention_p (const char *mangled)
1268{
1269 /* Prefix for functions needing 'this' */
1270 if (*mangled == 'M')
1271 {
1272 mangled++;
1273 /* Also skip over any type modifiers. */
1274 mangled += dlang_type_modifier_p (mangled);
1275 }
1276
1277 switch (*mangled)
1278 {
1279 case 'F': case 'U': case 'V':
1280 case 'W': case 'R':
1281 return 1;
43b1b9ed
IB
1282
1283 default:
1284 return 0;
1285 }
1286}
1287
1288/* Extract and demangle the symbol in MANGLED and append it to DECL.
1289 Returns the remaining signature on success or NULL on failure. */
1290static const char *
1291dlang_parse_symbol (string *decl, const char *mangled)
1292{
1293 size_t n = 0;
1294 do
1295 {
1296 if (n++)
1297 string_append (decl, ".");
1298
1299 mangled = dlang_identifier (decl, mangled);
1300
1301 if (mangled && dlang_call_convention_p (mangled))
1302 {
fa66ced4 1303 string mods;
43b1b9ed
IB
1304 int saved;
1305
1306 /* Skip over 'this' parameter. */
1307 if (*mangled == 'M')
fa66ced4
IB
1308 mangled++;
1309
1310 /* Save the type modifiers for appending at the end. */
1311 string_init (&mods);
1312 mangled = dlang_type_modifiers (&mods, mangled);
43b1b9ed
IB
1313
1314 /* Skip over calling convention and attributes in qualified name. */
1315 saved = string_length (decl);
1316 mangled = dlang_call_convention (decl, mangled);
1317 mangled = dlang_attributes (decl, mangled);
1318 string_setlength (decl, saved);
1319
1320 string_append (decl, "(");
1321 mangled = dlang_function_args (decl, mangled);
1322 string_append (decl, ")");
1323
1324 /* Demangle the function return type as a kind of sanity test. */
1325 if (mangled && !ISDIGIT (*mangled))
1326 {
1327 saved = string_length (decl);
1328 mangled = dlang_type (decl, mangled);
1329 string_setlength (decl, saved);
1330 }
fa66ced4
IB
1331
1332 /* Add any const/immutable/shared modifier. */
1333 string_appendn (decl, mods.b, string_length (&mods));
1334 string_delete (&mods);
43b1b9ed
IB
1335 }
1336 }
1337 while (mangled && ISDIGIT (*mangled));
1338
1339 return mangled;
1340}
1341
1342/* Demangle the tuple from MANGLED and append it to DECL.
1343 Return the remaining string on success or NULL on failure. */
1344static const char *
1345dlang_parse_tuple (string *decl, const char *mangled)
1346{
1347 char *endptr;
1348 long elements = strtol (mangled, &endptr, 10);
1349
1350 if (endptr == NULL || elements < 0)
1351 return NULL;
1352
1353 mangled = endptr;
1354 string_append (decl, "Tuple!(");
1355
1356 while (elements--)
1357 {
1358 mangled = dlang_type (decl, mangled);
1359 if (elements != 0)
1360 string_append (decl, ", ");
1361 }
1362
1363 string_append (decl, ")");
1364 return mangled;
1365}
1366
1367/* Demangle the argument list from MANGLED and append it to DECL.
1368 Return the remaining string on success or NULL on failure. */
1369static const char *
1370dlang_template_args (string *decl, const char *mangled)
1371{
1372 size_t n = 0;
1373
1374 while (mangled && *mangled != '\0')
1375 {
1376 switch (*mangled)
1377 {
1378 case 'Z': /* End of parameter list. */
1379 mangled++;
1380 return mangled;
1381 }
1382
1383 if (n++)
1384 string_append (decl, ", ");
1385
1386 switch (*mangled)
1387 {
1388 case 'S': /* Symbol parameter. */
1389 mangled++;
1390 mangled = dlang_parse_symbol (decl, mangled);
1391 break;
1392 case 'T': /* Type parameter. */
1393 mangled++;
1394 mangled = dlang_type (decl, mangled);
1395 break;
1396 case 'V': /* Value parameter. */
1397 {
1398 string name;
1399 char type;
1400
1401 /* Peek at the type. */
1402 mangled++;
1403 type = *mangled;
1404
1405 /* In the few instances where the type is actually desired in
1406 the output, it should precede the value from dlang_value. */
1407 string_init (&name);
1408 mangled = dlang_type (&name, mangled);
1409 string_need (&name, 1);
1410 *(name.p) = '\0';
1411
1412 mangled = dlang_value (decl, mangled, name.b, type);
1413 string_delete (&name);
1414 break;
1415 }
1416
1417 default:
1418 return NULL;
1419 }
1420 }
1421
1422 return mangled;
1423}
1424
1425/* Extract and demangle the template symbol in MANGLED, expected to
1426 be made up of LEN characters, and append it to DECL.
1427 Returns the remaining signature on success or NULL on failure. */
1428static const char *
1429dlang_parse_template (string *decl, const char *mangled, long len)
1430{
1431 const char *start = mangled;
1432
1433 /* Template instance names have the types and values of its parameters
1434 encoded into it.
1435
1436 TemplateInstanceName:
1437 Number __T LName TemplateArgs Z
1438 ^
1439 The start pointer should be at the above location, and LEN should be
1440 the value of the decoded number.
1441 */
1442 if (strncmp (mangled, "__T", 3) != 0)
1443 return NULL;
1444
1445 mangled += 3;
1446
1447 /* Template identifier. */
1448 mangled = dlang_identifier (decl, mangled);
1449
1450 /* Template arguments. */
1451 string_append (decl, "!(");
1452 mangled = dlang_template_args (decl, mangled);
1453 string_append (decl, ")");
1454
1455 /* Check for template name length mismatch. */
1456 if (mangled && (mangled - start) != len)
1457 return NULL;
1458
1459 return mangled;
1460}
1461
1462/* Extract and demangle the symbol in MANGLED. Returns the demangled
1463 signature on success or NULL on failure. */
1464
1465char *
1466dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1467{
1468 string decl;
1469 char *demangled = NULL;
1470
1471 if (mangled == NULL || *mangled == '\0')
1472 return NULL;
1473
1474 if (strncmp (mangled, "_D", 2) != 0)
1475 return NULL;
1476
1477 string_init (&decl);
1478
1479 if (strcmp (mangled, "_Dmain") == 0)
1480 {
1481 string_append (&decl, "D main");
1482 }
1483 else
1484 {
1485 mangled += 2;
1486
1487 if (dlang_parse_symbol (&decl, mangled) == NULL)
1488 string_delete (&decl);
1489 }
1490
1491 if (string_length (&decl) > 0)
1492 {
1493 string_need (&decl, 1);
1494 *(decl.p) = '\0';
1495 demangled = decl.b;
1496 }
1497
1498 return demangled;
1499}
1500