cxxfilt 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1646 @@
1
+ /* Demangler for the D programming language
2
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
3
+ Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
+
5
+ This file is part of the libiberty library.
6
+ Libiberty is free software; you can redistribute it and/or
7
+ modify it under the terms of the GNU Library General Public
8
+ License as published by the Free Software Foundation; either
9
+ version 2 of the License, or (at your option) any later version.
10
+
11
+ In addition to the permissions in the GNU Library General Public
12
+ License, the Free Software Foundation gives you unlimited permission
13
+ to link the compiled version of this file into combinations with other
14
+ programs, and to distribute those combinations without any restriction
15
+ coming from the use of this file. (The Library Public License
16
+ restrictions do apply in other respects; for example, they cover
17
+ modification of the file, and distribution when not linked into a
18
+ combined executable.)
19
+
20
+ Libiberty is distributed in the hope that it will be useful,
21
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
+ Library General Public License for more details.
24
+
25
+ You should have received a copy of the GNU Library General Public
26
+ License along with libiberty; see the file COPYING.LIB.
27
+ If not, see <http://www.gnu.org/licenses/>. */
28
+
29
+ /* This file exports one function; dlang_demangle. */
30
+
31
+ #ifdef HAVE_CONFIG_H
32
+ #include "config.h"
33
+ #endif
34
+
35
+ #include "safe-ctype.h"
36
+
37
+ #include <sys/types.h>
38
+ #include <string.h>
39
+ #include <stdio.h>
40
+
41
+ #ifdef HAVE_STDLIB_H
42
+ #include <stdlib.h>
43
+ #endif
44
+
45
+ #include <demangle.h>
46
+ #include "libiberty.h"
47
+
48
+ /* A mini string-handling package */
49
+
50
+ typedef struct string /* Beware: these aren't required to be */
51
+ { /* '\0' terminated. */
52
+ char *b; /* pointer to start of string */
53
+ char *p; /* pointer after last character */
54
+ char *e; /* pointer after end of allocated space */
55
+ } string;
56
+
57
+ static void
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. */
942
+ char value[10];
943
+ int pos = 10;
944
+ int width = 0;
945
+ long val;
946
+
947
+ mangled = dlang_number (mangled, &val);
948
+ if (mangled == NULL)
949
+ return NULL;
950
+
951
+ string_append (decl, "'");
952
+
953
+ if (type == 'a' && val >= 0x20 && val < 0x7F)
954
+ {
955
+ /* Represent as a character literal. */
956
+ char c = (char) val;
957
+ string_appendn (decl, &c, 1);
958
+ }
959
+ else
960
+ {
961
+ /* Represent as a hexadecimal value. */
962
+ switch (type)
963
+ {
964
+ case 'a': /* char */
965
+ string_append (decl, "\\x");
966
+ width = 2;
967
+ break;
968
+ case 'u': /* wchar */
969
+ string_append (decl, "\\u");
970
+ width = 4;
971
+ break;
972
+ case 'w': /* dchar */
973
+ string_append (decl, "\\U");
974
+ width = 8;
975
+ break;
976
+ }
977
+
978
+ while (val > 0)
979
+ {
980
+ int digit = val % 16;
981
+
982
+ if (digit < 10)
983
+ value[--pos] = (char)(digit + '0');
984
+ else
985
+ value[--pos] = (char)((digit - 10) + 'a');
986
+
987
+ val /= 16;
988
+ width--;
989
+ }
990
+
991
+ for (; width > 0; width--)
992
+ value[--pos] = '0';
993
+
994
+ string_appendn (decl, &(value[pos]), 10 - pos);
995
+ }
996
+ string_append (decl, "'");
997
+ }
998
+ else if (type == 'b')
999
+ {
1000
+ /* Parse boolean value. */
1001
+ long val;
1002
+
1003
+ mangled = dlang_number (mangled, &val);
1004
+ if (mangled == NULL)
1005
+ return NULL;
1006
+
1007
+ string_append (decl, val ? "true" : "false");
1008
+ }
1009
+ else
1010
+ {
1011
+ /* Parse integer value. */
1012
+ const char *numptr = mangled;
1013
+ size_t num = 0;
1014
+
1015
+ if (! ISDIGIT (*mangled))
1016
+ return NULL;
1017
+
1018
+ while (ISDIGIT (*mangled))
1019
+ {
1020
+ num++;
1021
+ mangled++;
1022
+ }
1023
+ string_appendn (decl, numptr, num);
1024
+
1025
+ /* Append suffix. */
1026
+ switch (type)
1027
+ {
1028
+ case 'h': /* ubyte */
1029
+ case 't': /* ushort */
1030
+ case 'k': /* uint */
1031
+ string_append (decl, "u");
1032
+ break;
1033
+ case 'l': /* long */
1034
+ string_append (decl, "L");
1035
+ break;
1036
+ case 'm': /* ulong */
1037
+ string_append (decl, "uL");
1038
+ break;
1039
+ }
1040
+ }
1041
+
1042
+ return mangled;
1043
+ }
1044
+
1045
+ /* Extract the floating-point value from MANGLED and append it to DECL.
1046
+ Return the remaining string on success or NULL on failure. */
1047
+ static const char *
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');
1194
+ if (elements != 0)
1195
+ string_append (decl, ", ");
1196
+ }
1197
+
1198
+ string_append (decl, "]");
1199
+ return mangled;
1200
+ }
1201
+
1202
+ /* Extract the associative array value from MANGLED and append it to DECL.
1203
+ Return the remaining string on success or NULL on failure. */
1204
+ static const char *
1205
+ dlang_parse_assocarray (string *decl, const char *mangled)
1206
+ {
1207
+ long elements;
1208
+
1209
+ mangled = dlang_number (mangled, &elements);
1210
+ if (mangled == NULL)
1211
+ return NULL;
1212
+
1213
+ string_append (decl, "[");
1214
+ while (elements--)
1215
+ {
1216
+ mangled = dlang_value (decl, mangled, NULL, '\0');
1217
+ string_append (decl, ":");
1218
+ mangled = dlang_value (decl, mangled, NULL, '\0');
1219
+
1220
+ if (elements != 0)
1221
+ string_append (decl, ", ");
1222
+ }
1223
+
1224
+ string_append (decl, "]");
1225
+ return mangled;
1226
+ }
1227
+
1228
+ /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1229
+ Return the remaining string on success or NULL on failure. */
1230
+ static const char *
1231
+ dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1232
+ {
1233
+ long args;
1234
+
1235
+ mangled = dlang_number (mangled, &args);
1236
+ if (mangled == NULL)
1237
+ return NULL;
1238
+
1239
+ if (name != NULL)
1240
+ string_append (decl, name);
1241
+
1242
+ string_append (decl, "(");
1243
+ while (args--)
1244
+ {
1245
+ mangled = dlang_value (decl, mangled, NULL, '\0');
1246
+ if (args != 0)
1247
+ string_append (decl, ", ");
1248
+ }
1249
+
1250
+ string_append (decl, ")");
1251
+ return mangled;
1252
+ }
1253
+
1254
+ /* Extract the value from MANGLED and append it to DECL.
1255
+ Return the remaining string on success or NULL on failure. */
1256
+ static const char *
1257
+ dlang_value (string *decl, const char *mangled, const char *name, char type)
1258
+ {
1259
+ if (mangled == NULL || *mangled == '\0')
1260
+ return NULL;
1261
+
1262
+ switch (*mangled)
1263
+ {
1264
+ /* Null value. */
1265
+ case 'n':
1266
+ mangled++;
1267
+ string_append (decl, "null");
1268
+ break;
1269
+
1270
+ /* Integral values. */
1271
+ case 'N':
1272
+ mangled++;
1273
+ string_append (decl, "-");
1274
+ mangled = dlang_parse_integer (decl, mangled, type);
1275
+ break;
1276
+
1277
+ case 'i':
1278
+ mangled++;
1279
+ /* Fall through */
1280
+
1281
+ /* There really should always be an `i' before encoded numbers, but there
1282
+ wasn't in early versions of D2, so this case range must remain for
1283
+ backwards compatibility. */
1284
+ case '0': case '1': case '2': case '3': case '4':
1285
+ case '5': case '6': case '7': case '8': case '9':
1286
+ mangled = dlang_parse_integer (decl, mangled, type);
1287
+ break;
1288
+
1289
+ /* Real value. */
1290
+ case 'e':
1291
+ mangled++;
1292
+ mangled = dlang_parse_real (decl, mangled);
1293
+ break;
1294
+
1295
+ /* Complex value. */
1296
+ case 'c':
1297
+ mangled++;
1298
+ mangled = dlang_parse_real (decl, mangled);
1299
+ string_append (decl, "+");
1300
+ if (mangled == NULL || *mangled != 'c')
1301
+ return NULL;
1302
+ mangled++;
1303
+ mangled = dlang_parse_real (decl, mangled);
1304
+ string_append (decl, "i");
1305
+ break;
1306
+
1307
+ /* String values. */
1308
+ case 'a': /* UTF8 */
1309
+ case 'w': /* UTF16 */
1310
+ case 'd': /* UTF32 */
1311
+ mangled = dlang_parse_string (decl, mangled);
1312
+ break;
1313
+
1314
+ /* Array values. */
1315
+ case 'A':
1316
+ mangled++;
1317
+ if (type == 'H')
1318
+ mangled = dlang_parse_assocarray (decl, mangled);
1319
+ else
1320
+ mangled = dlang_parse_arrayliteral (decl, mangled);
1321
+ break;
1322
+
1323
+ /* Struct values. */
1324
+ case 'S':
1325
+ mangled++;
1326
+ mangled = dlang_parse_structlit (decl, mangled, name);
1327
+ break;
1328
+
1329
+ default:
1330
+ return NULL;
1331
+ }
1332
+
1333
+ return mangled;
1334
+ }
1335
+
1336
+ /* Extract and demangle the symbol in MANGLED and append it to DECL.
1337
+ Returns the remaining signature on success or NULL on failure. */
1338
+ static const char *
1339
+ dlang_parse_mangle (string *decl, const char *mangled,
1340
+ enum dlang_symbol_kinds kind)
1341
+ {
1342
+ /* A D mangled symbol is comprised of both scope and type information.
1343
+
1344
+ MangleName:
1345
+ _D QualifiedName Type
1346
+ _D QualifiedName M Type
1347
+ _D QualifiedName Z
1348
+ ^
1349
+ The caller should have guaranteed that the start pointer is at the
1350
+ above location.
1351
+ */
1352
+ mangled += 2;
1353
+
1354
+ mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
1355
+
1356
+ if (mangled != NULL)
1357
+ {
1358
+ /* Artificial symbols end with 'Z' and have no type. */
1359
+ if (*mangled == 'Z')
1360
+ mangled++;
1361
+ else
1362
+ {
1363
+ string mods;
1364
+ int saved;
1365
+
1366
+ /* Skip over 'this' parameter. */
1367
+ if (*mangled == 'M')
1368
+ mangled++;
1369
+
1370
+ /* Save the type modifiers for appending at the end if needed. */
1371
+ string_init (&mods);
1372
+ mangled = dlang_type_modifiers (&mods, mangled);
1373
+
1374
+ if (mangled && dlang_call_convention_p (mangled))
1375
+ {
1376
+ /* Skip over calling convention and attributes. */
1377
+ saved = string_length (decl);
1378
+ mangled = dlang_call_convention (decl, mangled);
1379
+ mangled = dlang_attributes (decl, mangled);
1380
+ string_setlength (decl, saved);
1381
+
1382
+ string_append (decl, "(");
1383
+ mangled = dlang_function_args (decl, mangled);
1384
+ string_append (decl, ")");
1385
+
1386
+ /* Add any const/immutable/shared modifier. */
1387
+ string_appendn (decl, mods.b, string_length (&mods));
1388
+ }
1389
+
1390
+ /* Consume the decl type of symbol. */
1391
+ saved = string_length (decl);
1392
+ mangled = dlang_type (decl, mangled);
1393
+ string_setlength (decl, saved);
1394
+
1395
+ string_delete (&mods);
1396
+ }
1397
+ }
1398
+
1399
+ /* Check that the entire symbol was successfully demangled. */
1400
+ if (kind == dlang_top_level)
1401
+ {
1402
+ if (mangled == NULL || *mangled != '\0')
1403
+ return NULL;
1404
+ }
1405
+
1406
+ return mangled;
1407
+ }
1408
+
1409
+ /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1410
+ Returns the remaining signature on success or NULL on failure. */
1411
+ static const char *
1412
+ dlang_parse_qualified (string *decl, const char *mangled,
1413
+ enum dlang_symbol_kinds kind)
1414
+ {
1415
+ /* Qualified names are identifiers separated by their encoded length.
1416
+ Nested functions also encode their argument types without specifying
1417
+ what they return.
1418
+
1419
+ QualifiedName:
1420
+ SymbolName
1421
+ SymbolName QualifiedName
1422
+ SymbolName TypeFunctionNoReturn QualifiedName
1423
+ SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
1424
+ ^
1425
+ The start pointer should be at the above location.
1426
+ */
1427
+ size_t n = 0;
1428
+ do
1429
+ {
1430
+ if (n++)
1431
+ string_append (decl, ".");
1432
+
1433
+ /* Skip over anonymous symbols. */
1434
+ while (*mangled == '0')
1435
+ mangled++;
1436
+
1437
+ mangled = dlang_identifier (decl, mangled, kind);
1438
+
1439
+ /* Consume the encoded arguments. However if this is not followed by the
1440
+ next encoded length, then this is not a continuation of a qualified
1441
+ name, in which case we backtrack and return the current unconsumed
1442
+ position of the mangled decl. */
1443
+ if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
1444
+ {
1445
+ const char *start = mangled;
1446
+ int saved = string_length (decl);
1447
+
1448
+ /* Skip over 'this' parameter and type modifiers. */
1449
+ if (*mangled == 'M')
1450
+ {
1451
+ mangled++;
1452
+ mangled = dlang_type_modifiers (decl, mangled);
1453
+ string_setlength (decl, saved);
1454
+ }
1455
+
1456
+ /* The rule we expect to match in the mangled string is:
1457
+
1458
+ TypeFunctionNoReturn:
1459
+ CallConvention FuncAttrs Arguments ArgClose
1460
+
1461
+ The calling convention and function attributes are not included
1462
+ in the demangled string. */
1463
+ mangled = dlang_call_convention (decl, mangled);
1464
+ mangled = dlang_attributes (decl, mangled);
1465
+ string_setlength (decl, saved);
1466
+
1467
+ string_append (decl, "(");
1468
+ mangled = dlang_function_args (decl, mangled);
1469
+ string_append (decl, ")");
1470
+
1471
+ if (mangled == NULL || !ISDIGIT (*mangled))
1472
+ {
1473
+ /* Did not match the rule we were looking for. */
1474
+ mangled = start;
1475
+ string_setlength (decl, saved);
1476
+ }
1477
+ }
1478
+ }
1479
+ while (mangled && ISDIGIT (*mangled));
1480
+
1481
+ return mangled;
1482
+ }
1483
+
1484
+ /* Demangle the tuple from MANGLED and append it to DECL.
1485
+ Return the remaining string on success or NULL on failure. */
1486
+ static const char *
1487
+ dlang_parse_tuple (string *decl, const char *mangled)
1488
+ {
1489
+ long elements;
1490
+
1491
+ mangled = dlang_number (mangled, &elements);
1492
+ if (mangled == NULL)
1493
+ return NULL;
1494
+
1495
+ string_append (decl, "Tuple!(");
1496
+
1497
+ while (elements--)
1498
+ {
1499
+ mangled = dlang_type (decl, mangled);
1500
+ if (elements != 0)
1501
+ string_append (decl, ", ");
1502
+ }
1503
+
1504
+ string_append (decl, ")");
1505
+ return mangled;
1506
+ }
1507
+
1508
+ /* Demangle the argument list from MANGLED and append it to DECL.
1509
+ Return the remaining string on success or NULL on failure. */
1510
+ static const char *
1511
+ dlang_template_args (string *decl, const char *mangled)
1512
+ {
1513
+ size_t n = 0;
1514
+
1515
+ while (mangled && *mangled != '\0')
1516
+ {
1517
+ switch (*mangled)
1518
+ {
1519
+ case 'Z': /* End of parameter list. */
1520
+ mangled++;
1521
+ return mangled;
1522
+ }
1523
+
1524
+ if (n++)
1525
+ string_append (decl, ", ");
1526
+
1527
+ /* Skip over specialised template prefix. */
1528
+ if (*mangled == 'H')
1529
+ mangled++;
1530
+
1531
+ switch (*mangled)
1532
+ {
1533
+ case 'S': /* Symbol parameter. */
1534
+ mangled++;
1535
+ mangled = dlang_identifier (decl, mangled, dlang_template_param);
1536
+ break;
1537
+ case 'T': /* Type parameter. */
1538
+ mangled++;
1539
+ mangled = dlang_type (decl, mangled);
1540
+ break;
1541
+ case 'V': /* Value parameter. */
1542
+ {
1543
+ string name;
1544
+ char type;
1545
+
1546
+ /* Peek at the type. */
1547
+ mangled++;
1548
+ type = *mangled;
1549
+
1550
+ /* In the few instances where the type is actually desired in
1551
+ the output, it should precede the value from dlang_value. */
1552
+ string_init (&name);
1553
+ mangled = dlang_type (&name, mangled);
1554
+ string_need (&name, 1);
1555
+ *(name.p) = '\0';
1556
+
1557
+ mangled = dlang_value (decl, mangled, name.b, type);
1558
+ string_delete (&name);
1559
+ break;
1560
+ }
1561
+
1562
+ default:
1563
+ return NULL;
1564
+ }
1565
+ }
1566
+
1567
+ return mangled;
1568
+ }
1569
+
1570
+ /* Extract and demangle the template symbol in MANGLED, expected to
1571
+ be made up of LEN characters, and append it to DECL.
1572
+ Returns the remaining signature on success or NULL on failure. */
1573
+ static const char *
1574
+ dlang_parse_template (string *decl, const char *mangled, long len)
1575
+ {
1576
+ const char *start = mangled;
1577
+
1578
+ /* Template instance names have the types and values of its parameters
1579
+ encoded into it.
1580
+
1581
+ TemplateInstanceName:
1582
+ Number __T LName TemplateArgs Z
1583
+ Number __U LName TemplateArgs Z
1584
+ ^
1585
+ The start pointer should be at the above location, and LEN should be
1586
+ the value of the decoded number.
1587
+ */
1588
+
1589
+ /* Template symbol. */
1590
+ if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
1591
+ return NULL;
1592
+
1593
+ mangled += 3;
1594
+
1595
+ /* Template identifier. */
1596
+ mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1597
+
1598
+ /* Template arguments. */
1599
+ string_append (decl, "!(");
1600
+ mangled = dlang_template_args (decl, mangled);
1601
+ string_append (decl, ")");
1602
+
1603
+ /* Check for template name length mismatch. */
1604
+ if (mangled && (mangled - start) != len)
1605
+ return NULL;
1606
+
1607
+ return mangled;
1608
+ }
1609
+
1610
+ /* Extract and demangle the symbol in MANGLED. Returns the demangled
1611
+ signature on success or NULL on failure. */
1612
+
1613
+ char *
1614
+ dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1615
+ {
1616
+ string decl;
1617
+ char *demangled = NULL;
1618
+
1619
+ if (mangled == NULL || *mangled == '\0')
1620
+ return NULL;
1621
+
1622
+ if (strncmp (mangled, "_D", 2) != 0)
1623
+ return NULL;
1624
+
1625
+ string_init (&decl);
1626
+
1627
+ if (strcmp (mangled, "_Dmain") == 0)
1628
+ {
1629
+ string_append (&decl, "D main");
1630
+ }
1631
+ else
1632
+ {
1633
+ if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
1634
+ string_delete (&decl);
1635
+ }
1636
+
1637
+ if (string_length (&decl) > 0)
1638
+ {
1639
+ string_need (&decl, 1);
1640
+ *(decl.p) = '\0';
1641
+ demangled = decl.b;
1642
+ }
1643
+
1644
+ return demangled;
1645
+ }
1646
+