1 /* Demangler for the D programming language 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. 3 Written by Iain Buclaw (ibuclaw@gdcproject.org) 4 5 This file is part of the libiberty library. 6 Libiberty is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Library General Public 8 License as published by the Free Software Foundation; either 9 version 2 of the License, or (at your option) any later version. 10 11 In addition to the permissions in the GNU Library General Public 12 License, the Free Software Foundation gives you unlimited permission 13 to link the compiled version of this file into combinations with other 14 programs, and to distribute those combinations without any restriction 15 coming from the use of this file. (The Library Public License 16 restrictions do apply in other respects; for example, they cover 17 modification of the file, and distribution when not linked into a 18 combined executable.) 19 20 Libiberty is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 Library General Public License for more details. 24 25 You should have received a copy of the GNU Library General Public 26 License along with libiberty; see the file COPYING.LIB. 27 If not, see <http://www.gnu.org/licenses/>. */ 28 29 /* This file exports one function; dlang_demangle. */ 30 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif 34 #ifdef HAVE_LIMITS_H 35 #include <limits.h> 36 #endif 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> 46 #endif 47 48 #include <demangle.h> 49 #include "libiberty.h" 50 51 #ifndef ULONG_MAX 52 #define ULONG_MAX (~0UL) 53 #endif 54 #ifndef UINT_MAX 55 #define UINT_MAX (~0U) 56 #endif 57 58 /* A mini string-handling package */ 59 60 typedef 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 67 static void 68 string_need (string *s, size_t n) 69 { 70 size_t tem; 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 } 81 else if ((size_t) (s->e - s->p) < n) 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 92 static void 93 string_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 102 static void 103 string_init (string *s) 104 { 105 s->b = s->p = s->e = NULL; 106 } 107 108 static int 109 string_length (string *s) 110 { 111 if (s->p == s->b) 112 { 113 return 0; 114 } 115 return s->p - s->b; 116 } 117 118 static void 119 string_setlength (string *s, int n) 120 { 121 if (n - string_length (s) < 0) 122 { 123 s->p = s->b + n; 124 } 125 } 126 127 static void 128 string_append (string *p, const char *s) 129 { 130 size_t n = strlen (s); 131 string_need (p, n); 132 memcpy (p->p, s, n); 133 p->p += n; 134 } 135 136 static void 137 string_appendn (string *p, const char *s, size_t n) 138 { 139 if (n != 0) 140 { 141 string_need (p, n); 142 memcpy (p->p, s, n); 143 p->p += n; 144 } 145 } 146 147 static void 148 string_prependn (string *p, const char *s, size_t n) 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 164 static void 165 string_prepend (string *p, const char *s) 166 { 167 if (s != NULL && *s != '\0') 168 { 169 string_prependn (p, s, strlen (s)); 170 } 171 } 172 173 /* Demangle information structure we pass around. */ 174 struct dlang_info 175 { 176 /* The string we are demangling. */ 177 const char *s; 178 /* The index of the last back reference. */ 179 int last_backref; 180 }; 181 182 /* Pass as the LEN to dlang_parse_template if symbol length is not known. */ 183 #define TEMPLATE_LENGTH_UNKNOWN (-1UL) 184 185 /* Prototypes for forward referenced functions */ 186 static const char *dlang_function_type (string *, const char *, 187 struct dlang_info *); 188 189 static const char *dlang_function_args (string *, const char *, 190 struct dlang_info *); 191 192 static const char *dlang_type (string *, const char *, struct dlang_info *); 193 194 static const char *dlang_value (string *, const char *, const char *, char); 195 196 static const char *dlang_parse_qualified (string *, const char *, 197 struct dlang_info *, int); 198 199 static const char *dlang_parse_mangle (string *, const char *, 200 struct dlang_info *); 201 202 static const char *dlang_parse_tuple (string *, const char *, 203 struct dlang_info *); 204 205 static const char *dlang_parse_template (string *, const char *, 206 struct dlang_info *, unsigned long); 207 208 static const char *dlang_lname (string *, const char *, unsigned long); 209 210 211 /* Extract the number from MANGLED, and assign the result to RET. 212 Return the remaining string on success or NULL on failure. 213 A result larger than UINT_MAX is considered a failure. */ 214 static const char * 215 dlang_number (const char *mangled, unsigned long *ret) 216 { 217 /* Return NULL if trying to extract something that isn't a digit. */ 218 if (mangled == NULL || !ISDIGIT (*mangled)) 219 return NULL; 220 221 unsigned long val = 0; 222 223 while (ISDIGIT (*mangled)) 224 { 225 unsigned long digit = mangled[0] - '0'; 226 227 /* Check for overflow. */ 228 if (val > (UINT_MAX - digit) / 10) 229 return NULL; 230 231 val = val * 10 + digit; 232 mangled++; 233 } 234 235 if (*mangled == '\0') 236 return NULL; 237 238 *ret = val; 239 return mangled; 240 } 241 242 /* Extract the hex-digit from MANGLED, and assign the result to RET. 243 Return the remaining string on success or NULL on failure. */ 244 static const char * 245 dlang_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 270 /* Extract the function calling convention from MANGLED and 271 return 1 on success or 0 on failure. */ 272 static int 273 dlang_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 286 /* Extract the back reference position from MANGLED, and assign the result 287 to RET. Return the remaining string on success or NULL on failure. 288 A result <= 0 is a failure. */ 289 static const char * 290 dlang_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 */ 309 unsigned long val = 0; 310 311 while (ISALPHA (*mangled)) 312 { 313 /* Check for overflow. */ 314 if (val > (ULONG_MAX - 25) / 26) 315 break; 316 317 val *= 26; 318 319 if (mangled[0] >= 'a' && mangled[0] <= 'z') 320 { 321 val += mangled[0] - 'a'; 322 if ((long) val <= 0) 323 break; 324 *ret = val; 325 return mangled + 1; 326 } 327 328 val += mangled[0] - 'A'; 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. */ 337 static const char * 338 dlang_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 354 if (refpos > qpos - info->s) 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. */ 365 static const char * 366 dlang_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; 376 unsigned long len; 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. */ 396 static const char * 397 dlang_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. */ 435 static int 436 dlang_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); 452 if (mangled == NULL || ret > qref - info->s) 453 return 0; 454 455 return ISDIGIT (qref[-ret]); 456 } 457 458 /* Demangle the calling convention from MANGLED and append it to DECL. 459 Return the remaining string on success or NULL on failure. */ 460 static const char * 461 dlang_call_convention (string *decl, const char *mangled) 462 { 463 if (mangled == NULL || *mangled == '\0') 464 return NULL; 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; 487 case 'Y': /* (Objective-C) */ 488 mangled++; 489 string_append (decl, "extern(Objective-C) "); 490 break; 491 default: 492 return NULL; 493 } 494 495 return mangled; 496 } 497 498 /* Extract the type modifiers from MANGLED and append them to DECL. 499 Returns the remaining signature on success or NULL on failure. */ 500 static const char * 501 dlang_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 536 /* Demangle the D function attributes from MANGLED and append it to DECL. 537 Return the remaining string on success or NULL on failure. */ 538 static const char * 539 dlang_attributes (string *decl, const char *mangled) 540 { 541 if (mangled == NULL || *mangled == '\0') 542 return NULL; 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': 575 case 'k': 576 /* inout parameter is represented as 'Ng'. 577 vector parameter is represented as 'Nh'. 578 return paramenter is represented as 'Nk'. 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; 587 case 'j': /* return */ 588 mangled++; 589 string_append (decl, "return "); 590 continue; 591 case 'l': /* scope */ 592 mangled++; 593 string_append (decl, "scope "); 594 continue; 595 case 'm': /* @live */ 596 mangled++; 597 string_append (decl, "@live "); 598 continue; 599 600 default: /* unknown attribute */ 601 return NULL; 602 } 603 break; 604 } 605 606 return mangled; 607 } 608 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. */ 614 static const char * 615 dlang_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 636 /* Demangle the function type from MANGLED and append it to DECL. 637 Return the remaining string on success or NULL on failure. */ 638 static const char * 639 dlang_function_type (string *decl, const char *mangled, struct dlang_info *info) 640 { 641 string attr, args, type; 642 643 if (mangled == NULL || *mangled == '\0') 644 return NULL; 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 656 mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info); 657 658 /* Function return type. */ 659 mangled = dlang_type (&type, mangled, info); 660 661 /* Append to decl in order. */ 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)); 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. */ 675 static const char * 676 dlang_function_args (string *decl, const char *mangled, struct dlang_info *info) 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++; 690 if (n != 0) 691 string_append (decl, ", "); 692 string_append (decl, "..."); 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 708 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */ 709 { 710 mangled += 2; 711 string_append (decl, "return "); 712 } 713 714 switch (*mangled) 715 { 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; 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 } 738 mangled = dlang_type (decl, mangled, info); 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. */ 746 static const char * 747 dlang_type (string *decl, const char *mangled, struct dlang_info *info) 748 { 749 if (mangled == NULL || *mangled == '\0') 750 return NULL; 751 752 switch (*mangled) 753 { 754 case 'O': /* shared(T) */ 755 mangled++; 756 string_append (decl, "shared("); 757 mangled = dlang_type (decl, mangled, info); 758 string_append (decl, ")"); 759 return mangled; 760 case 'x': /* const(T) */ 761 mangled++; 762 string_append (decl, "const("); 763 mangled = dlang_type (decl, mangled, info); 764 string_append (decl, ")"); 765 return mangled; 766 case 'y': /* immutable(T) */ 767 mangled++; 768 string_append (decl, "immutable("); 769 mangled = dlang_type (decl, mangled, info); 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("); 778 mangled = dlang_type (decl, mangled, info); 779 string_append (decl, ")"); 780 return mangled; 781 } 782 else if (*mangled == 'h') /* vector(T) */ 783 { 784 mangled++; 785 string_append (decl, "__vector("); 786 mangled = dlang_type (decl, mangled, info); 787 string_append (decl, ")"); 788 return mangled; 789 } 790 else 791 return NULL; 792 case 'A': /* dynamic array (T[]) */ 793 mangled++; 794 mangled = dlang_type (decl, mangled, info); 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 } 809 mangled = dlang_type (decl, mangled, info); 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); 822 mangled = dlang_type (&type, mangled, info); 823 sztype = string_length (&type); 824 825 mangled = dlang_type (decl, mangled, info); 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++; 835 if (!dlang_call_convention_p (mangled)) 836 { 837 mangled = dlang_type (decl, mangled, info); 838 string_append (decl, "*"); 839 return mangled; 840 } 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. */ 849 mangled = dlang_function_type (decl, mangled, info); 850 string_append (decl, "function"); 851 return mangled; 852 case 'C': /* class T */ 853 case 'S': /* struct T */ 854 case 'E': /* enum T */ 855 case 'T': /* typedef T */ 856 mangled++; 857 return dlang_parse_qualified (decl, mangled, info, 0); 858 case 'D': /* delegate T */ 859 { 860 string mods; 861 size_t szmods; 862 mangled++; 863 864 string_init (&mods); 865 mangled = dlang_type_modifiers (&mods, mangled); 866 szmods = string_length (&mods); 867 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 874 string_append (decl, "delegate"); 875 string_appendn (decl, mods.b, szmods); 876 877 string_delete (&mods); 878 return mangled; 879 } 880 case 'B': /* tuple T */ 881 mangled++; 882 return dlang_parse_tuple (decl, mangled, info); 883 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; 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; 995 996 /* Back referenced type. */ 997 case 'Q': 998 return dlang_type_backref (decl, mangled, info, 0); 999 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. */ 1007 static const char * 1008 dlang_identifier (string *decl, const char *mangled, struct dlang_info *info) 1009 { 1010 unsigned long len; 1011 1012 if (mangled == NULL || *mangled == '\0') 1013 return NULL; 1014 1015 if (*mangled == 'Q') 1016 return dlang_symbol_backref (decl, mangled, info); 1017 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); 1022 1023 const char *endptr = dlang_number (mangled, &len); 1024 1025 if (endptr == NULL || len == 0) 1026 return NULL; 1027 1028 if (strlen (endptr) < len) 1029 return NULL; 1030 1031 mangled = endptr; 1032 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); 1037 1038 return dlang_lname (decl, mangled, len); 1039 } 1040 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. */ 1044 static const char * 1045 dlang_lname (string *decl, const char *mangled, unsigned long len) 1046 { 1047 switch (len) 1048 { 1049 case 6: 1050 if (strncmp (mangled, "__ctor", len) == 0) 1051 { 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; 1081 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; 1092 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; 1102 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; 1111 } 1112 break; 1113 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; 1124 } 1125 1126 string_appendn (decl, mangled, len); 1127 mangled += len; 1128 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. */ 1135 static const char * 1136 dlang_parse_integer (string *decl, const char *mangled, char type) 1137 { 1138 if (type == 'a' || type == 'u' || type == 'w') 1139 { 1140 /* Parse character value. */ 1141 char value[20]; 1142 int pos = sizeof(value); 1143 int width = 0; 1144 unsigned long val; 1145 1146 mangled = dlang_number (mangled, &val); 1147 if (mangled == NULL) 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 1193 string_appendn (decl, &(value[pos]), sizeof(value) - pos); 1194 } 1195 string_append (decl, "'"); 1196 } 1197 else if (type == 'b') 1198 { 1199 /* Parse boolean value. */ 1200 unsigned long val; 1201 1202 mangled = dlang_number (mangled, &val); 1203 if (mangled == NULL) 1204 return NULL; 1205 1206 string_append (decl, val ? "true" : "false"); 1207 } 1208 else 1209 { 1210 /* Parse integer value. */ 1211 const char *numptr = mangled; 1212 size_t num = 0; 1213 1214 if (! ISDIGIT (*mangled)) 1215 return NULL; 1216 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. */ 1246 static const char * 1247 dlang_parse_real (string *decl, const char *mangled) 1248 { 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 { 1272 string_append (decl, "-"); 1273 mangled++; 1274 } 1275 1276 if (!ISXDIGIT (*mangled)) 1277 return NULL; 1278 1279 string_append (decl, "0x"); 1280 string_appendn (decl, mangled, 1); 1281 string_append (decl, "."); 1282 mangled++; 1283 1284 /* Significand. */ 1285 while (ISXDIGIT (*mangled)) 1286 { 1287 string_appendn (decl, mangled, 1); 1288 mangled++; 1289 } 1290 1291 /* Exponent. */ 1292 if (*mangled != 'P') 1293 return NULL; 1294 1295 string_append (decl, "p"); 1296 mangled++; 1297 1298 if (*mangled == 'N') 1299 { 1300 string_append (decl, "-"); 1301 mangled++; 1302 } 1303 1304 while (ISDIGIT (*mangled)) 1305 { 1306 string_appendn (decl, mangled, 1); 1307 mangled++; 1308 } 1309 1310 return mangled; 1311 } 1312 1313 /* Extract the string value from MANGLED and append it to DECL. 1314 Return the remaining string on success or NULL on failure. */ 1315 static const char * 1316 dlang_parse_string (string *decl, const char *mangled) 1317 { 1318 char type = *mangled; 1319 unsigned long len; 1320 1321 mangled++; 1322 mangled = dlang_number (mangled, &len); 1323 if (mangled == NULL || *mangled != '_') 1324 return NULL; 1325 1326 mangled++; 1327 string_append (decl, "\""); 1328 while (len--) 1329 { 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) 1338 { 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; 1357 1358 default: 1359 if (ISPRINT (val)) 1360 string_appendn (decl, &val, 1); 1361 else 1362 { 1363 string_append (decl, "\\x"); 1364 string_appendn (decl, mangled, 2); 1365 } 1366 } 1367 1368 mangled = endptr; 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. */ 1380 static const char * 1381 dlang_parse_arrayliteral (string *decl, const char *mangled) 1382 { 1383 unsigned long elements; 1384 1385 mangled = dlang_number (mangled, &elements); 1386 if (mangled == NULL) 1387 return NULL; 1388 1389 string_append (decl, "["); 1390 while (elements--) 1391 { 1392 mangled = dlang_value (decl, mangled, NULL, '\0'); 1393 if (mangled == NULL) 1394 return NULL; 1395 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. */ 1406 static const char * 1407 dlang_parse_assocarray (string *decl, const char *mangled) 1408 { 1409 unsigned long elements; 1410 1411 mangled = dlang_number (mangled, &elements); 1412 if (mangled == NULL) 1413 return NULL; 1414 1415 string_append (decl, "["); 1416 while (elements--) 1417 { 1418 mangled = dlang_value (decl, mangled, NULL, '\0'); 1419 if (mangled == NULL) 1420 return NULL; 1421 1422 string_append (decl, ":"); 1423 mangled = dlang_value (decl, mangled, NULL, '\0'); 1424 if (mangled == NULL) 1425 return NULL; 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. */ 1437 static const char * 1438 dlang_parse_structlit (string *decl, const char *mangled, const char *name) 1439 { 1440 unsigned long args; 1441 1442 mangled = dlang_number (mangled, &args); 1443 if (mangled == NULL) 1444 return NULL; 1445 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'); 1453 if (mangled == NULL) 1454 return NULL; 1455 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. */ 1466 static const char * 1467 dlang_value (string *decl, const char *mangled, const char *name, char type) 1468 { 1469 if (mangled == NULL || *mangled == '\0') 1470 return NULL; 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++; 1489 /* Fall through */ 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. */ 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 1546 /* Extract and demangle the symbol in MANGLED and append it to DECL. 1547 Returns the remaining signature on success or NULL on failure. */ 1548 static const char * 1549 dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info) 1550 { 1551 /* A D mangled symbol is comprised of both scope and type information. 1552 1553 MangleName: 1554 _D QualifiedName Type 1555 _D QualifiedName Z 1556 ^ 1557 The caller should have guaranteed that the start pointer is at the 1558 above location. 1559 Note that type is never a function type, but only the return type of 1560 a function or the type of a variable. 1561 */ 1562 mangled += 2; 1563 1564 mangled = dlang_parse_qualified (decl, mangled, info, 1); 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 { 1573 /* Discard the declaration or return type. */ 1574 string type; 1575 1576 string_init (&type); 1577 mangled = dlang_type (&type, mangled, info); 1578 string_delete (&type); 1579 } 1580 } 1581 1582 return mangled; 1583 } 1584 1585 /* Extract and demangle the qualified symbol in MANGLED and append it to DECL. 1586 SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol. 1587 Returns the remaining signature on success or NULL on failure. */ 1588 static const char * 1589 dlang_parse_qualified (string *decl, const char *mangled, 1590 struct dlang_info *info, int suffix_modifiers) 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: 1597 SymbolFunctionName 1598 SymbolFunctionName QualifiedName 1599 ^ 1600 1601 SymbolFunctionName: 1602 SymbolName 1603 SymbolName TypeFunctionNoReturn 1604 SymbolName M TypeFunctionNoReturn 1605 SymbolName M TypeModifiers TypeFunctionNoReturn 1606 1607 The start pointer should be at the above location. 1608 */ 1609 size_t n = 0; 1610 do 1611 { 1612 if (n++) 1613 string_append (decl, "."); 1614 1615 /* Skip over anonymous symbols. */ 1616 while (*mangled == '0') 1617 mangled++; 1618 1619 mangled = dlang_identifier (decl, mangled, info); 1620 1621 /* Consume the encoded arguments. However if this is not followed by the 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. */ 1625 if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled))) 1626 { 1627 string mods; 1628 const char *start = mangled; 1629 int saved = string_length (decl); 1630 1631 /* Save the type modifiers for appending at the end if needed. */ 1632 string_init (&mods); 1633 1634 /* Skip over 'this' parameter and type modifiers. */ 1635 if (*mangled == 'M') 1636 { 1637 mangled++; 1638 mangled = dlang_type_modifiers (&mods, mangled); 1639 string_setlength (decl, saved); 1640 } 1641 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)); 1646 1647 if (mangled == NULL || *mangled == '\0') 1648 { 1649 /* Did not match the rule we were looking for. */ 1650 mangled = start; 1651 string_setlength (decl, saved); 1652 } 1653 1654 string_delete (&mods); 1655 } 1656 } 1657 while (mangled && dlang_symbol_name_p (mangled, info)); 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. */ 1664 static const char * 1665 dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info) 1666 { 1667 unsigned long elements; 1668 1669 mangled = dlang_number (mangled, &elements); 1670 if (mangled == NULL) 1671 return NULL; 1672 1673 string_append (decl, "Tuple!("); 1674 1675 while (elements--) 1676 { 1677 mangled = dlang_type (decl, mangled, info); 1678 if (mangled == NULL) 1679 return NULL; 1680 1681 if (elements != 0) 1682 string_append (decl, ", "); 1683 } 1684 1685 string_append (decl, ")"); 1686 return mangled; 1687 } 1688 1689 /* Demangle the template symbol parameter from MANGLED and append it to DECL. 1690 Return the remaining string on success or NULL on failure. */ 1691 static const char * 1692 dlang_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 1702 unsigned long len; 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 1750 /* Demangle the argument list from MANGLED and append it to DECL. 1751 Return the remaining string on success or NULL on failure. */ 1752 static const char * 1753 dlang_template_args (string *decl, const char *mangled, struct dlang_info *info) 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 1769 /* Skip over specialised template prefix. */ 1770 if (*mangled == 'H') 1771 mangled++; 1772 1773 switch (*mangled) 1774 { 1775 case 'S': /* Symbol parameter. */ 1776 mangled++; 1777 mangled = dlang_template_symbol_param (decl, mangled, info); 1778 break; 1779 case 'T': /* Type parameter. */ 1780 mangled++; 1781 mangled = dlang_type (decl, mangled, info); 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 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 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); 1805 mangled = dlang_type (&name, mangled, info); 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 } 1813 case 'X': /* Externally mangled parameter. */ 1814 { 1815 unsigned long len; 1816 const char *endptr; 1817 1818 mangled++; 1819 endptr = dlang_number (mangled, &len); 1820 if (endptr == NULL || strlen (endptr) < len) 1821 return NULL; 1822 1823 string_appendn (decl, endptr, len); 1824 mangled = endptr + len; 1825 break; 1826 } 1827 default: 1828 return NULL; 1829 } 1830 } 1831 1832 return mangled; 1833 } 1834 1835 /* Extract and demangle the template symbol in MANGLED, expected to 1836 be made up of LEN characters (-1 if unknown), and append it to DECL. 1837 Returns the remaining signature on success or NULL on failure. */ 1838 static const char * 1839 dlang_parse_template (string *decl, const char *mangled, 1840 struct dlang_info *info, unsigned long len) 1841 { 1842 const char *start = mangled; 1843 string args; 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 1850 Number __U LName TemplateArgs Z 1851 ^ 1852 The start pointer should be at the above location, and LEN should be 1853 the value of the decoded number. 1854 */ 1855 1856 /* Template symbol. */ 1857 if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0') 1858 return NULL; 1859 1860 mangled += 3; 1861 1862 /* Template identifier. */ 1863 mangled = dlang_identifier (decl, mangled, info); 1864 1865 /* Template arguments. */ 1866 string_init (&args); 1867 mangled = dlang_template_args (&args, mangled, info); 1868 1869 string_append (decl, "!("); 1870 string_appendn (decl, args.b, string_length (&args)); 1871 string_append (decl, ")"); 1872 1873 string_delete (&args); 1874 1875 /* Check for template name length mismatch. */ 1876 if (len != TEMPLATE_LENGTH_UNKNOWN 1877 && mangled 1878 && (unsigned long) (mangled - start) != len) 1879 return NULL; 1880 1881 return mangled; 1882 } 1883 1884 /* Initialize the information structure we use to pass around information. */ 1885 static void 1886 dlang_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 1893 /* Extract and demangle the symbol in MANGLED. Returns the demangled 1894 signature on success or NULL on failure. */ 1895 1896 char * 1897 dlang_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 { 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') 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 1936