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