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 
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10 
11 In addition to the permissions in the GNU Library General Public
12 License, the Free Software Foundation gives you unlimited permission
13 to link the compiled version of this file into combinations with other
14 programs, and to distribute those combinations without any restriction
15 coming from the use of this file.  (The Library Public License
16 restrictions do apply in other respects; for example, they cover
17 modification of the file, and distribution when not linked into a
18 combined executable.)
19 
20 Libiberty is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 Library General Public License for more details.
24 
25 You should have received a copy of the GNU Library General Public
26 License along with libiberty; see the file COPYING.LIB.
27 If not, see <http://www.gnu.org/licenses/>.  */
28 
29 /* This file exports one function; dlang_demangle.  */
30 
31 #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 
50 typedef 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 
57 static void
string_need(string * s,int n)58 string_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 
82 static void
string_delete(string * s)83 string_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 
92 static void
string_init(string * s)93 string_init (string *s)
94 {
95   s->b = s->p = s->e = NULL;
96 }
97 
98 static int
string_length(string * s)99 string_length (string *s)
100 {
101   if (s->p == s->b)
102     {
103       return 0;
104     }
105   return s->p - s->b;
106 }
107 
108 static void
string_setlength(string * s,int n)109 string_setlength (string *s, int n)
110 {
111   if (n - string_length (s) < 0)
112     {
113       s->p = s->b + n;
114     }
115 }
116 
117 static void
string_append(string * p,const char * s)118 string_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 
126 static void
string_appendn(string * p,const char * s,int n)127 string_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 
137 static void
string_prependn(string * p,const char * s,int n)138 string_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 
154 static void
string_prepend(string * p,const char * s)155 string_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.  */
164 enum 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 */
179 static const char *dlang_function_args (string *, const char *);
180 
181 static const char *dlang_type (string *, const char *);
182 
183 static const char *dlang_value (string *, const char *, const char *, char);
184 
185 static const char *dlang_parse_qualified (string *, const char *,
186 					  enum dlang_symbol_kinds);
187 
188 static const char *dlang_parse_mangle (string *, const char *,
189 				       enum dlang_symbol_kinds);
190 
191 static const char *dlang_parse_tuple (string *, const char *);
192 
193 static 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.  */
198 static const char *
dlang_number(const char * mangled,long * ret)199 dlang_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.  */
228 static const char *
dlang_hexdigit(const char * mangled,char * ret)229 dlang_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.  */
256 static int
dlang_call_convention_p(const char * mangled)257 dlang_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.  */
272 static const char *
dlang_call_convention(string * decl,const char * mangled)273 dlang_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.  */
312 static const char *
dlang_type_modifiers(string * decl,const char * mangled)313 dlang_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.  */
350 static const char *
dlang_attributes(string * decl,const char * mangled)351 dlang_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.  */
419 static const char *
dlang_function_type(string * decl,const char * mangled)420 dlang_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.  */
468 static const char *
dlang_function_args(string * decl,const char * mangled)469 dlang_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.  */
530 static const char *
dlang_type(string * decl,const char * mangled)531 dlang_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.  */
783 static const char *
dlang_identifier(string * decl,const char * mangled,enum dlang_symbol_kinds kind)784 dlang_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.  */
936 static const char *
dlang_parse_integer(string * decl,const char * mangled,char type)937 dlang_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.  */
1047 static const char *
dlang_parse_real(string * decl,const char * mangled)1048 dlang_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.  */
1116 static const char *
dlang_parse_string(string * decl,const char * mangled)1117 dlang_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.  */
1181 static const char *
dlang_parse_arrayliteral(string * decl,const char * mangled)1182 dlang_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.  */
1204 static const char *
dlang_parse_assocarray(string * decl,const char * mangled)1205 dlang_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.  */
1230 static const char *
dlang_parse_structlit(string * decl,const char * mangled,const char * name)1231 dlang_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.  */
1256 static const char *
dlang_value(string * decl,const char * mangled,const char * name,char type)1257 dlang_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.  */
1338 static const char *
dlang_parse_mangle(string * decl,const char * mangled,enum dlang_symbol_kinds kind)1339 dlang_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.  */
1411 static const char *
dlang_parse_qualified(string * decl,const char * mangled,enum dlang_symbol_kinds kind)1412 dlang_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.  */
1486 static const char *
dlang_parse_tuple(string * decl,const char * mangled)1487 dlang_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.  */
1510 static const char *
dlang_template_args(string * decl,const char * mangled)1511 dlang_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.  */
1573 static const char *
dlang_parse_template(string * decl,const char * mangled,long len)1574 dlang_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 
1613 char *
dlang_demangle(const char * mangled,int option ATTRIBUTE_UNUSED)1614 dlang_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