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