1 /*- 2 * This code is derived from software copyrighted by the Free Software 3 * Foundation. 4 */ 5 6 #ifndef lint 7 static char sccsid[] = "@(#)cplus-dem.c 5.4 (Berkeley) 04/30/91"; 8 #endif /* not lint */ 9 10 /* Demangler for GNU C++ 11 Copyright (C) 1989 Free Software Foundation, Inc. 12 written by James Clark (jjc@jclark.uucp) 13 14 This program is free software; you can redistribute it and/or modify 15 it under the terms of the GNU General Public License as published by 16 the Free Software Foundation; either version 1, or (at your option) 17 any later version. 18 19 This program is distributed in the hope that it will be useful, 20 but WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 GNU General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 27 28 /* This is for g++ 1.36.1 (November 6 version). It will probably 29 require changes for any other version. 30 31 Modified for g++ 1.36.2 (November 18 version). */ 32 33 /* This file exports one function 34 35 char *cplus_demangle (const char *name) 36 37 If `name' is a mangled function name produced by g++, then 38 a pointer to a malloced string giving a C++ representation 39 of the name will be returned; otherwise NULL will be returned. 40 It is the caller's responsibility to free the string which 41 is returned. 42 43 For example, 44 45 cplus_demangle ("_foo__1Ai") 46 47 returns 48 49 "A::foo(int)" 50 51 This file imports xmalloc and xrealloc, which are like malloc and 52 realloc except that they generate a fatal error if there is no 53 available memory. */ 54 55 /* #define nounderscore 1 /* define this is names don't start with _ */ 56 57 #include <stdio.h> 58 #include <ctype.h> 59 60 #ifdef USG 61 #include <memory.h> 62 #include <string.h> 63 #else 64 #include <strings.h> 65 #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n)) 66 #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n)) 67 #define strchr index 68 #define strrchr rindex 69 #endif 70 71 #ifndef __STDC__ 72 #define const 73 #endif 74 75 #ifdef __STDC__ 76 extern char *cplus_demangle (const char *type); 77 #else 78 extern char *cplus_demangle (); 79 #endif 80 81 #ifdef __STDC__ 82 extern char *xmalloc (int); 83 extern char *xrealloc (char *, int); 84 #else 85 extern char *xmalloc (); 86 extern char *xrealloc (); 87 #endif 88 89 static char **typevec = 0; 90 static int ntypes = 0; 91 static int typevec_size = 0; 92 93 static struct { 94 const char *in; 95 const char *out; 96 } optable[] = { 97 "new", " new", 98 "delete", " delete", 99 "ne", "!=", 100 "eq", "==", 101 "ge", ">=", 102 "gt", ">", 103 "le", "<=", 104 "lt", "<", 105 "plus", "+", 106 "minus", "-", 107 "mult", "*", 108 "convert", "+", /* unary + */ 109 "negate", "-", /* unary - */ 110 "trunc_mod", "%", 111 "trunc_div", "/", 112 "truth_andif", "&&", 113 "truth_orif", "||", 114 "truth_not", "!", 115 "postincrement", "++", 116 "postdecrement", "--", 117 "bit_ior", "|", 118 "bit_xor", "^", 119 "bit_and", "&", 120 "bit_not", "~", 121 "call", "()", 122 "cond", "?:", 123 "alshift", "<<", 124 "arshift", ">>", 125 "component", "->", 126 "indirect", "*", 127 "method_call", "->()", 128 "addr", "&", /* unary & */ 129 "array", "[]", 130 "nop", "", /* for operator= */ 131 }; 132 133 /* Beware: these aren't '\0' terminated. */ 134 135 typedef struct { 136 char *b; /* pointer to start of string */ 137 char *p; /* pointer after last character */ 138 char *e; /* pointer after end of allocated space */ 139 } string; 140 141 #ifdef __STDC__ 142 static void string_need (string *s, int n); 143 static void string_delete (string *s); 144 static void string_init (string *s); 145 static void string_clear (string *s); 146 static int string_empty (string *s); 147 static void string_append (string *p, const char *s); 148 static void string_appends (string *p, string *s); 149 static void string_appendn (string *p, const char *s, int n); 150 static void string_prepend (string *p, const char *s); 151 #if 0 152 static void string_prepends (string *p, string *s); 153 #endif 154 static void string_prependn (string *p, const char *s, int n); 155 static int get_count (const char **type, int *count); 156 static int do_args (const char **type, string *decl); 157 static int do_type (const char **type, string *result); 158 static int do_arg (const char **type, string *result); 159 static int do_args (const char **type, string *decl); 160 static void munge_function_name (string *name); 161 static void remember_type (const char *type, int len); 162 #else 163 static void string_need (); 164 static void string_delete (); 165 static void string_init (); 166 static void string_clear (); 167 static int string_empty (); 168 static void string_append (); 169 static void string_appends (); 170 static void string_appendn (); 171 static void string_prepend (); 172 static void string_prepends (); 173 static void string_prependn (); 174 static int get_count (); 175 static int do_args (); 176 static int do_type (); 177 static int do_arg (); 178 static int do_args (); 179 static void munge_function_name (); 180 static void remember_type (); 181 #endif 182 183 char * 184 cplus_demangle (type) 185 const char *type; 186 { 187 string decl; 188 int n; 189 int success = 0; 190 int constructor = 0; 191 int const_flag = 0; 192 int i; 193 const char *p; 194 #ifndef LONGERNAMES 195 const char *premangle; 196 #endif 197 198 if (type == NULL || *type == '\0') 199 return NULL; 200 #ifndef nounderscore 201 if (*type++ != '_') 202 return NULL; 203 #endif 204 p = type; 205 while (*p != '\0' && !(*p == '_' && p[1] == '_')) 206 p++; 207 if (*p == '\0') 208 { 209 /* destructor */ 210 if (type[0] == '_' && type[1] == '$' && type[2] == '_') 211 { 212 int n = (strlen (type) - 3)*2 + 3 + 2 + 1; 213 char *tem = (char *) xmalloc (n); 214 strcpy (tem, type + 3); 215 strcat (tem, "::~"); 216 strcat (tem, type + 3); 217 strcat (tem, "()"); 218 return tem; 219 } 220 /* static data member */ 221 if (*type != '_' && (p = strchr (type, '$')) != NULL) 222 { 223 int n = strlen (type) + 2; 224 char *tem = (char *) xmalloc (n); 225 memcpy (tem, type, p - type); 226 strcpy (tem + (p - type), "::"); 227 strcpy (tem + (p - type) + 2, p + 1); 228 return tem; 229 } 230 /* virtual table */ 231 if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$') 232 { 233 int n = strlen (type + 4) + 14 + 1; 234 char *tem = (char *) xmalloc (n); 235 strcpy (tem, type + 4); 236 strcat (tem, " virtual table"); 237 return tem; 238 } 239 return NULL; 240 } 241 242 string_init (&decl); 243 244 if (p == type) 245 { 246 if (!isdigit (p[2])) 247 { 248 string_delete (&decl); 249 return NULL; 250 } 251 constructor = 1; 252 } 253 else 254 { 255 string_appendn (&decl, type, p - type); 256 munge_function_name (&decl); 257 } 258 p += 2; 259 260 #ifndef LONGERNAMES 261 premangle = p; 262 #endif 263 switch (*p) 264 { 265 case 'C': 266 /* a const member function */ 267 if (!isdigit (p[1])) 268 { 269 string_delete (&decl); 270 return NULL; 271 } 272 p += 1; 273 const_flag = 1; 274 /* fall through */ 275 case '0': 276 case '1': 277 case '2': 278 case '3': 279 case '4': 280 case '5': 281 case '6': 282 case '7': 283 case '8': 284 case '9': 285 n = 0; 286 do 287 { 288 n *= 10; 289 n += *p - '0'; 290 p += 1; 291 } 292 while (isdigit (*p)); 293 if (strlen (p) < n) 294 { 295 string_delete (&decl); 296 return NULL; 297 } 298 if (constructor) 299 { 300 string_appendn (&decl, p, n); 301 string_append (&decl, "::"); 302 string_appendn (&decl, p, n); 303 } 304 else 305 { 306 string_prepend (&decl, "::"); 307 string_prependn (&decl, p, n); 308 } 309 p += n; 310 #ifndef LONGERNAMES 311 remember_type (premangle, p - premangle); 312 #endif 313 success = do_args (&p, &decl); 314 if (const_flag) 315 string_append (&decl, " const"); 316 break; 317 case 'F': 318 p += 1; 319 success = do_args (&p, &decl); 320 break; 321 } 322 323 for (i = 0; i < ntypes; i++) 324 if (typevec[i] != NULL) 325 free (typevec[i]); 326 ntypes = 0; 327 if (typevec != NULL) 328 { 329 free ((char *)typevec); 330 typevec = NULL; 331 typevec_size = 0; 332 } 333 334 if (success) 335 { 336 string_appendn (&decl, "", 1); 337 return decl.b; 338 } 339 else 340 { 341 string_delete (&decl); 342 return NULL; 343 } 344 } 345 346 static int 347 get_count (type, count) 348 const char **type; 349 int *count; 350 { 351 if (!isdigit (**type)) 352 return 0; 353 *count = **type - '0'; 354 *type += 1; 355 /* see flush_repeats in cplus-method.c */ 356 if (isdigit (**type)) 357 { 358 const char *p = *type; 359 int n = *count; 360 do 361 { 362 n *= 10; 363 n += *p - '0'; 364 p += 1; 365 } 366 while (isdigit (*p)); 367 if (*p == '_') 368 { 369 *type = p + 1; 370 *count = n; 371 } 372 } 373 return 1; 374 } 375 376 /* result will be initialised here; it will be freed on failure */ 377 378 static int 379 do_type (type, result) 380 const char **type; 381 string *result; 382 { 383 int n; 384 int done; 385 int non_empty = 0; 386 int success; 387 string decl; 388 const char *remembered_type; 389 390 string_init (&decl); 391 string_init (result); 392 393 done = 0; 394 success = 1; 395 while (success && !done) 396 { 397 int member; 398 switch (**type) 399 { 400 case 'P': 401 *type += 1; 402 string_prepend (&decl, "*"); 403 break; 404 405 case 'R': 406 *type += 1; 407 string_prepend (&decl, "&"); 408 break; 409 410 case 'T': 411 *type += 1; 412 if (!get_count (type, &n) || n >= ntypes) 413 success = 0; 414 else 415 { 416 remembered_type = typevec[n]; 417 type = &remembered_type; 418 } 419 break; 420 421 case 'F': 422 *type += 1; 423 if (!string_empty (&decl) && decl.b[0] == '*') 424 { 425 string_prepend (&decl, "("); 426 string_append (&decl, ")"); 427 } 428 if (!do_args (type, &decl) || **type != '_') 429 success = 0; 430 else 431 *type += 1; 432 break; 433 434 case 'M': 435 case 'O': 436 { 437 int constp = 0; 438 int volatilep = 0; 439 440 member = **type == 'M'; 441 *type += 1; 442 if (!isdigit (**type)) 443 { 444 success = 0; 445 break; 446 } 447 n = 0; 448 do 449 { 450 n *= 10; 451 n += **type - '0'; 452 *type += 1; 453 } 454 while (isdigit (**type)); 455 if (strlen (*type) < n) 456 { 457 success = 0; 458 break; 459 } 460 string_append (&decl, ")"); 461 string_prepend (&decl, "::"); 462 string_prependn (&decl, *type, n); 463 string_prepend (&decl, "("); 464 *type += n; 465 if (member) 466 { 467 if (**type == 'C') 468 { 469 *type += 1; 470 constp = 1; 471 } 472 if (**type == 'V') 473 { 474 *type += 1; 475 volatilep = 1; 476 } 477 if (*(*type)++ != 'F') 478 { 479 success = 0; 480 break; 481 } 482 } 483 if ((member && !do_args (type, &decl)) || **type != '_') 484 { 485 success = 0; 486 break; 487 } 488 *type += 1; 489 if (constp) 490 { 491 if (non_empty) 492 string_append (&decl, " "); 493 else 494 non_empty = 1; 495 string_append (&decl, "const"); 496 } 497 if (volatilep) 498 { 499 if (non_empty) 500 string_append (&decl, " "); 501 else 502 non_empty = 1; 503 string_append (&decl, "volatilep"); 504 } 505 break; 506 } 507 508 case 'C': 509 if ((*type)[1] == 'P') 510 { 511 *type += 1; 512 if (!string_empty (&decl)) 513 string_prepend (&decl, " "); 514 string_prepend (&decl, "const"); 515 break; 516 } 517 518 /* fall through */ 519 default: 520 done = 1; 521 break; 522 } 523 } 524 525 done = 0; 526 non_empty = 0; 527 while (success && !done) 528 { 529 switch (**type) 530 { 531 case 'C': 532 *type += 1; 533 if (non_empty) 534 string_append (result, " "); 535 else 536 non_empty = 1; 537 string_append (result, "const"); 538 break; 539 case 'U': 540 *type += 1; 541 if (non_empty) 542 string_append (result, " "); 543 else 544 non_empty = 1; 545 string_append (result, "unsigned"); 546 break; 547 case 'V': 548 *type += 1; 549 if (non_empty) 550 string_append (result, " "); 551 else 552 non_empty = 1; 553 string_append (result, "volatile"); 554 break; 555 default: 556 done = 1; 557 break; 558 } 559 } 560 561 if (success) 562 switch (**type) 563 { 564 case '\0': 565 case '_': 566 break; 567 case 'v': 568 *type += 1; 569 if (non_empty) 570 string_append (result, " "); 571 string_append (result, "void"); 572 break; 573 case 'x': 574 *type += 1; 575 if (non_empty) 576 string_append (result, " "); 577 string_append (result, "long long"); 578 break; 579 case 'l': 580 *type += 1; 581 if (non_empty) 582 string_append (result, " "); 583 string_append (result, "long"); 584 break; 585 case 'i': 586 *type += 1; 587 if (non_empty) 588 string_append (result, " "); 589 string_append (result, "int"); 590 break; 591 case 's': 592 *type += 1; 593 if (non_empty) 594 string_append (result, " "); 595 string_append (result, "short"); 596 break; 597 case 'c': 598 *type += 1; 599 if (non_empty) 600 string_append (result, " "); 601 string_append (result, "char"); 602 break; 603 case 'r': 604 *type += 1; 605 if (non_empty) 606 string_append (result, " "); 607 string_append (result, "long double"); 608 break; 609 case 'd': 610 *type += 1; 611 if (non_empty) 612 string_append (result, " "); 613 string_append (result, "double"); 614 break; 615 case 'f': 616 *type += 1; 617 if (non_empty) 618 string_append (result, " "); 619 string_append (result, "float"); 620 break; 621 case 'G': 622 *type += 1; 623 if (!isdigit (**type)) 624 { 625 success = 0; 626 break; 627 } 628 /* fall through */ 629 case '0': 630 case '1': 631 case '2': 632 case '3': 633 case '4': 634 case '5': 635 case '6': 636 case '7': 637 case '8': 638 case '9': 639 n = 0; 640 do 641 { 642 n *= 10; 643 n += **type - '0'; 644 *type += 1; 645 } 646 while (isdigit (**type)); 647 if (strlen (*type) < n) 648 { 649 success = 0; 650 break; 651 } 652 if (non_empty) 653 string_append (result, " "); 654 string_appendn (result, *type, n); 655 *type += n; 656 break; 657 default: 658 success = 0; 659 break; 660 } 661 662 if (success) 663 { 664 if (!string_empty (&decl)) 665 { 666 string_append (result, " "); 667 string_appends (result, &decl); 668 } 669 string_delete (&decl); 670 return 1; 671 } 672 else 673 { 674 string_delete (&decl); 675 string_delete (result); 676 return 0; 677 } 678 } 679 680 /* `result' will be initialised in do_type; it will be freed on failure */ 681 682 static int 683 do_arg (type, result) 684 const char **type; 685 string *result; 686 { 687 const char *start = *type; 688 689 if (!do_type (type, result)) 690 return 0; 691 remember_type (start, *type - start); 692 return 1; 693 } 694 695 static void 696 remember_type (start, len) 697 const char *start; 698 int len; 699 { 700 char *tem; 701 702 if (ntypes >= typevec_size) 703 { 704 if (typevec_size == 0) 705 { 706 typevec_size = 3; 707 typevec = (char **) xmalloc (sizeof (char*)*typevec_size); 708 } 709 else 710 { 711 typevec_size *= 2; 712 typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size); 713 } 714 } 715 tem = (char *) xmalloc (len + 1); 716 memcpy (tem, start, len); 717 tem[len] = '\0'; 718 typevec[ntypes++] = tem; 719 } 720 721 /* `decl' must be already initialised, usually non-empty; 722 it won't be freed on failure */ 723 724 static int 725 do_args (type, decl) 726 const char **type; 727 string *decl; 728 { 729 string arg; 730 int need_comma = 0; 731 732 string_append (decl, "("); 733 734 while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v') 735 { 736 if (**type == 'N') 737 { 738 int r; 739 int t; 740 *type += 1; 741 if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes) 742 return 0; 743 while (--r >= 0) 744 { 745 const char *tem = typevec[t]; 746 if (need_comma) 747 string_append (decl, ", "); 748 if (!do_arg (&tem, &arg)) 749 return 0; 750 string_appends (decl, &arg); 751 string_delete (&arg); 752 need_comma = 1; 753 } 754 } 755 else 756 { 757 if (need_comma) 758 string_append (decl, ", "); 759 if (!do_arg (type, &arg)) 760 return 0; 761 string_appends (decl, &arg); 762 string_delete (&arg); 763 need_comma = 1; 764 } 765 } 766 767 if (**type == 'v') 768 *type += 1; 769 else if (**type == 'e') 770 { 771 *type += 1; 772 if (need_comma) 773 string_append (decl, ","); 774 string_append (decl, "..."); 775 } 776 777 string_append (decl, ")"); 778 return 1; 779 } 780 781 static void 782 munge_function_name (name) 783 string *name; 784 { 785 if (!string_empty (name) && name->p - name->b >= 3 786 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$') 787 { 788 int i; 789 /* see if it's an assignment expression */ 790 if (name->p - name->b >= 10 /* op$assign_ */ 791 && memcmp (name->b + 3, "assign_", 7) == 0) 792 { 793 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) 794 { 795 int len = name->p - name->b - 10; 796 if (strlen (optable[i].in) == len 797 && memcmp (optable[i].in, name->b + 10, len) == 0) 798 { 799 string_clear (name); 800 string_append (name, "operator"); 801 string_append (name, optable[i].out); 802 string_append (name, "="); 803 return; 804 } 805 } 806 } 807 else 808 { 809 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) 810 { 811 int len = name->p - name->b - 3; 812 if (strlen (optable[i].in) == len 813 && memcmp (optable[i].in, name->b + 3, len) == 0) 814 { 815 string_clear (name); 816 string_append (name, "operator"); 817 string_append (name, optable[i].out); 818 return; 819 } 820 } 821 } 822 return; 823 } 824 else if (!string_empty (name) && name->p - name->b >= 5 825 && memcmp (name->b, "type$", 5) == 0) 826 { 827 /* type conversion operator */ 828 string type; 829 const char *tem = name->b + 5; 830 if (do_type (&tem, &type)) 831 { 832 string_clear (name); 833 string_append (name, "operator "); 834 string_appends (name, &type); 835 string_delete (&type); 836 return; 837 } 838 } 839 } 840 841 /* a mini string-handling package */ 842 843 static void 844 string_need (s, n) 845 string *s; 846 int n; 847 { 848 if (s->b == NULL) 849 { 850 if (n < 32) 851 n = 32; 852 s->p = s->b = (char *) xmalloc (n); 853 s->e = s->b + n; 854 } 855 else if (s->e - s->p < n) 856 { 857 int tem = s->p - s->b; 858 n += tem; 859 n *= 2; 860 s->b = (char *) xrealloc (s->b, n); 861 s->p = s->b + tem; 862 s->e = s->b + n; 863 } 864 } 865 866 static void 867 string_delete (s) 868 string *s; 869 { 870 if (s->b != NULL) 871 { 872 free (s->b); 873 s->b = s->e = s->p = NULL; 874 } 875 } 876 877 static void 878 string_init (s) 879 string *s; 880 { 881 s->b = s->p = s->e = NULL; 882 } 883 884 static void 885 string_clear (s) 886 string *s; 887 { 888 s->p = s->b; 889 } 890 891 static int 892 string_empty (s) 893 string *s; 894 { 895 return s->b == s->p; 896 } 897 898 static void 899 string_append (p, s) 900 string *p; 901 const char *s; 902 { 903 int n; 904 if (s == NULL || *s == '\0') 905 return; 906 n = strlen (s); 907 string_need (p, n); 908 memcpy (p->p, s, n); 909 p->p += n; 910 } 911 912 static void 913 string_appends (p, s) 914 string *p, *s; 915 { 916 int n; 917 if (s->b == s->p) 918 return; 919 n = s->p - s->b; 920 string_need (p, n); 921 memcpy (p->p, s->b, n); 922 p->p += n; 923 } 924 925 static void 926 string_appendn (p, s, n) 927 string *p; 928 const char *s; 929 int n; 930 { 931 if (n == 0) 932 return; 933 string_need (p, n); 934 memcpy (p->p, s, n); 935 p->p += n; 936 } 937 938 static void 939 string_prepend (p, s) 940 string *p; 941 const char *s; 942 { 943 if (s == NULL || *s == '\0') 944 return; 945 string_prependn (p, s, strlen (s)); 946 } 947 948 #if 0 949 static void 950 string_prepends (p, s) 951 string *p, *s; 952 { 953 if (s->b == s->p) 954 return; 955 string_prependn (p, s->b, s->p - s->b); 956 } 957 #endif 958 959 static void 960 string_prependn (p, s, n) 961 string *p; 962 const char *s; 963 int n; 964 { 965 char *q; 966 967 if (n == 0) 968 return; 969 string_need (p, n); 970 for (q = p->p - 1; q >= p->b; q--) 971 q[n] = q[0]; 972 memcpy (p->b, s, n); 973 p->p += n; 974 } 975