Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / libiberty / d-demangle.c
1 /* Demangler for the D programming language
2    Copyright 2014 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 /* Prototypes for forward referenced functions */
169 static const char *dlang_function_args (string *, const char *);
170
171 static const char *dlang_type (string *, const char *);
172
173 static const char *dlang_value (string *, const char *, const char *, char);
174
175 static const char *dlang_parse_symbol (string *, const char *);
176
177 static const char *dlang_parse_tuple (string *, const char *);
178
179 static const char *dlang_parse_template (string *, const char *, long);
180
181
182 /* Demangle the calling convention from MANGLED and append it to DECL.
183    Return the remaining string on success or NULL on failure.  */
184 static const char *
185 dlang_call_convention (string *decl, const char *mangled)
186 {
187   if (mangled == NULL || *mangled == '\0')
188     return mangled;
189
190   switch (*mangled)
191     {
192     case 'F': /* (D) */
193       mangled++;
194       break;
195     case 'U': /* (C) */
196       mangled++;
197       string_append (decl, "extern(C) ");
198       break;
199     case 'W': /* (Windows) */
200       mangled++;
201       string_append (decl, "extern(Windows) ");
202       break;
203     case 'V': /* (Pascal) */
204       mangled++;
205       string_append (decl, "extern(Pascal) ");
206       break;
207     case 'R': /* (C++) */
208       mangled++;
209       string_append (decl, "extern(C++) ");
210       break;
211     default:
212       return NULL;
213     }
214
215   return mangled;
216 }
217
218 /* Demangle the D function attributes from MANGLED and append it to DECL.
219    Return the remaining string on success or NULL on failure.  */
220 static const char *
221 dlang_attributes (string *decl, const char *mangled)
222 {
223   if (mangled == NULL || *mangled == '\0')
224     return mangled;
225
226   while (*mangled == 'N')
227     {
228       mangled++;
229       switch (*mangled)
230         {
231         case 'a': /* pure */
232           mangled++;
233           string_append (decl, "pure ");
234           continue;
235         case 'b': /* nothrow */
236           mangled++;
237           string_append (decl, "nothrow ");
238           continue;
239         case 'c': /* ref */
240           mangled++;
241           string_append (decl, "ref ");
242           continue;
243         case 'd': /* @property */
244           mangled++;
245           string_append (decl, "@property ");
246           continue;
247         case 'e': /* @trusted */
248           mangled++;
249           string_append (decl, "@trusted ");
250           continue;
251         case 'f': /* @safe */
252           mangled++;
253           string_append (decl, "@safe ");
254           continue;
255         case 'g':
256         case 'h':
257           /* inout parameter is represented as 'Ng'.
258              vector parameter is represented as 'Nh'.
259              If we see this, then we know we're really in the
260              parameter list.  Rewind and break.  */
261           mangled--;
262           break;
263         case 'i': /* @nogc */
264           mangled++;
265           string_append (decl, "@nogc ");
266           continue;
267         }
268       break;
269     }
270
271   return mangled;
272 }
273
274 /* Demangle the function type from MANGLED and append it to DECL.
275    Return the remaining string on success or NULL on failure.  */
276 static const char *
277 dlang_function_type (string *decl, const char *mangled)
278 {
279   string attr, args, type;
280   size_t szattr, szargs, sztype;
281
282   if (mangled == NULL || *mangled == '\0')
283     return mangled;
284
285   /* The order of the mangled string is:
286         CallConvention FuncAttrs Arguments ArgClose Type
287
288      The demangled string is re-ordered as:
289         CallConvention Type Arguments FuncAttrs
290    */
291   string_init (&attr);
292   string_init (&args);
293   string_init (&type);
294
295   /* Function call convention.  */
296   mangled = dlang_call_convention (decl, mangled);
297
298   /* Function attributes.  */
299   mangled = dlang_attributes (&attr, mangled);
300   szattr = string_length (&attr);
301
302   /* Function arguments.  */
303   mangled = dlang_function_args (&args, mangled);
304   szargs = string_length (&args);
305
306   /* Function return type.  */
307   mangled = dlang_type (&type, mangled);
308   sztype = string_length (&type);
309
310   /* Append to decl in order. */
311   string_appendn (decl, type.b, sztype);
312   string_append (decl, "(");
313   string_appendn (decl, args.b, szargs);
314   string_append (decl, ") ");
315   string_appendn (decl, attr.b, szattr);
316
317   string_delete (&attr);
318   string_delete (&args);
319   string_delete (&type);
320   return mangled;
321 }
322
323 /* Demangle the argument list from MANGLED and append it to DECL.
324    Return the remaining string on success or NULL on failure.  */
325 static const char *
326 dlang_function_args (string *decl, const char *mangled)
327 {
328   size_t n = 0;
329
330   while (mangled && *mangled != '\0')
331     {
332       switch (*mangled)
333         {
334         case 'X': /* (variadic T t...) style.  */
335           mangled++;
336           string_append (decl, "...");
337           return mangled;
338         case 'Y': /* (variadic T t, ...) style.  */
339           mangled++;
340           string_append (decl, ", ...");
341           return mangled;
342         case 'Z': /* Normal function.  */
343           mangled++;
344           return mangled;
345         }
346
347       if (n++)
348         string_append (decl, ", ");
349
350       if (*mangled == 'M') /* scope(T) */
351         {
352           mangled++;
353           string_append (decl, "scope ");
354         }
355
356       switch (*mangled)
357         {
358         case 'J': /* out(T) */
359           mangled++;
360           string_append (decl, "out ");
361           break;
362         case 'K': /* ref(T) */
363           mangled++;
364           string_append (decl, "ref ");
365           break;
366         case 'L': /* lazy(T) */
367           mangled++;
368           string_append (decl, "lazy ");
369           break;
370         }
371       mangled = dlang_type (decl, mangled);
372     }
373
374   return mangled;
375 }
376
377 /* Demangle the type from MANGLED and append it to DECL.
378    Return the remaining string on success or NULL on failure.  */
379 static const char *
380 dlang_type (string *decl, const char *mangled)
381 {
382   if (mangled == NULL || *mangled == '\0')
383     return mangled;
384
385   switch (*mangled)
386     {
387     case 'O': /* shared(T) */
388       mangled++;
389       string_append (decl, "shared(");
390       mangled = dlang_type (decl, mangled);
391       string_append (decl, ")");
392       return mangled;
393     case 'x': /* const(T) */
394       mangled++;
395       string_append (decl, "const(");
396       mangled = dlang_type (decl, mangled);
397       string_append (decl, ")");
398       return mangled;
399     case 'y': /* immutable(T) */
400       mangled++;
401       string_append (decl, "immutable(");
402       mangled = dlang_type (decl, mangled);
403       string_append (decl, ")");
404       return mangled;
405     case 'N':
406       mangled++;
407       if (*mangled == 'g') /* wild(T) */
408         {
409           mangled++;
410           string_append (decl, "inout(");
411           mangled = dlang_type (decl, mangled);
412           string_append (decl, ")");
413           return mangled;
414         }
415       else if (*mangled == 'h') /* vector(T) */
416         {
417           mangled++;
418           string_append (decl, "__vector(");
419           mangled = dlang_type (decl, mangled);
420           string_append (decl, ")");
421           return mangled;
422         }
423       else
424         return NULL;
425     case 'A': /* dynamic array (T[]) */
426       mangled++;
427       mangled = dlang_type (decl, mangled);
428       string_append (decl, "[]");
429       return mangled;
430     case 'G': /* static array (T[N]) */
431     {
432       const char *numptr;
433       size_t num = 0;
434       mangled++;
435
436       numptr = mangled;
437       while (ISDIGIT (*mangled))
438         {
439           num++;
440           mangled++;
441         }
442       mangled = dlang_type (decl, mangled);
443       string_append (decl, "[");
444       string_appendn (decl, numptr, num);
445       string_append (decl, "]");
446       return mangled;
447     }
448     case 'H': /* associative array (T[T]) */
449     {
450       string type;
451       size_t sztype;
452       mangled++;
453
454       string_init (&type);
455       mangled = dlang_type (&type, mangled);
456       sztype = string_length (&type);
457
458       mangled = dlang_type (decl, mangled);
459       string_append (decl, "[");
460       string_appendn (decl, type.b, sztype);
461       string_append (decl, "]");
462
463       string_delete (&type);
464       return mangled;
465     }
466     case 'P': /* pointer (T*) */
467       mangled++;
468       mangled = dlang_type (decl, mangled);
469       string_append (decl, "*");
470       return mangled;
471     case 'I': /* ident T */
472     case 'C': /* class T */
473     case 'S': /* struct T */
474     case 'E': /* enum T */
475     case 'T': /* typedef T */
476       mangled++;
477       return dlang_parse_symbol (decl, mangled);
478     case 'D': /* delegate T */
479       mangled++;
480       mangled = dlang_function_type (decl, mangled);
481       string_append (decl, "delegate");
482       return mangled;
483     case 'B': /* tuple T */
484       mangled++;
485       return dlang_parse_tuple (decl, mangled);
486
487     /* Function types */
488     case 'F': case 'U': case 'W':
489     case 'V': case 'R':
490       mangled = dlang_function_type (decl, mangled);
491       string_append (decl, "function");
492       return mangled;
493
494     /* Basic types */
495     case 'n':
496       mangled++;
497       string_append (decl, "none");
498       return mangled;
499     case 'v':
500       mangled++;
501       string_append (decl, "void");
502       return mangled;
503     case 'g':
504       mangled++;
505       string_append (decl, "byte");
506       return mangled;
507     case 'h':
508       mangled++;
509       string_append (decl, "ubyte");
510       return mangled;
511     case 's':
512       mangled++;
513       string_append (decl, "short");
514       return mangled;
515     case 't':
516       mangled++;
517       string_append (decl, "ushort");
518       return mangled;
519     case 'i':
520       mangled++;
521       string_append (decl, "int");
522       return mangled;
523     case 'k':
524       mangled++;
525       string_append (decl, "uint");
526       return mangled;
527     case 'l':
528       mangled++;
529       string_append (decl, "long");
530       return mangled;
531     case 'm':
532       mangled++;
533       string_append (decl, "ulong");
534       return mangled;
535     case 'f':
536       mangled++;
537       string_append (decl, "float");
538       return mangled;
539     case 'd':
540       mangled++;
541       string_append (decl, "double");
542       return mangled;
543     case 'e':
544       mangled++;
545       string_append (decl, "real");
546       return mangled;
547
548     /* Imaginary and Complex types */
549     case 'o':
550       mangled++;
551       string_append (decl, "ifloat");
552       return mangled;
553     case 'p':
554       mangled++;
555       string_append (decl, "idouble");
556       return mangled;
557     case 'j':
558       mangled++;
559       string_append (decl, "ireal");
560       return mangled;
561     case 'q':
562       mangled++;
563       string_append (decl, "cfloat");
564       return mangled;
565     case 'r':
566       mangled++;
567       string_append (decl, "cdouble");
568       return mangled;
569     case 'c':
570       mangled++;
571       string_append (decl, "creal");
572       return mangled;
573
574     /* Other types */
575     case 'b':
576       mangled++;
577       string_append (decl, "bool");
578       return mangled;
579     case 'a':
580       mangled++;
581       string_append (decl, "char");
582       return mangled;
583     case 'u':
584       mangled++;
585       string_append (decl, "wchar");
586       return mangled;
587     case 'w':
588       mangled++;
589       string_append (decl, "dchar");
590       return mangled;
591
592     default: /* unhandled */
593       return NULL;
594     }
595 }
596
597 /* Extract the identifier from MANGLED and append it to DECL.
598    Return the remaining string on success or NULL on failure.  */
599 static const char *
600 dlang_identifier (string *decl, const char *mangled)
601 {
602   if (mangled == NULL || *mangled == '\0')
603     return mangled;
604
605   if (ISDIGIT (*mangled))
606     {
607       char *endptr;
608       long i = strtol (mangled, &endptr, 10);
609
610       if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
611         return NULL;
612
613       mangled = endptr;
614
615       /* May be a template instance.  */
616       if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
617         {
618           /* Template symbol.  */
619           if (ISDIGIT (mangled[3]) && mangled[3] != '0')
620             return dlang_parse_template (decl, mangled, i);
621
622           return NULL;
623         }
624
625       if (strncmp (mangled, "__ctor", i) == 0)
626         {
627           /* Constructor symbol for a class/struct.  */
628           string_append (decl, "this");
629           mangled += i;
630           return mangled;
631         }
632       else if (strncmp (mangled, "__dtor", i) == 0)
633         {
634           /* Destructor symbol for a class/struct.  */
635           string_append (decl, "~this");
636           mangled += i;
637           return mangled;
638         }
639       else if (strncmp (mangled, "__postblit", i) == 0)
640         {
641           /* Postblit symbol for a struct.  */
642           string_append (decl, "this(this)");
643           mangled += i;
644           return mangled;
645         }
646       else if (strncmp (mangled, "__initZ", i+1) == 0)
647         {
648           /* The static initialiser for a given symbol.  */
649           string_append (decl, "init$");
650           mangled += i + 1;
651           return mangled;
652         }
653       else if (strncmp (mangled, "__ClassZ", i+1) == 0)
654         {
655           /* The classinfo symbol for a given class.  */
656           string_prepend (decl, "ClassInfo for ");
657           string_setlength (decl, string_length (decl) - 1);
658           mangled += i + 1;
659           return mangled;
660         }
661       else if (strncmp (mangled, "__vtblZ", i+1) == 0)
662         {
663           /* The vtable symbol for a given class.  */
664           string_prepend (decl, "vtable for ");
665           string_setlength (decl, string_length (decl) - 1);
666           mangled += i + 1;
667           return mangled;
668         }
669       else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
670         {
671           /* The interface symbol for a given class.  */
672           string_prepend (decl, "Interface for ");
673           string_setlength (decl, string_length (decl) - 1);
674           mangled += i + 1;
675           return mangled;
676         }
677       else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
678         {
679           /* The ModuleInfo symbol for a given module.  */
680           string_prepend (decl, "ModuleInfo for ");
681           string_setlength (decl, string_length (decl) - 1);
682           mangled += i + 1;
683           return mangled;
684         }
685
686       string_appendn (decl, mangled, i);
687       mangled += i;
688     }
689   else
690     return NULL;
691
692   return mangled;
693 }
694
695 /* Extract the integer value from MANGLED and append it to DECL,
696    where TYPE is the type it should be represented as.
697    Return the remaining string on success or NULL on failure.  */
698 static const char *
699 dlang_parse_integer (string *decl, const char *mangled, char type)
700 {
701   if (type == 'a' || type == 'u' || type == 'w')
702     {
703       /* Parse character value.  */
704       char value[10];
705       int pos = 10;
706       int width = 0;
707       char *endptr;
708       long val = strtol (mangled, &endptr, 10);
709
710       if (endptr == NULL || val < 0)
711         return NULL;
712
713       string_append (decl, "'");
714
715       if (type == 'a' && val >= 0x20 && val < 0x7F)
716         {
717           /* Represent as a character literal.  */
718           char c = (char) val;
719           string_appendn (decl, &c, 1);
720         }
721       else
722         {
723           /* Represent as a hexadecimal value.  */
724           switch (type)
725             {
726             case 'a': /* char */
727               string_append (decl, "\\x");
728               width = 2;
729               break;
730             case 'u': /* wchar */
731               string_append (decl, "\\u");
732               width = 4;
733               break;
734             case 'w': /* dchar */
735               string_append (decl, "\\U");
736               width = 8;
737               break;
738             }
739
740           while (val > 0)
741             {
742               int digit = val % 16;
743
744               if (digit < 10)
745                 value[--pos] = (char)(digit + '0');
746               else
747                 value[--pos] = (char)((digit - 10) + 'a');
748
749               val /= 16;
750               width--;
751             }
752
753           for (; width > 0; width--)
754             value[--pos] = '0';
755
756           string_appendn (decl, &(value[pos]), 10 - pos);
757         }
758       string_append (decl, "'");
759       mangled = endptr;
760     }
761   else if (type == 'b')
762     {
763       /* Parse boolean value.  */
764       char *endptr;
765       long val = strtol (mangled, &endptr, 10);
766
767       if (endptr == NULL || val < 0)
768         return NULL;
769
770       string_append (decl, val ? "true" : "false");
771       mangled = endptr;
772     }
773   else
774     {
775       /* Parse integer value.  */
776       const char *numptr = mangled;
777       size_t num = 0;
778
779       while (ISDIGIT (*mangled))
780         {
781           num++;
782           mangled++;
783         }
784       string_appendn (decl, numptr, num);
785
786       /* Append suffix.  */
787       switch (type)
788         {
789         case 'h': /* ubyte */
790         case 't': /* ushort */
791         case 'k': /* uint */
792           string_append (decl, "u");
793           break;
794         case 'l': /* long */
795           string_append (decl, "L");
796           break;
797         case 'm': /* ulong */
798           string_append (decl, "uL");
799           break;
800         }
801     }
802
803   return mangled;
804 }
805
806 /* Extract the floating-point value from MANGLED and append it to DECL.
807    Return the remaining string on success or NULL on failure.  */
808 static const char *
809 dlang_parse_real (string *decl, const char *mangled)
810 {
811   char buffer[64];
812   int len = 0;
813   double value;
814   char *endptr;
815
816   /* Handle NAN and +-INF.  */
817   if (strncmp (mangled, "NAN", 3) == 0)
818     {
819       string_append (decl, "NaN");
820       mangled += 3;
821       return mangled;
822     }
823   else if (strncmp (mangled, "INF", 3) == 0)
824     {
825       string_append (decl, "Inf");
826       mangled += 3;
827       return mangled;
828     }
829   else if (strncmp (mangled, "NINF", 4) == 0)
830     {
831       string_append (decl, "-Inf");
832       mangled += 4;
833       return mangled;
834     }
835
836   /* Hexadecimal prefix and leading bit.  */
837   if (*mangled == 'N')
838     {
839       buffer[len++] = '-';
840       mangled++;
841     }
842
843   if (!ISXDIGIT (*mangled))
844     return NULL;
845
846   buffer[len++] = '0';
847   buffer[len++] = 'x';
848   buffer[len++] = *mangled;
849   buffer[len++] = '.';
850   mangled++;
851
852   /* Significand.  */
853   while (ISXDIGIT (*mangled))
854     {
855       buffer[len++] = *mangled;
856       mangled++;
857     }
858
859   /* Exponent.  */
860   if (*mangled != 'P')
861     return NULL;
862
863   buffer[len++] = 'p';
864   mangled++;
865
866   if (*mangled == 'N')
867     {
868       buffer[len++] = '-';
869       mangled++;
870     }
871
872   while (ISDIGIT (*mangled))
873     {
874       buffer[len++] = *mangled;
875       mangled++;
876     }
877
878   /* Convert buffer from hexadecimal to floating-point.  */
879   buffer[len] = '\0';
880   value = strtod (buffer, &endptr);
881
882   if (endptr == NULL || endptr != (buffer + len))
883     return NULL;
884
885   len = snprintf (buffer, sizeof(buffer), "%#g", value);
886   string_appendn (decl, buffer, len);
887   return mangled;
888 }
889
890 /* Convert VAL from an ascii hexdigit to value.  */
891 static char
892 ascii2hex (char val)
893 {
894   if (val >= 'a' && val <= 'f')
895     return (val - 'a' + 10);
896
897   if (val >= 'A' && val <= 'F')
898     return (val - 'A' + 10);
899
900   if (val >= '0' && val <= '9')
901     return (val - '0');
902
903   return 0;
904 }
905
906 /* Extract the string value from MANGLED and append it to DECL.
907    Return the remaining string on success or NULL on failure.  */
908 static const char *
909 dlang_parse_string (string *decl, const char *mangled)
910 {
911   char type = *mangled;
912   char *endptr;
913   long len;
914
915   mangled++;
916   len = strtol (mangled, &endptr, 10);
917
918   if (endptr == NULL || len < 0)
919     return NULL;
920
921   mangled = endptr;
922   if (*mangled != '_')
923     return NULL;
924
925   mangled++;
926   string_append (decl, "\"");
927   while (len--)
928     {
929       if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
930         {
931           char a = ascii2hex (mangled[0]);
932           char b = ascii2hex (mangled[1]);
933           char val = (a << 4) | b;
934           string_appendn (decl, &val, 1);
935         }
936       else
937         return NULL;
938
939       mangled += 2;
940     }
941   string_append (decl, "\"");
942
943   if (type != 'a')
944     string_appendn (decl, &type, 1);
945
946   return mangled;
947 }
948
949 /* Extract the static array value from MANGLED and append it to DECL.
950    Return the remaining string on success or NULL on failure.  */
951 static const char *
952 dlang_parse_arrayliteral (string *decl, const char *mangled)
953 {
954   char *endptr;
955   long elements = strtol (mangled, &endptr, 10);
956
957   if (endptr == NULL || elements < 0)
958     return NULL;
959
960   mangled = endptr;
961   string_append (decl, "[");
962   while (elements--)
963     {
964       mangled = dlang_value (decl, mangled, NULL, '\0');
965       if (elements != 0)
966         string_append (decl, ", ");
967     }
968
969   string_append (decl, "]");
970   return mangled;
971 }
972
973 /* Extract the associative array value from MANGLED and append it to DECL.
974    Return the remaining string on success or NULL on failure.  */
975 static const char *
976 dlang_parse_assocarray (string *decl, const char *mangled)
977 {
978   char *endptr;
979   long elements = strtol (mangled, &endptr, 10);
980
981   if (endptr == NULL || elements < 0)
982     return NULL;
983
984   mangled = endptr;
985   string_append (decl, "[");
986   while (elements--)
987     {
988       mangled = dlang_value (decl, mangled, NULL, '\0');
989       string_append (decl, ":");
990       mangled = dlang_value (decl, mangled, NULL, '\0');
991
992       if (elements != 0)
993         string_append (decl, ", ");
994     }
995
996   string_append (decl, "]");
997   return mangled;
998 }
999
1000 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1001    Return the remaining string on success or NULL on failure.  */
1002 static const char *
1003 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1004 {
1005   char *endptr;
1006   long args = strtol (mangled, &endptr, 10);
1007
1008   if (endptr == NULL || args < 0)
1009     return NULL;
1010
1011   mangled = endptr;
1012   if (name != NULL)
1013     string_append (decl, name);
1014
1015   string_append (decl, "(");
1016   while (args--)
1017     {
1018       mangled = dlang_value (decl, mangled, NULL, '\0');
1019       if (args != 0)
1020         string_append (decl, ", ");
1021     }
1022
1023   string_append (decl, ")");
1024   return mangled;
1025 }
1026
1027 /* Extract the value from MANGLED and append it to DECL.
1028    Return the remaining string on success or NULL on failure.  */
1029 static const char *
1030 dlang_value (string *decl, const char *mangled, const char *name, char type)
1031 {
1032   if (mangled == NULL || *mangled == '\0')
1033     return mangled;
1034
1035   switch (*mangled)
1036     {
1037       /* Null value.  */
1038     case 'n':
1039       mangled++;
1040       string_append (decl, "null");
1041       break;
1042
1043       /* Integral values.  */
1044     case 'N':
1045       mangled++;
1046       string_append (decl, "-");
1047       mangled = dlang_parse_integer (decl, mangled, type);
1048       break;
1049
1050     case 'i':
1051       mangled++;
1052       if (*mangled < '0' || *mangled > '9')
1053         return NULL;
1054       /* Fall through */
1055     case '0': case '1': case '2': case '3': case '4':
1056     case '5': case '6': case '7': case '8': case '9':
1057       mangled = dlang_parse_integer (decl, mangled, type);
1058       break;
1059
1060       /* Real value.  */
1061     case 'e':
1062       mangled++;
1063       mangled = dlang_parse_real (decl, mangled);
1064       break;
1065
1066       /* Complex value.  */
1067     case 'c':
1068       mangled++;
1069       mangled = dlang_parse_real (decl, mangled);
1070       string_append (decl, "+");
1071       if (mangled == NULL || *mangled != 'c')
1072         return NULL;
1073       mangled++;
1074       mangled = dlang_parse_real (decl, mangled);
1075       string_append (decl, "i");
1076       break;
1077
1078       /* String values.  */
1079     case 'a': /* UTF8 */
1080     case 'w': /* UTF16 */
1081     case 'd': /* UTF32 */
1082       mangled = dlang_parse_string (decl, mangled);
1083       break;
1084
1085       /* Array values.  */
1086     case 'A':
1087       mangled++;
1088       if (type == 'H')
1089         mangled = dlang_parse_assocarray (decl, mangled);
1090       else
1091         mangled = dlang_parse_arrayliteral (decl, mangled);
1092       break;
1093
1094       /* Struct values.  */
1095     case 'S':
1096       mangled++;
1097       mangled = dlang_parse_structlit (decl, mangled, name);
1098       break;
1099
1100     default:
1101       return NULL;
1102     }
1103
1104   return mangled;
1105 }
1106
1107 static int
1108 dlang_call_convention_p (const char *mangled)
1109 {
1110   size_t i;
1111
1112   switch (*mangled)
1113     {
1114     case 'F': case 'U': case 'V':
1115     case 'W': case 'R':
1116       return 1;
1117
1118     case 'M': /* Prefix for functions needing 'this' */
1119       i = 1;
1120       if (mangled[i] == 'x')
1121         i++;
1122
1123       switch (mangled[i])
1124         {
1125         case 'F': case 'U': case 'V':
1126         case 'W': case 'R':
1127           return 1;
1128         }
1129
1130     default:
1131       return 0;
1132     }
1133 }
1134
1135 /* Extract and demangle the symbol in MANGLED and append it to DECL.
1136    Returns the remaining signature on success or NULL on failure.  */
1137 static const char *
1138 dlang_parse_symbol (string *decl, const char *mangled)
1139 {
1140   size_t n = 0;
1141   do
1142     {
1143       if (n++)
1144         string_append (decl, ".");
1145
1146       mangled = dlang_identifier (decl, mangled);
1147
1148       if (mangled && dlang_call_convention_p (mangled))
1149         {
1150           int saved;
1151
1152           /* Skip over 'this' parameter.  */
1153           if (*mangled == 'M')
1154             mangled += (mangled[1] == 'x') ? 2 : 1;
1155
1156           /* Skip over calling convention and attributes in qualified name.  */
1157           saved = string_length (decl);
1158           mangled = dlang_call_convention (decl, mangled);
1159           mangled = dlang_attributes (decl, mangled);
1160           string_setlength (decl, saved);
1161
1162           string_append (decl, "(");
1163           mangled = dlang_function_args (decl, mangled);
1164           string_append (decl, ")");
1165
1166           /* Demangle the function return type as a kind of sanity test.  */
1167           if (mangled && !ISDIGIT (*mangled))
1168             {
1169               saved = string_length (decl);
1170               mangled = dlang_type (decl, mangled);
1171               string_setlength (decl, saved);
1172             }
1173         }
1174     }
1175   while (mangled && ISDIGIT (*mangled));
1176
1177   return mangled;
1178 }
1179
1180 /* Demangle the tuple from MANGLED and append it to DECL.
1181    Return the remaining string on success or NULL on failure.  */
1182 static const char *
1183 dlang_parse_tuple (string *decl, const char *mangled)
1184 {
1185   char *endptr;
1186   long elements = strtol (mangled, &endptr, 10);
1187
1188   if (endptr == NULL || elements < 0)
1189     return NULL;
1190
1191   mangled = endptr;
1192   string_append (decl, "Tuple!(");
1193
1194   while (elements--)
1195     {
1196       mangled = dlang_type (decl, mangled);
1197       if (elements != 0)
1198         string_append (decl, ", ");
1199     }
1200
1201   string_append (decl, ")");
1202   return mangled;
1203 }
1204
1205 /* Demangle the argument list from MANGLED and append it to DECL.
1206    Return the remaining string on success or NULL on failure.  */
1207 static const char *
1208 dlang_template_args (string *decl, const char *mangled)
1209 {
1210   size_t n = 0;
1211
1212   while (mangled && *mangled != '\0')
1213     {
1214       switch (*mangled)
1215         {
1216         case 'Z': /* End of parameter list.  */
1217           mangled++;
1218           return mangled;
1219         }
1220
1221       if (n++)
1222         string_append (decl, ", ");
1223
1224       switch (*mangled)
1225         {
1226         case 'S': /* Symbol parameter.  */
1227           mangled++;
1228           mangled = dlang_parse_symbol (decl, mangled);
1229           break;
1230         case 'T': /* Type parameter.  */
1231           mangled++;
1232           mangled = dlang_type (decl, mangled);
1233           break;
1234         case 'V': /* Value parameter.  */
1235         {
1236           string name;
1237           char type;
1238
1239           /* Peek at the type.  */
1240           mangled++;
1241           type = *mangled;
1242
1243           /* In the few instances where the type is actually desired in
1244              the output, it should precede the value from dlang_value.  */
1245           string_init (&name);
1246           mangled = dlang_type (&name, mangled);
1247           string_need (&name, 1);
1248           *(name.p) = '\0';
1249
1250           mangled = dlang_value (decl, mangled, name.b, type);
1251           string_delete (&name);
1252           break;
1253         }
1254
1255         default:
1256           return NULL;
1257         }
1258     }
1259
1260   return mangled;
1261 }
1262
1263 /* Extract and demangle the template symbol in MANGLED, expected to
1264    be made up of LEN characters, and append it to DECL.
1265    Returns the remaining signature on success or NULL on failure.  */
1266 static const char *
1267 dlang_parse_template (string *decl, const char *mangled, long len)
1268 {
1269   const char *start = mangled;
1270
1271   /* Template instance names have the types and values of its parameters
1272      encoded into it.
1273
1274         TemplateInstanceName:
1275             Number __T LName TemplateArgs Z
1276                    ^
1277      The start pointer should be at the above location, and LEN should be
1278      the value of the decoded number.
1279    */
1280   if (strncmp (mangled, "__T", 3) != 0)
1281     return NULL;
1282
1283   mangled += 3;
1284
1285   /* Template identifier.  */
1286   mangled = dlang_identifier (decl, mangled);
1287
1288   /* Template arguments.  */
1289   string_append (decl, "!(");
1290   mangled = dlang_template_args (decl, mangled);
1291   string_append (decl, ")");
1292
1293   /* Check for template name length mismatch.  */
1294   if (mangled && (mangled - start) != len)
1295     return NULL;
1296
1297   return mangled;
1298 }
1299
1300 /* Extract and demangle the symbol in MANGLED.  Returns the demangled
1301    signature on success or NULL on failure.  */
1302
1303 char *
1304 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1305 {
1306   string decl;
1307   char *demangled = NULL;
1308
1309   if (mangled == NULL || *mangled == '\0')
1310     return NULL;
1311
1312   if (strncmp (mangled, "_D", 2) != 0)
1313     return NULL;
1314
1315   string_init (&decl);
1316
1317   if (strcmp (mangled, "_Dmain") == 0)
1318     {
1319       string_append (&decl, "D main");
1320     }
1321   else
1322     {
1323       mangled += 2;
1324
1325       if (dlang_parse_symbol (&decl, mangled) == NULL)
1326         string_delete (&decl);
1327     }
1328
1329   if (string_length (&decl) > 0)
1330     {
1331       string_need (&decl, 1);
1332       *(decl.p) = '\0';
1333       demangled = decl.b;
1334     }
1335
1336   return demangled;
1337 }
1338