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