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