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