1 /* Demangler for the D programming language 2 Copyright (C) 2014-2017 Free Software Foundation, Inc. 3 Written by Iain Buclaw (ibuclaw (at) 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 This file imports strtol for decoding mangled literals. */ 32 33 #if 0 /* in valgrind */ 34 #ifdef HAVE_CONFIG_H 35 #include "config.h" 36 #endif 37 #endif /* ! in valgrind */ 38 39 #if 0 /* in valgrind */ 40 #include "safe-ctype.h" 41 #endif /* ! in valgrind */ 42 43 #if 0 /* in valgrind */ 44 #include <sys/types.h> 45 #include <string.h> 46 #include <stdio.h> 47 #endif /* ! in valgrind */ 48 49 #if 0 /* in valgrind */ 50 #ifdef HAVE_STDLIB_H 51 #include <stdlib.h> 52 #else 53 extern long strtol (const char *nptr, char **endptr, int base); 54 #endif 55 #endif /* ! in valgrind */ 56 57 #if 0 /* in valgrind */ 58 #include <demangle.h> 59 #include "libiberty.h" 60 #endif /* ! in valgrind */ 61 62 #include "vg_libciface.h" 63 64 #include "ansidecl.h" 65 #include "demangle.h" 66 #include "safe-ctype.h" 67 68 /* A mini string-handling package */ 69 70 typedef struct string /* Beware: these aren't required to be */ 71 { /* '\0' terminated. */ 72 char *b; /* pointer to start of string */ 73 char *p; /* pointer after last character */ 74 char *e; /* pointer after end of allocated space */ 75 } string; 76 77 static void 78 string_need (string *s, int n) 79 { 80 int tem; 81 82 if (s->b == NULL) 83 { 84 if (n < 32) 85 { 86 n = 32; 87 } 88 s->p = s->b = XNEWVEC (char, n); 89 s->e = s->b + n; 90 } 91 else if (s->e - s->p < n) 92 { 93 tem = s->p - s->b; 94 n += tem; 95 n *= 2; 96 s->b = XRESIZEVEC (char, s->b, n); 97 s->p = s->b + tem; 98 s->e = s->b + n; 99 } 100 } 101 102 static void 103 string_delete (string *s) 104 { 105 if (s->b != NULL) 106 { 107 XDELETEVEC (s->b); 108 s->b = s->e = s->p = NULL; 109 } 110 } 111 112 static void 113 string_init (string *s) 114 { 115 s->b = s->p = s->e = NULL; 116 } 117 118 static int 119 string_length (string *s) 120 { 121 if (s->p == s->b) 122 { 123 return 0; 124 } 125 return s->p - s->b; 126 } 127 128 static void 129 string_setlength (string *s, int n) 130 { 131 if (n - string_length (s) < 0) 132 { 133 s->p = s->b + n; 134 } 135 } 136 137 static void 138 string_append (string *p, const char *s) 139 { 140 int n = strlen (s); 141 string_need (p, n); 142 memcpy (p->p, s, n); 143 p->p += n; 144 } 145 146 static void 147 string_appendn (string *p, const char *s, int n) 148 { 149 if (n != 0) 150 { 151 string_need (p, n); 152 memcpy (p->p, s, n); 153 p->p += n; 154 } 155 } 156 157 static void 158 string_prependn (string *p, const char *s, int n) 159 { 160 char *q; 161 162 if (n != 0) 163 { 164 string_need (p, n); 165 for (q = p->p - 1; q >= p->b; q--) 166 { 167 q[n] = q[0]; 168 } 169 memcpy (p->b, s, n); 170 p->p += n; 171 } 172 } 173 174 static void 175 string_prepend (string *p, const char *s) 176 { 177 if (s != NULL && *s != '\0') 178 { 179 string_prependn (p, s, strlen (s)); 180 } 181 } 182 183 /* What kinds of symbol we could be parsing. */ 184 enum dlang_symbol_kinds 185 { 186 /* Top-level symbol, needs it's type checked. */ 187 dlang_top_level, 188 /* Function symbol, needs it's type checked. */ 189 dlang_function, 190 /* Strongly typed name, such as for classes, structs and enums. */ 191 dlang_type_name, 192 /* Template identifier. */ 193 dlang_template_ident, 194 /* Template symbol parameter. */ 195 dlang_template_param 196 }; 197 198 /* Prototypes for forward referenced functions */ 199 static const char *dlang_function_args (string *, const char *); 200 201 static const char *dlang_type (string *, const char *); 202 203 static const char *dlang_value (string *, const char *, const char *, char); 204 205 static const char *dlang_parse_symbol (string *, const char *, 206 enum dlang_symbol_kinds); 207 208 static const char *dlang_parse_tuple (string *, const char *); 209 210 static const char *dlang_parse_template (string *, const char *, long); 211 212 213 /* Demangle the calling convention from MANGLED and append it to DECL. 214 Return the remaining string on success or NULL on failure. */ 215 static const char * 216 dlang_call_convention (string *decl, const char *mangled) 217 { 218 if (mangled == NULL || *mangled == '\0') 219 return NULL; 220 221 switch (*mangled) 222 { 223 case 'F': /* (D) */ 224 mangled++; 225 break; 226 case 'U': /* (C) */ 227 mangled++; 228 string_append (decl, "extern(C) "); 229 break; 230 case 'W': /* (Windows) */ 231 mangled++; 232 string_append (decl, "extern(Windows) "); 233 break; 234 case 'V': /* (Pascal) */ 235 mangled++; 236 string_append (decl, "extern(Pascal) "); 237 break; 238 case 'R': /* (C++) */ 239 mangled++; 240 string_append (decl, "extern(C++) "); 241 break; 242 case 'Y': /* (Objective-C) */ 243 mangled++; 244 string_append (decl, "extern(Objective-C) "); 245 break; 246 default: 247 return NULL; 248 } 249 250 return mangled; 251 } 252 253 /* Extract the type modifiers from MANGLED and append them to DECL. 254 Returns the remaining signature on success or NULL on failure. */ 255 static const char * 256 dlang_type_modifiers (string *decl, const char *mangled) 257 { 258 if (mangled == NULL || *mangled == '\0') 259 return NULL; 260 261 switch (*mangled) 262 { 263 case 'x': /* const */ 264 mangled++; 265 string_append (decl, " const"); 266 return mangled; 267 case 'y': /* immutable */ 268 mangled++; 269 string_append (decl, " immutable"); 270 return mangled; 271 case 'O': /* shared */ 272 mangled++; 273 string_append (decl, " shared"); 274 return dlang_type_modifiers (decl, mangled); 275 case 'N': 276 mangled++; 277 if (*mangled == 'g') /* wild */ 278 { 279 mangled++; 280 string_append (decl, " inout"); 281 return dlang_type_modifiers (decl, mangled); 282 } 283 else 284 return NULL; 285 286 default: 287 return mangled; 288 } 289 } 290 291 /* Demangle the D function attributes from MANGLED and append it to DECL. 292 Return the remaining string on success or NULL on failure. */ 293 static const char * 294 dlang_attributes (string *decl, const char *mangled) 295 { 296 if (mangled == NULL || *mangled == '\0') 297 return NULL; 298 299 while (*mangled == 'N') 300 { 301 mangled++; 302 switch (*mangled) 303 { 304 case 'a': /* pure */ 305 mangled++; 306 string_append (decl, "pure "); 307 continue; 308 case 'b': /* nothrow */ 309 mangled++; 310 string_append (decl, "nothrow "); 311 continue; 312 case 'c': /* ref */ 313 mangled++; 314 string_append (decl, "ref "); 315 continue; 316 case 'd': /* @property */ 317 mangled++; 318 string_append (decl, "@property "); 319 continue; 320 case 'e': /* @trusted */ 321 mangled++; 322 string_append (decl, "@trusted "); 323 continue; 324 case 'f': /* @safe */ 325 mangled++; 326 string_append (decl, "@safe "); 327 continue; 328 case 'g': 329 case 'h': 330 case 'k': 331 /* inout parameter is represented as 'Ng'. 332 vector parameter is represented as 'Nh'. 333 return paramenter is represented as 'Nk'. 334 If we see this, then we know we're really in the 335 parameter list. Rewind and break. */ 336 mangled--; 337 break; 338 case 'i': /* @nogc */ 339 mangled++; 340 string_append (decl, "@nogc "); 341 continue; 342 case 'j': /* return */ 343 mangled++; 344 string_append (decl, "return "); 345 continue; 346 347 default: /* unknown attribute */ 348 return NULL; 349 } 350 break; 351 } 352 353 return mangled; 354 } 355 356 /* Demangle the function type from MANGLED and append it to DECL. 357 Return the remaining string on success or NULL on failure. */ 358 static const char * 359 dlang_function_type (string *decl, const char *mangled) 360 { 361 string attr, args, type; 362 size_t szattr, szargs, sztype; 363 364 if (mangled == NULL || *mangled == '\0') 365 return NULL; 366 367 /* The order of the mangled string is: 368 CallConvention FuncAttrs Arguments ArgClose Type 369 370 The demangled string is re-ordered as: 371 CallConvention Type Arguments FuncAttrs 372 */ 373 string_init (&attr); 374 string_init (&args); 375 string_init (&type); 376 377 /* Function call convention. */ 378 mangled = dlang_call_convention (decl, mangled); 379 380 /* Function attributes. */ 381 mangled = dlang_attributes (&attr, mangled); 382 szattr = string_length (&attr); 383 384 /* Function arguments. */ 385 mangled = dlang_function_args (&args, mangled); 386 szargs = string_length (&args); 387 388 /* Function return type. */ 389 mangled = dlang_type (&type, mangled); 390 sztype = string_length (&type); 391 392 /* Append to decl in order. */ 393 string_appendn (decl, type.b, sztype); 394 string_append (decl, "("); 395 string_appendn (decl, args.b, szargs); 396 string_append (decl, ") "); 397 string_appendn (decl, attr.b, szattr); 398 399 string_delete (&attr); 400 string_delete (&args); 401 string_delete (&type); 402 return mangled; 403 } 404 405 /* Demangle the argument list from MANGLED and append it to DECL. 406 Return the remaining string on success or NULL on failure. */ 407 static const char * 408 dlang_function_args (string *decl, const char *mangled) 409 { 410 size_t n = 0; 411 412 while (mangled && *mangled != '\0') 413 { 414 switch (*mangled) 415 { 416 case 'X': /* (variadic T t...) style. */ 417 mangled++; 418 string_append (decl, "..."); 419 return mangled; 420 case 'Y': /* (variadic T t, ...) style. */ 421 mangled++; 422 if (n != 0) 423 string_append (decl, ", "); 424 string_append (decl, "..."); 425 return mangled; 426 case 'Z': /* Normal function. */ 427 mangled++; 428 return mangled; 429 } 430 431 if (n++) 432 string_append (decl, ", "); 433 434 if (*mangled == 'M') /* scope(T) */ 435 { 436 mangled++; 437 string_append (decl, "scope "); 438 } 439 440 if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */ 441 { 442 mangled += 2; 443 string_append (decl, "return "); 444 } 445 446 switch (*mangled) 447 { 448 case 'J': /* out(T) */ 449 mangled++; 450 string_append (decl, "out "); 451 break; 452 case 'K': /* ref(T) */ 453 mangled++; 454 string_append (decl, "ref "); 455 break; 456 case 'L': /* lazy(T) */ 457 mangled++; 458 string_append (decl, "lazy "); 459 break; 460 } 461 mangled = dlang_type (decl, mangled); 462 } 463 464 return mangled; 465 } 466 467 /* Demangle the type from MANGLED and append it to DECL. 468 Return the remaining string on success or NULL on failure. */ 469 static const char * 470 dlang_type (string *decl, const char *mangled) 471 { 472 if (mangled == NULL || *mangled == '\0') 473 return NULL; 474 475 switch (*mangled) 476 { 477 case 'O': /* shared(T) */ 478 mangled++; 479 string_append (decl, "shared("); 480 mangled = dlang_type (decl, mangled); 481 string_append (decl, ")"); 482 return mangled; 483 case 'x': /* const(T) */ 484 mangled++; 485 string_append (decl, "const("); 486 mangled = dlang_type (decl, mangled); 487 string_append (decl, ")"); 488 return mangled; 489 case 'y': /* immutable(T) */ 490 mangled++; 491 string_append (decl, "immutable("); 492 mangled = dlang_type (decl, mangled); 493 string_append (decl, ")"); 494 return mangled; 495 case 'N': 496 mangled++; 497 if (*mangled == 'g') /* wild(T) */ 498 { 499 mangled++; 500 string_append (decl, "inout("); 501 mangled = dlang_type (decl, mangled); 502 string_append (decl, ")"); 503 return mangled; 504 } 505 else if (*mangled == 'h') /* vector(T) */ 506 { 507 mangled++; 508 string_append (decl, "__vector("); 509 mangled = dlang_type (decl, mangled); 510 string_append (decl, ")"); 511 return mangled; 512 } 513 else 514 return NULL; 515 case 'A': /* dynamic array (T[]) */ 516 mangled++; 517 mangled = dlang_type (decl, mangled); 518 string_append (decl, "[]"); 519 return mangled; 520 case 'G': /* static array (T[N]) */ 521 { 522 const char *numptr; 523 size_t num = 0; 524 mangled++; 525 526 numptr = mangled; 527 while (ISDIGIT (*mangled)) 528 { 529 num++; 530 mangled++; 531 } 532 mangled = dlang_type (decl, mangled); 533 string_append (decl, "["); 534 string_appendn (decl, numptr, num); 535 string_append (decl, "]"); 536 return mangled; 537 } 538 case 'H': /* associative array (T[T]) */ 539 { 540 string type; 541 size_t sztype; 542 mangled++; 543 544 string_init (&type); 545 mangled = dlang_type (&type, mangled); 546 sztype = string_length (&type); 547 548 mangled = dlang_type (decl, mangled); 549 string_append (decl, "["); 550 string_appendn (decl, type.b, sztype); 551 string_append (decl, "]"); 552 553 string_delete (&type); 554 return mangled; 555 } 556 case 'P': /* pointer (T*) */ 557 mangled++; 558 /* Function pointer types don't include the trailing asterisk. */ 559 switch (*mangled) 560 { 561 case 'F': case 'U': case 'W': 562 case 'V': case 'R': case 'Y': 563 mangled = dlang_function_type (decl, mangled); 564 string_append (decl, "function"); 565 return mangled; 566 } 567 mangled = dlang_type (decl, mangled); 568 string_append (decl, "*"); 569 return mangled; 570 case 'I': /* ident T */ 571 case 'C': /* class T */ 572 case 'S': /* struct T */ 573 case 'E': /* enum T */ 574 case 'T': /* typedef T */ 575 mangled++; 576 return dlang_parse_symbol (decl, mangled, dlang_type_name); 577 case 'D': /* delegate T */ 578 { 579 string mods; 580 size_t szmods; 581 mangled++; 582 583 string_init (&mods); 584 mangled = dlang_type_modifiers (&mods, mangled); 585 szmods = string_length (&mods); 586 587 mangled = dlang_function_type (decl, mangled); 588 string_append (decl, "delegate"); 589 string_appendn (decl, mods.b, szmods); 590 591 string_delete (&mods); 592 return mangled; 593 } 594 case 'B': /* tuple T */ 595 mangled++; 596 return dlang_parse_tuple (decl, mangled); 597 598 /* Basic types */ 599 case 'n': 600 mangled++; 601 string_append (decl, "none"); 602 return mangled; 603 case 'v': 604 mangled++; 605 string_append (decl, "void"); 606 return mangled; 607 case 'g': 608 mangled++; 609 string_append (decl, "byte"); 610 return mangled; 611 case 'h': 612 mangled++; 613 string_append (decl, "ubyte"); 614 return mangled; 615 case 's': 616 mangled++; 617 string_append (decl, "short"); 618 return mangled; 619 case 't': 620 mangled++; 621 string_append (decl, "ushort"); 622 return mangled; 623 case 'i': 624 mangled++; 625 string_append (decl, "int"); 626 return mangled; 627 case 'k': 628 mangled++; 629 string_append (decl, "uint"); 630 return mangled; 631 case 'l': 632 mangled++; 633 string_append (decl, "long"); 634 return mangled; 635 case 'm': 636 mangled++; 637 string_append (decl, "ulong"); 638 return mangled; 639 case 'f': 640 mangled++; 641 string_append (decl, "float"); 642 return mangled; 643 case 'd': 644 mangled++; 645 string_append (decl, "double"); 646 return mangled; 647 case 'e': 648 mangled++; 649 string_append (decl, "real"); 650 return mangled; 651 652 /* Imaginary and Complex types */ 653 case 'o': 654 mangled++; 655 string_append (decl, "ifloat"); 656 return mangled; 657 case 'p': 658 mangled++; 659 string_append (decl, "idouble"); 660 return mangled; 661 case 'j': 662 mangled++; 663 string_append (decl, "ireal"); 664 return mangled; 665 case 'q': 666 mangled++; 667 string_append (decl, "cfloat"); 668 return mangled; 669 case 'r': 670 mangled++; 671 string_append (decl, "cdouble"); 672 return mangled; 673 case 'c': 674 mangled++; 675 string_append (decl, "creal"); 676 return mangled; 677 678 /* Other types */ 679 case 'b': 680 mangled++; 681 string_append (decl, "bool"); 682 return mangled; 683 case 'a': 684 mangled++; 685 string_append (decl, "char"); 686 return mangled; 687 case 'u': 688 mangled++; 689 string_append (decl, "wchar"); 690 return mangled; 691 case 'w': 692 mangled++; 693 string_append (decl, "dchar"); 694 return mangled; 695 case 'z': 696 mangled++; 697 switch (*mangled) 698 { 699 case 'i': 700 mangled++; 701 string_append (decl, "cent"); 702 return mangled; 703 case 'k': 704 mangled++; 705 string_append (decl, "ucent"); 706 return mangled; 707 } 708 return NULL; 709 710 default: /* unhandled */ 711 return NULL; 712 } 713 } 714 715 /* Extract the identifier from MANGLED and append it to DECL. 716 Return the remaining string on success or NULL on failure. */ 717 static const char * 718 dlang_identifier (string *decl, const char *mangled, 719 enum dlang_symbol_kinds kind) 720 { 721 char *endptr; 722 long len; 723 724 if (mangled == NULL || *mangled == '\0') 725 return NULL; 726 727 len = strtol (mangled, &endptr, 10); 728 729 if (endptr == NULL || len <= 0) 730 return NULL; 731 732 /* In template parameter symbols, the first character of the mangled 733 name can be a digit. This causes ambiguity issues because the 734 digits of the two numbers are adjacent. */ 735 if (kind == dlang_template_param) 736 { 737 long psize = len; 738 char *pend; 739 int saved = string_length (decl); 740 741 /* Work backwards until a match is found. */ 742 for (pend = endptr; endptr != NULL; pend--) 743 { 744 mangled = pend; 745 746 /* Reached the beginning of the pointer to the name length, 747 try parsing the entire symbol. */ 748 if (psize == 0) 749 { 750 psize = len; 751 pend = endptr; 752 endptr = NULL; 753 } 754 755 /* Check whether template parameter is a function with a valid 756 return type or an untyped identifier. */ 757 if (ISDIGIT (*mangled)) 758 mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident); 759 else if (strncmp (mangled, "_D", 2) == 0) 760 { 761 mangled += 2; 762 mangled = dlang_parse_symbol (decl, mangled, dlang_function); 763 } 764 765 /* Check for name length mismatch. */ 766 if (mangled && (mangled - pend) == psize) 767 return mangled; 768 769 psize /= 10; 770 string_setlength (decl, saved); 771 } 772 773 /* No match on any combinations. */ 774 return NULL; 775 } 776 else 777 { 778 if (strlen (endptr) < (size_t) len) 779 return NULL; 780 781 mangled = endptr; 782 783 /* May be a template instance. */ 784 if (len >= 5 && strncmp (mangled, "__T", 3) == 0) 785 { 786 /* Template symbol. */ 787 if (ISDIGIT (mangled[3]) && mangled[3] != '0') 788 return dlang_parse_template (decl, mangled, len); 789 790 return NULL; 791 } 792 793 switch (len) 794 { 795 case 6: 796 if (strncmp (mangled, "__ctor", len) == 0) 797 { 798 /* Constructor symbol for a class/struct. */ 799 string_append (decl, "this"); 800 mangled += len; 801 return mangled; 802 } 803 else if (strncmp (mangled, "__dtor", len) == 0) 804 { 805 /* Destructor symbol for a class/struct. */ 806 string_append (decl, "~this"); 807 mangled += len; 808 return mangled; 809 } 810 else if (strncmp (mangled, "__initZ", len+1) == 0) 811 { 812 /* The static initialiser for a given symbol. */ 813 string_append (decl, "init$"); 814 mangled += len; 815 return mangled; 816 } 817 else if (strncmp (mangled, "__vtblZ", len+1) == 0) 818 { 819 /* The vtable symbol for a given class. */ 820 string_prepend (decl, "vtable for "); 821 string_setlength (decl, string_length (decl) - 1); 822 mangled += len; 823 return mangled; 824 } 825 break; 826 827 case 7: 828 if (strncmp (mangled, "__ClassZ", len+1) == 0) 829 { 830 /* The classinfo symbol for a given class. */ 831 string_prepend (decl, "ClassInfo for "); 832 string_setlength (decl, string_length (decl) - 1); 833 mangled += len; 834 return mangled; 835 } 836 break; 837 838 case 10: 839 if (strncmp (mangled, "__postblitMFZ", len+3) == 0) 840 { 841 /* Postblit symbol for a struct. */ 842 string_append (decl, "this(this)"); 843 mangled += len + 3; 844 return mangled; 845 } 846 break; 847 848 case 11: 849 if (strncmp (mangled, "__InterfaceZ", len+1) == 0) 850 { 851 /* The interface symbol for a given class. */ 852 string_prepend (decl, "Interface for "); 853 string_setlength (decl, string_length (decl) - 1); 854 mangled += len; 855 return mangled; 856 } 857 break; 858 859 case 12: 860 if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0) 861 { 862 /* The ModuleInfo symbol for a given module. */ 863 string_prepend (decl, "ModuleInfo for "); 864 string_setlength (decl, string_length (decl) - 1); 865 mangled += len; 866 return mangled; 867 } 868 break; 869 } 870 871 string_appendn (decl, mangled, len); 872 mangled += len; 873 } 874 875 return mangled; 876 } 877 878 /* Extract the integer value from MANGLED and append it to DECL, 879 where TYPE is the type it should be represented as. 880 Return the remaining string on success or NULL on failure. */ 881 static const char * 882 dlang_parse_integer (string *decl, const char *mangled, char type) 883 { 884 if (type == 'a' || type == 'u' || type == 'w') 885 { 886 /* Parse character value. */ 887 char value[10]; 888 int pos = 10; 889 int width = 0; 890 char *endptr; 891 long val = strtol (mangled, &endptr, 10); 892 893 if (endptr == NULL || val < 0) 894 return NULL; 895 896 string_append (decl, "'"); 897 898 if (type == 'a' && val >= 0x20 && val < 0x7F) 899 { 900 /* Represent as a character literal. */ 901 char c = (char) val; 902 string_appendn (decl, &c, 1); 903 } 904 else 905 { 906 /* Represent as a hexadecimal value. */ 907 switch (type) 908 { 909 case 'a': /* char */ 910 string_append (decl, "\\x"); 911 width = 2; 912 break; 913 case 'u': /* wchar */ 914 string_append (decl, "\\u"); 915 width = 4; 916 break; 917 case 'w': /* dchar */ 918 string_append (decl, "\\U"); 919 width = 8; 920 break; 921 } 922 923 while (val > 0) 924 { 925 int digit = val % 16; 926 927 if (digit < 10) 928 value[--pos] = (char)(digit + '0'); 929 else 930 value[--pos] = (char)((digit - 10) + 'a'); 931 932 val /= 16; 933 width--; 934 } 935 936 for (; width > 0; width--) 937 value[--pos] = '0'; 938 939 string_appendn (decl, &(value[pos]), 10 - pos); 940 } 941 string_append (decl, "'"); 942 mangled = endptr; 943 } 944 else if (type == 'b') 945 { 946 /* Parse boolean value. */ 947 char *endptr; 948 long val = strtol (mangled, &endptr, 10); 949 950 if (endptr == NULL || val < 0) 951 return NULL; 952 953 string_append (decl, val ? "true" : "false"); 954 mangled = endptr; 955 } 956 else 957 { 958 /* Parse integer value. */ 959 const char *numptr = mangled; 960 size_t num = 0; 961 962 while (ISDIGIT (*mangled)) 963 { 964 num++; 965 mangled++; 966 } 967 string_appendn (decl, numptr, num); 968 969 /* Append suffix. */ 970 switch (type) 971 { 972 case 'h': /* ubyte */ 973 case 't': /* ushort */ 974 case 'k': /* uint */ 975 string_append (decl, "u"); 976 break; 977 case 'l': /* long */ 978 string_append (decl, "L"); 979 break; 980 case 'm': /* ulong */ 981 string_append (decl, "uL"); 982 break; 983 } 984 } 985 986 return mangled; 987 } 988 989 /* Extract the floating-point value from MANGLED and append it to DECL. 990 Return the remaining string on success or NULL on failure. */ 991 static const char * 992 dlang_parse_real (string *decl, const char *mangled) 993 { 994 char buffer[64]; 995 int len = 0; 996 997 /* Handle NAN and +-INF. */ 998 if (strncmp (mangled, "NAN", 3) == 0) 999 { 1000 string_append (decl, "NaN"); 1001 mangled += 3; 1002 return mangled; 1003 } 1004 else if (strncmp (mangled, "INF", 3) == 0) 1005 { 1006 string_append (decl, "Inf"); 1007 mangled += 3; 1008 return mangled; 1009 } 1010 else if (strncmp (mangled, "NINF", 4) == 0) 1011 { 1012 string_append (decl, "-Inf"); 1013 mangled += 4; 1014 return mangled; 1015 } 1016 1017 /* Hexadecimal prefix and leading bit. */ 1018 if (*mangled == 'N') 1019 { 1020 buffer[len++] = '-'; 1021 mangled++; 1022 } 1023 1024 if (!ISXDIGIT (*mangled)) 1025 return NULL; 1026 1027 buffer[len++] = '0'; 1028 buffer[len++] = 'x'; 1029 buffer[len++] = *mangled; 1030 buffer[len++] = '.'; 1031 mangled++; 1032 1033 /* Significand. */ 1034 while (ISXDIGIT (*mangled)) 1035 { 1036 buffer[len++] = *mangled; 1037 mangled++; 1038 } 1039 1040 /* Exponent. */ 1041 if (*mangled != 'P') 1042 return NULL; 1043 1044 buffer[len++] = 'p'; 1045 mangled++; 1046 1047 if (*mangled == 'N') 1048 { 1049 buffer[len++] = '-'; 1050 mangled++; 1051 } 1052 1053 while (ISDIGIT (*mangled)) 1054 { 1055 buffer[len++] = *mangled; 1056 mangled++; 1057 } 1058 1059 /* Write out the demangled hexadecimal, rather than trying to 1060 convert the buffer into a floating-point value. */ 1061 buffer[len] = '\0'; 1062 len = strlen (buffer); 1063 string_appendn (decl, buffer, len); 1064 return mangled; 1065 } 1066 1067 /* Convert VAL from an ascii hexdigit to value. */ 1068 static char 1069 ascii2hex (char val) 1070 { 1071 if (val >= 'a' && val <= 'f') 1072 return (val - 'a' + 10); 1073 1074 if (val >= 'A' && val <= 'F') 1075 return (val - 'A' + 10); 1076 1077 if (val >= '0' && val <= '9') 1078 return (val - '0'); 1079 1080 return 0; 1081 } 1082 1083 /* Extract the string value from MANGLED and append it to DECL. 1084 Return the remaining string on success or NULL on failure. */ 1085 static const char * 1086 dlang_parse_string (string *decl, const char *mangled) 1087 { 1088 char type = *mangled; 1089 char *endptr; 1090 long len; 1091 1092 mangled++; 1093 len = strtol (mangled, &endptr, 10); 1094 1095 if (endptr == NULL || len < 0) 1096 return NULL; 1097 1098 mangled = endptr; 1099 if (*mangled != '_') 1100 return NULL; 1101 1102 mangled++; 1103 string_append (decl, "\""); 1104 while (len--) 1105 { 1106 if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1])) 1107 { 1108 char a = ascii2hex (mangled[0]); 1109 char b = ascii2hex (mangled[1]); 1110 char val = (a << 4) | b; 1111 1112 /* Sanitize white and non-printable characters. */ 1113 switch (val) 1114 { 1115 case ' ': 1116 string_append (decl, " "); 1117 break; 1118 case '\t': 1119 string_append (decl, "\\t"); 1120 break; 1121 case '\n': 1122 string_append (decl, "\\n"); 1123 break; 1124 case '\r': 1125 string_append (decl, "\\r"); 1126 break; 1127 case '\f': 1128 string_append (decl, "\\f"); 1129 break; 1130 case '\v': 1131 string_append (decl, "\\v"); 1132 break; 1133 1134 default: 1135 if (ISPRINT (val)) 1136 string_appendn (decl, &val, 1); 1137 else 1138 { 1139 string_append (decl, "\\x"); 1140 string_appendn (decl, mangled, 2); 1141 } 1142 } 1143 } 1144 else 1145 return NULL; 1146 1147 mangled += 2; 1148 } 1149 string_append (decl, "\""); 1150 1151 if (type != 'a') 1152 string_appendn (decl, &type, 1); 1153 1154 return mangled; 1155 } 1156 1157 /* Extract the static array value from MANGLED and append it to DECL. 1158 Return the remaining string on success or NULL on failure. */ 1159 static const char * 1160 dlang_parse_arrayliteral (string *decl, const char *mangled) 1161 { 1162 char *endptr; 1163 long elements = strtol (mangled, &endptr, 10); 1164 1165 if (endptr == NULL || elements < 0) 1166 return NULL; 1167 1168 mangled = endptr; 1169 string_append (decl, "["); 1170 while (elements--) 1171 { 1172 mangled = dlang_value (decl, mangled, NULL, '\0'); 1173 if (elements != 0) 1174 string_append (decl, ", "); 1175 } 1176 1177 string_append (decl, "]"); 1178 return mangled; 1179 } 1180 1181 /* Extract the associative array value from MANGLED and append it to DECL. 1182 Return the remaining string on success or NULL on failure. */ 1183 static const char * 1184 dlang_parse_assocarray (string *decl, const char *mangled) 1185 { 1186 char *endptr; 1187 long elements = strtol (mangled, &endptr, 10); 1188 1189 if (endptr == NULL || elements < 0) 1190 return NULL; 1191 1192 mangled = endptr; 1193 string_append (decl, "["); 1194 while (elements--) 1195 { 1196 mangled = dlang_value (decl, mangled, NULL, '\0'); 1197 string_append (decl, ":"); 1198 mangled = dlang_value (decl, mangled, NULL, '\0'); 1199 1200 if (elements != 0) 1201 string_append (decl, ", "); 1202 } 1203 1204 string_append (decl, "]"); 1205 return mangled; 1206 } 1207 1208 /* Extract the struct literal value for NAME from MANGLED and append it to DECL. 1209 Return the remaining string on success or NULL on failure. */ 1210 static const char * 1211 dlang_parse_structlit (string *decl, const char *mangled, const char *name) 1212 { 1213 char *endptr; 1214 long args = strtol (mangled, &endptr, 10); 1215 1216 if (endptr == NULL || args < 0) 1217 return NULL; 1218 1219 mangled = endptr; 1220 if (name != NULL) 1221 string_append (decl, name); 1222 1223 string_append (decl, "("); 1224 while (args--) 1225 { 1226 mangled = dlang_value (decl, mangled, NULL, '\0'); 1227 if (args != 0) 1228 string_append (decl, ", "); 1229 } 1230 1231 string_append (decl, ")"); 1232 return mangled; 1233 } 1234 1235 /* Extract the value from MANGLED and append it to DECL. 1236 Return the remaining string on success or NULL on failure. */ 1237 static const char * 1238 dlang_value (string *decl, const char *mangled, const char *name, char type) 1239 { 1240 if (mangled == NULL || *mangled == '\0') 1241 return NULL; 1242 1243 switch (*mangled) 1244 { 1245 /* Null value. */ 1246 case 'n': 1247 mangled++; 1248 string_append (decl, "null"); 1249 break; 1250 1251 /* Integral values. */ 1252 case 'N': 1253 mangled++; 1254 string_append (decl, "-"); 1255 mangled = dlang_parse_integer (decl, mangled, type); 1256 break; 1257 1258 case 'i': 1259 mangled++; 1260 if (*mangled < '0' || *mangled > '9') 1261 return NULL; 1262 /* Fall through */ 1263 case '0': case '1': case '2': case '3': case '4': 1264 case '5': case '6': case '7': case '8': case '9': 1265 mangled = dlang_parse_integer (decl, mangled, type); 1266 break; 1267 1268 /* Real value. */ 1269 case 'e': 1270 mangled++; 1271 mangled = dlang_parse_real (decl, mangled); 1272 break; 1273 1274 /* Complex value. */ 1275 case 'c': 1276 mangled++; 1277 mangled = dlang_parse_real (decl, mangled); 1278 string_append (decl, "+"); 1279 if (mangled == NULL || *mangled != 'c') 1280 return NULL; 1281 mangled++; 1282 mangled = dlang_parse_real (decl, mangled); 1283 string_append (decl, "i"); 1284 break; 1285 1286 /* String values. */ 1287 case 'a': /* UTF8 */ 1288 case 'w': /* UTF16 */ 1289 case 'd': /* UTF32 */ 1290 mangled = dlang_parse_string (decl, mangled); 1291 break; 1292 1293 /* Array values. */ 1294 case 'A': 1295 mangled++; 1296 if (type == 'H') 1297 mangled = dlang_parse_assocarray (decl, mangled); 1298 else 1299 mangled = dlang_parse_arrayliteral (decl, mangled); 1300 break; 1301 1302 /* Struct values. */ 1303 case 'S': 1304 mangled++; 1305 mangled = dlang_parse_structlit (decl, mangled, name); 1306 break; 1307 1308 default: 1309 return NULL; 1310 } 1311 1312 return mangled; 1313 } 1314 1315 /* Extract the type modifiers from MANGLED and return the string 1316 length that it consumes in MANGLED on success or 0 on failure. */ 1317 static int 1318 dlang_type_modifier_p (const char *mangled) 1319 { 1320 int i; 1321 1322 switch (*mangled) 1323 { 1324 case 'x': case 'y': 1325 return 1; 1326 1327 case 'O': 1328 mangled++; 1329 i = dlang_type_modifier_p (mangled); 1330 return i + 1; 1331 1332 case 'N': 1333 mangled++; 1334 if (*mangled == 'g') 1335 { 1336 mangled++; 1337 i = dlang_type_modifier_p (mangled); 1338 return i + 2; 1339 } 1340 } 1341 1342 return 0; 1343 } 1344 1345 /* Extract the function calling convention from MANGLED and 1346 return 1 on success or 0 on failure. */ 1347 static int 1348 dlang_call_convention_p (const char *mangled) 1349 { 1350 /* Prefix for functions needing 'this' */ 1351 if (*mangled == 'M') 1352 { 1353 mangled++; 1354 /* Also skip over any type modifiers. */ 1355 mangled += dlang_type_modifier_p (mangled); 1356 } 1357 1358 switch (*mangled) 1359 { 1360 case 'F': case 'U': case 'V': 1361 case 'W': case 'R': case 'Y': 1362 return 1; 1363 1364 default: 1365 return 0; 1366 } 1367 } 1368 1369 /* Extract and demangle the symbol in MANGLED and append it to DECL. 1370 Returns the remaining signature on success or NULL on failure. */ 1371 static const char * 1372 dlang_parse_symbol (string *decl, const char *mangled, 1373 enum dlang_symbol_kinds kind) 1374 { 1375 int saved; 1376 size_t n = 0; 1377 do 1378 { 1379 if (n++) 1380 string_append (decl, "."); 1381 1382 mangled = dlang_identifier (decl, mangled, kind); 1383 1384 if (mangled && dlang_call_convention_p (mangled)) 1385 { 1386 string mods; 1387 const char *start = NULL; 1388 int checkpoint = 0; 1389 1390 /* Skip over 'this' parameter. */ 1391 if (*mangled == 'M') 1392 mangled++; 1393 1394 /* We have reached here because we expect an extern(Pascal) function. 1395 However this is so rare, that it is more likely a template value 1396 parameter. Since this can't be assumed, first attempt parsing 1397 the symbol as a function, and then back out on failure. */ 1398 if (*mangled == 'V') 1399 { 1400 start = mangled; 1401 checkpoint = string_length (decl); 1402 } 1403 1404 /* Save the type modifiers for appending at the end. */ 1405 string_init (&mods); 1406 mangled = dlang_type_modifiers (&mods, mangled); 1407 1408 /* Skip over calling convention and attributes in qualified name. */ 1409 saved = string_length (decl); 1410 mangled = dlang_call_convention (decl, mangled); 1411 mangled = dlang_attributes (decl, mangled); 1412 string_setlength (decl, saved); 1413 1414 string_append (decl, "("); 1415 mangled = dlang_function_args (decl, mangled); 1416 string_append (decl, ")"); 1417 1418 /* Add any const/immutable/shared modifier. */ 1419 string_appendn (decl, mods.b, string_length (&mods)); 1420 string_delete (&mods); 1421 1422 if (mangled == NULL && checkpoint != 0) 1423 { 1424 mangled = start; 1425 string_setlength (decl, checkpoint); 1426 } 1427 } 1428 } 1429 while (mangled && ISDIGIT (*mangled)); 1430 1431 /* Only top-level symbols or function template parameters have 1432 a type that needs checking. */ 1433 if (kind == dlang_top_level || kind == dlang_function) 1434 { 1435 /* Artificial symbols end with 'Z' and have no type. */ 1436 if (mangled && *mangled == 'Z') 1437 mangled++; 1438 else 1439 { 1440 saved = string_length (decl); 1441 mangled = dlang_type (decl, mangled); 1442 string_setlength (decl, saved); 1443 } 1444 1445 /* Check that the entire symbol was successfully demangled. */ 1446 if (kind == dlang_top_level) 1447 { 1448 if (mangled == NULL || *mangled != '\0') 1449 return NULL; 1450 } 1451 } 1452 1453 return mangled; 1454 } 1455 1456 /* Demangle the tuple from MANGLED and append it to DECL. 1457 Return the remaining string on success or NULL on failure. */ 1458 static const char * 1459 dlang_parse_tuple (string *decl, const char *mangled) 1460 { 1461 char *endptr; 1462 long elements = strtol (mangled, &endptr, 10); 1463 1464 if (endptr == NULL || elements < 0) 1465 return NULL; 1466 1467 mangled = endptr; 1468 string_append (decl, "Tuple!("); 1469 1470 while (elements--) 1471 { 1472 mangled = dlang_type (decl, mangled); 1473 if (elements != 0) 1474 string_append (decl, ", "); 1475 } 1476 1477 string_append (decl, ")"); 1478 return mangled; 1479 } 1480 1481 /* Demangle the argument list from MANGLED and append it to DECL. 1482 Return the remaining string on success or NULL on failure. */ 1483 static const char * 1484 dlang_template_args (string *decl, const char *mangled) 1485 { 1486 size_t n = 0; 1487 1488 while (mangled && *mangled != '\0') 1489 { 1490 switch (*mangled) 1491 { 1492 case 'Z': /* End of parameter list. */ 1493 mangled++; 1494 return mangled; 1495 } 1496 1497 if (n++) 1498 string_append (decl, ", "); 1499 1500 /* Skip over specialised template prefix. */ 1501 if (*mangled == 'H') 1502 mangled++; 1503 1504 switch (*mangled) 1505 { 1506 case 'S': /* Symbol parameter. */ 1507 mangled++; 1508 mangled = dlang_parse_symbol (decl, mangled, dlang_template_param); 1509 break; 1510 case 'T': /* Type parameter. */ 1511 mangled++; 1512 mangled = dlang_type (decl, mangled); 1513 break; 1514 case 'V': /* Value parameter. */ 1515 { 1516 string name; 1517 char type; 1518 1519 /* Peek at the type. */ 1520 mangled++; 1521 type = *mangled; 1522 1523 /* In the few instances where the type is actually desired in 1524 the output, it should precede the value from dlang_value. */ 1525 string_init (&name); 1526 mangled = dlang_type (&name, mangled); 1527 string_need (&name, 1); 1528 *(name.p) = '\0'; 1529 1530 mangled = dlang_value (decl, mangled, name.b, type); 1531 string_delete (&name); 1532 break; 1533 } 1534 1535 default: 1536 return NULL; 1537 } 1538 } 1539 1540 return mangled; 1541 } 1542 1543 /* Extract and demangle the template symbol in MANGLED, expected to 1544 be made up of LEN characters, and append it to DECL. 1545 Returns the remaining signature on success or NULL on failure. */ 1546 static const char * 1547 dlang_parse_template (string *decl, const char *mangled, long len) 1548 { 1549 const char *start = mangled; 1550 1551 /* Template instance names have the types and values of its parameters 1552 encoded into it. 1553 1554 TemplateInstanceName: 1555 Number __T LName TemplateArgs Z 1556 ^ 1557 The start pointer should be at the above location, and LEN should be 1558 the value of the decoded number. 1559 */ 1560 if (strncmp (mangled, "__T", 3) != 0) 1561 return NULL; 1562 1563 mangled += 3; 1564 1565 /* Template identifier. */ 1566 mangled = dlang_identifier (decl, mangled, dlang_template_ident); 1567 1568 /* Template arguments. */ 1569 string_append (decl, "!("); 1570 mangled = dlang_template_args (decl, mangled); 1571 string_append (decl, ")"); 1572 1573 /* Check for template name length mismatch. */ 1574 if (mangled && (mangled - start) != len) 1575 return NULL; 1576 1577 return mangled; 1578 } 1579 1580 /* Extract and demangle the symbol in MANGLED. Returns the demangled 1581 signature on success or NULL on failure. */ 1582 1583 char * 1584 dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) 1585 { 1586 string decl; 1587 char *demangled = NULL; 1588 1589 if (mangled == NULL || *mangled == '\0') 1590 return NULL; 1591 1592 if (strncmp (mangled, "_D", 2) != 0) 1593 return NULL; 1594 1595 string_init (&decl); 1596 1597 if (strcmp (mangled, "_Dmain") == 0) 1598 { 1599 string_append (&decl, "D main"); 1600 } 1601 else 1602 { 1603 mangled += 2; 1604 1605 if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL) 1606 string_delete (&decl); 1607 } 1608 1609 if (string_length (&decl) > 0) 1610 { 1611 string_need (&decl, 1); 1612 *(decl.p) = '\0'; 1613 demangled = decl.b; 1614 } 1615 1616 return demangled; 1617 } 1618 1619