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
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035
00036 #include <ctype.h>
00037 #include <sys/types.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041
00042 #include "demangle.h"
00043 #undef CURRENT_DEMANGLING_STYLE
00044 #define CURRENT_DEMANGLING_STYLE work->options
00045
00046
00047 #define xmalloc malloc
00048 #define xrealloc realloc
00049
00050 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
00051
00052
00053
00054 #define INTBUF_SIZE 32
00055
00056 extern void fancy_abort (void);
00057
00058 static const char *mystrstr (const char *, const char *);
00059
00060 static const char *
00061 mystrstr (s1, s2)
00062 const char *s1, *s2;
00063 {
00064 register const char *p = s1;
00065 register int len = strlen (s2);
00066
00067 for (; (p = strchr (p, *s2)) != 0; p++)
00068 {
00069 if (strncmp (p, s2, len) == 0)
00070 {
00071 return (p);
00072 }
00073 }
00074 return (0);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 #if !defined (CPLUS_MARKER)
00094 #define CPLUS_MARKER '$'
00095 #endif
00096
00097 enum demangling_styles current_demangling_style = gnu_demangling;
00098
00099 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
00100
00101 static char char_str[2] = { '\000', '\000' };
00102
00103 void
00104 set_cplus_marker_for_demangling (ch)
00105 int ch;
00106 {
00107 cplus_markers[0] = ch;
00108 }
00109
00110 typedef struct string
00111 {
00112 char *b;
00113 char *p;
00114 char *e;
00115 } string;
00116
00117
00118
00119
00120 struct work_stuff
00121 {
00122 int options;
00123 char **typevec;
00124 char **ktypevec;
00125 char **btypevec;
00126 int numk;
00127 int numb;
00128 int ksize;
00129 int bsize;
00130 int ntypes;
00131 int typevec_size;
00132 int constructor;
00133 int destructor;
00134 int static_type;
00135 int temp_start;
00136 int type_quals;
00137 int dllimported;
00138 char **tmpl_argvec;
00139 int ntmpl_args;
00140 int forgetting_types;
00141
00142 string* previous_argument;
00143 int nrepeats;
00144
00145 };
00146
00147 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
00148 #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
00149
00150 static const struct optable
00151 {
00152 const char *in;
00153 const char *out;
00154 int flags;
00155 } optable[] = {
00156 {"nw", " new", DMGL_ANSI},
00157 {"dl", " delete", DMGL_ANSI},
00158 {"new", " new", 0},
00159 {"delete", " delete", 0},
00160 {"vn", " new []", DMGL_ANSI},
00161 {"vd", " delete []", DMGL_ANSI},
00162 {"as", "=", DMGL_ANSI},
00163 {"ne", "!=", DMGL_ANSI},
00164 {"eq", "==", DMGL_ANSI},
00165 {"ge", ">=", DMGL_ANSI},
00166 {"gt", ">", DMGL_ANSI},
00167 {"le", "<=", DMGL_ANSI},
00168 {"lt", "<", DMGL_ANSI},
00169 {"plus", "+", 0},
00170 {"pl", "+", DMGL_ANSI},
00171 {"apl", "+=", DMGL_ANSI},
00172 {"minus", "-", 0},
00173 {"mi", "-", DMGL_ANSI},
00174 {"ami", "-=", DMGL_ANSI},
00175 {"mult", "*", 0},
00176 {"ml", "*", DMGL_ANSI},
00177 {"amu", "*=", DMGL_ANSI},
00178 {"aml", "*=", DMGL_ANSI},
00179 {"convert", "+", 0},
00180 {"negate", "-", 0},
00181 {"trunc_mod", "%", 0},
00182 {"md", "%", DMGL_ANSI},
00183 {"amd", "%=", DMGL_ANSI},
00184 {"trunc_div", "/", 0},
00185 {"dv", "/", DMGL_ANSI},
00186 {"adv", "/=", DMGL_ANSI},
00187 {"truth_andif", "&&", 0},
00188 {"aa", "&&", DMGL_ANSI},
00189 {"truth_orif", "||", 0},
00190 {"oo", "||", DMGL_ANSI},
00191 {"truth_not", "!", 0},
00192 {"nt", "!", DMGL_ANSI},
00193 {"postincrement","++", 0},
00194 {"pp", "++", DMGL_ANSI},
00195 {"postdecrement","--", 0},
00196 {"mm", "--", DMGL_ANSI},
00197 {"bit_ior", "|", 0},
00198 {"or", "|", DMGL_ANSI},
00199 {"aor", "|=", DMGL_ANSI},
00200 {"bit_xor", "^", 0},
00201 {"er", "^", DMGL_ANSI},
00202 {"aer", "^=", DMGL_ANSI},
00203 {"bit_and", "&", 0},
00204 {"ad", "&", DMGL_ANSI},
00205 {"aad", "&=", DMGL_ANSI},
00206 {"bit_not", "~", 0},
00207 {"co", "~", DMGL_ANSI},
00208 {"call", "()", 0},
00209 {"cl", "()", DMGL_ANSI},
00210 {"alshift", "<<", 0},
00211 {"ls", "<<", DMGL_ANSI},
00212 {"als", "<<=", DMGL_ANSI},
00213 {"arshift", ">>", 0},
00214 {"rs", ">>", DMGL_ANSI},
00215 {"ars", ">>=", DMGL_ANSI},
00216 {"component", "->", 0},
00217 {"pt", "->", DMGL_ANSI},
00218 {"rf", "->", DMGL_ANSI},
00219 {"indirect", "*", 0},
00220 {"method_call", "->()", 0},
00221 {"addr", "&", 0},
00222 {"array", "[]", 0},
00223 {"vc", "[]", DMGL_ANSI},
00224 {"compound", ", ", 0},
00225 {"cm", ", ", DMGL_ANSI},
00226 {"cond", "?:", 0},
00227 {"cn", "?:", DMGL_ANSI},
00228 {"max", ">?", 0},
00229 {"mx", ">?", DMGL_ANSI},
00230 {"min", "<?", 0},
00231 {"mn", "<?", DMGL_ANSI},
00232 {"nop", "", 0},
00233 {"rm", "->*", DMGL_ANSI},
00234 {"sz", "sizeof ", DMGL_ANSI}
00235 };
00236
00237
00238
00239
00240 typedef enum type_kind_t
00241 {
00242 tk_none,
00243 tk_pointer,
00244 tk_reference,
00245 tk_integral,
00246 tk_bool,
00247 tk_char,
00248 tk_real
00249 } type_kind_t;
00250
00251 #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
00252 #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
00253 string_prepend(str, " ");}
00254 #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
00255 string_append(str, " ");}
00256 #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
00257
00258
00259
00260 #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
00261
00262 #define ARM_VTABLE_STRING "__vtbl__"
00263 #define ARM_VTABLE_STRLEN 8
00264
00265
00266
00267 static char *
00268 mop_up (struct work_stuff *, string *, int);
00269
00270 static void
00271 squangle_mop_up (struct work_stuff *);
00272
00273 #if 0
00274 static int
00275 demangle_method_args (struct work_stuff *, const char **, string *);
00276 #endif
00277
00278 static char *
00279 internal_cplus_demangle (struct work_stuff *, const char *);
00280
00281 static int
00282 demangle_template_template_parm (struct work_stuff *work,
00283 const char **, string *);
00284
00285 static int
00286 demangle_template (struct work_stuff *work, const char **, string *,
00287 string *, int, int);
00288
00289 static int
00290 arm_pt (struct work_stuff *, const char *, int, const char **,
00291 const char **);
00292
00293 static int
00294 demangle_class_name (struct work_stuff *, const char **, string *);
00295
00296 static int
00297 demangle_qualified (struct work_stuff *, const char **, string *,
00298 int, int);
00299
00300 static int
00301 demangle_class (struct work_stuff *, const char **, string *);
00302
00303 static int
00304 demangle_fund_type (struct work_stuff *, const char **, string *);
00305
00306 static int
00307 demangle_signature (struct work_stuff *, const char **, string *);
00308
00309 static int
00310 demangle_prefix (struct work_stuff *, const char **, string *);
00311
00312 static int
00313 gnu_special (struct work_stuff *, const char **, string *);
00314
00315 static int
00316 arm_special (const char **, string *);
00317
00318 static void
00319 string_need (string *, int);
00320
00321 static void
00322 string_delete (string *);
00323
00324 static void
00325 string_init (string *);
00326
00327 static void
00328 string_clear (string *);
00329
00330 #if 0
00331 static int
00332 string_empty (string *);
00333 #endif
00334
00335 static void
00336 string_append (string *, const char *);
00337
00338 static void
00339 string_appends (string *, string *);
00340
00341 static void
00342 string_appendn (string *, const char *, int);
00343
00344 static void
00345 string_prepend (string *, const char *);
00346
00347 static void
00348 string_prependn (string *, const char *, int);
00349
00350 static void
00351 string_append_template_idx (string *, int);
00352
00353 static int
00354 get_count (const char **, int *);
00355
00356 static int
00357 consume_count (const char **);
00358
00359 static int
00360 consume_count_with_underscores (const char**);
00361
00362 static int
00363 demangle_args (struct work_stuff *, const char **, string *);
00364
00365 static int
00366 demangle_nested_args (struct work_stuff*, const char**, string*);
00367
00368 static int
00369 do_type (struct work_stuff *, const char **, string *);
00370
00371 static int
00372 do_arg (struct work_stuff *, const char **, string *);
00373
00374 static void
00375 demangle_function_name (struct work_stuff *, const char **, string *,
00376 const char *);
00377
00378 static void
00379 remember_type (struct work_stuff *, const char *, int);
00380
00381 static void
00382 remember_Btype (struct work_stuff *, const char *, int, int);
00383
00384 static int
00385 register_Btype (struct work_stuff *);
00386
00387 static void
00388 remember_Ktype (struct work_stuff *, const char *, int);
00389
00390 static void
00391 forget_types (struct work_stuff *);
00392
00393 static void
00394 forget_B_and_K_types (struct work_stuff *);
00395
00396 static void
00397 string_prepends (string *, string *);
00398
00399 static int
00400 demangle_template_value_parm (struct work_stuff*, const char**,
00401 string*, type_kind_t);
00402
00403 static int
00404 do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
00405
00406 static int
00407 do_hpacc_template_literal (struct work_stuff *, const char **, string *);
00408
00409 static int
00410 snarf_numeric_literal (const char **, string *);
00411
00412
00413
00414
00415
00416 #define TYPE_UNQUALIFIED 0x0
00417 #define TYPE_QUAL_CONST 0x1
00418 #define TYPE_QUAL_VOLATILE 0x2
00419 #define TYPE_QUAL_RESTRICT 0x4
00420
00421 static int
00422 code_for_qualifier (int);
00423
00424 static const char*
00425 qualifier_string (int);
00426
00427 static const char*
00428 demangle_qualifier (int);
00429
00430 static int
00431 demangle_expression (struct work_stuff *, const char **, string *,
00432 type_kind_t);
00433
00434 static int
00435 demangle_integral_value (struct work_stuff *, const char **,
00436 string *);
00437
00438 static int
00439 demangle_real_value (struct work_stuff *, const char **, string *);
00440
00441 static void
00442 demangle_arm_hp_template (struct work_stuff *, const char **, int,
00443 string *);
00444
00445 static void
00446 recursively_demangle (struct work_stuff *, const char **, string *,
00447 int);
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 static int
00458 consume_count (type)
00459 const char **type;
00460 {
00461 int count = 0;
00462
00463 if (! isdigit ((unsigned char)**type))
00464 return -1;
00465
00466 while (isdigit ((unsigned char)**type))
00467 {
00468 count *= 10;
00469
00470
00471
00472
00473
00474
00475 if ((count % 10) != 0)
00476 {
00477 while (isdigit ((unsigned char) **type))
00478 (*type)++;
00479 return -1;
00480 }
00481
00482 count += **type - '0';
00483 (*type)++;
00484 }
00485
00486 return (count);
00487 }
00488
00489
00490
00491
00492
00493
00494 static int
00495 consume_count_with_underscores (mangled)
00496 const char **mangled;
00497 {
00498 int idx;
00499
00500 if (**mangled == '_')
00501 {
00502 (*mangled)++;
00503 if (!isdigit ((unsigned char)**mangled))
00504 return -1;
00505
00506 idx = consume_count (mangled);
00507 if (**mangled != '_')
00508
00509 return -1;
00510
00511 (*mangled)++;
00512 }
00513 else
00514 {
00515 if (**mangled < '0' || **mangled > '9')
00516 return -1;
00517
00518 idx = **mangled - '0';
00519 (*mangled)++;
00520 }
00521
00522 return idx;
00523 }
00524
00525
00526
00527
00528 static int
00529 code_for_qualifier (c)
00530 int c;
00531 {
00532 switch (c)
00533 {
00534 case 'C':
00535 return TYPE_QUAL_CONST;
00536
00537 case 'V':
00538 return TYPE_QUAL_VOLATILE;
00539
00540 case 'u':
00541 return TYPE_QUAL_RESTRICT;
00542
00543 default:
00544 break;
00545 }
00546
00547
00548 abort ();
00549 }
00550
00551
00552
00553
00554 static const char*
00555 qualifier_string (type_quals)
00556 int type_quals;
00557 {
00558 switch (type_quals)
00559 {
00560 case TYPE_UNQUALIFIED:
00561 return "";
00562
00563 case TYPE_QUAL_CONST:
00564 return "const";
00565
00566 case TYPE_QUAL_VOLATILE:
00567 return "volatile";
00568
00569 case TYPE_QUAL_RESTRICT:
00570 return "__restrict";
00571
00572 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
00573 return "const volatile";
00574
00575 case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
00576 return "const __restrict";
00577
00578 case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00579 return "volatile __restrict";
00580
00581 case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
00582 return "const volatile __restrict";
00583
00584 default:
00585 break;
00586 }
00587
00588
00589 abort ();
00590 }
00591
00592
00593
00594
00595
00596 static const char*
00597 demangle_qualifier (c)
00598 int c;
00599 {
00600 return qualifier_string (code_for_qualifier (c));
00601 }
00602
00603 int
00604 cplus_demangle_opname (opname, result, options)
00605 const char *opname;
00606 char *result;
00607 int options;
00608 {
00609 int len, len1, ret;
00610 string type;
00611 struct work_stuff work[1];
00612 const char *tem;
00613
00614 len = strlen(opname);
00615 result[0] = '\0';
00616 ret = 0;
00617 memset ((char *) work, 0, sizeof (work));
00618 work->options = options;
00619
00620 if (opname[0] == '_' && opname[1] == '_'
00621 && opname[2] == 'o' && opname[3] == 'p')
00622 {
00623
00624
00625 tem = opname + 4;
00626 if (do_type (work, &tem, &type))
00627 {
00628 strcat (result, "operator ");
00629 strncat (result, type.b, type.p - type.b);
00630 string_delete (&type);
00631 ret = 1;
00632 }
00633 }
00634 else if (opname[0] == '_' && opname[1] == '_'
00635 && opname[2] >= 'a' && opname[2] <= 'z'
00636 && opname[3] >= 'a' && opname[3] <= 'z')
00637 {
00638 if (opname[4] == '\0')
00639 {
00640
00641 size_t i;
00642 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00643 {
00644 if (strlen (optable[i].in) == 2
00645 && memcmp (optable[i].in, opname + 2, 2) == 0)
00646 {
00647 strcat (result, "operator");
00648 strcat (result, optable[i].out);
00649 ret = 1;
00650 break;
00651 }
00652 }
00653 }
00654 else
00655 {
00656 if (opname[2] == 'a' && opname[5] == '\0')
00657 {
00658
00659 size_t i;
00660 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00661 {
00662 if (strlen (optable[i].in) == 3
00663 && memcmp (optable[i].in, opname + 2, 3) == 0)
00664 {
00665 strcat (result, "operator");
00666 strcat (result, optable[i].out);
00667 ret = 1;
00668 break;
00669 }
00670 }
00671 }
00672 }
00673 }
00674 else if (len >= 3
00675 && opname[0] == 'o'
00676 && opname[1] == 'p'
00677 && strchr (cplus_markers, opname[2]) != NULL)
00678 {
00679
00680 if (len >= 10
00681 && memcmp (opname + 3, "assign_", 7) == 0)
00682 {
00683 size_t i;
00684 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00685 {
00686 len1 = len - 10;
00687 if ((int) strlen (optable[i].in) == len1
00688 && memcmp (optable[i].in, opname + 10, len1) == 0)
00689 {
00690 strcat (result, "operator");
00691 strcat (result, optable[i].out);
00692 strcat (result, "=");
00693 ret = 1;
00694 break;
00695 }
00696 }
00697 }
00698 else
00699 {
00700 size_t i;
00701 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00702 {
00703 len1 = len - 3;
00704 if ((int) strlen (optable[i].in) == len1
00705 && memcmp (optable[i].in, opname + 3, len1) == 0)
00706 {
00707 strcat (result, "operator");
00708 strcat (result, optable[i].out);
00709 ret = 1;
00710 break;
00711 }
00712 }
00713 }
00714 }
00715 else if (len >= 5 && memcmp (opname, "type", 4) == 0
00716 && strchr (cplus_markers, opname[4]) != NULL)
00717 {
00718
00719 tem = opname + 5;
00720 if (do_type (work, &tem, &type))
00721 {
00722 strcat (result, "operator ");
00723 strncat (result, type.b, type.p - type.b);
00724 string_delete (&type);
00725 ret = 1;
00726 }
00727 }
00728 squangle_mop_up (work);
00729 return ret;
00730
00731 }
00732
00733
00734
00735
00736
00737
00738 const char *
00739 cplus_mangle_opname (opname, options)
00740 const char *opname;
00741 int options;
00742 {
00743 size_t i;
00744 int len;
00745
00746 len = strlen (opname);
00747 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
00748 {
00749 if ((int) strlen (optable[i].out) == len
00750 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
00751 && memcmp (optable[i].out, opname, len) == 0)
00752 return optable[i].in;
00753 }
00754 return (0);
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 char *
00786 cplus_demangle (mangled, options)
00787 const char *mangled;
00788 int options;
00789 {
00790 char *ret;
00791 struct work_stuff work[1];
00792 memset ((char *) work, 0, sizeof (work));
00793 work -> options = options;
00794 if ((work -> options & DMGL_STYLE_MASK) == 0)
00795 work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
00796
00797 ret = internal_cplus_demangle (work, mangled);
00798 squangle_mop_up (work);
00799 return (ret);
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809 static char *
00810 internal_cplus_demangle (work, mangled)
00811 struct work_stuff *work;
00812 const char *mangled;
00813 {
00814
00815 string decl;
00816 int success = 0;
00817 char *demangled = NULL;
00818 int s1,s2,s3,s4;
00819 s1 = work->constructor;
00820 s2 = work->destructor;
00821 s3 = work->static_type;
00822 s4 = work->type_quals;
00823 work->constructor = work->destructor = 0;
00824 work->type_quals = TYPE_UNQUALIFIED;
00825 work->dllimported = 0;
00826
00827 if ((mangled != NULL) && (*mangled != '\0'))
00828 {
00829 string_init (&decl);
00830
00831
00832
00833
00834
00835
00836
00837
00838 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
00839 {
00840 success = gnu_special (work, &mangled, &decl);
00841 }
00842 if (!success)
00843 {
00844 success = demangle_prefix (work, &mangled, &decl);
00845 }
00846 if (success && (*mangled != '\0'))
00847 {
00848 success = demangle_signature (work, &mangled, &decl);
00849 }
00850 if (work->constructor == 2)
00851 {
00852 string_prepend (&decl, "global constructors keyed to ");
00853 work->constructor = 0;
00854 }
00855 else if (work->destructor == 2)
00856 {
00857 string_prepend (&decl, "global destructors keyed to ");
00858 work->destructor = 0;
00859 }
00860 else if (work->dllimported == 1)
00861 {
00862 string_prepend (&decl, "import stub for ");
00863 work->dllimported = 0;
00864 }
00865 demangled = mop_up (work, &decl, success);
00866 }
00867 work->constructor = s1;
00868 work->destructor = s2;
00869 work->static_type = s3;
00870 work->type_quals = s4;
00871 return (demangled);
00872 }
00873
00874
00875
00876 static void
00877 squangle_mop_up (work)
00878 struct work_stuff *work;
00879 {
00880
00881 forget_B_and_K_types (work);
00882 if (work -> btypevec != NULL)
00883 {
00884 free ((char *) work -> btypevec);
00885 }
00886 if (work -> ktypevec != NULL)
00887 {
00888 free ((char *) work -> ktypevec);
00889 }
00890 }
00891
00892
00893
00894 static char *
00895 mop_up (work, declp, success)
00896 struct work_stuff *work;
00897 string *declp;
00898 int success;
00899 {
00900 char *demangled = NULL;
00901
00902
00903
00904 forget_types (work);
00905 if (work -> typevec != NULL)
00906 {
00907 free ((char *) work -> typevec);
00908 work -> typevec = NULL;
00909 work -> typevec_size = 0;
00910 }
00911 if (work->tmpl_argvec)
00912 {
00913 int i;
00914
00915 for (i = 0; i < work->ntmpl_args; i++)
00916 if (work->tmpl_argvec[i])
00917 free ((char*) work->tmpl_argvec[i]);
00918
00919 free ((char*) work->tmpl_argvec);
00920 work->tmpl_argvec = NULL;
00921 }
00922 if (work->previous_argument)
00923 {
00924 string_delete (work->previous_argument);
00925 free ((char*) work->previous_argument);
00926 work->previous_argument = NULL;
00927 }
00928
00929
00930
00931
00932 if (!success)
00933 {
00934 string_delete (declp);
00935 }
00936 else
00937 {
00938 string_appendn (declp, "", 1);
00939 demangled = declp -> b;
00940 }
00941 return (demangled);
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 static int
00975 demangle_signature (work, mangled, declp)
00976 struct work_stuff *work;
00977 const char **mangled;
00978 string *declp;
00979 {
00980 int success = 1;
00981 int func_done = 0;
00982 int expect_func = 0;
00983 int expect_return_type = 0;
00984 const char *oldmangled = NULL;
00985 string trawname;
00986 string tname;
00987
00988 while (success && (**mangled != '\0'))
00989 {
00990 switch (**mangled)
00991 {
00992 case 'Q':
00993 oldmangled = *mangled;
00994 success = demangle_qualified (work, mangled, declp, 1, 0);
00995 if (success)
00996 remember_type (work, oldmangled, *mangled - oldmangled);
00997 if (AUTO_DEMANGLING || GNU_DEMANGLING)
00998 expect_func = 1;
00999 oldmangled = NULL;
01000 break;
01001
01002 case 'K':
01003 oldmangled = *mangled;
01004 success = demangle_qualified (work, mangled, declp, 1, 0);
01005 if (AUTO_DEMANGLING || GNU_DEMANGLING)
01006 {
01007 expect_func = 1;
01008 }
01009 oldmangled = NULL;
01010 break;
01011
01012 case 'S':
01013
01014 if (oldmangled == NULL)
01015 {
01016 oldmangled = *mangled;
01017 }
01018 (*mangled)++;
01019 work -> static_type = 1;
01020 break;
01021
01022 case 'C':
01023 case 'V':
01024 case 'u':
01025 work->type_quals |= code_for_qualifier (**mangled);
01026
01027
01028 if (oldmangled == NULL)
01029 oldmangled = *mangled;
01030 (*mangled)++;
01031 break;
01032
01033 case 'L':
01034
01035 if (HP_DEMANGLING)
01036 {
01037 while (**mangled && (**mangled != '_'))
01038 (*mangled)++;
01039 if (!**mangled)
01040 success = 0;
01041 else
01042 (*mangled)++;
01043 }
01044 else
01045 success = 0;
01046 break;
01047
01048 case '0': case '1': case '2': case '3': case '4':
01049 case '5': case '6': case '7': case '8': case '9':
01050 if (oldmangled == NULL)
01051 {
01052 oldmangled = *mangled;
01053 }
01054 work->temp_start = -1;
01055 success = demangle_class (work, mangled, declp);
01056 if (success)
01057 {
01058 remember_type (work, oldmangled, *mangled - oldmangled);
01059 }
01060 if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
01061 {
01062
01063
01064 if (**mangled != 'F')
01065 expect_func = 1;
01066 }
01067 oldmangled = NULL;
01068 break;
01069
01070 case 'B':
01071 {
01072 string s;
01073 success = do_type (work, mangled, &s);
01074 if (success)
01075 {
01076 string_append (&s, SCOPE_STRING (work));
01077 string_prepends (declp, &s);
01078 }
01079 oldmangled = NULL;
01080 expect_func = 1;
01081 }
01082 break;
01083
01084 case 'F':
01085
01086
01087
01088
01089
01090
01091 oldmangled = NULL;
01092 func_done = 1;
01093 (*mangled)++;
01094
01095
01096
01097
01098
01099
01100 if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
01101 {
01102 forget_types (work);
01103 }
01104 success = demangle_args (work, mangled, declp);
01105
01106
01107
01108 if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
01109 {
01110 ++(*mangled);
01111
01112 success = do_type (work, mangled, &tname);
01113 string_delete (&tname);
01114 }
01115
01116 break;
01117
01118 case 't':
01119
01120 string_init(&trawname);
01121 string_init(&tname);
01122 if (oldmangled == NULL)
01123 {
01124 oldmangled = *mangled;
01125 }
01126 success = demangle_template (work, mangled, &tname,
01127 &trawname, 1, 1);
01128 if (success)
01129 {
01130 remember_type (work, oldmangled, *mangled - oldmangled);
01131 }
01132 string_append (&tname, SCOPE_STRING (work));
01133
01134 string_prepends(declp, &tname);
01135 if (work -> destructor & 1)
01136 {
01137 string_prepend (&trawname, "~");
01138 string_appends (declp, &trawname);
01139 work->destructor -= 1;
01140 }
01141 if ((work->constructor & 1) || (work->destructor & 1))
01142 {
01143 string_appends (declp, &trawname);
01144 work->constructor -= 1;
01145 }
01146 string_delete(&trawname);
01147 string_delete(&tname);
01148 oldmangled = NULL;
01149 expect_func = 1;
01150 break;
01151
01152 case '_':
01153 if (GNU_DEMANGLING && expect_return_type)
01154 {
01155
01156 string return_type;
01157 string_init (&return_type);
01158
01159 (*mangled)++;
01160 success = do_type (work, mangled, &return_type);
01161 APPEND_BLANK (&return_type);
01162
01163 string_prepends (declp, &return_type);
01164 string_delete (&return_type);
01165 break;
01166 }
01167 else
01168
01169
01170
01171
01172
01173
01174
01175
01176 if (HP_DEMANGLING)
01177 {
01178 (*mangled)++;
01179 while (**mangled && isdigit ((unsigned char)**mangled))
01180 (*mangled)++;
01181 }
01182 else
01183 success = 0;
01184 break;
01185
01186 case 'H':
01187 if (GNU_DEMANGLING)
01188 {
01189
01190 success = demangle_template (work, mangled, declp, 0, 0,
01191 0);
01192 if (!(work->constructor & 1))
01193 expect_return_type = 1;
01194 (*mangled)++;
01195 break;
01196 }
01197 else
01198
01199 {;}
01200
01201 default:
01202 if (AUTO_DEMANGLING || GNU_DEMANGLING)
01203 {
01204
01205
01206 func_done = 1;
01207 success = demangle_args (work, mangled, declp);
01208 }
01209 else
01210 {
01211
01212
01213
01214
01215 success = 0;
01216 }
01217 break;
01218 }
01219
01220
01221
01222 {
01223 if (success && expect_func)
01224 {
01225 func_done = 1;
01226 if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
01227 {
01228 forget_types (work);
01229 }
01230 success = demangle_args (work, mangled, declp);
01231
01232
01233
01234 expect_func = 0;
01235 }
01236 }
01237 }
01238 if (success && !func_done)
01239 {
01240 if (AUTO_DEMANGLING || GNU_DEMANGLING)
01241 {
01242
01243
01244
01245
01246
01247
01248 success = demangle_args (work, mangled, declp);
01249 }
01250 }
01251 if (success && PRINT_ARG_TYPES)
01252 {
01253 if (work->static_type)
01254 string_append (declp, " static");
01255 if (work->type_quals != TYPE_UNQUALIFIED)
01256 {
01257 APPEND_BLANK (declp);
01258 string_append (declp, qualifier_string (work->type_quals));
01259 }
01260 }
01261
01262 return (success);
01263 }
01264
01265 #if 0
01266
01267 static int
01268 demangle_method_args (work, mangled, declp)
01269 struct work_stuff *work;
01270 const char **mangled;
01271 string *declp;
01272 {
01273 int success = 0;
01274
01275 if (work -> static_type)
01276 {
01277 string_append (declp, *mangled + 1);
01278 *mangled += strlen (*mangled);
01279 success = 1;
01280 }
01281 else
01282 {
01283 success = demangle_args (work, mangled, declp);
01284 }
01285 return (success);
01286 }
01287
01288 #endif
01289
01290 static int
01291 demangle_template_template_parm (work, mangled, tname)
01292 struct work_stuff *work;
01293 const char **mangled;
01294 string *tname;
01295 {
01296 int i;
01297 int r;
01298 int need_comma = 0;
01299 int success = 1;
01300 string temp;
01301
01302 string_append (tname, "template <");
01303
01304 if (get_count (mangled, &r))
01305 {
01306 for (i = 0; i < r; i++)
01307 {
01308 if (need_comma)
01309 {
01310 string_append (tname, ", ");
01311 }
01312
01313
01314 if (**mangled == 'Z')
01315 {
01316 (*mangled)++;
01317 string_append (tname, "class");
01318 }
01319
01320 else if (**mangled == 'z')
01321 {
01322 (*mangled)++;
01323 success =
01324 demangle_template_template_parm (work, mangled, tname);
01325 if (!success)
01326 {
01327 break;
01328 }
01329 }
01330 else
01331 {
01332
01333 success = do_type (work, mangled, &temp);
01334 if (success)
01335 {
01336 string_appends (tname, &temp);
01337 }
01338 string_delete(&temp);
01339 if (!success)
01340 {
01341 break;
01342 }
01343 }
01344 need_comma = 1;
01345 }
01346
01347 }
01348 if (tname->p[-1] == '>')
01349 string_append (tname, " ");
01350 string_append (tname, "> class");
01351 return (success);
01352 }
01353
01354 static int
01355 demangle_expression (work, mangled, s, tk)
01356 struct work_stuff *work;
01357 const char** mangled;
01358 string* s;
01359 type_kind_t tk;
01360 {
01361 int need_operator = 0;
01362 int success;
01363
01364 success = 1;
01365 string_appendn (s, "(", 1);
01366 (*mangled)++;
01367 while (success && **mangled != 'W' && **mangled != '\0')
01368 {
01369 if (need_operator)
01370 {
01371 size_t i;
01372 size_t len;
01373
01374 success = 0;
01375
01376 len = strlen (*mangled);
01377
01378 for (i = 0;
01379 i < sizeof (optable) / sizeof (optable [0]);
01380 ++i)
01381 {
01382 size_t l = strlen (optable[i].in);
01383
01384 if (l <= len
01385 && memcmp (optable[i].in, *mangled, l) == 0)
01386 {
01387 string_appendn (s, " ", 1);
01388 string_append (s, optable[i].out);
01389 string_appendn (s, " ", 1);
01390 success = 1;
01391 (*mangled) += l;
01392 break;
01393 }
01394 }
01395
01396 if (!success)
01397 break;
01398 }
01399 else
01400 need_operator = 1;
01401
01402 success = demangle_template_value_parm (work, mangled, s, tk);
01403 }
01404
01405 if (**mangled != 'W')
01406 success = 0;
01407 else
01408 {
01409 string_appendn (s, ")", 1);
01410 (*mangled)++;
01411 }
01412
01413 return success;
01414 }
01415
01416 static int
01417 demangle_integral_value (work, mangled, s)
01418 struct work_stuff *work;
01419 const char** mangled;
01420 string* s;
01421 {
01422 int success;
01423
01424 if (**mangled == 'E')
01425 success = demangle_expression (work, mangled, s, tk_integral);
01426 else if (**mangled == 'Q' || **mangled == 'K')
01427 success = demangle_qualified (work, mangled, s, 0, 1);
01428 else
01429 {
01430 int value;
01431
01432 success = 0;
01433
01434
01435 if (**mangled == 'm')
01436 {
01437 string_appendn (s, "-", 1);
01438 (*mangled)++;
01439 }
01440
01441
01442 value = consume_count_with_underscores (mangled);
01443 if (value != -1)
01444 {
01445 char buf[INTBUF_SIZE];
01446 sprintf (buf, "%d", value);
01447 string_append (s, buf);
01448
01449
01450 if (**mangled == '_')
01451 (*mangled)++;
01452
01453
01454 success = 1;
01455 }
01456 }
01457
01458 return success;
01459 }
01460
01461
01462
01463 static int
01464 demangle_real_value (work, mangled, s)
01465 struct work_stuff *work;
01466 const char **mangled;
01467 string* s;
01468 {
01469 if (**mangled == 'E')
01470 return demangle_expression (work, mangled, s, tk_real);
01471
01472 if (**mangled == 'm')
01473 {
01474 string_appendn (s, "-", 1);
01475 (*mangled)++;
01476 }
01477 while (isdigit ((unsigned char)**mangled))
01478 {
01479 string_appendn (s, *mangled, 1);
01480 (*mangled)++;
01481 }
01482 if (**mangled == '.')
01483 {
01484 string_appendn (s, ".", 1);
01485 (*mangled)++;
01486 while (isdigit ((unsigned char)**mangled))
01487 {
01488 string_appendn (s, *mangled, 1);
01489 (*mangled)++;
01490 }
01491 }
01492 if (**mangled == 'e')
01493 {
01494 string_appendn (s, "e", 1);
01495 (*mangled)++;
01496 while (isdigit ((unsigned char)**mangled))
01497 {
01498 string_appendn (s, *mangled, 1);
01499 (*mangled)++;
01500 }
01501 }
01502
01503 return 1;
01504 }
01505
01506 static int
01507 demangle_template_value_parm (work, mangled, s, tk)
01508 struct work_stuff *work;
01509 const char **mangled;
01510 string* s;
01511 type_kind_t tk;
01512 {
01513 int success = 1;
01514
01515 if (**mangled == 'Y')
01516 {
01517
01518 int idx;
01519
01520 (*mangled)++;
01521 idx = consume_count_with_underscores (mangled);
01522 if (idx == -1
01523 || (work->tmpl_argvec && idx >= work->ntmpl_args)
01524 || consume_count_with_underscores (mangled) == -1)
01525 return -1;
01526 if (work->tmpl_argvec)
01527 string_append (s, work->tmpl_argvec[idx]);
01528 else
01529 string_append_template_idx (s, idx);
01530 }
01531 else if (tk == tk_integral)
01532 success = demangle_integral_value (work, mangled, s);
01533 else if (tk == tk_char)
01534 {
01535 char tmp[2];
01536 int val;
01537 if (**mangled == 'm')
01538 {
01539 string_appendn (s, "-", 1);
01540 (*mangled)++;
01541 }
01542 string_appendn (s, "'", 1);
01543 val = consume_count(mangled);
01544 if (val <= 0)
01545 success = 0;
01546 else
01547 {
01548 tmp[0] = (char)val;
01549 tmp[1] = '\0';
01550 string_appendn (s, &tmp[0], 1);
01551 string_appendn (s, "'", 1);
01552 }
01553 }
01554 else if (tk == tk_bool)
01555 {
01556 int val = consume_count (mangled);
01557 if (val == 0)
01558 string_appendn (s, "false", 5);
01559 else if (val == 1)
01560 string_appendn (s, "true", 4);
01561 else
01562 success = 0;
01563 }
01564 else if (tk == tk_real)
01565 success = demangle_real_value (work, mangled, s);
01566 else if (tk == tk_pointer || tk == tk_reference)
01567 {
01568 if (**mangled == 'Q')
01569 success = demangle_qualified (work, mangled, s,
01570 0,
01571 1);
01572 else
01573 {
01574 int symbol_len = consume_count (mangled);
01575 if (symbol_len == -1)
01576 return -1;
01577 if (symbol_len == 0)
01578 string_appendn (s, "0", 1);
01579 else
01580 {
01581 char *p = xmalloc (symbol_len + 1), *q;
01582 strncpy (p, *mangled, symbol_len);
01583 p [symbol_len] = '\0';
01584
01585
01586
01587
01588
01589 q = cplus_demangle (p, work->options);
01590 if (tk == tk_pointer)
01591 string_appendn (s, "&", 1);
01592
01593
01594 if (q)
01595 {
01596 string_append (s, q);
01597 free (q);
01598 }
01599 else
01600 string_append (s, p);
01601 free (p);
01602 }
01603 *mangled += symbol_len;
01604 }
01605 }
01606
01607 return success;
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618 static int
01619 demangle_template (work, mangled, tname, trawname, is_type, remember)
01620 struct work_stuff *work;
01621 const char **mangled;
01622 string *tname;
01623 string *trawname;
01624 int is_type;
01625 int remember;
01626 {
01627 int i;
01628 int r;
01629 int need_comma = 0;
01630 int success = 0;
01631 const char *start;
01632 int is_java_array = 0;
01633 string temp;
01634 int bindex = 0;
01635
01636 (*mangled)++;
01637 if (is_type)
01638 {
01639 if (remember)
01640 bindex = register_Btype (work);
01641 start = *mangled;
01642
01643 if (**mangled == 'z')
01644 {
01645 int idx;
01646 (*mangled)++;
01647 (*mangled)++;
01648
01649 idx = consume_count_with_underscores (mangled);
01650 if (idx == -1
01651 || (work->tmpl_argvec && idx >= work->ntmpl_args)
01652 || consume_count_with_underscores (mangled) == -1)
01653 return (0);
01654
01655 if (work->tmpl_argvec)
01656 {
01657 string_append (tname, work->tmpl_argvec[idx]);
01658 if (trawname)
01659 string_append (trawname, work->tmpl_argvec[idx]);
01660 }
01661 else
01662 {
01663 string_append_template_idx (tname, idx);
01664 if (trawname)
01665 string_append_template_idx (trawname, idx);
01666 }
01667 }
01668 else
01669 {
01670 if ((r = consume_count (mangled)) <= 0
01671 || (int) strlen (*mangled) < r)
01672 {
01673 return (0);
01674 }
01675 is_java_array = (work -> options & DMGL_JAVA)
01676 && strncmp (*mangled, "JArray1Z", 8) == 0;
01677 if (! is_java_array)
01678 {
01679 string_appendn (tname, *mangled, r);
01680 }
01681 if (trawname)
01682 string_appendn (trawname, *mangled, r);
01683 *mangled += r;
01684 }
01685 }
01686 if (!is_java_array)
01687 string_append (tname, "<");
01688
01689 if (!get_count (mangled, &r))
01690 {
01691 return (0);
01692 }
01693 if (!is_type)
01694 {
01695
01696 work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
01697 work->ntmpl_args = r;
01698 for (i = 0; i < r; i++)
01699 work->tmpl_argvec[i] = 0;
01700 }
01701 for (i = 0; i < r; i++)
01702 {
01703 if (need_comma)
01704 {
01705 string_append (tname, ", ");
01706 }
01707
01708 if (**mangled == 'Z')
01709 {
01710 (*mangled)++;
01711
01712 success = do_type (work, mangled, &temp);
01713 if (success)
01714 {
01715 string_appends (tname, &temp);
01716
01717 if (!is_type)
01718 {
01719
01720 int len = temp.p - temp.b;
01721 work->tmpl_argvec[i] = xmalloc (len + 1);
01722 memcpy (work->tmpl_argvec[i], temp.b, len);
01723 work->tmpl_argvec[i][len] = '\0';
01724 }
01725 }
01726 string_delete(&temp);
01727 if (!success)
01728 {
01729 break;
01730 }
01731 }
01732
01733 else if (**mangled == 'z')
01734 {
01735 int r2;
01736 (*mangled)++;
01737 success = demangle_template_template_parm (work, mangled, tname);
01738
01739 if (success
01740 && (r2 = consume_count (mangled)) > 0
01741 && (int) strlen (*mangled) >= r2)
01742 {
01743 string_append (tname, " ");
01744 string_appendn (tname, *mangled, r2);
01745 if (!is_type)
01746 {
01747
01748 int len = r2;
01749 work->tmpl_argvec[i] = xmalloc (len + 1);
01750 memcpy (work->tmpl_argvec[i], *mangled, len);
01751 work->tmpl_argvec[i][len] = '\0';
01752 }
01753 *mangled += r2;
01754 }
01755