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