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