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