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