]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/d-demangle.c
This patch removes the use of the "register" keyword from the bsearch() and bsearch_r...
[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;
3a55774f
IB
581 case 'm': /* @live */
582 mangled++;
583 string_append (decl, "@live ");
584 continue;
7ce4461f
IB
585
586 default: /* unknown attribute */
587 return NULL;
43b1b9ed
IB
588 }
589 break;
590 }
591
592 return mangled;
593}
594
3f30a274
IB
595/* Demangle the function type from MANGLED without the return type.
596 The arguments are appended to ARGS, the calling convention is appended
597 to CALL and attributes are appended to ATTR. Any of these can be NULL
598 to throw the information away. Return the remaining string on success
599 or NULL on failure. */
600static const char *
601dlang_function_type_noreturn (string *args, string *call, string *attr,
602 const char *mangled, struct dlang_info *info)
603{
604 string dump;
605 string_init (&dump);
606
607 /* Skip over calling convention and attributes. */
608 mangled = dlang_call_convention (call ? call : &dump, mangled);
609 mangled = dlang_attributes (attr ? attr : &dump, mangled);
610
611 if (args)
612 string_append (args, "(");
613
614 mangled = dlang_function_args (args ? args : &dump, mangled, info);
615 if (args)
616 string_append (args, ")");
617
618 string_delete (&dump);
619 return mangled;
620}
621
43b1b9ed
IB
622/* Demangle the function type from MANGLED and append it to DECL.
623 Return the remaining string on success or NULL on failure. */
624static const char *
3f30a274 625dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
626{
627 string attr, args, type;
43b1b9ed
IB
628
629 if (mangled == NULL || *mangled == '\0')
76b41cad 630 return NULL;
43b1b9ed
IB
631
632 /* The order of the mangled string is:
633 CallConvention FuncAttrs Arguments ArgClose Type
634
635 The demangled string is re-ordered as:
636 CallConvention Type Arguments FuncAttrs
637 */
638 string_init (&attr);
639 string_init (&args);
640 string_init (&type);
641
3f30a274 642 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
43b1b9ed
IB
643
644 /* Function return type. */
3f30a274 645 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
646
647 /* Append to decl in order. */
3f30a274
IB
648 string_appendn (decl, type.b, string_length (&type));
649 string_appendn (decl, args.b, string_length (&args));
650 string_append (decl, " ");
651 string_appendn (decl, attr.b, string_length (&attr));
43b1b9ed
IB
652
653 string_delete (&attr);
654 string_delete (&args);
655 string_delete (&type);
656 return mangled;
657}
658
659/* Demangle the argument list from MANGLED and append it to DECL.
660 Return the remaining string on success or NULL on failure. */
661static const char *
3f30a274 662dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
663{
664 size_t n = 0;
665
666 while (mangled && *mangled != '\0')
667 {
668 switch (*mangled)
669 {
670 case 'X': /* (variadic T t...) style. */
671 mangled++;
672 string_append (decl, "...");
673 return mangled;
674 case 'Y': /* (variadic T t, ...) style. */
675 mangled++;
acf1f7da
IB
676 if (n != 0)
677 string_append (decl, ", ");
678 string_append (decl, "...");
43b1b9ed
IB
679 return mangled;
680 case 'Z': /* Normal function. */
681 mangled++;
682 return mangled;
683 }
684
685 if (n++)
686 string_append (decl, ", ");
687
688 if (*mangled == 'M') /* scope(T) */
689 {
690 mangled++;
691 string_append (decl, "scope ");
692 }
693
7ce4461f
IB
694 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
695 {
696 mangled += 2;
697 string_append (decl, "return ");
698 }
699
43b1b9ed
IB
700 switch (*mangled)
701 {
702 case 'J': /* out(T) */
703 mangled++;
704 string_append (decl, "out ");
705 break;
706 case 'K': /* ref(T) */
707 mangled++;
708 string_append (decl, "ref ");
709 break;
710 case 'L': /* lazy(T) */
711 mangled++;
712 string_append (decl, "lazy ");
713 break;
714 }
3f30a274 715 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
716 }
717
718 return mangled;
719}
720
721/* Demangle the type from MANGLED and append it to DECL.
722 Return the remaining string on success or NULL on failure. */
723static const char *
3f30a274 724dlang_type (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
725{
726 if (mangled == NULL || *mangled == '\0')
76b41cad 727 return NULL;
43b1b9ed
IB
728
729 switch (*mangled)
730 {
731 case 'O': /* shared(T) */
732 mangled++;
733 string_append (decl, "shared(");
3f30a274 734 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
735 string_append (decl, ")");
736 return mangled;
737 case 'x': /* const(T) */
738 mangled++;
739 string_append (decl, "const(");
3f30a274 740 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
741 string_append (decl, ")");
742 return mangled;
743 case 'y': /* immutable(T) */
744 mangled++;
745 string_append (decl, "immutable(");
3f30a274 746 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
747 string_append (decl, ")");
748 return mangled;
749 case 'N':
750 mangled++;
751 if (*mangled == 'g') /* wild(T) */
752 {
753 mangled++;
754 string_append (decl, "inout(");
3f30a274 755 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
756 string_append (decl, ")");
757 return mangled;
758 }
759 else if (*mangled == 'h') /* vector(T) */
760 {
761 mangled++;
762 string_append (decl, "__vector(");
3f30a274 763 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
764 string_append (decl, ")");
765 return mangled;
766 }
767 else
768 return NULL;
769 case 'A': /* dynamic array (T[]) */
770 mangled++;
3f30a274 771 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
772 string_append (decl, "[]");
773 return mangled;
774 case 'G': /* static array (T[N]) */
775 {
776 const char *numptr;
777 size_t num = 0;
778 mangled++;
779
780 numptr = mangled;
781 while (ISDIGIT (*mangled))
782 {
783 num++;
784 mangled++;
785 }
3f30a274 786 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
787 string_append (decl, "[");
788 string_appendn (decl, numptr, num);
789 string_append (decl, "]");
790 return mangled;
791 }
792 case 'H': /* associative array (T[T]) */
793 {
794 string type;
795 size_t sztype;
796 mangled++;
797
798 string_init (&type);
3f30a274 799 mangled = dlang_type (&type, mangled, info);
43b1b9ed
IB
800 sztype = string_length (&type);
801
3f30a274 802 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
803 string_append (decl, "[");
804 string_appendn (decl, type.b, sztype);
805 string_append (decl, "]");
806
807 string_delete (&type);
808 return mangled;
809 }
810 case 'P': /* pointer (T*) */
811 mangled++;
0e3712f6 812 if (!dlang_call_convention_p (mangled))
0f4b8b31 813 {
3f30a274 814 mangled = dlang_type (decl, mangled, info);
0e3712f6 815 string_append (decl, "*");
0f4b8b31
IB
816 return mangled;
817 }
0e3712f6
IB
818 /* Fall through */
819 case 'F': /* function T (D) */
820 case 'U': /* function T (C) */
821 case 'W': /* function T (Windows) */
822 case 'V': /* function T (Pascal) */
823 case 'R': /* function T (C++) */
824 case 'Y': /* function T (Objective-C) */
825 /* Function pointer types don't include the trailing asterisk. */
3f30a274 826 mangled = dlang_function_type (decl, mangled, info);
0e3712f6 827 string_append (decl, "function");
43b1b9ed
IB
828 return mangled;
829 case 'I': /* ident T */
830 case 'C': /* class T */
831 case 'S': /* struct T */
832 case 'E': /* enum T */
833 case 'T': /* typedef T */
834 mangled++;
3f30a274 835 return dlang_parse_qualified (decl, mangled, info, 0);
43b1b9ed 836 case 'D': /* delegate T */
fa66ced4
IB
837 {
838 string mods;
839 size_t szmods;
43b1b9ed 840 mangled++;
fa66ced4
IB
841
842 string_init (&mods);
843 mangled = dlang_type_modifiers (&mods, mangled);
844 szmods = string_length (&mods);
845
3f30a274
IB
846 /* Back referenced function type. */
847 if (*mangled == 'Q')
848 mangled = dlang_type_backref (decl, mangled, info, 1);
849 else
850 mangled = dlang_function_type (decl, mangled, info);
851
43b1b9ed 852 string_append (decl, "delegate");
fa66ced4
IB
853 string_appendn (decl, mods.b, szmods);
854
855 string_delete (&mods);
43b1b9ed 856 return mangled;
fa66ced4 857 }
43b1b9ed
IB
858 case 'B': /* tuple T */
859 mangled++;
3f30a274 860 return dlang_parse_tuple (decl, mangled, info);
43b1b9ed 861
43b1b9ed
IB
862 /* Basic types */
863 case 'n':
864 mangled++;
865 string_append (decl, "none");
866 return mangled;
867 case 'v':
868 mangled++;
869 string_append (decl, "void");
870 return mangled;
871 case 'g':
872 mangled++;
873 string_append (decl, "byte");
874 return mangled;
875 case 'h':
876 mangled++;
877 string_append (decl, "ubyte");
878 return mangled;
879 case 's':
880 mangled++;
881 string_append (decl, "short");
882 return mangled;
883 case 't':
884 mangled++;
885 string_append (decl, "ushort");
886 return mangled;
887 case 'i':
888 mangled++;
889 string_append (decl, "int");
890 return mangled;
891 case 'k':
892 mangled++;
893 string_append (decl, "uint");
894 return mangled;
895 case 'l':
896 mangled++;
897 string_append (decl, "long");
898 return mangled;
899 case 'm':
900 mangled++;
901 string_append (decl, "ulong");
902 return mangled;
903 case 'f':
904 mangled++;
905 string_append (decl, "float");
906 return mangled;
907 case 'd':
908 mangled++;
909 string_append (decl, "double");
910 return mangled;
911 case 'e':
912 mangled++;
913 string_append (decl, "real");
914 return mangled;
915
916 /* Imaginary and Complex types */
917 case 'o':
918 mangled++;
919 string_append (decl, "ifloat");
920 return mangled;
921 case 'p':
922 mangled++;
923 string_append (decl, "idouble");
924 return mangled;
925 case 'j':
926 mangled++;
927 string_append (decl, "ireal");
928 return mangled;
929 case 'q':
930 mangled++;
931 string_append (decl, "cfloat");
932 return mangled;
933 case 'r':
934 mangled++;
935 string_append (decl, "cdouble");
936 return mangled;
937 case 'c':
938 mangled++;
939 string_append (decl, "creal");
940 return mangled;
941
942 /* Other types */
943 case 'b':
944 mangled++;
945 string_append (decl, "bool");
946 return mangled;
947 case 'a':
948 mangled++;
949 string_append (decl, "char");
950 return mangled;
951 case 'u':
952 mangled++;
953 string_append (decl, "wchar");
954 return mangled;
955 case 'w':
956 mangled++;
957 string_append (decl, "dchar");
958 return mangled;
59251a73
IB
959 case 'z':
960 mangled++;
961 switch (*mangled)
962 {
963 case 'i':
964 mangled++;
965 string_append (decl, "cent");
966 return mangled;
967 case 'k':
968 mangled++;
969 string_append (decl, "ucent");
970 return mangled;
971 }
972 return NULL;
43b1b9ed 973
3f30a274
IB
974 /* Back referenced type. */
975 case 'Q':
976 return dlang_type_backref (decl, mangled, info, 0);
977
43b1b9ed
IB
978 default: /* unhandled */
979 return NULL;
980 }
981}
982
983/* Extract the identifier from MANGLED and append it to DECL.
984 Return the remaining string on success or NULL on failure. */
985static const char *
3f30a274 986dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 987{
7e865541
IB
988 long len;
989
3f30a274 990 if (mangled == NULL || *mangled == '\0')
7e865541
IB
991 return NULL;
992
3f30a274
IB
993 if (*mangled == 'Q')
994 return dlang_symbol_backref (decl, mangled, info);
43b1b9ed 995
3f30a274
IB
996 /* May be a template instance without a length prefix. */
997 if (mangled[0] == '_' && mangled[1] == '_'
998 && (mangled[2] == 'T' || mangled[2] == 'U'))
999 return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
7e865541 1000
3f30a274 1001 const char *endptr = dlang_number (mangled, &len);
7e865541 1002
3f30a274
IB
1003 if (endptr == NULL || len == 0)
1004 return NULL;
7e865541 1005
3f30a274
IB
1006 if (strlen (endptr) < (size_t) len)
1007 return NULL;
7e865541 1008
3f30a274 1009 mangled = endptr;
43b1b9ed 1010
3f30a274
IB
1011 /* May be a template instance with a length prefix. */
1012 if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1013 && (mangled[2] == 'T' || mangled[2] == 'U'))
1014 return dlang_parse_template (decl, mangled, info, len);
43b1b9ed 1015
3f30a274
IB
1016 return dlang_lname (decl, mangled, len);
1017}
43b1b9ed 1018
3f30a274
IB
1019/* Extract the plain identifier from MANGLED and prepend/append it to DECL
1020 with special treatment for some magic compiler generted symbols.
1021 Return the remaining string on success or NULL on failure. */
1022static const char *
1023dlang_lname (string *decl, const char *mangled, long len)
1024{
1025 switch (len)
1026 {
1027 case 6:
1028 if (strncmp (mangled, "__ctor", len) == 0)
43b1b9ed 1029 {
3f30a274
IB
1030 /* Constructor symbol for a class/struct. */
1031 string_append (decl, "this");
1032 mangled += len;
1033 return mangled;
1034 }
1035 else if (strncmp (mangled, "__dtor", len) == 0)
1036 {
1037 /* Destructor symbol for a class/struct. */
1038 string_append (decl, "~this");
1039 mangled += len;
1040 return mangled;
1041 }
1042 else if (strncmp (mangled, "__initZ", len + 1) == 0)
1043 {
1044 /* The static initialiser for a given symbol. */
1045 string_prepend (decl, "initializer for ");
1046 string_setlength (decl, string_length (decl) - 1);
1047 mangled += len;
1048 return mangled;
1049 }
1050 else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1051 {
1052 /* The vtable symbol for a given class. */
1053 string_prepend (decl, "vtable for ");
1054 string_setlength (decl, string_length (decl) - 1);
1055 mangled += len;
1056 return mangled;
1057 }
1058 break;
5cc158e9 1059
3f30a274
IB
1060 case 7:
1061 if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1062 {
1063 /* The classinfo symbol for a given class. */
1064 string_prepend (decl, "ClassInfo for ");
1065 string_setlength (decl, string_length (decl) - 1);
1066 mangled += len;
1067 return mangled;
1068 }
1069 break;
5cc158e9 1070
3f30a274
IB
1071 case 10:
1072 if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1073 {
1074 /* Postblit symbol for a struct. */
1075 string_append (decl, "this(this)");
1076 mangled += len + 3;
1077 return mangled;
1078 }
1079 break;
5cc158e9 1080
3f30a274
IB
1081 case 11:
1082 if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1083 {
1084 /* The interface symbol for a given class. */
1085 string_prepend (decl, "Interface for ");
1086 string_setlength (decl, string_length (decl) - 1);
1087 mangled += len;
1088 return mangled;
43b1b9ed 1089 }
3f30a274 1090 break;
43b1b9ed 1091
3f30a274
IB
1092 case 12:
1093 if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1094 {
1095 /* The ModuleInfo symbol for a given module. */
1096 string_prepend (decl, "ModuleInfo for ");
1097 string_setlength (decl, string_length (decl) - 1);
1098 mangled += len;
1099 return mangled;
1100 }
1101 break;
43b1b9ed 1102 }
43b1b9ed 1103
3f30a274
IB
1104 string_appendn (decl, mangled, len);
1105 mangled += len;
1106
43b1b9ed
IB
1107 return mangled;
1108}
1109
1110/* Extract the integer value from MANGLED and append it to DECL,
1111 where TYPE is the type it should be represented as.
1112 Return the remaining string on success or NULL on failure. */
1113static const char *
1114dlang_parse_integer (string *decl, const char *mangled, char type)
1115{
1116 if (type == 'a' || type == 'u' || type == 'w')
1117 {
1118 /* Parse character value. */
81adfd10
B
1119 char value[20];
1120 int pos = sizeof(value);
43b1b9ed 1121 int width = 0;
dbe65f77 1122 long val;
43b1b9ed 1123
dbe65f77
IB
1124 mangled = dlang_number (mangled, &val);
1125 if (mangled == NULL)
43b1b9ed
IB
1126 return NULL;
1127
1128 string_append (decl, "'");
1129
1130 if (type == 'a' && val >= 0x20 && val < 0x7F)
1131 {
1132 /* Represent as a character literal. */
1133 char c = (char) val;
1134 string_appendn (decl, &c, 1);
1135 }
1136 else
1137 {
1138 /* Represent as a hexadecimal value. */
1139 switch (type)
1140 {
1141 case 'a': /* char */
1142 string_append (decl, "\\x");
1143 width = 2;
1144 break;
1145 case 'u': /* wchar */
1146 string_append (decl, "\\u");
1147 width = 4;
1148 break;
1149 case 'w': /* dchar */
1150 string_append (decl, "\\U");
1151 width = 8;
1152 break;
1153 }
1154
1155 while (val > 0)
1156 {
1157 int digit = val % 16;
1158
1159 if (digit < 10)
1160 value[--pos] = (char)(digit + '0');
1161 else
1162 value[--pos] = (char)((digit - 10) + 'a');
1163
1164 val /= 16;
1165 width--;
1166 }
1167
1168 for (; width > 0; width--)
1169 value[--pos] = '0';
1170
81adfd10 1171 string_appendn (decl, &(value[pos]), sizeof(value) - pos);
43b1b9ed
IB
1172 }
1173 string_append (decl, "'");
43b1b9ed
IB
1174 }
1175 else if (type == 'b')
1176 {
1177 /* Parse boolean value. */
dbe65f77 1178 long val;
43b1b9ed 1179
dbe65f77
IB
1180 mangled = dlang_number (mangled, &val);
1181 if (mangled == NULL)
43b1b9ed
IB
1182 return NULL;
1183
1184 string_append (decl, val ? "true" : "false");
43b1b9ed
IB
1185 }
1186 else
1187 {
1188 /* Parse integer value. */
1189 const char *numptr = mangled;
1190 size_t num = 0;
1191
dbe65f77
IB
1192 if (! ISDIGIT (*mangled))
1193 return NULL;
1194
43b1b9ed
IB
1195 while (ISDIGIT (*mangled))
1196 {
1197 num++;
1198 mangled++;
1199 }
1200 string_appendn (decl, numptr, num);
1201
1202 /* Append suffix. */
1203 switch (type)
1204 {
1205 case 'h': /* ubyte */
1206 case 't': /* ushort */
1207 case 'k': /* uint */
1208 string_append (decl, "u");
1209 break;
1210 case 'l': /* long */
1211 string_append (decl, "L");
1212 break;
1213 case 'm': /* ulong */
1214 string_append (decl, "uL");
1215 break;
1216 }
1217 }
1218
1219 return mangled;
1220}
1221
1222/* Extract the floating-point value from MANGLED and append it to DECL.
1223 Return the remaining string on success or NULL on failure. */
1224static const char *
1225dlang_parse_real (string *decl, const char *mangled)
1226{
43b1b9ed
IB
1227 /* Handle NAN and +-INF. */
1228 if (strncmp (mangled, "NAN", 3) == 0)
1229 {
1230 string_append (decl, "NaN");
1231 mangled += 3;
1232 return mangled;
1233 }
1234 else if (strncmp (mangled, "INF", 3) == 0)
1235 {
1236 string_append (decl, "Inf");
1237 mangled += 3;
1238 return mangled;
1239 }
1240 else if (strncmp (mangled, "NINF", 4) == 0)
1241 {
1242 string_append (decl, "-Inf");
1243 mangled += 4;
1244 return mangled;
1245 }
1246
1247 /* Hexadecimal prefix and leading bit. */
1248 if (*mangled == 'N')
1249 {
1a122a71 1250 string_append (decl, "-");
43b1b9ed
IB
1251 mangled++;
1252 }
1253
1254 if (!ISXDIGIT (*mangled))
1255 return NULL;
1256
1a122a71
IB
1257 string_append (decl, "0x");
1258 string_appendn (decl, mangled, 1);
1259 string_append (decl, ".");
43b1b9ed
IB
1260 mangled++;
1261
1262 /* Significand. */
1263 while (ISXDIGIT (*mangled))
1264 {
1a122a71 1265 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1266 mangled++;
1267 }
1268
1269 /* Exponent. */
1270 if (*mangled != 'P')
1271 return NULL;
1272
1a122a71 1273 string_append (decl, "p");
43b1b9ed
IB
1274 mangled++;
1275
1276 if (*mangled == 'N')
1277 {
1a122a71 1278 string_append (decl, "-");
43b1b9ed
IB
1279 mangled++;
1280 }
1281
1282 while (ISDIGIT (*mangled))
1283 {
1a122a71 1284 string_appendn (decl, mangled, 1);
43b1b9ed
IB
1285 mangled++;
1286 }
1287
43b1b9ed
IB
1288 return mangled;
1289}
1290
43b1b9ed
IB
1291/* Extract the string value from MANGLED and append it to DECL.
1292 Return the remaining string on success or NULL on failure. */
1293static const char *
1294dlang_parse_string (string *decl, const char *mangled)
1295{
1296 char type = *mangled;
43b1b9ed
IB
1297 long len;
1298
1299 mangled++;
dbe65f77
IB
1300 mangled = dlang_number (mangled, &len);
1301 if (mangled == NULL || *mangled != '_')
43b1b9ed
IB
1302 return NULL;
1303
1304 mangled++;
1305 string_append (decl, "\"");
1306 while (len--)
1307 {
5398cab9
IB
1308 char val;
1309 const char *endptr = dlang_hexdigit (mangled, &val);
1310
1311 if (endptr == NULL)
1312 return NULL;
1313
1314 /* Sanitize white and non-printable characters. */
1315 switch (val)
43b1b9ed 1316 {
5398cab9
IB
1317 case ' ':
1318 string_append (decl, " ");
1319 break;
1320 case '\t':
1321 string_append (decl, "\\t");
1322 break;
1323 case '\n':
1324 string_append (decl, "\\n");
1325 break;
1326 case '\r':
1327 string_append (decl, "\\r");
1328 break;
1329 case '\f':
1330 string_append (decl, "\\f");
1331 break;
1332 case '\v':
1333 string_append (decl, "\\v");
1334 break;
eb058b7d 1335
5398cab9
IB
1336 default:
1337 if (ISPRINT (val))
1338 string_appendn (decl, &val, 1);
1339 else
eb058b7d 1340 {
5398cab9
IB
1341 string_append (decl, "\\x");
1342 string_appendn (decl, mangled, 2);
eb058b7d 1343 }
43b1b9ed 1344 }
43b1b9ed 1345
5398cab9 1346 mangled = endptr;
43b1b9ed
IB
1347 }
1348 string_append (decl, "\"");
1349
1350 if (type != 'a')
1351 string_appendn (decl, &type, 1);
1352
1353 return mangled;
1354}
1355
1356/* Extract the static array value from MANGLED and append it to DECL.
1357 Return the remaining string on success or NULL on failure. */
1358static const char *
1359dlang_parse_arrayliteral (string *decl, const char *mangled)
1360{
dbe65f77 1361 long elements;
43b1b9ed 1362
dbe65f77
IB
1363 mangled = dlang_number (mangled, &elements);
1364 if (mangled == NULL)
43b1b9ed
IB
1365 return NULL;
1366
43b1b9ed
IB
1367 string_append (decl, "[");
1368 while (elements--)
1369 {
1370 mangled = dlang_value (decl, mangled, NULL, '\0');
80b1ab15
B
1371 if (mangled == NULL)
1372 return NULL;
1373
43b1b9ed
IB
1374 if (elements != 0)
1375 string_append (decl, ", ");
1376 }
1377
1378 string_append (decl, "]");
1379 return mangled;
1380}
1381
1382/* Extract the associative array value from MANGLED and append it to DECL.
1383 Return the remaining string on success or NULL on failure. */
1384static const char *
1385dlang_parse_assocarray (string *decl, const char *mangled)
1386{
dbe65f77 1387 long elements;
43b1b9ed 1388
dbe65f77
IB
1389 mangled = dlang_number (mangled, &elements);
1390 if (mangled == NULL)
43b1b9ed
IB
1391 return NULL;
1392
43b1b9ed
IB
1393 string_append (decl, "[");
1394 while (elements--)
1395 {
1396 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1397 if (mangled == NULL)
1398 return NULL;
1399
43b1b9ed
IB
1400 string_append (decl, ":");
1401 mangled = dlang_value (decl, mangled, NULL, '\0');
6c8dbbfe
B
1402 if (mangled == NULL)
1403 return NULL;
43b1b9ed
IB
1404
1405 if (elements != 0)
1406 string_append (decl, ", ");
1407 }
1408
1409 string_append (decl, "]");
1410 return mangled;
1411}
1412
1413/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1414 Return the remaining string on success or NULL on failure. */
1415static const char *
1416dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1417{
dbe65f77 1418 long args;
43b1b9ed 1419
dbe65f77
IB
1420 mangled = dlang_number (mangled, &args);
1421 if (mangled == NULL)
43b1b9ed
IB
1422 return NULL;
1423
43b1b9ed
IB
1424 if (name != NULL)
1425 string_append (decl, name);
1426
1427 string_append (decl, "(");
1428 while (args--)
1429 {
1430 mangled = dlang_value (decl, mangled, NULL, '\0');
dba20a51
B
1431 if (mangled == NULL)
1432 return NULL;
1433
43b1b9ed
IB
1434 if (args != 0)
1435 string_append (decl, ", ");
1436 }
1437
1438 string_append (decl, ")");
1439 return mangled;
1440}
1441
1442/* Extract the value from MANGLED and append it to DECL.
1443 Return the remaining string on success or NULL on failure. */
1444static const char *
1445dlang_value (string *decl, const char *mangled, const char *name, char type)
1446{
1447 if (mangled == NULL || *mangled == '\0')
76b41cad 1448 return NULL;
43b1b9ed
IB
1449
1450 switch (*mangled)
1451 {
1452 /* Null value. */
1453 case 'n':
1454 mangled++;
1455 string_append (decl, "null");
1456 break;
1457
1458 /* Integral values. */
1459 case 'N':
1460 mangled++;
1461 string_append (decl, "-");
1462 mangled = dlang_parse_integer (decl, mangled, type);
1463 break;
1464
1465 case 'i':
1466 mangled++;
43b1b9ed 1467 /* Fall through */
dd03444b
IB
1468
1469 /* There really should always be an `i' before encoded numbers, but there
1470 wasn't in early versions of D2, so this case range must remain for
1471 backwards compatibility. */
43b1b9ed
IB
1472 case '0': case '1': case '2': case '3': case '4':
1473 case '5': case '6': case '7': case '8': case '9':
1474 mangled = dlang_parse_integer (decl, mangled, type);
1475 break;
1476
1477 /* Real value. */
1478 case 'e':
1479 mangled++;
1480 mangled = dlang_parse_real (decl, mangled);
1481 break;
1482
1483 /* Complex value. */
1484 case 'c':
1485 mangled++;
1486 mangled = dlang_parse_real (decl, mangled);
1487 string_append (decl, "+");
1488 if (mangled == NULL || *mangled != 'c')
1489 return NULL;
1490 mangled++;
1491 mangled = dlang_parse_real (decl, mangled);
1492 string_append (decl, "i");
1493 break;
1494
1495 /* String values. */
1496 case 'a': /* UTF8 */
1497 case 'w': /* UTF16 */
1498 case 'd': /* UTF32 */
1499 mangled = dlang_parse_string (decl, mangled);
1500 break;
1501
1502 /* Array values. */
1503 case 'A':
1504 mangled++;
1505 if (type == 'H')
1506 mangled = dlang_parse_assocarray (decl, mangled);
1507 else
1508 mangled = dlang_parse_arrayliteral (decl, mangled);
1509 break;
1510
1511 /* Struct values. */
1512 case 'S':
1513 mangled++;
1514 mangled = dlang_parse_structlit (decl, mangled, name);
1515 break;
1516
1517 default:
1518 return NULL;
1519 }
1520
1521 return mangled;
1522}
1523
43b1b9ed
IB
1524/* Extract and demangle the symbol in MANGLED and append it to DECL.
1525 Returns the remaining signature on success or NULL on failure. */
1526static const char *
3f30a274 1527dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1528{
5a4dbf7d
IB
1529 /* A D mangled symbol is comprised of both scope and type information.
1530
1531 MangleName:
1532 _D QualifiedName Type
5a4dbf7d
IB
1533 _D QualifiedName Z
1534 ^
1535 The caller should have guaranteed that the start pointer is at the
1536 above location.
3f30a274
IB
1537 Note that type is never a function type, but only the return type of
1538 a function or the type of a variable.
5a4dbf7d
IB
1539 */
1540 mangled += 2;
1541
3f30a274 1542 mangled = dlang_parse_qualified (decl, mangled, info, 1);
5a4dbf7d
IB
1543
1544 if (mangled != NULL)
1545 {
1546 /* Artificial symbols end with 'Z' and have no type. */
1547 if (*mangled == 'Z')
1548 mangled++;
1549 else
1550 {
3f30a274
IB
1551 /* Discard the declaration or return type. */
1552 string type;
5a4dbf7d 1553
3f30a274
IB
1554 string_init (&type);
1555 mangled = dlang_type (&type, mangled, info);
1556 string_delete (&type);
5a4dbf7d
IB
1557 }
1558 }
1559
5a4dbf7d
IB
1560 return mangled;
1561}
1562
1563/* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
3f30a274 1564 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
5a4dbf7d
IB
1565 Returns the remaining signature on success or NULL on failure. */
1566static const char *
1567dlang_parse_qualified (string *decl, const char *mangled,
3f30a274 1568 struct dlang_info *info, int suffix_modifiers)
5a4dbf7d
IB
1569{
1570 /* Qualified names are identifiers separated by their encoded length.
1571 Nested functions also encode their argument types without specifying
1572 what they return.
1573
1574 QualifiedName:
3f30a274
IB
1575 SymbolFunctionName
1576 SymbolFunctionName QualifiedName
5a4dbf7d 1577 ^
3f30a274
IB
1578
1579 SymbolFunctionName:
1580 SymbolName
1581 SymbolName TypeFunctionNoReturn
1582 SymbolName M TypeFunctionNoReturn
1583 SymbolName M TypeModifiers TypeFunctionNoReturn
1584
5a4dbf7d
IB
1585 The start pointer should be at the above location.
1586 */
43b1b9ed
IB
1587 size_t n = 0;
1588 do
1589 {
1590 if (n++)
1591 string_append (decl, ".");
1592
98bb7ee2
IB
1593 /* Skip over anonymous symbols. */
1594 while (*mangled == '0')
1595 mangled++;
1596
3f30a274 1597 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed 1598
5a4dbf7d 1599 /* Consume the encoded arguments. However if this is not followed by the
3f30a274
IB
1600 next encoded length or mangle type, then this is not a continuation of
1601 a qualified name, in which case we backtrack and return the current
1602 unconsumed position of the mangled decl. */
5a4dbf7d 1603 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
43b1b9ed 1604 {
3f30a274 1605 string mods;
5a4dbf7d
IB
1606 const char *start = mangled;
1607 int saved = string_length (decl);
43b1b9ed 1608
3f30a274
IB
1609 /* Save the type modifiers for appending at the end if needed. */
1610 string_init (&mods);
1611
5a4dbf7d 1612 /* Skip over 'this' parameter and type modifiers. */
43b1b9ed 1613 if (*mangled == 'M')
7e865541 1614 {
5a4dbf7d 1615 mangled++;
3f30a274 1616 mangled = dlang_type_modifiers (&mods, mangled);
5a4dbf7d 1617 string_setlength (decl, saved);
7e865541
IB
1618 }
1619
3f30a274
IB
1620 mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1621 mangled, info);
1622 if (suffix_modifiers)
1623 string_appendn (decl, mods.b, string_length (&mods));
43b1b9ed 1624
3f30a274 1625 if (mangled == NULL || *mangled == '\0')
7e865541 1626 {
5a4dbf7d 1627 /* Did not match the rule we were looking for. */
7e865541 1628 mangled = start;
5a4dbf7d 1629 string_setlength (decl, saved);
7e865541 1630 }
3f30a274
IB
1631
1632 string_delete (&mods);
43b1b9ed
IB
1633 }
1634 }
3f30a274 1635 while (mangled && dlang_symbol_name_p (mangled, info));
43b1b9ed
IB
1636
1637 return mangled;
1638}
1639
1640/* Demangle the tuple from MANGLED and append it to DECL.
1641 Return the remaining string on success or NULL on failure. */
1642static const char *
3f30a274 1643dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed 1644{
dbe65f77 1645 long elements;
43b1b9ed 1646
dbe65f77
IB
1647 mangled = dlang_number (mangled, &elements);
1648 if (mangled == NULL)
43b1b9ed
IB
1649 return NULL;
1650
43b1b9ed
IB
1651 string_append (decl, "Tuple!(");
1652
1653 while (elements--)
1654 {
3f30a274 1655 mangled = dlang_type (decl, mangled, info);
f181b8e7
B
1656 if (mangled == NULL)
1657 return NULL;
1658
43b1b9ed
IB
1659 if (elements != 0)
1660 string_append (decl, ", ");
1661 }
1662
1663 string_append (decl, ")");
1664 return mangled;
1665}
1666
3f30a274
IB
1667/* Demangle the template symbol parameter from MANGLED and append it to DECL.
1668 Return the remaining string on success or NULL on failure. */
1669static const char *
1670dlang_template_symbol_param (string *decl, const char *mangled,
1671 struct dlang_info *info)
1672{
1673 if (strncmp (mangled, "_D", 2) == 0
1674 && dlang_symbol_name_p (mangled + 2, info))
1675 return dlang_parse_mangle (decl, mangled, info);
1676
1677 if (*mangled == 'Q')
1678 return dlang_parse_qualified (decl, mangled, info, 0);
1679
1680 long len;
1681 const char *endptr = dlang_number (mangled, &len);
1682
1683 if (endptr == NULL || len == 0)
1684 return NULL;
1685
1686 /* In template parameter symbols generated by the frontend up to 2.076,
1687 the symbol length is encoded and the first character of the mangled
1688 name can be a digit. This causes ambiguity issues because the digits
1689 of the two numbers are adjacent. */
1690 long psize = len;
1691 const char *pend;
1692 int saved = string_length (decl);
1693
1694 /* Work backwards until a match is found. */
1695 for (pend = endptr; endptr != NULL; pend--)
1696 {
1697 mangled = pend;
1698
1699 /* Reached the beginning of the pointer to the name length,
1700 try parsing the entire symbol. */
1701 if (psize == 0)
1702 {
1703 psize = len;
1704 pend = endptr;
1705 endptr = NULL;
1706 }
1707
1708 /* Check whether template parameter is a function with a valid
1709 return type or an untyped identifier. */
1710 if (dlang_symbol_name_p (mangled, info))
1711 mangled = dlang_parse_qualified (decl, mangled, info, 0);
1712 else if (strncmp (mangled, "_D", 2) == 0
1713 && dlang_symbol_name_p (mangled + 2, info))
1714 mangled = dlang_parse_mangle (decl, mangled, info);
1715
1716 /* Check for name length mismatch. */
1717 if (mangled && (endptr == NULL || (mangled - pend) == psize))
1718 return mangled;
1719
1720 psize /= 10;
1721 string_setlength (decl, saved);
1722 }
1723
1724 /* No match on any combinations. */
1725 return NULL;
1726}
1727
43b1b9ed
IB
1728/* Demangle the argument list from MANGLED and append it to DECL.
1729 Return the remaining string on success or NULL on failure. */
1730static const char *
3f30a274 1731dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
43b1b9ed
IB
1732{
1733 size_t n = 0;
1734
1735 while (mangled && *mangled != '\0')
1736 {
1737 switch (*mangled)
1738 {
1739 case 'Z': /* End of parameter list. */
1740 mangled++;
1741 return mangled;
1742 }
1743
1744 if (n++)
1745 string_append (decl, ", ");
1746
ed4cdb85
IB
1747 /* Skip over specialised template prefix. */
1748 if (*mangled == 'H')
1749 mangled++;
1750
43b1b9ed
IB
1751 switch (*mangled)
1752 {
1753 case 'S': /* Symbol parameter. */
1754 mangled++;
3f30a274 1755 mangled = dlang_template_symbol_param (decl, mangled, info);
43b1b9ed
IB
1756 break;
1757 case 'T': /* Type parameter. */
1758 mangled++;
3f30a274 1759 mangled = dlang_type (decl, mangled, info);
43b1b9ed
IB
1760 break;
1761 case 'V': /* Value parameter. */
1762 {
1763 string name;
1764 char type;
1765
1766 /* Peek at the type. */
1767 mangled++;
1768 type = *mangled;
1769
3f30a274
IB
1770 if (type == 'Q')
1771 {
1772 /* Value type is a back reference, peek at the real type. */
1773 const char *backref;
1774 if (dlang_backref (mangled, &backref, info) == NULL)
1775 return NULL;
1776
1777 type = *backref;
1778 }
1779
43b1b9ed
IB
1780 /* In the few instances where the type is actually desired in
1781 the output, it should precede the value from dlang_value. */
1782 string_init (&name);
3f30a274 1783 mangled = dlang_type (&name, mangled, info);
43b1b9ed
IB
1784 string_need (&name, 1);
1785 *(name.p) = '\0';
1786
1787 mangled = dlang_value (decl, mangled, name.b, type);
1788 string_delete (&name);
1789 break;
1790 }
3f30a274
IB
1791 case 'X': /* Externally mangled parameter. */
1792 {
1793 long len;
1794 const char *endptr;
43b1b9ed 1795
3f30a274
IB
1796 mangled++;
1797 endptr = dlang_number (mangled, &len);
1798 if (endptr == NULL || strlen (endptr) < (size_t) len)
1799 return NULL;
1800
1801 string_appendn (decl, endptr, len);
1802 mangled = endptr + len;
1803 break;
1804 }
43b1b9ed
IB
1805 default:
1806 return NULL;
1807 }
1808 }
1809
1810 return mangled;
1811}
1812
1813/* Extract and demangle the template symbol in MANGLED, expected to
3f30a274 1814 be made up of LEN characters (-1 if unknown), and append it to DECL.
43b1b9ed
IB
1815 Returns the remaining signature on success or NULL on failure. */
1816static const char *
3f30a274
IB
1817dlang_parse_template (string *decl, const char *mangled,
1818 struct dlang_info *info, long len)
43b1b9ed
IB
1819{
1820 const char *start = mangled;
3f30a274 1821 string args;
43b1b9ed
IB
1822
1823 /* Template instance names have the types and values of its parameters
1824 encoded into it.
1825
1826 TemplateInstanceName:
1827 Number __T LName TemplateArgs Z
c6f44bae 1828 Number __U LName TemplateArgs Z
43b1b9ed
IB
1829 ^
1830 The start pointer should be at the above location, and LEN should be
1831 the value of the decoded number.
1832 */
c6f44bae
IB
1833
1834 /* Template symbol. */
3f30a274 1835 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
43b1b9ed
IB
1836 return NULL;
1837
1838 mangled += 3;
1839
1840 /* Template identifier. */
3f30a274 1841 mangled = dlang_identifier (decl, mangled, info);
43b1b9ed
IB
1842
1843 /* Template arguments. */
3f30a274
IB
1844 string_init (&args);
1845 mangled = dlang_template_args (&args, mangled, info);
1846
43b1b9ed 1847 string_append (decl, "!(");
3f30a274 1848 string_appendn (decl, args.b, string_length (&args));
43b1b9ed
IB
1849 string_append (decl, ")");
1850
3f30a274
IB
1851 string_delete (&args);
1852
43b1b9ed 1853 /* Check for template name length mismatch. */
3f30a274 1854 if (len != TEMPLATE_LENGTH_UNKNOWN && mangled && (mangled - start) != len)
43b1b9ed
IB
1855 return NULL;
1856
1857 return mangled;
1858}
1859
3f30a274
IB
1860/* Initialize the information structure we use to pass around information. */
1861static void
1862dlang_demangle_init_info (const char *mangled, int last_backref,
1863 struct dlang_info *info)
1864{
1865 info->s = mangled;
1866 info->last_backref = last_backref;
1867}
1868
43b1b9ed
IB
1869/* Extract and demangle the symbol in MANGLED. Returns the demangled
1870 signature on success or NULL on failure. */
1871
1872char *
1873dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1874{
1875 string decl;
1876 char *demangled = NULL;
1877
1878 if (mangled == NULL || *mangled == '\0')
1879 return NULL;
1880
1881 if (strncmp (mangled, "_D", 2) != 0)
1882 return NULL;
1883
1884 string_init (&decl);
1885
1886 if (strcmp (mangled, "_Dmain") == 0)
1887 {
1888 string_append (&decl, "D main");
1889 }
1890 else
1891 {
3f30a274
IB
1892 struct dlang_info info;
1893
1894 dlang_demangle_init_info (mangled, strlen (mangled), &info);
1895 mangled = dlang_parse_mangle (&decl, mangled, &info);
1896
1897 /* Check that the entire symbol was successfully demangled. */
1898 if (mangled == NULL || *mangled != '\0')
43b1b9ed
IB
1899 string_delete (&decl);
1900 }
1901
1902 if (string_length (&decl) > 0)
1903 {
1904 string_need (&decl, 1);
1905 *(decl.p) = '\0';
1906 demangled = decl.b;
1907 }
1908
1909 return demangled;
1910}
1911