]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
libiberty: Update D symbol demangling for latest ABI spec.
[thirdparty/gcc.git] / libiberty / d-demangle.c
CommitLineData
43b1b9ed 1/* Demangler for the D programming language
8d9254fc 2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
43b1b9ed
IB
3 Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11In addition to the permissions in the GNU Library General Public
12License, the Free Software Foundation gives you unlimited permission
13to link the compiled version of this file into combinations with other
14programs, and to distribute those combinations without any restriction
15coming from the use of this file. (The Library Public License
16restrictions do apply in other respects; for example, they cover
17modification of the file, and distribution when not linked into a
18combined executable.)
19
20Libiberty is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23Library General Public License for more details.
24
25You should have received a copy of the GNU Library General Public
26License along with libiberty; see the file COPYING.LIB.
27If not, see <http://www.gnu.org/licenses/>. */
28
dbe65f77 29/* This file exports one function; dlang_demangle. */
43b1b9ed
IB
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>
43b1b9ed
IB
43#endif
44
45#include <demangle.h>
46#include "libiberty.h"
47
48/* A mini string-handling package */
49
50typedef struct string /* Beware: these aren't required to be */
51{ /* '\0' terminated. */
52 char *b; /* pointer to start of string */
53 char *p; /* pointer after last character */
54 char *e; /* pointer after end of allocated space */
55} string;
56
57static void
58string_need (string *s, int n)
59{
60 int tem;
61
62 if (s->b == NULL)
63 {
64 if (n < 32)
65 {
66 n = 32;
67 }
68 s->p = s->b = XNEWVEC (char, n);
69 s->e = s->b + n;
70 }
71 else if (s->e - s->p < n)
72 {
73 tem = s->p - s->b;
74 n += tem;
75 n *= 2;
76 s->b = XRESIZEVEC (char, s->b, n);
77 s->p = s->b + tem;
78 s->e = s->b + n;
79 }
80}
81
82static void
83string_delete (string *s)
84{
85 if (s->b != NULL)
86 {
87 XDELETEVEC (s->b);
88 s->b = s->e = s->p = NULL;
89 }
90}
91
92static void
93string_init (string *s)
94{
95 s->b = s->p = s->e = NULL;
96}
97
98static int
99string_length (string *s)
100{
101 if (s->p == s->b)
102 {
103 return 0;
104 }
105 return s->p - s->b;
106}
107
108static void
109string_setlength (string *s, int n)
110{
111 if (n - string_length (s) < 0)
112 {
113 s->p = s->b + n;
114 }
115}
116
117static void
118string_append (string *p, const char *s)
119{
120 int n = strlen (s);
121 string_need (p, n);
122 memcpy (p->p, s, n);
123 p->p += n;
124}
125
126static void
127string_appendn (string *p, const char *s, int n)
128{
129 if (n != 0)
130 {
131 string_need (p, n);
132 memcpy (p->p, s, n);
133 p->p += n;
134 }
135}
136
137static void
138string_prependn (string *p, const char *s, int n)
139{
140 char *q;
141
142 if (n != 0)
143 {
144 string_need (p, n);
145 for (q = p->p - 1; q >= p->b; q--)
146 {
147 q[n] = q[0];
148 }
149 memcpy (p->b, s, n);
150 p->p += n;
151 }
152}
153
154static void
155string_prepend (string *p, const char *s)
156{
157 if (s != NULL && *s != '\0')
158 {
159 string_prependn (p, s, strlen (s));
160 }
161}
162
3f30a274
IB
163/* Demangle information structure we pass around. */
164struct dlang_info
7e865541 165{
3f30a274
IB
166 /* The string we are demangling. */
167 const char *s;
168 /* The index of the last back reference. */
169 int last_backref;
7e865541
IB
170};
171
3f30a274
IB
172/* Pass as the LEN to dlang_parse_template if symbol length is not known. */
173enum { TEMPLATE_LENGTH_UNKNOWN = -1 };
174
43b1b9ed 175/* Prototypes for forward referenced functions */
3f30a274
IB
176static const char *dlang_function_type (string *, const char *,
177 struct dlang_info *);
43b1b9ed 178
3f30a274
IB
179static const char *dlang_function_args (string *, const char *,
180 struct dlang_info *);
181
182static const char *dlang_type (string *, const char *, struct dlang_info *);
43b1b9ed
IB
183
184static const char *dlang_value (string *, const char *, const char *, char);
185
5a4dbf7d 186static const char *dlang_parse_qualified (string *, const char *,
3f30a274 187 struct dlang_info *, int);
5a4dbf7d
IB
188
189static const char *dlang_parse_mangle (string *, const char *,
3f30a274
IB
190 struct dlang_info *);
191
192static const char *dlang_parse_tuple (string *, const char *,
193 struct dlang_info *);
43b1b9ed 194
3f30a274
IB
195static const char *dlang_parse_template (string *, const char *,
196 struct dlang_info *, long);
43b1b9ed 197
3f30a274 198static const char *dlang_lname (string *, const char *, long);
43b1b9ed
IB
199
200
dbe65f77
IB
201/* Extract the number from MANGLED, and assign the result to RET.
202 Return the remaining string on success or NULL on failure. */
203static const char *
204dlang_number (const char *mangled, long *ret)
205{
206 /* Return NULL if trying to extract something that isn't a digit. */
207 if (mangled == NULL || !ISDIGIT (*mangled))
208 return NULL;
209
210 (*ret) = 0;
211
212 while (ISDIGIT (*mangled))
213 {
214 (*ret) *= 10;
215
216 /* If an overflow occured when multiplying by ten, the result
217 will not be a multiple of ten. */
218 if ((*ret % 10) != 0)
219 return NULL;
220
221 (*ret) += mangled[0] - '0';
222 mangled++;
223 }
224
225 if (*mangled == '\0' || *ret < 0)
226 return NULL;
227
228 return mangled;
229}
230
5398cab9
IB
231/* Extract the hex-digit from MANGLED, and assign the result to RET.
232 Return the remaining string on success or NULL on failure. */
233static const char *
234dlang_hexdigit (const char *mangled, char *ret)
235{
236 char c;
237
238 /* Return NULL if trying to extract something that isn't a hexdigit. */
239 if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
240 return NULL;
241
242 c = mangled[0];
243 if (!ISDIGIT (c))
244 (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10);
245 else
246 (*ret) = (c - '0');
247
248 c = mangled[1];
249 if (!ISDIGIT (c))
250 (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
251 else
252 (*ret) = (*ret << 4) | (c - '0');
253
254 mangled += 2;
255
256 return mangled;
257}
258
0e3712f6
IB
259/* Extract the function calling convention from MANGLED and
260 return 1 on success or 0 on failure. */
261static int
262dlang_call_convention_p (const char *mangled)
263{
264 switch (*mangled)
265 {
266 case 'F': case 'U': case 'V':
267 case 'W': case 'R': case 'Y':
268 return 1;
269
270 default:
271 return 0;
272 }
273}
274
3f30a274
IB
275/* Extract the back reference position from MANGLED, and assign the result
276 to RET. Return the remaining string on success or NULL on failure. */
277static const char *
278dlang_decode_backref (const char *mangled, long *ret)
279{
280 /* Return NULL if trying to extract something that isn't a digit. */
281 if (mangled == NULL || !ISALPHA (*mangled))
282 return NULL;
283
284 /* Any identifier or non-basic type that has been emitted to the mangled
285 symbol before will not be emitted again, but is referenced by a special
286 sequence encoding the relative position of the original occurrence in the
287 mangled symbol name.
288
289 Numbers in back references are encoded with base 26 by upper case letters
290 A-Z for higher digits but lower case letters a-z for the last digit.
291
292 NumberBackRef:
293 [a-z]
294 [A-Z] NumberBackRef
295 ^
296 */
297 (*ret) = 0;
298
299 while (ISALPHA (*mangled))
300 {
301 (*ret) *= 26;
302
303 /* If an overflow occured when multiplying by 26, the result
304 will not be a multiple of 26. */
305 if ((*ret % 26) != 0)
306 return NULL;
307
308 if (mangled[0] >= 'a' && mangled[0] <= 'z')
309 {
310 (*ret) += mangled[0] - 'a';
311 return mangled + 1;
312 }
313
314 (*ret) += mangled[0] - 'A';
315 mangled++;
316 }
317
318 return NULL;
319}
320
321/* Extract the symbol pointed at by the back reference and assign the result
322 to RET. Return the remaining string on success or NULL on failure. */
323static const char *
324dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
325{
326 (*ret) = NULL;
327
328 if (mangled == NULL || *mangled != 'Q')
329 return NULL;
330
331 /* Position of 'Q'. */
332 const char *qpos = mangled;
333 long refpos;
334 mangled++;
335
336 mangled = dlang_decode_backref (mangled, &refpos);
337 if (mangled == NULL)
338 return NULL;
339
340 if (refpos <= 0 || refpos > qpos - info->s)
341 return NULL;
342
343 /* Set the position of the back reference. */
344 (*ret) = qpos - refpos;
345
346 return mangled;
347}
348
349/* Demangle a back referenced symbol from MANGLED and append it to DECL.
350 Return the remaining string on success or NULL on failure. */
351static const char *
352dlang_symbol_backref (string *decl, const char *mangled,
353 struct dlang_info *info)
354{
355 /* An identifier back reference always points to a digit 0 to 9.
356
357 IdentifierBackRef:
358 Q NumberBackRef
359 ^
360 */
361 const char *backref;
362 long len;
363
364 /* Get position of the back reference. */
365 mangled = dlang_backref (mangled, &backref, info);
366
367 /* Must point to a simple identifier. */
368 backref = dlang_number (backref, &len);
369 if (backref == NULL)
370 return NULL;
371
372 backref = dlang_lname (decl, backref, len);
373 if (backref == NULL)
374 return NULL;
375
376 return mangled;
377}
378
379/* Demangle a back referenced type from MANGLED and append it to DECL.
380 IS_FUNCTION is 1 if the back referenced type is expected to be a function.
381 Return the remaining string on success or NULL on failure. */
382static const char *
383dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
384 int is_function)
385{
386 /* A type back reference always points to a letter.
387
388 TypeBackRef:
389 Q NumberBackRef
390 ^
391 */
392 const char *backref;
393
394 /* If we appear to be moving backwards through the mangle string, then
395 bail as this may be a recursive back reference. */
396 if (mangled - info->s >= info->last_backref)
397 return NULL;
398
399 int save_refpos = info->last_backref;
400 info->last_backref = mangled - info->s;
401
402 /* Get position of the back reference. */
403 mangled = dlang_backref (mangled, &backref, info);
404
405 /* Must point to a type. */
406 if (is_function)
407 backref = dlang_function_type (decl, backref, info);
408 else
409 backref = dlang_type (decl, backref, info);
410
411 info->last_backref = save_refpos;
412
413 if (backref == NULL)
414 return NULL;
415
416 return mangled;
417}
418
419/* Extract the beginning of a symbol name from MANGLED and
420 return 1 on success or 0 on failure. */
421static int
422dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
423{
424 long ret;
425 const char *qref = mangled;
426
427 if (ISDIGIT (*mangled))
428 return 1;
429
430 if (mangled[0] == '_' && mangled[1] == '_'
431 && (mangled[2] == 'T' || mangled[2] == 'U'))
432 return 1;
433
434 if (*mangled != 'Q')
435 return 0;
436
437 mangled = dlang_decode_backref (mangled + 1, &ret);
438 if (mangled == NULL || ret <= 0 || ret > qref - info->s)
439 return 0;
440
441 return ISDIGIT (qref[-ret]);
442}
443
43b1b9ed
IB
444/* Demangle the calling convention from MANGLED and append it to DECL.
445 Return the remaining string on success or NULL on failure. */
446static const char *
447dlang_call_convention (string *decl, const char *mangled)
448{
449 if (mangled == NULL || *mangled == '\0')
76b41cad 450 return NULL;
43b1b9ed
IB
451
452 switch (*mangled)
453 {
454 case 'F': /* (D) */
455 mangled++;
456 break;
457 case 'U': /* (C) */
458 mangled++;
459 string_append (decl, "extern(C) ");
460 break;
461 case 'W': /* (Windows) */
462 mangled++;
463 string_append (decl, "extern(Windows) ");
464 break;
465 case 'V': /* (Pascal) */
466 mangled++;
467 string_append (decl, "extern(Pascal) ");
468 break;
469 case 'R': /* (C++) */
470 mangled++;
471 string_append (decl, "extern(C++) ");
472 break;
13617162
IB
473 case 'Y': /* (Objective-C) */
474 mangled++;
475 string_append (decl, "extern(Objective-C) ");
476 break;
43b1b9ed
IB
477 default:
478 return NULL;
479 }
480
481 return mangled;
482}
483
fa66ced4
IB
484/* Extract the type modifiers from MANGLED and append them to DECL.
485 Returns the remaining signature on success or NULL on failure. */
486static const char *
487dlang_type_modifiers (string *decl, const char *mangled)
488{
489 if (mangled == NULL || *mangled == '\0')
490 return NULL;
491
492 switch (*mangled)
493 {
494 case 'x': /* const */
495 mangled++;
496 string_append (decl, " const");
497 return mangled;
498 case 'y': /* immutable */
499 mangled++;
500 string_append (decl, " immutable");
501 return mangled;
502 case 'O': /* shared */
503 mangled++;
504 string_append (decl, " shared");
505 return dlang_type_modifiers (decl, mangled);
506 case 'N':
507 mangled++;
508 if (*mangled == 'g') /* wild */
509 {
510 mangled++;
511 string_append (decl, " inout");
512 return dlang_type_modifiers (decl, mangled);
513 }
514 else
515 return NULL;
516
517 default:
518 return mangled;
519 }
520}
521
43b1b9ed
IB
522/* Demangle the D function attributes from MANGLED and append it to DECL.
523 Return the remaining string on success or NULL on failure. */
524static const char *
525dlang_attributes (string *decl, const char *mangled)
526{
527 if (mangled == NULL || *mangled == '\0')
76b41cad 528 return NULL;
43b1b9ed
IB
529
530 while (*mangled == 'N')
531 {
532 mangled++;
533 switch (*mangled)
534 {
535 case 'a': /* pure */
536 mangled++;
537 string_append (decl, "pure ");
538 continue;
539 case 'b': /* nothrow */
540 mangled++;
541 string_append (decl, "nothrow ");
542 continue;
543 case 'c': /* ref */
544 mangled++;
545 string_append (decl, "ref ");
546 continue;
547 case 'd': /* @property */
548 mangled++;
549 string_append (decl, "@property ");
550 continue;
551 case 'e': /* @trusted */
552 mangled++;
553 string_append (decl, "@trusted ");
554 continue;
555 case 'f': /* @safe */
556 mangled++;
557 string_append (decl, "@safe ");
558 continue;
559 case 'g':
560 case 'h':
7ce4461f 561 case 'k':
43b1b9ed
IB
562 /* inout parameter is represented as 'Ng'.
563 vector parameter is represented as 'Nh'.
7ce4461f 564 return paramenter is represented as 'Nk'.
43b1b9ed
IB
565 If we see this, then we know we're really in the
566 parameter list. Rewind and break. */
567 mangled--;
568 break;
569 case 'i': /* @nogc */
570 mangled++;
571 string_append (decl, "@nogc ");
572 continue;
7ce4461f
IB
573 case 'j': /* return */
574 mangled++;
575 string_append (decl, "return ");
576 continue;
ec89d258
IB
577 case 'l': /* scope */
578 mangled++;
579 string_append (decl, "scope ");
580 continue;
7ce4461f
IB
581
582 default: /* unknown attribute */
583 return NULL;
43b1b9ed
IB
584 }
585 break;
586 }
587
588 return mangled;
589}
590
3f30a274
IB
591/* Demangle the function type from MANGLED without the return type.
592 The arguments are appended to ARGS, the calling convention is appended
593 to CALL and attributes are appended to ATTR. Any of these can be NULL
594 to throw the information away. Return the remaining string on success
595 or NULL on failure. */
596static const char *
597dlang_function_type_noreturn (string *args, string *call, string *attr,
598 const char *mangled, struct dlang_info *info)
599{
600 string dump;
601 string_init (&dump);
602
603 /* Skip over calling convention and attributes. */
604 mangled = dlang_call_convention (call ? call : &dump, mangled);
605 mangled = dlang_attributes (attr ? attr : &dump, mangled);
606
607 if (args)
608 string_append (args, "(");
609
610 mangled = dlang_function_args (args ? args : &dump, mangled, info);
611 if (args)
612 string_append (args, ")");
613
614 string_delete (&dump);
615 return mangled;
616}
617
43b1b9ed
IB
618/* Demangle the function type from MANGLED and append it to DECL.
619 Return the remaining string on success or NULL on failure. */
620static const char *
3f30a274 621dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
622{
623 string attr, args, type;
43b1b9ed
IB
624
625 if (mangled == NULL || *mangled == '\0')
76b41cad 626 return NULL;
43b1b9ed
IB
627
628 /* The order of the mangled string is:
629 CallConvention FuncAttrs Arguments ArgClose Type
630
631 The demangled string is re-ordered as:
632 CallConvention Type Arguments FuncAttrs
633 */
634 string_init (&attr);
635 string_init (&args);
636 string_init (&type);
637
3f30a274 638 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
43b1b9ed
IB
639
640 /* Function return type. */
3f30a274 641 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
642
643 /* Append to decl in order. */
3f30a274
IB
644 string_appendn (decl, type.b, string_length (&type));
645 string_appendn (decl, args.b, string_length (&args));
646 string_append (decl, " ");
647 string_appendn (decl, attr.b, string_length (&attr));
43b1b9ed
IB
648
649 string_delete (&attr);
650 string_delete (&args);
651 string_delete (&type);
652 return mangled;
653}
654
655/* Demangle the argument list from MANGLED and append it to DECL.
656 Return the remaining string on success or NULL on failure. */
657static const char *
3f30a274 658dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
659{
660 size_t n = 0;
661
662 while (mangled && *mangled != '\0')
663 {
664 switch (*mangled)
665 {
666 case 'X': /* (variadic T t...) style. */
667 mangled++;
668 string_append (decl, "...");
669 return mangled;
670 case 'Y': /* (variadic T t, ...) style. */
671 mangled++;
acf1f7da
IB
672 if (n != 0)
673 string_append (decl, ", ");
674 string_append (decl, "...");
43b1b9ed
IB
675 return mangled;
676 case 'Z': /* Normal function. */
677 mangled++;
678 return mangled;
679 }
680
681 if (n++)
682 string_append (decl, ", ");
683
684 if (*mangled == 'M') /* scope(T) */
685 {
686 mangled++;
687 string_append (decl, "scope ");
688 }
689
7ce4461f
IB
690 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
691 {
692 mangled += 2;
693 string_append (decl, "return ");
694 }
695
43b1b9ed
IB
696 switch (*mangled)
697 {
698 case 'J': /* out(T) */
699 mangled++;
700 string_append (decl, "out ");
701 break;
702 case 'K': /* ref(T) */
703 mangled++;
704 string_append (decl, "ref ");
705 break;
706 case 'L': /* lazy(T) */
707 mangled++;
708 string_append (decl, "lazy ");
709 break;
710 }
3f30a274 711 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
712 }
713
714 return mangled;
715}
716
717/* Demangle the type from MANGLED and append it to DECL.
718 Return the remaining string on success or NULL on failure. */
719static const char *
3f30a274 720dlang_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
721{
722 if (mangled == NULL || *mangled == '\0')
76b41cad 723 return NULL;
43b1b9ed
IB
724
725 switch (*mangled)
726 {
727 case 'O': /* shared(T) */
728 mangled++;
729 string_append (decl, "shared(");
3f30a274 730 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
731 string_append (decl, ")");
732 return mangled;
733 case 'x': /* const(T) */
734 mangled++;
735 string_append (decl, "const(");
3f30a274 736 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
737 string_append (decl, ")");
738 return mangled;
739 case 'y': /* immutable(T) */
740 mangled++;
741 string_append (decl, "immutable(");
3f30a274 742 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
743 string_append (decl, ")");
744 return mangled;
745 case 'N':
746 mangled++;
747 if (*mangled == 'g') /* wild(T) */
748 {
749 mangled++;
750 string_append (decl, "inout(");
3f30a274 751 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
752 string_append (decl, ")");
753 return mangled;
754 }
755 else if (*mangled == 'h') /* vector(T) */
756 {
757 mangled++;
758 string_append (decl, "__vector(");
3f30a274 759 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
760 string_append (decl, ")");
761 return mangled;
762 }
763 else
764 return NULL;
765 case 'A': /* dynamic array (T[]) */
766 mangled++;
3f30a274 767 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
768 string_append (decl, "[]");
769 return mangled;
770 case 'G': /* static array (T[N]) */
771 {
772 const char *numptr;
773 size_t num = 0;
774 mangled++;
775
776 numptr = mangled;
777 while (ISDIGIT (*mangled))
778 {
779 num++;
780 mangled++;
781 }
3f30a274 782 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
783 string_append (decl, "[");
784 string_appendn (decl, numptr, num);
785 string_append (decl, "]");
786 return mangled;
787 }
788 case 'H': /* associative array (T[T]) */
789 {
790 string type;
791 size_t sztype;
792 mangled++;
793
794 string_init (&type);
3f30a274 795 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
796 sztype = string_length (&type);
797
3f30a274 798 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
799 string_append (decl, "[");
800 string_appendn (decl, type.b, sztype);
801 string_append (decl, "]");
802
803 string_delete (&type);
804 return mangled;
805 }
806 case 'P': /* pointer (T*) */
807 mangled++;
0e3712f6 808 if (!dlang_call_convention_p (mangled))
0f4b8b31 809 {
3f30a274 810 mangled = dlang_type (decl, mangled, info);
0e3712f6 811 string_append (decl, "*");
0f4b8b31
IB
812 return mangled;
813 }
0e3712f6
IB
814 /* Fall through */
815 case 'F': /* function T (D) */
816 case 'U': /* function T (C) */
817 case 'W': /* function T (Windows) */
818 case 'V': /* function T (Pascal) */
819 case 'R': /* function T (C++) */
820 case 'Y': /* function T (Objective-C) */
821 /* Function pointer types don't include the trailing asterisk. */
3f30a274 822 mangled = dlang_function_type (decl, mangled, info);
0e3712f6 823 string_append (decl, "function");
43b1b9ed
IB
824 return mangled;
825 case 'I': /* ident T */
826 case 'C': /* class T */
827 case 'S': /* struct T */
828 case 'E': /* enum T */
829 case 'T': /* typedef T */
830 mangled++;
3f30a274 831 return dlang_parse_qualified (decl, mangled, info, 0);
43b1b9ed 832 case 'D': /* delegate T */
fa66ced4
IB
833 {
834 string mods;
835 size_t szmods;
43b1b9ed 836 mangled++;
fa66ced4
IB
837
838 string_init (&mods);
839 mangled = dlang_type_modifiers (&mods, mangled);
840 szmods = string_length (&mods);
841
3f30a274
IB
842 /* Back referenced function type. */
843 if (*mangled == 'Q')
844 mangled = dlang_type_backref (decl, mangled, info, 1);
845 else
846 mangled = dlang_function_type (decl, mangled, info);
847
43b1b9ed 848 string_append (decl, "delegate");
fa66ced4
IB
849 string_appendn (decl, mods.b, szmods);
850
851 string_delete (&mods);
43b1b9ed 852 return mangled;
fa66ced4 853 }
43b1b9ed
IB
854 case 'B': /* tuple T */
855 mangled++;
3f30a274 856 return dlang_parse_tuple (decl, mangled, info);
43b1b9ed 857
43b1b9ed
IB
858 /* Basic types */
859 case 'n':
860 mangled++;
861 string_append (decl, "none");
862 return mangled;
863 case 'v':
864 mangled++;
865 string_append (decl, "void");
866 return mangled;
867 case 'g':
868 mangled++;
869 string_append (decl, "byte");
870 return mangled;
871 case 'h':
872 mangled++;
873 string_append (decl, "ubyte");
874 return mangled;
875 case 's':
876 mangled++;
877 string_append (decl, "short");
878 return mangled;
879 case 't':
880 mangled++;
881 string_append (decl, "ushort");
882 return mangled;
883 case 'i':
884 mangled++;
885 string_append (decl, "int");
886 return mangled;
887 case 'k':
888 mangled++;
889 string_append (decl, "uint");
890 return mangled;
891 case 'l':
892 mangled++;
893 string_append (decl, "long");
894 return mangled;
895 case 'm':
896 mangled++;
897 string_append (decl, "ulong");
898 return mangled;
899 case 'f':
900 mangled++;
901 string_append (decl, "float");
902 return mangled;
903 case 'd':
904 mangled++;
905 string_append (decl, "double");
906 return mangled;
907 case 'e':
908 mangled++;
909 string_append (decl, "real");
910 return mangled;
911
912 /* Imaginary and Complex types */
913 case 'o':
914 mangled++;
915 string_append (decl, "ifloat");
916 return mangled;
917 case 'p':
918 mangled++;
919 string_append (decl, "idouble");
920 return mangled;
921 case 'j':
922 mangled++;
923 string_append (decl, "ireal");
924 return mangled;
925 case 'q':
926 mangled++;
927 string_append (decl, "cfloat");
928 return mangled;
929 case 'r':
930 mangled++;
931 string_append (decl, "cdouble");
932 return mangled;
933 case 'c':
934 mangled++;
935 string_append (decl, "creal");
936 return mangled;
937
938 /* Other types */
939 case 'b':
940 mangled++;
941 string_append (decl, "bool");
942 return mangled;
943 case 'a':
944 mangled++;
945 string_append (decl, "char");
946 return mangled;
947 case 'u':
948 mangled++;
949 string_append (decl, "wchar");
950 return mangled;
951 case 'w':
952 mangled++;
953 string_append (decl, "dchar");
954 return mangled;
59251a73
IB
955 case 'z':
956 mangled++;
957 switch (*mangled)
958 {
959 case 'i':
960 mangled++;
961 string_append (decl, "cent");
962 return mangled;
963 case 'k':
964 mangled++;
965 string_append (decl, "ucent");
966 return mangled;
967 }
968 return NULL;
43b1b9ed 969
3f30a274
IB
970 /* Back referenced type. */
971 case 'Q':
972 return dlang_type_backref (decl, mangled, info, 0);
973
43b1b9ed
IB
974 default: /* unhandled */
975 return NULL;
976 }
977}
978
979/* Extract the identifier from MANGLED and append it to DECL.
980 Return the remaining string on success or NULL on failure. */
981static const char *
3f30a274 982dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 983{
7e865541
IB
984 long len;
985
3f30a274 986 if (mangled == NULL || *mangled == '\0')
7e865541
IB
987 return NULL;
988
3f30a274
IB
989 if (*mangled == 'Q')
990 return dlang_symbol_backref (decl, mangled, info);
43b1b9ed 991
3f30a274
IB
992 /* May be a template instance without a length prefix. */
993 if (mangled[0] == '_' && mangled[1] == '_'
994 && (mangled[2] == 'T' || mangled[2] == 'U'))
995 return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
7e865541 996
3f30a274 997 const char *endptr = dlang_number (mangled, &len);
7e865541 998
3f30a274
IB
999 if (endptr == NULL || len == 0)
1000 return NULL;
7e865541 1001
3f30a274
IB
1002 if (strlen (endptr) < (size_t) len)
1003 return NULL;
7e865541 1004
3f30a274 1005 mangled = endptr;
43b1b9ed 1006
3f30a274
IB
1007 /* May be a template instance with a length prefix. */
1008 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1009 && (mangled[2] == 'T' || mangled[2] == 'U'))
1010 return dlang_parse_template (decl, mangled, info, len);
43b1b9ed 1011
3f30a274
IB
1012 return dlang_lname (decl, mangled, len);
1013}
43b1b9ed 1014
3f30a274
IB
1015/* Extract the plain identifier from MANGLED and prepend/append it to DECL
1016 with special treatment for some magic compiler generted symbols.
1017 Return the remaining string on success or NULL on failure. */
1018static const char *
1019dlang_lname (string *decl, const char *mangled, long len)
1020{
1021 switch (len)
1022 {
1023 case 6:
1024 if (strncmp (mangled, "__ctor", len) == 0)
43b1b9ed 1025 {
3f30a274
IB
1026 /* Constructor symbol for a class/struct. */
1027 string_append (decl, "this");
1028 mangled += len;
1029 return mangled;
1030 }
1031 else if (strncmp (mangled, "__dtor", len) == 0)
1032 {
1033 /* Destructor symbol for a class/struct. */
1034 string_append (decl, "~this");
1035 mangled += len;
1036 return mangled;
1037 }
1038 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1039 {
1040 /* The static initialiser for a given symbol. */
1041 string_prepend (decl, "initializer for ");
1042 string_setlength (decl, string_length (decl) - 1);
1043 mangled += len;
1044 return mangled;
1045 }
1046 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1047 {
1048 /* The vtable symbol for a given class. */
1049 string_prepend (decl, "vtable for ");
1050 string_setlength (decl, string_length (decl) - 1);
1051 mangled += len;
1052 return mangled;
1053 }
1054 break;
5cc158e9 1055
3f30a274
IB
1056 case 7:
1057 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1058 {
1059 /* The classinfo symbol for a given class. */
1060 string_prepend (decl, "ClassInfo for ");
1061 string_setlength (decl, string_length (decl) - 1);
1062 mangled += len;
1063 return mangled;
1064 }
1065 break;
5cc158e9 1066
3f30a274
IB
1067 case 10:
1068 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1069 {
1070 /* Postblit symbol for a struct. */
1071 string_append (decl, "this(this)");
1072 mangled += len + 3;
1073 return mangled;
1074 }
1075 break;
5cc158e9 1076
3f30a274
IB
1077 case 11:
1078 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1079 {
1080 /* The interface symbol for a given class. */
1081 string_prepend (decl, "Interface for ");
1082 string_setlength (decl, string_length (decl) - 1);
1083 mangled += len;
1084 return mangled;
43b1b9ed 1085 }
3f30a274 1086 break;
43b1b9ed 1087
3f30a274
IB
1088 case 12:
1089 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1090 {
1091 /* The ModuleInfo symbol for a given module. */
1092 string_prepend (decl, "ModuleInfo for ");
1093 string_setlength (decl, string_length (decl) - 1);
1094 mangled += len;
1095 return mangled;
1096 }
1097 break;
43b1b9ed 1098 }
43b1b9ed 1099
3f30a274
IB
1100 string_appendn (decl, mangled, len);
1101 mangled += len;
1102
43b1b9ed
IB
1103 return mangled;
1104}
1105
1106/* Extract the integer value from MANGLED and append it to DECL,
1107 where TYPE is the type it should be represented as.
1108 Return the remaining string on success or NULL on failure. */
1109static const char *
1110dlang_parse_integer (string *decl, const char *mangled, char type)
1111{
1112 if (type == 'a' || type == 'u' || type == 'w')
1113 {
1114 /* Parse character value. */
81adfd10
B
1115 char value[20];
1116 int pos = sizeof(value);
43b1b9ed 1117 int width = 0;
dbe65f77 1118 long val;
43b1b9ed 1119
dbe65f77
IB
1120 mangled = dlang_number (mangled, &val);
1121 if (mangled == NULL)
43b1b9ed
IB
1122 return NULL;
1123
1124 string_append (decl, "'");
1125
1126 if (type == 'a' && val >= 0x20 && val < 0x7F)
1127 {
1128 /* Represent as a character literal. */
1129 char c = (char) val;
1130 string_appendn (decl, &c, 1);
1131 }
1132 else
1133 {
1134 /* Represent as a hexadecimal value. */
1135 switch (type)
1136 {
1137 case 'a': /* char */
1138 string_append (decl, "\\x");
1139 width = 2;
1140 break;
1141 case 'u': /* wchar */
1142 string_append (decl, "\\u");
1143 width = 4;
1144 break;
1145 case 'w': /* dchar */
1146 string_append (decl, "\\U");
1147 width = 8;
1148 break;
1149 }
1150
1151 while (val > 0)
1152 {
1153 int digit = val % 16;
1154
1155 if (digit < 10)
1156 value[--pos] = (char)(digit + '0');
1157 else
1158 value[--pos] = (char)((digit - 10) + 'a');
1159
1160 val /= 16;
1161 width--;
1162 }
1163
1164 for (; width > 0; width--)
1165 value[--pos] = '0';
1166
81adfd10 1167 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
43b1b9ed
IB
1168 }
1169 string_append (decl, "'");
43b1b9ed
IB
1170 }
1171 else if (type == 'b')
1172 {
1173 /* Parse boolean value. */
dbe65f77 1174 long val;
43b1b9ed 1175
dbe65f77
IB
1176 mangled = dlang_number (mangled, &val);
1177 if (mangled == NULL)
43b1b9ed
IB
1178 return NULL;
1179
1180 string_append (decl, val ? "true" : "false");
43b1b9ed
IB
1181 }
1182 else
1183 {
1184 /* Parse integer value. */
1185 const char *numptr = mangled;
1186 size_t num = 0;
1187
dbe65f77
IB
1188 if (! ISDIGIT (*mangled))
1189 return NULL;
1190
43b1b9ed
IB
1191 while (ISDIGIT (*mangled))
1192 {
1193 num++;
1194 mangled++;
1195 }
1196 string_appendn (decl, numptr, num);
1197
1198 /* Append suffix. */
1199 switch (type)
1200 {
1201 case 'h': /* ubyte */
1202 case 't': /* ushort */
1203 case 'k': /* uint */
1204 string_append (decl, "u");
1205 break;
1206 case 'l': /* long */
1207 string_append (decl, "L");
1208 break;
1209 case 'm': /* ulong */
1210 string_append (decl, "uL");
1211 break;
1212 }
1213 }
1214
1215 return mangled;
1216}
1217
1218/* Extract the floating-point value from MANGLED and append it to DECL.
1219 Return the remaining string on success or NULL on failure. */
1220static const char *
1221dlang_parse_real (string *decl, const char *mangled)
1222{
43b1b9ed
IB
1223 /* Handle NAN and +-INF. */
1224 if (strncmp (mangled, "NAN", 3) == 0)
1225 {
1226 string_append (decl, "NaN");
1227 mangled += 3;
1228 return mangled;
1229 }
1230 else if (strncmp (mangled, "INF", 3) == 0)
1231 {
1232 string_append (decl, "Inf");
1233 mangled += 3;
1234 return mangled;
1235 }
1236 else if (strncmp (mangled, "NINF", 4) == 0)
1237 {
1238 string_append (decl, "-Inf");
1239 mangled += 4;
1240 return mangled;
1241 }
1242
1243 /* Hexadecimal prefix and leading bit. */
1244 if (*mangled == 'N')
1245 {
1a122a71 1246 string_append (decl, "-");
43b1b9ed
IB
1247 mangled++;
1248 }
1249
1250 if (!ISXDIGIT (*mangled))
1251 return NULL;
1252
1a122a71
IB
1253 string_append (decl, "0x");
1254 string_appendn (decl, mangled, 1);
1255 string_append (decl, ".");
43b1b9ed
IB
1256 mangled++;
1257
1258 /* Significand. */
1259 while (ISXDIGIT (*mangled))
1260 {
1a122a71 1261 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1262 mangled++;
1263 }
1264
1265 /* Exponent. */
1266 if (*mangled != 'P')
1267 return NULL;
1268
1a122a71 1269 string_append (decl, "p");
43b1b9ed
IB
1270 mangled++;
1271
1272 if (*mangled == 'N')
1273 {
1a122a71 1274 string_append (decl, "-");
43b1b9ed
IB
1275 mangled++;
1276 }
1277
1278 while (ISDIGIT (*mangled))
1279 {
1a122a71 1280 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1281 mangled++;
1282 }
1283
43b1b9ed
IB
1284 return mangled;
1285}
1286
43b1b9ed
IB
1287/* Extract the string value from MANGLED and append it to DECL.
1288 Return the remaining string on success or NULL on failure. */
1289static const char *
1290dlang_parse_string (string *decl, const char *mangled)
1291{
1292 char type = *mangled;
43b1b9ed
IB
1293 long len;
1294
1295 mangled++;
dbe65f77
IB
1296 mangled = dlang_number (mangled, &len);
1297 if (mangled == NULL || *mangled != '_')
43b1b9ed
IB
1298 return NULL;
1299
1300 mangled++;
1301 string_append (decl, "\"");
1302 while (len--)
1303 {
5398cab9
IB
1304 char val;
1305 const char *endptr = dlang_hexdigit (mangled, &val);
1306
1307 if (endptr == NULL)
1308 return NULL;
1309
1310 /* Sanitize white and non-printable characters. */
1311 switch (val)
43b1b9ed 1312 {
5398cab9
IB
1313 case ' ':
1314 string_append (decl, " ");
1315 break;
1316 case '\t':
1317 string_append (decl, "\\t");
1318 break;
1319 case '\n':
1320 string_append (decl, "\\n");
1321 break;
1322 case '\r':
1323 string_append (decl, "\\r");
1324 break;
1325 case '\f':
1326 string_append (decl, "\\f");
1327 break;
1328 case '\v':
1329 string_append (decl, "\\v");
1330 break;
eb058b7d 1331
5398cab9
IB
1332 default:
1333 if (ISPRINT (val))
1334 string_appendn (decl, &val, 1);
1335 else
eb058b7d 1336 {
5398cab9
IB
1337 string_append (decl, "\\x");
1338 string_appendn (decl, mangled, 2);
eb058b7d 1339 }
43b1b9ed 1340 }
43b1b9ed 1341
5398cab9 1342 mangled = endptr;
43b1b9ed
IB
1343 }
1344 string_append (decl, "\"");
1345
1346 if (type != 'a')
1347 string_appendn (decl, &type, 1);
1348
1349 return mangled;
1350}
1351
1352/* Extract the static array value from MANGLED and append it to DECL.
1353 Return the remaining string on success or NULL on failure. */
1354static const char *
1355dlang_parse_arrayliteral (string *decl, const char *mangled)
1356{
dbe65f77 1357 long elements;
43b1b9ed 1358
dbe65f77
IB
1359 mangled = dlang_number (mangled, &elements);
1360 if (mangled == NULL)
43b1b9ed
IB
1361 return NULL;
1362
43b1b9ed
IB
1363 string_append (decl, "[");
1364 while (elements--)
1365 {
1366 mangled = dlang_value (decl, mangled, NULL, '\0');
80b1ab15
B
1367 if (mangled == NULL)
1368 return NULL;
1369
43b1b9ed
IB
1370 if (elements != 0)
1371 string_append (decl, ", ");
1372 }
1373
1374 string_append (decl, "]");
1375 return mangled;
1376}
1377
1378/* Extract the associative array value from MANGLED and append it to DECL.
1379 Return the remaining string on success or NULL on failure. */
1380static const char *
1381dlang_parse_assocarray (string *decl, const char *mangled)
1382{
dbe65f77 1383 long elements;
43b1b9ed 1384
dbe65f77
IB
1385 mangled = dlang_number (mangled, &elements);
1386 if (mangled == NULL)
43b1b9ed
IB
1387 return NULL;
1388
43b1b9ed
IB
1389 string_append (decl, "[");
1390 while (elements--)
1391 {
1392 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1393 if (mangled == NULL)
1394 return NULL;
1395
43b1b9ed
IB
1396 string_append (decl, ":");
1397 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1398 if (mangled == NULL)
1399 return NULL;
43b1b9ed
IB
1400
1401 if (elements != 0)
1402 string_append (decl, ", ");
1403 }
1404
1405 string_append (decl, "]");
1406 return mangled;
1407}
1408
1409/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1410 Return the remaining string on success or NULL on failure. */
1411static const char *
1412dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1413{
dbe65f77 1414 long args;
43b1b9ed 1415
dbe65f77
IB
1416 mangled = dlang_number (mangled, &args);
1417 if (mangled == NULL)
43b1b9ed
IB
1418 return NULL;
1419
43b1b9ed
IB
1420 if (name != NULL)
1421 string_append (decl, name);
1422
1423 string_append (decl, "(");
1424 while (args--)
1425 {
1426 mangled = dlang_value (decl, mangled, NULL, '\0');
dba20a51
B
1427 if (mangled == NULL)
1428 return NULL;
1429
43b1b9ed
IB
1430 if (args != 0)
1431 string_append (decl, ", ");
1432 }
1433
1434 string_append (decl, ")");
1435 return mangled;
1436}
1437
1438/* Extract the value from MANGLED and append it to DECL.
1439 Return the remaining string on success or NULL on failure. */
1440static const char *
1441dlang_value (string *decl, const char *mangled, const char *name, char type)
1442{
1443 if (mangled == NULL || *mangled == '\0')
76b41cad 1444 return NULL;
43b1b9ed
IB
1445
1446 switch (*mangled)
1447 {
1448 /* Null value. */
1449 case 'n':
1450 mangled++;
1451 string_append (decl, "null");
1452 break;
1453
1454 /* Integral values. */
1455 case 'N':
1456 mangled++;
1457 string_append (decl, "-");
1458 mangled = dlang_parse_integer (decl, mangled, type);
1459 break;
1460
1461 case 'i':
1462 mangled++;
43b1b9ed 1463 /* Fall through */
dd03444b
IB
1464
1465 /* There really should always be an `i' before encoded numbers, but there
1466 wasn't in early versions of D2, so this case range must remain for
1467 backwards compatibility. */
43b1b9ed
IB
1468 case '0': case '1': case '2': case '3': case '4':
1469 case '5': case '6': case '7': case '8': case '9':
1470 mangled = dlang_parse_integer (decl, mangled, type);
1471 break;
1472
1473 /* Real value. */
1474 case 'e':
1475 mangled++;
1476 mangled = dlang_parse_real (decl, mangled);
1477 break;
1478
1479 /* Complex value. */
1480 case 'c':
1481 mangled++;
1482 mangled = dlang_parse_real (decl, mangled);
1483 string_append (decl, "+");
1484 if (mangled == NULL || *mangled != 'c')
1485 return NULL;
1486 mangled++;
1487 mangled = dlang_parse_real (decl, mangled);
1488 string_append (decl, "i");
1489 break;
1490
1491 /* String values. */
1492 case 'a': /* UTF8 */
1493 case 'w': /* UTF16 */
1494 case 'd': /* UTF32 */
1495 mangled = dlang_parse_string (decl, mangled);
1496 break;
1497
1498 /* Array values. */
1499 case 'A':
1500 mangled++;
1501 if (type == 'H')
1502 mangled = dlang_parse_assocarray (decl, mangled);
1503 else
1504 mangled = dlang_parse_arrayliteral (decl, mangled);
1505 break;
1506
1507 /* Struct values. */
1508 case 'S':
1509 mangled++;
1510 mangled = dlang_parse_structlit (decl, mangled, name);
1511 break;
1512
1513 default:
1514 return NULL;
1515 }
1516
1517 return mangled;
1518}
1519
43b1b9ed
IB
1520/* Extract and demangle the symbol in MANGLED and append it to DECL.
1521 Returns the remaining signature on success or NULL on failure. */
1522static const char *
3f30a274 1523dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1524{
5a4dbf7d
IB
1525 /* A D mangled symbol is comprised of both scope and type information.
1526
1527 MangleName:
1528 _D QualifiedName Type
5a4dbf7d
IB
1529 _D QualifiedName Z
1530 ^
1531 The caller should have guaranteed that the start pointer is at the
1532 above location.
3f30a274
IB
1533 Note that type is never a function type, but only the return type of
1534 a function or the type of a variable.
5a4dbf7d
IB
1535 */
1536 mangled += 2;
1537
3f30a274 1538 mangled = dlang_parse_qualified (decl, mangled, info, 1);
5a4dbf7d
IB
1539
1540 if (mangled != NULL)
1541 {
1542 /* Artificial symbols end with 'Z' and have no type. */
1543 if (*mangled == 'Z')
1544 mangled++;
1545 else
1546 {
3f30a274
IB
1547 /* Discard the declaration or return type. */
1548 string type;
5a4dbf7d 1549
3f30a274
IB
1550 string_init (&type);
1551 mangled = dlang_type (&type, mangled, info);
1552 string_delete (&type);
5a4dbf7d
IB
1553 }
1554 }
1555
5a4dbf7d
IB
1556 return mangled;
1557}
1558
1559/* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
3f30a274 1560 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
5a4dbf7d
IB
1561 Returns the remaining signature on success or NULL on failure. */
1562static const char *
1563dlang_parse_qualified (string *decl, const char *mangled,
3f30a274 1564 struct dlang_info *info, int suffix_modifiers)
5a4dbf7d
IB
1565{
1566 /* Qualified names are identifiers separated by their encoded length.
1567 Nested functions also encode their argument types without specifying
1568 what they return.
1569
1570 QualifiedName:
3f30a274
IB
1571 SymbolFunctionName
1572 SymbolFunctionName QualifiedName
5a4dbf7d 1573 ^
3f30a274
IB
1574
1575 SymbolFunctionName:
1576 SymbolName
1577 SymbolName TypeFunctionNoReturn
1578 SymbolName M TypeFunctionNoReturn
1579 SymbolName M TypeModifiers TypeFunctionNoReturn
1580
5a4dbf7d
IB
1581 The start pointer should be at the above location.
1582 */
43b1b9ed
IB
1583 size_t n = 0;
1584 do
1585 {
1586 if (n++)
1587 string_append (decl, ".");
1588
98bb7ee2
IB
1589 /* Skip over anonymous symbols. */
1590 while (*mangled == '0')
1591 mangled++;
1592
3f30a274 1593 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed 1594
5a4dbf7d 1595 /* Consume the encoded arguments. However if this is not followed by the
3f30a274
IB
1596 next encoded length or mangle type, then this is not a continuation of
1597 a qualified name, in which case we backtrack and return the current
1598 unconsumed position of the mangled decl. */
5a4dbf7d 1599 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
43b1b9ed 1600 {
3f30a274 1601 string mods;
5a4dbf7d
IB
1602 const char *start = mangled;
1603 int saved = string_length (decl);
43b1b9ed 1604
3f30a274
IB
1605 /* Save the type modifiers for appending at the end if needed. */
1606 string_init (&mods);
1607
5a4dbf7d 1608 /* Skip over 'this' parameter and type modifiers. */
43b1b9ed 1609 if (*mangled == 'M')
7e865541 1610 {
5a4dbf7d 1611 mangled++;
3f30a274 1612 mangled = dlang_type_modifiers (&mods, mangled);
5a4dbf7d 1613 string_setlength (decl, saved);
7e865541
IB
1614 }
1615
3f30a274
IB
1616 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1617 mangled, info);
1618 if (suffix_modifiers)
1619 string_appendn (decl, mods.b, string_length (&mods));
43b1b9ed 1620
3f30a274 1621 if (mangled == NULL || *mangled == '\0')
7e865541 1622 {
5a4dbf7d 1623 /* Did not match the rule we were looking for. */
7e865541 1624 mangled = start;
5a4dbf7d 1625 string_setlength (decl, saved);
7e865541 1626 }
3f30a274
IB
1627
1628 string_delete (&mods);
43b1b9ed
IB
1629 }
1630 }
3f30a274 1631 while (mangled && dlang_symbol_name_p (mangled, info));
43b1b9ed
IB
1632
1633 return mangled;
1634}
1635
1636/* Demangle the tuple from MANGLED and append it to DECL.
1637 Return the remaining string on success or NULL on failure. */
1638static const char *
3f30a274 1639dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1640{
dbe65f77 1641 long elements;
43b1b9ed 1642
dbe65f77
IB
1643 mangled = dlang_number (mangled, &elements);
1644 if (mangled == NULL)
43b1b9ed
IB
1645 return NULL;
1646
43b1b9ed
IB
1647 string_append (decl, "Tuple!(");
1648
1649 while (elements--)
1650 {
3f30a274 1651 mangled = dlang_type (decl, mangled, info);
f181b8e7
B
1652 if (mangled == NULL)
1653 return NULL;
1654
43b1b9ed
IB
1655 if (elements != 0)
1656 string_append (decl, ", ");
1657 }
1658
1659 string_append (decl, ")");
1660 return mangled;
1661}
1662
3f30a274
IB
1663/* Demangle the template symbol parameter from MANGLED and append it to DECL.
1664 Return the remaining string on success or NULL on failure. */
1665static const char *
1666dlang_template_symbol_param (string *decl, const char *mangled,
1667 struct dlang_info *info)
1668{
1669 if (strncmp (mangled, "_D", 2) == 0
1670 && dlang_symbol_name_p (mangled + 2, info))
1671 return dlang_parse_mangle (decl, mangled, info);
1672
1673 if (*mangled == 'Q')
1674 return dlang_parse_qualified (decl, mangled, info, 0);
1675
1676 long len;
1677 const char *endptr = dlang_number (mangled, &len);
1678
1679 if (endptr == NULL || len == 0)
1680 return NULL;
1681
1682 /* In template parameter symbols generated by the frontend up to 2.076,
1683 the symbol length is encoded and the first character of the mangled
1684 name can be a digit. This causes ambiguity issues because the digits
1685 of the two numbers are adjacent. */
1686 long psize = len;
1687 const char *pend;
1688 int saved = string_length (decl);
1689
1690 /* Work backwards until a match is found. */
1691 for (pend = endptr; endptr != NULL; pend--)
1692 {
1693 mangled = pend;
1694
1695 /* Reached the beginning of the pointer to the name length,
1696 try parsing the entire symbol. */
1697 if (psize == 0)
1698 {
1699 psize = len;
1700 pend = endptr;
1701 endptr = NULL;
1702 }
1703
1704 /* Check whether template parameter is a function with a valid
1705 return type or an untyped identifier. */
1706 if (dlang_symbol_name_p (mangled, info))
1707 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1708 else if (strncmp (mangled, "_D", 2) == 0
1709 && dlang_symbol_name_p (mangled + 2, info))
1710 mangled = dlang_parse_mangle (decl, mangled, info);
1711
1712 /* Check for name length mismatch. */
1713 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1714 return mangled;
1715
1716 psize /= 10;
1717 string_setlength (decl, saved);
1718 }
1719
1720 /* No match on any combinations. */
1721 return NULL;
1722}
1723
43b1b9ed
IB
1724/* Demangle the argument list from MANGLED and append it to DECL.
1725 Return the remaining string on success or NULL on failure. */
1726static const char *
3f30a274 1727dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
1728{
1729 size_t n = 0;
1730
1731 while (mangled && *mangled != '\0')
1732 {
1733 switch (*mangled)
1734 {
1735 case 'Z': /* End of parameter list. */
1736 mangled++;
1737 return mangled;
1738 }
1739
1740 if (n++)
1741 string_append (decl, ", ");
1742
ed4cdb85
IB
1743 /* Skip over specialised template prefix. */
1744 if (*mangled == 'H')
1745 mangled++;
1746
43b1b9ed
IB
1747 switch (*mangled)
1748 {
1749 case 'S': /* Symbol parameter. */
1750 mangled++;
3f30a274 1751 mangled = dlang_template_symbol_param (decl, mangled, info);
43b1b9ed
IB
1752 break;
1753 case 'T': /* Type parameter. */
1754 mangled++;
3f30a274 1755 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
1756 break;
1757 case 'V': /* Value parameter. */
1758 {
1759 string name;
1760 char type;
1761
1762 /* Peek at the type. */
1763 mangled++;
1764 type = *mangled;
1765
3f30a274
IB
1766 if (type == 'Q')
1767 {
1768 /* Value type is a back reference, peek at the real type. */
1769 const char *backref;
1770 if (dlang_backref (mangled, &backref, info) == NULL)
1771 return NULL;
1772
1773 type = *backref;
1774 }
1775
43b1b9ed
IB
1776 /* In the few instances where the type is actually desired in
1777 the output, it should precede the value from dlang_value. */
1778 string_init (&name);
3f30a274 1779 mangled = dlang_type (&name, mangled, info);
43b1b9ed
IB
1780 string_need (&name, 1);
1781 *(name.p) = '\0';
1782
1783 mangled = dlang_value (decl, mangled, name.b, type);
1784 string_delete (&name);
1785 break;
1786 }
3f30a274
IB
1787 case 'X': /* Externally mangled parameter. */
1788 {
1789 long len;
1790 const char *endptr;
43b1b9ed 1791
3f30a274
IB
1792 mangled++;
1793 endptr = dlang_number (mangled, &len);
1794 if (endptr == NULL || strlen (endptr) < (size_t) len)
1795 return NULL;
1796
1797 string_appendn (decl, endptr, len);
1798 mangled = endptr + len;
1799 break;
1800 }
43b1b9ed
IB
1801 default:
1802 return NULL;
1803 }
1804 }
1805
1806 return mangled;
1807}
1808
1809/* Extract and demangle the template symbol in MANGLED, expected to
3f30a274 1810 be made up of LEN characters (-1 if unknown), and append it to DECL.
43b1b9ed
IB
1811 Returns the remaining signature on success or NULL on failure. */
1812static const char *
3f30a274
IB
1813dlang_parse_template (string *decl, const char *mangled,
1814 struct dlang_info *info, long len)
43b1b9ed
IB
1815{
1816 const char *start = mangled;
3f30a274 1817 string args;
43b1b9ed
IB
1818
1819 /* Template instance names have the types and values of its parameters
1820 encoded into it.
1821
1822 TemplateInstanceName:
1823 Number __T LName TemplateArgs Z
c6f44bae 1824 Number __U LName TemplateArgs Z
43b1b9ed
IB
1825 ^
1826 The start pointer should be at the above location, and LEN should be
1827 the value of the decoded number.
1828 */
c6f44bae
IB
1829
1830 /* Template symbol. */
3f30a274 1831 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
43b1b9ed
IB
1832 return NULL;
1833
1834 mangled += 3;
1835
1836 /* Template identifier. */
3f30a274 1837 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed
IB
1838
1839 /* Template arguments. */
3f30a274
IB
1840 string_init (&args);
1841 mangled = dlang_template_args (&args, mangled, info);
1842
43b1b9ed 1843 string_append (decl, "!(");
3f30a274 1844 string_appendn (decl, args.b, string_length (&args));
43b1b9ed
IB
1845 string_append (decl, ")");
1846
3f30a274
IB
1847 string_delete (&args);
1848
43b1b9ed 1849 /* Check for template name length mismatch. */
3f30a274 1850 if (len != TEMPLATE_LENGTH_UNKNOWN && mangled && (mangled - start) != len)
43b1b9ed
IB
1851 return NULL;
1852
1853 return mangled;
1854}
1855
3f30a274
IB
1856/* Initialize the information structure we use to pass around information. */
1857static void
1858dlang_demangle_init_info (const char *mangled, int last_backref,
1859 struct dlang_info *info)
1860{
1861 info->s = mangled;
1862 info->last_backref = last_backref;
1863}
1864
43b1b9ed
IB
1865/* Extract and demangle the symbol in MANGLED. Returns the demangled
1866 signature on success or NULL on failure. */
1867
1868char *
1869dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1870{
1871 string decl;
1872 char *demangled = NULL;
1873
1874 if (mangled == NULL || *mangled == '\0')
1875 return NULL;
1876
1877 if (strncmp (mangled, "_D", 2) != 0)
1878 return NULL;
1879
1880 string_init (&decl);
1881
1882 if (strcmp (mangled, "_Dmain") == 0)
1883 {
1884 string_append (&decl, "D main");
1885 }
1886 else
1887 {
3f30a274
IB
1888 struct dlang_info info;
1889
1890 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1891 mangled = dlang_parse_mangle (&decl, mangled, &info);
1892
1893 /* Check that the entire symbol was successfully demangled. */
1894 if (mangled == NULL || *mangled != '\0')
43b1b9ed
IB
1895 string_delete (&decl);
1896 }
1897
1898 if (string_length (&decl) > 0)
1899 {
1900 string_need (&decl, 1);
1901 *(decl.p) = '\0';
1902 demangled = decl.b;
1903 }
1904
1905 return demangled;
1906}
1907