00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "Demangle.h"
00029 #undef CURRENT_DEMANGLING_STYLE
00030 #define CURRENT_DEMANGLING_STYLE work->options
00031 #include <ctype.h>
00032 #include <string.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #if !defined (CPLUS_MARKER)
00053 #define CPLUS_MARKER '$'
00054 #endif
00055
00056 enum demangling_styles current_demangling_style = gnu_demangling;
00057
00058 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
00059
00060 void
00061 set_cplus_marker_for_demangling (ch)
00062 int ch;
00063 {
00064 cplus_markers[0] = ch;
00065 }
00066
00067
00068
00069
00070 struct work_stuff
00071 {
00072 int options;
00073 char **typevec;
00074 int ntypes;
00075 int typevec_size;
00076 int constructor;
00077 int destructor;
00078 int static_type;
00079 int const_type;
00080 };
00081
00082 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
00083 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
00084
00085 static const struct optable
00086 {
00087 const char *in;
00088 const char *out;
00089 int flags;
00090 } optable[] = {
00091 {"nw", " new", DMGL_ANSI},
00092 {"dl", " delete", DMGL_ANSI},
00093 {"new", " new", 0},
00094 {"delete", " delete", 0},
00095 {"vn", " new []", DMGL_ANSI},
00096 {"vd", " delete []", DMGL_ANSI},
00097 {"as", "=", DMGL_ANSI},
00098 {"ne", "!=", DMGL_ANSI},
00099 {"eq", "==", DMGL_ANSI},
00100 {"ge", ">=", DMGL_ANSI},
00101 {"gt", ">", DMGL_ANSI},
00102 {"le", "<=", DMGL_ANSI},
00103 {"lt", "<", DMGL_ANSI},
00104 {"plus", "+", 0},
00105 {"pl", "+", DMGL_ANSI},
00106 {"apl", "+=", DMGL_ANSI},
00107 {"minus", "-", 0},
00108 {"mi", "-", DMGL_ANSI},
00109 {"ami", "-=", DMGL_ANSI},
00110 {"mult", "*", 0},
00111 {"ml", "*", DMGL_ANSI},
00112 {"amu", "*=", DMGL_ANSI},
00113 {"aml", "*=", DMGL_ANSI},
00114 {"convert", "+", 0},
00115 {"negate", "-", 0},
00116 {"trunc_mod", "%", 0},
00117 {"md", "%", DMGL_ANSI},
00118 {"amd", "%=", DMGL_ANSI},
00119 {"trunc_div", "/", 0},
00120 {"dv", "/", DMGL_ANSI},
00121 {"adv", "/=", DMGL_ANSI},
00122 {"truth_andif", "&&", 0},
00123 {"aa", "&&", DMGL_ANSI},
00124 {"truth_orif", "||", 0},
00125 {"oo", "||", DMGL_ANSI},
00126 {"truth_not", "!", 0},
00127 {"nt", "!", DMGL_ANSI},
00128 {"postincrement","++", 0},
00129 {"pp", "++", DMGL_ANSI},
00130 {"postdecrement","--", 0},
00131 {"mm", "--", DMGL_ANSI},
00132 {"bit_ior", "|", 0},
00133 {"or", "|", DMGL_ANSI},
00134 {"aor", "|=", DMGL_ANSI},
00135 {"bit_xor", "^", 0},
00136 {"er", "^", DMGL_ANSI},
00137 {"aer", "^=", DMGL_ANSI},
00138 {"bit_and", "&", 0},
00139 {"ad", "&", DMGL_ANSI},
00140 {"aad", "&=", DMGL_ANSI},
00141 {"bit_not", "~", 0},
00142 {"co", "~", DMGL_ANSI},
00143 {"call", "()", 0},
00144 {"cl", "()", DMGL_ANSI},
00145 {"alshift", "<<", 0},
00146 {"ls", "<<", DMGL_ANSI},
00147 {"als", "<<=", DMGL_ANSI},
00148 {"arshift", ">>", 0},
00149 {"rs", ">>", DMGL_ANSI},
00150 {"ars", ">>=", DMGL_ANSI},
00151 {"component", "->", 0},
00152 {"pt", "->", DMGL_ANSI},
00153 {"rf", "->", DMGL_ANSI},
00154 {"indirect", "*", 0},
00155 {"method_call", "->()", 0},
00156 {"addr", "&", 0},
00157 {"array", "[]", 0},
00158 {"vc", "[]", DMGL_ANSI},
00159 {"compound", ", ", 0},
00160 {"cm", ", ", DMGL_ANSI},
00161 {"cond", "?:", 0},
00162 {"cn", "?:", DMGL_ANSI},
00163 {"max", ">?", 0},
00164 {"mx", ">?", DMGL_ANSI},
00165 {"min", "<?", 0},
00166 {"mn", "<?", DMGL_ANSI},
00167 {"nop", "", 0},
00168 {"rm", "->*", DMGL_ANSI}
00169 };
00170
00171
00172 typedef struct string
00173 {
00174 char *b;
00175 char *p;
00176 char *e;
00177 } string;
00178
00179 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
00180 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
00181 string_prepend(str, " ");}
00182 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
00183 string_append(str, " ");}
00184
00185 #define ARM_VTABLE_STRING "__vtbl__"
00186 #define ARM_VTABLE_STRLEN 8
00187
00188
00189
00190 static char *
00191 mop_up (struct work_stuff *, string *, int);
00192
00193 #if 0
00194 static int
00195 demangle_method_args (struct work_stuff *work, const char **, string *);
00196 #endif
00197
00198 static int
00199 demangle_template (struct work_stuff *work, const char **, string *, string *);
00200
00201 static int
00202 demangle_qualified (struct work_stuff *, const char **, string *, int, int);
00203
00204 static int
00205 demangle_class (struct work_stuff *, const char **, string *);
00206
00207 static int
00208 demangle_fund_type (struct work_stuff *, const char **, string *);
00209
00210 static int
00211 demangle_signature (struct work_stuff *, const char **, string *);
00212
00213 static int
00214 demangle_prefix (struct work_stuff *, const char **, string *);
00215
00216 static int
00217 gnu_special (struct work_stuff *, const char **, string *);
00218
00219 static int
00220 arm_special (struct work_stuff *, const char **, string *);
00221
00222 static void
00223 string_need (string *, int);
00224
00225 static void
00226 string_delete (string *);
00227
00228 static void
00229 string_init (string *);
00230
00231 static void
00232 string_clear (string *);
00233
00234 #if 0
00235 static int
00236 string_empty (string *);
00237 #endif
00238
00239 static void
00240 string_append (string *, const char *);
00241
00242 static void
00243 string_appends (string *, string *);
00244
00245 static void
00246 string_appendn (string *, const char *, int);
00247
00248 static void
00249 string_prepend (string *, const char *);
00250
00251 static void
00252 string_prependn (string *, const char *, int);
00253
00254 static int
00255 get_count (const char **, int *);
00256
00257 static int
00258 consume_count (const char **);
00259
00260 static int
00261 demangle_args (struct work_stuff *, const char **, string *);
00262
00263 static int
00264 do_type (struct work_stuff *, const char **, string *);
00265
00266 static int
00267 do_arg (struct work_stuff *, const char **, string *);
00268
00269 static void
00270 demangle_function_name (struct work_stuff *, const char **, string *,
00271 const char *);
00272
00273 static void
00274 remember_type (struct work_stuff *, const char *, int);
00275
00276 static void
00277 forget_types (struct work_stuff *);
00278
00279 static void
00280 string_prepends (string *, string *);
00281
00282
00283
00284
00285
00286
00287 static int
00288 consume_count (type)
00289 const char **type;
00290 {
00291 int count = 0;
00292
00293 while (isdigit (**type))
00294 {
00295 count *= 10;
00296 count += **type - '0';
00297 (*type)++;
00298 }
00299 return (count);
00300 }
00301
00302 int
00303 cplus_demangle_opname (opname, result, options)
00304 char *opname;
00305 char *result;
00306 int options;
00307 {
00308 int len, i, len1, ret;
00309 string type;
00310 struct work_stuff work[1];
00311 const char *tem;
00312
00313 len = strlen(opname);
00314 result[0] = '\0';
00315 ret = 0;
00316 work->options = options;
00317
00318 if (opname[0] == '_' && opname[1] == '_'
00319 && opname[2] == 'o' && opname[3] == 'p')
00320 {
00321
00322
00323 tem = opname + 4;
00324 if (do_type (work, &tem, &type))
00325 {
00326 strcat (result, "operator ");
00327 strncat (result, type.b, type.p - type.b);
00328 string_delete (&type);
00329 ret = 1;
00330 }
00331 }
00332 else if (opname[0] == '_' && opname[1] == '_'
00333 && opname[2] >= 'a' && opname[2] <= 'z'
00334 && opname[3] >= 'a' && opname[3] <= 'z')
00335 {
00336 if (opname[4] == '\0')
00337 {
00338
00339 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00340 {
00341 if (strlen (optable[i].in) == 2
00342 && memcmp (optable[i].in, opname + 2, 2) == 0)
00343 {
00344 strcat (result, "operator");
00345 strcat (result, optable[i].out);
00346 ret = 1;
00347 break;
00348 }
00349 }
00350 }
00351 else
00352 {
00353 if (opname[2] == 'a' && opname[5] == '\0')
00354 {
00355
00356 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00357 {
00358 if (strlen (optable[i].in) == 3
00359 && memcmp (optable[i].in, opname + 2, 3) == 0)
00360 {
00361 strcat (result, "operator");
00362 strcat (result, optable[i].out);
00363 ret = 1;
00364 break;
00365 }
00366 }
00367 }
00368 }
00369 }
00370 else if (len >= 3
00371 && opname[0] == 'o'
00372 && opname[1] == 'p'
00373 && strchr (cplus_markers, opname[2]) != NULL)
00374 {
00375
00376 if (len >= 10
00377 && memcmp (opname + 3, "assign_", 7) == 0)
00378 {
00379 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00380 {
00381 len1 = len - 10;
00382 if ((int)strlen (optable[i].in) == len1
00383 && memcmp (optable[i].in, opname + 10, len1) == 0)
00384 {
00385 strcat (result, "operator");
00386 strcat (result, optable[i].out);
00387 strcat (result, "=");
00388 ret = 1;
00389 break;
00390 }
00391 }
00392 }
00393 else
00394 {
00395 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00396 {
00397 len1 = len - 3;
00398 if ((int)strlen (optable[i].in) == len1
00399 && memcmp (optable[i].in, opname + 3, len1) == 0)
00400 {
00401 strcat (result, "operator");
00402 strcat (result, optable[i].out);
00403 ret = 1;
00404 break;
00405 }
00406 }
00407 }
00408 }
00409 else if (len >= 5 && memcmp (opname, "type", 4) == 0
00410 && strchr (cplus_markers, opname[4]) != NULL)
00411 {
00412
00413 tem = opname + 5;
00414 if (do_type (work, &tem, &type))
00415 {
00416 strcat (result, "operator ");
00417 strncat (result, type.b, type.p - type.b);
00418 string_delete (&type);
00419 ret = 1;
00420 }
00421 }
00422 return ret;
00423
00424 }
00425
00426
00427
00428
00429
00430
00431 char *
00432 cplus_mangle_opname (opname, options)
00433 char *opname;
00434 int options;
00435 {
00436 int i;
00437 int len;
00438
00439 len = strlen (opname);
00440 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
00441 {
00442 if ((int)strlen (optable[i].out) == len
00443 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
00444 && memcmp (optable[i].out, opname, len) == 0)
00445 return ((char *)optable[i].in);
00446 }
00447 return (0);
00448 }
00449
00450
00451
00452
00453 int cplus_match (mangled, text, text_len)
00454 const char *mangled;
00455 char *text;
00456 int text_len;
00457 {
00458 if (strncmp (mangled, text, text_len) != 0) {
00459 return(0);
00460 } else {
00461 return(1);
00462 }
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 char *
00494 cplus_demangle (mangled, options)
00495 const char *mangled;
00496 int options;
00497 {
00498 string decl;
00499 int success = 0;
00500 struct work_stuff work[1];
00501 char *demangled = NULL;
00502
00503 if ((mangled != NULL) && (*mangled != '\0'))
00504 {
00505 memset ((char *) work, 0, sizeof (work));
00506 work -> options = options;
00507 if ((work->options & DMGL_STYLE_MASK) == 0)
00508 work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
00509
00510 string_init (&decl);
00511
00512
00513
00514
00515
00516
00517
00518
00519 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
00520 {
00521 success = gnu_special (work, &mangled, &decl);
00522 }
00523 if (!success)
00524 {
00525 success = demangle_prefix (work, &mangled, &decl);
00526 }
00527 if (success && (*mangled != '\0'))
00528 {
00529 success = demangle_signature (work, &mangled, &decl);
00530 }
00531 if (work->constructor == 2)
00532 {
00533 string_prepend(&decl, "global constructors keyed to ");
00534 work->constructor = 0;
00535 }
00536 else if (work->destructor == 2)
00537 {
00538 string_prepend(&decl, "global destructors keyed to ");
00539 work->destructor = 0;
00540 }
00541 demangled = mop_up (work, &decl, success);
00542 }
00543 return (demangled);
00544 }
00545
00546 static char *
00547 mop_up (work, declp, success)
00548 struct work_stuff *work;
00549 string *declp;
00550 int success;
00551 {
00552 char *demangled = NULL;
00553
00554
00555
00556 forget_types (work);
00557 if (work -> typevec != NULL)
00558 {
00559 free ((char *) work -> typevec);
00560 }
00561
00562
00563
00564
00565 if (!success)
00566 {
00567 string_delete (declp);
00568 }
00569 else
00570 {
00571 string_appendn (declp, "", 1);
00572 demangled = declp -> b;
00573 }
00574 return (demangled);
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 static int
00609 demangle_signature (work, mangled, declp)
00610 struct work_stuff *work;
00611 const char **mangled;
00612 string *declp;
00613 {
00614 int success = 1;
00615 int func_done = 0;
00616 int expect_func = 0;
00617 const char *oldmangled = NULL;
00618 string trawname;
00619 string tname;
00620
00621 while (success && (**mangled != '\0'))
00622 {
00623 switch (**mangled)
00624 {
00625 case 'Q':
00626 oldmangled = *mangled;
00627 success = demangle_qualified (work, mangled, declp, 1, 0);
00628 if (success)
00629 {
00630 remember_type (work, oldmangled, *mangled - oldmangled);
00631 }
00632 if (AUTO_DEMANGLING || GNU_DEMANGLING)
00633 {
00634 expect_func = 1;
00635 }
00636 oldmangled = NULL;
00637 break;
00638
00639 case 'S':
00640
00641 if (oldmangled == NULL)
00642 {
00643 oldmangled = *mangled;
00644 }
00645 (*mangled)++;
00646 work -> static_type = 1;
00647 break;
00648
00649 case 'C':
00650
00651 if (oldmangled == NULL)
00652 {
00653 oldmangled = *mangled;
00654 }
00655 (*mangled)++;
00656 work -> const_type = 1;
00657 break;
00658
00659 case '0': case '1': case '2': case '3': case '4':
00660 case '5': case '6': case '7': case '8': case '9':
00661 if (oldmangled == NULL)
00662 {
00663 oldmangled = *mangled;
00664 }
00665 success = demangle_class (work, mangled, declp);
00666 if (success)
00667 {
00668 remember_type (work, oldmangled, *mangled - oldmangled);
00669 }
00670 if (AUTO_DEMANGLING || GNU_DEMANGLING)
00671 {
00672 expect_func = 1;
00673 }
00674 oldmangled = NULL;
00675 break;
00676
00677 case 'F':
00678
00679
00680
00681
00682
00683
00684 oldmangled = NULL;
00685 func_done = 1;
00686 (*mangled)++;
00687
00688
00689
00690
00691
00692
00693 if (LUCID_DEMANGLING || ARM_DEMANGLING)
00694 {
00695 forget_types (work);
00696 }
00697 success = demangle_args (work, mangled, declp);
00698 break;
00699
00700 case 't':
00701
00702 string_init(&trawname);
00703 string_init(&tname);
00704 if (oldmangled == NULL)
00705 {
00706 oldmangled = *mangled;
00707 }
00708 success = demangle_template (work, mangled, &tname, &trawname);
00709 if (success)
00710 {
00711 remember_type (work, oldmangled, *mangled - oldmangled);
00712 }
00713 string_append(&tname, "::");
00714 string_prepends(declp, &tname);
00715 if (work -> destructor & 1)
00716 {
00717 string_prepend (&trawname, "~");
00718 string_appends (declp, &trawname);
00719 work->destructor -= 1;
00720 }
00721 if ((work->constructor & 1) || (work->destructor & 1))
00722 {
00723 string_appends (declp, &trawname);
00724 work->constructor -= 1;
00725 }
00726 string_delete(&trawname);
00727 string_delete(&tname);
00728 oldmangled = NULL;
00729 expect_func = 1;
00730 break;
00731
00732 case '_':
00733
00734
00735
00736
00737
00738 success = 0;
00739 break;
00740
00741 default:
00742 if (AUTO_DEMANGLING || GNU_DEMANGLING)
00743 {
00744
00745
00746 func_done = 1;
00747 success = demangle_args (work, mangled, declp);
00748 }
00749 else
00750 {
00751
00752
00753
00754
00755 success = 0;
00756 }
00757 break;
00758 }
00759
00760
00761
00762 {
00763 if (success && expect_func)
00764 {
00765 func_done = 1;
00766 success = demangle_args (work, mangled, declp);
00767 }
00768 }
00769 }
00770 if (success && !func_done)
00771 {
00772 if (AUTO_DEMANGLING || GNU_DEMANGLING)
00773 {
00774
00775
00776
00777
00778
00779
00780 success = demangle_args (work, mangled, declp);
00781 }
00782 }
00783 if (success && work -> static_type && PRINT_ARG_TYPES)
00784 {
00785 string_append (declp, " static");
00786 }
00787 if (success && work -> const_type && PRINT_ARG_TYPES)
00788 {
00789 string_append (declp, " const");
00790 }
00791 return (success);
00792 }
00793
00794 #if 0
00795
00796 static int
00797 demangle_method_args (work, mangled, declp)
00798 struct work_stuff *work;
00799 const char **mangled;
00800 string *declp;
00801 {
00802 int success = 0;
00803
00804 if (work -> static_type)
00805 {
00806 string_append (declp, *mangled + 1);
00807 *mangled += strlen (*mangled);
00808 success = 1;
00809 }
00810 else
00811 {
00812 success = demangle_args (work, mangled, declp);
00813 }
00814 return (success);
00815 }
00816
00817 #endif
00818
00819 static int
00820 demangle_template (work, mangled, tname, trawname)
00821 struct work_stuff *work;
00822 const char **mangled;
00823 string *tname;
00824 string *trawname;
00825 {
00826 int i;
00827 int is_pointer;
00828 int is_real;
00829 int is_integral;
00830 int is_char;
00831 int r;
00832 int need_comma = 0;
00833 int success = 0;
00834 int done;
00835 const char *old_p;
00836 int symbol_len;
00837 string temp;
00838
00839 (*mangled)++;
00840
00841 if ((r = consume_count (mangled)) == 0 || (int)strlen (*mangled) < r)
00842 {
00843 return (0);
00844 }
00845 if (trawname)
00846 string_appendn (trawname, *mangled, r);
00847 string_appendn (tname, *mangled, r);
00848 *mangled += r;
00849 string_append (tname, "<");
00850
00851 if (!get_count (mangled, &r))
00852 {
00853 return (0);
00854 }
00855 for (i = 0; i < r; i++)
00856 {
00857 if (need_comma)
00858 {
00859 string_append (tname, ", ");
00860 }
00861
00862 if (**mangled == 'Z')
00863 {
00864 (*mangled)++;
00865
00866 success = do_type (work, mangled, &temp);
00867 if (success)
00868 {
00869 string_appends (tname, &temp);
00870 }
00871 string_delete(&temp);
00872 if (!success)
00873 {
00874 break;
00875 }
00876 }
00877 else
00878 {
00879
00880 old_p = *mangled;
00881 is_pointer = 0;
00882 is_real = 0;
00883 is_integral = 0;
00884 is_char = 0;
00885 done = 0;
00886
00887 success = do_type (work, mangled, &temp);
00888
00889
00890
00891
00892
00893
00894 string_delete(&temp);
00895 if (!success)
00896 {
00897 break;
00898 }
00899
00900
00901
00902 while (*old_p && !done)
00903 {
00904 switch (*old_p)
00905 {
00906 case 'P':
00907 case 'p':
00908 case 'R':
00909 done = is_pointer = 1;
00910 break;
00911 case 'C':
00912 case 'S':
00913 case 'U':
00914 case 'V':
00915 case 'F':
00916 case 'M':
00917 case 'O':
00918 old_p++;
00919 continue;
00920 case 'Q':
00921 done = is_integral = 1;
00922 break;
00923 case 'T':
00924 abort ();
00925 break;
00926 case 'v':
00927 abort ();
00928 break;
00929 case 'x':
00930 case 'l':
00931 case 'i':
00932 case 's':
00933 case 'w':
00934 done = is_integral = 1;
00935 break;
00936 case 'c':
00937 done = is_char = 1;
00938 break;
00939 case 'r':
00940 case 'd':
00941 case 'f':
00942 done = is_real = 1;
00943 break;
00944 default:
00945
00946
00947
00948 done = is_integral = 1;
00949 }
00950 }
00951 if (is_integral)
00952 {
00953 if (**mangled == 'm')
00954 {
00955 string_appendn (tname, "-", 1);
00956 (*mangled)++;
00957 }
00958 while (isdigit (**mangled))
00959 {
00960 string_appendn (tname, *mangled, 1);
00961 (*mangled)++;
00962 }
00963 }
00964 else if (is_char)
00965 {
00966 char tmp[2];
00967 int val;
00968 if (**mangled == 'm')
00969 {
00970 string_appendn (tname, "-", 1);
00971 (*mangled)++;
00972 }
00973 string_appendn (tname, "'", 1);
00974 val = consume_count(mangled);
00975 if (val == 0)
00976 {
00977 success = 0;
00978 break;
00979 }
00980 tmp[0] = (char)val;
00981 tmp[1] = '\0';
00982 string_appendn (tname, &tmp[0], 1);
00983 string_appendn (tname, "'", 1);
00984 }
00985 else if (is_real)
00986 {
00987 if (**mangled == 'm')
00988 {
00989 string_appendn (tname, "-", 1);
00990 (*mangled)++;
00991 }
00992 while (isdigit (**mangled))
00993 {
00994 string_appendn (tname, *mangled, 1);
00995 (*mangled)++;
00996 }
00997 if (**mangled == '.')
00998 {
00999 string_appendn (tname, ".", 1);
01000 (*mangled)++;
01001 while (isdigit (**mangled))
01002 {
01003 string_appendn (tname, *mangled, 1);
01004 (*mangled)++;
01005 }
01006 }
01007 if (**mangled == 'e')
01008 {
01009 string_appendn (tname, "e", 1);
01010 (*mangled)++;
01011 while (isdigit (**mangled))
01012 {
01013 string_appendn (tname, *mangled, 1);
01014 (*mangled)++;
01015 }
01016 }
01017 }
01018 else if (is_pointer)
01019 {
01020 if (!get_count (mangled, &symbol_len))
01021 {
01022 success = 0;
01023 break;
01024 }
01025 string_appendn (tname, *mangled, symbol_len);
01026 *mangled += symbol_len;
01027 }
01028 }
01029 need_comma = 1;
01030 }
01031 if (tname->p[-1] == '>')
01032 string_append (tname, " ");
01033 string_append (tname, ">");
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 return (success);
01049 }
01050
01051 static int
01052 arm_pt (work, mangled, n, anchor, args)
01053 struct work_stuff *work;
01054 const char *mangled;
01055 int n;
01056 const char **anchor, **args;
01057 {
01058
01059 if (ARM_DEMANGLING && (*anchor = strstr(mangled, "__pt__")))
01060 {
01061 int len;
01062 *args = *anchor + 6;
01063 len = consume_count (args);
01064 if (*args + len == mangled + n && **args == '_')
01065 {
01066 ++*args;
01067 return 1;
01068 }
01069 }
01070 return 0;
01071 }
01072
01073 static void
01074 demangle_arm_pt (work, mangled, n, declp)
01075 struct work_stuff *work;
01076 const char **mangled;
01077 int n;
01078 string *declp;
01079 {
01080 const char *p;
01081 const char *args;
01082 const char *e = *mangled + n;
01083
01084
01085 if (arm_pt (work, *mangled, n, &p, &args))
01086 {
01087 string arg;
01088 string_init (&arg);
01089 string_appendn (declp, *mangled, p - *mangled);
01090 string_append (declp, "<");
01091
01092 while (args < e) {
01093 string_clear (&arg);
01094 do_type (work, &args, &arg);
01095 string_appends (declp, &arg);
01096 string_append (declp, ",");
01097 }
01098 string_delete (&arg);
01099 --declp->p;
01100 string_append (declp, ">");
01101 }
01102 else
01103 {
01104 string_appendn (declp, *mangled, n);
01105 }
01106 *mangled += n;
01107 }
01108
01109 static int
01110 demangle_class_name (work, mangled, declp)
01111 struct work_stuff *work;
01112 const char **mangled;
01113 string *declp;
01114 {
01115 int n;
01116 int success = 0;
01117
01118 n = consume_count (mangled);
01119 if ((int)strlen (*mangled) >= n)
01120 {
01121 demangle_arm_pt (work, mangled, n, declp);
01122 success = 1;
01123 }
01124
01125 return (success);
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 static int
01164 demangle_class (work, mangled, declp)
01165 struct work_stuff *work;
01166 const char **mangled;
01167 string *declp;
01168 {
01169 int success = 0;
01170 string class_name;
01171
01172 string_init (&class_name);
01173 if (demangle_class_name (work, mangled, &class_name))
01174 {
01175 if ((work->constructor & 1) || (work->destructor & 1))
01176 {
01177 string_prepends (declp, &class_name);
01178 if (work -> destructor & 1)
01179 {
01180 string_prepend (declp, "~");
01181 work -> destructor -= 1;
01182 }
01183 else
01184 {
01185 work -> constructor -= 1;
01186 }
01187 }
01188 string_prepend (declp, "::");
01189 string_prepends (declp, &class_name);
01190 success = 1;
01191 }
01192 string_delete (&class_name);
01193 return (success);
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 static int
01228 demangle_prefix (work, mangled, declp)
01229 struct work_stuff *work;
01230 const char **mangled;
01231 string *declp;
01232 {
01233 int success = 1;
01234 const char *scan;
01235 int i;
01236
01237 if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
01238 {
01239 char *marker = strchr (cplus_markers, (*mangled)[8]);
01240 if (marker != NULL && *marker == (*mangled)[10])
01241 {
01242 if ((*mangled)[9] == 'D')
01243 {
01244
01245 (*mangled) += 11;
01246 work->destructor = 2;
01247 }
01248 else if ((*mangled)[9] == 'I')
01249 {
01250
01251 (*mangled) += 11;
01252 work->constructor = 2;
01253 }
01254 }
01255 }
01256 else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
01257 {
01258
01259 (*mangled) += 7;
01260 work->destructor = 2;
01261 }
01262 else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
01263 {
01264
01265 (*mangled) += 7;
01266 work->constructor = 2;
01267 }
01268
01269
01270
01271
01272
01273 {
01274 scan = *mangled;
01275
01276 do {
01277 scan = strchr (scan, '_');
01278 } while (scan != NULL && *++scan != '_');
01279
01280 if (scan != NULL) --scan;
01281 }
01282
01283 if (scan != NULL)
01284 {
01285
01286
01287 i = strspn (scan, "_");
01288 if (i > 2)
01289 {
01290 scan += (i - 2);
01291 }
01292 }
01293
01294 if (scan == NULL)
01295 {
01296 success = 0;
01297 }
01298 else if (work -> static_type)
01299 {
01300 if (!isdigit (scan[0]) && (scan[0] != 't'))
01301 {
01302 success = 0;
01303 }
01304 }
01305 else if ((scan == *mangled) &&
01306 (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
01307 {
01308
01309
01310
01311 if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
01312 {
01313 *mangled = scan + 2;
01314 consume_count (mangled);
01315 string_append (declp, *mangled);
01316 *mangled += strlen (*mangled);
01317 success = 1;
01318 }
01319 else
01320 {
01321
01322
01323
01324 if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
01325 work -> constructor += 1;
01326 *mangled = scan + 2;
01327 }
01328 }
01329 else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
01330 {
01331
01332
01333
01334 if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
01335 || (arm_special (work, mangled, declp) == 0))
01336 {
01337 while (*scan == '_')
01338 {
01339 scan++;
01340 }
01341 if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
01342 {
01343
01344
01345 success = 0;
01346 }
01347 else
01348 {
01349 demangle_function_name (work, mangled, declp, scan);
01350 }
01351 }
01352 }
01353 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
01354 {
01355
01356 success = 1;
01357
01358
01359 demangle_arm_pt (work, mangled, (int)strlen (*mangled), declp);
01360 }
01361 else if (*(scan + 2) != '\0')
01362 {
01363
01364
01365
01366 demangle_function_name (work, mangled, declp, scan);
01367 }
01368 else
01369 {
01370
01371 success = 0;
01372 }
01373
01374 if (!success && (work->constructor == 2 || work->destructor == 2))
01375 {
01376 string_append (declp, *mangled);
01377 *mangled += strlen (*mangled);
01378 success = 1;
01379 }
01380 return (success);
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411 static int
01412 gnu_special (work, mangled, declp)
01413 struct work_stuff *work;
01414 const char **mangled;
01415 string *declp;
01416 {
01417 int n;
01418 int success = 1;
01419 const char *p;
01420
01421 if ((*mangled)[0] == '_'
01422 && strchr (cplus_markers, (*mangled)[1]) != NULL
01423 && (*mangled)[2] == '_')
01424 {
01425
01426 (*mangled) += 3;
01427 work -> destructor += 1;
01428 }
01429 else if ((*mangled)[0] == '_'
01430 && (((*mangled)[1] == '_'
01431 && (*mangled)[2] == 'v'
01432 && (*mangled)[3] == 't'
01433 && (*mangled)[4] == '_')
01434 || ((*mangled)[1] == 'v'
01435 && (*mangled)[2] == 't'
01436 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
01437 {
01438
01439
01440
01441
01442 if ((*mangled)[2] == 'v')
01443 (*mangled) += 5;
01444 else
01445 (*mangled) += 4;
01446 while (**mangled != '\0')
01447 {
01448 p = strpbrk (*mangled, cplus_markers);
01449 switch (**mangled)
01450 {
01451 case 'Q':
01452 success = demangle_qualified (work, mangled, declp, 0, 1);
01453 break;
01454 case 't':
01455 success = demangle_template (work, mangled, declp, 0);
01456 break;
01457 default:
01458 if (isdigit(*mangled[0]))
01459 {
01460 n = consume_count(mangled);
01461 }
01462 else
01463 {
01464 n = strcspn (*mangled, cplus_markers);
01465 }
01466 string_appendn (declp, *mangled, n);
01467 (*mangled) += n;
01468 }
01469
01470 if (success && ((p == NULL) || (p == *mangled)))
01471 {
01472 if (p != NULL)
01473 {
01474 string_append (declp, "::");
01475 (*mangled)++;
01476 }
01477 }
01478 else
01479 {
01480 success = 0;
01481 break;
01482 }
01483 }
01484 if (success)
01485 string_append (declp, " virtual table");
01486 }
01487 else if ((*mangled)[0] == '_'
01488 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
01489 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
01490 {
01491
01492 (*mangled)++;
01493 switch (**mangled)
01494 {
01495 case 'Q':
01496 success = demangle_qualified (work, mangled, declp, 0, 1);
01497 break;
01498 case 't':
01499 success = demangle_template (work, mangled, declp, 0);
01500 break;
01501 default:
01502 n = consume_count (mangled);
01503 string_appendn (declp, *mangled, n);
01504 (*mangled) += n;
01505 }
01506 if (success && (p == *mangled))
01507 {
01508
01509
01510 (*mangled)++;
01511 string_append (declp, "::");
01512 n = strlen (*mangled);
01513 string_appendn (declp, *mangled, n);
01514 (*mangled) += n;
01515 }
01516 else
01517 {
01518 success = 0;
01519 }
01520 }
01521 else if (strncmp (*mangled, "__thunk_", 8) == 0)
01522 {
01523 int delta = ((*mangled) += 8, consume_count (mangled));
01524 char *method = cplus_demangle (++*mangled, work->options);
01525 if (method)
01526 {
01527 char buf[50];
01528 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
01529 string_append (declp, buf);
01530 string_append (declp, method);
01531 free (method);
01532 n = strlen (*mangled);
01533 (*mangled) += n;
01534 }
01535 else
01536 {
01537 success = 0;
01538 }
01539 }
01540 else
01541 {
01542 success = 0;
01543 }
01544 return (success);
01545 }
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 static int
01571 arm_special (struct work_stuff *work, const char **mangled, string *declp)
01572 {
01573 int n;
01574 int success = 1;
01575 const char *scan;
01576
01577 if (work) { }
01578
01579 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
01580 {
01581
01582
01583
01584
01585 scan = *mangled + ARM_VTABLE_STRLEN;
01586 while (*scan != '\0')
01587 {
01588 n = consume_count (&scan);
01589 if (n==0)
01590 {
01591 return (0);
01592 }
01593 scan += n;
01594 if (scan[0] == '_' && scan[1] == '_')
01595 {
01596 scan += 2;
01597 }
01598 }
01599 (*mangled) += ARM_VTABLE_STRLEN;
01600 while (**mangled != '\0')
01601 {
01602 n = consume_count (mangled);
01603 string_prependn (declp, *mangled, n);
01604 (*mangled) += n;
01605 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
01606 {
01607 string_prepend (declp, "::");
01608 (*mangled) += 2;
01609 }
01610 }
01611 string_append (declp, " virtual table");
01612 }
01613 else
01614 {
01615 success = 0;
01616 }
01617 return (success);
01618 }
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652 static int
01653 demangle_qualified (work, mangled, result, isfuncname, append)
01654 struct work_stuff *work;
01655 const char **mangled;
01656 string *result;
01657 int isfuncname;
01658 int append;
01659 {
01660 int qualifiers = 0;
01661 int namelength = 0;
01662 int success = 1;
01663 const char *p;
01664 char num[2];
01665 string temp;
01666
01667 string_init (&temp);
01668 switch ((*mangled)[1])
01669 {
01670 case '_':
01671
01672
01673
01674 p = *mangled + 2;
01675 qualifiers = atoi (p);
01676 if (!isdigit (*p) || *p == '0')
01677 success = 0;
01678
01679
01680 while (isdigit (*p))
01681 ++p;
01682
01683 if (*p != '_')
01684 success = 0;
01685
01686 *mangled = p + 1;
01687 break;
01688
01689 case '1':
01690 case '2':
01691 case '3':
01692 case '4':
01693 case '5':
01694 case '6':
01695 case '7':
01696 case '8':
01697 case '9':
01698
01699 num[0] = (*mangled)[1];
01700 num[1] = '\0';
01701 qualifiers = atoi (num);
01702
01703
01704
01705
01706 if ((*mangled)[2] == '_')
01707 {
01708 (*mangled)++;
01709 }
01710 (*mangled) += 2;
01711 break;
01712
01713 case '0':
01714 default:
01715 success = 0;
01716 }
01717
01718 if (!success)
01719 return success;
01720
01721
01722
01723
01724 while (qualifiers-- > 0)
01725 {
01726 if (*mangled[0] == '_')
01727 *mangled = *mangled + 1;
01728 if (*mangled[0] == 't')
01729 {
01730 success = demangle_template(work, mangled, &temp, 0);
01731 if (!success) break;
01732 }
01733 else
01734 {
01735 namelength = consume_count (mangled);
01736 if ((int)strlen (*mangled) < namelength)
01737 {
01738
01739 success = 0;
01740 break;
01741 }
01742 string_appendn (&temp, *mangled, namelength);
01743 *mangled += namelength;
01744 }
01745 if (qualifiers > 0)
01746 {
01747 string_appendn (&temp, "::", 2);
01748 }
01749 }
01750
01751
01752
01753
01754
01755
01756 if (isfuncname && (work->constructor & 1 || work->destructor & 1))
01757 {
01758 string_appendn (&temp, "::", 2);
01759 if (work -> destructor & 1)
01760 {
01761 string_append (&temp, "~");
01762 }
01763 string_appendn (&temp, (*mangled) - namelength, namelength);
01764 }
01765
01766
01767
01768
01769 if (append)
01770 {
01771 string_appends (result, &temp);
01772 }
01773 else
01774 {
01775 if (!STRING_EMPTY (result))
01776 {
01777 string_appendn (&temp, "::", 2);
01778 }
01779 string_prepends (result, &temp);
01780 }
01781
01782 string_delete (&temp);
01783 return (success);
01784 }
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802 static int
01803 get_count (type, count)
01804 const char **type;
01805 int *count;
01806 {
01807 const char *p;
01808 int n;
01809
01810 if (!isdigit (**type))
01811 {
01812 return (0);
01813 }
01814 else
01815 {
01816 *count = **type - '0';
01817 (*type)++;
01818 if (isdigit (**type))
01819 {
01820 p = *type;
01821 n = *count;
01822 do
01823 {
01824 n *= 10;
01825 n += *p - '0';
01826 p++;
01827 }
01828 while (isdigit (*p));
01829 if (*p == '_')
01830 {
01831 *type = p + 1;
01832 *count = n;
01833 }
01834 }
01835 }
01836 return (1);
01837 }
01838
01839
01840
01841 static int
01842 do_type (work, mangled, result)
01843 struct work_stuff *work;
01844 const char **mangled;
01845 string *result;
01846 {
01847 int n;
01848 int done;
01849 int success;
01850 string decl;
01851 const char *remembered_type;
01852 int constp;
01853 int volatilep;
01854
01855 string_init (&decl);
01856 string_init (result);
01857
01858 done = 0;
01859 success = 1;
01860 while (success && !done)
01861 {
01862 int member;
01863 switch (**mangled)
01864 {
01865
01866
01867 case 'P':
01868 case 'p':
01869 (*mangled)++;
01870 string_prepend (&decl, "*");
01871 break;
01872
01873
01874 case 'R':
01875 (*mangled)++;
01876 string_prepend (&decl, "&");
01877 break;
01878
01879
01880 case 'A':
01881 {
01882 const char *p = ++(*mangled);
01883
01884 string_prepend (&decl, "(");
01885 string_append (&decl, ")[");
01886
01887
01888 while (**mangled && **mangled != '_')
01889 ++(*mangled);
01890 if (**mangled == '_')
01891 {
01892 string_appendn (&decl, p, *mangled - p);
01893 string_append (&decl, "]");
01894 *mangled += 1;
01895 }
01896 else
01897 success = 0;
01898 break;
01899 }
01900
01901
01902 case 'T':
01903 (*mangled)++;
01904 if (!get_count (mangled, &n) || n >= work -> ntypes)
01905 {
01906 success = 0;
01907 }
01908 else
01909 {
01910 remembered_type = work -> typevec[n];
01911 mangled = &remembered_type;
01912 }
01913 break;
01914
01915
01916 case 'F':
01917 (*mangled)++;
01918 if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
01919 {
01920 string_prepend (&decl, "(");
01921 string_append (&decl, ")");
01922 }
01923
01924
01925
01926 if (!demangle_args (work, mangled, &decl)
01927 || (**mangled != '_' && **mangled != '\0'))
01928 {
01929 success = 0;
01930 }
01931 if (success && (**mangled == '_'))
01932 {
01933 (*mangled)++;
01934 }
01935 break;
01936
01937 case 'M':
01938 case 'O':
01939 {
01940 constp = 0;
01941 volatilep = 0;
01942
01943 member = **mangled == 'M';
01944 (*mangled)++;
01945 if (!isdigit (**mangled))
01946 {
01947 success = 0;
01948 break;
01949 }
01950 n = consume_count (mangled);
01951 if ((int)strlen (*mangled) < n)
01952 {
01953 success = 0;
01954 break;
01955 }
01956 string_append (&decl, ")");
01957 string_prepend (&decl, "::");
01958 string_prependn (&decl, *mangled, n);
01959 string_prepend (&decl, "(");
01960 *mangled += n;
01961 if (member)
01962 {
01963 if (**mangled == 'C')
01964 {
01965 (*mangled)++;
01966 constp = 1;
01967 }
01968 if (**mangled == 'V')
01969 {
01970 (*mangled)++;
01971 volatilep = 1;
01972 }
01973 if (*(*mangled)++ != 'F')
01974 {
01975 success = 0;
01976 break;
01977 }
01978 }
01979 if ((member && !demangle_args (work, mangled, &decl))
01980 || **mangled != '_')
01981 {
01982 success = 0;
01983 break;
01984 }
01985 (*mangled)++;
01986 if (! PRINT_ANSI_QUALIFIERS)
01987 {
01988 break;
01989 }
01990 if (constp)
01991 {
01992 APPEND_BLANK (&decl);
01993 string_append (&decl, "const");
01994 }
01995 if (volatilep)
01996 {
01997 APPEND_BLANK (&decl);
01998 string_append (&decl, "volatile");
01999 }
02000 break;
02001 }
02002 case 'G':
02003 (*mangled)++;
02004 break;
02005
02006 case 'C':
02007 (*mangled)++;
02008
02009
02010
02011
02012 if (PRINT_ANSI_QUALIFIERS)
02013 {
02014 if (!STRING_EMPTY (&decl))
02015 {
02016 string_prepend (&decl, " ");
02017 }
02018 string_prepend (&decl, "const");
02019 }
02020 break;
02021
02022
02023
02024
02025
02026 default:
02027 done = 1;
02028 break;
02029 }
02030 }
02031
02032 switch (**mangled)
02033 {
02034
02035 case 'Q':
02036 success = demangle_qualified (work, mangled, result, 0, 1);
02037 break;
02038
02039 default:
02040 success = demangle_fund_type (work, mangled, result);
02041 break;
02042 }
02043
02044 if (success)
02045 {
02046 if (!STRING_EMPTY (&decl))
02047 {
02048 string_append (result, " ");
02049 string_appends (result, &decl);
02050 }
02051 }
02052 else
02053 {
02054 string_delete (result);
02055 }
02056 string_delete (&decl);
02057 return (success);
02058 }
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073 static int
02074 demangle_fund_type (work, mangled, result)
02075 struct work_stuff *work;
02076 const char **mangled;
02077 string *result;
02078 {
02079 int done = 0;
02080 int success = 1;
02081
02082
02083
02084 while (!done)
02085 {
02086 switch (**mangled)
02087 {
02088 case 'C':
02089 (*mangled)++;
02090 if (PRINT_ANSI_QUALIFIERS)
02091 {
02092 APPEND_BLANK (result);
02093 string_append (result, "const");
02094 }
02095 break;
02096 case 'U':
02097 (*mangled)++;
02098 APPEND_BLANK (result);
02099 string_append (result, "unsigned");
02100 break;
02101 case 'S':
02102 (*mangled)++;
02103 APPEND_BLANK (result);
02104 string_append (result, "signed");
02105 break;
02106 case 'V':
02107 (*mangled)++;
02108 if (PRINT_ANSI_QUALIFIERS)
02109 {
02110 APPEND_BLANK (result);
02111 string_append (result, "volatile");
02112 }
02113 break;
02114 default:
02115 done = 1;
02116 break;
02117 }
02118 }
02119
02120
02121
02122 switch (**mangled)
02123 {
02124 case '\0':
02125 case '_':
02126 break;
02127 case 'v':
02128 (*mangled)++;
02129 APPEND_BLANK (result);
02130 string_append (result, "void");
02131 break;
02132 case 'x':
02133 (*mangled)++;
02134 APPEND_BLANK (result);
02135 string_append (result, "long long");
02136 break;
02137 case 'l':
02138 (*mangled)++;
02139 APPEND_BLANK (result);
02140 string_append (result, "long");
02141 break;
02142 case 'i':
02143 (*mangled)++;
02144 APPEND_BLANK (result);
02145 string_append (result, "int");
02146 break;
02147 case 's':
02148 (*mangled)++;
02149 APPEND_BLANK (result);
02150 string_append (result, "short");
02151 break;
02152 case 'b':
02153 (*mangled)++;
02154 APPEND_BLANK (result);
02155 string_append (result, "bool");
02156 break;
02157 case 'c':
02158 (*mangled)++;
02159 APPEND_BLANK (result);
02160 string_append (result, "char");
02161 break;
02162 case 'w':
02163 (*mangled)++;
02164 APPEND_BLANK (result);
02165 string_append (result, "wchar_t");
02166 break;
02167 case 'r':
02168 (*mangled)++;
02169 APPEND_BLANK (result);
02170 string_append (result, "long double");
02171 break;
02172 case 'd':
02173 (*mangled)++;
02174 APPEND_BLANK (result);
02175 string_append (result, "double");
02176 break;
02177 case 'f':
02178 (*mangled)++;
02179 APPEND_BLANK (result);
02180 string_append (result, "float");
02181 break;
02182 case 'G':
02183 (*mangled)++;
02184 if (!isdigit (**mangled))
02185 {
02186 success = 0;
02187 break;
02188 }
02189
02190
02191 case '0':
02192 case '1':
02193 case '2':
02194 case '3':
02195 case '4':
02196 case '5':
02197 case '6':
02198 case '7':
02199 case '8':
02200 case '9':
02201 APPEND_BLANK (result);
02202 if (!demangle_class_name (work, mangled, result)) {
02203 --result->p;
02204 success = 0;
02205 }
02206 break;
02207 case 't':
02208 success = demangle_template(work,mangled, result, 0);
02209 break;
02210 default:
02211 success = 0;
02212 break;
02213 }
02214
02215 return (success);
02216 }
02217
02218
02219
02220 static int
02221 do_arg (work, mangled, result)
02222 struct work_stuff *work;
02223 const char **mangled;
02224 string *result;
02225 {
02226 const char *start = *mangled;
02227
02228 if (!do_type (work, mangled, result))
02229 {
02230 return (0);
02231 }
02232 else
02233 {
02234 remember_type (work, start, *mangled - start);
02235 return (1);
02236 }
02237 }
02238
02239 static void
02240 remember_type (work, start, len)
02241 struct work_stuff *work;
02242 const char *start;
02243 int len;
02244 {
02245 char *tem;
02246
02247 if (work -> ntypes >= work -> typevec_size)
02248 {
02249 if (work -> typevec_size == 0)
02250 {
02251 work -> typevec_size = 3;
02252 work -> typevec =
02253 (char **) malloc (sizeof (char *) * work -> typevec_size);
02254 }
02255 else
02256 {
02257 work -> typevec_size *= 2;
02258 work -> typevec =
02259 (char **) realloc ((char *)work -> typevec,
02260 sizeof (char *) * work -> typevec_size);
02261 }
02262 }
02263 tem = malloc (len + 1);
02264 memcpy (tem, start, len);
02265 tem[len] = '\0';
02266 work -> typevec[work -> ntypes++] = tem;
02267 }
02268
02269
02270
02271 static void
02272 forget_types (work)
02273 struct work_stuff *work;
02274 {
02275 int i;
02276
02277 while (work -> ntypes > 0)
02278 {
02279 i = --(work -> ntypes);
02280 if (work -> typevec[i] != NULL)
02281 {
02282 free (work -> typevec[i]);
02283 work -> typevec[i] = NULL;
02284 }
02285 }
02286 }
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330 static int
02331 demangle_args (work, mangled, declp)
02332 struct work_stuff *work;
02333 const char **mangled;
02334 string *declp;
02335 {
02336 string arg;
02337 int need_comma = 0;
02338 int r;
02339 int t;
02340 const char *tem;
02341 char temptype;
02342
02343 if (PRINT_ARG_TYPES)
02344 {
02345 string_append (declp, "(");
02346 if (**mangled == '\0')
02347 {
02348 string_append (declp, "void");
02349 }
02350 }
02351
02352 while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
02353 {
02354 if ((**mangled == 'N') || (**mangled == 'T'))
02355 {
02356 temptype = *(*mangled)++;
02357
02358 if (temptype == 'N')
02359 {
02360 if (!get_count (mangled, &r))
02361 {
02362 return (0);
02363 }
02364 }
02365 else
02366 {
02367 r = 1;
02368 }
02369 if (ARM_DEMANGLING && work -> ntypes >= 10)
02370 {
02371
02372
02373
02374
02375
02376
02377
02378 if ((t = consume_count(mangled)) == 0)
02379 {
02380 return (0);
02381 }
02382 }
02383 else
02384 {
02385 if (!get_count (mangled, &t))
02386 {
02387 return (0);
02388 }
02389 }
02390 if (LUCID_DEMANGLING || ARM_DEMANGLING)
02391 {
02392 t--;
02393 }
02394
02395
02396 if ((t < 0) || (t >= work -> ntypes))
02397 {
02398 return (0);
02399 }
02400 while (--r >= 0)
02401 {
02402 tem = work -> typevec[t];
02403 if (need_comma && PRINT_ARG_TYPES)
02404 {
02405 string_append (declp, ", ");
02406 }
02407 if (!do_arg (work, &tem, &arg))
02408 {
02409 return (0);
02410 }
02411 if (PRINT_ARG_TYPES)
02412 {
02413 string_appends (declp, &arg);
02414 }
02415 string_delete (&arg);
02416 need_comma = 1;
02417 }
02418 }
02419 else
02420 {
02421 if (need_comma & PRINT_ARG_TYPES)
02422 {
02423 string_append (declp, ", ");
02424 }
02425 if (!do_arg (work, mangled, &arg))
02426 {
02427 return (0);
02428 }
02429 if (PRINT_ARG_TYPES)
02430 {
02431 string_appends (declp, &arg);
02432 }
02433 string_delete (&arg);
02434 need_comma = 1;
02435 }
02436 }
02437
02438 if (**mangled == 'e')
02439 {
02440 (*mangled)++;
02441 if (PRINT_ARG_TYPES)
02442 {
02443 if (need_comma)
02444 {
02445 string_append (declp, ",");
02446 }
02447 string_append (declp, "...");
02448 }
02449 }
02450
02451 if (PRINT_ARG_TYPES)
02452 {
02453 string_append (declp, ")");
02454 }
02455 return (1);
02456 }
02457
02458 static void
02459 demangle_function_name (work, mangled, declp, scan)
02460 struct work_stuff *work;
02461 const char **mangled;
02462 string *declp;
02463 const char *scan;
02464 {
02465 int i;
02466 int len;
02467 string type;
02468 const char *tem;
02469
02470 string_appendn (declp, (*mangled), scan - (*mangled));
02471 string_need (declp, 1);
02472 *(declp -> p) = '\0';
02473
02474
02475
02476
02477
02478 (*mangled) = scan + 2;
02479
02480 if (LUCID_DEMANGLING || ARM_DEMANGLING)
02481 {
02482
02483
02484
02485
02486
02487
02488 if (strcmp (declp -> b, "__ct") == 0)
02489 {
02490 work -> constructor += 1;
02491 string_clear (declp);
02492 return;
02493 }
02494 else if (strcmp (declp -> b, "__dt") == 0)
02495 {
02496 work -> destructor += 1;
02497 string_clear (declp);
02498 return;
02499 }
02500 }
02501
02502 if (declp->p - declp->b >= 3
02503 && declp->b[0] == 'o'
02504 && declp->b[1] == 'p'
02505 && strchr (cplus_markers, declp->b[2]) != NULL)
02506 {
02507
02508 if (declp->p - declp->b >= 10
02509 && memcmp (declp->b + 3, "assign_", 7) == 0)
02510 {
02511 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02512 {
02513 len = declp->p - declp->b - 10;
02514 if ((int)strlen (optable[i].in) == len
02515 && memcmp (optable[i].in, declp->b + 10, len) == 0)
02516 {
02517 string_clear (declp);
02518 string_append (declp, "operator");
02519 string_append (declp, optable[i].out);
02520 string_append (declp, "=");
02521 break;
02522 }
02523 }
02524 }
02525 else
02526 {
02527 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02528 {
02529 len = declp->p - declp->b - 3;
02530 if ((int)strlen(optable[i].in) == len
02531 && memcmp (optable[i].in, declp->b + 3, len) == 0)
02532 {
02533 string_clear (declp);
02534 string_append (declp, "operator");
02535 string_append (declp, optable[i].out);
02536 break;
02537 }
02538 }
02539 }
02540 }
02541 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
02542 && strchr (cplus_markers, declp->b[4]) != NULL)
02543 {
02544
02545 tem = declp->b + 5;
02546 if (do_type (work, &tem, &type))
02547 {
02548 string_clear (declp);
02549 string_append (declp, "operator ");
02550 string_appends (declp, &type);
02551 string_delete (&type);
02552 }
02553 }
02554 else if (declp->b[0] == '_' && declp->b[1] == '_'
02555 && declp->b[2] == 'o' && declp->b[3] == 'p')
02556 {
02557
02558
02559 tem = declp->b + 4;
02560 if (do_type (work, &tem, &type))
02561 {
02562 string_clear (declp);
02563 string_append (declp, "operator ");
02564 string_appends (declp, &type);
02565 string_delete (&type);
02566 }
02567 }
02568 else if (declp->b[0] == '_' && declp->b[1] == '_'
02569 && declp->b[2] >= 'a' && declp->b[2] <= 'z'
02570 && declp->b[3] >= 'a' && declp->b[3] <= 'z')
02571 {
02572 if (declp->b[4] == '\0')
02573 {
02574
02575 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02576 {
02577 if ((int)strlen (optable[i].in) == 2
02578 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
02579 {
02580 string_clear (declp);
02581 string_append (declp, "operator");
02582 string_append (declp, optable[i].out);
02583 break;
02584 }
02585 }
02586 }
02587 else
02588 {
02589 if (declp->b[2] == 'a' && declp->b[5] == '\0')
02590 {
02591
02592 for (i = 0; i < (int)(sizeof (optable) / sizeof (optable[0])); i++)
02593 {
02594 if ((int)strlen (optable[i].in) == 3
02595 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
02596 {
02597 string_clear (declp);
02598 string_append (declp, "operator");
02599 string_append (declp, optable[i].out);
02600 break;
02601 }
02602 }
02603 }
02604 }
02605 }
02606 }
02607
02608
02609
02610 static void
02611 string_need (s, n)
02612 string *s;
02613 int n;
02614 {
02615 int tem;
02616
02617 if (s->b == NULL)
02618 {
02619 if (n < 32)
02620 {
02621 n = 32;
02622 }
02623 s->p = s->b = malloc (n);
02624 s->e = s->b + n;
02625 }
02626 else if (s->e - s->p < n)
02627 {
02628 tem = s->p - s->b;
02629 n += tem;
02630 n *= 2;
02631 s->b = realloc (s->b, n);
02632 s->p = s->b + tem;
02633 s->e = s->b + n;
02634 }
02635 }
02636
02637 static void
02638 string_delete (s)
02639 string *s;
02640 {
02641 if (s->b != NULL)
02642 {
02643 free (s->b);
02644 s->b = s->e = s->p = NULL;
02645 }
02646 }
02647
02648 static void
02649 string_init (s)
02650 string *s;
02651 {
02652 s->b = s->p = s->e = NULL;
02653 }
02654
02655 static void
02656 string_clear (s)
02657 string *s;
02658 {
02659 s->p = s->b;
02660 }
02661
02662 #if 0
02663
02664 static int
02665 string_empty (s)
02666 string *s;
02667 {
02668 return (s->b == s->p);
02669 }
02670
02671 #endif
02672
02673 static void
02674 string_append (p, s)
02675 string *p;
02676 const char *s;
02677 {
02678 int n;
02679 if (s == NULL || *s == '\0')
02680 return;
02681 n = strlen (s);
02682 string_need (p, n);
02683 memcpy (p->p, s, n);
02684 p->p += n;
02685 }
02686
02687 static void
02688 string_appends (p, s)
02689 string *p, *s;
02690 {
02691 int n;
02692
02693 if (s->b != s->p)
02694 {
02695 n = s->p - s->b;
02696 string_need (p, n);
02697 memcpy (p->p, s->b, n);
02698 p->p += n;
02699 }
02700 }
02701
02702 static void
02703 string_appendn (p, s, n)
02704 string *p;
02705 const char *s;
02706 int n;
02707 {
02708 if (n != 0)
02709 {
02710 string_need (p, n);
02711 memcpy (p->p, s, n);
02712 p->p += n;
02713 }
02714 }
02715
02716 static void
02717 string_prepend (p, s)
02718 string *p;
02719 const char *s;
02720 {
02721 if (s != NULL && *s != '\0')
02722 {
02723 string_prependn (p, s, strlen (s));
02724 }
02725 }
02726
02727 static void
02728 string_prepends (p, s)
02729 string *p, *s;
02730 {
02731 if (s->b != s->p)
02732 {
02733 string_prependn (p, s->b, s->p - s->b);
02734 }
02735 }
02736
02737 static void
02738 string_prependn (p, s, n)
02739 string *p;
02740 const char *s;
02741 int n;
02742 {
02743 char *q;
02744
02745 if (n != 0)
02746 {
02747 string_need (p, n);
02748 for (q = p->p - 1; q >= p->b; q--)
02749 {
02750 q[n] = q[0];
02751 }
02752 memcpy (p->b, s, n);
02753 p->p += n;
02754 }
02755 }
02756
02757
02758
02759
02760
02761
02762 #ifdef MAIN
02763
02764 static void
02765 demangle_it (mangled_name)
02766 char *mangled_name;
02767 {
02768 char *result;
02769
02770 result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
02771 if (result == NULL)
02772 {
02773 printf ("%s\n", mangled_name);
02774 }
02775 else
02776 {
02777 printf ("%s\n", result);
02778 free (result);
02779 }
02780 }
02781
02782 #include "getopt.h"
02783
02784 static char *program_name;
02785 extern char *program_version;
02786
02787 static void
02788 usage (stream, status)
02789 FILE *stream;
02790 int status;
02791 {
02792 fprintf (stream, "\
02793 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
02794 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
02795 [--help] [--version] [arg...]\n",
02796 program_name);
02797 exit (status);
02798 }
02799
02800 #define MBUF_SIZE 512
02801 char mbuffer[MBUF_SIZE];
02802
02803
02804 extern int prepends_underscore;
02805
02806 int strip_underscore = 0;
02807
02808 static struct option long_options[] = {
02809 {"strip-underscores", no_argument, 0, '_'},
02810 {"format", required_argument, 0, 's'},
02811 {"help", no_argument, 0, 'h'},
02812 {"no-strip-underscores", no_argument, 0, 'n'},
02813 {"version", no_argument, 0, 'v'},
02814 {0, no_argument, 0, 0}
02815 };
02816
02817 int
02818 main (argc, argv)
02819 int argc;
02820 char **argv;
02821 {
02822 char *result;
02823 int c;
02824
02825 program_name = argv[0];
02826 malloc_set_program_name (program_name);
02827
02828 strip_underscore = prepends_underscore;
02829
02830 while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
02831 {
02832 switch (c)
02833 {
02834 case '?':
02835 usage (stderr, 1);
02836 break;
02837 case 'h':
02838 usage (stdout, 0);
02839 case 'n':
02840 strip_underscore = 0;
02841 break;
02842 case 'v':
02843 printf ("GNU %s version %s\n", program_name, program_version);
02844 exit (0);
02845 case '_':
02846 strip_underscore = 1;
02847 break;
02848 case 's':
02849 if (strcmp (optarg, "gnu") == 0)
02850 {
02851 current_demangling_style = gnu_demangling;
02852 }
02853 else if (strcmp (optarg, "lucid") == 0)
02854 {
02855 current_demangling_style = lucid_demangling;
02856 }
02857 else if (strcmp (optarg, "arm") == 0)
02858 {
02859 current_demangling_style = arm_demangling;
02860 }
02861 else
02862 {
02863 fprintf (stderr, "%s: unknown demangling style `%s'\n",
02864 program_name, optarg);
02865 exit (1);
02866 }
02867 break;
02868 }
02869 }
02870
02871 if (optind < argc)
02872 {
02873 for ( ; optind < argc; optind++)
02874 {
02875 demangle_it (argv[optind]);
02876 }
02877 }
02878 else
02879 {
02880 for (;;)
02881 {
02882 int i = 0;
02883 c = getchar ();
02884
02885 while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
02886 {
02887 if (i >= MBUF_SIZE-1)
02888 break;
02889 mbuffer[i++] = c;
02890 c = getchar ();
02891 }
02892 if (i > 0)
02893 {
02894 int skip_first = strip_underscore && i > 1 && mbuffer[0] == '_';
02895 mbuffer[i] = 0;
02896
02897 result = cplus_demangle (mbuffer+skip_first,
02898 DMGL_PARAMS | DMGL_ANSI);
02899 if (result)
02900 {
02901 fputs (result, stdout);
02902 free (result);
02903 }
02904 else
02905 fputs (mbuffer + skip_first, stdout);
02906
02907 fflush (stdout);
02908 }
02909 if (c == EOF)
02910 break;
02911 putchar (c);
02912 }
02913 }
02914
02915 exit (0);
02916 }
02917
02918 #endif