111
|
1 /* Demangler for the D programming language
|
145
|
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
111
|
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
|
|
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
|
|
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
|
|
93 string_init (string *s)
|
|
94 {
|
|
95 s->b = s->p = s->e = NULL;
|
|
96 }
|
|
97
|
|
98 static int
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 *
|
|
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 *
|
|
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
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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 *
|
|
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. */
|
145
|
942 char value[20];
|
|
943 int pos = sizeof(value);
|
111
|
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
|
145
|
994 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
|
111
|
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 *
|
|
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 *
|
|
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 *
|
|
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');
|
145
|
1194 if (mangled == NULL)
|
|
1195 return NULL;
|
|
1196
|
111
|
1197 if (elements != 0)
|
|
1198 string_append (decl, ", ");
|
|
1199 }
|
|
1200
|
|
1201 string_append (decl, "]");
|
|
1202 return mangled;
|
|
1203 }
|
|
1204
|
|
1205 /* Extract the associative array value from MANGLED and append it to DECL.
|
|
1206 Return the remaining string on success or NULL on failure. */
|
|
1207 static const char *
|
|
1208 dlang_parse_assocarray (string *decl, const char *mangled)
|
|
1209 {
|
|
1210 long elements;
|
|
1211
|
|
1212 mangled = dlang_number (mangled, &elements);
|
|
1213 if (mangled == NULL)
|
|
1214 return NULL;
|
|
1215
|
|
1216 string_append (decl, "[");
|
|
1217 while (elements--)
|
|
1218 {
|
|
1219 mangled = dlang_value (decl, mangled, NULL, '\0');
|
145
|
1220 if (mangled == NULL)
|
|
1221 return NULL;
|
|
1222
|
111
|
1223 string_append (decl, ":");
|
|
1224 mangled = dlang_value (decl, mangled, NULL, '\0');
|
145
|
1225 if (mangled == NULL)
|
|
1226 return NULL;
|
111
|
1227
|
|
1228 if (elements != 0)
|
|
1229 string_append (decl, ", ");
|
|
1230 }
|
|
1231
|
|
1232 string_append (decl, "]");
|
|
1233 return mangled;
|
|
1234 }
|
|
1235
|
|
1236 /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
|
|
1237 Return the remaining string on success or NULL on failure. */
|
|
1238 static const char *
|
|
1239 dlang_parse_structlit (string *decl, const char *mangled, const char *name)
|
|
1240 {
|
|
1241 long args;
|
|
1242
|
|
1243 mangled = dlang_number (mangled, &args);
|
|
1244 if (mangled == NULL)
|
|
1245 return NULL;
|
|
1246
|
|
1247 if (name != NULL)
|
|
1248 string_append (decl, name);
|
|
1249
|
|
1250 string_append (decl, "(");
|
|
1251 while (args--)
|
|
1252 {
|
|
1253 mangled = dlang_value (decl, mangled, NULL, '\0');
|
145
|
1254 if (mangled == NULL)
|
|
1255 return NULL;
|
|
1256
|
111
|
1257 if (args != 0)
|
|
1258 string_append (decl, ", ");
|
|
1259 }
|
|
1260
|
|
1261 string_append (decl, ")");
|
|
1262 return mangled;
|
|
1263 }
|
|
1264
|
|
1265 /* Extract the value from MANGLED and append it to DECL.
|
|
1266 Return the remaining string on success or NULL on failure. */
|
|
1267 static const char *
|
|
1268 dlang_value (string *decl, const char *mangled, const char *name, char type)
|
|
1269 {
|
|
1270 if (mangled == NULL || *mangled == '\0')
|
|
1271 return NULL;
|
|
1272
|
|
1273 switch (*mangled)
|
|
1274 {
|
|
1275 /* Null value. */
|
|
1276 case 'n':
|
|
1277 mangled++;
|
|
1278 string_append (decl, "null");
|
|
1279 break;
|
|
1280
|
|
1281 /* Integral values. */
|
|
1282 case 'N':
|
|
1283 mangled++;
|
|
1284 string_append (decl, "-");
|
|
1285 mangled = dlang_parse_integer (decl, mangled, type);
|
|
1286 break;
|
|
1287
|
|
1288 case 'i':
|
|
1289 mangled++;
|
|
1290 /* Fall through */
|
|
1291
|
|
1292 /* There really should always be an `i' before encoded numbers, but there
|
|
1293 wasn't in early versions of D2, so this case range must remain for
|
|
1294 backwards compatibility. */
|
|
1295 case '0': case '1': case '2': case '3': case '4':
|
|
1296 case '5': case '6': case '7': case '8': case '9':
|
|
1297 mangled = dlang_parse_integer (decl, mangled, type);
|
|
1298 break;
|
|
1299
|
|
1300 /* Real value. */
|
|
1301 case 'e':
|
|
1302 mangled++;
|
|
1303 mangled = dlang_parse_real (decl, mangled);
|
|
1304 break;
|
|
1305
|
|
1306 /* Complex value. */
|
|
1307 case 'c':
|
|
1308 mangled++;
|
|
1309 mangled = dlang_parse_real (decl, mangled);
|
|
1310 string_append (decl, "+");
|
|
1311 if (mangled == NULL || *mangled != 'c')
|
|
1312 return NULL;
|
|
1313 mangled++;
|
|
1314 mangled = dlang_parse_real (decl, mangled);
|
|
1315 string_append (decl, "i");
|
|
1316 break;
|
|
1317
|
|
1318 /* String values. */
|
|
1319 case 'a': /* UTF8 */
|
|
1320 case 'w': /* UTF16 */
|
|
1321 case 'd': /* UTF32 */
|
|
1322 mangled = dlang_parse_string (decl, mangled);
|
|
1323 break;
|
|
1324
|
|
1325 /* Array values. */
|
|
1326 case 'A':
|
|
1327 mangled++;
|
|
1328 if (type == 'H')
|
|
1329 mangled = dlang_parse_assocarray (decl, mangled);
|
|
1330 else
|
|
1331 mangled = dlang_parse_arrayliteral (decl, mangled);
|
|
1332 break;
|
|
1333
|
|
1334 /* Struct values. */
|
|
1335 case 'S':
|
|
1336 mangled++;
|
|
1337 mangled = dlang_parse_structlit (decl, mangled, name);
|
|
1338 break;
|
|
1339
|
|
1340 default:
|
|
1341 return NULL;
|
|
1342 }
|
|
1343
|
|
1344 return mangled;
|
|
1345 }
|
|
1346
|
|
1347 /* Extract and demangle the symbol in MANGLED and append it to DECL.
|
|
1348 Returns the remaining signature on success or NULL on failure. */
|
|
1349 static const char *
|
|
1350 dlang_parse_mangle (string *decl, const char *mangled,
|
|
1351 enum dlang_symbol_kinds kind)
|
|
1352 {
|
|
1353 /* A D mangled symbol is comprised of both scope and type information.
|
|
1354
|
|
1355 MangleName:
|
|
1356 _D QualifiedName Type
|
|
1357 _D QualifiedName M Type
|
|
1358 _D QualifiedName Z
|
|
1359 ^
|
|
1360 The caller should have guaranteed that the start pointer is at the
|
|
1361 above location.
|
|
1362 */
|
|
1363 mangled += 2;
|
|
1364
|
|
1365 mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
|
|
1366
|
|
1367 if (mangled != NULL)
|
|
1368 {
|
|
1369 /* Artificial symbols end with 'Z' and have no type. */
|
|
1370 if (*mangled == 'Z')
|
|
1371 mangled++;
|
|
1372 else
|
|
1373 {
|
|
1374 string mods;
|
|
1375 int saved;
|
|
1376
|
|
1377 /* Skip over 'this' parameter. */
|
|
1378 if (*mangled == 'M')
|
|
1379 mangled++;
|
|
1380
|
|
1381 /* Save the type modifiers for appending at the end if needed. */
|
|
1382 string_init (&mods);
|
|
1383 mangled = dlang_type_modifiers (&mods, mangled);
|
|
1384
|
|
1385 if (mangled && dlang_call_convention_p (mangled))
|
|
1386 {
|
|
1387 /* Skip over calling convention and attributes. */
|
|
1388 saved = string_length (decl);
|
|
1389 mangled = dlang_call_convention (decl, mangled);
|
|
1390 mangled = dlang_attributes (decl, mangled);
|
|
1391 string_setlength (decl, saved);
|
|
1392
|
|
1393 string_append (decl, "(");
|
|
1394 mangled = dlang_function_args (decl, mangled);
|
|
1395 string_append (decl, ")");
|
|
1396
|
|
1397 /* Add any const/immutable/shared modifier. */
|
|
1398 string_appendn (decl, mods.b, string_length (&mods));
|
|
1399 }
|
|
1400
|
|
1401 /* Consume the decl type of symbol. */
|
|
1402 saved = string_length (decl);
|
|
1403 mangled = dlang_type (decl, mangled);
|
|
1404 string_setlength (decl, saved);
|
|
1405
|
|
1406 string_delete (&mods);
|
|
1407 }
|
|
1408 }
|
|
1409
|
|
1410 /* Check that the entire symbol was successfully demangled. */
|
|
1411 if (kind == dlang_top_level)
|
|
1412 {
|
|
1413 if (mangled == NULL || *mangled != '\0')
|
|
1414 return NULL;
|
|
1415 }
|
|
1416
|
|
1417 return mangled;
|
|
1418 }
|
|
1419
|
|
1420 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
|
|
1421 Returns the remaining signature on success or NULL on failure. */
|
|
1422 static const char *
|
|
1423 dlang_parse_qualified (string *decl, const char *mangled,
|
|
1424 enum dlang_symbol_kinds kind)
|
|
1425 {
|
|
1426 /* Qualified names are identifiers separated by their encoded length.
|
|
1427 Nested functions also encode their argument types without specifying
|
|
1428 what they return.
|
|
1429
|
|
1430 QualifiedName:
|
|
1431 SymbolName
|
|
1432 SymbolName QualifiedName
|
|
1433 SymbolName TypeFunctionNoReturn QualifiedName
|
|
1434 SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
|
|
1435 ^
|
|
1436 The start pointer should be at the above location.
|
|
1437 */
|
|
1438 size_t n = 0;
|
|
1439 do
|
|
1440 {
|
|
1441 if (n++)
|
|
1442 string_append (decl, ".");
|
|
1443
|
|
1444 /* Skip over anonymous symbols. */
|
|
1445 while (*mangled == '0')
|
|
1446 mangled++;
|
|
1447
|
|
1448 mangled = dlang_identifier (decl, mangled, kind);
|
|
1449
|
|
1450 /* Consume the encoded arguments. However if this is not followed by the
|
|
1451 next encoded length, then this is not a continuation of a qualified
|
|
1452 name, in which case we backtrack and return the current unconsumed
|
|
1453 position of the mangled decl. */
|
|
1454 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
|
|
1455 {
|
|
1456 const char *start = mangled;
|
|
1457 int saved = string_length (decl);
|
|
1458
|
|
1459 /* Skip over 'this' parameter and type modifiers. */
|
|
1460 if (*mangled == 'M')
|
|
1461 {
|
|
1462 mangled++;
|
|
1463 mangled = dlang_type_modifiers (decl, mangled);
|
|
1464 string_setlength (decl, saved);
|
|
1465 }
|
|
1466
|
|
1467 /* The rule we expect to match in the mangled string is:
|
|
1468
|
|
1469 TypeFunctionNoReturn:
|
|
1470 CallConvention FuncAttrs Arguments ArgClose
|
|
1471
|
|
1472 The calling convention and function attributes are not included
|
|
1473 in the demangled string. */
|
|
1474 mangled = dlang_call_convention (decl, mangled);
|
|
1475 mangled = dlang_attributes (decl, mangled);
|
|
1476 string_setlength (decl, saved);
|
|
1477
|
|
1478 string_append (decl, "(");
|
|
1479 mangled = dlang_function_args (decl, mangled);
|
|
1480 string_append (decl, ")");
|
|
1481
|
|
1482 if (mangled == NULL || !ISDIGIT (*mangled))
|
|
1483 {
|
|
1484 /* Did not match the rule we were looking for. */
|
|
1485 mangled = start;
|
|
1486 string_setlength (decl, saved);
|
|
1487 }
|
|
1488 }
|
|
1489 }
|
|
1490 while (mangled && ISDIGIT (*mangled));
|
|
1491
|
|
1492 return mangled;
|
|
1493 }
|
|
1494
|
|
1495 /* Demangle the tuple from MANGLED and append it to DECL.
|
|
1496 Return the remaining string on success or NULL on failure. */
|
|
1497 static const char *
|
|
1498 dlang_parse_tuple (string *decl, const char *mangled)
|
|
1499 {
|
|
1500 long elements;
|
|
1501
|
|
1502 mangled = dlang_number (mangled, &elements);
|
|
1503 if (mangled == NULL)
|
|
1504 return NULL;
|
|
1505
|
|
1506 string_append (decl, "Tuple!(");
|
|
1507
|
|
1508 while (elements--)
|
|
1509 {
|
|
1510 mangled = dlang_type (decl, mangled);
|
145
|
1511 if (mangled == NULL)
|
|
1512 return NULL;
|
|
1513
|
111
|
1514 if (elements != 0)
|
|
1515 string_append (decl, ", ");
|
|
1516 }
|
|
1517
|
|
1518 string_append (decl, ")");
|
|
1519 return mangled;
|
|
1520 }
|
|
1521
|
|
1522 /* Demangle the argument list from MANGLED and append it to DECL.
|
|
1523 Return the remaining string on success or NULL on failure. */
|
|
1524 static const char *
|
|
1525 dlang_template_args (string *decl, const char *mangled)
|
|
1526 {
|
|
1527 size_t n = 0;
|
|
1528
|
|
1529 while (mangled && *mangled != '\0')
|
|
1530 {
|
|
1531 switch (*mangled)
|
|
1532 {
|
|
1533 case 'Z': /* End of parameter list. */
|
|
1534 mangled++;
|
|
1535 return mangled;
|
|
1536 }
|
|
1537
|
|
1538 if (n++)
|
|
1539 string_append (decl, ", ");
|
|
1540
|
|
1541 /* Skip over specialised template prefix. */
|
|
1542 if (*mangled == 'H')
|
|
1543 mangled++;
|
|
1544
|
|
1545 switch (*mangled)
|
|
1546 {
|
|
1547 case 'S': /* Symbol parameter. */
|
|
1548 mangled++;
|
|
1549 mangled = dlang_identifier (decl, mangled, dlang_template_param);
|
|
1550 break;
|
|
1551 case 'T': /* Type parameter. */
|
|
1552 mangled++;
|
|
1553 mangled = dlang_type (decl, mangled);
|
|
1554 break;
|
|
1555 case 'V': /* Value parameter. */
|
|
1556 {
|
|
1557 string name;
|
|
1558 char type;
|
|
1559
|
|
1560 /* Peek at the type. */
|
|
1561 mangled++;
|
|
1562 type = *mangled;
|
|
1563
|
|
1564 /* In the few instances where the type is actually desired in
|
|
1565 the output, it should precede the value from dlang_value. */
|
|
1566 string_init (&name);
|
|
1567 mangled = dlang_type (&name, mangled);
|
|
1568 string_need (&name, 1);
|
|
1569 *(name.p) = '\0';
|
|
1570
|
|
1571 mangled = dlang_value (decl, mangled, name.b, type);
|
|
1572 string_delete (&name);
|
|
1573 break;
|
|
1574 }
|
|
1575
|
|
1576 default:
|
|
1577 return NULL;
|
|
1578 }
|
|
1579 }
|
|
1580
|
|
1581 return mangled;
|
|
1582 }
|
|
1583
|
|
1584 /* Extract and demangle the template symbol in MANGLED, expected to
|
|
1585 be made up of LEN characters, and append it to DECL.
|
|
1586 Returns the remaining signature on success or NULL on failure. */
|
|
1587 static const char *
|
|
1588 dlang_parse_template (string *decl, const char *mangled, long len)
|
|
1589 {
|
|
1590 const char *start = mangled;
|
|
1591
|
|
1592 /* Template instance names have the types and values of its parameters
|
|
1593 encoded into it.
|
|
1594
|
|
1595 TemplateInstanceName:
|
|
1596 Number __T LName TemplateArgs Z
|
|
1597 Number __U LName TemplateArgs Z
|
|
1598 ^
|
|
1599 The start pointer should be at the above location, and LEN should be
|
|
1600 the value of the decoded number.
|
|
1601 */
|
|
1602
|
|
1603 /* Template symbol. */
|
|
1604 if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
|
|
1605 return NULL;
|
|
1606
|
|
1607 mangled += 3;
|
|
1608
|
|
1609 /* Template identifier. */
|
|
1610 mangled = dlang_identifier (decl, mangled, dlang_template_ident);
|
|
1611
|
|
1612 /* Template arguments. */
|
|
1613 string_append (decl, "!(");
|
|
1614 mangled = dlang_template_args (decl, mangled);
|
|
1615 string_append (decl, ")");
|
|
1616
|
|
1617 /* Check for template name length mismatch. */
|
|
1618 if (mangled && (mangled - start) != len)
|
|
1619 return NULL;
|
|
1620
|
|
1621 return mangled;
|
|
1622 }
|
|
1623
|
|
1624 /* Extract and demangle the symbol in MANGLED. Returns the demangled
|
|
1625 signature on success or NULL on failure. */
|
|
1626
|
|
1627 char *
|
|
1628 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
|
|
1629 {
|
|
1630 string decl;
|
|
1631 char *demangled = NULL;
|
|
1632
|
|
1633 if (mangled == NULL || *mangled == '\0')
|
|
1634 return NULL;
|
|
1635
|
|
1636 if (strncmp (mangled, "_D", 2) != 0)
|
|
1637 return NULL;
|
|
1638
|
|
1639 string_init (&decl);
|
|
1640
|
|
1641 if (strcmp (mangled, "_Dmain") == 0)
|
|
1642 {
|
|
1643 string_append (&decl, "D main");
|
|
1644 }
|
|
1645 else
|
|
1646 {
|
|
1647 if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
|
|
1648 string_delete (&decl);
|
|
1649 }
|
|
1650
|
|
1651 if (string_length (&decl) > 0)
|
|
1652 {
|
|
1653 string_need (&decl, 1);
|
|
1654 *(decl.p) = '\0';
|
|
1655 demangled = decl.b;
|
|
1656 }
|
|
1657
|
|
1658 return demangled;
|
|
1659 }
|
|
1660
|