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