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