]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
d-demangle.c (dlang_type_modifiers): New function.
[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':
295 /* inout parameter is represented as 'Ng'.
296 vector parameter is represented as 'Nh'.
297 If we see this, then we know we're really in the
298 parameter list. Rewind and break. */
299 mangled--;
300 break;
301 case 'i': /* @nogc */
302 mangled++;
303 string_append (decl, "@nogc ");
304 continue;
305 }
306 break;
307 }
308
309 return mangled;
310}
311
312/* Demangle the function type from MANGLED and append it to DECL.
313 Return the remaining string on success or NULL on failure. */
314static const char *
315dlang_function_type (string *decl, const char *mangled)
316{
317 string attr, args, type;
318 size_t szattr, szargs, sztype;
319
320 if (mangled == NULL || *mangled == '\0')
76b41cad 321 return NULL;
43b1b9ed
IB
322
323 /* The order of the mangled string is:
324 CallConvention FuncAttrs Arguments ArgClose Type
325
326 The demangled string is re-ordered as:
327 CallConvention Type Arguments FuncAttrs
328 */
329 string_init (&attr);
330 string_init (&args);
331 string_init (&type);
332
333 /* Function call convention. */
334 mangled = dlang_call_convention (decl, mangled);
335
336 /* Function attributes. */
337 mangled = dlang_attributes (&attr, mangled);
338 szattr = string_length (&attr);
339
340 /* Function arguments. */
341 mangled = dlang_function_args (&args, mangled);
342 szargs = string_length (&args);
343
344 /* Function return type. */
345 mangled = dlang_type (&type, mangled);
346 sztype = string_length (&type);
347
348 /* Append to decl in order. */
349 string_appendn (decl, type.b, sztype);
350 string_append (decl, "(");
351 string_appendn (decl, args.b, szargs);
352 string_append (decl, ") ");
353 string_appendn (decl, attr.b, szattr);
354
355 string_delete (&attr);
356 string_delete (&args);
357 string_delete (&type);
358 return mangled;
359}
360
361/* Demangle the argument list from MANGLED and append it to DECL.
362 Return the remaining string on success or NULL on failure. */
363static const char *
364dlang_function_args (string *decl, const char *mangled)
365{
366 size_t n = 0;
367
368 while (mangled && *mangled != '\0')
369 {
370 switch (*mangled)
371 {
372 case 'X': /* (variadic T t...) style. */
373 mangled++;
374 string_append (decl, "...");
375 return mangled;
376 case 'Y': /* (variadic T t, ...) style. */
377 mangled++;
378 string_append (decl, ", ...");
379 return mangled;
380 case 'Z': /* Normal function. */
381 mangled++;
382 return mangled;
383 }
384
385 if (n++)
386 string_append (decl, ", ");
387
388 if (*mangled == 'M') /* scope(T) */
389 {
390 mangled++;
391 string_append (decl, "scope ");
392 }
393
394 switch (*mangled)
395 {
396 case 'J': /* out(T) */
397 mangled++;
398 string_append (decl, "out ");
399 break;
400 case 'K': /* ref(T) */
401 mangled++;
402 string_append (decl, "ref ");
403 break;
404 case 'L': /* lazy(T) */
405 mangled++;
406 string_append (decl, "lazy ");
407 break;
408 }
409 mangled = dlang_type (decl, mangled);
410 }
411
412 return mangled;
413}
414
415/* Demangle the type from MANGLED and append it to DECL.
416 Return the remaining string on success or NULL on failure. */
417static const char *
418dlang_type (string *decl, const char *mangled)
419{
420 if (mangled == NULL || *mangled == '\0')
76b41cad 421 return NULL;
43b1b9ed
IB
422
423 switch (*mangled)
424 {
425 case 'O': /* shared(T) */
426 mangled++;
427 string_append (decl, "shared(");
428 mangled = dlang_type (decl, mangled);
429 string_append (decl, ")");
430 return mangled;
431 case 'x': /* const(T) */
432 mangled++;
433 string_append (decl, "const(");
434 mangled = dlang_type (decl, mangled);
435 string_append (decl, ")");
436 return mangled;
437 case 'y': /* immutable(T) */
438 mangled++;
439 string_append (decl, "immutable(");
440 mangled = dlang_type (decl, mangled);
441 string_append (decl, ")");
442 return mangled;
443 case 'N':
444 mangled++;
445 if (*mangled == 'g') /* wild(T) */
446 {
447 mangled++;
448 string_append (decl, "inout(");
449 mangled = dlang_type (decl, mangled);
450 string_append (decl, ")");
451 return mangled;
452 }
453 else if (*mangled == 'h') /* vector(T) */
454 {
455 mangled++;
456 string_append (decl, "__vector(");
457 mangled = dlang_type (decl, mangled);
458 string_append (decl, ")");
459 return mangled;
460 }
461 else
462 return NULL;
463 case 'A': /* dynamic array (T[]) */
464 mangled++;
465 mangled = dlang_type (decl, mangled);
466 string_append (decl, "[]");
467 return mangled;
468 case 'G': /* static array (T[N]) */
469 {
470 const char *numptr;
471 size_t num = 0;
472 mangled++;
473
474 numptr = mangled;
475 while (ISDIGIT (*mangled))
476 {
477 num++;
478 mangled++;
479 }
480 mangled = dlang_type (decl, mangled);
481 string_append (decl, "[");
482 string_appendn (decl, numptr, num);
483 string_append (decl, "]");
484 return mangled;
485 }
486 case 'H': /* associative array (T[T]) */
487 {
488 string type;
489 size_t sztype;
490 mangled++;
491
492 string_init (&type);
493 mangled = dlang_type (&type, mangled);
494 sztype = string_length (&type);
495
496 mangled = dlang_type (decl, mangled);
497 string_append (decl, "[");
498 string_appendn (decl, type.b, sztype);
499 string_append (decl, "]");
500
501 string_delete (&type);
502 return mangled;
503 }
504 case 'P': /* pointer (T*) */
505 mangled++;
506 mangled = dlang_type (decl, mangled);
507 string_append (decl, "*");
508 return mangled;
509 case 'I': /* ident T */
510 case 'C': /* class T */
511 case 'S': /* struct T */
512 case 'E': /* enum T */
513 case 'T': /* typedef T */
514 mangled++;
515 return dlang_parse_symbol (decl, mangled);
516 case 'D': /* delegate T */
fa66ced4
IB
517 {
518 string mods;
519 size_t szmods;
43b1b9ed 520 mangled++;
fa66ced4
IB
521
522 string_init (&mods);
523 mangled = dlang_type_modifiers (&mods, mangled);
524 szmods = string_length (&mods);
525
43b1b9ed
IB
526 mangled = dlang_function_type (decl, mangled);
527 string_append (decl, "delegate");
fa66ced4
IB
528 string_appendn (decl, mods.b, szmods);
529
530 string_delete (&mods);
43b1b9ed 531 return mangled;
fa66ced4 532 }
43b1b9ed
IB
533 case 'B': /* tuple T */
534 mangled++;
535 return dlang_parse_tuple (decl, mangled);
536
537 /* Function types */
538 case 'F': case 'U': case 'W':
539 case 'V': case 'R':
540 mangled = dlang_function_type (decl, mangled);
541 string_append (decl, "function");
542 return mangled;
543
544 /* Basic types */
545 case 'n':
546 mangled++;
547 string_append (decl, "none");
548 return mangled;
549 case 'v':
550 mangled++;
551 string_append (decl, "void");
552 return mangled;
553 case 'g':
554 mangled++;
555 string_append (decl, "byte");
556 return mangled;
557 case 'h':
558 mangled++;
559 string_append (decl, "ubyte");
560 return mangled;
561 case 's':
562 mangled++;
563 string_append (decl, "short");
564 return mangled;
565 case 't':
566 mangled++;
567 string_append (decl, "ushort");
568 return mangled;
569 case 'i':
570 mangled++;
571 string_append (decl, "int");
572 return mangled;
573 case 'k':
574 mangled++;
575 string_append (decl, "uint");
576 return mangled;
577 case 'l':
578 mangled++;
579 string_append (decl, "long");
580 return mangled;
581 case 'm':
582 mangled++;
583 string_append (decl, "ulong");
584 return mangled;
585 case 'f':
586 mangled++;
587 string_append (decl, "float");
588 return mangled;
589 case 'd':
590 mangled++;
591 string_append (decl, "double");
592 return mangled;
593 case 'e':
594 mangled++;
595 string_append (decl, "real");
596 return mangled;
597
598 /* Imaginary and Complex types */
599 case 'o':
600 mangled++;
601 string_append (decl, "ifloat");
602 return mangled;
603 case 'p':
604 mangled++;
605 string_append (decl, "idouble");
606 return mangled;
607 case 'j':
608 mangled++;
609 string_append (decl, "ireal");
610 return mangled;
611 case 'q':
612 mangled++;
613 string_append (decl, "cfloat");
614 return mangled;
615 case 'r':
616 mangled++;
617 string_append (decl, "cdouble");
618 return mangled;
619 case 'c':
620 mangled++;
621 string_append (decl, "creal");
622 return mangled;
623
624 /* Other types */
625 case 'b':
626 mangled++;
627 string_append (decl, "bool");
628 return mangled;
629 case 'a':
630 mangled++;
631 string_append (decl, "char");
632 return mangled;
633 case 'u':
634 mangled++;
635 string_append (decl, "wchar");
636 return mangled;
637 case 'w':
638 mangled++;
639 string_append (decl, "dchar");
640 return mangled;
641
642 default: /* unhandled */
643 return NULL;
644 }
645}
646
647/* Extract the identifier from MANGLED and append it to DECL.
648 Return the remaining string on success or NULL on failure. */
649static const char *
650dlang_identifier (string *decl, const char *mangled)
651{
652 if (mangled == NULL || *mangled == '\0')
76b41cad 653 return NULL;
43b1b9ed
IB
654
655 if (ISDIGIT (*mangled))
656 {
657 char *endptr;
658 long i = strtol (mangled, &endptr, 10);
659
660 if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
661 return NULL;
662
663 mangled = endptr;
664
665 /* May be a template instance. */
666 if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
667 {
668 /* Template symbol. */
669 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
670 return dlang_parse_template (decl, mangled, i);
671
672 return NULL;
673 }
674
675 if (strncmp (mangled, "__ctor", i) == 0)
676 {
677 /* Constructor symbol for a class/struct. */
678 string_append (decl, "this");
679 mangled += i;
680 return mangled;
681 }
682 else if (strncmp (mangled, "__dtor", i) == 0)
683 {
684 /* Destructor symbol for a class/struct. */
685 string_append (decl, "~this");
686 mangled += i;
687 return mangled;
688 }
689 else if (strncmp (mangled, "__postblit", i) == 0)
690 {
691 /* Postblit symbol for a struct. */
692 string_append (decl, "this(this)");
693 mangled += i;
694 return mangled;
695 }
696 else if (strncmp (mangled, "__initZ", i+1) == 0)
697 {
698 /* The static initialiser for a given symbol. */
699 string_append (decl, "init$");
700 mangled += i + 1;
701 return mangled;
702 }
703 else if (strncmp (mangled, "__ClassZ", i+1) == 0)
704 {
705 /* The classinfo symbol for a given class. */
706 string_prepend (decl, "ClassInfo for ");
707 string_setlength (decl, string_length (decl) - 1);
708 mangled += i + 1;
709 return mangled;
710 }
711 else if (strncmp (mangled, "__vtblZ", i+1) == 0)
712 {
713 /* The vtable symbol for a given class. */
714 string_prepend (decl, "vtable for ");
715 string_setlength (decl, string_length (decl) - 1);
716 mangled += i + 1;
717 return mangled;
718 }
719 else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
720 {
721 /* The interface symbol for a given class. */
722 string_prepend (decl, "Interface for ");
723 string_setlength (decl, string_length (decl) - 1);
724 mangled += i + 1;
725 return mangled;
726 }
727 else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
728 {
729 /* The ModuleInfo symbol for a given module. */
730 string_prepend (decl, "ModuleInfo for ");
731 string_setlength (decl, string_length (decl) - 1);
732 mangled += i + 1;
733 return mangled;
734 }
735
736 string_appendn (decl, mangled, i);
737 mangled += i;
738 }
739 else
740 return NULL;
741
742 return mangled;
743}
744
745/* Extract the integer value from MANGLED and append it to DECL,
746 where TYPE is the type it should be represented as.
747 Return the remaining string on success or NULL on failure. */
748static const char *
749dlang_parse_integer (string *decl, const char *mangled, char type)
750{
751 if (type == 'a' || type == 'u' || type == 'w')
752 {
753 /* Parse character value. */
754 char value[10];
755 int pos = 10;
756 int width = 0;
757 char *endptr;
758 long val = strtol (mangled, &endptr, 10);
759
760 if (endptr == NULL || val < 0)
761 return NULL;
762
763 string_append (decl, "'");
764
765 if (type == 'a' && val >= 0x20 && val < 0x7F)
766 {
767 /* Represent as a character literal. */
768 char c = (char) val;
769 string_appendn (decl, &c, 1);
770 }
771 else
772 {
773 /* Represent as a hexadecimal value. */
774 switch (type)
775 {
776 case 'a': /* char */
777 string_append (decl, "\\x");
778 width = 2;
779 break;
780 case 'u': /* wchar */
781 string_append (decl, "\\u");
782 width = 4;
783 break;
784 case 'w': /* dchar */
785 string_append (decl, "\\U");
786 width = 8;
787 break;
788 }
789
790 while (val > 0)
791 {
792 int digit = val % 16;
793
794 if (digit < 10)
795 value[--pos] = (char)(digit + '0');
796 else
797 value[--pos] = (char)((digit - 10) + 'a');
798
799 val /= 16;
800 width--;
801 }
802
803 for (; width > 0; width--)
804 value[--pos] = '0';
805
806 string_appendn (decl, &(value[pos]), 10 - pos);
807 }
808 string_append (decl, "'");
809 mangled = endptr;
810 }
811 else if (type == 'b')
812 {
813 /* Parse boolean value. */
814 char *endptr;
815 long val = strtol (mangled, &endptr, 10);
816
817 if (endptr == NULL || val < 0)
818 return NULL;
819
820 string_append (decl, val ? "true" : "false");
821 mangled = endptr;
822 }
823 else
824 {
825 /* Parse integer value. */
826 const char *numptr = mangled;
827 size_t num = 0;
828
829 while (ISDIGIT (*mangled))
830 {
831 num++;
832 mangled++;
833 }
834 string_appendn (decl, numptr, num);
835
836 /* Append suffix. */
837 switch (type)
838 {
839 case 'h': /* ubyte */
840 case 't': /* ushort */
841 case 'k': /* uint */
842 string_append (decl, "u");
843 break;
844 case 'l': /* long */
845 string_append (decl, "L");
846 break;
847 case 'm': /* ulong */
848 string_append (decl, "uL");
849 break;
850 }
851 }
852
853 return mangled;
854}
855
856/* Extract the floating-point value from MANGLED and append it to DECL.
857 Return the remaining string on success or NULL on failure. */
858static const char *
859dlang_parse_real (string *decl, const char *mangled)
860{
861 char buffer[64];
862 int len = 0;
2a523cfe 863 double value;
43b1b9ed
IB
864 char *endptr;
865
866 /* Handle NAN and +-INF. */
867 if (strncmp (mangled, "NAN", 3) == 0)
868 {
869 string_append (decl, "NaN");
870 mangled += 3;
871 return mangled;
872 }
873 else if (strncmp (mangled, "INF", 3) == 0)
874 {
875 string_append (decl, "Inf");
876 mangled += 3;
877 return mangled;
878 }
879 else if (strncmp (mangled, "NINF", 4) == 0)
880 {
881 string_append (decl, "-Inf");
882 mangled += 4;
883 return mangled;
884 }
885
886 /* Hexadecimal prefix and leading bit. */
887 if (*mangled == 'N')
888 {
889 buffer[len++] = '-';
890 mangled++;
891 }
892
893 if (!ISXDIGIT (*mangled))
894 return NULL;
895
896 buffer[len++] = '0';
897 buffer[len++] = 'x';
898 buffer[len++] = *mangled;
899 buffer[len++] = '.';
900 mangled++;
901
902 /* Significand. */
903 while (ISXDIGIT (*mangled))
904 {
905 buffer[len++] = *mangled;
906 mangled++;
907 }
908
909 /* Exponent. */
910 if (*mangled != 'P')
911 return NULL;
912
913 buffer[len++] = 'p';
914 mangled++;
915
916 if (*mangled == 'N')
917 {
918 buffer[len++] = '-';
919 mangled++;
920 }
921
922 while (ISDIGIT (*mangled))
923 {
924 buffer[len++] = *mangled;
925 mangled++;
926 }
927
928 /* Convert buffer from hexadecimal to floating-point. */
929 buffer[len] = '\0';
2a523cfe 930 value = strtod (buffer, &endptr);
43b1b9ed
IB
931
932 if (endptr == NULL || endptr != (buffer + len))
933 return NULL;
934
2a523cfe 935 len = snprintf (buffer, sizeof(buffer), "%#g", value);
43b1b9ed
IB
936 string_appendn (decl, buffer, len);
937 return mangled;
938}
939
940/* Convert VAL from an ascii hexdigit to value. */
941static char
942ascii2hex (char val)
943{
944 if (val >= 'a' && val <= 'f')
945 return (val - 'a' + 10);
946
947 if (val >= 'A' && val <= 'F')
948 return (val - 'A' + 10);
949
950 if (val >= '0' && val <= '9')
951 return (val - '0');
952
953 return 0;
954}
955
956/* Extract the string value from MANGLED and append it to DECL.
957 Return the remaining string on success or NULL on failure. */
958static const char *
959dlang_parse_string (string *decl, const char *mangled)
960{
961 char type = *mangled;
962 char *endptr;
963 long len;
964
965 mangled++;
966 len = strtol (mangled, &endptr, 10);
967
968 if (endptr == NULL || len < 0)
969 return NULL;
970
971 mangled = endptr;
972 if (*mangled != '_')
973 return NULL;
974
975 mangled++;
976 string_append (decl, "\"");
977 while (len--)
978 {
979 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
980 {
981 char a = ascii2hex (mangled[0]);
982 char b = ascii2hex (mangled[1]);
983 char val = (a << 4) | b;
eb058b7d
IB
984
985 /* Sanitize white and non-printable characters. */
986 switch (val)
987 {
988 case ' ':
989 string_append (decl, " ");
990 break;
991 case '\t':
992 string_append (decl, "\\t");
993 break;
994 case '\n':
995 string_append (decl, "\\n");
996 break;
997 case '\r':
998 string_append (decl, "\\r");
999 break;
1000 case '\f':
1001 string_append (decl, "\\f");
1002 break;
1003 case '\v':
1004 string_append (decl, "\\v");
1005 break;
1006
1007 default:
1008 if (ISPRINT (val))
1009 string_appendn (decl, &val, 1);
1010 else
1011 {
1012 string_append (decl, "\\x");
1013 string_appendn (decl, mangled, 2);
1014 }
1015 }
43b1b9ed
IB
1016 }
1017 else
1018 return NULL;
1019
1020 mangled += 2;
1021 }
1022 string_append (decl, "\"");
1023
1024 if (type != 'a')
1025 string_appendn (decl, &type, 1);
1026
1027 return mangled;
1028}
1029
1030/* Extract the static array value from MANGLED and append it to DECL.
1031 Return the remaining string on success or NULL on failure. */
1032static const char *
1033dlang_parse_arrayliteral (string *decl, const char *mangled)
1034{
1035 char *endptr;
1036 long elements = strtol (mangled, &endptr, 10);
1037
1038 if (endptr == NULL || elements < 0)
1039 return NULL;
1040
1041 mangled = endptr;
1042 string_append (decl, "[");
1043 while (elements--)
1044 {
1045 mangled = dlang_value (decl, mangled, NULL, '\0');
1046 if (elements != 0)
1047 string_append (decl, ", ");
1048 }
1049
1050 string_append (decl, "]");
1051 return mangled;
1052}
1053
1054/* Extract the associative array value from MANGLED and append it to DECL.
1055 Return the remaining string on success or NULL on failure. */
1056static const char *
1057dlang_parse_assocarray (string *decl, const char *mangled)
1058{
1059 char *endptr;
1060 long elements = strtol (mangled, &endptr, 10);
1061
1062 if (endptr == NULL || elements < 0)
1063 return NULL;
1064
1065 mangled = endptr;
1066 string_append (decl, "[");
1067 while (elements--)
1068 {
1069 mangled = dlang_value (decl, mangled, NULL, '\0');
1070 string_append (decl, ":");
1071 mangled = dlang_value (decl, mangled, NULL, '\0');
1072
1073 if (elements != 0)
1074 string_append (decl, ", ");
1075 }
1076
1077 string_append (decl, "]");
1078 return mangled;
1079}
1080
1081/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1082 Return the remaining string on success or NULL on failure. */
1083static const char *
1084dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1085{
1086 char *endptr;
1087 long args = strtol (mangled, &endptr, 10);
1088
1089 if (endptr == NULL || args < 0)
1090 return NULL;
1091
1092 mangled = endptr;
1093 if (name != NULL)
1094 string_append (decl, name);
1095
1096 string_append (decl, "(");
1097 while (args--)
1098 {
1099 mangled = dlang_value (decl, mangled, NULL, '\0');
1100 if (args != 0)
1101 string_append (decl, ", ");
1102 }
1103
1104 string_append (decl, ")");
1105 return mangled;
1106}
1107
1108/* Extract the value from MANGLED and append it to DECL.
1109 Return the remaining string on success or NULL on failure. */
1110static const char *
1111dlang_value (string *decl, const char *mangled, const char *name, char type)
1112{
1113 if (mangled == NULL || *mangled == '\0')
76b41cad 1114 return NULL;
43b1b9ed
IB
1115
1116 switch (*mangled)
1117 {
1118 /* Null value. */
1119 case 'n':
1120 mangled++;
1121 string_append (decl, "null");
1122 break;
1123
1124 /* Integral values. */
1125 case 'N':
1126 mangled++;
1127 string_append (decl, "-");
1128 mangled = dlang_parse_integer (decl, mangled, type);
1129 break;
1130
1131 case 'i':
1132 mangled++;
1133 if (*mangled < '0' || *mangled > '9')
1134 return NULL;
1135 /* Fall through */
1136 case '0': case '1': case '2': case '3': case '4':
1137 case '5': case '6': case '7': case '8': case '9':
1138 mangled = dlang_parse_integer (decl, mangled, type);
1139 break;
1140
1141 /* Real value. */
1142 case 'e':
1143 mangled++;
1144 mangled = dlang_parse_real (decl, mangled);
1145 break;
1146
1147 /* Complex value. */
1148 case 'c':
1149 mangled++;
1150 mangled = dlang_parse_real (decl, mangled);
1151 string_append (decl, "+");
1152 if (mangled == NULL || *mangled != 'c')
1153 return NULL;
1154 mangled++;
1155 mangled = dlang_parse_real (decl, mangled);
1156 string_append (decl, "i");
1157 break;
1158
1159 /* String values. */
1160 case 'a': /* UTF8 */
1161 case 'w': /* UTF16 */
1162 case 'd': /* UTF32 */
1163 mangled = dlang_parse_string (decl, mangled);
1164 break;
1165
1166 /* Array values. */
1167 case 'A':
1168 mangled++;
1169 if (type == 'H')
1170 mangled = dlang_parse_assocarray (decl, mangled);
1171 else
1172 mangled = dlang_parse_arrayliteral (decl, mangled);
1173 break;
1174
1175 /* Struct values. */
1176 case 'S':
1177 mangled++;
1178 mangled = dlang_parse_structlit (decl, mangled, name);
1179 break;
1180
1181 default:
1182 return NULL;
1183 }
1184
1185 return mangled;
1186}
1187
fa66ced4
IB
1188/* Extract the type modifiers from MANGLED and return the string
1189 length that it consumes in MANGLED on success or 0 on failure. */
43b1b9ed 1190static int
fa66ced4 1191dlang_type_modifier_p (const char *mangled)
43b1b9ed 1192{
fa66ced4 1193 int i;
43b1b9ed
IB
1194
1195 switch (*mangled)
1196 {
fa66ced4 1197 case 'x': case 'y':
43b1b9ed
IB
1198 return 1;
1199
fa66ced4
IB
1200 case 'O':
1201 mangled++;
1202 i = dlang_type_modifier_p (mangled);
1203 return i + 1;
43b1b9ed 1204
fa66ced4
IB
1205 case 'N':
1206 mangled++;
1207 if (*mangled == 'g')
43b1b9ed 1208 {
fa66ced4
IB
1209 mangled++;
1210 i = dlang_type_modifier_p (mangled);
1211 return i + 2;
43b1b9ed 1212 }
fa66ced4
IB
1213 }
1214
1215 return 0;
1216}
1217
1218/* Extract the function calling convention from MANGLED and
1219 return 1 on success or 0 on failure. */
1220static int
1221dlang_call_convention_p (const char *mangled)
1222{
1223 /* Prefix for functions needing 'this' */
1224 if (*mangled == 'M')
1225 {
1226 mangled++;
1227 /* Also skip over any type modifiers. */
1228 mangled += dlang_type_modifier_p (mangled);
1229 }
1230
1231 switch (*mangled)
1232 {
1233 case 'F': case 'U': case 'V':
1234 case 'W': case 'R':
1235 return 1;
43b1b9ed
IB
1236
1237 default:
1238 return 0;
1239 }
1240}
1241
1242/* Extract and demangle the symbol in MANGLED and append it to DECL.
1243 Returns the remaining signature on success or NULL on failure. */
1244static const char *
1245dlang_parse_symbol (string *decl, const char *mangled)
1246{
1247 size_t n = 0;
1248 do
1249 {
1250 if (n++)
1251 string_append (decl, ".");
1252
1253 mangled = dlang_identifier (decl, mangled);
1254
1255 if (mangled && dlang_call_convention_p (mangled))
1256 {
fa66ced4 1257 string mods;
43b1b9ed
IB
1258 int saved;
1259
1260 /* Skip over 'this' parameter. */
1261 if (*mangled == 'M')
fa66ced4
IB
1262 mangled++;
1263
1264 /* Save the type modifiers for appending at the end. */
1265 string_init (&mods);
1266 mangled = dlang_type_modifiers (&mods, mangled);
43b1b9ed
IB
1267
1268 /* Skip over calling convention and attributes in qualified name. */
1269 saved = string_length (decl);
1270 mangled = dlang_call_convention (decl, mangled);
1271 mangled = dlang_attributes (decl, mangled);
1272 string_setlength (decl, saved);
1273
1274 string_append (decl, "(");
1275 mangled = dlang_function_args (decl, mangled);
1276 string_append (decl, ")");
1277
1278 /* Demangle the function return type as a kind of sanity test. */
1279 if (mangled && !ISDIGIT (*mangled))
1280 {
1281 saved = string_length (decl);
1282 mangled = dlang_type (decl, mangled);
1283 string_setlength (decl, saved);
1284 }
fa66ced4
IB
1285
1286 /* Add any const/immutable/shared modifier. */
1287 string_appendn (decl, mods.b, string_length (&mods));
1288 string_delete (&mods);
43b1b9ed
IB
1289 }
1290 }
1291 while (mangled && ISDIGIT (*mangled));
1292
1293 return mangled;
1294}
1295
1296/* Demangle the tuple from MANGLED and append it to DECL.
1297 Return the remaining string on success or NULL on failure. */
1298static const char *
1299dlang_parse_tuple (string *decl, const char *mangled)
1300{
1301 char *endptr;
1302 long elements = strtol (mangled, &endptr, 10);
1303
1304 if (endptr == NULL || elements < 0)
1305 return NULL;
1306
1307 mangled = endptr;
1308 string_append (decl, "Tuple!(");
1309
1310 while (elements--)
1311 {
1312 mangled = dlang_type (decl, mangled);
1313 if (elements != 0)
1314 string_append (decl, ", ");
1315 }
1316
1317 string_append (decl, ")");
1318 return mangled;
1319}
1320
1321/* Demangle the argument list from MANGLED and append it to DECL.
1322 Return the remaining string on success or NULL on failure. */
1323static const char *
1324dlang_template_args (string *decl, const char *mangled)
1325{
1326 size_t n = 0;
1327
1328 while (mangled && *mangled != '\0')
1329 {
1330 switch (*mangled)
1331 {
1332 case 'Z': /* End of parameter list. */
1333 mangled++;
1334 return mangled;
1335 }
1336
1337 if (n++)
1338 string_append (decl, ", ");
1339
1340 switch (*mangled)
1341 {
1342 case 'S': /* Symbol parameter. */
1343 mangled++;
1344 mangled = dlang_parse_symbol (decl, mangled);
1345 break;
1346 case 'T': /* Type parameter. */
1347 mangled++;
1348 mangled = dlang_type (decl, mangled);
1349 break;
1350 case 'V': /* Value parameter. */
1351 {
1352 string name;
1353 char type;
1354
1355 /* Peek at the type. */
1356 mangled++;
1357 type = *mangled;
1358
1359 /* In the few instances where the type is actually desired in
1360 the output, it should precede the value from dlang_value. */
1361 string_init (&name);
1362 mangled = dlang_type (&name, mangled);
1363 string_need (&name, 1);
1364 *(name.p) = '\0';
1365
1366 mangled = dlang_value (decl, mangled, name.b, type);
1367 string_delete (&name);
1368 break;
1369 }
1370
1371 default:
1372 return NULL;
1373 }
1374 }
1375
1376 return mangled;
1377}
1378
1379/* Extract and demangle the template symbol in MANGLED, expected to
1380 be made up of LEN characters, and append it to DECL.
1381 Returns the remaining signature on success or NULL on failure. */
1382static const char *
1383dlang_parse_template (string *decl, const char *mangled, long len)
1384{
1385 const char *start = mangled;
1386
1387 /* Template instance names have the types and values of its parameters
1388 encoded into it.
1389
1390 TemplateInstanceName:
1391 Number __T LName TemplateArgs Z
1392 ^
1393 The start pointer should be at the above location, and LEN should be
1394 the value of the decoded number.
1395 */
1396 if (strncmp (mangled, "__T", 3) != 0)
1397 return NULL;
1398
1399 mangled += 3;
1400
1401 /* Template identifier. */
1402 mangled = dlang_identifier (decl, mangled);
1403
1404 /* Template arguments. */
1405 string_append (decl, "!(");
1406 mangled = dlang_template_args (decl, mangled);
1407 string_append (decl, ")");
1408
1409 /* Check for template name length mismatch. */
1410 if (mangled && (mangled - start) != len)
1411 return NULL;
1412
1413 return mangled;
1414}
1415
1416/* Extract and demangle the symbol in MANGLED. Returns the demangled
1417 signature on success or NULL on failure. */
1418
1419char *
1420dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1421{
1422 string decl;
1423 char *demangled = NULL;
1424
1425 if (mangled == NULL || *mangled == '\0')
1426 return NULL;
1427
1428 if (strncmp (mangled, "_D", 2) != 0)
1429 return NULL;
1430
1431 string_init (&decl);
1432
1433 if (strcmp (mangled, "_Dmain") == 0)
1434 {
1435 string_append (&decl, "D main");
1436 }
1437 else
1438 {
1439 mangled += 2;
1440
1441 if (dlang_parse_symbol (&decl, mangled) == NULL)
1442 string_delete (&decl);
1443 }
1444
1445 if (string_length (&decl) > 0)
1446 {
1447 string_need (&decl, 1);
1448 *(decl.p) = '\0';
1449 demangled = decl.b;
1450 }
1451
1452 return demangled;
1453}
1454