]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
d-demangle.c (dlang_parse_string): Represent embedded whitespace or non-printable...
[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')
188 return mangled;
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
218/* Demangle the D function attributes from MANGLED and append it to DECL.
219 Return the remaining string on success or NULL on failure. */
220static const char *
221dlang_attributes (string *decl, const char *mangled)
222{
223 if (mangled == NULL || *mangled == '\0')
224 return mangled;
225
226 while (*mangled == 'N')
227 {
228 mangled++;
229 switch (*mangled)
230 {
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;
267 }
268 break;
269 }
270
271 return mangled;
272}
273
274/* Demangle the function type from MANGLED and append it to DECL.
275 Return the remaining string on success or NULL on failure. */
276static const char *
277dlang_function_type (string *decl, const char *mangled)
278{
279 string attr, args, type;
280 size_t szattr, szargs, sztype;
281
282 if (mangled == NULL || *mangled == '\0')
283 return mangled;
284
285 /* The order of the mangled string is:
286 CallConvention FuncAttrs Arguments ArgClose Type
287
288 The demangled string is re-ordered as:
289 CallConvention Type Arguments FuncAttrs
290 */
291 string_init (&attr);
292 string_init (&args);
293 string_init (&type);
294
295 /* Function call convention. */
296 mangled = dlang_call_convention (decl, mangled);
297
298 /* Function attributes. */
299 mangled = dlang_attributes (&attr, mangled);
300 szattr = string_length (&attr);
301
302 /* Function arguments. */
303 mangled = dlang_function_args (&args, mangled);
304 szargs = string_length (&args);
305
306 /* Function return type. */
307 mangled = dlang_type (&type, mangled);
308 sztype = string_length (&type);
309
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);
316
317 string_delete (&attr);
318 string_delete (&args);
319 string_delete (&type);
320 return mangled;
321}
322
323/* Demangle the argument list from MANGLED and append it to DECL.
324 Return the remaining string on success or NULL on failure. */
325static const char *
326dlang_function_args (string *decl, const char *mangled)
327{
328 size_t n = 0;
329
330 while (mangled && *mangled != '\0')
331 {
332 switch (*mangled)
333 {
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;
345 }
346
347 if (n++)
348 string_append (decl, ", ");
349
350 if (*mangled == 'M') /* scope(T) */
351 {
352 mangled++;
353 string_append (decl, "scope ");
354 }
355
356 switch (*mangled)
357 {
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;
370 }
371 mangled = dlang_type (decl, mangled);
372 }
373
374 return mangled;
375}
376
377/* Demangle the type from MANGLED and append it to DECL.
378 Return the remaining string on success or NULL on failure. */
379static const char *
380dlang_type (string *decl, const char *mangled)
381{
382 if (mangled == NULL || *mangled == '\0')
383 return mangled;
384
385 switch (*mangled)
386 {
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) */
408 {
409 mangled++;
410 string_append (decl, "inout(");
411 mangled = dlang_type (decl, mangled);
412 string_append (decl, ")");
413 return mangled;
414 }
415 else if (*mangled == 'h') /* vector(T) */
416 {
417 mangled++;
418 string_append (decl, "__vector(");
419 mangled = dlang_type (decl, mangled);
420 string_append (decl, ")");
421 return mangled;
422 }
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]) */
431 {
432 const char *numptr;
433 size_t num = 0;
434 mangled++;
435
436 numptr = mangled;
437 while (ISDIGIT (*mangled))
438 {
439 num++;
440 mangled++;
441 }
442 mangled = dlang_type (decl, mangled);
443 string_append (decl, "[");
444 string_appendn (decl, numptr, num);
445 string_append (decl, "]");
446 return mangled;
447 }
448 case 'H': /* associative array (T[T]) */
449 {
450 string type;
451 size_t sztype;
452 mangled++;
453
454 string_init (&type);
455 mangled = dlang_type (&type, mangled);
456 sztype = string_length (&type);
457
458 mangled = dlang_type (decl, mangled);
459 string_append (decl, "[");
460 string_appendn (decl, type.b, sztype);
461 string_append (decl, "]");
462
463 string_delete (&type);
464 return mangled;
465 }
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);
486
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;
493
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;
547
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;
573
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;
591
592 default: /* unhandled */
593 return NULL;
594 }
595}
596
597/* Extract the identifier from MANGLED and append it to DECL.
598 Return the remaining string on success or NULL on failure. */
599static const char *
600dlang_identifier (string *decl, const char *mangled)
601{
602 if (mangled == NULL || *mangled == '\0')
603 return mangled;
604
605 if (ISDIGIT (*mangled))
606 {
607 char *endptr;
608 long i = strtol (mangled, &endptr, 10);
609
610 if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
611 return NULL;
612
613 mangled = endptr;
614
615 /* May be a template instance. */
616 if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
617 {
618 /* Template symbol. */
619 if (ISDIGIT (mangled[3]) && mangled[3] != '0')
620 return dlang_parse_template (decl, mangled, i);
621
622 return NULL;
623 }
624
625 if (strncmp (mangled, "__ctor", i) == 0)
626 {
627 /* Constructor symbol for a class/struct. */
628 string_append (decl, "this");
629 mangled += i;
630 return mangled;
631 }
632 else if (strncmp (mangled, "__dtor", i) == 0)
633 {
634 /* Destructor symbol for a class/struct. */
635 string_append (decl, "~this");
636 mangled += i;
637 return mangled;
638 }
639 else if (strncmp (mangled, "__postblit", i) == 0)
640 {
641 /* Postblit symbol for a struct. */
642 string_append (decl, "this(this)");
643 mangled += i;
644 return mangled;
645 }
646 else if (strncmp (mangled, "__initZ", i+1) == 0)
647 {
648 /* The static initialiser for a given symbol. */
649 string_append (decl, "init$");
650 mangled += i + 1;
651 return mangled;
652 }
653 else if (strncmp (mangled, "__ClassZ", i+1) == 0)
654 {
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;
660 }
661 else if (strncmp (mangled, "__vtblZ", i+1) == 0)
662 {
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;
668 }
669 else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
670 {
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;
676 }
677 else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
678 {
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;
684 }
685
686 string_appendn (decl, mangled, i);
687 mangled += i;
688 }
689 else
690 return NULL;
691
692 return mangled;
693}
694
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. */
698static const char *
699dlang_parse_integer (string *decl, const char *mangled, char type)
700{
701 if (type == 'a' || type == 'u' || type == 'w')
702 {
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);
709
710 if (endptr == NULL || val < 0)
711 return NULL;
712
713 string_append (decl, "'");
714
715 if (type == 'a' && val >= 0x20 && val < 0x7F)
716 {
717 /* Represent as a character literal. */
718 char c = (char) val;
719 string_appendn (decl, &c, 1);
720 }
721 else
722 {
723 /* Represent as a hexadecimal value. */
724 switch (type)
725 {
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;
738 }
739
740 while (val > 0)
741 {
742 int digit = val % 16;
743
744 if (digit < 10)
745 value[--pos] = (char)(digit + '0');
746 else
747 value[--pos] = (char)((digit - 10) + 'a');
748
749 val /= 16;
750 width--;
751 }
752
753 for (; width > 0; width--)
754 value[--pos] = '0';
755
756 string_appendn (decl, &(value[pos]), 10 - pos);
757 }
758 string_append (decl, "'");
759 mangled = endptr;
760 }
761 else if (type == 'b')
762 {
763 /* Parse boolean value. */
764 char *endptr;
765 long val = strtol (mangled, &endptr, 10);
766
767 if (endptr == NULL || val < 0)
768 return NULL;
769
770 string_append (decl, val ? "true" : "false");
771 mangled = endptr;
772 }
773 else
774 {
775 /* Parse integer value. */
776 const char *numptr = mangled;
777 size_t num = 0;
778
779 while (ISDIGIT (*mangled))
780 {
781 num++;
782 mangled++;
783 }
784 string_appendn (decl, numptr, num);
785
786 /* Append suffix. */
787 switch (type)
788 {
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;
800 }
801 }
802
803 return mangled;
804}
805
806/* Extract the floating-point value from MANGLED and append it to DECL.
807 Return the remaining string on success or NULL on failure. */
808static const char *
809dlang_parse_real (string *decl, const char *mangled)
810{
811 char buffer[64];
812 int len = 0;
2a523cfe 813 double value;
43b1b9ed
IB
814 char *endptr;
815
816 /* Handle NAN and +-INF. */
817 if (strncmp (mangled, "NAN", 3) == 0)
818 {
819 string_append (decl, "NaN");
820 mangled += 3;
821 return mangled;
822 }
823 else if (strncmp (mangled, "INF", 3) == 0)
824 {
825 string_append (decl, "Inf");
826 mangled += 3;
827 return mangled;
828 }
829 else if (strncmp (mangled, "NINF", 4) == 0)
830 {
831 string_append (decl, "-Inf");
832 mangled += 4;
833 return mangled;
834 }
835
836 /* Hexadecimal prefix and leading bit. */
837 if (*mangled == 'N')
838 {
839 buffer[len++] = '-';
840 mangled++;
841 }
842
843 if (!ISXDIGIT (*mangled))
844 return NULL;
845
846 buffer[len++] = '0';
847 buffer[len++] = 'x';
848 buffer[len++] = *mangled;
849 buffer[len++] = '.';
850 mangled++;
851
852 /* Significand. */
853 while (ISXDIGIT (*mangled))
854 {
855 buffer[len++] = *mangled;
856 mangled++;
857 }
858
859 /* Exponent. */
860 if (*mangled != 'P')
861 return NULL;
862
863 buffer[len++] = 'p';
864 mangled++;
865
866 if (*mangled == 'N')
867 {
868 buffer[len++] = '-';
869 mangled++;
870 }
871
872 while (ISDIGIT (*mangled))
873 {
874 buffer[len++] = *mangled;
875 mangled++;
876 }
877
878 /* Convert buffer from hexadecimal to floating-point. */
879 buffer[len] = '\0';
2a523cfe 880 value = strtod (buffer, &endptr);
43b1b9ed
IB
881
882 if (endptr == NULL || endptr != (buffer + len))
883 return NULL;
884
2a523cfe 885 len = snprintf (buffer, sizeof(buffer), "%#g", value);
43b1b9ed
IB
886 string_appendn (decl, buffer, len);
887 return mangled;
888}
889
890/* Convert VAL from an ascii hexdigit to value. */
891static char
892ascii2hex (char val)
893{
894 if (val >= 'a' && val <= 'f')
895 return (val - 'a' + 10);
896
897 if (val >= 'A' && val <= 'F')
898 return (val - 'A' + 10);
899
900 if (val >= '0' && val <= '9')
901 return (val - '0');
902
903 return 0;
904}
905
906/* Extract the string value from MANGLED and append it to DECL.
907 Return the remaining string on success or NULL on failure. */
908static const char *
909dlang_parse_string (string *decl, const char *mangled)
910{
911 char type = *mangled;
912 char *endptr;
913 long len;
914
915 mangled++;
916 len = strtol (mangled, &endptr, 10);
917
918 if (endptr == NULL || len < 0)
919 return NULL;
920
921 mangled = endptr;
922 if (*mangled != '_')
923 return NULL;
924
925 mangled++;
926 string_append (decl, "\"");
927 while (len--)
928 {
929 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
930 {
931 char a = ascii2hex (mangled[0]);
932 char b = ascii2hex (mangled[1]);
933 char val = (a << 4) | b;
eb058b7d
IB
934
935 /* Sanitize white and non-printable characters. */
936 switch (val)
937 {
938 case ' ':
939 string_append (decl, " ");
940 break;
941 case '\t':
942 string_append (decl, "\\t");
943 break;
944 case '\n':
945 string_append (decl, "\\n");
946 break;
947 case '\r':
948 string_append (decl, "\\r");
949 break;
950 case '\f':
951 string_append (decl, "\\f");
952 break;
953 case '\v':
954 string_append (decl, "\\v");
955 break;
956
957 default:
958 if (ISPRINT (val))
959 string_appendn (decl, &val, 1);
960 else
961 {
962 string_append (decl, "\\x");
963 string_appendn (decl, mangled, 2);
964 }
965 }
43b1b9ed
IB
966 }
967 else
968 return NULL;
969
970 mangled += 2;
971 }
972 string_append (decl, "\"");
973
974 if (type != 'a')
975 string_appendn (decl, &type, 1);
976
977 return mangled;
978}
979
980/* Extract the static array value from MANGLED and append it to DECL.
981 Return the remaining string on success or NULL on failure. */
982static const char *
983dlang_parse_arrayliteral (string *decl, const char *mangled)
984{
985 char *endptr;
986 long elements = strtol (mangled, &endptr, 10);
987
988 if (endptr == NULL || elements < 0)
989 return NULL;
990
991 mangled = endptr;
992 string_append (decl, "[");
993 while (elements--)
994 {
995 mangled = dlang_value (decl, mangled, NULL, '\0');
996 if (elements != 0)
997 string_append (decl, ", ");
998 }
999
1000 string_append (decl, "]");
1001 return mangled;
1002}
1003
1004/* Extract the associative array value from MANGLED and append it to DECL.
1005 Return the remaining string on success or NULL on failure. */
1006static const char *
1007dlang_parse_assocarray (string *decl, const char *mangled)
1008{
1009 char *endptr;
1010 long elements = strtol (mangled, &endptr, 10);
1011
1012 if (endptr == NULL || elements < 0)
1013 return NULL;
1014
1015 mangled = endptr;
1016 string_append (decl, "[");
1017 while (elements--)
1018 {
1019 mangled = dlang_value (decl, mangled, NULL, '\0');
1020 string_append (decl, ":");
1021 mangled = dlang_value (decl, mangled, NULL, '\0');
1022
1023 if (elements != 0)
1024 string_append (decl, ", ");
1025 }
1026
1027 string_append (decl, "]");
1028 return mangled;
1029}
1030
1031/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1032 Return the remaining string on success or NULL on failure. */
1033static const char *
1034dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1035{
1036 char *endptr;
1037 long args = strtol (mangled, &endptr, 10);
1038
1039 if (endptr == NULL || args < 0)
1040 return NULL;
1041
1042 mangled = endptr;
1043 if (name != NULL)
1044 string_append (decl, name);
1045
1046 string_append (decl, "(");
1047 while (args--)
1048 {
1049 mangled = dlang_value (decl, mangled, NULL, '\0');
1050 if (args != 0)
1051 string_append (decl, ", ");
1052 }
1053
1054 string_append (decl, ")");
1055 return mangled;
1056}
1057
1058/* Extract the value from MANGLED and append it to DECL.
1059 Return the remaining string on success or NULL on failure. */
1060static const char *
1061dlang_value (string *decl, const char *mangled, const char *name, char type)
1062{
1063 if (mangled == NULL || *mangled == '\0')
1064 return mangled;
1065
1066 switch (*mangled)
1067 {
1068 /* Null value. */
1069 case 'n':
1070 mangled++;
1071 string_append (decl, "null");
1072 break;
1073
1074 /* Integral values. */
1075 case 'N':
1076 mangled++;
1077 string_append (decl, "-");
1078 mangled = dlang_parse_integer (decl, mangled, type);
1079 break;
1080
1081 case 'i':
1082 mangled++;
1083 if (*mangled < '0' || *mangled > '9')
1084 return NULL;
1085 /* Fall through */
1086 case '0': case '1': case '2': case '3': case '4':
1087 case '5': case '6': case '7': case '8': case '9':
1088 mangled = dlang_parse_integer (decl, mangled, type);
1089 break;
1090
1091 /* Real value. */
1092 case 'e':
1093 mangled++;
1094 mangled = dlang_parse_real (decl, mangled);
1095 break;
1096
1097 /* Complex value. */
1098 case 'c':
1099 mangled++;
1100 mangled = dlang_parse_real (decl, mangled);
1101 string_append (decl, "+");
1102 if (mangled == NULL || *mangled != 'c')
1103 return NULL;
1104 mangled++;
1105 mangled = dlang_parse_real (decl, mangled);
1106 string_append (decl, "i");
1107 break;
1108
1109 /* String values. */
1110 case 'a': /* UTF8 */
1111 case 'w': /* UTF16 */
1112 case 'd': /* UTF32 */
1113 mangled = dlang_parse_string (decl, mangled);
1114 break;
1115
1116 /* Array values. */
1117 case 'A':
1118 mangled++;
1119 if (type == 'H')
1120 mangled = dlang_parse_assocarray (decl, mangled);
1121 else
1122 mangled = dlang_parse_arrayliteral (decl, mangled);
1123 break;
1124
1125 /* Struct values. */
1126 case 'S':
1127 mangled++;
1128 mangled = dlang_parse_structlit (decl, mangled, name);
1129 break;
1130
1131 default:
1132 return NULL;
1133 }
1134
1135 return mangled;
1136}
1137
1138static int
1139dlang_call_convention_p (const char *mangled)
1140{
1141 size_t i;
1142
1143 switch (*mangled)
1144 {
1145 case 'F': case 'U': case 'V':
1146 case 'W': case 'R':
1147 return 1;
1148
1149 case 'M': /* Prefix for functions needing 'this' */
1150 i = 1;
1151 if (mangled[i] == 'x')
1152 i++;
1153
1154 switch (mangled[i])
1155 {
1156 case 'F': case 'U': case 'V':
1157 case 'W': case 'R':
1158 return 1;
1159 }
1160
1161 default:
1162 return 0;
1163 }
1164}
1165
1166/* Extract and demangle the symbol in MANGLED and append it to DECL.
1167 Returns the remaining signature on success or NULL on failure. */
1168static const char *
1169dlang_parse_symbol (string *decl, const char *mangled)
1170{
1171 size_t n = 0;
1172 do
1173 {
1174 if (n++)
1175 string_append (decl, ".");
1176
1177 mangled = dlang_identifier (decl, mangled);
1178
1179 if (mangled && dlang_call_convention_p (mangled))
1180 {
1181 int saved;
1182
1183 /* Skip over 'this' parameter. */
1184 if (*mangled == 'M')
1185 mangled += (mangled[1] == 'x') ? 2 : 1;
1186
1187 /* Skip over calling convention and attributes in qualified name. */
1188 saved = string_length (decl);
1189 mangled = dlang_call_convention (decl, mangled);
1190 mangled = dlang_attributes (decl, mangled);
1191 string_setlength (decl, saved);
1192
1193 string_append (decl, "(");
1194 mangled = dlang_function_args (decl, mangled);
1195 string_append (decl, ")");
1196
1197 /* Demangle the function return type as a kind of sanity test. */
1198 if (mangled && !ISDIGIT (*mangled))
1199 {
1200 saved = string_length (decl);
1201 mangled = dlang_type (decl, mangled);
1202 string_setlength (decl, saved);
1203 }
1204 }
1205 }
1206 while (mangled && ISDIGIT (*mangled));
1207
1208 return mangled;
1209}
1210
1211/* Demangle the tuple from MANGLED and append it to DECL.
1212 Return the remaining string on success or NULL on failure. */
1213static const char *
1214dlang_parse_tuple (string *decl, const char *mangled)
1215{
1216 char *endptr;
1217 long elements = strtol (mangled, &endptr, 10);
1218
1219 if (endptr == NULL || elements < 0)
1220 return NULL;
1221
1222 mangled = endptr;
1223 string_append (decl, "Tuple!(");
1224
1225 while (elements--)
1226 {
1227 mangled = dlang_type (decl, mangled);
1228 if (elements != 0)
1229 string_append (decl, ", ");
1230 }
1231
1232 string_append (decl, ")");
1233 return mangled;
1234}
1235
1236/* Demangle the argument list from MANGLED and append it to DECL.
1237 Return the remaining string on success or NULL on failure. */
1238static const char *
1239dlang_template_args (string *decl, const char *mangled)
1240{
1241 size_t n = 0;
1242
1243 while (mangled && *mangled != '\0')
1244 {
1245 switch (*mangled)
1246 {
1247 case 'Z': /* End of parameter list. */
1248 mangled++;
1249 return mangled;
1250 }
1251
1252 if (n++)
1253 string_append (decl, ", ");
1254
1255 switch (*mangled)
1256 {
1257 case 'S': /* Symbol parameter. */
1258 mangled++;
1259 mangled = dlang_parse_symbol (decl, mangled);
1260 break;
1261 case 'T': /* Type parameter. */
1262 mangled++;
1263 mangled = dlang_type (decl, mangled);
1264 break;
1265 case 'V': /* Value parameter. */
1266 {
1267 string name;
1268 char type;
1269
1270 /* Peek at the type. */
1271 mangled++;
1272 type = *mangled;
1273
1274 /* In the few instances where the type is actually desired in
1275 the output, it should precede the value from dlang_value. */
1276 string_init (&name);
1277 mangled = dlang_type (&name, mangled);
1278 string_need (&name, 1);
1279 *(name.p) = '\0';
1280
1281 mangled = dlang_value (decl, mangled, name.b, type);
1282 string_delete (&name);
1283 break;
1284 }
1285
1286 default:
1287 return NULL;
1288 }
1289 }
1290
1291 return mangled;
1292}
1293
1294/* Extract and demangle the template symbol in MANGLED, expected to
1295 be made up of LEN characters, and append it to DECL.
1296 Returns the remaining signature on success or NULL on failure. */
1297static const char *
1298dlang_parse_template (string *decl, const char *mangled, long len)
1299{
1300 const char *start = mangled;
1301
1302 /* Template instance names have the types and values of its parameters
1303 encoded into it.
1304
1305 TemplateInstanceName:
1306 Number __T LName TemplateArgs Z
1307 ^
1308 The start pointer should be at the above location, and LEN should be
1309 the value of the decoded number.
1310 */
1311 if (strncmp (mangled, "__T", 3) != 0)
1312 return NULL;
1313
1314 mangled += 3;
1315
1316 /* Template identifier. */
1317 mangled = dlang_identifier (decl, mangled);
1318
1319 /* Template arguments. */
1320 string_append (decl, "!(");
1321 mangled = dlang_template_args (decl, mangled);
1322 string_append (decl, ")");
1323
1324 /* Check for template name length mismatch. */
1325 if (mangled && (mangled - start) != len)
1326 return NULL;
1327
1328 return mangled;
1329}
1330
1331/* Extract and demangle the symbol in MANGLED. Returns the demangled
1332 signature on success or NULL on failure. */
1333
1334char *
1335dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1336{
1337 string decl;
1338 char *demangled = NULL;
1339
1340 if (mangled == NULL || *mangled == '\0')
1341 return NULL;
1342
1343 if (strncmp (mangled, "_D", 2) != 0)
1344 return NULL;
1345
1346 string_init (&decl);
1347
1348 if (strcmp (mangled, "_Dmain") == 0)
1349 {
1350 string_append (&decl, "D main");
1351 }
1352 else
1353 {
1354 mangled += 2;
1355
1356 if (dlang_parse_symbol (&decl, mangled) == NULL)
1357 string_delete (&decl);
1358 }
1359
1360 if (string_length (&decl) > 0)
1361 {
1362 string_need (&decl, 1);
1363 *(decl.p) = '\0';
1364 demangled = decl.b;
1365 }
1366
1367 return demangled;
1368}
1369