Resync files in the binutils repository that are maintained in the gcc repository.
[external/binutils.git] / libiberty / d-demangle.c
1 /* Demangler for the D programming language
2    Copyright 2014, 2015 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     default:
227       return NULL;
228     }
229
230   return mangled;
231 }
232
233 /* Extract the type modifiers from MANGLED and append them to DECL.
234    Returns the remaining signature on success or NULL on failure.  */
235 static const char *
236 dlang_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
271 /* Demangle the D function attributes from MANGLED and append it to DECL.
272    Return the remaining string on success or NULL on failure.  */
273 static const char *
274 dlang_attributes (string *decl, const char *mangled)
275 {
276   if (mangled == NULL || *mangled == '\0')
277     return NULL;
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':
310         case 'k':
311           /* inout parameter is represented as 'Ng'.
312              vector parameter is represented as 'Nh'.
313              return paramenter is represented as 'Nk'.
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;
322         case 'j': /* return */
323           mangled++;
324           string_append (decl, "return ");
325           continue;
326
327         default: /* unknown attribute */
328           return NULL;
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.  */
338 static const char *
339 dlang_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')
345     return NULL;
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.  */
387 static const char *
388 dlang_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
418       if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
419         {
420           mangled += 2;
421           string_append (decl, "return ");
422         }
423
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.  */
447 static const char *
448 dlang_type (string *decl, const char *mangled)
449 {
450   if (mangled == NULL || *mangled == '\0')
451     return NULL;
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++;
545       return dlang_parse_symbol (decl, mangled, dlang_type_name);
546     case 'D': /* delegate T */
547     {
548       string mods;
549       size_t szmods;
550       mangled++;
551
552       string_init (&mods);
553       mangled = dlang_type_modifiers (&mods, mangled);
554       szmods = string_length (&mods);
555
556       mangled = dlang_function_type (decl, mangled);
557       string_append (decl, "delegate");
558       string_appendn (decl, mods.b, szmods);
559
560       string_delete (&mods);
561       return mangled;
562     }
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;
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;
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.  */
693 static const char *
694 dlang_identifier (string *decl, const char *mangled,
695                   enum dlang_symbol_kinds kind)
696 {
697   char *endptr;
698   long len;
699
700   if (mangled == NULL || *mangled == '\0')
701     return NULL;
702
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)
712     {
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;
721
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)
755         return NULL;
756
757       mangled = endptr;
758
759       /* May be a template instance.  */
760       if (len >= 5 && strncmp (mangled, "__T", 3) == 0)
761         {
762           /* Template symbol.  */
763           if (ISDIGIT (mangled[3]) && mangled[3] != '0')
764             return dlang_parse_template (decl, mangled, len);
765
766           return NULL;
767         }
768
769       switch (len)
770         {
771         case 6:
772           if (strncmp (mangled, "__ctor", len) == 0)
773             {
774               /* Constructor symbol for a class/struct.  */
775               string_append (decl, "this");
776               mangled += len;
777               return mangled;
778             }
779           else if (strncmp (mangled, "__dtor", len) == 0)
780             {
781               /* Destructor symbol for a class/struct.  */
782               string_append (decl, "~this");
783               mangled += len;
784               return mangled;
785             }
786           else if (strncmp (mangled, "__initZ", len+1) == 0)
787             {
788               /* The static initialiser for a given symbol.  */
789               string_append (decl, "init$");
790               mangled += len;
791               return mangled;
792             }
793           else if (strncmp (mangled, "__vtblZ", len+1) == 0)
794             {
795               /* The vtable symbol for a given class.  */
796               string_prepend (decl, "vtable for ");
797               string_setlength (decl, string_length (decl) - 1);
798               mangled += len;
799               return mangled;
800             }
801           break;
802
803         case 7:
804           if (strncmp (mangled, "__ClassZ", len+1) == 0)
805             {
806               /* The classinfo symbol for a given class.  */
807               string_prepend (decl, "ClassInfo for ");
808               string_setlength (decl, string_length (decl) - 1);
809               mangled += len;
810               return mangled;
811             }
812           break;
813
814         case 10:
815           if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
816             {
817               /* Postblit symbol for a struct.  */
818               string_append (decl, "this(this)");
819               mangled += len + 3;
820               return mangled;
821             }
822           break;
823
824         case 11:
825           if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
826             {
827               /* The interface symbol for a given class.  */
828               string_prepend (decl, "Interface for ");
829               string_setlength (decl, string_length (decl) - 1);
830               mangled += len;
831               return mangled;
832             }
833           break;
834
835         case 12:
836           if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
837             {
838               /* The ModuleInfo symbol for a given module.  */
839               string_prepend (decl, "ModuleInfo for ");
840               string_setlength (decl, string_length (decl) - 1);
841               mangled += len;
842               return mangled;
843             }
844           break;
845         }
846
847       string_appendn (decl, mangled, len);
848       mangled += len;
849     }
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.  */
857 static const char *
858 dlang_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.  */
967 static const char *
968 dlang_parse_real (string *decl, const char *mangled)
969 {
970   char buffer[64];
971   int len = 0;
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
1035   /* Write out the demangled hexadecimal, rather than trying to
1036      convert the buffer into a floating-point value.  */
1037   buffer[len] = '\0';
1038   len = strlen (buffer);
1039   string_appendn (decl, buffer, len);
1040   return mangled;
1041 }
1042
1043 /* Convert VAL from an ascii hexdigit to value.  */
1044 static char
1045 ascii2hex (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.  */
1061 static const char *
1062 dlang_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;
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             }
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.  */
1135 static const char *
1136 dlang_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.  */
1159 static const char *
1160 dlang_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.  */
1186 static const char *
1187 dlang_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.  */
1213 static const char *
1214 dlang_value (string *decl, const char *mangled, const char *name, char type)
1215 {
1216   if (mangled == NULL || *mangled == '\0')
1217     return NULL;
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
1291 /* Extract the type modifiers from MANGLED and return the string
1292    length that it consumes in MANGLED on success or 0 on failure.  */
1293 static int
1294 dlang_type_modifier_p (const char *mangled)
1295 {
1296   int i;
1297
1298   switch (*mangled)
1299     {
1300     case 'x': case 'y':
1301       return 1;
1302
1303     case 'O':
1304       mangled++;
1305       i = dlang_type_modifier_p (mangled);
1306       return i + 1;
1307
1308     case 'N':
1309       mangled++;
1310       if (*mangled == 'g')
1311         {
1312           mangled++;
1313           i = dlang_type_modifier_p (mangled);
1314           return i + 2;
1315         }
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.  */
1323 static int
1324 dlang_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;
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.  */
1347 static const char *
1348 dlang_parse_symbol (string *decl, const char *mangled,
1349                     enum dlang_symbol_kinds kind)
1350 {
1351   int saved;
1352   size_t n = 0;
1353   do
1354     {
1355       if (n++)
1356         string_append (decl, ".");
1357
1358       mangled = dlang_identifier (decl, mangled, kind);
1359
1360       if (mangled && dlang_call_convention_p (mangled))
1361         {
1362           string mods;
1363           const char *start = NULL;
1364           int checkpoint = 0;
1365
1366           /* Skip over 'this' parameter.  */
1367           if (*mangled == 'M')
1368             mangled++;
1369
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
1380           /* Save the type modifiers for appending at the end.  */
1381           string_init (&mods);
1382           mangled = dlang_type_modifiers (&mods, mangled);
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
1394           /* Add any const/immutable/shared modifier. */
1395           string_appendn (decl, mods.b, string_length (&mods));
1396           string_delete (&mods);
1397
1398           if (mangled == NULL && checkpoint != 0)
1399             {
1400               mangled = start;
1401               string_setlength (decl, checkpoint);
1402             }
1403         }
1404     }
1405   while (mangled && ISDIGIT (*mangled));
1406
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
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.  */
1434 static const char *
1435 dlang_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.  */
1459 static const char *
1460 dlang_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
1476       /* Skip over specialised template prefix.  */
1477       if (*mangled == 'H')
1478         mangled++;
1479
1480       switch (*mangled)
1481         {
1482         case 'S': /* Symbol parameter.  */
1483           mangled++;
1484           mangled = dlang_parse_symbol (decl, mangled, dlang_template_param);
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.  */
1522 static const char *
1523 dlang_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.  */
1542   mangled = dlang_identifier (decl, mangled, dlang_template_ident);
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
1559 char *
1560 dlang_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
1581       if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL)
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