Merge branch 'vendor/LIBRESSL'
[dragonfly.git] / contrib / binutils-2.27 / libiberty / d-demangle.c
1 /* Demangler for the D programming language
2    Copyright 2014, 2015, 2016 Free Software Foundation, Inc.
3    Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 In addition to the permissions in the GNU Library General Public
12 License, the Free Software Foundation gives you unlimited permission
13 to link the compiled version of this file into combinations with other
14 programs, and to distribute those combinations without any restriction
15 coming from the use of this file.  (The Library Public License
16 restrictions do apply in other respects; for example, they cover
17 modification of the file, and distribution when not linked into a
18 combined executable.)
19
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 Library General Public License for more details.
24
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>.  */
28
29 /* This file exports one function; dlang_demangle.
30
31    This file imports strtol for decoding mangled literals.  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "safe-ctype.h"
38
39 #include <sys/types.h>
40 #include <string.h>
41 #include <stdio.h>
42
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #else
46 extern long strtol (const char *nptr, char **endptr, int base);
47 #endif
48
49 #include <demangle.h>
50 #include "libiberty.h"
51
52 /* A mini string-handling package */
53
54 typedef 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
61 static void
62 string_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
86 static void
87 string_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
96 static void
97 string_init (string *s)
98 {
99   s->b = s->p = s->e = NULL;
100 }
101
102 static int
103 string_length (string *s)
104 {
105   if (s->p == s->b)
106     {
107       return 0;
108     }
109   return s->p - s->b;
110 }
111
112 static void
113 string_setlength (string *s, int n)
114 {
115   if (n - string_length (s) < 0)
116     {
117       s->p = s->b + n;
118     }
119 }
120
121 static void
122 string_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
130 static void
131 string_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
141 static void
142 string_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
158 static void
159 string_prepend (string *p, const char *s)
160 {
161   if (s != NULL && *s != '\0')
162     {
163       string_prependn (p, s, strlen (s));
164     }
165 }
166
167 /* What kinds of symbol we could be parsing.  */
168 enum 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
182 /* Prototypes for forward referenced functions */
183 static const char *dlang_function_args (string *, const char *);
184
185 static const char *dlang_type (string *, const char *);
186
187 static const char *dlang_value (string *, const char *, const char *, char);
188
189 static const char *dlang_parse_symbol (string *, const char *,
190                                        enum dlang_symbol_kinds);
191
192 static const char *dlang_parse_tuple (string *, const char *);
193
194 static 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.  */
199 static const char *
200 dlang_call_convention (string *decl, const char *mangled)
201 {
202   if (mangled == NULL || *mangled == '\0')
203     return NULL;
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     case 'Y': /* (Objective-C) */
227       mangled++;
228       string_append (decl, "extern(Objective-C) ");
229       break;
230     default:
231       return NULL;
232     }
233
234   return mangled;
235 }
236
237 /* Extract the type modifiers from MANGLED and append them to DECL.
238    Returns the remaining signature on success or NULL on failure.  */
239 static const char *
240 dlang_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
275 /* Demangle the D function attributes from MANGLED and append it to DECL.
276    Return the remaining string on success or NULL on failure.  */
277 static const char *
278 dlang_attributes (string *decl, const char *mangled)
279 {
280   if (mangled == NULL || *mangled == '\0')
281     return NULL;
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':
314         case 'k':
315           /* inout parameter is represented as 'Ng'.
316              vector parameter is represented as 'Nh'.
317              return paramenter is represented as 'Nk'.
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;
326         case 'j': /* return */
327           mangled++;
328           string_append (decl, "return ");
329           continue;
330
331         default: /* unknown attribute */
332           return NULL;
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.  */
342 static const char *
343 dlang_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')
349     return NULL;
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.  */
391 static const char *
392 dlang_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++;
406           if (n != 0)
407             string_append (decl, ", ");
408           string_append (decl, "...");
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
424       if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
425         {
426           mangled += 2;
427           string_append (decl, "return ");
428         }
429
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.  */
453 static const char *
454 dlang_type (string *decl, const char *mangled)
455 {
456   if (mangled == NULL || *mangled == '\0')
457     return NULL;
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++;
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         }
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++;
560       return dlang_parse_symbol (decl, mangled, dlang_type_name);
561     case 'D': /* delegate T */
562     {
563       string mods;
564       size_t szmods;
565       mangled++;
566
567       string_init (&mods);
568       mangled = dlang_type_modifiers (&mods, mangled);
569       szmods = string_length (&mods);
570
571       mangled = dlang_function_type (decl, mangled);
572       string_append (decl, "delegate");
573       string_appendn (decl, mods.b, szmods);
574
575       string_delete (&mods);
576       return mangled;
577     }
578     case 'B': /* tuple T */
579       mangled++;
580       return dlang_parse_tuple (decl, mangled);
581
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;
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;
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.  */
701 static const char *
702 dlang_identifier (string *decl, const char *mangled,
703                   enum dlang_symbol_kinds kind)
704 {
705   char *endptr;
706   long len;
707
708   if (mangled == NULL || *mangled == '\0')
709     return NULL;
710
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)
720     {
721       long psize = len;
722       char *pend;
723       int saved = string_length (decl);
724
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)
763         return NULL;
764
765       mangled = endptr;
766
767       /* May be a template instance.  */
768       if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
769         {
770           /* Template symbol.  */
771           if (ISDIGIT (mangled[3]) && mangled[3] != '0')
772             return dlang_parse_template (decl, mangled, len);
773
774           return NULL;
775         }
776
777       switch (len)
778         {
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;
853         }
854
855       string_appendn (decl, mangled, len);
856       mangled += len;
857     }
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.  */
865 static const char *
866 dlang_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.  */
975 static const char *
976 dlang_parse_real (string *decl, const char *mangled)
977 {
978   char buffer[64];
979   int len = 0;
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
1043   /* Write out the demangled hexadecimal, rather than trying to
1044      convert the buffer into a floating-point value.  */
1045   buffer[len] = '\0';
1046   len = strlen (buffer);
1047   string_appendn (decl, buffer, len);
1048   return mangled;
1049 }
1050
1051 /* Convert VAL from an ascii hexdigit to value.  */
1052 static char
1053 ascii2hex (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.  */
1069 static const char *
1070 dlang_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;
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             }
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.  */
1143 static const char *
1144 dlang_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.  */
1167 static const char *
1168 dlang_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.  */
1194 static const char *
1195 dlang_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.  */
1221 static const char *
1222 dlang_value (string *decl, const char *mangled, const char *name, char type)
1223 {
1224   if (mangled == NULL || *mangled == '\0')
1225     return NULL;
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
1299 /* Extract the type modifiers from MANGLED and return the string
1300    length that it consumes in MANGLED on success or 0 on failure.  */
1301 static int
1302 dlang_type_modifier_p (const char *mangled)
1303 {
1304   int i;
1305
1306   switch (*mangled)
1307     {
1308     case 'x': case 'y':
1309       return 1;
1310
1311     case 'O':
1312       mangled++;
1313       i = dlang_type_modifier_p (mangled);
1314       return i + 1;
1315
1316     case 'N':
1317       mangled++;
1318       if (*mangled == 'g')
1319         {
1320           mangled++;
1321           i = dlang_type_modifier_p (mangled);
1322           return i + 2;
1323         }
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.  */
1331 static int
1332 dlang_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':
1345     case 'W': case 'R': case 'Y':
1346       return 1;
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.  */
1355 static const char *
1356 dlang_parse_symbol (string *decl, const char *mangled,
1357                     enum dlang_symbol_kinds kind)
1358 {
1359   int saved;
1360   size_t n = 0;
1361   do
1362     {
1363       if (n++)
1364         string_append (decl, ".");
1365
1366       mangled = dlang_identifier (decl, mangled, kind);
1367
1368       if (mangled && dlang_call_convention_p (mangled))
1369         {
1370           string mods;
1371           const char *start = NULL;
1372           int checkpoint = 0;
1373
1374           /* Skip over 'this' parameter.  */
1375           if (*mangled == 'M')
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);
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
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)
1407             {
1408               mangled = start;
1409               string_setlength (decl, checkpoint);
1410             }
1411         }
1412     }
1413   while (mangled && ISDIGIT (*mangled));
1414
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
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.  */
1442 static const char *
1443 dlang_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.  */
1467 static const char *
1468 dlang_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
1484       /* Skip over specialised template prefix.  */
1485       if (*mangled == 'H')
1486         mangled++;
1487
1488       switch (*mangled)
1489         {
1490         case 'S': /* Symbol parameter.  */
1491           mangled++;
1492           mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
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.  */
1530 static const char *
1531 dlang_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.  */
1550   mangled = dlang_identifier (decl, mangled, dlang_template_ident);
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
1567 char *
1568 dlang_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
1589       if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
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