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